# Copyright 2016 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import unittest

import mock


class Test_logger_name_from_path(unittest.TestCase):
    def _call_fut(self, path):
        from google.cloud.logging.entries import logger_name_from_path

        return logger_name_from_path(path)

    def test_w_simple_name(self):
        LOGGER_NAME = "LOGGER_NAME"
        PROJECT = "my-project-1234"
        PATH = "projects/%s/logs/%s" % (PROJECT, LOGGER_NAME)
        logger_name = self._call_fut(PATH)
        self.assertEqual(logger_name, LOGGER_NAME)

    def test_w_name_w_all_extras(self):
        LOGGER_NAME = "LOGGER_NAME-part.one~part.two%part-three"
        PROJECT = "my-project-1234"
        PATH = "projects/%s/logs/%s" % (PROJECT, LOGGER_NAME)
        logger_name = self._call_fut(PATH)
        self.assertEqual(logger_name, LOGGER_NAME)


class Test__int_or_none(unittest.TestCase):
    def _call_fut(self, value):
        from google.cloud.logging.entries import _int_or_none

        return _int_or_none(value)

    def test_w_none(self):
        self.assertIsNone(self._call_fut(None))

    def test_w_int(self):
        self.assertEqual(self._call_fut(123), 123)

    def test_w_str(self):
        self.assertEqual(self._call_fut("123"), 123)


class TestLogEntry(unittest.TestCase):

    PROJECT = "PROJECT"
    LOGGER_NAME = "LOGGER_NAME"

    @staticmethod
    def _get_target_class():
        from google.cloud.logging.entries import LogEntry

        return LogEntry

    def _make_one(self, *args, **kw):
        return self._get_target_class()(*args, **kw)

    def test_ctor_defaults(self):
        from google.cloud.logging.entries import _GLOBAL_RESOURCE

        entry = self._make_one()

        self.assertIsNone(entry.log_name)
        self.assertIsNone(entry.logger)
        self.assertIsNone(entry.labels)
        self.assertIsNone(entry.insert_id)
        self.assertIsNone(entry.severity)
        self.assertIsNone(entry.http_request)
        self.assertIsNone(entry.timestamp)
        self.assertIs(entry.resource, _GLOBAL_RESOURCE)
        self.assertIsNone(entry.trace)
        self.assertIsNone(entry.span_id)
        self.assertIsNone(entry.trace_sampled)
        self.assertIsNone(entry.source_location)
        self.assertIsNone(entry.operation)
        self.assertIsNone(entry.payload)

    def test_ctor_explicit(self):
        import datetime
        from google.cloud.logging.resource import Resource

        LOG_NAME = "projects/%s/logs/%s" % (self.PROJECT, self.LOGGER_NAME)
        IID = "IID"
        TIMESTAMP = datetime.datetime.now()
        LABELS = {"foo": "bar", "baz": "qux"}
        SEVERITY = "CRITICAL"
        METHOD = "POST"
        URI = "https://api.example.com/endpoint"
        STATUS = "500"
        REQUEST = {"requestMethod": METHOD, "requestUrl": URI, "status": STATUS}
        resource = Resource(type="global", labels={})
        TRACE = "12345678-1234-5678-1234-567812345678"
        SPANID = "000000000000004a"
        FILE = "my_file.py"
        LINE_NO = 123
        FUNCTION = "my_function"
        SOURCE_LOCATION = {"file": FILE, "line": LINE_NO, "function": FUNCTION}
        OP_ID = "OP_ID"
        PRODUCER = "PRODUCER"
        OPERATION = {"id": OP_ID, "producer": PRODUCER, "first": True, "last": False}
        logger = _Logger(self.LOGGER_NAME, self.PROJECT)

        entry = self._make_one(
            log_name=LOG_NAME,
            logger=logger,
            insert_id=IID,
            timestamp=TIMESTAMP,
            labels=LABELS,
            severity=SEVERITY,
            http_request=REQUEST,
            resource=resource,
            trace=TRACE,
            span_id=SPANID,
            trace_sampled=True,
            source_location=SOURCE_LOCATION,
            operation=OPERATION,
        )

        self.assertEqual(entry.log_name, LOG_NAME)
        self.assertIs(entry.logger, logger)
        self.assertEqual(entry.insert_id, IID)
        self.assertEqual(entry.timestamp, TIMESTAMP)
        self.assertEqual(entry.labels, LABELS)
        self.assertEqual(entry.severity, SEVERITY)
        self.assertEqual(entry.http_request["requestMethod"], METHOD)
        self.assertEqual(entry.http_request["requestUrl"], URI)
        self.assertEqual(entry.http_request["status"], STATUS)
        self.assertEqual(entry.resource, resource)
        self.assertEqual(entry.trace, TRACE)
        self.assertEqual(entry.span_id, SPANID)
        self.assertTrue(entry.trace_sampled)

        source_location = entry.source_location
        self.assertEqual(source_location["file"], FILE)
        self.assertEqual(source_location["line"], LINE_NO)
        self.assertEqual(source_location["function"], FUNCTION)

        self.assertEqual(entry.operation, OPERATION)
        self.assertIsNone(entry.payload)

    def test_from_api_repr_missing_data_no_loggers(self):
        client = _Client(self.PROJECT)
        LOG_NAME = "projects/%s/logs/%s" % (self.PROJECT, self.LOGGER_NAME)
        API_REPR = {"logName": LOG_NAME}
        klass = self._get_target_class()

        entry = klass.from_api_repr(API_REPR, client)

        self.assertEqual(entry.log_name, LOG_NAME)
        logger = entry.logger
        self.assertIsInstance(logger, _Logger)
        self.assertEqual(logger.name, self.LOGGER_NAME)
        self.assertIsNone(entry.insert_id)
        self.assertIsNone(entry.timestamp)
        self.assertIsNone(entry.severity)
        self.assertIsNone(entry.http_request)
        self.assertIsNone(entry.trace)
        self.assertIsNone(entry.span_id)
        self.assertIsNone(entry.trace_sampled)
        self.assertIsNone(entry.source_location)
        self.assertIsNone(entry.operation)
        self.assertIs(logger.client, client)
        self.assertIsNone(entry.payload)

    def test_from_api_repr_w_loggers_no_logger_match(self):
        from datetime import datetime
        from google.cloud._helpers import UTC
        from google.cloud.logging.resource import Resource

        klass = self._get_target_class()
        client = _Client(self.PROJECT)
        SEVERITY = "CRITICAL"
        IID = "IID"
        NOW = datetime.utcnow().replace(tzinfo=UTC)
        TIMESTAMP = _datetime_to_rfc3339_w_nanos(NOW)
        LOG_NAME = "projects/%s/logs/%s" % (self.PROJECT, self.LOGGER_NAME)
        LABELS = {"foo": "bar", "baz": "qux"}
        METHOD = "POST"
        URI = "https://api.example.com/endpoint"
        RESOURCE = Resource(
            type="gae_app",
            labels={
                "type": "gae_app",
                "labels": {"module_id": "default", "version": "test"},
            },
        )
        STATUS = "500"
        TRACE = "12345678-1234-5678-1234-567812345678"
        SPANID = "000000000000004a"
        FILE = "my_file.py"
        LINE_NO = 123
        FUNCTION = "my_function"
        SOURCE_LOCATION = {"file": FILE, "line": str(LINE_NO), "function": FUNCTION}
        OP_ID = "OP_ID"
        PRODUCER = "PRODUCER"
        OPERATION = {"id": OP_ID, "producer": PRODUCER, "first": True, "last": False}
        API_REPR = {
            "logName": LOG_NAME,
            "insertId": IID,
            "timestamp": TIMESTAMP,
            "labels": LABELS,
            "severity": SEVERITY,
            "httpRequest": {
                "requestMethod": METHOD,
                "requestUrl": URI,
                "status": STATUS,
            },
            "resource": RESOURCE._to_dict(),
            "trace": TRACE,
            "spanId": SPANID,
            "traceSampled": True,
            "sourceLocation": SOURCE_LOCATION,
            "operation": OPERATION,
        }
        loggers = {}

        entry = klass.from_api_repr(API_REPR, client, loggers=loggers)

        self.assertEqual(entry.log_name, LOG_NAME)
        logger = entry.logger
        self.assertIsInstance(logger, _Logger)
        self.assertEqual(logger.name, self.LOGGER_NAME)
        self.assertEqual(entry.insert_id, IID)
        self.assertEqual(entry.timestamp, NOW)
        self.assertIsNone(entry.received_timestamp)
        self.assertEqual(entry.labels, LABELS)
        self.assertEqual(entry.severity, SEVERITY)
        self.assertEqual(entry.http_request["requestMethod"], METHOD)
        self.assertEqual(entry.http_request["requestUrl"], URI)
        self.assertEqual(entry.http_request["status"], STATUS)
        self.assertIs(logger.client, client)
        self.assertEqual(logger.name, self.LOGGER_NAME)
        self.assertEqual(loggers, {LOG_NAME: logger})
        self.assertEqual(entry.resource, RESOURCE)
        self.assertEqual(entry.trace, TRACE)
        self.assertEqual(entry.span_id, SPANID)
        self.assertTrue(entry.trace_sampled)

        source_location = entry.source_location
        self.assertEqual(source_location["file"], FILE)
        self.assertEqual(source_location["line"], LINE_NO)
        self.assertEqual(source_location["function"], FUNCTION)

        self.assertEqual(entry.operation, OPERATION)
        self.assertIsNone(entry.payload)

    def test_from_api_repr_w_loggers_w_logger_match(self):
        from datetime import datetime
        from datetime import timedelta
        from google.cloud._helpers import UTC

        client = _Client(self.PROJECT)
        IID = "IID"
        NOW = datetime.utcnow().replace(tzinfo=UTC)
        LATER = NOW + timedelta(seconds=1)
        TIMESTAMP = _datetime_to_rfc3339_w_nanos(NOW)
        RECEIVED = _datetime_to_rfc3339_w_nanos(LATER)
        LOG_NAME = "projects/%s/logs/%s" % (self.PROJECT, self.LOGGER_NAME)
        LABELS = {"foo": "bar", "baz": "qux"}
        TRACE = "12345678-1234-5678-1234-567812345678"
        SPANID = "000000000000004a"
        FILE = "my_file.py"
        LINE_NO = 123
        FUNCTION = "my_function"
        SOURCE_LOCATION = {"file": FILE, "line": str(LINE_NO), "function": FUNCTION}
        OP_ID = "OP_ID"
        PRODUCER = "PRODUCER"
        OPERATION = {"id": OP_ID, "producer": PRODUCER, "first": True, "last": False}
        API_REPR = {
            "logName": LOG_NAME,
            "insertId": IID,
            "timestamp": TIMESTAMP,
            "receiveTimestamp": RECEIVED,
            "labels": LABELS,
            "trace": TRACE,
            "spanId": SPANID,
            "traceSampled": True,
            "sourceLocation": SOURCE_LOCATION,
            "operation": OPERATION,
        }
        LOGGER = object()
        loggers = {LOG_NAME: LOGGER}
        klass = self._get_target_class()

        entry = klass.from_api_repr(API_REPR, client, loggers=loggers)

        self.assertEqual(entry.log_name, LOG_NAME)
        self.assertIs(entry.logger, LOGGER)
        self.assertEqual(entry.insert_id, IID)
        self.assertEqual(entry.timestamp, NOW)
        self.assertEqual(entry.received_timestamp, LATER)
        self.assertEqual(entry.labels, LABELS)
        self.assertEqual(entry.trace, TRACE)
        self.assertEqual(entry.span_id, SPANID)
        self.assertTrue(entry.trace_sampled)

        source_location = entry.source_location
        self.assertEqual(source_location["file"], FILE)
        self.assertEqual(source_location["line"], LINE_NO)
        self.assertEqual(source_location["function"], FUNCTION)

        self.assertEqual(entry.operation, OPERATION)
        self.assertIsNone(entry.payload)

    def test_to_api_repr_w_source_location_no_line(self):
        from google.cloud.logging.logger import _GLOBAL_RESOURCE

        LOG_NAME = "test.log"
        FILE = "my_file.py"
        FUNCTION = "my_function"
        SOURCE_LOCATION = {"file": FILE, "function": FUNCTION}
        entry = self._make_one(log_name=LOG_NAME, source_location=SOURCE_LOCATION)
        expected = {
            "logName": LOG_NAME,
            "resource": _GLOBAL_RESOURCE._to_dict(),
            "sourceLocation": {"file": FILE, "line": "0", "function": FUNCTION},
        }
        self.assertEqual(entry.to_api_repr(), expected)

    def test_to_api_repr_explicit(self):
        import datetime
        from google.cloud.logging.resource import Resource
        from google.cloud._helpers import _datetime_to_rfc3339

        LOG_NAME = "test.log"
        LABELS = {"foo": "bar", "baz": "qux"}
        IID = "IID"
        SEVERITY = "CRITICAL"
        METHOD = "POST"
        URI = "https://api.example.com/endpoint"
        STATUS = "500"
        REQUEST = {"requestMethod": METHOD, "requestUrl": URI, "status": STATUS}
        TIMESTAMP = datetime.datetime(2016, 12, 31, 0, 1, 2, 999999)
        RESOURCE = Resource(
            type="gae_app", labels={"module_id": "default", "version_id": "test"}
        )
        TRACE = "12345678-1234-5678-1234-567812345678"
        SPANID = "000000000000004a"
        FILE = "my_file.py"
        LINE = 123
        FUNCTION = "my_function"
        SOURCE_LOCATION = {"file": FILE, "line": LINE, "function": FUNCTION}
        OP_ID = "OP_ID"
        PRODUCER = "PRODUCER"
        OPERATION = {"id": OP_ID, "producer": PRODUCER, "first": True, "last": False}
        expected = {
            "logName": LOG_NAME,
            "labels": LABELS,
            "insertId": IID,
            "severity": SEVERITY,
            "httpRequest": REQUEST,
            "timestamp": _datetime_to_rfc3339(TIMESTAMP),
            "resource": RESOURCE._to_dict(),
            "trace": TRACE,
            "spanId": SPANID,
            "traceSampled": True,
            "sourceLocation": {"file": FILE, "line": str(LINE), "function": FUNCTION},
            "operation": OPERATION,
        }
        entry = self._make_one(
            log_name=LOG_NAME,
            labels=LABELS,
            insert_id=IID,
            severity=SEVERITY,
            http_request=REQUEST,
            timestamp=TIMESTAMP,
            resource=RESOURCE,
            trace=TRACE,
            span_id=SPANID,
            trace_sampled=True,
            source_location=SOURCE_LOCATION,
            operation=OPERATION,
        )

        self.assertEqual(entry.to_api_repr(), expected)


class TestTextEntry(unittest.TestCase):

    PROJECT = "PROJECT"
    LOGGER_NAME = "LOGGER_NAME"

    @staticmethod
    def _get_target_class():
        from google.cloud.logging.entries import TextEntry

        return TextEntry

    def _make_one(self, *args, **kw):
        return self._get_target_class()(*args, **kw)

    def test_to_api_repr_defaults(self):
        from google.cloud.logging.logger import _GLOBAL_RESOURCE

        LOG_NAME = "test.log"
        TEXT = "TESTING"
        entry = self._make_one(log_name=LOG_NAME, payload=TEXT)
        expected = {
            "logName": LOG_NAME,
            "textPayload": TEXT,
            "resource": _GLOBAL_RESOURCE._to_dict(),
        }
        self.assertEqual(entry.to_api_repr(), expected)

    def test_to_api_repr_explicit(self):
        import datetime
        from google.cloud.logging.resource import Resource
        from google.cloud._helpers import _datetime_to_rfc3339

        LOG_NAME = "test.log"
        TEXT = "This is the entry text"
        LABELS = {"foo": "bar", "baz": "qux"}
        IID = "IID"
        SEVERITY = "CRITICAL"
        METHOD = "POST"
        URI = "https://api.example.com/endpoint"
        STATUS = "500"
        REQUEST = {"requestMethod": METHOD, "requestUrl": URI, "status": STATUS}
        TIMESTAMP = datetime.datetime(2016, 12, 31, 0, 1, 2, 999999)
        RESOURCE = Resource(
            type="gae_app", labels={"module_id": "default", "version_id": "test"}
        )
        TRACE = "12345678-1234-5678-1234-567812345678"
        SPANID = "000000000000004a"
        FILE = "my_file.py"
        LINE = 123
        FUNCTION = "my_function"
        SOURCE_LOCATION = {"file": FILE, "line": LINE, "function": FUNCTION}
        OP_ID = "OP_ID"
        PRODUCER = "PRODUCER"
        OPERATION = {"id": OP_ID, "producer": PRODUCER, "first": True, "last": False}
        expected = {
            "logName": LOG_NAME,
            "textPayload": TEXT,
            "labels": LABELS,
            "insertId": IID,
            "severity": SEVERITY,
            "httpRequest": REQUEST,
            "timestamp": _datetime_to_rfc3339(TIMESTAMP),
            "resource": RESOURCE._to_dict(),
            "trace": TRACE,
            "spanId": SPANID,
            "traceSampled": True,
            "sourceLocation": {"file": FILE, "line": str(LINE), "function": FUNCTION},
            "operation": OPERATION,
        }
        entry = self._make_one(
            log_name=LOG_NAME,
            payload=TEXT,
            labels=LABELS,
            insert_id=IID,
            severity=SEVERITY,
            http_request=REQUEST,
            timestamp=TIMESTAMP,
            resource=RESOURCE,
            trace=TRACE,
            span_id=SPANID,
            trace_sampled=True,
            source_location=SOURCE_LOCATION,
            operation=OPERATION,
        )

        self.assertEqual(entry.to_api_repr(), expected)


class TestStructEntry(unittest.TestCase):

    PROJECT = "PROJECT"
    LOGGER_NAME = "LOGGER_NAME"

    @staticmethod
    def _get_target_class():
        from google.cloud.logging.entries import StructEntry

        return StructEntry

    def _make_one(self, *args, **kw):
        return self._get_target_class()(*args, **kw)

    def test_to_api_repr_defaults(self):
        from google.cloud.logging.logger import _GLOBAL_RESOURCE

        LOG_NAME = "test.log"
        JSON_PAYLOAD = {"key": "value"}
        entry = self._make_one(log_name=LOG_NAME, payload=JSON_PAYLOAD)
        expected = {
            "logName": LOG_NAME,
            "jsonPayload": JSON_PAYLOAD,
            "resource": _GLOBAL_RESOURCE._to_dict(),
        }
        self.assertEqual(entry.to_api_repr(), expected)

    def test_to_api_repr_explicit(self):
        import datetime
        from google.cloud.logging.resource import Resource
        from google.cloud._helpers import _datetime_to_rfc3339

        LOG_NAME = "test.log"
        JSON_PAYLOAD = {"key": "value"}
        LABELS = {"foo": "bar", "baz": "qux"}
        IID = "IID"
        SEVERITY = "CRITICAL"
        METHOD = "POST"
        URI = "https://api.example.com/endpoint"
        STATUS = "500"
        REQUEST = {"requestMethod": METHOD, "requestUrl": URI, "status": STATUS}
        TIMESTAMP = datetime.datetime(2016, 12, 31, 0, 1, 2, 999999)
        RESOURCE = Resource(
            type="gae_app", labels={"module_id": "default", "version_id": "test"}
        )
        TRACE = "12345678-1234-5678-1234-567812345678"
        SPANID = "000000000000004a"
        FILE = "my_file.py"
        LINE = 123
        FUNCTION = "my_function"
        SOURCE_LOCATION = {"file": FILE, "line": LINE, "function": FUNCTION}
        OP_ID = "OP_ID"
        PRODUCER = "PRODUCER"
        OPERATION = {"id": OP_ID, "producer": PRODUCER, "first": True, "last": False}
        expected = {
            "logName": LOG_NAME,
            "jsonPayload": JSON_PAYLOAD,
            "labels": LABELS,
            "insertId": IID,
            "severity": SEVERITY,
            "httpRequest": REQUEST,
            "timestamp": _datetime_to_rfc3339(TIMESTAMP),
            "resource": RESOURCE._to_dict(),
            "trace": TRACE,
            "spanId": SPANID,
            "traceSampled": True,
            "sourceLocation": {"file": FILE, "line": str(LINE), "function": FUNCTION},
            "operation": OPERATION,
        }
        entry = self._make_one(
            log_name=LOG_NAME,
            payload=JSON_PAYLOAD,
            labels=LABELS,
            insert_id=IID,
            severity=SEVERITY,
            http_request=REQUEST,
            timestamp=TIMESTAMP,
            resource=RESOURCE,
            trace=TRACE,
            span_id=SPANID,
            trace_sampled=True,
            source_location=SOURCE_LOCATION,
            operation=OPERATION,
        )

        self.assertEqual(entry.to_api_repr(), expected)


class TestProtobufEntry(unittest.TestCase):

    PROJECT = "PROJECT"
    LOGGER_NAME = "LOGGER_NAME"

    @staticmethod
    def _get_target_class():
        from google.cloud.logging.entries import ProtobufEntry

        return ProtobufEntry

    def _make_one(self, *args, **kw):
        return self._get_target_class()(*args, **kw)

    def test_constructor_basic(self):
        payload = {"foo": "bar"}

        pb_entry = self._make_one(payload=payload, logger=mock.sentinel.logger)

        self.assertIs(pb_entry.payload, payload)
        self.assertIsNone(pb_entry.payload_pb)
        self.assertIs(pb_entry.payload_json, payload)
        self.assertIs(pb_entry.logger, mock.sentinel.logger)
        self.assertIsNone(pb_entry.insert_id)
        self.assertIsNone(pb_entry.timestamp)
        self.assertIsNone(pb_entry.labels)
        self.assertIsNone(pb_entry.severity)
        self.assertIsNone(pb_entry.http_request)
        self.assertIsNone(pb_entry.trace)
        self.assertIsNone(pb_entry.span_id)
        self.assertIsNone(pb_entry.trace_sampled)
        self.assertIsNone(pb_entry.source_location)

    def test_constructor_with_any(self):
        from google.protobuf.any_pb2 import Any

        payload = Any()

        pb_entry = self._make_one(payload=payload, logger=mock.sentinel.logger)

        self.assertIs(pb_entry.payload, payload)
        self.assertIs(pb_entry.payload_pb, payload)
        self.assertIsNone(pb_entry.payload_json)
        self.assertIs(pb_entry.logger, mock.sentinel.logger)
        self.assertIsNone(pb_entry.insert_id)
        self.assertIsNone(pb_entry.timestamp)
        self.assertIsNone(pb_entry.labels)
        self.assertIsNone(pb_entry.severity)
        self.assertIsNone(pb_entry.http_request)
        self.assertIsNone(pb_entry.trace)
        self.assertIsNone(pb_entry.span_id)
        self.assertIsNone(pb_entry.trace_sampled)
        self.assertIsNone(pb_entry.source_location)

    def test_parse_message(self):
        import json
        from google.protobuf.json_format import MessageToJson
        from google.protobuf.struct_pb2 import Struct, Value

        message = Struct(fields={"foo": Value(bool_value=False)})
        with_true = Struct(fields={"foo": Value(bool_value=True)})
        payload = json.loads(MessageToJson(with_true))
        entry = self._make_one(payload=payload, logger=mock.sentinel.logger)

        entry.parse_message(message)

        self.assertTrue(message.fields["foo"])

    def test_to_api_repr_proto_defaults(self):
        from google.protobuf.json_format import MessageToDict
        from google.cloud.logging.logger import _GLOBAL_RESOURCE
        from google.protobuf.struct_pb2 import Struct
        from google.protobuf.struct_pb2 import Value

        LOG_NAME = "test.log"
        message = Struct(fields={"foo": Value(bool_value=True)})

        entry = self._make_one(log_name=LOG_NAME, payload=message)
        expected = {
            "logName": LOG_NAME,
            "protoPayload": MessageToDict(message),
            "resource": _GLOBAL_RESOURCE._to_dict(),
        }
        self.assertEqual(entry.to_api_repr(), expected)

    def test_to_api_repr_proto_explicit(self):
        import datetime
        from google.protobuf.json_format import MessageToDict
        from google.cloud.logging.resource import Resource
        from google.cloud._helpers import _datetime_to_rfc3339
        from google.protobuf.struct_pb2 import Struct
        from google.protobuf.struct_pb2 import Value

        LOG_NAME = "test.log"
        message = Struct(fields={"foo": Value(bool_value=True)})
        LABELS = {"foo": "bar", "baz": "qux"}
        IID = "IID"
        SEVERITY = "CRITICAL"
        METHOD = "POST"
        URI = "https://api.example.com/endpoint"
        STATUS = "500"
        REQUEST = {"requestMethod": METHOD, "requestUrl": URI, "status": STATUS}
        TIMESTAMP = datetime.datetime(2016, 12, 31, 0, 1, 2, 999999)
        RESOURCE = Resource(
            type="gae_app", labels={"module_id": "default", "version_id": "test"}
        )
        TRACE = "12345678-1234-5678-1234-567812345678"
        SPANID = "000000000000004a"
        FILE = "my_file.py"
        LINE = 123
        FUNCTION = "my_function"
        SOURCE_LOCATION = {"file": FILE, "line": LINE, "function": FUNCTION}
        OP_ID = "OP_ID"
        PRODUCER = "PRODUCER"
        OPERATION = {"id": OP_ID, "producer": PRODUCER, "first": True, "last": False}
        expected = {
            "logName": LOG_NAME,
            "protoPayload": MessageToDict(message),
            "labels": LABELS,
            "insertId": IID,
            "severity": SEVERITY,
            "httpRequest": REQUEST,
            "timestamp": _datetime_to_rfc3339(TIMESTAMP),
            "resource": RESOURCE._to_dict(),
            "trace": TRACE,
            "spanId": SPANID,
            "traceSampled": True,
            "sourceLocation": {"file": FILE, "line": str(LINE), "function": FUNCTION},
            "operation": OPERATION,
        }

        entry = self._make_one(
            log_name=LOG_NAME,
            payload=message,
            labels=LABELS,
            insert_id=IID,
            severity=SEVERITY,
            http_request=REQUEST,
            timestamp=TIMESTAMP,
            resource=RESOURCE,
            trace=TRACE,
            span_id=SPANID,
            trace_sampled=True,
            source_location=SOURCE_LOCATION,
            operation=OPERATION,
        )

        self.assertEqual(entry.to_api_repr(), expected)


def _datetime_to_rfc3339_w_nanos(value):
    from google.cloud._helpers import _RFC3339_NO_FRACTION

    no_fraction = value.strftime(_RFC3339_NO_FRACTION)
    return "%s.%09dZ" % (no_fraction, value.microsecond * 1000)


class _Logger(object):
    def __init__(self, name, client):
        self.name = name
        self.client = client


class _Client(object):
    def __init__(self, project):
        self.project = project

    def logger(self, name):
        return _Logger(name, self)
