From 1ffd3aae48a0f352f4d8c8bdcae52ca4d46477e9 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Tue, 22 Sep 2020 17:37:16 -0700 Subject: [PATCH] [EventGrid] Distributed Tracing for EventGrid - Create spans for each of the send operations on `EventGridPublisherClient` - When sending events in the Cloud Events schema, if we have a traceparent or tracestate and an event we are sending does not have any distributed tracing metadata (per the Cloud Events distributed tracing spec) we add this metadata associating the events with the span representing the HTTP operation that sends the event to the Azure Event Grid Service. Fixes: #11056 --- ..._with_distributed_tracing_information.json | 32 +++++ .../recording_sends_a_single_event.json | 10 +- .../recording_sends_multiple_events.json | 14 +- .../recording_sends_a_single_event.json | 4 +- .../recording_sends_multiple_events.json | 4 +- .../recording_sends_a_single_event.json | 10 +- .../recording_sends_multiple_events.json | 14 +- ...ts_with_distributed_tracing_information.js | 23 ++++ .../recording_sends_a_single_event.js | 8 +- .../recording_sends_multiple_events.js | 8 +- .../recording_sends_a_single_event.js | 4 +- .../recording_sends_multiple_events.js | 4 +- .../recording_sends_a_single_event.js | 8 +- .../recording_sends_multiple_events.js | 8 +- ...oudEventDistrubtedTracingEnricherPolicy.ts | 72 +++++++++++ .../eventgrid/src/eventGridClient.ts | 102 ++++++++++----- .../src/generated/generatedClient.ts | 6 +- sdk/eventgrid/eventgrid/src/tracing.ts | 57 ++++++++ ...entDistrubtedTracingEnricherPolicy.spec.ts | 122 ++++++++++++++++++ .../eventgrid/test/eventGridClient.spec.ts | 44 +++++++ 20 files changed, 472 insertions(+), 82 deletions(-) create mode 100644 sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendcloudeventschemaevents/recording_enriches_events_with_distributed_tracing_information.json create mode 100644 sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendcloudeventschemaevents/recording_enriches_events_with_distributed_tracing_information.js create mode 100644 sdk/eventgrid/eventgrid/src/cloudEventDistrubtedTracingEnricherPolicy.ts create mode 100644 sdk/eventgrid/eventgrid/src/tracing.ts create mode 100644 sdk/eventgrid/eventgrid/test/cloudEventDistrubtedTracingEnricherPolicy.spec.ts diff --git a/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendcloudeventschemaevents/recording_enriches_events_with_distributed_tracing_information.json b/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendcloudeventschemaevents/recording_enriches_events_with_distributed_tracing_information.json new file mode 100644 index 000000000000..177d140987a9 --- /dev/null +++ b/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendcloudeventschemaevents/recording_enriches_events_with_distributed_tracing_information.json @@ -0,0 +1,32 @@ +{ + "recordings": [ + { + "method": "POST", + "url": "https://endpoint/api/events", + "query": { + "api-version": "2018-01-01" + }, + "requestBody": "[{\"id\":\"cloudTracingEventId160161957922404717\",\"source\":\"/earth/unitedstates/washington/kirkland/finnhill\",\"data\":{\"hello\":\"world\"},\"type\":\"Azure.Sdk.TestEvent1\",\"time\":\"2020-10-02T06:19:39.224Z\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"subject\":\"Single with Trace Parent\",\"traceparent\":\"00-1-3-00\"}]", + "status": 200, + "response": "", + "responseHeaders": { + "api-supported-versions": "2018-01-01", + "content-length": "0", + "date": "Fri, 02 Oct 2020 06:19:39 GMT", + "server": "Microsoft-HTTPAPI/2.0", + "status": "200", + "strict-transport-security": "max-age=31536000; includeSubDomains", + "x-ms-request-id": "98b6d722-9da2-4723-88dd-03201af90be8" + } + } + ], + "uniqueTestInfo": { + "uniqueName": { + "cloudTracingEventId": "cloudTracingEventId160161957922404717" + }, + "newDate": { + "cloudTracingEventDate": "2020-10-02T06:19:39.224Z" + } + }, + "hash": "25b86eb5cf132e9be63d832bd8de85a7" +} \ No newline at end of file diff --git a/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendcloudeventschemaevents/recording_sends_a_single_event.json b/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendcloudeventschemaevents/recording_sends_a_single_event.json index e06cfedfde60..62c2db666bec 100644 --- a/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendcloudeventschemaevents/recording_sends_a_single_event.json +++ b/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendcloudeventschemaevents/recording_sends_a_single_event.json @@ -6,26 +6,26 @@ "query": { "api-version": "2018-01-01" }, - "requestBody": "[{\"id\":\"cloudSingleEventId159588374669809673\",\"source\":\"/earth/unitedstates/washington/kirkland/finnhill\",\"data\":{\"hello\":\"world\"},\"type\":\"Azure.Sdk.TestEvent1\",\"time\":\"2020-07-27T21:02:26.698Z\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\"}]", + "requestBody": "[{\"id\":\"cloudSingleEventId160161957916908323\",\"source\":\"/earth/unitedstates/washington/kirkland/finnhill\",\"data\":{\"hello\":\"world\"},\"type\":\"Azure.Sdk.TestEvent1\",\"time\":\"2020-10-02T06:19:39.169Z\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\"}]", "status": 200, "response": "", "responseHeaders": { "api-supported-versions": "2018-01-01", "content-length": "0", - "date": "Mon, 27 Jul 2020 21:02:26 GMT", + "date": "Fri, 02 Oct 2020 06:19:39 GMT", "server": "Microsoft-HTTPAPI/2.0", "status": "200", "strict-transport-security": "max-age=31536000; includeSubDomains", - "x-ms-request-id": "46a799c7-f453-4894-9b7e-e6fd93259622" + "x-ms-request-id": "a7889d03-9a79-4916-b459-cb52b7f28794" } } ], "uniqueTestInfo": { "uniqueName": { - "cloudSingleEventId": "cloudSingleEventId159588374669809673" + "cloudSingleEventId": "cloudSingleEventId160161957916908323" }, "newDate": { - "cloudSingleEventDate": "2020-07-27T21:02:26.698Z" + "cloudSingleEventDate": "2020-10-02T06:19:39.169Z" } }, "hash": "7fe25ee020ac364dae32ce81a81c7c3f" diff --git a/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendcloudeventschemaevents/recording_sends_multiple_events.json b/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendcloudeventschemaevents/recording_sends_multiple_events.json index d4491d390ec3..1c6482037261 100644 --- a/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendcloudeventschemaevents/recording_sends_multiple_events.json +++ b/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendcloudeventschemaevents/recording_sends_multiple_events.json @@ -6,28 +6,28 @@ "query": { "api-version": "2018-01-01" }, - "requestBody": "[{\"id\":\"cloudMultiEventId1159588374680705635\",\"source\":\"/earth/unitedstates/washington/kirkland/finnhill\",\"data\":{\"hello\":\"world\"},\"type\":\"Azure.Sdk.TestEvent1\",\"time\":\"2020-07-27T21:02:26.807Z\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"subject\":\"Multiple 1\"},{\"id\":\"cloudMultiEventId2159588374680700679\",\"source\":\"/earth/unitedstates/washington/kirkland/finnhill\",\"data\":{\"hello\":\"world\"},\"type\":\"Azure.Sdk.TestEvent1\",\"time\":\"2020-07-27T21:02:26.807Z\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"subject\":\"Multiple 2\"}]", + "requestBody": "[{\"id\":\"cloudMultiEventId1160161957919602606\",\"source\":\"/earth/unitedstates/washington/kirkland/finnhill\",\"data\":{\"hello\":\"world\"},\"type\":\"Azure.Sdk.TestEvent1\",\"time\":\"2020-10-02T06:19:39.196Z\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"subject\":\"Multiple 1\"},{\"id\":\"cloudMultiEventId2160161957919607521\",\"source\":\"/earth/unitedstates/washington/kirkland/finnhill\",\"data\":{\"hello\":\"world\"},\"type\":\"Azure.Sdk.TestEvent1\",\"time\":\"2020-10-02T06:19:39.196Z\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"subject\":\"Multiple 2\"}]", "status": 200, "response": "", "responseHeaders": { "api-supported-versions": "2018-01-01", "content-length": "0", - "date": "Mon, 27 Jul 2020 21:02:26 GMT", + "date": "Fri, 02 Oct 2020 06:19:39 GMT", "server": "Microsoft-HTTPAPI/2.0", "status": "200", "strict-transport-security": "max-age=31536000; includeSubDomains", - "x-ms-request-id": "5883a20b-ce78-4928-afb8-bde068f61fb5" + "x-ms-request-id": "8ff6465b-3625-4a89-b5d9-a37604f36895" } } ], "uniqueTestInfo": { "uniqueName": { - "cloudMultiEventId1": "cloudMultiEventId1159588374680705635", - "cloudMultiEventId2": "cloudMultiEventId2159588374680700679" + "cloudMultiEventId1": "cloudMultiEventId1160161957919602606", + "cloudMultiEventId2": "cloudMultiEventId2160161957919607521" }, "newDate": { - "cloudMultiEventDate1": "2020-07-27T21:02:26.807Z", - "cloudMultiEventDate2": "2020-07-27T21:02:26.807Z" + "cloudMultiEventDate1": "2020-10-02T06:19:39.196Z", + "cloudMultiEventDate2": "2020-10-02T06:19:39.196Z" } }, "hash": "799392d36931d99dc2c24d3db67fcb0b" diff --git a/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendcustomschemaevents/recording_sends_a_single_event.json b/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendcustomschemaevents/recording_sends_a_single_event.json index 4e1ad0aed8ec..655b61dc580f 100644 --- a/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendcustomschemaevents/recording_sends_a_single_event.json +++ b/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendcustomschemaevents/recording_sends_a_single_event.json @@ -12,11 +12,11 @@ "responseHeaders": { "api-supported-versions": "2018-01-01", "content-length": "0", - "date": "Mon, 27 Jul 2020 21:02:26 GMT", + "date": "Fri, 02 Oct 2020 06:19:39 GMT", "server": "Microsoft-HTTPAPI/2.0", "status": "200", "strict-transport-security": "max-age=31536000; includeSubDomains", - "x-ms-request-id": "e9595ef6-2387-4362-9573-9a2189e74b7d" + "x-ms-request-id": "83c15d3b-2389-48c1-b34a-f38772788075" } } ], diff --git a/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendcustomschemaevents/recording_sends_multiple_events.json b/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendcustomschemaevents/recording_sends_multiple_events.json index bfcb02399eb2..c26be7cf35b7 100644 --- a/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendcustomschemaevents/recording_sends_multiple_events.json +++ b/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendcustomschemaevents/recording_sends_multiple_events.json @@ -12,11 +12,11 @@ "responseHeaders": { "api-supported-versions": "2018-01-01", "content-length": "0", - "date": "Mon, 27 Jul 2020 21:02:26 GMT", + "date": "Fri, 02 Oct 2020 06:19:39 GMT", "server": "Microsoft-HTTPAPI/2.0", "status": "200", "strict-transport-security": "max-age=31536000; includeSubDomains", - "x-ms-request-id": "a2b97d35-f1aa-4033-9886-e6907c7d6769" + "x-ms-request-id": "dab12263-7746-4a18-b9f5-36b83d744385" } } ], diff --git a/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendevents/recording_sends_a_single_event.json b/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendevents/recording_sends_a_single_event.json index cf64165efb69..fb52f32afd5d 100644 --- a/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendevents/recording_sends_a_single_event.json +++ b/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendevents/recording_sends_a_single_event.json @@ -6,26 +6,26 @@ "query": { "api-version": "2018-01-01" }, - "requestBody": "[{\"id\":\"singleEventId159588374414604202\",\"subject\":\"Single 1\",\"data\":{\"hello\":\"world\"},\"eventType\":\"Azure.Sdk.TestEvent1\",\"eventTime\":\"2020-07-27T21:02:24.145Z\",\"dataVersion\":\"1.0\"}]", + "requestBody": "[{\"id\":\"singleEventId160161957902009844\",\"subject\":\"Single 1\",\"data\":{\"hello\":\"world\"},\"eventType\":\"Azure.Sdk.TestEvent1\",\"eventTime\":\"2020-10-02T06:19:39.020Z\",\"dataVersion\":\"1.0\"}]", "status": 200, "response": "", "responseHeaders": { "api-supported-versions": "2018-01-01", "content-length": "0", - "date": "Mon, 27 Jul 2020 21:02:26 GMT", + "date": "Fri, 02 Oct 2020 06:19:39 GMT", "server": "Microsoft-HTTPAPI/2.0", "status": "200", "strict-transport-security": "max-age=31536000; includeSubDomains", - "x-ms-request-id": "6b4ec1fb-b123-4406-ba01-4fd7c70f4ac0" + "x-ms-request-id": "4ac1571b-c1eb-4795-92a6-f7d1e1f5ea5d" } } ], "uniqueTestInfo": { "uniqueName": { - "singleEventId": "singleEventId159588374414604202" + "singleEventId": "singleEventId160161957902009844" }, "newDate": { - "singleEventDate": "2020-07-27T21:02:24.145Z" + "singleEventDate": "2020-10-02T06:19:39.020Z" } }, "hash": "9b44e18369316233af4458904ca8ae09" diff --git a/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendevents/recording_sends_multiple_events.json b/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendevents/recording_sends_multiple_events.json index a05ed1e4160b..c91100a7889d 100644 --- a/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendevents/recording_sends_multiple_events.json +++ b/sdk/eventgrid/eventgrid/recordings/browsers/eventgridpublisherclient_sendevents/recording_sends_multiple_events.json @@ -6,28 +6,28 @@ "query": { "api-version": "2018-01-01" }, - "requestBody": "[{\"id\":\"multiEventId1159588374666206734\",\"subject\":\"Multiple 1\",\"data\":{\"hello\":\"world\"},\"eventType\":\"Azure.Sdk.TestEvent1\",\"eventTime\":\"2020-07-27T21:02:26.662Z\",\"dataVersion\":\"1.0\"},{\"id\":\"multiEventId2159588374666206405\",\"subject\":\"Multiple 2\",\"data\":{\"hello\":\"world\"},\"eventType\":\"Azure.Sdk.TestEvent1\",\"eventTime\":\"2020-07-27T21:02:26.662Z\",\"dataVersion\":\"1.0\"}]", + "requestBody": "[{\"id\":\"multiEventId1160161957914201725\",\"subject\":\"Multiple 1\",\"data\":{\"hello\":\"world\"},\"eventType\":\"Azure.Sdk.TestEvent1\",\"eventTime\":\"2020-10-02T06:19:39.142Z\",\"dataVersion\":\"1.0\"},{\"id\":\"multiEventId2160161957914306573\",\"subject\":\"Multiple 2\",\"data\":{\"hello\":\"world\"},\"eventType\":\"Azure.Sdk.TestEvent1\",\"eventTime\":\"2020-10-02T06:19:39.143Z\",\"dataVersion\":\"1.0\"}]", "status": 200, "response": "", "responseHeaders": { "api-supported-versions": "2018-01-01", "content-length": "0", - "date": "Mon, 27 Jul 2020 21:02:26 GMT", + "date": "Fri, 02 Oct 2020 06:19:39 GMT", "server": "Microsoft-HTTPAPI/2.0", "status": "200", "strict-transport-security": "max-age=31536000; includeSubDomains", - "x-ms-request-id": "e8eb4406-e3e9-4f10-9f25-31ebd5c4e48b" + "x-ms-request-id": "00cbfe5a-179b-4cda-a2a3-8bd1d6a56cb1" } } ], "uniqueTestInfo": { "uniqueName": { - "multiEventId1": "multiEventId1159588374666206734", - "multiEventId2": "multiEventId2159588374666206405" + "multiEventId1": "multiEventId1160161957914201725", + "multiEventId2": "multiEventId2160161957914306573" }, "newDate": { - "multiEventDate1": "2020-07-27T21:02:26.662Z", - "multiEventDate2": "2020-07-27T21:02:26.662Z" + "multiEventDate1": "2020-10-02T06:19:39.142Z", + "multiEventDate2": "2020-10-02T06:19:39.143Z" } }, "hash": "a1eefb69b1513dc523f50ee66055787d" diff --git a/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendcloudeventschemaevents/recording_enriches_events_with_distributed_tracing_information.js b/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendcloudeventschemaevents/recording_enriches_events_with_distributed_tracing_information.js new file mode 100644 index 000000000000..8570a2c12027 --- /dev/null +++ b/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendcloudeventschemaevents/recording_enriches_events_with_distributed_tracing_information.js @@ -0,0 +1,23 @@ +let nock = require('nock'); + +module.exports.hash = "e2a76a5d9d938e00781cf1196fef789c"; + +module.exports.testInfo = {"uniqueName":{"cloudTracingEventId":"cloudTracingEventId160161957338401351"},"newDate":{"cloudTracingEventDate":"2020-10-02T06:19:33.384Z"}} + +nock('https://endpoint', {"encodedQueryParams":true}) + .post('/api/events', [{"id":"cloudTracingEventId160161957338401351","source":"/earth/unitedstates/washington/kirkland/finnhill","data":{"hello":"world"},"type":"Azure.Sdk.TestEvent1","time":"2020-10-02T06:19:33.384Z","specversion":"1.0","datacontenttype":"application/json","subject":"Single with Trace Parent","traceparent":"00-1-3-00"}]) + .query(true) + .reply(200, "", [ + 'Content-Length', + '0', + 'Server', + 'Microsoft-HTTPAPI/2.0', + 'Strict-Transport-Security', + 'max-age=31536000; includeSubDomains', + 'api-supported-versions', + '2018-01-01', + 'x-ms-request-id', + '53541e19-8134-404e-b98f-5606335f3849', + 'Date', + 'Fri, 02 Oct 2020 06:19:34 GMT' +]); diff --git a/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendcloudeventschemaevents/recording_sends_a_single_event.js b/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendcloudeventschemaevents/recording_sends_a_single_event.js index fcbb53e92b2f..c93b0c80b798 100644 --- a/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendcloudeventschemaevents/recording_sends_a_single_event.js +++ b/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendcloudeventschemaevents/recording_sends_a_single_event.js @@ -2,10 +2,10 @@ let nock = require('nock'); module.exports.hash = "b15b1edb6fd215ff27f66c70053afbb8"; -module.exports.testInfo = {"uniqueName":{"cloudSingleEventId":"cloudSingleEventId159588373652209687"},"newDate":{"cloudSingleEventDate":"2020-07-27T21:02:16.522Z"}} +module.exports.testInfo = {"uniqueName":{"cloudSingleEventId":"cloudSingleEventId160161957312109296"},"newDate":{"cloudSingleEventDate":"2020-10-02T06:19:33.121Z"}} nock('https://endpoint', {"encodedQueryParams":true}) - .post('/api/events', [{"id":"cloudSingleEventId159588373652209687","source":"/earth/unitedstates/washington/kirkland/finnhill","data":{"hello":"world"},"type":"Azure.Sdk.TestEvent1","time":"2020-07-27T21:02:16.522Z","specversion":"1.0","datacontenttype":"application/json"}]) + .post('/api/events', [{"id":"cloudSingleEventId160161957312109296","source":"/earth/unitedstates/washington/kirkland/finnhill","data":{"hello":"world"},"type":"Azure.Sdk.TestEvent1","time":"2020-10-02T06:19:33.121Z","specversion":"1.0","datacontenttype":"application/json"}]) .query(true) .reply(200, "", [ 'Content-Length', @@ -17,7 +17,7 @@ nock('https://endpoint', {"encodedQueryParams":true}) 'api-supported-versions', '2018-01-01', 'x-ms-request-id', - '05f88f8f-bd50-41d7-b56c-394c1eeebe1f', + '8cb4c799-b937-4ebf-b2c5-5803f9af5f30', 'Date', - 'Mon, 27 Jul 2020 21:02:16 GMT' + 'Fri, 02 Oct 2020 06:19:33 GMT' ]); diff --git a/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendcloudeventschemaevents/recording_sends_multiple_events.js b/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendcloudeventschemaevents/recording_sends_multiple_events.js index 2deaf6208971..3e248783176e 100644 --- a/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendcloudeventschemaevents/recording_sends_multiple_events.js +++ b/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendcloudeventschemaevents/recording_sends_multiple_events.js @@ -2,10 +2,10 @@ let nock = require('nock'); module.exports.hash = "cefc29910fbb6c53981faf8430a3521b"; -module.exports.testInfo = {"uniqueName":{"cloudMultiEventId1":"cloudMultiEventId1159588373674007628","cloudMultiEventId2":"cloudMultiEventId2159588373674005416"},"newDate":{"cloudMultiEventDate1":"2020-07-27T21:02:16.740Z","cloudMultiEventDate2":"2020-07-27T21:02:16.740Z"}} +module.exports.testInfo = {"uniqueName":{"cloudMultiEventId1":"cloudMultiEventId1160161957330706944","cloudMultiEventId2":"cloudMultiEventId2160161957330706023"},"newDate":{"cloudMultiEventDate1":"2020-10-02T06:19:33.307Z","cloudMultiEventDate2":"2020-10-02T06:19:33.307Z"}} nock('https://endpoint', {"encodedQueryParams":true}) - .post('/api/events', [{"id":"cloudMultiEventId1159588373674007628","source":"/earth/unitedstates/washington/kirkland/finnhill","data":{"hello":"world"},"type":"Azure.Sdk.TestEvent1","time":"2020-07-27T21:02:16.740Z","specversion":"1.0","datacontenttype":"application/json","subject":"Multiple 1"},{"id":"cloudMultiEventId2159588373674005416","source":"/earth/unitedstates/washington/kirkland/finnhill","data":{"hello":"world"},"type":"Azure.Sdk.TestEvent1","time":"2020-07-27T21:02:16.740Z","specversion":"1.0","datacontenttype":"application/json","subject":"Multiple 2"}]) + .post('/api/events', [{"id":"cloudMultiEventId1160161957330706944","source":"/earth/unitedstates/washington/kirkland/finnhill","data":{"hello":"world"},"type":"Azure.Sdk.TestEvent1","time":"2020-10-02T06:19:33.307Z","specversion":"1.0","datacontenttype":"application/json","subject":"Multiple 1"},{"id":"cloudMultiEventId2160161957330706023","source":"/earth/unitedstates/washington/kirkland/finnhill","data":{"hello":"world"},"type":"Azure.Sdk.TestEvent1","time":"2020-10-02T06:19:33.307Z","specversion":"1.0","datacontenttype":"application/json","subject":"Multiple 2"}]) .query(true) .reply(200, "", [ 'Content-Length', @@ -17,7 +17,7 @@ nock('https://endpoint', {"encodedQueryParams":true}) 'api-supported-versions', '2018-01-01', 'x-ms-request-id', - '9ff2a9d4-8089-4ac2-9c2d-1d184abf00e5', + 'ce2dbd99-384b-450a-9644-23508bdcbfc0', 'Date', - 'Mon, 27 Jul 2020 21:02:16 GMT' + 'Fri, 02 Oct 2020 06:19:34 GMT' ]); diff --git a/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendcustomschemaevents/recording_sends_a_single_event.js b/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendcustomschemaevents/recording_sends_a_single_event.js index a8611e922173..324f24a0fae2 100644 --- a/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendcustomschemaevents/recording_sends_a_single_event.js +++ b/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendcustomschemaevents/recording_sends_a_single_event.js @@ -17,7 +17,7 @@ nock('https://endpoint', {"encodedQueryParams":true}) 'api-supported-versions', '2018-01-01', 'x-ms-request-id', - 'fbdc8574-3c20-4bc9-af6b-0d5e454611f6', + '1164c7cc-b631-4fed-979b-912946a72d7b', 'Date', - 'Mon, 27 Jul 2020 21:02:16 GMT' + 'Fri, 02 Oct 2020 06:19:33 GMT' ]); diff --git a/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendcustomschemaevents/recording_sends_multiple_events.js b/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendcustomschemaevents/recording_sends_multiple_events.js index 1735dfe3ec3f..9d236f8ffc2a 100644 --- a/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendcustomschemaevents/recording_sends_multiple_events.js +++ b/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendcustomschemaevents/recording_sends_multiple_events.js @@ -17,7 +17,7 @@ nock('https://endpoint', {"encodedQueryParams":true}) 'api-supported-versions', '2018-01-01', 'x-ms-request-id', - '3461b247-63cd-4940-8cfd-61ada2073c7f', + 'a541a967-991c-4d1f-9bc5-59b318703d1c', 'Date', - 'Mon, 27 Jul 2020 21:02:17 GMT' + 'Fri, 02 Oct 2020 06:19:34 GMT' ]); diff --git a/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendevents/recording_sends_a_single_event.js b/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendevents/recording_sends_a_single_event.js index ffd251f0e8ea..da0749021af4 100644 --- a/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendevents/recording_sends_a_single_event.js +++ b/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendevents/recording_sends_a_single_event.js @@ -2,10 +2,10 @@ let nock = require('nock'); module.exports.hash = "93ae44857b9e0329bc4ac9a07e444214"; -module.exports.testInfo = {"uniqueName":{"singleEventId":"singleEventId159588373611301458"},"newDate":{"singleEventDate":"2020-07-27T21:02:16.113Z"}} +module.exports.testInfo = {"uniqueName":{"singleEventId":"singleEventId160161957273508409"},"newDate":{"singleEventDate":"2020-10-02T06:19:32.735Z"}} nock('https://endpoint', {"encodedQueryParams":true}) - .post('/api/events', [{"id":"singleEventId159588373611301458","subject":"Single 1","data":{"hello":"world"},"eventType":"Azure.Sdk.TestEvent1","eventTime":"2020-07-27T21:02:16.113Z","dataVersion":"1.0"}]) + .post('/api/events', [{"id":"singleEventId160161957273508409","subject":"Single 1","data":{"hello":"world"},"eventType":"Azure.Sdk.TestEvent1","eventTime":"2020-10-02T06:19:32.735Z","dataVersion":"1.0"}]) .query(true) .reply(200, "", [ 'Content-Length', @@ -17,7 +17,7 @@ nock('https://endpoint', {"encodedQueryParams":true}) 'api-supported-versions', '2018-01-01', 'x-ms-request-id', - 'ef70f7ba-868c-4cee-8c9b-e27e2c01409b', + 'd713b5c5-e878-4527-91f4-a4264f98124d', 'Date', - 'Mon, 27 Jul 2020 21:02:16 GMT' + 'Fri, 02 Oct 2020 06:19:33 GMT' ]); diff --git a/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendevents/recording_sends_multiple_events.js b/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendevents/recording_sends_multiple_events.js index 7f892aba5190..b5cb6c854196 100644 --- a/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendevents/recording_sends_multiple_events.js +++ b/sdk/eventgrid/eventgrid/recordings/node/eventgridpublisherclient_sendevents/recording_sends_multiple_events.js @@ -2,10 +2,10 @@ let nock = require('nock'); module.exports.hash = "b8c32c266a21a9129c07d237cc8e3d2b"; -module.exports.testInfo = {"uniqueName":{"multiEventId1":"multiEventId1159588373643900701","multiEventId2":"multiEventId2159588373643900216"},"newDate":{"multiEventDate1":"2020-07-27T21:02:16.439Z","multiEventDate2":"2020-07-27T21:02:16.439Z"}} +module.exports.testInfo = {"uniqueName":{"multiEventId1":"multiEventId1160161957303904323","multiEventId2":"multiEventId2160161957303900629"},"newDate":{"multiEventDate1":"2020-10-02T06:19:33.039Z","multiEventDate2":"2020-10-02T06:19:33.039Z"}} nock('https://endpoint', {"encodedQueryParams":true}) - .post('/api/events', [{"id":"multiEventId1159588373643900701","subject":"Multiple 1","data":{"hello":"world"},"eventType":"Azure.Sdk.TestEvent1","eventTime":"2020-07-27T21:02:16.439Z","dataVersion":"1.0"},{"id":"multiEventId2159588373643900216","subject":"Multiple 2","data":{"hello":"world"},"eventType":"Azure.Sdk.TestEvent1","eventTime":"2020-07-27T21:02:16.439Z","dataVersion":"1.0"}]) + .post('/api/events', [{"id":"multiEventId1160161957303904323","subject":"Multiple 1","data":{"hello":"world"},"eventType":"Azure.Sdk.TestEvent1","eventTime":"2020-10-02T06:19:33.039Z","dataVersion":"1.0"},{"id":"multiEventId2160161957303900629","subject":"Multiple 2","data":{"hello":"world"},"eventType":"Azure.Sdk.TestEvent1","eventTime":"2020-10-02T06:19:33.039Z","dataVersion":"1.0"}]) .query(true) .reply(200, "", [ 'Content-Length', @@ -17,7 +17,7 @@ nock('https://endpoint', {"encodedQueryParams":true}) 'api-supported-versions', '2018-01-01', 'x-ms-request-id', - '2ea7f5e7-f8cf-4051-8b39-353aaa531c12', + 'dfdb4176-a8de-4aa4-a900-c5b21303284f', 'Date', - 'Mon, 27 Jul 2020 21:02:16 GMT' + 'Fri, 02 Oct 2020 06:19:34 GMT' ]); diff --git a/sdk/eventgrid/eventgrid/src/cloudEventDistrubtedTracingEnricherPolicy.ts b/sdk/eventgrid/eventgrid/src/cloudEventDistrubtedTracingEnricherPolicy.ts new file mode 100644 index 000000000000..73792592aa03 --- /dev/null +++ b/sdk/eventgrid/eventgrid/src/cloudEventDistrubtedTracingEnricherPolicy.ts @@ -0,0 +1,72 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import { + HttpOperationResponse, + RequestPolicy, + RequestPolicyOptions, + RequestPolicyFactory, + WebResourceLike +} from "@azure/core-http"; + +export const CloudEventBatchContentType = "application/cloudevents-batch+json; charset=utf-8"; +export const TraceParentHeaderName = "traceparent"; +export const TraceStateHeaderName = "tracestate"; +export const ContentTypeHeaderName = "Content-Type"; + +export function cloudEventDistributedTracingEnricherPolicy(): RequestPolicyFactory { + return { + create: (nextPolicy: RequestPolicy, _options: RequestPolicyOptions) => { + return new CloudEventDistributedTracingEnricherPolicy(nextPolicy); + } + }; +} + +/** + * CloudEventDistributedTracingEnricherPolicy is a policy which adds distributed tracing information + * to a batch of cloud events. It does so by copying the `traceparent` and `tracestate` properties + * from the HTTP request into the individual events as extension properties. + * + * This will only happen in the case where an event does not have a `traceparent` defined already. This + * allows events to explicitly set a traceparent and tracestate which would be respected during "multi-hop + * transmition". + * + * See https://github.com/cloudevents/spec/blob/master/extensions/distributed-tracing.md + * for more information on distributed tracing and cloud events. + */ +export class CloudEventDistributedTracingEnricherPolicy implements RequestPolicy { + constructor(readonly _nextPolicy: RequestPolicy) {} + + sendRequest(httpRequest: WebResourceLike): Promise { + const traceparent = httpRequest.headers.get(TraceParentHeaderName); + const tracestate = httpRequest.headers.get(TraceStateHeaderName); + + if ( + httpRequest.headers.get(ContentTypeHeaderName) === CloudEventBatchContentType && + typeof httpRequest.body === "string" && + traceparent + ) { + // per the cloud event batched content type we know the body is an array encoded in JSON. + const parsedBody = JSON.parse(httpRequest.body) as any[]; + + for (const item of parsedBody) { + // When using the distributed tracing extension, the "traceparent" is a required property + // and "tracestate" is optional. This means if an item already has a "traceparent" property + // we should not stomp over it. Well formed events will not have a "tracestate" without + // also having a "traceparent" so there's no need to guard against that case. + if (typeof item !== "object" || item.traceparent) { + continue; + } + + item.traceparent = traceparent; + if (tracestate) { + item.tracestate = tracestate; + } + } + + httpRequest.body = JSON.stringify(parsedBody); + } + + return this._nextPolicy.sendRequest(httpRequest); + } +} diff --git a/sdk/eventgrid/eventgrid/src/eventGridClient.ts b/sdk/eventgrid/eventgrid/src/eventGridClient.ts index 04992c0421e3..4ca93dbec698 100644 --- a/sdk/eventgrid/eventgrid/src/eventGridClient.ts +++ b/sdk/eventgrid/eventgrid/src/eventGridClient.ts @@ -7,7 +7,9 @@ import { createPipelineFromOptions, OperationOptions, generateUuid, - HttpResponse + HttpResponse, + RequestPolicyFactory, + RestResponse } from "@azure/core-http"; import { createEventGridCredentialPolicy } from "./eventGridAuthenticationPolicy"; @@ -23,6 +25,9 @@ import { CloudEvent as CloudEventWireModel, EventGridEvent as EventGridEventWireModel } from "./generated/models"; +import { cloudEventDistributedTracingEnricherPolicy } from "./cloudEventDistrubtedTracingEnricherPolicy"; +import { createSpan } from "./tracing"; +import { CanonicalCode } from "@opentelemetry/api"; /** * Options for the Event Grid Client. @@ -110,6 +115,10 @@ export class EventGridPublisherClient { const authPolicy = createEventGridCredentialPolicy(credential); const pipeline = createPipelineFromOptions(options, authPolicy); + (pipeline.requestPolicyFactories as RequestPolicyFactory[]).push( + cloudEventDistributedTracingEnricherPolicy() + ); + this.client = new GeneratedClient(pipeline); this.apiVersion = this.client.apiVersion; } @@ -119,21 +128,28 @@ export class EventGridPublisherClient { * * @param message One or more events to publish */ - sendEvents( + async sendEvents( events: SendEventGridEventInput[], options?: SendEventsOptions ): Promise { - return this.client - .publishEvents( + const { span, updatedOptions } = createSpan( + "EventGridPublisherClient-sendEvents", + options || {} + ); + + try { + const r = await this.client.publishEvents( this.endpointUrl, (events || []).map(convertEventGridEventToModelType), - options - ) - .then((r) => { - return { - _response: r._response - }; - }); + updatedOptions + ); + return buildResponse(r); + } catch (e) { + span.setStatus({ code: CanonicalCode.UNKNOWN, message: e.message }); + throw e; + } finally { + span.end(); + } } /** @@ -141,21 +157,28 @@ export class EventGridPublisherClient { * * @param message One or more events to publish */ - sendCloudEvents( + async sendCloudEvents( events: SendCloudEventInput[], options?: SendCloudEventsOptions ): Promise { - return this.client - .publishCloudEventEvents( + const { span, updatedOptions } = createSpan( + "EventGridPublisherClient-sendCloudEvents", + options || {} + ); + + try { + const r = await this.client.publishCloudEventEvents( this.endpointUrl, (events || []).map(convertCloudEventToModelType), - options - ) - .then((r) => { - return { - _response: r._response - }; - }); + updatedOptions + ); + return buildResponse(r); + } catch (e) { + span.setStatus({ code: CanonicalCode.UNKNOWN, message: e.message }); + throw e; + } finally { + span.end(); + } } /** @@ -163,20 +186,41 @@ export class EventGridPublisherClient { * * @param message One or more events to publish */ - sendCustomSchemaEvents( + async sendCustomSchemaEvents( events: Record[], options?: SendCustomSchemaEventsOptions ): Promise { - return this.client - .publishCustomEventEvents(this.endpointUrl, events || [], options) - .then((r) => { - return { - _response: r._response - }; - }); + const { span, updatedOptions } = createSpan( + "EventGridPublisherClient-sendCustomSchemaEvents", + options || {} + ); + + try { + const r = await this.client.publishCustomEventEvents( + this.endpointUrl, + events || [], + updatedOptions + ); + return buildResponse(r); + } catch (e) { + span.setStatus({ code: CanonicalCode.UNKNOWN, message: e.message }); + throw e; + } finally { + span.end(); + } } } +function buildResponse(r: RestResponse): SendEventsResponse { + const ret = { _response: r._response }; + + Object.defineProperty(ret, "_response", { + enumerable: false + }); + + return ret; +} + /** * @internal */ diff --git a/sdk/eventgrid/eventgrid/src/generated/generatedClient.ts b/sdk/eventgrid/eventgrid/src/generated/generatedClient.ts index 80ed26cec84a..d0fbc81974b2 100644 --- a/sdk/eventgrid/eventgrid/src/generated/generatedClient.ts +++ b/sdk/eventgrid/eventgrid/src/generated/generatedClient.ts @@ -11,11 +11,7 @@ import * as Parameters from "./models/parameters"; import * as Models from "./models"; import * as Mappers from "./models/mappers"; import { GeneratedClientContext } from "./generatedClientContext"; -import { - GeneratedClientOptionalParams, - EventGridEvent, - CloudEvent -} from "./models"; +import { GeneratedClientOptionalParams, EventGridEvent, CloudEvent } from "./models"; class GeneratedClient extends GeneratedClientContext { /** diff --git a/sdk/eventgrid/eventgrid/src/tracing.ts b/sdk/eventgrid/eventgrid/src/tracing.ts new file mode 100644 index 000000000000..8d747dca28e0 --- /dev/null +++ b/sdk/eventgrid/eventgrid/src/tracing.ts @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import { getTracer } from "@azure/core-tracing"; +import { Span, SpanOptions, SpanKind } from "@opentelemetry/api"; +import { OperationOptions } from "@azure/core-http"; + +type OperationTracingOptions = OperationOptions["tracingOptions"]; + +/** + * Creates a span using the global tracer. + * @ignore + * @param name The name of the operation being performed. + * @param tracingOptions The options for the underlying http request. + */ +export function createSpan( + operationName: string, + operationOptions: T +): { span: Span; updatedOptions: T } { + const tracer = getTracer(); + const tracingOptions = operationOptions.tracingOptions || {}; + const spanOptions: SpanOptions = { + ...tracingOptions.spanOptions, + kind: SpanKind.INTERNAL + }; + + const span = tracer.startSpan(`Azure.Data.EventGrid.${operationName}`, spanOptions); + + span.setAttribute("az.namespace", "Microsoft.Messaging.EventGrid"); + + let newSpanOptions = tracingOptions.spanOptions || {}; + if (span.isRecording()) { + newSpanOptions = { + ...tracingOptions.spanOptions, + parent: span.context(), + attributes: { + ...spanOptions.attributes, + "az.namespace": "Microsoft.Data.EventGrid" + } + }; + } + + const newTracingOptions: OperationTracingOptions = { + ...tracingOptions, + spanOptions: newSpanOptions + }; + + const newOperationOptions: T = { + ...operationOptions, + tracingOptions: newTracingOptions + }; + + return { + span, + updatedOptions: newOperationOptions + }; +} diff --git a/sdk/eventgrid/eventgrid/test/cloudEventDistrubtedTracingEnricherPolicy.spec.ts b/sdk/eventgrid/eventgrid/test/cloudEventDistrubtedTracingEnricherPolicy.spec.ts new file mode 100644 index 000000000000..bd67611ff825 --- /dev/null +++ b/sdk/eventgrid/eventgrid/test/cloudEventDistrubtedTracingEnricherPolicy.spec.ts @@ -0,0 +1,122 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import { assert } from "chai"; +import { CloudEventDistributedTracingEnricherPolicy } from "../src/cloudEventDistrubtedTracingEnricherPolicy"; +import { + RequestPolicy, + WebResource, + WebResourceLike, + HttpOperationResponse +} from "@azure/core-http"; + +const CloudEventBatchContentType = "application/cloudevents-batch+json; charset=utf-8"; + +describe("CloudEventDistributedTracingEnricherPolicy", function() { + const emptyRequestPolicy: RequestPolicy = { + sendRequest(request: WebResourceLike): Promise { + return Promise.resolve({ request: request, status: 200, headers: request.headers }); + } + }; + + const TraceParentHeaderValue = "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"; + const TraceStateHeaderValue = + "rojo=00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01,congo=lZWRzIHRoNhcm5hbCBwbGVhc3VyZS4"; + + it("copies traceparent and tracestate as expected", async () => { + const policy = new CloudEventDistributedTracingEnricherPolicy(emptyRequestPolicy); + + const request = new WebResource(); + request.headers.set("content-type", CloudEventBatchContentType); + request.headers.set("traceparent", TraceParentHeaderValue); + request.headers.set("tracestate", TraceStateHeaderValue); + request.body = JSON.stringify([{}, {}]); + + const resp = await policy.sendRequest(request); + const parsedBody = JSON.parse(resp.request.body); + + assert.equal(parsedBody[0].traceparent, TraceParentHeaderValue); + assert.equal(parsedBody[0].tracestate, TraceStateHeaderValue); + assert.equal(parsedBody[1].traceparent, TraceParentHeaderValue); + assert.equal(parsedBody[1].tracestate, TraceStateHeaderValue); + }); + + it("does nothing when no distributed tracing headers exists", async () => { + const policy = new CloudEventDistributedTracingEnricherPolicy(emptyRequestPolicy); + + const request = new WebResource(); + request.headers.set("content-type", CloudEventBatchContentType); + request.body = JSON.stringify([{}, {}]); + + const resp = await policy.sendRequest(request); + const parsedBody = JSON.parse(resp.request.body); + + assert.isUndefined(parsedBody[0].traceparent); + assert.isUndefined(parsedBody[0].tracestate); + assert.isUndefined(parsedBody[1].traceparent); + assert.isUndefined(parsedBody[1].tracestate); + }); + + it("does not overwrite an existing traceparent or tracestate", async () => { + const policy = new CloudEventDistributedTracingEnricherPolicy(emptyRequestPolicy); + + const traceparent = "00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01"; + const tracestate = + "rojo=00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01,congo=lZWRzIHRoNhcm5hbCBwbGVhc3VyZS4"; + + const request = new WebResource(); + request.headers.set("content-type", CloudEventBatchContentType); + request.headers.set("traceparent", TraceParentHeaderValue); + request.headers.set("tracestate", TraceStateHeaderValue); + request.body = JSON.stringify([ + { + traceparent, + tracestate + }, + {} + ]); + + const resp = await policy.sendRequest(request); + const parsedBody = JSON.parse(resp.request.body); + + // The first event already had some tracing information, and it shouldn't be overwritten + assert.equal(parsedBody[0].traceparent, traceparent); + assert.equal(parsedBody[0].tracestate, tracestate); + + // The second event did not have tracing information, so it should be set to the values + // from the request. + assert.equal(parsedBody[1].traceparent, TraceParentHeaderValue); + assert.equal(parsedBody[1].tracestate, TraceStateHeaderValue); + }); + + it("only enriches requests with the cloud event content type", async () => { + const policy = new CloudEventDistributedTracingEnricherPolicy(emptyRequestPolicy); + + const request = new WebResource(); + request.headers.set("content-type", "application/json"); + request.headers.set("traceparent", TraceParentHeaderValue); + request.headers.set("tracestate", TraceStateHeaderValue); + request.body = JSON.stringify([{}, {}]); + + const resp = await policy.sendRequest(request); + + assert.isUndefined(resp.request.body[0].traceparent); + assert.isUndefined(resp.request.body[0].tracestate); + assert.isUndefined(resp.request.body[1].traceparent); + assert.isUndefined(resp.request.body[1].tracestate); + }); + + it("does not fail when there are no events", async () => { + const policy = new CloudEventDistributedTracingEnricherPolicy(emptyRequestPolicy); + + const request = new WebResource(); + request.headers.set("content-type", CloudEventBatchContentType); + request.headers.set("traceparent", TraceParentHeaderValue); + request.headers.set("tracestate", TraceStateHeaderValue); + request.body = JSON.stringify([]); + + const resp = await policy.sendRequest(request); + + assert.equal(resp.request.body, JSON.stringify([])); + }); +}); diff --git a/sdk/eventgrid/eventgrid/test/eventGridClient.spec.ts b/sdk/eventgrid/eventgrid/test/eventGridClient.spec.ts index 4960cc10be96..dd4295717923 100644 --- a/sdk/eventgrid/eventgrid/test/eventGridClient.spec.ts +++ b/sdk/eventgrid/eventgrid/test/eventGridClient.spec.ts @@ -8,6 +8,8 @@ import { Recorder } from "@azure/test-utils-recorder"; import { createRecordedClient, testEnv } from "./utils/recordedClient"; +import { TestTracer, setTracer } from "@azure/core-tracing"; + import { AzureKeyCredential, EventGridPublisherClient } from "../src/index"; import { @@ -134,6 +136,48 @@ describe("EventGridPublisherClient", function() { assert.equal(res._response.status, 200); }); + + it("enriches events with distributed tracing information", async () => { + const tracer = new TestTracer(); + setTracer(tracer); + const rootSpan = tracer.startSpan("root"); + + const res = await client.sendCloudEvents( + [ + { + type: "Azure.Sdk.TestEvent1", + id: recorder.getUniqueName("cloudTracingEventId"), + time: recorder.newDate("cloudTracingEventDate"), + source: "/earth/unitedstates/washington/kirkland/finnhill", + subject: "Single with Trace Parent", + data: { + hello: "world" + } + } + ], + { + tracingOptions: { + spanOptions: { + parent: rootSpan.context() + } + } + } + ); + + rootSpan.end(); + + const parsedBody = JSON.parse(res._response.request.body); + + assert.isArray(parsedBody); + assert.equal(parsedBody[0].traceparent, "00-1-3-00"); + + const spans = tracer.getKnownSpans(); + + assert.equal(spans.length, 3); + assert.equal(spans[0].name, "root"); + assert.equal(spans[1].name, "Azure.Data.EventGrid.EventGridPublisherClient-sendCloudEvents"); + assert.equal(spans[2].name, "/api/events"); + }); }); describe("#sendCustomSchemaEvents", function() {