1414 * limitations under the License.
1515 */
1616
17- import { CoreTracer , globalStats , HeaderGetter , HeaderSetter , logger , Measurement , MessageEventType , Propagation , Span , SpanContext , SpanEventListener , StatsEventListener , TagKey , TagMap , TagValue , View } from '@opencensus/core' ;
17+ import { CoreTracer , globalStats , HeaderGetter , HeaderSetter , logger , Measurement , MessageEventType , Propagation , Span , SpanContext , SpanEventListener , SpanKind , StatsEventListener , TagKey , TagMap , TagValue , View } from '@opencensus/core' ;
1818import * as assert from 'assert' ;
1919import * as http from 'http' ;
2020import * as nock from 'nock' ;
@@ -31,6 +31,12 @@ function doNock(
3131 nock ( url ) . get ( path ) . times ( i ) . reply ( httpCode , respBody ) ;
3232}
3333
34+ function customAttributeFunction (
35+ span : Span , request : http . ClientRequest | http . IncomingMessage ,
36+ response : http . IncomingMessage | http . ServerResponse ) : void {
37+ span . addAttribute ( 'span kind' , span . kind ) ;
38+ }
39+
3440class TestExporter implements StatsEventListener {
3541 registeredViews : View [ ] = [ ] ;
3642 recordedMeasurements : Measurement [ ] = [ ] ;
@@ -123,6 +129,11 @@ function assertSpanAttributes(
123129 `${ httpStatusCode } ` ) ;
124130}
125131
132+ function assertCustomAttribute (
133+ span : Span , attributeName : string , attributeValue : SpanKind ) {
134+ assert . strictEqual ( span . attributes [ attributeName ] , attributeValue ) ;
135+ }
136+
126137function assertClientStats (
127138 testExporter : TestExporter , httpStatusCode : number , httpMethod : string ) {
128139 const tags = new TagMap ( ) ;
@@ -161,8 +172,11 @@ describe('HttpPlugin', () => {
161172 const log = logger . logger ( ) ;
162173 const tracer = new CoreTracer ( ) ;
163174 const spanVerifier = new SpanVerifier ( ) ;
164- tracer . start (
165- { samplingRate : 1 , logger : log , propagation : new DummyPropagation ( ) } ) ;
175+ tracer . start ( {
176+ samplingRate : 1 ,
177+ logger : log ,
178+ propagation : new DummyPropagation ( ) ,
179+ } ) ;
166180 const testExporter = new TestExporter ( ) ;
167181
168182 it ( 'should return a plugin' , ( ) => {
@@ -180,7 +194,8 @@ describe('HttpPlugin', () => {
180194 `${ urlHost } /ignored/string` ,
181195 / ^ h t t p : \/ \/ f a k e \. s e r v i c e \. i o \/ i g n o r e d \/ r e g e x p $ / ,
182196 ( url : string ) => url === `${ urlHost } /ignored/function`
183- ]
197+ ] ,
198+ applyCustomAttributesOnSpan : customAttributeFunction
184199 } ,
185200 '' , globalStats ) ;
186201 tracer . registerSpanEventListener ( spanVerifier ) ;
@@ -374,6 +389,19 @@ describe('HttpPlugin', () => {
374389 nock . disableNetConnect ( ) ;
375390 } ) ;
376391
392+ it ( 'custom attributes should show up on client spans' , async ( ) => {
393+ nock . enableNetConnect ( ) ;
394+ assert . strictEqual ( spanVerifier . endedSpans . length , 0 ) ;
395+ await httpRequest . get ( `http://google.fr/` ) . then ( ( result ) => {
396+ assert . strictEqual ( spanVerifier . endedSpans . length , 1 ) ;
397+ assert . ok ( spanVerifier . endedSpans [ 0 ] . name . indexOf ( 'GET /' ) >= 0 ) ;
398+
399+ const span = spanVerifier . endedSpans [ 0 ] ;
400+ assertCustomAttribute ( span , 'span kind' , SpanKind . CLIENT ) ;
401+ } ) ;
402+ nock . disableNetConnect ( ) ;
403+ } ) ;
404+
377405 it ( 'should create a rootSpan for GET requests and add propagation headers with Expect headers' ,
378406 async ( ) => {
379407 nock . enableNetConnect ( ) ;
@@ -450,6 +478,29 @@ describe('HttpPlugin', () => {
450478 } ) ;
451479 } ) ;
452480
481+ it ( 'custom attributes should show up on server spans' , async ( ) => {
482+ const testPath = '/incoming/rootSpan/' ;
483+
484+ const options = {
485+ host : 'localhost' ,
486+ path : testPath ,
487+ port : serverPort ,
488+ headers : { 'User-Agent' : 'Android' }
489+ } ;
490+ shimmer . unwrap ( http , 'get' ) ;
491+ shimmer . unwrap ( http , 'request' ) ;
492+ nock . enableNetConnect ( ) ;
493+
494+ assert . strictEqual ( spanVerifier . endedSpans . length , 0 ) ;
495+
496+ await httpRequest . get ( options ) . then ( ( result ) => {
497+ assert . ok ( spanVerifier . endedSpans [ 0 ] . name . indexOf ( testPath ) >= 0 ) ;
498+ assert . strictEqual ( spanVerifier . endedSpans . length , 1 ) ;
499+ const span = spanVerifier . endedSpans [ 0 ] ;
500+ assertCustomAttribute ( span , 'span kind' , SpanKind . SERVER ) ;
501+ } ) ;
502+ } ) ;
503+
453504 for ( const ignored of [ 'string' , 'function' , 'regexp' ] ) {
454505 it ( `should not trace ignored requests with type ${ ignored } ` , async ( ) => {
455506 const testPath = `/ignored/${ ignored } ` ;
0 commit comments