def test_initialization(self): lf = LogFields() self.assertEqual(lf.fields, {}) fields = {"k1": "v1", "k2": 2, "k3": True} lf = LogFields(fields=fields) self.assertEqual(lf.fields, fields)
def add_request_log_fields(self, log_fields: LogFields, call_details: Union[grpc.HandlerCallDetails, grpc.ClientCallDetails]): """Add log fields related to a request to the provided log fields :param log_fields: log fields instance to which to add the fields :param call_details: some information regarding the call """ service, method = call_details.method[1:].split("/") log_fields.add_fields({ "system": "grpc", "span.kind": self.KIND, "grpc.service": service, "grpc.method": method, })
def test_add_fields(self): lf = LogFields() lf.add_fields({"k1": "v1", "w": 3}) self.assertEqual(lf.fields, {"k1": "v1", "w": 3}) fields = {"k1": "v1", "k2": 2, "k3": True} lf = LogFields(fields=fields) lf.add_fields({"k1": "y", "w": 3}) self.assertEqual(lf.fields, {"k1": "v1", "k2": 2, "k3": True, "w": 3})
def test_initialization_from_metadata(self): metadata = { "outer_k1": "v1", "outer_k2": 2, "outer_k3": True, } lf = LogFields.from_metadata(metadata) self.assertEqual(lf.fields, {}) metadata = { "outer_k1": "v1", "outer_k2": 2, "outer_k3": True, LOG_FIELDS_KEY_META: '{"k1": "v1", "k2": 2, "k3": true}' } fields = {"k1": "v1", "k2": 2, "k3": True} lf = LogFields.from_metadata(metadata) self.assertEqual(lf.fields, fields)
def add_response_log_fields(self, log_fields: LogFields, start_time: datetime, err: Exception): """Add log fields related to a response to the provided log fields :param log_fields: log fields instnace to which to add the fields :param start_time: start time of the request :param err: exception raised during the handling of the request. """ code = "Unknown" if err is not None else "OK" duration = (datetime.utcnow() - start_time).total_seconds() * 1000 log_fields.add_fields({ "grpc.start_time": start_time.isoformat() + "Z", "grpc.code": code, "duration": "{duration}ms".format(duration=duration), })
def intercept(self, continuation, client_call_details, request): log_fields = LogFields.from_metadata( dict(client_call_details.metadata or {})) self.add_request_log_fields(log_fields, client_call_details) self._log_fn(log_fields, self.PRE_REQUEST_MESSAGE) start = datetime.utcnow() out = continuation(client_call_details, request) self.add_response_log_fields(log_fields, start, None) self._log_fn(log_fields, self.POST_REQUEST_MESSAGE) return out
def intercept_service(self, continuation, handler_call_details): log_fields = LogFields.from_metadata( dict(handler_call_details.invocation_metadata or {})) self.add_request_log_fields(log_fields, handler_call_details) out = continuation(handler_call_details) # wraps each gRPC method independently the type, the correct one # is ensured to be called by the wrapper. return out._replace( unary_unary=self._build_wrapper(log_fields, out.unary_unary), unary_stream=self._build_wrapper(log_fields, out.unary_stream), stream_unary=self._build_wrapper(log_fields, out.stream_unary), stream_stream=self._build_wrapper(log_fields, out.stream_stream), )
def test_serialization(self): lf = LogFields() self.assertEqual(json.loads(lf.dumps()), {}) fields = {"k1": "v1", "k2": 2, "k3": True} lf = LogFields(fields=fields) self.assertEqual(json.loads(lf.dumps()), { "k1": "v1", "k2": 2, "k3": True })