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, self._max_tag_value_length) 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 _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 export(self, spans) -> SpanExportResult: # Populate service_name from first span # We restrict any SpanProcessor to be only associated with a single # TracerProvider, so it is safe to assume that all Spans in a single # batch all originate from one TracerProvider (and in turn have all # the same service.name) if spans: service_name = spans[0].resource.attributes.get(SERVICE_NAME) if service_name: self.service_name = service_name translator = Translate(spans) thrift_translator = ThriftTranslator(self._max_tag_value_length) 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( self, span: ReadableSpan) -> 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 emit(self, batch: jaeger.Batch): """ Args: batch: Object to emit Jaeger spans. """ # pylint: disable=protected-access self.client._seqid = 0 # truncate and reset the position of BytesIO object self.buffer._buffer.truncate(0) self.buffer._buffer.seek(0) self.client.emitBatch(batch) buff = self.buffer.getvalue() if len(buff) > self.max_packet_size: if self.split_oversized_batches and len(batch.spans) > 1: packets = math.ceil(len(buff) / self.max_packet_size) div = math.ceil(len(batch.spans) / packets) for packet in range(packets): start = packet * div end = (packet + 1) * div if start < len(batch.spans): self.emit( jaeger.Batch( process=batch.process, spans=batch.spans[start:end], )) else: logger.warning( "Data exceeds the max UDP packet size; size %r, max %r", len(buff), self.max_packet_size, ) return with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as udp_socket: udp_socket.sendto(buff, self.address)
def _get_string_tag(key, value: str) -> TCollector.Tag: """Returns jaeger string tag.""" return TCollector.Tag(key=key, vStr=value, vType=TCollector.TagType.STRING)
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)