From 2e48472a232637b4fa4c24cb4ce64f930046ad3b Mon Sep 17 00:00:00 2001 From: Ty Bekiares Date: Sun, 20 Nov 2022 09:17:42 -0600 Subject: [PATCH] feat(instrumentation-grpc): set peer.service on client spans --- .../src/grpc-js/index.ts | 7 ++++++- .../opentelemetry-instrumentation-grpc/src/grpc/index.ts | 7 ++++++- .../opentelemetry-instrumentation-grpc/src/utils.ts | 3 +++ .../opentelemetry-instrumentation-grpc/test/helper.ts | 4 ++++ .../test/utils/assertionUtils.ts | 6 +++++- 5 files changed, 24 insertions(+), 3 deletions(-) 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 4a1c8e9f3aa..dc2b9d88247 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/index.ts +++ b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc-js/index.ts @@ -49,7 +49,7 @@ import { getMetadata, } from './clientUtils'; import { EventEmitter } from 'events'; -import { _extractMethodAndService } from '../utils'; +import { _extractMethodAndService, URI_REGEX } from '../utils'; import { AttributeValues } from '../enums/AttributeValues'; import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; @@ -298,6 +298,11 @@ export class GrpcJsInstrumentation extends InstrumentationBase { [SemanticAttributes.RPC_METHOD]: method, [SemanticAttributes.RPC_SERVICE]: service, }); + // set peer.service from target (e.g., "dns:otel-productcatalogservice:8080") as a hint to APMs + const parsedUri = URI_REGEX.exec(this.getChannel().getTarget()); + if (parsedUri != null && parsedUri.groups != null) { + span.setAttribute(SemanticAttributes.PEER_SERVICE, parsedUri.groups['addr']); + } return context.with(trace.setSpan(context.active(), span), () => makeGrpcClientRemoteCall(original, args, metadata, this)(span) ); diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc/index.ts b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc/index.ts index b31d9ef55c3..9631952df6a 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc/index.ts +++ b/experimental/packages/opentelemetry-instrumentation-grpc/src/grpc/index.ts @@ -41,7 +41,7 @@ import { serverStreamAndBidiHandler, } from './serverUtils'; import { makeGrpcClientRemoteCall, getMetadata } from './clientUtils'; -import { _extractMethodAndService, _methodIsIgnored } from '../utils'; +import { _extractMethodAndService, _methodIsIgnored, URI_REGEX } from '../utils'; import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; import {AttributeValues} from '../enums/AttributeValues'; @@ -306,6 +306,11 @@ export class GrpcNativeInstrumentation extends InstrumentationBase< [SemanticAttributes.RPC_METHOD]: method, [SemanticAttributes.RPC_SERVICE]: service, }); + // set peer.service from target (e.g., "dns:otel-productcatalogservice:8080") as a hint to APMs + const parsedUri = URI_REGEX.exec(this.getChannel().getTarget()); + if (parsedUri != null && parsedUri.groups != null) { + span.setAttribute(SemanticAttributes.PEER_SERVICE, parsedUri.groups['addr']); + } return context.with(trace.setSpan(context.active(), span), () => makeGrpcClientRemoteCall( grpcClient, diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/src/utils.ts b/experimental/packages/opentelemetry-instrumentation-grpc/src/utils.ts index 16bf81a7286..770862a1f27 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/src/utils.ts +++ b/experimental/packages/opentelemetry-instrumentation-grpc/src/utils.ts @@ -19,6 +19,9 @@ import type * as grpcTypes from 'grpc'; import type * as grpcJsTypes from '@grpc/grpc-js'; import { IgnoreMatcher } from './types'; +// e.g., "dns:otel-productcatalogservice:8080" or "127.0.0.1:8080" +export const URI_REGEX = /(?:([A-Za-z0-9+.-]+):(?:\/\/)?)?(?[A-Za-z0-9+.-]+:[0-9+.-]+)$/; + // Equivalent to lodash _.findIndex export const findIndex: (args: T[], fn: (arg: T) => boolean) => number = ( args, diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/test/helper.ts b/experimental/packages/opentelemetry-instrumentation-grpc/test/helper.ts index 5564c7c964f..fca64eceb9f 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/test/helper.ts +++ b/experimental/packages/opentelemetry-instrumentation-grpc/test/helper.ts @@ -481,6 +481,7 @@ export const runTests = ( const validations = { name: `grpc.pkg_test.GrpcTester/${method.methodName}`, status: grpc.status.OK, + peerService: 'localhost:' + grpcPort, }; assert.strictEqual(spans.length, 2); @@ -530,6 +531,7 @@ export const runTests = ( const validations = { name: `grpc.pkg_test.GrpcTester/${method.methodName}`, status: grpc.status.OK, + peerService: 'localhost:' + grpcPort, }; assertSpan( moduleName, @@ -590,6 +592,7 @@ export const runTests = ( const validations = { name: `grpc.pkg_test.GrpcTester/${method.methodName}`, status: errorCode, + peerService: 'localhost:' + grpcPort, }; const serverRoot = spans[0]; const clientRoot = spans[1]; @@ -629,6 +632,7 @@ export const runTests = ( const validations = { name: `grpc.pkg_test.GrpcTester/${method.methodName}`, status: errorCode, + peerService: 'localhost:' + grpcPort, }; assertSpan(moduleName, serverSpan, SpanKind.SERVER, validations); assertSpan(moduleName, clientSpan, SpanKind.CLIENT, validations); diff --git a/experimental/packages/opentelemetry-instrumentation-grpc/test/utils/assertionUtils.ts b/experimental/packages/opentelemetry-instrumentation-grpc/test/utils/assertionUtils.ts index e399a4a5c52..03a39e7e221 100644 --- a/experimental/packages/opentelemetry-instrumentation-grpc/test/utils/assertionUtils.ts +++ b/experimental/packages/opentelemetry-instrumentation-grpc/test/utils/assertionUtils.ts @@ -37,7 +37,7 @@ export const assertSpan = ( component: string, span: ReadableSpan, kind: SpanKind, - validations: { name: string; status: grpc.status | grpcJs.status } + validations: { name: string; status: grpc.status | grpcJs.status; peerService?: string } ) => { assert.strictEqual(span.spanContext().traceId.length, 32); assert.strictEqual(span.spanContext().spanId.length, 16); @@ -55,6 +55,10 @@ export const assertSpan = ( assert.ok(span.spanContext()); } + if (span.kind === SpanKind.CLIENT && validations.peerService != undefined) { + assert.strictEqual(span.attributes['peer.service'], validations.peerService); + } + // validations assert.strictEqual(span.name, validations.name); assert.strictEqual(