From 24fdf41758506fbba64ae069814ed0f7d1f0a917 Mon Sep 17 00:00:00 2001 From: Mathias Klippinge Date: Fri, 1 Sep 2023 09:22:45 +0200 Subject: [PATCH] Add API for adding custom metric attributes --- .../opentelemetry-instrumentation-http/README.md | 1 + .../opentelemetry-instrumentation-http/src/http.ts | 12 ++++++++---- .../opentelemetry-instrumentation-http/src/types.ts | 8 +++++++- .../test/functionals/http-metrics.test.ts | 13 ++++++++++++- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/experimental/packages/opentelemetry-instrumentation-http/README.md b/experimental/packages/opentelemetry-instrumentation-http/README.md index 312eb73bd76..951f0304497 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/README.md +++ b/experimental/packages/opentelemetry-instrumentation-http/README.md @@ -57,6 +57,7 @@ Http instrumentation has few options available to choose from. You can set the f | [`startOutgoingSpanHook`](https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/packages/opentelemetry-instrumentation-http/src/types.ts#L99) | `StartOutgoingSpanCustomAttributeFunction` | Function for adding custom attributes before a span is started in outgoingRequest | | `ignoreIncomingRequestHook` | `IgnoreIncomingRequestFunction` | Http instrumentation will not trace all incoming requests that matched with custom function | | `ignoreOutgoingRequestHook` | `IgnoreOutgoingRequestFunction` | Http instrumentation will not trace all outgoing requests that matched with custom function | +| `customMetricAttributes` | `CustomMetricAttributeFunction` | Function for adding custom metric attributes on all recorded metrics | | [`serverName`](https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/packages/opentelemetry-instrumentation-http/src/types.ts#L101) | `string` | The primary server name of the matched virtual host. | | [`requireParentforOutgoingSpans`](https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/packages/opentelemetry-instrumentation-http/src/types.ts#L103) | Boolean | Require that is a parent span to create new span for outgoing requests. | | [`requireParentforIncomingSpans`](https://github.com/open-telemetry/opentelemetry-js/blob/main/experimental/packages/opentelemetry-instrumentation-http/src/types.ts#L105) | Boolean | Require that is a parent span to create new span for incoming requests. | diff --git a/experimental/packages/opentelemetry-instrumentation-http/src/http.ts b/experimental/packages/opentelemetry-instrumentation-http/src/http.ts index 9422bbc9efd..aa43e4c7e48 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/src/http.ts +++ b/experimental/packages/opentelemetry-instrumentation-http/src/http.ts @@ -512,8 +512,10 @@ export class HttpInstrumentation extends InstrumentationBase { }; const startTime = hrTime(); - const metricAttributes = - utils.getIncomingRequestMetricAttributes(spanAttributes); + const metricAttributes: MetricAttributes = Object.assign( + utils.getIncomingRequestMetricAttributes(spanAttributes), + instrumentation._getConfig().customMetricAttributes?.() + ); const ctx = propagation.extract(ROOT_CONTEXT, headers); const span = instrumentation._startHttpSpan(method, spanOptions, ctx); @@ -658,8 +660,10 @@ export class HttpInstrumentation extends InstrumentationBase { }); const startTime = hrTime(); - const metricAttributes: MetricAttributes = - utils.getOutgoingRequestMetricAttributes(attributes); + const metricAttributes: MetricAttributes = Object.assign( + utils.getOutgoingRequestMetricAttributes(attributes), + instrumentation._getConfig().customMetricAttributes?.() + ); const spanOptions: SpanOptions = { kind: SpanKind.CLIENT, diff --git a/experimental/packages/opentelemetry-instrumentation-http/src/types.ts b/experimental/packages/opentelemetry-instrumentation-http/src/types.ts index 5cc09341d43..5734e737f5f 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/src/types.ts +++ b/experimental/packages/opentelemetry-instrumentation-http/src/types.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Span, SpanAttributes } from '@opentelemetry/api'; +import { MetricAttributes, Span, SpanAttributes } from '@opentelemetry/api'; import type * as http from 'http'; import type * as https from 'https'; import { @@ -80,6 +80,10 @@ export interface StartOutgoingSpanCustomAttributeFunction { (request: RequestOptions): SpanAttributes; } +export interface CustomMetricAttributeFunction { + (): MetricAttributes; +} + /** * Options available for the HTTP instrumentation (see [documentation](https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-instrumentation-http#http-instrumentation-options)) */ @@ -108,6 +112,8 @@ export interface HttpInstrumentationConfig extends InstrumentationConfig { startIncomingSpanHook?: StartIncomingSpanCustomAttributeFunction; /** Function for adding custom attributes before a span is started in outgoingRequest */ startOutgoingSpanHook?: StartOutgoingSpanCustomAttributeFunction; + /** Function for adding custom metric attributes on all recorded metrics */ + customMetricAttributes?: CustomMetricAttributeFunction; /** The primary server name of the matched virtual host. */ serverName?: string; /** Require parent to create span for outgoing requests */ diff --git a/experimental/packages/opentelemetry-instrumentation-http/test/functionals/http-metrics.test.ts b/experimental/packages/opentelemetry-instrumentation-http/test/functionals/http-metrics.test.ts index d7f55ed8463..3b385e679e5 100644 --- a/experimental/packages/opentelemetry-instrumentation-http/test/functionals/http-metrics.test.ts +++ b/experimental/packages/opentelemetry-instrumentation-http/test/functionals/http-metrics.test.ts @@ -26,7 +26,14 @@ import { HttpInstrumentation } from '../../src/http'; import { httpRequest } from '../utils/httpRequest'; import { TestMetricReader } from '../utils/TestMetricReader'; -const instrumentation = new HttpInstrumentation(); +const instrumentation = new HttpInstrumentation({ + customMetricAttributes: () => { + return { + foo: 'bar', + }; + }, +}); + instrumentation.enable(); instrumentation.disable(); @@ -115,6 +122,8 @@ describe('metrics', () => { metrics[0].dataPoints[0].attributes[SemanticAttributes.NET_HOST_PORT], 22346 ); + // Custom attributes + assert.strictEqual(metrics[0].dataPoints[0].attributes['foo'], 'bar'); assert.strictEqual(metrics[1].dataPointType, DataPointType.HISTOGRAM); assert.strictEqual( @@ -148,5 +157,7 @@ describe('metrics', () => { metrics[1].dataPoints[0].attributes[SemanticAttributes.HTTP_FLAVOR], '1.1' ); + // Custom attributes + assert.strictEqual(metrics[1].dataPoints[0].attributes['foo'], 'bar'); }); });