What is @opentelemetry/instrumentation?
The @opentelemetry/instrumentation package is part of the OpenTelemetry project, which aims to provide a unified and standardized observability framework for monitoring applications' performance and behavior. This particular package offers a way to automatically instrument code to collect telemetry data such as traces and metrics, making it easier to monitor and debug applications.
What are @opentelemetry/instrumentation's main functionalities?
Automatic Instrumentation
Automatically instruments Node.js applications to collect telemetry data, such as tracing information for HTTP requests. This example shows how to set up the NodeTracerProvider and register the HttpInstrumentation to start collecting data.
const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
const { registerInstrumentations } = require('@opentelemetry/instrumentation');
const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http');
const provider = new NodeTracerProvider();
registerInstrumentations({
instrumentations: [
new HttpInstrumentation()
],
tracerProvider: provider,
});
Custom Instrumentation
Enables the creation of custom instrumentation for any library or application code not covered by the existing instrumentations. This example demonstrates how to extend the InstrumentationBase class to create a custom instrumentation.
const { InstrumentationBase } = require('@opentelemetry/instrumentation');
class MyCustomInstrumentation extends InstrumentationBase {
constructor() {
super('MyCustomInstrumentation');
}
init() {
// Custom initialization logic
}
}
Other packages similar to @opentelemetry/instrumentation
jaeger-client
Jaeger client is a package for distributed tracing in microservices architecture. It can be used to monitor and troubleshoot transactions in complex distributed systems. Compared to @opentelemetry/instrumentation, jaeger-client is more specific to the Jaeger backend, whereas OpenTelemetry provides a more vendor-neutral approach, allowing data to be exported to various backends including Jaeger.
OpenTelemetry Instrumentation for web and node
Installation
npm install --save @opentelemetry/instrumentation
Usage in Node
import {
InstrumentationBase,
InstrumentationConfig,
InstrumentationNodeModuleDefinition,
InstrumentationNodeModuleFile,
} from '@opentelemetry/instrumentation';
import type * as module_name_to_be_patched from 'module_name_to_be_patched';
export class MyPlugin extends InstrumentationBase {
constructor(config: InstrumentationConfig = {}) {
super('MyPlugin', VERSION, config);
}
protected init() {
const module = new InstrumentationNodeModuleDefinition<typeof module_name_to_be_patched>(
'module_name_to_be_patched',
['1.*'],
this._onPatchMain,
this._onUnPatchMain,
);
module.files.push(this._addPatchingMethod());
return module;
}
private _onPatchMain(moduleExports: typeof module_name_to_be_patched) {
this._wrap(
moduleExports,
'mainMethodName',
this._patchMainMethodName()
);
return moduleExports;
}
private _onUnPatchMain(moduleExports: typeof module_name_to_be_patched) {
this._unwrap(moduleExports, 'mainMethodName');
}
private _addPatchingMethod(): InstrumentationNodeModuleFile<typeof module_name_to_be_patched> {
const file = new InstrumentationNodeModuleFile<typeof module_name_to_be_patched>(
'module_name_to_be_patched/src/some_file.js',
this._onPatchMethodName,
this._onUnPatchMethodName,
);
return file;
}
private _onPatchMethodName(moduleExports: typeof module_name_to_be_patched) {
this._wrap(
moduleExports,
'methodName',
this._patchMethodName()
);
return moduleExports;
}
private _onUnPatchMethodName(moduleExports: typeof module_name_to_be_patched) {
this._unwrap(moduleExports, 'methodName');
}
private _patchMethodName(): (original) => any {
const plugin = this;
return function methodName(original) {
return function patchMethodName(this: any): PromiseOrValue<module_name_to_be_patched.methodName> {
console.log('methodName', arguments);
return original.apply(this, arguments);
};
};
}
private _patchMainMethodName(): (original) => any {
const plugin = this;
return function mainMethodName(original) {
return function patchMainMethodName(this: any): PromiseOrValue<module_name_to_be_patched.mainMethodName> {
console.log('mainMethodName', arguments);
return original.apply(this, arguments);
};
};
}
}
const myPLugin = new MyPlugin();
myPLugin.setTracerProvider(provider);
myPLugin.setMeterProvider(meterProvider);
myPLugin.enable();
Usage in Web
import {
InstrumentationBase,
InstrumentationConfig,
} from '@opentelemetry/instrumentation';
import { Instrumentation } from '@opentelemetry/instrumentation';
export class MyPlugin extends InstrumentationBase {
constructor(config: InstrumentationConfig = {}) {
super('MyPlugin', VERSION, config);
}
private _patchOpen() {
return (original: OpenFunction): OpenFunction => {
const plugin = this;
return function patchOpen(this: XMLHttpRequest, ...args): void {
console.log('open', arguments);
return original.apply(this, args);
};
};
}
public enable() {
this._wrap(XMLHttpRequest.prototype, 'open', this._patchOpen());
}
public disable() {
this._unwrap(XMLHttpRequest.prototype, 'open');
}
}
const myPLugin = new MyPlugin();
myPLugin.setTracerProvider(provider);
myPLugin.setMeterProvider(meterProvider);
myPLugin.enable();
License
Apache 2.0 - See LICENSE for more information.