def translate_to_zipkin(self, span_datas): """Translate the opencensus spans to zipkin spans. :type span_datas: list of :class: `~opencensus.trace.span_data.SpanData` :param span_datas: SpanData tuples to emit :rtype: list :returns: List of zipkin format spans. """ local_endpoint = { 'serviceName': self.service_name, 'port': self.port, } if self.ipv4 is not None: local_endpoint['ipv4'] = self.ipv4 if self.ipv6 is not None: local_endpoint['ipv6'] = self.ipv6 zipkin_spans = [] for span in span_datas: # Timestamp in zipkin spans is int of microseconds. start_timestamp_mus = timestamp_to_microseconds(span.start_time) end_timestamp_mus = timestamp_to_microseconds(span.end_time) duration_mus = end_timestamp_mus - start_timestamp_mus zipkin_span = { 'traceId': span.context.trace_id, 'id': str(span.span_id), 'name': span.name, 'timestamp': int(round(start_timestamp_mus)), 'duration': int(round(duration_mus)), 'localEndpoint': local_endpoint, 'tags': _extract_tags_from_span(span.attributes), 'annotations': _extract_annotations_from_span(span), } span_kind = span.span_kind parent_span_id = span.parent_span_id if span_kind is not None: kind = SPAN_KIND_MAP.get(span_kind) # Zipkin API for span kind only accept # enum(CLIENT|SERVER|PRODUCER|CONSUMER|Absent) if kind is not None: zipkin_span['kind'] = kind if parent_span_id is not None: zipkin_span['parentId'] = str(parent_span_id) zipkin_spans.append(zipkin_span) return zipkin_spans
def honeycombSpan(span_data): start_timestamp_mus = timestamp_to_microseconds(span_data.start_time) end_timestamp_mus = timestamp_to_microseconds(span_data.end_time) sc = span_data.context hcSpan = { "trace.trace_id": sc.trace_id, "name": span_data.name, "trace.span_id": span_data.span_id, "duration_ms": round((end_timestamp_mus - start_timestamp_mus) / 1000), } if span_data.parent_span_id != None: hcSpan["trace.parent_id"] = span_data.parent_span_id if len(span_data.time_events): hcSpan["annotations"] = _extract_annotations_from_span(span_data) return hcSpan
def emit(self, span_datas): """Immediately marshal span data to the tracing backend :param span_datas: list of :class:`opencensus.trace.span_data.SpanData` to emit :type span_datas: list """ spans = [] for span_data in span_datas: start_timestamp_mus = timestamp_to_microseconds( span_data.start_time) end_timestamp_mus = timestamp_to_microseconds(span_data.end_time) duration_mus = end_timestamp_mus - start_timestamp_mus start_time_ms = start_timestamp_mus // 1000 duration_ms = duration_mus // 1000 span = Span( name=span_data.name, tags=span_data.attributes, guid=span_data.span_id, trace_id=span_data.context.trace_id, parent_id=span_data.parent_span_id, start_time_ms=start_time_ms, duration_ms=duration_ms, ) spans.append(span) try: response = self.client.send_batch(spans, self._common) except Exception: _logger.exception("New Relic send_spans failed with an exception.") return if not response.ok: _logger.error("New Relic send_spans failed with status code: %r", response.status) return response
def _extract_annotations_from_span(span): """Extract and convert time event annotations to zipkin annotations""" if span.annotations is None: return [] annotations = [] for annotation in span.annotations: event_timestamp_mus = timestamp_to_microseconds(annotation.timestamp) annotations.append({ 'timestamp': int(round(event_timestamp_mus)), 'value': annotation.description }) return annotations
def _extract_logs_from_span(span): if span.annotations is None: return None logs = [] for annotation in span.annotations: fields = [] if annotation.attributes is not None: fields = _extract_tags(annotation.attributes.attributes) fields.append( jaeger.Tag(key='message', vType=jaeger.TagType.STRING, vStr=annotation.description)) event_timestamp = timestamp_to_microseconds(annotation.timestamp) logs.append( jaeger.Log(timestamp=int(round(event_timestamp)), fields=fields)) return logs
def translate_to_jaeger(self, span_datas): """Translate the spans to Jaeger format. :type span_datas: list of :class: `~opencensus.trace.span_data.SpanData` :param span_datas: SpanData tuples to emit """ top_span = span_datas[0] trace_id = top_span.context.trace_id if top_span.context is not None \ else None jaeger_spans = [] for span in span_datas: start_timestamp_ms = timestamp_to_microseconds(span.start_time) end_timestamp_ms = timestamp_to_microseconds(span.end_time) duration_ms = end_timestamp_ms - start_timestamp_ms tags = _extract_tags(span.attributes) status = span.status if status is not None: tags.append( jaeger.Tag(key='status.code', vType=jaeger.TagType.LONG, vLong=status.code)) tags.append( jaeger.Tag(key='status.message', vType=jaeger.TagType.STRING, vStr=status.message)) refs = _extract_refs_from_span(span) logs = _extract_logs_from_span(span) context = span.context flags = None if context is not None: flags = int(context.trace_options.trace_options_byte) span_id = span.span_id parent_span_id = span.parent_span_id jaeger_span = jaeger.Span( traceIdHigh=_convert_hex_str_to_int(trace_id[0:16]), traceIdLow=_convert_hex_str_to_int(trace_id[16:32]), spanId=_convert_hex_str_to_int(span_id), operationName=span.name, startTime=int(round(start_timestamp_ms)), duration=int(round(duration_ms)), tags=tags, logs=logs, references=refs, flags=flags, parentSpanId=_convert_hex_str_to_int(parent_span_id or '0')) jaeger_spans.append(jaeger_span) return jaeger_spans
def timestamp_to_duration(start_time, end_time): start_time_us = timestamp_to_microseconds(start_time) end_time_us = timestamp_to_microseconds(end_time) duration_us = int(end_time_us - start_time_us) return microseconds_to_duration(duration_us)