@@ -20,7 +20,6 @@ import * as http from 'http';
2020import * as nock from 'nock' ;
2121import * as shimmer from 'shimmer' ;
2222import * as url from 'url' ;
23-
2423import { HttpPlugin , plugin } from '../src/' ;
2524import * as stats from '../src/http-stats' ;
2625
@@ -135,10 +134,18 @@ function assertCustomAttribute(
135134}
136135
137136function assertClientStats (
138- testExporter : TestExporter , httpStatusCode : number , httpMethod : string ) {
137+ testExporter : TestExporter , httpStatusCode : number , httpMethod : string ,
138+ tagCtx ?: TagMap ) {
139139 const tags = new TagMap ( ) ;
140140 tags . set ( stats . HTTP_CLIENT_METHOD , { value : httpMethod } ) ;
141141 tags . set ( stats . HTTP_CLIENT_STATUS , { value : `${ httpStatusCode } ` } ) ;
142+
143+ if ( tagCtx ) {
144+ tagCtx . tags . forEach ( ( tagValue : TagValue , tagKey : TagKey ) => {
145+ tags . set ( tagKey , tagValue ) ;
146+ } ) ;
147+ }
148+
142149 assert . strictEqual ( testExporter . registeredViews . length , 8 ) ;
143150 assert . strictEqual ( testExporter . recordedMeasurements . length , 1 ) ;
144151 assert . strictEqual (
@@ -150,11 +157,18 @@ function assertClientStats(
150157
151158function assertServerStats (
152159 testExporter : TestExporter , httpStatusCode : number , httpMethod : string ,
153- path : string ) {
160+ path : string , tagCtx ?: TagMap ) {
154161 const tags = new TagMap ( ) ;
155162 tags . set ( stats . HTTP_SERVER_METHOD , { value : httpMethod } ) ;
156163 tags . set ( stats . HTTP_SERVER_STATUS , { value : `${ httpStatusCode } ` } ) ;
157164 tags . set ( stats . HTTP_SERVER_ROUTE , { value : path } ) ;
165+
166+ if ( tagCtx ) {
167+ tagCtx . tags . forEach ( ( tagValue : TagValue , tagKey : TagKey ) => {
168+ tags . set ( tagKey , tagValue ) ;
169+ } ) ;
170+ }
171+
158172 assert . strictEqual ( testExporter . registeredViews . length , 8 ) ;
159173 assert . strictEqual ( testExporter . recordedMeasurements . length , 1 ) ;
160174 assert . strictEqual (
@@ -269,7 +283,6 @@ describe('HttpPlugin', () => {
269283 } ) ;
270284 }
271285
272-
273286 it ( 'should create a child span for GET requests' , ( ) => {
274287 const testPath = '/outgoing/rootSpan/childs/1' ;
275288 doNock ( urlHost , testPath , 200 , 'Ok' ) ;
@@ -290,6 +303,60 @@ describe('HttpPlugin', () => {
290303 } ) ;
291304 } ) ;
292305
306+ it ( 'should create a child span for GET requests with tag context' , ( ) => {
307+ const testPath = '/outgoing/rootSpan/childs/1' ;
308+ doNock ( urlHost , testPath , 200 , 'Ok' ) ;
309+ const tags = new TagMap ( ) ;
310+ tags . set ( { name : 'testKey1' } , { value : 'value1' } ) ;
311+ tags . set ( { name : 'testKey2' } , { value : 'value2' } ) ;
312+ return globalStats . withTagContext ( tags , async ( ) => {
313+ return tracer . startRootSpan (
314+ { name : 'TestRootSpan' } , async ( root : Span ) => {
315+ await httpRequest . get ( `${ urlHost } ${ testPath } ` ) . then ( ( result ) => {
316+ assert . ok ( root . name . indexOf ( 'TestRootSpan' ) >= 0 ) ;
317+ assert . strictEqual ( root . spans . length , 1 ) ;
318+ const [ span ] = root . spans ;
319+ assert . ok ( span . name . indexOf ( testPath ) >= 0 ) ;
320+ assert . strictEqual ( root . traceId , span . traceId ) ;
321+ assertSpanAttributes ( span , 200 , 'GET' , hostName , testPath ) ;
322+ assert . strictEqual ( span . messageEvents . length , 1 ) ;
323+ const [ messageEvent ] = span . messageEvents ;
324+ assert . strictEqual ( messageEvent . type , MessageEventType . SENT ) ;
325+ assert . strictEqual ( messageEvent . id , 1 ) ;
326+ assertClientStats ( testExporter , 200 , 'GET' , tags ) ;
327+ } ) ;
328+ } ) ;
329+ } ) ;
330+ } ) ;
331+
332+ it ( 'should create a child span for GET requests with empty tag context' ,
333+ ( ) => {
334+ const testPath = '/outgoing/rootSpan/childs/1' ;
335+ doNock ( urlHost , testPath , 200 , 'Ok' ) ;
336+ const tags = new TagMap ( ) ;
337+ return globalStats . withTagContext ( tags , async ( ) => {
338+ return tracer . startRootSpan (
339+ { name : 'TestRootSpan' } , async ( root : Span ) => {
340+ await httpRequest . get ( `${ urlHost } ${ testPath } ` )
341+ . then ( ( result ) => {
342+ assert . ok ( root . name . indexOf ( 'TestRootSpan' ) >= 0 ) ;
343+ assert . strictEqual ( root . spans . length , 1 ) ;
344+ const [ span ] = root . spans ;
345+ assert . ok ( span . name . indexOf ( testPath ) >= 0 ) ;
346+ assert . strictEqual ( root . traceId , span . traceId ) ;
347+ assertSpanAttributes (
348+ span , 200 , 'GET' , hostName , testPath ) ;
349+ assert . strictEqual ( span . messageEvents . length , 1 ) ;
350+ const [ messageEvent ] = span . messageEvents ;
351+ assert . strictEqual (
352+ messageEvent . type , MessageEventType . SENT ) ;
353+ assert . strictEqual ( messageEvent . id , 1 ) ;
354+ assertClientStats ( testExporter , 200 , 'GET' ) ;
355+ } ) ;
356+ } ) ;
357+ } ) ;
358+ } ) ;
359+
293360 for ( let i = 0 ; i < httpErrorCodes . length ; i ++ ) {
294361 it ( `should test a child spans for GET requests with http error ${
295362 httpErrorCodes [ i ] } `,
@@ -449,6 +516,38 @@ describe('HttpPlugin', () => {
449516 } ) ;
450517 } ) ;
451518
519+ it ( 'should create a root span for incoming requests with Correlation Context header' ,
520+ async ( ) => {
521+ const testPath = '/incoming/rootSpan/' ;
522+ const options = {
523+ host : 'localhost' ,
524+ path : testPath ,
525+ port : serverPort ,
526+ headers :
527+ { 'User-Agent' : 'Android' , 'Correlation-Context' : 'k1=v1,k2=v2' }
528+ } ;
529+
530+ const expectedTagsFromHeaders = new TagMap ( ) ;
531+ expectedTagsFromHeaders . set ( { name : 'k1' } , { value : 'v1' } ) ;
532+ expectedTagsFromHeaders . set ( { name : 'k2' } , { value : 'v2' } ) ;
533+
534+ shimmer . unwrap ( http , 'get' ) ;
535+ shimmer . unwrap ( http , 'request' ) ;
536+ nock . enableNetConnect ( ) ;
537+
538+ assert . strictEqual ( spanVerifier . endedSpans . length , 0 ) ;
539+
540+ await httpRequest . get ( options ) . then ( ( result ) => {
541+ assert . ok ( spanVerifier . endedSpans [ 0 ] . name . indexOf ( testPath ) >= 0 ) ;
542+ assert . strictEqual ( spanVerifier . endedSpans . length , 1 ) ;
543+ const [ span ] = spanVerifier . endedSpans ;
544+ assertSpanAttributes (
545+ span , 200 , 'GET' , 'localhost' , testPath , 'Android' ) ;
546+ assertServerStats (
547+ testExporter , 200 , 'GET' , testPath , expectedTagsFromHeaders ) ;
548+ } ) ;
549+ } ) ;
550+
452551 it ( 'should handle incoming requests with long request url path' ,
453552 async ( ) => {
454553 const testPath = '/test&code=' +
0 commit comments