def _translate_data( self, data: Sequence[SDKSpan] ) -> ExportTraceServiceRequest: # pylint: disable=attribute-defined-outside-init sdk_resource_instrumentation_library_spans = {} for sdk_span in data: if sdk_span.resource not in ( sdk_resource_instrumentation_library_spans.keys() ): if sdk_span.instrumentation_info is not None: instrumentation_library_spans = InstrumentationLibrarySpans( instrumentation_library=InstrumentationLibrary( name=sdk_span.instrumentation_info.name, version=sdk_span.instrumentation_info.version, ) ) else: instrumentation_library_spans = ( InstrumentationLibrarySpans() ) sdk_resource_instrumentation_library_spans[ sdk_span.resource ] = instrumentation_library_spans self._collector_span_kwargs = {} self._translate_name(sdk_span) self._translate_start_time(sdk_span) self._translate_end_time(sdk_span) self._translate_span_id(sdk_span) self._translate_trace_id(sdk_span) self._translate_parent(sdk_span) self._translate_context_trace_state(sdk_span) self._translate_attributes(sdk_span) self._translate_events(sdk_span) self._translate_links(sdk_span) self._translate_status(sdk_span) self._collector_span_kwargs["kind"] = getattr( CollectorSpan.SpanKind, "SPAN_KIND_{}".format(sdk_span.kind.name), ) sdk_resource_instrumentation_library_spans[ sdk_span.resource ].spans.append(CollectorSpan(**self._collector_span_kwargs)) return ExportTraceServiceRequest( resource_spans=_get_resource_data( sdk_resource_instrumentation_library_spans, ResourceSpans, "spans", ) )
def _translate_data(self, data: Sequence[LogData]) -> ExportLogsServiceRequest: # pylint: disable=attribute-defined-outside-init sdk_resource_instrumentation_library_logs = {} for log_data in data: resource = log_data.log_record.resource instrumentation_library_logs_map = ( sdk_resource_instrumentation_library_logs.get(resource, {})) if not instrumentation_library_logs_map: sdk_resource_instrumentation_library_logs[ resource] = instrumentation_library_logs_map instrumentation_library_logs = ( instrumentation_library_logs_map.get( log_data.instrumentation_info)) if not instrumentation_library_logs: if log_data.instrumentation_info is not None: instrumentation_library_logs_map[ log_data. instrumentation_info] = InstrumentationLibraryLogs( instrumentation_library=InstrumentationLibrary( name=log_data.instrumentation_info.name, version=log_data.instrumentation_info.version, )) else: instrumentation_library_logs_map[ log_data. instrumentation_info] = InstrumentationLibraryLogs() instrumentation_library_logs = ( instrumentation_library_logs_map.get( log_data.instrumentation_info)) self._collector_kwargs = {} self._translate_name(log_data) self._translate_time(log_data) self._translate_span_id(log_data) self._translate_trace_id(log_data) self._translate_trace_flags(log_data) self._translate_body(log_data) self._translate_severity_text(log_data) self._collector_kwargs["attributes"] = self._translate_attributes( log_data.log_record.attributes) self._collector_kwargs[ "severity_number"] = log_data.log_record.severity_number.value instrumentation_library_logs.log_records.append( PB2LogRecord(**self._collector_kwargs)) return ExportLogsServiceRequest(resource_logs=get_resource_data( sdk_resource_instrumentation_library_logs, ResourceLogs, "logs", ))
def test_translate_updowncounter_export_record(self, mock_time_ns): mock_time_ns.configure_mock(**{"return_value": 1}) counter_export_record = ExportRecord( UpDownCounter("c", "d", "e", int, self.meter), [("g", "h")], SumAggregator(), self.resource, ) counter_export_record.aggregator.checkpoint = 1 counter_export_record.aggregator.initial_checkpoint_timestamp = 1 counter_export_record.aggregator.last_update_timestamp = 1 expected = ExportMetricsServiceRequest(resource_metrics=[ ResourceMetrics( resource=OTLPResource(attributes=[ KeyValue(key="a", value=AnyValue(int_value=1)), KeyValue(key="b", value=AnyValue(bool_value=False)), ]), instrumentation_library_metrics=[ InstrumentationLibraryMetrics( instrumentation_library=InstrumentationLibrary( name="name", version="version", ), metrics=[ OTLPMetric( name="c", description="d", unit="e", int_sum=IntSum( data_points=[ IntDataPoint( labels=[ StringKeyValue(key="g", value="h") ], value=1, time_unix_nano=1, start_time_unix_nano=1, ) ], aggregation_temporality=( AggregationTemporality. AGGREGATION_TEMPORALITY_CUMULATIVE), ), ) ], ) ], ) ]) # pylint: disable=protected-access actual = self.exporter._translate_data([counter_export_record]) self.assertEqual(expected, actual)
def test_translate_sum_double(self): expected = ExportMetricsServiceRequest( resource_metrics=[ pb2.ResourceMetrics( resource=OTLPResource( attributes=[ KeyValue(key="a", value=AnyValue(int_value=1)), KeyValue( key="b", value=AnyValue(bool_value=False) ), ] ), instrumentation_library_metrics=[ pb2.InstrumentationLibraryMetrics( instrumentation_library=InstrumentationLibrary( name="first_name", version="first_version" ), metrics=[ pb2.Metric( name="sum_double", unit="s", description="foo", sum=pb2.Sum( data_points=[ pb2.NumberDataPoint( attributes=[ KeyValue( key="a", value=AnyValue( int_value=1 ), ), KeyValue( key="b", value=AnyValue( bool_value=True ), ), ], start_time_unix_nano=1641946015139533244, time_unix_nano=1641946016139533244, as_double=2.98, ) ], aggregation_temporality=AggregationTemporality.CUMULATIVE, is_monotonic=True, ), ) ], ) ], ) ] ) # pylint: disable=protected-access actual = self.exporter._translate_data([self.metrics["sum_double"]]) self.assertEqual(expected, actual)
def test_translate_gauge_double(self): expected = ExportMetricsServiceRequest( resource_metrics=[ pb2.ResourceMetrics( resource=OTLPResource( attributes=[ KeyValue(key="a", value=AnyValue(int_value=1)), KeyValue( key="b", value=AnyValue(bool_value=False) ), ] ), instrumentation_library_metrics=[ pb2.InstrumentationLibraryMetrics( instrumentation_library=InstrumentationLibrary( name="first_name", version="first_version" ), metrics=[ pb2.Metric( name="gauge_double", unit="s", description="foo", gauge=pb2.Gauge( data_points=[ pb2.NumberDataPoint( attributes=[ KeyValue( key="a", value=AnyValue( int_value=1 ), ), KeyValue( key="b", value=AnyValue( bool_value=True ), ), ], time_unix_nano=1641946016139533244, as_double=52.028, ) ], ), ) ], ) ], ) ] ) # pylint: disable=protected-access actual = self.exporter._translate_data([self.metrics["gauge_double"]]) self.assertEqual(expected, actual)
def test_translate_log_data(self): expected = ExportLogsServiceRequest(resource_logs=[ ResourceLogs( resource=OTLPResource(attributes=[ KeyValue(key="key", value=AnyValue(string_value="value")), ]), instrumentation_library_logs=[ InstrumentationLibraryLogs( instrumentation_library=InstrumentationLibrary( name="first_name", version="first_version"), logs=[ PB2LogRecord( # pylint: disable=no-member name="name", time_unix_nano=self.log_data_1.log_record. timestamp, severity_number=self.log_data_1.log_record. severity_number.value, severity_text="WARNING", span_id=int.to_bytes(5213367945872657620, 8, "big"), trace_id=int.to_bytes( 2604504634922341076776623263868986797, 16, "big", ), body=_translate_value( "Zhengzhou, We have a heaviest rains in 1000 years" ), attributes=[ KeyValue( key="a", value=AnyValue(int_value=1), ), KeyValue( key="b", value=AnyValue(string_value="c"), ), ], flags=int( self.log_data_1.log_record.trace_flags), ) ], ) ], ), ]) # pylint: disable=protected-access self.assertEqual(expected, self.exporter._translate_data([self.log_data_1]))
def _translate_data(self, data: Sequence[Metric]) -> ExportMetricsServiceRequest: sdk_resource_instrumentation_library_metrics = {} for metric in data: resource = metric.resource instrumentation_library_map = ( sdk_resource_instrumentation_library_metrics.get(resource, {})) if not instrumentation_library_map: sdk_resource_instrumentation_library_metrics[ resource] = instrumentation_library_map instrumentation_library_metrics = instrumentation_library_map.get( metric.instrumentation_info) if not instrumentation_library_metrics: if metric.instrumentation_info is not None: instrumentation_library_map[ metric. instrumentation_info] = pb2.InstrumentationLibraryMetrics( instrumentation_library=InstrumentationLibrary( name=metric.instrumentation_info.name, version=metric.instrumentation_info.version, )) else: instrumentation_library_map[ metric. instrumentation_info] = pb2.InstrumentationLibraryMetrics( ) instrumentation_library_metrics = instrumentation_library_map.get( metric.instrumentation_info) pbmetric = pb2.Metric( name=metric.name, description=metric.description, unit=metric.unit, ) if isinstance(metric.point, Gauge): pt = pb2.NumberDataPoint( attributes=self._translate_attributes(metric.attributes), time_unix_nano=metric.point.time_unix_nano, ) if isinstance(metric.point.value, int): pt.as_int = metric.point.value else: pt.as_double = metric.point.value pbmetric.gauge.data_points.append(pt) elif isinstance(metric.point, Histogram): pt = pb2.HistogramDataPoint( attributes=self._translate_attributes(metric.attributes), time_unix_nano=metric.point.time_unix_nano, start_time_unix_nano=metric.point.start_time_unix_nano, count=sum(metric.point.bucket_counts), sum=metric.point.sum, bucket_counts=metric.point.bucket_counts, explicit_bounds=metric.point.explicit_bounds, ) pbmetric.histogram.aggregation_temporality = ( metric.point.aggregation_temporality) pbmetric.histogram.data_points.append(pt) elif isinstance(metric.point, Sum): pt = pb2.NumberDataPoint( attributes=self._translate_attributes(metric.attributes), start_time_unix_nano=metric.point.start_time_unix_nano, time_unix_nano=metric.point.time_unix_nano, ) if isinstance(metric.point.value, int): pt.as_int = metric.point.value else: pt.as_double = metric.point.value # note that because sum is a message type, the fields must be # set individually rather than instantiating a pb2.Sum and setting # it once pbmetric.sum.aggregation_temporality = ( metric.point.aggregation_temporality) pbmetric.sum.is_monotonic = metric.point.is_monotonic pbmetric.sum.data_points.append(pt) else: logger.warn("unsupported datapoint type %s", metric.point) continue instrumentation_library_metrics.metrics.append(pbmetric, ) return ExportMetricsServiceRequest(resource_metrics=get_resource_data( sdk_resource_instrumentation_library_metrics, pb2.ResourceMetrics, "metrics", ))
def test_translate_multiple_logs(self): expected = ExportLogsServiceRequest(resource_logs=[ ResourceLogs( resource=OTLPResource(attributes=[ KeyValue(key="key", value=AnyValue(string_value="value")), ]), instrumentation_library_logs=[ InstrumentationLibraryLogs( instrumentation_library=InstrumentationLibrary( name="first_name", version="first_version"), logs=[ PB2LogRecord( # pylint: disable=no-member name="name", time_unix_nano=self.log_data_1.log_record. timestamp, severity_number=self.log_data_1.log_record. severity_number.value, severity_text="WARNING", span_id=int.to_bytes(5213367945872657620, 8, "big"), trace_id=int.to_bytes( 2604504634922341076776623263868986797, 16, "big", ), body=_translate_value( "Zhengzhou, We have a heaviest rains in 1000 years" ), attributes=[ KeyValue( key="a", value=AnyValue(int_value=1), ), KeyValue( key="b", value=AnyValue(string_value="c"), ), ], flags=int( self.log_data_1.log_record.trace_flags), ) ], ), InstrumentationLibraryLogs( instrumentation_library=InstrumentationLibrary( name="second_name", version="second_version"), logs=[ PB2LogRecord( # pylint: disable=no-member name="info name", time_unix_nano=self.log_data_2.log_record. timestamp, severity_number=self.log_data_2.log_record. severity_number.value, severity_text="INFO", span_id=int.to_bytes(5213367945872657623, 8, "big"), trace_id=int.to_bytes( 2604504634922341076776623263868986799, 16, "big", ), body=_translate_value( "Sydney, Opera House is closed"), attributes=[ KeyValue( key="custom_attr", value=_translate_value([1, 2, 3]), ), ], flags=int( self.log_data_2.log_record.trace_flags), ) ], ), ], ), ResourceLogs( resource=OTLPResource(attributes=[ KeyValue( key="service", value=AnyValue(string_value="myapp"), ), ]), instrumentation_library_logs=[ InstrumentationLibraryLogs( instrumentation_library=InstrumentationLibrary( name="third_name", version="third_version"), logs=[ PB2LogRecord( # pylint: disable=no-member name="error name", time_unix_nano=self.log_data_3.log_record. timestamp, severity_number=self.log_data_3.log_record. severity_number.value, severity_text="ERROR", span_id=int.to_bytes(5213367945872657628, 8, "big"), trace_id=int.to_bytes( 2604504634922341076776623263868986800, 16, "big", ), body=_translate_value( "Mumbai, Boil water before drinking"), attributes=[], flags=int( self.log_data_3.log_record.trace_flags), ) ], ) ], ), ]) # pylint: disable=protected-access self.assertEqual( expected, self.exporter._translate_data( [self.log_data_1, self.log_data_2, self.log_data_3]), )
def test_translate_spans(self): expected = ExportTraceServiceRequest(resource_spans=[ ResourceSpans( resource=OTLPResource(attributes=[ KeyValue(key="a", value=AnyValue(int_value=1)), KeyValue(key="b", value=AnyValue(bool_value=False)), ]), instrumentation_library_spans=[ InstrumentationLibrarySpans( instrumentation_library=InstrumentationLibrary( name="name", version="version"), spans=[ OTLPSpan( # pylint: disable=no-member name="a", start_time_unix_nano=self.span.start_time, end_time_unix_nano=self.span.end_time, trace_state="a=b,c=d", span_id=int.to_bytes(10217189687419569865, 8, "big"), trace_id=int.to_bytes( 67545097771067222548457157018666467027, 16, "big", ), parent_span_id=(b"\000\000\000\000\000\00009"), kind=(OTLPSpan.SpanKind.SPAN_KIND_INTERNAL), attributes=[ KeyValue( key="a", value=AnyValue(int_value=1), ), KeyValue( key="b", value=AnyValue(bool_value=True), ), ], events=[ OTLPSpan.Event( name="a", time_unix_nano=1591240820506462784, attributes=[ KeyValue( key="a", value=AnyValue(int_value=1), ), KeyValue( key="b", value=AnyValue( bool_value=False), ), ], ) ], status=Status(code=0, message=""), links=[ OTLPSpan.Link( trace_id=int.to_bytes(1, 16, "big"), span_id=int.to_bytes(2, 8, "big"), attributes=[ KeyValue( key="a", value=AnyValue(int_value=1), ), KeyValue( key="b", value=AnyValue( bool_value=False), ), ], ) ], ) ], ) ], ), ]) # pylint: disable=protected-access self.assertEqual(expected, self.exporter._translate_data([self.span]))
def _translate_data( self, data: Sequence[ReadableSpan]) -> ExportTraceServiceRequest: # pylint: disable=attribute-defined-outside-init sdk_resource_instrumentation_library_spans = {} for sdk_span in data: instrumentation_library_spans_map = ( sdk_resource_instrumentation_library_spans.get( sdk_span.resource, {})) # If we haven't seen the Resource yet, add it to the map if not instrumentation_library_spans_map: sdk_resource_instrumentation_library_spans[ sdk_span.resource] = instrumentation_library_spans_map instrumentation_library_spans = ( instrumentation_library_spans_map.get( sdk_span.instrumentation_info)) # If we haven't seen the InstrumentationInfo for this Resource yet, add it to the map if not instrumentation_library_spans: if sdk_span.instrumentation_info is not None: instrumentation_library_spans_map[ sdk_span. instrumentation_info] = InstrumentationLibrarySpans( instrumentation_library=InstrumentationLibrary( name=sdk_span.instrumentation_info.name, version=sdk_span.instrumentation_info.version, )) else: # If no InstrumentationInfo, store in None key instrumentation_library_spans_map[ sdk_span. instrumentation_info] = InstrumentationLibrarySpans() instrumentation_library_spans = ( instrumentation_library_spans_map.get( sdk_span.instrumentation_info)) self._collector_kwargs = {} self._translate_name(sdk_span) self._translate_start_time(sdk_span) self._translate_end_time(sdk_span) self._translate_span_id(sdk_span) self._translate_trace_id(sdk_span) self._translate_parent(sdk_span) self._translate_context_trace_state(sdk_span) self._collector_kwargs["attributes"] = self._translate_attributes( sdk_span.attributes) self._translate_events(sdk_span) self._translate_links(sdk_span) self._translate_status(sdk_span) if sdk_span.dropped_attributes: self._collector_kwargs[ "dropped_attributes_count"] = sdk_span.dropped_attributes if sdk_span.dropped_events: self._collector_kwargs[ "dropped_events_count"] = sdk_span.dropped_events if sdk_span.dropped_links: self._collector_kwargs[ "dropped_links_count"] = sdk_span.dropped_links self._collector_kwargs["kind"] = getattr( CollectorSpan.SpanKind, f"SPAN_KIND_{sdk_span.kind.name}", ) instrumentation_library_spans.spans.append( CollectorSpan(**self._collector_kwargs)) return ExportTraceServiceRequest(resource_spans=get_resource_data( sdk_resource_instrumentation_library_spans, ResourceSpans, "spans", ))
def test_translate_histogram(self): expected = ExportMetricsServiceRequest( resource_metrics=[ pb2.ResourceMetrics( resource=OTLPResource( attributes=[ KeyValue(key="a", value=AnyValue(int_value=1)), KeyValue( key="b", value=AnyValue(bool_value=False) ), ] ), instrumentation_library_metrics=[ pb2.InstrumentationLibraryMetrics( instrumentation_library=InstrumentationLibrary( name="first_name", version="first_version" ), metrics=[ pb2.Metric( name="histogram", unit="s", description="foo", histogram=pb2.Histogram( data_points=[ pb2.HistogramDataPoint( attributes=[ KeyValue( key="a", value=AnyValue( int_value=1 ), ), KeyValue( key="b", value=AnyValue( bool_value=True ), ), ], start_time_unix_nano=1641946016139533244, time_unix_nano=1641946016139533244, count=5, sum=67, bucket_counts=[1, 4], explicit_bounds=[10.0, 20.0], exemplars=[], flags=pb2.DataPointFlags.FLAG_NONE, ) ], aggregation_temporality=AggregationTemporality.DELTA, ), ) ], ) ], ) ] ) # pylint: disable=protected-access actual = self.exporter._translate_data([self.metrics["histogram"]]) self.assertEqual(expected, actual)