def metric_to_envelope( self, metric_record: MetricRecord ) -> protocol.Envelope: if not metric_record: return None envelope = protocol.Envelope( ikey=self.options.instrumentation_key, tags=dict(utils.azure_monitor_context), time=ns_to_iso_str( metric_record.metric.get_handle( metric_record.label_set ).last_update_timestamp ), ) envelope.name = "Microsoft.ApplicationInsights.Metric" data_point = protocol.DataPoint( ns=metric_record.metric.name, name=metric_record.metric.description, value=metric_record.aggregator.checkpoint, kind=protocol.DataPointType.MEASUREMENT, ) properties = {} for label_tuple in metric_record.label_set.labels: properties[label_tuple[0]] = label_tuple[1] data = protocol.MetricData(metrics=[data_point], properties=properties) envelope.data = protocol.Data(base_data=data, base_type="MetricData") return envelope
def _metric_to_envelope(self, metric_record: MetricRecord) -> protocol.Envelope: if not metric_record: return None envelope = protocol.Envelope( ikey=self.options.instrumentation_key, tags=dict(utils.azure_monitor_context), time=ns_to_iso_str(metric_record.aggregator.last_update_timestamp), ) envelope.name = "Microsoft.ApplicationInsights.Metric" value = 0 _min = None _max = None count = None metric = metric_record.instrument if isinstance(metric, ValueObserver): # mmscl value = metric_record.aggregator.checkpoint.last elif isinstance(metric, ValueRecorder): # mmsc value = metric_record.aggregator.checkpoint.sum _min = metric_record.aggregator.checkpoint.min _max = metric_record.aggregator.checkpoint.max count = metric_record.aggregator.checkpoint.count else: # sum or lv value = metric_record.aggregator.checkpoint if value is None: logger.warning("Value is none. Default to 0.") value = 0 data_point = protocol.DataPoint( ns=metric.description, name=metric.name, value=value, min=_min, max=_max, count=count, kind=protocol.DataPointType.MEASUREMENT.value, ) properties = {} for label_tuple in metric_record.labels: properties[label_tuple[0]] = label_tuple[1] data = protocol.MetricData(metrics=[data_point], properties=properties) envelope.data = protocol.Data(base_data=data, base_type="MetricData") return envelope
def _metric_to_envelope(self, metric_record: MetricRecord) -> protocol.Envelope: if not metric_record: return None # TODO: Opentelemetry has timestamp for Observer, awaiting release # TODO: Timestamp info is also moved into aggregators _time = time_ns() if isinstance(metric_record.metric, Metric): _time = metric_record.metric.bind(dict( metric_record.labels)).last_update_timestamp envelope = protocol.Envelope( ikey=self.options.instrumentation_key, tags=dict(utils.azure_monitor_context), time=ns_to_iso_str(_time), ) envelope.name = "Microsoft.ApplicationInsights.Metric" value = 0 metric = metric_record.metric if isinstance(metric, Counter): value = metric_record.aggregator.checkpoint elif isinstance(metric, Observer): value = metric_record.aggregator.checkpoint.last if not value: value = 0 else: # TODO: What do measure aggregations look like in AI? logger.warning("Measure metric recorded.") data_point = protocol.DataPoint( ns=metric_record.metric.description, name=metric_record.metric.name, value=value, kind=protocol.DataPointType.MEASUREMENT.value, ) properties = {} for label_tuple in metric_record.labels: properties[label_tuple[0]] = label_tuple[1] data = protocol.MetricData(metrics=[data_point], properties=properties) envelope.data = protocol.Data(base_data=data, base_type="MetricData") return envelope
def _span_to_envelope(self, span: Span) -> protocol.Envelope: if not span: return None envelope = protocol.Envelope( ikey=self.options.instrumentation_key, tags=dict(utils.azure_monitor_context), time=ns_to_iso_str(span.start_time), ) envelope.tags["ai.operation.id"] = "{:032x}".format( span.context.trace_id) parent = span.parent if isinstance(parent, Span): parent = parent.context if parent: envelope.tags["ai.operation.parentId"] = "{:016x}".format( parent.span_id) if span.kind in (SpanKind.CONSUMER, SpanKind.SERVER): envelope.name = "Microsoft.ApplicationInsights.Request" data = protocol.Request( id="{:016x}".format(span.context.span_id), duration=utils.ns_to_duration(span.end_time - span.start_time), response_code=str(span.status.canonical_code.value), success=span.status.canonical_code == StatusCanonicalCode. OK, # Modify based off attributes or Status properties={}, ) envelope.data = protocol.Data(base_data=data, base_type="RequestData") if "http.method" in span.attributes: data.name = span.attributes["http.method"] if "http.route" in span.attributes: data.name = data.name + " " + span.attributes["http.route"] envelope.tags["ai.operation.name"] = data.name data.properties["request.name"] = data.name elif "http.path" in span.attributes: data.properties["request.name"] = ( data.name + " " + span.attributes["http.path"]) if "http.url" in span.attributes: data.url = span.attributes["http.url"] data.properties["request.url"] = span.attributes["http.url"] if "http.status_code" in span.attributes: status_code = span.attributes["http.status_code"] data.response_code = str(status_code) data.success = 200 <= status_code < 400 else: envelope.name = "Microsoft.ApplicationInsights.RemoteDependency" data = protocol.RemoteDependency( name=span.name, id="{:016x}".format(span.context.span_id), result_code=str(span.status.canonical_code.value), duration=utils.ns_to_duration(span.end_time - span.start_time), success=span.status.canonical_code == StatusCanonicalCode. OK, # Modify based off attributes or Status properties={}, ) envelope.data = protocol.Data(base_data=data, base_type="RemoteDependencyData") if span.kind in (SpanKind.CLIENT, SpanKind.PRODUCER): if ("component" in span.attributes and span.attributes["component"] == "http"): data.type = "HTTP" if "http.url" in span.attributes: url = span.attributes["http.url"] # data is the url data.data = url parse_url = urlparse(url) # TODO: error handling, probably put scheme as well # target matches authority (host:port) data.target = parse_url.netloc if "http.method" in span.attributes: # name is METHOD/path data.name = (span.attributes["http.method"] + "/" + parse_url.path) if "http.status_code" in span.attributes: status_code = span.attributes["http.status_code"] data.result_code = str(status_code) data.success = 200 <= status_code < 400 else: # SpanKind.INTERNAL data.type = "InProc" data.success = True for key in span.attributes: # This removes redundant data from ApplicationInsights if key.startswith("http."): continue data.properties[key] = span.attributes[key] if span.links: links = [] for link in span.links: operation_id = "{:032x}".format(link.context.trace_id) span_id = "{:016x}".format(link.context.span_id) links.append({"operation_Id": operation_id, "id": span_id}) data.properties["_MS.links"] = json.dumps(links) # TODO: tracestate, tags return envelope
def test_data(self): data = protocol.Data() self.assertIsNone(data.baseData) self.assertIsNone(data.baseType)
def span_to_envelope(self, span): # noqa pylint: disable=too-many-branches envelope = protocol.Envelope( iKey=self.options.instrumentation_key, tags=dict(util.azure_monitor_context), time=ns_to_iso_str(span.start_time), ) envelope.tags["ai.operation.id"] = "{:032x}".format( span.context.trace_id) parent = span.parent if isinstance(parent, Span): parent = parent.context if parent: envelope.tags[ "ai.operation.parentId"] = "|{:032x}.{:016x}.".format( parent.trace_id, parent.span_id) if span.kind in (SpanKind.CONSUMER, SpanKind.SERVER): envelope.name = "Microsoft.ApplicationInsights.Request" data = protocol.Request( id="|{:032x}.{:016x}.".format(span.context.trace_id, span.context.span_id), duration=self.ns_to_duration(span.end_time - span.start_time), responseCode="0", success=False, properties={}, ) envelope.data = protocol.Data(baseData=data, baseType="RequestData") if "http.method" in span.attributes: data.name = span.attributes["http.method"] if "http.route" in span.attributes: data.name = data.name + " " + span.attributes["http.route"] envelope.tags["ai.operation.name"] = data.name if "http.url" in span.attributes: data.url = span.attributes["http.url"] if "http.status_code" in span.attributes: status_code = span.attributes["http.status_code"] data.responseCode = str(status_code) data.success = 200 <= status_code < 400 else: envelope.name = "Microsoft.ApplicationInsights.RemoteDependency" data = protocol.RemoteDependency( name=span.name, id="|{:032x}.{:016x}.".format(span.context.trace_id, span.context.span_id), resultCode="0", # TODO duration=self.ns_to_duration(span.end_time - span.start_time), success=True, # TODO properties={}, ) envelope.data = protocol.Data(baseData=data, baseType="RemoteDependencyData") if span.kind in (SpanKind.CLIENT, SpanKind.PRODUCER): data.type = "HTTP" # TODO if "http.url" in span.attributes: url = span.attributes["http.url"] # TODO: error handling, probably put scheme as well data.name = urlparse(url).netloc if "http.status_code" in span.attributes: data.resultCode = str(span.attributes["http.status_code"]) else: # SpanKind.INTERNAL data.type = "InProc" for key in span.attributes: data.properties[key] = span.attributes[key] if span.links: links = [] for link in span.links: links.append({ "operation_Id": "{:032x}".format(link.context.trace_id), "id": "|{:032x}.{:016x}.".format(link.context.trace_id, link.context.span_id), }) data.properties["_MS.links"] = json.dumps(links) print(data.properties["_MS.links"]) # TODO: tracestate, tags return envelope