Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
feat(add-option-to-disable-instrumentation-http-metrics
  • Loading branch information
AkselAllas committed Oct 1, 2024
commit d918ac69474e0bb3da25331d2078ebc58497c1dc
1 change: 1 addition & 0 deletions experimental/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ All notable changes to experimental packages in this project will be documented
* Applies to both client and server spans
* Generate spans compliant with Semantic Conventions 1.27+ when `OTEL_SEMCONV_STABILITY_OPT_IN` contains `http` or `http/dup`
* Generate spans backwards compatible with previous attributes when `OTEL_SEMCONV_STABILITY_OPT_IN` contains `http/dup` or DOES NOT contain `http`
* feat(add-option-to-disable-instrumentation-http-metrics): Add option to disable instrumentation-http metrics such as incoming or outgoing HTTP request duration [#4409](https://github.com/open-telemetry/opentelemetry-js/pull/5029) @AkselAllas

### :bug: (Bug Fix)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ Http instrumentation has few options available to choose from. You can set the f
| `ignoreOutgoingRequestHook` | `IgnoreOutgoingRequestFunction` | Http instrumentation will not trace all outgoing requests that matched with custom function |
| `disableOutgoingRequestInstrumentation` | `boolean` | Set to true to avoid instrumenting outgoing requests at all. This can be helpful when another instrumentation handles outgoing requests. |
| `disableIncomingRequestInstrumentation` | `boolean` | Set to true to avoid instrumenting incoming requests at all. This can be helpful when another instrumentation handles incoming requests. |
| `disableMetrics` | `boolean` | Set to true in order to disable instrumentation-http from emitting any metrics such as duration of inbound/outbound HTTP requests. |
| [`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. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export class HttpInstrumentation extends InstrumentationBase<HttpInstrumentation
/** keep track on spans not ended */
private readonly _spanNotEnded: WeakSet<Span> = new WeakSet<Span>();
private _headerCapture;
private _disableMetrics: boolean;
private _httpServerDurationHistogram!: Histogram;
private _httpClientDurationHistogram!: Histogram;

Expand All @@ -96,6 +97,7 @@ export class HttpInstrumentation extends InstrumentationBase<HttpInstrumentation
constructor(config: HttpInstrumentationConfig = {}) {
super('@opentelemetry/instrumentation-http', VERSION, config);
this._headerCapture = this._createHeaderCapture();
this._disableMetrics = this.getConfig().disableMetrics || false;

for (const entry in getEnv().OTEL_SEMCONV_STABILITY_OPT_IN) {
if (entry.toLowerCase() === 'http/dup') {
Expand Down Expand Up @@ -851,9 +853,9 @@ export class HttpInstrumentation extends InstrumentationBase<HttpInstrumentation

// Record metrics
const duration = hrTimeToMilliseconds(hrTimeDuration(startTime, hrTime()));
if (spanKind === SpanKind.SERVER) {
if (spanKind === SpanKind.SERVER && !this._disableMetrics) {
this._httpServerDurationHistogram.record(duration, metricAttributes);
} else if (spanKind === SpanKind.CLIENT) {
} else if (spanKind === SpanKind.CLIENT && !this._disableMetrics) {
this._httpClientDurationHistogram.record(duration, metricAttributes);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ export interface HttpInstrumentationConfig extends InstrumentationConfig {
disableIncomingRequestInstrumentation?: boolean;
/** If set to true, outgoing requests will not be instrumented at all. */
disableOutgoingRequestInstrumentation?: boolean;
/** If set to true, no metrics will be emitted */
disableMetrics?: boolean;
/** Function for adding custom attributes after response is handled */
applyCustomAttributesOnSpan?: HttpCustomAttributeFunction;
/** Function for adding custom attributes before request is handled */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
AggregationTemporality,
InMemoryMetricExporter,
MeterProvider,
} from '@opentelemetry/sdk-metrics';
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
import * as assert from 'assert';
import { HttpInstrumentation } from '../../src/http';
import { httpRequest } from '../utils/httpRequest';
import { TestMetricReader } from '../utils/TestMetricReader';

const instrumentation = new HttpInstrumentation({ disableMetrics: true });
instrumentation.enable();
instrumentation.disable();

import * as http from 'http';

let server: http.Server;
const serverPort = 22346;
const protocol = 'http';
const hostname = 'localhost';
const pathname = '/test';
const tracerProvider = new NodeTracerProvider();
const metricsMemoryExporter = new InMemoryMetricExporter(
AggregationTemporality.DELTA
);
const metricReader = new TestMetricReader(metricsMemoryExporter);
const meterProvider = new MeterProvider({ readers: [metricReader] });

instrumentation.setTracerProvider(tracerProvider);
instrumentation.setMeterProvider(meterProvider);

describe('metrics can be disabled', () => {
beforeEach(() => {
metricsMemoryExporter.reset();
});

before(() => {
instrumentation.enable();
server = http.createServer((request, response) => {
response.end('Test Server Response');
});
server.listen(serverPort);
});

after(() => {
server.close();
instrumentation.disable();
});

it('should not create server/client duration metrics', async () => {
const requestCount = 3;
for (let i = 0; i < requestCount; i++) {
await httpRequest.get(
`${protocol}://${hostname}:${serverPort}${pathname}`
);
}
await metricReader.collectAndExport();
const resourceMetrics = metricsMemoryExporter.getMetrics();
const scopeMetrics = resourceMetrics[0].scopeMetrics;
assert.strictEqual(scopeMetrics.length, 0, 'scopeMetrics count');
});
});