UNPKG

@aws/aws-distro-opentelemetry-node-autoinstrumentation

Version:

This package provides Amazon Web Services distribution of the OpenTelemetry Node Instrumentation, which allows for auto-instrumentation of NodeJS applications.

104 lines 5.52 kB
"use strict"; // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 Object.defineProperty(exports, "__esModule", { value: true }); exports.AwsMetricAttributesSpanExporter = void 0; const aws_attribute_keys_1 = require("./aws-attribute-keys"); const aws_span_processing_util_1 = require("./aws-span-processing-util"); const metric_attribute_generator_1 = require("./metric-attribute-generator"); /** * This exporter will update a span with metric attributes before exporting. It depends on a * {@link SpanExporter} being provided on instantiation, which the AwsMetricAttributesSpanExporter will * delegate export to. Also, a {@link MetricAttributeGenerator} must be provided, which will provide a * means to determine attributes which should be applied to the span. Finally, a {@link Resource} must * be provided, which is used to generate metric attributes. * * <p>This exporter should be coupled with the {@link AwsSpanMetricsProcessor} using the same * {@link MetricAttributeGenerator}. This will result in metrics and spans being produced with * common attributes. */ class AwsMetricAttributesSpanExporter { constructor(delegate, generator, resource) { this.delegate = delegate; this.generator = generator; this.resource = resource; } /** Use {@link AwsMetricAttributesSpanExporterBuilder} to construct this exporter. */ static create(delegate, generator, resource) { return new AwsMetricAttributesSpanExporter(delegate, generator, resource); } export(spans, resultCallback) { const modifiedSpans = this.addMetricAttributes(spans); this.delegate.export(modifiedSpans, resultCallback); } shutdown() { return this.delegate.shutdown(); } forceFlush() { if (this.delegate.forceFlush !== undefined) { return this.delegate.forceFlush(); } return Promise.resolve(); } addMetricAttributes(spans) { const modifiedSpans = []; spans.forEach((span) => { // If the map has no items, no modifications are required. If there is one item, it means the // span either produces Service or Dependency metric attributes, and in either case we want to // modify the span with them. If there are two items, the span produces both Service and // Dependency metric attributes indicating the span is a local dependency root. The Service // Attributes must be a subset of the Dependency, with the exception of AWS_SPAN_KIND. The // knowledge that the span is a local root is more important that knowing that it is a // Dependency metric, so we take all the Dependency metrics but replace AWS_SPAN_KIND with // LOCAL_ROOT. const attributeMap = this.generator.generateMetricAttributeMapFromSpan(span, this.resource); let attributes = {}; const generatesServiceMetrics = aws_span_processing_util_1.AwsSpanProcessingUtil.shouldGenerateServiceMetricAttributes(span); const generatesDependencyMetrics = aws_span_processing_util_1.AwsSpanProcessingUtil.shouldGenerateDependencyMetricAttributes(span); if (generatesServiceMetrics && generatesDependencyMetrics) { attributes = this.copyAttributesWithLocalRoot(attributeMap[metric_attribute_generator_1.DEPENDENCY_METRIC]); } else if (generatesServiceMetrics) { attributes = attributeMap[metric_attribute_generator_1.SERVICE_METRIC]; } else if (generatesDependencyMetrics) { attributes = attributeMap[metric_attribute_generator_1.DEPENDENCY_METRIC]; } if (attributes !== undefined && Object.keys(attributes).length > 0) { span = AwsMetricAttributesSpanExporter.wrapSpanWithAttributes(span, attributes); } modifiedSpans.push(span); }); return modifiedSpans; } copyAttributesWithLocalRoot(attributes) { const updatedAttributes = Object.assign({}, attributes); delete updatedAttributes[aws_attribute_keys_1.AWS_ATTRIBUTE_KEYS.AWS_SPAN_KIND]; updatedAttributes[aws_attribute_keys_1.AWS_ATTRIBUTE_KEYS.AWS_SPAN_KIND] = aws_span_processing_util_1.AwsSpanProcessingUtil.LOCAL_ROOT; return updatedAttributes; } /** * {@link export} works with a {@link ReadableSpan}, which does not permit modification. However, we * need to add derived metric attributes to the span. However, we are still able to modify the * attributes in the span (the attributes itself is readonly, so it cannot be outright replaced). * This may be risky. * * <p>See https://github.com/open-telemetry/opentelemetry-specification/issues/1089 for more * context on this approach. */ static wrapSpanWithAttributes(span, attributes) { const originalAttributes = span.attributes; const updateAttributes = {}; for (const key in originalAttributes) { updateAttributes[key] = originalAttributes[key]; } for (const key in attributes) { updateAttributes[key] = attributes[key]; } const mutableSpan = span; mutableSpan.attributes = updateAttributes; return span; } } exports.AwsMetricAttributesSpanExporter = AwsMetricAttributesSpanExporter; //# sourceMappingURL=aws-metric-attributes-span-exporter.js.map