What is the best way to handle No-Op #4414
-
👋🏻 I am looking for some help on how to control rollout of OTEL thus to minimize the risk of accidentally bursting our 💰 Currently our setup is pretty vanilla, we instantiate the OTEL library before anything else runs in order to get the tracing / metrics from the very first start of the stack. The injection of this requirement is handled by our IAC. Namely we have our k8s configuration making the decisions on whether to require the otel setup or not on boot. This gives us a nice way to incrementally rollout the OTEL library to individual deployments, however the ability to use this as a kill switch is limited due to deployment time. As such I am looking to have a kill switch within the otel code itself via a feature flag setting. The code where we call the SDK looks like this: export class Client {
private sdk: NodeSDK | undefined = undefined;
constructor() {
this.sdk = new NodeSDK({
traceExporter: new OTLPTraceExporter(),
metricReader: new PeriodicExportingMetricReader({
exporter: new OTLPMetricExporter(),
exportIntervalMillis: 60000,
}),
});
}
public start(): void {
return this.sdk?.start();
}
public async shutdown(): Promise<void> {
return this.sdk?.shutdown();
}
}
export const meter = (): Meter => opentelemetry.metrics.getMeter("myapp");
export const tracer = (): Tracer => {
return opentelemetry.trace.getTracer("myapp", process.env.HEAD_SHA);
}; We could of course feature flag the call sites for No-opI understand that there is a no-op spec for metrics which seems to address this requirement. It looks like we have support for this via Would setting the import { NoopMeterProvider } from "@opentelemetry/api/build/src/metrics/NoopMeterProvider";
import { NoopTracerProvider } from "@opentelemetry/api/build/src/trace/NoopTracerProvider";
export class Client {
private sdk: NodeSDK | undefined = undefined;
constructor() {
if (getFeatureSetting("mycondition") === true) {
opentelemetry.metrics.setGlobalMeterProvider(new NoopMeterProvider());
opentelemetry.trace.setGlobalTracerProvider(new NoopTracerProvider());
}
this.sdk = new NodeSDK({
traceExporter: new OTLPTraceExporter(),
metricReader: new PeriodicExportingMetricReader({
exporter: new OTLPMetricExporter(),
exportIntervalMillis: 60000,
}),
});
}
public start(): void {
return this.sdk?.start();
}
public async shutdown(): Promise<void> {
return this.sdk?.shutdown();
}
}
export const meter = (): Meter => opentelemetry.metrics.getMeter("myapp");
export const tracer = (): Tracer => {
return opentelemetry.trace.getTracer("myapp", process.env.HEAD_SHA);
}; And secondly is importing the providers from import { NoopMeterProvider } from "@opentelemetry/api/build/src/metrics/NoopMeterProvider";
import { NoopTracerProvider } from "@opentelemetry/api/build/src/trace/NoopTracerProvider"; Thanks in advance for your help ❤️ |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 7 replies
-
If you never call e.g. Note that the So whenever you operate on tracer.startActiveSpan("span", (span) => {
span.setAttribute("key", "value"); // ok, this is a noop
const activeSpan = trace.getActiveSpan(); // returns span with real context manager but undefined in case of NooP
activeSpan.setAttribute("key", "value"); // not ok
}); |
Beta Was this translation helpful? Give feedback.
-
Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './build/src/metrics/NoopMeterProvider' is not defined by "exports" |
Beta Was this translation helpful? Give feedback.
well, if you start the SDK it's expected that the SDK is started and it does it's job to create traces, metrics,...
Just don't start the SDK if you don't want this.
The API is built to work without SDK. This allows to write instrumentations using API only as dependency. If there is an SDK they create real spans/metrics if not it's a noop (with hopefully minimal overhead).