def _extract_logs( self, span: ReadableSpan) -> Optional[Sequence[TCollector.Log]]: """Returns jaeger logs if events exists, otherwise None. Args: span: span to extract logs """ if not span.events: return None logs = [] for event in span.events: fields = [] for key, value in event.attributes.items(): tag = _translate_attribute(key, value) if tag: fields.append(tag) fields.append( TCollector.Tag( key="message", vType=TCollector.TagType.STRING, vStr=event.name, )) event_timestamp_us = _nsec_to_usec_round(event.timestamp) logs.append( TCollector.Log(timestamp=int(event_timestamp_us), fields=fields)) return logs
def export(self, spans): jaeger_spans = _translate_to_jaeger(spans) batch = jaeger.Batch( spans=jaeger_spans, process=jaeger.Process(serviceName=self.service_name), ) if self.collector is not None: self.collector.submit(batch) self.agent_client.emit(batch) return SpanExportResult.SUCCESS
def _convert_attribute_to_tag(key, attr): """Convert the attributes to jaeger tags.""" if isinstance(attr, bool): return jaeger.Tag(key=key, vBool=attr, vType=jaeger.TagType.BOOL) if isinstance(attr, str): return jaeger.Tag(key=key, vStr=attr, vType=jaeger.TagType.STRING) if isinstance(attr, int): return jaeger.Tag(key=key, vLong=attr, vType=jaeger.TagType.LONG) if isinstance(attr, float): return jaeger.Tag(key=key, vDouble=attr, vType=jaeger.TagType.DOUBLE) if isinstance(attr, tuple): return jaeger.Tag(key=key, vStr=str(attr), vType=jaeger.TagType.STRING) logger.warning("Could not serialize attribute %s:%r to tag", key, attr) return None
def _translate_span(self, span: ReadableSpan) -> TCollector.Span: ctx = span.get_span_context() trace_id = ctx.trace_id span_id = ctx.span_id start_time_us = _nsec_to_usec_round(span.start_time) duration_us = _nsec_to_usec_round(span.end_time - span.start_time) parent_id = span.parent.span_id if span.parent else 0 tags = self._extract_tags(span) refs = self._extract_refs(span) logs = self._extract_logs(span) flags = int(ctx.trace_flags) jaeger_span = TCollector.Span( traceIdHigh=_get_trace_id_high(trace_id), traceIdLow=_get_trace_id_low(trace_id), spanId=_convert_int_to_i64(span_id), operationName=span.name, startTime=start_time_us, duration=duration_us, tags=tags, logs=logs, references=refs, flags=flags, parentSpanId=_convert_int_to_i64(parent_id), ) return jaeger_span
def _translate_to_jaeger(spans: Span): """Translate the spans to Jaeger format. Args: spans: Tuple of spans to convert """ jaeger_spans = [] for span in spans: ctx = span.get_context() trace_id = ctx.trace_id span_id = ctx.span_id start_time_us = _nsec_to_usec_round(span.start_time) duration_us = _nsec_to_usec_round(span.end_time - span.start_time) status = span.status parent_id = span.parent.span_id if span.parent else 0 tags = _extract_tags(span.attributes) tags.extend(_extract_tags(span.resource.attributes)) tags.extend( [ _get_long_tag("status.code", status.canonical_code.value), _get_string_tag("status.message", status.description), _get_string_tag("span.kind", span.kind.name), ] ) # Ensure that if Status.Code is not OK, that we set the "error" tag on the Jaeger span. if status.canonical_code is not StatusCanonicalCode.OK: tags.append(_get_bool_tag("error", True)) refs = _extract_refs_from_span(span) logs = _extract_logs_from_span(span) flags = int(ctx.trace_flags) jaeger_span = jaeger.Span( traceIdHigh=_get_trace_id_high(trace_id), traceIdLow=_get_trace_id_low(trace_id), # generated code expects i64 spanId=_convert_int_to_i64(span_id), operationName=span.name, startTime=start_time_us, duration=duration_us, tags=tags, logs=logs, references=refs, flags=flags, parentSpanId=_convert_int_to_i64(parent_id), ) jaeger_spans.append(jaeger_span) return jaeger_spans
def _extract_logs_from_span(span): if not span.events: return None logs = [] for event in span.events: fields = _extract_tags(event.attributes) fields.append( jaeger.Tag(key="message", vType=jaeger.TagType.STRING, vStr=event.name)) event_timestamp_us = _nsec_to_usec_round(event.timestamp) logs.append( jaeger.Log(timestamp=int(event_timestamp_us), fields=fields)) return logs
def export(self, spans) -> SpanExportResult: translator = Translate(spans) if self.transport_format == TRANSPORT_FORMAT_PROTOBUF: pb_translator = ProtobufTranslator(self.service_name) jaeger_spans = translator._translate(pb_translator) batch = model_pb2.Batch(spans=jaeger_spans) request = PostSpansRequest(batch=batch) self._collector_grpc_client.PostSpans(request) else: thrift_translator = ThriftTranslator() jaeger_spans = translator._translate(thrift_translator) batch = jaeger_thrift.Batch( spans=jaeger_spans, process=jaeger_thrift.Process(serviceName=self.service_name), ) if self._collector_http_client is not None: self._collector_http_client.submit(batch) else: self._agent_client.emit(batch) return SpanExportResult.SUCCESS
def _extract_refs_from_span(span): if not span.links: return None refs = [] for link in span.links: trace_id = link.context.trace_id span_id = link.context.span_id refs.append( jaeger.SpanRef( refType=jaeger.SpanRefType.FOLLOWS_FROM, traceIdHigh=_get_trace_id_high(trace_id), traceIdLow=_get_trace_id_low(trace_id), spanId=_convert_int_to_i64(span_id), )) return refs
def _extract_refs(self, span: Span) -> Optional[Sequence[TCollector.SpanRef]]: if not span.links: return None refs = [] for link in span.links: trace_id = link.context.trace_id span_id = link.context.span_id refs.append( TCollector.SpanRef( refType=TCollector.SpanRefType.FOLLOWS_FROM, traceIdHigh=_get_trace_id_high(trace_id), traceIdLow=_get_trace_id_low(trace_id), spanId=_convert_int_to_i64(span_id), )) return refs
def _get_bool_tag(key, val): return jaeger.Tag(key=key, vBool=val, vType=jaeger.TagType.BOOL)
def _get_string_tag(key, val): return jaeger.Tag(key=key, vStr=val, vType=jaeger.TagType.STRING)
def _get_long_tag(key, val): return jaeger.Tag(key=key, vLong=val, vType=jaeger.TagType.LONG)
def _get_double_tag(key: str, value: float) -> TCollector.Tag: """Returns jaeger double tag.""" return TCollector.Tag( key=key, vDouble=value, vType=TCollector.TagType.DOUBLE )
def _get_long_tag(key: str, value: int) -> TCollector.Tag: """Returns jaeger long tag.""" return TCollector.Tag(key=key, vLong=value, vType=TCollector.TagType.LONG)
def _get_bool_tag(key: str, value: bool) -> TCollector.Tag: """Returns jaeger boolean tag.""" return TCollector.Tag(key=key, vBool=value, vType=TCollector.TagType.BOOL)
def _get_string_tag(key, value: str) -> TCollector.Tag: """Returns jaeger string tag.""" return TCollector.Tag(key=key, vStr=value, vType=TCollector.TagType.STRING)