22
33A partial implementation of the [ OpenTracing JavaScript API] ( https://opentracing-javascript.surge.sh ) for [ honeycomb.io] ( https://www.honeycomb.io ) backend.
44
5-
6- [ ![ homecomb-ui] ( https://user-images.githubusercontent.com/229881/53273403-ed56fd80-36c1-11e9-95b5-d5277bb621ff.png )] ( https://ui.honeycomb.io )
5+ [ ![ homecomb-ui] ( https://user-images.githubusercontent.com/229881/53371218-a1a09000-391d-11e9-9956-8ee2b5d62a0f.png )] ( https://ui.honeycomb.io )
76
87## Usage
98
109``` ts
11- import { Tracer } from ' @zeit/tracing-js' ;
10+ import { IncomingMessage , ServerResponse , createServer } from ' http' ;
11+ import { Tracer , SpanContext , Tags , DeterministicSampler } from ' @zeit/tracing-js' ;
1212
13- const tracer = new Tracer (' service-name' , {
14- writeKey: process .env .HONEYCOMB_KEY ,
15- dataset: process .env .HONEYCOMB_DATASET
16- });
13+ const tracer = new Tracer (
14+ {
15+ serviceName: ' routing-example' ,
16+ environment: process .env .ENVIRONMENT ,
17+ dc: process .env .DC ,
18+ podName: process .env .PODNAME ,
19+ hostName: process .env .HOSTNAME ,
20+ sampler: new DeterministicSampler (process .env .TRACE_SAMPLE_RATE ),
21+ },
22+ {
23+ writeKey: process .env .HONEYCOMB_KEY ! ,
24+ dataset: process .env .HONEYCOMB_DATASET ! ,
25+ },
26+ );
1727
1828// example child function we wish to trace
19- async function sleep(ms , parentSpan ) {
20- const span = tracer .startSpan (sleep .name , { childOf: parentSpan });
21- return new Promise (resolve =>
22- setTimeout (() => {
23- span .finish ();
24- resolve ();
25- }, ms )
26- );
29+ async function sleep(ms : number , childOf : SpanContext ) {
30+ const span = tracer .startSpan (sleep .name , { childOf });
31+ return new Promise (resolve =>
32+ setTimeout (() => {
33+ span .finish ();
34+ resolve ();
35+ }, ms ),
36+ );
2737}
2838
29- // example parent function we wish to trace
30- async function handler(req , res ) {
31- const span = tracer .startSpan (handler .name );
32- await sleep (300 , span );
33- console .log (' end trace' );
39+ // example child function we wish to trace
40+ async function route(path : string , childOf : SpanContext ) {
41+ const span = tracer .startSpan (route .name , { childOf });
42+ const spanContext = span .context ();
43+
44+ await sleep (200 , spanContext );
45+
46+ if (! path || path === ' /' ) {
3447 span .finish ();
35- };
48+ return ' Home page' ;
49+ } else if (path === ' /next' ) {
50+ span .finish ();
51+ return ' Next page' ;
52+ }
53+
54+ span .finish ();
55+ throw new Error (' Page not found' );
56+ }
57+
58+ // example parent function we wish to trace
59+ async function handler(req : IncomingMessage , res : ServerResponse ) {
60+ const { tags, childOf } = parseRequest (req );
61+ const span = tracer .startSpan (handler .name , { tags , childOf });
62+ const spanContext = span .context ();
63+ let statusCode = 200 ;
64+
65+ try {
66+ const { url = ' /' } = req ;
67+ await sleep (100 , spanContext );
68+ const output = await route (url , spanContext );
69+ res .write (output );
70+ } catch (error ) {
71+ statusCode = 500 ;
72+ tags [Tags .ERROR ] = true ;
73+ res .write (error .message );
74+ }
75+
76+ tags [Tags .HTTP_STATUS_CODE ] = statusCode ;
77+ res .statusCode = statusCode ;
78+ res .end ();
79+ span .finish ();
80+ }
81+
82+ function getFirstHeader(req : IncomingMessage , key : string ) {
83+ const value = req .headers [key ];
84+ return Array .isArray (value ) ? value [0 ] : value ;
85+ }
86+
87+ function parseRequest(req : IncomingMessage ) {
88+ const tags: { [key : string ]: any } = {};
89+ tags [Tags .HTTP_METHOD ] = req .method ;
90+ tags [Tags .HTTP_URL ] = req .url ;
91+
92+ const priority = getFirstHeader (req , ' x-now-trace-priority' );
93+ if (typeof priority !== ' undefined' ) {
94+ tags [Tags .SAMPLING_PRIORITY ] = Number .parseInt (priority );
95+ }
96+
97+ let childOf: SpanContext | undefined ;
98+ const traceId = getFirstHeader (req , ' x-now-id' );
99+ const parentId = getFirstHeader (req , ' x-now-parent-id' );
100+ if (traceId ) {
101+ childOf = new SpanContext (traceId , parentId , tags );
102+ }
103+
104+ return { tags , childOf };
105+ }
36106
37- handler (' req' , ' res' )
38- .then (() => console .log (' done' ))
39- .catch (e => console .error (e ));
107+ createServer (handler ).listen (3000 );
40108```
41109
42110## Connecting traces across multiple services
@@ -45,10 +113,10 @@ You can set a parent trace, even if you don't have a reference to the `Span` obj
45113
46114Instead, you can create a new ` SpanContext ` .
47115
48- You'll need the ` parentTraceId ` and ` parentSpanId ` (typically found in ` req.headers ` ).
116+ You'll need the ` traceId ` and ` parentSpanId ` (typically found in ` req.headers ` ).
49117
50118``` ts
51- const context = new SpanContext (parentTraceId , parentSpanId );
119+ const context = new SpanContext (traceId , parentSpanId );
52120const childSpan = tracer .startSpan (' child' , { childOf: context });
53121// ...do stuff like normal
54122childSpan .finish ();
0 commit comments