def log_spans(self): """Main function to log all the annotations stored during the entire request. This is done if the request is sampled and the response was a success. It also logs the service `ss` and `sr` annotations. """ if self.zipkin_attrs.is_sampled and self.is_response_success(): for span in self.handler.spans: # If a logged client span overrode the 'service_name' attr, # swap that out. if span['service_name'] is None: endpoint = self.thrift_endpoint else: endpoint = copy_endpoint_with_new_service_name( self.thrift_endpoint, span['service_name'] ) annotations = annotation_list_builder( span['annotations'], endpoint) binary_annotations = binary_annotation_list_builder( span['binary_annotations'], endpoint) log_span(self.zipkin_attrs, span['span_name'], self.registry_settings, annotations, binary_annotations, span['is_client']) end_timestamp = time.time() log_service_span(self.zipkin_attrs, self.start_timestamp, end_timestamp, self.binary_annotations_dict, self.thrift_endpoint, self.request_method, self.registry_settings)
def log_service_span(zipkin_attrs, start_timestamp, end_timestamp, binary_annotations_dict, thrift_endpoint, method, registry_settings): """Logs a span with `ss` and `sr` annotations. """ annotations = annotation_list_builder( {'sr': start_timestamp, 'ss': end_timestamp}, thrift_endpoint) binary_annotations = binary_annotation_list_builder( binary_annotations_dict, thrift_endpoint) log_span(zipkin_attrs, method, registry_settings, annotations, binary_annotations, False)
def log_spans(self): """Main function to log all the annotations stored during the entire request. This is done if the request is sampled and the response was a success. It also logs the service `ss` and `sr` annotations. """ if self.zipkin_attrs.is_sampled and self.is_response_success(): for _, span in self.handler.spans.items(): annotations = annotation_list_builder( span['annotations'], self.endpoint_attrs) binary_annotations = binary_annotation_list_builder( span['binary_annotations'], self.endpoint_attrs) log_span(self.zipkin_attrs, span['span_name'], self.registry_settings, annotations, binary_annotations, span['is_client']) end_timestamp = time.time() log_service_span(self.zipkin_attrs, self.start_timestamp, end_timestamp, self.binary_annotations_dict, self.endpoint_attrs, self.request_method, self.registry_settings)
def log_spans(self): """Main function to log all the annotations stored during the entire request. This is done if the request is sampled and the response was a success. It also logs the service `ss` and `sr` annotations. """ if self.zipkin_attrs.is_sampled and self.is_response_success(): for _, span in self.handler.spans.items(): annotations = annotation_list_builder(span['annotations'], self.endpoint_attrs) binary_annotations = binary_annotation_list_builder( span['binary_annotations'], self.endpoint_attrs) log_span(self.zipkin_attrs, span['span_name'], self.registry_settings, annotations, binary_annotations, span['is_client']) end_timestamp = time.time() log_service_span(self.zipkin_attrs, self.start_timestamp, end_timestamp, self.binary_annotations_dict, self.endpoint_attrs, self.request_method, self.registry_settings)
def log_spans(self): """Main function to log all the annotations stored during the entire request. This is done if the request is sampled and the response was a success. It also logs the service `ss` and `sr` annotations. """ if self.zipkin_attrs.is_sampled and self.is_response_success(): # Collect additional annotations from the logging handler annotations_by_span_id = defaultdict(dict) binary_annotations_by_span_id = defaultdict(dict) for msg in self.handler.extra_annotations: span_id = msg['parent_span_id'] or self.zipkin_attrs.span_id # This should check if these are non-None annotations_by_span_id[span_id].update(msg['annotations']) binary_annotations_by_span_id[span_id].update( msg['binary_annotations'] ) # Collect, annotate, and log client spans from the logging handler for span in self.handler.client_spans: # The parent_span_id is either the parent ID set in the # logging handler or the current Zipkin context's span ID. parent_span_id = ( span['parent_span_id'] or self.zipkin_attrs.span_id ) # A new client span's span ID can be overridden span_id = span['span_id'] or generate_random_64bit_string() endpoint = copy_endpoint_with_new_service_name( self.thrift_endpoint, span['service_name'] ) # Collect annotations both logged with the new spans and # logged in separate log messages. annotations = span['annotations'] annotations.update(annotations_by_span_id[span_id]) binary_annotations = span['binary_annotations'] binary_annotations.update(binary_annotations_by_span_id[span_id]) # Create serializable thrift objects of annotations thrift_annotations = annotation_list_builder( annotations, endpoint ) thrift_binary_annotations = binary_annotation_list_builder( binary_annotations, endpoint ) log_span( span_id=span_id, parent_span_id=parent_span_id, trace_id=self.zipkin_attrs.trace_id, span_name=span['span_name'], annotations=thrift_annotations, binary_annotations=thrift_binary_annotations, registry_settings=self.registry_settings, ) # Collect extra annotations for server span, then log it. extra_annotations = annotations_by_span_id[self.zipkin_attrs.span_id] extra_binary_annotations = binary_annotations_by_span_id[ self.zipkin_attrs.span_id ] annotations = dict( sr=self.start_timestamp, ss=time.time(), **extra_annotations ) thrift_annotations = annotation_list_builder( annotations, self.thrift_endpoint, ) # Binary annotations can be set through debug messages or the # set_extra_binary_annotations registry setting. self.binary_annotations_dict.update(extra_binary_annotations) thrift_binary_annotations = binary_annotation_list_builder( self.binary_annotations_dict, self.thrift_endpoint, ) span_name = "{0} {1}".format( self.request_method, self.request_path) log_span( span_id=self.zipkin_attrs.span_id, parent_span_id=self.zipkin_attrs.parent_span_id, trace_id=self.zipkin_attrs.trace_id, span_name=span_name, annotations=thrift_annotations, binary_annotations=thrift_binary_annotations, registry_settings=self.registry_settings, )
def test_binary_annotation_list_builder_with_nonstring_values(): bann_list = {'test key': 5} banns = thrift_helper.binary_annotation_list_builder(bann_list, 'host') assert banns[0].key == 'test key' assert banns[0].value == '5'
def test_binary_annotation_list_builder(bann_mock): bann_list = {'key1': 'val1', 'key2': 'val2'} thrift_helper.binary_annotation_list_builder(bann_list, 'host') bann_mock.assert_any_call('key1', 'val1', 6, 'host') bann_mock.assert_any_call('key2', 'val2', 6, 'host') assert bann_mock.call_count == 2
def test_binary_annotation_list_builder(bann_mock): bann_list = {'key1': 'val1', 'key2': 'val2'} thrift_helper.binary_annotation_list_builder(bann_list, 'host') bann_mock.assert_any_call('key1', 'val1', 6, 'host') bann_mock.assert_any_call('key2', 'val2', 6, 'host') assert bann_mock.call_count == 2
def test_binary_annotation_list_builder(bann_mock): bann_list = {"key1": "val1", "key2": "val2"} thrift_helper.binary_annotation_list_builder(bann_list, "host") bann_mock.assert_any_call("key1", "val1", 6, "host") bann_mock.assert_any_call("key2", "val2", 6, "host") assert bann_mock.call_count == 2