diff --git a/sdk/eventhub/event-hubs/CHANGELOG.md b/sdk/eventhub/event-hubs/CHANGELOG.md index 734809f546af..520ec2c9b68c 100644 --- a/sdk/eventhub/event-hubs/CHANGELOG.md +++ b/sdk/eventhub/event-hubs/CHANGELOG.md @@ -6,6 +6,12 @@ where events could be _skipped_ while receiving messages. Previously this could occur when a retryable error was encountered and retries were exhausted while receiving a batch of events. +### Tracing updates: + +- Addresses [#10276](https://github.com/Azure/azure-sdk-for-js/issues/10276): adds + `message_bus.destination` and `peer.address` attributes to `Azure.EventHubs.message` spans. + ([PR 10389](https://github.com/Azure/azure-sdk-for-js/pull/10389)) + ## 5.3.0-preview.1 (2020-07-07) - Adds `loadBalancingOptions` to the `EventHubConsumerClient` to add control around diff --git a/sdk/eventhub/event-hubs/src/diagnostics/messageSpan.ts b/sdk/eventhub/event-hubs/src/diagnostics/messageSpan.ts index 15ca481c5964..ad15fae72bbc 100644 --- a/sdk/eventhub/event-hubs/src/diagnostics/messageSpan.ts +++ b/sdk/eventhub/event-hubs/src/diagnostics/messageSpan.ts @@ -3,18 +3,26 @@ import { getTracer } from "@azure/core-tracing"; import { Span, SpanContext, SpanKind } from "@opentelemetry/api"; +import { EventHubConnectionConfig } from "@azure/core-amqp"; /** * @internal * @ignore */ -export function createMessageSpan(parentSpan?: Span | SpanContext | null): Span { +export function createMessageSpan( + parentSpan?: Span | SpanContext | null, + eventHubConfig?: Pick +): Span { const tracer = getTracer(); const span = tracer.startSpan("Azure.EventHubs.message", { kind: SpanKind.PRODUCER, parent: parentSpan }); span.setAttribute("az.namespace", "Microsoft.EventHub"); + if (eventHubConfig) { + span.setAttribute("message_bus.destination", eventHubConfig.entityPath); + span.setAttribute("peer.address", eventHubConfig.host); + } return span; } diff --git a/sdk/eventhub/event-hubs/src/eventDataBatch.ts b/sdk/eventhub/event-hubs/src/eventDataBatch.ts index 5299b3370519..eca16b5b6826 100644 --- a/sdk/eventhub/event-hubs/src/eventDataBatch.ts +++ b/sdk/eventhub/event-hubs/src/eventDataBatch.ts @@ -296,7 +296,7 @@ export class EventDataBatchImpl implements EventDataBatch { ); let spanContext: SpanContext | undefined; if (!previouslyInstrumented) { - const messageSpan = createMessageSpan(options.parentSpan); + const messageSpan = createMessageSpan(options.parentSpan, this._context.config); eventData = instrumentEventData(eventData, messageSpan); spanContext = messageSpan.context(); messageSpan.end(); diff --git a/sdk/eventhub/event-hubs/src/eventHubProducerClient.ts b/sdk/eventhub/event-hubs/src/eventHubProducerClient.ts index 5ef3d55c39f5..7f03604d06fa 100644 --- a/sdk/eventhub/event-hubs/src/eventHubProducerClient.ts +++ b/sdk/eventhub/event-hubs/src/eventHubProducerClient.ts @@ -265,7 +265,10 @@ export class EventHubProducerClient { for (let i = 0; i < batch.length; i++) { const event = batch[i]; if (!event.properties || !event.properties[TRACEPARENT_PROPERTY]) { - const messageSpan = createMessageSpan(getParentSpan(options.tracingOptions)); + const messageSpan = createMessageSpan( + getParentSpan(options.tracingOptions), + this._context.config + ); // since these message spans are created from same context as the send span, // these message spans don't need to be linked. // replace the original event with the instrumented one diff --git a/sdk/eventhub/event-hubs/test/diagnostics/messageSpan.spec.ts b/sdk/eventhub/event-hubs/test/diagnostics/messageSpan.spec.ts new file mode 100644 index 000000000000..63f6f52d5807 --- /dev/null +++ b/sdk/eventhub/event-hubs/test/diagnostics/messageSpan.spec.ts @@ -0,0 +1,82 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import chai from "chai"; +import { createMessageSpan } from "../../src/diagnostics/messageSpan"; +import { TraceFlags, SpanContext } from "@opentelemetry/api"; +import { TestTracer, setTracer, getTracer } from "@azure/core-tracing"; +import { EventHubConnectionConfig } from '@azure/core-amqp'; + +const should = chai.should(); +const assert = chai.assert; + +describe("#createMessageSpan()", () => { + const origTracer = getTracer(); + + before(() => { + setTracer(new TestTracer()); + }); + + after(() => { + setTracer(origTracer); + }); + + const mockSpanContext: SpanContext = { + traceId: "d4cda95b652f4a1592b449d5929fda1b", + spanId: "6e0c63257de34c92", + traceFlags: TraceFlags.SAMPLED + }; + const mockEventHubConnectionConfig: Pick = { + entityPath: "entity", + host: "foo.example.com" + }; + + it("should create a span without a parent", () => { + const span = createMessageSpan(); + + should.exist(span); + should.exist(span.context().spanId); + should.exist(span.context().traceId); + + should.equal((span as any).name, "Azure.EventHubs.message"); + assert.deepStrictEqual((span as any).attributes, { + "az.namespace": "Microsoft.EventHub" + }); + + span.end(); + }); + + it("should create a span with a parent", () => { + const span = createMessageSpan(mockSpanContext); + + should.exist(span); + should.equal(span.context().traceId, mockSpanContext.traceId); + should.exist(span.context().spanId); + should.not.equal(span.context().spanId, mockSpanContext.spanId); + + should.equal((span as any).name, "Azure.EventHubs.message"); + assert.deepStrictEqual((span as any).attributes, { + "az.namespace": "Microsoft.EventHub" + }); + + span.end(); + }); + + it("should create a span with an eventHubConfig", () => { + const span = createMessageSpan(mockSpanContext, mockEventHubConnectionConfig); + + should.exist(span); + should.equal(span.context().traceId, mockSpanContext.traceId); + should.exist(span.context().spanId); + should.not.equal(span.context().spanId, mockSpanContext.spanId); + + should.equal((span as any).name, "Azure.EventHubs.message"); + assert.deepStrictEqual((span as any).attributes, { + "az.namespace": "Microsoft.EventHub", + "message_bus.destination": mockEventHubConnectionConfig.entityPath, + "peer.address": mockEventHubConnectionConfig.host + }); + + span.end(); + }); +});