diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/clientUtils.ts b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/clientUtils.ts index 1ffaab39bb9..20f089efc36 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/clientUtils.ts +++ b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/clientUtils.ts @@ -23,7 +23,7 @@ import { propagation, context, } from '@opentelemetry/api'; -import type * as grpcJs from '@grpc/grpc-js'; +import { Client, Metadata, ServiceError } from '@grpc/grpc-js'; import { _grpcStatusCodeToSpanStatus, _grpcStatusCodeToOpenTelemetryStatusCode, @@ -42,7 +42,7 @@ import { GRPC_STATUS_CODE_OK } from '../status-code'; */ export function getMethodsToWrap( this: GrpcJsInstrumentation, - client: typeof grpcJs.Client, + client: typeof Client, methods: { [key: string]: { originalName?: string } } ): string[] { const methodList: string[] = []; @@ -74,8 +74,8 @@ export function makeGrpcClientRemoteCall( metadataCapture: metadataCaptureType, original: GrpcClientFunc, args: unknown[], - metadata: grpcJs.Metadata, - self: grpcJs.Client + metadata: Metadata, + self: Client ): (span: Span) => EventEmitter { /** * Patches a callback so that the current span for this trace is also ended @@ -86,7 +86,7 @@ export function makeGrpcClientRemoteCall( callback: SendUnaryDataCallback ) { const wrappedFn: SendUnaryDataCallback = ( - err: grpcJs.ServiceError | null, + err: ServiceError | null, res?: ResponseType ) => { if (err) { @@ -145,7 +145,7 @@ export function makeGrpcClientRemoteCall( } }; context.bind(context.active(), call); - call.on('error', (err: grpcJs.ServiceError) => { + call.on('error', (err: ServiceError) => { if (call[CALL_SPAN_ENDED]) { return; } @@ -185,26 +185,25 @@ export function makeGrpcClientRemoteCall( */ export function getMetadata( this: GrpcJsInstrumentation, - grpcClient: typeof grpcJs, original: GrpcClientFunc, - args: Array -): grpcJs.Metadata { - let metadata: grpcJs.Metadata; + args: Array +): Metadata { + let metadata: Metadata; // This finds an instance of Metadata among the arguments. // A possible issue that could occur is if the 'options' parameter from // the user contains an '_internal_repr' as well as a 'getMap' function, // but this is an extremely rare case. - let metadataIndex = args.findIndex((arg: unknown | grpcJs.Metadata) => { + let metadataIndex = args.findIndex((arg: unknown | Metadata) => { return ( arg && typeof arg === 'object' && - (arg as grpcJs.Metadata)['internalRepr'] && // changed from _internal_repr in grpc --> @grpc/grpc-js https://github.com/grpc/grpc-node/blob/95289edcaf36979cccf12797cc27335da8d01f03/packages/grpc-js/src/metadata.ts#L88 - typeof (arg as grpcJs.Metadata).getMap === 'function' + (arg as Metadata)['internalRepr'] && // changed from _internal_repr in grpc --> @grpc/grpc-js https://github.com/grpc/grpc-node/blob/95289edcaf36979cccf12797cc27335da8d01f03/packages/grpc-js/src/metadata.ts#L88 + typeof (arg as Metadata).getMap === 'function' ); }); if (metadataIndex === -1) { - metadata = new grpcClient.Metadata(); + metadata = new Metadata(); if (!original.requestStream) { // unary or server stream metadataIndex = 1; @@ -214,7 +213,7 @@ export function getMetadata( } args.splice(metadataIndex, 0, metadata); } else { - metadata = args[metadataIndex] as grpcJs.Metadata; + metadata = args[metadataIndex] as Metadata; } return metadata; } @@ -224,7 +223,7 @@ export function getMetadata( * grpc receiver * @param metadata */ -export function setSpanContext(metadata: grpcJs.Metadata): void { +export function setSpanContext(metadata: Metadata): void { propagation.inject(context.active(), metadata, { set: (meta, k, v) => meta.set(k, v), }); diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/index.ts b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/index.ts index eaae47c8efa..4809b2682fb 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/index.ts +++ b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/index.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -import type * as grpcJs from '@grpc/grpc-js'; import { InstrumentationNodeModuleDefinition, isWrapped, @@ -53,6 +52,17 @@ import { EventEmitter } from 'events'; import { _extractMethodAndService, metadataCapture, URI_REGEX } from '../utils'; import { AttributeValues } from '../enums/AttributeValues'; import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; +import { + Server, + serialize as Serialize, + deserialize as Deserialize, + Metadata, + Client, + ServiceDefinition, + loadPackageDefinition, + GrpcObject, +} from '@grpc/grpc-js'; +import * as grpcJs from '@grpc/grpc-js'; export class GrpcJsInstrumentation extends InstrumentationBase { private _metadataCapture: metadataCaptureType; @@ -89,7 +99,7 @@ export class GrpcJsInstrumentation extends InstrumentationBase { this._wrap( moduleExports, 'makeGenericClientConstructor', - this._patchClient(moduleExports) + this._patchClient() ); if (isWrapped(moduleExports.makeClientConstructor)) { this._unwrap(moduleExports, 'makeClientConstructor'); @@ -97,7 +107,7 @@ export class GrpcJsInstrumentation extends InstrumentationBase { this._wrap( moduleExports, 'makeClientConstructor', - this._patchClient(moduleExports) + this._patchClient() ); if (isWrapped(moduleExports.loadPackageDefinition)) { this._unwrap(moduleExports, 'loadPackageDefinition'); @@ -105,7 +115,7 @@ export class GrpcJsInstrumentation extends InstrumentationBase { this._wrap( moduleExports, 'loadPackageDefinition', - this._patchLoadPackageDefinition(moduleExports) + this._patchLoadPackageDefinition() ); return moduleExports; }, @@ -143,11 +153,11 @@ export class GrpcJsInstrumentation extends InstrumentationBase { const config = this.getConfig(); instrumentation._diag.debug('patched gRPC server'); return function register( - this: grpcJs.Server, + this: Server, name: string, handler: HandleCall, - serialize: grpcJs.serialize, - deserialize: grpcJs.deserialize, + serialize: Serialize, + deserialize: Deserialize, type: string ): boolean { const originalRegisterResult = originalRegister.call( @@ -171,13 +181,7 @@ export class GrpcJsInstrumentation extends InstrumentationBase { ) { const self = this; - if ( - shouldNotTraceServerCall( - call.metadata, - name, - config.ignoreGrpcMethods - ) - ) { + if (shouldNotTraceServerCall(name, config.ignoreGrpcMethods)) { return handleUntracedServerFunction( type, originalFunc, @@ -220,14 +224,13 @@ export class GrpcJsInstrumentation extends InstrumentationBase { instrumentation._wrap( call, 'sendMetadata', - originalSendMetadata => - (responseMetadata: grpcJs.Metadata) => { - instrumentation._metadataCapture.server.captureResponseMetadata( - span, - responseMetadata - ); - originalSendMetadata.call(call, responseMetadata); - } + originalSendMetadata => (responseMetadata: Metadata) => { + instrumentation._metadataCapture.server.captureResponseMetadata( + span, + responseMetadata + ); + originalSendMetadata.call(call, responseMetadata); + } ); context.with(trace.setSpan(context.active(), span), () => { @@ -246,7 +249,7 @@ export class GrpcJsInstrumentation extends InstrumentationBase { } ); return originalRegisterResult; - } as typeof grpcJs.Server.prototype.register; + } as typeof Server.prototype.register; }; } @@ -254,17 +257,15 @@ export class GrpcJsInstrumentation extends InstrumentationBase { * Entry point for applying client patches to `grpc.makeClientConstructor(...)` equivalents * @param this GrpcJsPlugin */ - private _patchClient( - grpcClient: typeof grpcJs - ): ( + private _patchClient(): ( original: MakeClientConstructorFunction ) => MakeClientConstructorFunction { const instrumentation = this; return (original: MakeClientConstructorFunction) => { instrumentation._diag.debug('patching client'); return function makeClientConstructor( - this: typeof grpcJs.Client, - methods: grpcJs.ServiceDefinition, + this: typeof Client, + methods: ServiceDefinition, serviceName: string, options?: object ) { @@ -272,7 +273,7 @@ export class GrpcJsInstrumentation extends InstrumentationBase { instrumentation._massWrap( client.prototype, getMethodsToWrap.call(instrumentation, client, methods), - instrumentation._getPatchedClientMethods(grpcClient) + instrumentation._getPatchedClientMethods() ); return client; }; @@ -283,42 +284,37 @@ export class GrpcJsInstrumentation extends InstrumentationBase { * Entry point for client patching for grpc.loadPackageDefinition(...) * @param this - GrpcJsPlugin */ - private _patchLoadPackageDefinition(grpcClient: typeof grpcJs) { + private _patchLoadPackageDefinition() { const instrumentation = this; instrumentation._diag.debug('patching loadPackageDefinition'); - return (original: typeof grpcJs.loadPackageDefinition) => { + return (original: typeof loadPackageDefinition) => { return function patchedLoadPackageDefinition( this: null, packageDef: PackageDefinition ) { - const result: grpcJs.GrpcObject = original.call( + const result: GrpcObject = original.call( this, packageDef - ) as grpcJs.GrpcObject; - instrumentation._patchLoadedPackage(grpcClient, result); + ) as GrpcObject; + instrumentation._patchLoadedPackage(result); return result; - } as typeof grpcJs.loadPackageDefinition; + } as typeof loadPackageDefinition; }; } /** * Parse initial client call properties and start a span to trace its execution */ - private _getPatchedClientMethods( - grpcClient: typeof grpcJs - ): (original: GrpcClientFunc) => () => EventEmitter { + private _getPatchedClientMethods(): ( + original: GrpcClientFunc + ) => () => EventEmitter { const instrumentation = this; return (original: GrpcClientFunc) => { instrumentation._diag.debug('patch all client methods'); - function clientMethodTrace(this: grpcJs.Client) { + function clientMethodTrace(this: Client) { const name = `grpc.${original.path.replace('/', '')}`; const args = [...arguments]; - const metadata = getMetadata.call( - instrumentation, - grpcClient, - original, - args - ); + const metadata = getMetadata.call(instrumentation, original, args); const { service, method } = _extractMethodAndService(original.path); const span = instrumentation.tracer @@ -367,24 +363,17 @@ export class GrpcJsInstrumentation extends InstrumentationBase { * parsing done by grpc.loadPackageDefinition * https://github.com/grpc/grpc-node/blob/1d14203c382509c3f36132bd0244c99792cb6601/packages/grpc-js/src/make-client.ts#L200-L217 */ - private _patchLoadedPackage( - grpcClient: typeof grpcJs, - result: grpcJs.GrpcObject - ): void { + private _patchLoadedPackage(result: GrpcObject): void { Object.values(result).forEach(service => { if (typeof service === 'function') { this._massWrap( service.prototype, getMethodsToWrap.call(this, service, service.service), - this._getPatchedClientMethods.call(this, grpcClient) + this._getPatchedClientMethods.call(this) ); } else if (typeof service.format !== 'string') { // GrpcObject - this._patchLoadedPackage.call( - this, - grpcClient, - service as grpcJs.GrpcObject - ); + this._patchLoadedPackage.call(this, service as GrpcObject); } }); } diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/serverUtils.ts b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/serverUtils.ts index ecfbc3d957d..78ebdfddefa 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/serverUtils.ts +++ b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/serverUtils.ts @@ -21,7 +21,6 @@ */ import { context, Span, SpanStatusCode } from '@opentelemetry/api'; -import type * as grpcJs from '@grpc/grpc-js'; import type { ServerCallWithMeta, SendUnaryDataCallback, @@ -36,6 +35,13 @@ import { IgnoreMatcher } from '../types'; import { AttributeNames } from '../enums/AttributeNames'; import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; import { GRPC_STATUS_CODE_OK } from '../status-code'; +import { + ClientReadableStream, + handleBidiStreamingCall, + handleServerStreamingCall, + handleUnaryCall, + ServiceError, +} from '@grpc/grpc-js'; export const CALL_SPAN_ENDED = Symbol('opentelemetry call span ended'); @@ -46,8 +52,8 @@ function serverStreamAndBidiHandler( span: Span, call: GrpcEmitter, original: - | grpcJs.handleBidiStreamingCall - | grpcJs.handleServerStreamingCall + | handleBidiStreamingCall + | handleServerStreamingCall ): void { let spanEnded = false; const endSpan = () => { @@ -79,7 +85,7 @@ function serverStreamAndBidiHandler( endSpan(); }); - call.on('error', (err: grpcJs.ServiceError) => { + call.on('error', (err: ServiceError) => { if (call[CALL_SPAN_ENDED]) { return; } @@ -111,11 +117,11 @@ function clientStreamAndUnaryHandler( call: ServerCallWithMeta, callback: SendUnaryDataCallback, original: - | grpcJs.handleUnaryCall - | grpcJs.ClientReadableStream + | handleUnaryCall + | ClientReadableStream ): void { const patchedCallback: SendUnaryDataCallback = ( - err: grpcJs.ServiceError | null, + err: ServiceError | null, value?: ResponseType ) => { if (err) { @@ -166,8 +172,8 @@ export function handleServerFunction( call, callback, originalFunc as - | grpcJs.handleUnaryCall - | grpcJs.ClientReadableStream + | handleUnaryCall + | ClientReadableStream ); case 'serverStream': case 'server_stream': @@ -176,8 +182,8 @@ export function handleServerFunction( span, call, originalFunc as - | grpcJs.handleBidiStreamingCall - | grpcJs.handleServerStreamingCall + | handleBidiStreamingCall + | handleServerStreamingCall ); default: break; @@ -212,7 +218,6 @@ export function handleUntracedServerFunction( * Returns true if the server call should not be traced. */ export function shouldNotTraceServerCall( - metadata: grpcJs.Metadata, methodName: string, ignoreGrpcMethods?: IgnoreMatcher[] ): boolean { diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/types.ts b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/types.ts index e0ae1545d2b..d55e80bcb38 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/types.ts +++ b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/types.ts @@ -14,29 +14,38 @@ * limitations under the License. */ -import type * as grpcJs from '@grpc/grpc-js'; import type { EventEmitter } from 'events'; import type { CALL_SPAN_ENDED } from './serverUtils'; +import { + requestCallback, + ServerUnaryCall, + ServerReadableStream, + ServerWritableStream, + ServerDuplexStream, + Metadata, + Server, + makeGenericClientConstructor, +} from '@grpc/grpc-js'; /** * Server Unary callback type */ -export type SendUnaryDataCallback = grpcJs.requestCallback; +export type SendUnaryDataCallback = requestCallback; /** * Intersection type of all grpc server call types */ export type ServerCall = - | grpcJs.ServerUnaryCall - | grpcJs.ServerReadableStream - | grpcJs.ServerWritableStream - | grpcJs.ServerDuplexStream; + | ServerUnaryCall + | ServerReadableStream + | ServerWritableStream + | ServerDuplexStream; /** * {@link ServerCall} ServerCall extended with misc. missing utility types */ export type ServerCallWithMeta = ServerCall & { - metadata: grpcJs.Metadata; + metadata: Metadata; }; /** @@ -53,10 +62,9 @@ export type GrpcClientFunc = ((...args: unknown[]) => GrpcEmitter) & { responseStream: boolean; }; -export type ServerRegisterFunction = typeof grpcJs.Server.prototype.register; +export type ServerRegisterFunction = typeof Server.prototype.register; -export type MakeClientConstructorFunction = - typeof grpcJs.makeGenericClientConstructor; +export type MakeClientConstructorFunction = typeof makeGenericClientConstructor; export type { HandleCall } from '@grpc/grpc-js/build/src/server-call'; export type { PackageDefinition } from '@grpc/grpc-js/build/src/make-client'; diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/src/instrumentation.ts b/experimental/packages/opentelemetry-instrumentation-grpc/src/instrumentation.ts index d597beaae27..d07481cfcb6 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/src/instrumentation.ts +++ b/experimental/packages/opentelemetry-instrumentation-grpc/src/instrumentation.ts @@ -17,7 +17,7 @@ import { GrpcInstrumentationConfig } from './types'; import { VERSION } from './version'; import { GrpcJsInstrumentation } from './grpc-js'; -import * as api from '@opentelemetry/api'; +import { MeterProvider, TracerProvider } from '@opentelemetry/api'; /** The metadata key under which span context is stored as a binary value. */ export const GRPC_TRACE_KEY = 'grpc-trace-bin'; @@ -68,7 +68,7 @@ export class GrpcInstrumentation { * Sets MeterProvider to this plugin * @param meterProvider */ - public setMeterProvider(meterProvider: api.MeterProvider) { + public setMeterProvider(meterProvider: MeterProvider) { this._grpcJsInstrumentation.setMeterProvider(meterProvider); } @@ -76,7 +76,7 @@ export class GrpcInstrumentation { * Sets TraceProvider to this plugin * @param tracerProvider */ - public setTracerProvider(tracerProvider: api.TracerProvider) { + public setTracerProvider(tracerProvider: TracerProvider) { this._grpcJsInstrumentation.setTracerProvider(tracerProvider); } } diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/src/internal-types.ts b/experimental/packages/opentelemetry-instrumentation-grpc/src/internal-types.ts index 594ad7ce0a0..dea26591b8a 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/src/internal-types.ts +++ b/experimental/packages/opentelemetry-instrumentation-grpc/src/internal-types.ts @@ -15,27 +15,15 @@ */ import { Span } from '@opentelemetry/api'; -import type * as grpcJsTypes from '@grpc/grpc-js'; +import type { Metadata } from '@grpc/grpc-js'; export type metadataCaptureType = { client: { - captureRequestMetadata: ( - span: Span, - metadata: grpcJsTypes.Metadata - ) => void; - captureResponseMetadata: ( - span: Span, - metadata: grpcJsTypes.Metadata - ) => void; + captureRequestMetadata: (span: Span, metadata: Metadata) => void; + captureResponseMetadata: (span: Span, metadata: Metadata) => void; }; server: { - captureRequestMetadata: ( - span: Span, - metadata: grpcJsTypes.Metadata - ) => void; - captureResponseMetadata: ( - span: Span, - metadata: grpcJsTypes.Metadata - ) => void; + captureRequestMetadata: (span: Span, metadata: Metadata) => void; + captureResponseMetadata: (span: Span, metadata: Metadata) => void; }; }; diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/src/utils.ts b/experimental/packages/opentelemetry-instrumentation-grpc/src/utils.ts index d9e542f509b..d65ed1c1031 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/src/utils.ts +++ b/experimental/packages/opentelemetry-instrumentation-grpc/src/utils.ts @@ -15,7 +15,7 @@ */ import { SpanStatusCode, SpanStatus, Span } from '@opentelemetry/api'; -import type * as grpcJsTypes from '@grpc/grpc-js'; +import type { status as GrpcStatus, Metadata } from '@grpc/grpc-js'; import { IgnoreMatcher } from './types'; // e.g., "dns:otel-productcatalogservice:8080" or "otel-productcatalogservice:8080" or "127.0.0.1:8080" @@ -42,7 +42,7 @@ export const findIndex: (args: T[], fn: (arg: T) => boolean) => number = ( * @param status */ export const _grpcStatusCodeToOpenTelemetryStatusCode = ( - status?: grpcJsTypes.status + status?: GrpcStatus ): SpanStatusCode => { if (status !== undefined && status === 0) { return SpanStatusCode.UNSET; @@ -127,7 +127,7 @@ export function metadataCapture( ]) ); - return (span: Span, metadata: grpcJsTypes.Metadata) => { + return (span: Span, metadata: Metadata) => { for (const [ capturedMetadata, normalizedMetadata,