rian 0.2.4 → 0.3.0-next.1
Sign up to get free protection for your applications and to get access to all the features.
- package/exporter.otel.http/index.js +1 -1
- package/exporter.otel.http/index.mjs +1 -1
- package/exporter.zipkin/index.js +1 -1
- package/exporter.zipkin/index.mjs +1 -1
- package/index.d.ts +5 -3
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/package.json +1 -1
- package/readme.md +18 -61
- package/utils/index.d.ts +9 -11
- package/utils/index.js +1 -1
- package/utils/index.mjs +1 -1
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
var e=r=>{let n=typeof r,a={};return"string"===n?a.stringValue=r:"number"===n?Number.isInteger(r)?a.intValue=r:a.doubleValue=r:"boolean"===n?a.boolValue=r:Array.isArray(r)?a.arrayValue={values:r.map((t=>e(t)))}:r&&(a.kvlistValue={values:t(r)}),a},t=t=>{let r=[];for(let n of Object.keys(t))r.push({key:n,value:e(t[n])});return r},r=e=>{switch(e){default:case"INTERNAL":return 1;case"SERVER":return 2;case"CLIENT":return 3;case"PRODUCER":return 4;case"CONSUMER":return 5}},n=e=>(n,a)=>{let s=[];for(let e of n){let n,{kind:a,error:u,...i}=e.context;u&&(n={code:2},"message"in u&&(n.message=u.message)),s.push({traceId:e.id.trace_id,spanId:e.id.parent_id,parentSpanId:e.parent?.parent_id,name:e.name,kind:r(a||"INTERNAL"),startTimeUnixNano:1e6*e.start,endTimeUnixNano:e.end?1e6*e.end:void 0,droppedAttributesCount:0,droppedEventsCount:0,droppedLinksCount:0,attributes:t(i),status:n||{code:0},events:e.events.map((e=>({name:e.name,attributes:t(e.attributes),droppedAttributesCount:0,timeUnixNano:1e6*e.timestamp})))})}return e({resourceSpans:[{resource:{attributes:t(a),droppedAttributesCount:0},instrumentationLibrarySpans:[{instrumentationLibrary:{name:"rian",version:"0.3.0-next.1"},spans:s}]}]})};exports.exporter=n;
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
var e=r=>{let n=typeof r,a={};return"string"===n?a.stringValue=r:"number"===n?Number.isInteger(r)?a.intValue=r:a.doubleValue=r:"boolean"===n?a.boolValue=r:Array.isArray(r)?a.arrayValue={values:r.map((t=>e(t)))}:r&&(a.kvlistValue={values:t(r)}),a},t=t=>{let r=[];for(let n of Object.keys(t))r.push({key:n,value:e(t[n])});return r},r=e=>{switch(e){default:case"INTERNAL":return 1;case"SERVER":return 2;case"CLIENT":return 3;case"PRODUCER":return 4;case"CONSUMER":return 5}},n=e=>(n,a)=>{let s=[];for(let e of n){let n,{kind:a,error:u,...i}=e.context;u&&(n={code:2},"message"in u&&(n.message=u.message)),s.push({traceId:e.id.trace_id,spanId:e.id.parent_id,parentSpanId:e.parent?.parent_id,name:e.name,kind:r(a||"INTERNAL"),startTimeUnixNano:1e6*e.start,endTimeUnixNano:e.end?1e6*e.end:void 0,droppedAttributesCount:0,droppedEventsCount:0,droppedLinksCount:0,attributes:t(i),status:n||{code:0},events:e.events.map((e=>({name:e.name,attributes:t(e.attributes),droppedAttributesCount:0,timeUnixNano:1e6*e.timestamp})))})}return e({resourceSpans:[{resource:{attributes:t(a),droppedAttributesCount:0},instrumentationLibrarySpans:[{instrumentationLibrary:{name:"rian",version:"0.3.0-next.1"},spans:s}]}]})};export{n as exporter};
|
package/exporter.zipkin/index.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
const { flattie:e } = require('flattie');var t=t=>(a,
|
1
|
+
const { flattie:e } = require('flattie');var t=t=>(a,r)=>{let n=[];for(let t of a){let{kind:a,error:i,...s}=t.context;i&&(s.error=!("message"in i)||{name:i.name,message:i.message,stack:i.stack}),n.push({id:t.id.parent_id,traceId:t.id.trace_id,parentId:t.parent?t.parent.parent_id:void 0,name:t.name,kind:"INTERNAL"===a?void 0:a,timestamp:1e3*t.start,duration:t.end?1e3*(t.end-t.start):void 0,localEndpoint:{serviceName:r["service.name"]},tags:e({...r,...s},".",!0),annotations:t.events.map((e=>({value:`${e.name} :: ${JSON.stringify(e.attributes)}`,timestamp:1e3*e.timestamp})))})}return t(n)};exports.exporter=t;
|
@@ -1 +1 @@
|
|
1
|
-
import{flattie as e}from"flattie";var t=t=>(a,
|
1
|
+
import{flattie as e}from"flattie";var t=t=>(a,r)=>{let n=[];for(let t of a){let{kind:a,error:i,...s}=t.context;i&&(s.error=!("message"in i)||{name:i.name,message:i.message,stack:i.stack}),n.push({id:t.id.parent_id,traceId:t.id.trace_id,parentId:t.parent?t.parent.parent_id:void 0,name:t.name,kind:"INTERNAL"===a?void 0:a,timestamp:1e3*t.start,duration:t.end?1e3*(t.end-t.start):void 0,localEndpoint:{serviceName:r["service.name"]},tags:e({...r,...s},".",!0),annotations:t.events.map((e=>({value:`${e.name} :: ${JSON.stringify(e.attributes)}`,timestamp:1e3*e.timestamp})))})}return t(n)};export{t as exporter};
|
package/index.d.ts
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
import type { Traceparent } from 'tctx';
|
2
|
+
|
1
3
|
/**
|
2
4
|
* Spans are units within a distributed trace. Spans encapsulate mainly 3 pieces of information, a
|
3
5
|
* {@link Span.name|name}, and a {@link Span.start|start} and {@link Span.end|end} time.
|
@@ -93,7 +95,7 @@ export interface Scope {
|
|
93
95
|
/**
|
94
96
|
* Forks the span into a new child span.
|
95
97
|
*/
|
96
|
-
|
98
|
+
span(name: string): CallableScope;
|
97
99
|
|
98
100
|
/**
|
99
101
|
* Allows the span's context to be set. Passing an object will be `Object.assign`ed into the
|
@@ -116,8 +118,8 @@ export interface Scope {
|
|
116
118
|
end(): void;
|
117
119
|
}
|
118
120
|
|
119
|
-
export interface Tracer extends
|
120
|
-
|
121
|
+
export interface Tracer extends Pick<Scope, 'span'> {
|
122
|
+
report(): ReturnType<Exporter>;
|
121
123
|
}
|
122
124
|
|
123
125
|
/**
|
package/index.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
const { measureFn:e } = require('rian/utils');const t = require('tctx');var n=(e,n)=>!n||t.is_sampled(n),a=
|
1
|
+
const { measureFn:e } = require('rian/utils');const t = require('tctx');var n=(e,n)=>!n||t.is_sampled(n),a=(a,r)=>{let o=new Set,s=new Set,i=r.sampler||n,d="boolean"!=typeof i,p=r.context||{};p["service.name"]=a,p["telemetry.sdk.name"]="rian",p["telemetry.sdk.version"]="0.3.0-next.1";let m="string"==typeof r.traceparent?t.parse(r.traceparent):void 0,c=(n,a)=>{let p=d?i(n,a,r.context):i,m=a?a.child(p):t.make(p),l={id:m,parent:a,start:Date.now(),name:n,events:[],context:{}};p&&o.add(l);let x=t=>e(x,t);return x.traceparent=m,x.span=e=>c(e,m),x.set_context=e=>"function"==typeof e?void(l.context=e(l.context)):void Object.assign(l.context,e),x.add_event=(e,t)=>{l.events.push({name:e,timestamp:Date.now(),attributes:t||{}})},x.end=()=>{null==l.end&&(l.end=Date.now())},x.__add_promise=s.add.bind(s),x};return{span:e=>c(e,m),report:async()=>(s.size>0&&await Promise.all([...s.values()]),r.exporter(o,p))}};exports.create=a;
|
package/index.mjs
CHANGED
@@ -1 +1 @@
|
|
1
|
-
import{measureFn as e}from"rian/utils";import*as t from"tctx";var n=(e,n)=>!n||t.is_sampled(n),a=
|
1
|
+
import{measureFn as e}from"rian/utils";import*as t from"tctx";var n=(e,n)=>!n||t.is_sampled(n),a=(a,r)=>{let o=new Set,s=new Set,i=r.sampler||n,d="boolean"!=typeof i,p=r.context||{};p["service.name"]=a,p["telemetry.sdk.name"]="rian",p["telemetry.sdk.version"]="0.3.0-next.1";let m="string"==typeof r.traceparent?t.parse(r.traceparent):void 0,c=(n,a)=>{let p=d?i(n,a,r.context):i,m=a?a.child(p):t.make(p),l={id:m,parent:a,start:Date.now(),name:n,events:[],context:{}};p&&o.add(l);let x=t=>e(x,t);return x.traceparent=m,x.span=e=>c(e,m),x.set_context=e=>"function"==typeof e?void(l.context=e(l.context)):void Object.assign(l.context,e),x.add_event=(e,t)=>{l.events.push({name:e,timestamp:Date.now(),attributes:t||{}})},x.end=()=>{null==l.end&&(l.end=Date.now())},x.__add_promise=s.add.bind(s),x};return{span:e=>c(e,m),report:async()=>(s.size>0&&await Promise.all([...s.values()]),r.exporter(o,p))}};export{a as create};
|
package/package.json
CHANGED
package/readme.md
CHANGED
@@ -28,7 +28,7 @@
|
|
28
28
|
|
29
29
|
- 🤔 **Familiar** — looks very much like OpenTracing.
|
30
30
|
|
31
|
-
- ✅ **Simple** — `create` a tracer, and `.
|
31
|
+
- ✅ **Simple** — `create` a tracer, and `.report()` a tracer, done.
|
32
32
|
|
33
33
|
- 🏎 **Performant** — check the [benchmarks](#-benchmark).
|
34
34
|
|
@@ -52,21 +52,23 @@ const otel_endpoint = exporter((payload) =>
|
|
52
52
|
);
|
53
53
|
|
54
54
|
// ~> Create a tracer — typically "per request" or "per operation"
|
55
|
-
const tracer = create('
|
55
|
+
const tracer = create('my-service', {
|
56
56
|
exporter: otel_endpoint,
|
57
57
|
});
|
58
58
|
|
59
59
|
// Let us trace
|
60
60
|
|
61
|
-
tracer.
|
61
|
+
const req = tracer.span('GET ~> /data');
|
62
|
+
|
63
|
+
req.set_context({
|
62
64
|
user: request_context.user_id,
|
63
65
|
});
|
64
66
|
|
65
67
|
// ~> Wrap any method and be timed 🕺🏻
|
66
|
-
const data = await measure(
|
68
|
+
const data = await measure(req.span('db::read'), get_data);
|
67
69
|
|
68
70
|
// ~> Maybe have some in-flow spanning
|
69
|
-
const span =
|
71
|
+
const span = req.span('process records');
|
70
72
|
|
71
73
|
for (let row of data) {
|
72
74
|
span.add_event('doing stuff', { id: row.id });
|
@@ -75,8 +77,10 @@ for (let row of data) {
|
|
75
77
|
|
76
78
|
span.end();
|
77
79
|
|
80
|
+
req.end();
|
81
|
+
|
78
82
|
// ~> And finally let's export — will also end the root span.
|
79
|
-
await tracer.
|
83
|
+
await tracer.report();
|
80
84
|
|
81
85
|
/*
|
82
86
|
And we end up with something like this in our reporting tool:
|
@@ -101,50 +105,10 @@ The main and _default_ module responsible for creating and provisioning spans.
|
|
101
105
|
|
102
106
|
Exports the spans created using the zipkin protocol and leaves the shipping up to you.
|
103
107
|
|
104
|
-
> 💡 Note ~> with the nature of zipkin, the `localEndpoint` must be set in your span context.
|
105
|
-
>
|
106
|
-
> <details><summary>Example</summary>
|
107
|
-
>
|
108
|
-
> ```ts
|
109
|
-
> const tracer = create('example', {
|
110
|
-
> context: {
|
111
|
-
> localEndpoint: {
|
112
|
-
> serviceName: 'my-service', // 👈 important part
|
113
|
-
> },
|
114
|
-
> },
|
115
|
-
> });
|
116
|
-
> ```
|
117
|
-
>
|
118
|
-
> Both of these are functionally equivalent. `service.name` will be used if no `localEndpoint.serviceName` is set.
|
119
|
-
>
|
120
|
-
> ```ts
|
121
|
-
> const tracer = create('example', {
|
122
|
-
> context: {
|
123
|
-
> 'service.name': 'my-service',
|
124
|
-
> },
|
125
|
-
> });
|
126
|
-
> ```
|
127
|
-
>
|
128
|
-
> </details>
|
129
|
-
|
130
108
|
#### Module: [`rian/exporter.otel.http`](./packages/rian/src/exporter.otel.http.ts)
|
131
109
|
|
132
110
|
Implements the OpenTelemetry protocol for use with http transports.
|
133
111
|
|
134
|
-
> 💡 Note ~> services require a `service.name` context value.
|
135
|
-
>
|
136
|
-
> <details><summary>Example</summary>
|
137
|
-
>
|
138
|
-
> ```ts
|
139
|
-
> const tracer = create('example', {
|
140
|
-
> context: {
|
141
|
-
> 'service.name': 'my-service', // 👈 important part
|
142
|
-
> },
|
143
|
-
> });
|
144
|
-
> ```
|
145
|
-
>
|
146
|
-
> </details>
|
147
|
-
|
148
112
|
## 🧑🍳 Exporter Recipes
|
149
113
|
|
150
114
|
<details><summary>NewRelic</summary>
|
@@ -166,10 +130,7 @@ const newrelic = exporter((payload) =>
|
|
166
130
|
}),
|
167
131
|
);
|
168
132
|
|
169
|
-
const tracer = create('
|
170
|
-
context: {
|
171
|
-
'service.name': 'my-service', // 👈 important part
|
172
|
-
},
|
133
|
+
const tracer = create('my-service', {
|
173
134
|
exporter: newrelic,
|
174
135
|
});
|
175
136
|
```
|
@@ -195,10 +156,7 @@ const lightstep = exporter((payload) =>
|
|
195
156
|
}),
|
196
157
|
);
|
197
158
|
|
198
|
-
const tracer = create('
|
199
|
-
context: {
|
200
|
-
'service.name': 'my-service', // 👈 important part
|
201
|
-
},
|
159
|
+
const tracer = create('my-service', {
|
202
160
|
exporter: lightstep,
|
203
161
|
});
|
204
162
|
```
|
@@ -249,9 +207,9 @@ Validation :: single span
|
|
249
207
|
✔ opentracing
|
250
208
|
|
251
209
|
Benchmark :: single span
|
252
|
-
rian x
|
253
|
-
opentelemetry x
|
254
|
-
opentracing x
|
210
|
+
rian x 392,796 ops/sec ±3.73% (86 runs sampled)
|
211
|
+
opentelemetry x 205,544 ops/sec ±11.98% (65 runs sampled)
|
212
|
+
opentracing x 60,043 ops/sec ±35.25% (97 runs sampled)
|
255
213
|
|
256
214
|
Validation :: child span
|
257
215
|
✔ rian
|
@@ -259,10 +217,9 @@ Validation :: child span
|
|
259
217
|
✔ opentracing
|
260
218
|
|
261
219
|
Benchmark :: child span
|
262
|
-
rian x
|
263
|
-
opentelemetry x
|
264
|
-
opentracing x
|
265
|
-
|
220
|
+
rian x 208,186 ops/sec ±6.28% (82 runs sampled)
|
221
|
+
opentelemetry x 121,740 ops/sec ±16.56% (62 runs sampled)
|
222
|
+
opentracing x 37,405 ops/sec ±0.48% (99 runs sampled)
|
266
223
|
```
|
267
224
|
|
268
225
|
> And please... I know these results are anything but the full story. But it's a number and point on comparison.
|
package/utils/index.d.ts
CHANGED
@@ -17,20 +17,19 @@ export type MeasureFn =
|
|
17
17
|
* @example
|
18
18
|
*
|
19
19
|
* ```text
|
20
|
-
* const data = await measure(scope,
|
21
|
-
*
|
22
|
-
*
|
23
|
-
*
|
24
|
-
*
|
25
|
-
*
|
26
|
-
*
|
27
|
-
*
|
28
|
-
*
|
20
|
+
* const data = await measure(scope, get_data, 'user_id_123');
|
21
|
+
* ^ ^ ^ ^
|
22
|
+
* | | | |
|
23
|
+
* | | | the first argument to get_data
|
24
|
+
* | | |
|
25
|
+
* | | function to be called
|
26
|
+
* | |
|
27
|
+
* | the parent scope
|
28
|
+
* return value from get_data
|
29
29
|
* ```
|
30
30
|
*/
|
31
31
|
export const measure: <Fn extends MeasureFn>(
|
32
32
|
scope: Scope,
|
33
|
-
name: string,
|
34
33
|
fn: Fn, // TODO: fn doesnt see scope correctly
|
35
34
|
...args: RealMeasureFnParams<Parameters<Fn>>
|
36
35
|
) => ReturnType<Fn>;
|
@@ -51,7 +50,6 @@ export const measure: <Fn extends MeasureFn>(
|
|
51
50
|
*/
|
52
51
|
export const wrap: <Fn extends MeasureFn>(
|
53
52
|
scope: Scope,
|
54
|
-
name: string,
|
55
53
|
fn: Fn, // TODO: fn doesnt see scope correctly
|
56
54
|
) => Fn;
|
57
55
|
|
package/utils/index.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
var r=(r,t,...e)=>{try{var n=t(...e,r),o=n instanceof Promise;return o&&r.__add_promise(n.catch((t=>{r.set_context({error:t})})).finally((()=>r.end()))),n}catch(t){throw t instanceof Error&&r.set_context({error:t}),t}finally{!0!==o&&r.end()}},t=(t,e
|
1
|
+
var r=(r,t,...e)=>{try{var n=t(...e,r),o=n instanceof Promise;return o&&r.__add_promise(n.catch((t=>{r.set_context({error:t})})).finally((()=>r.end()))),n}catch(t){throw t instanceof Error&&r.set_context({error:t}),t}finally{!0!==o&&r.end()}},t=(t,e,...n)=>r(t,e,...n),e=(t,e)=>function(){return r(t,e,...arguments)};exports.measure=t;exports.measureFn=r;exports.wrap=e;
|
package/utils/index.mjs
CHANGED
@@ -1 +1 @@
|
|
1
|
-
var r=(r,t,...e)=>{try{var n=t(...e,r),o=n instanceof Promise;return o&&r.__add_promise(n.catch((t=>{r.set_context({error:t})})).finally((()=>r.end()))),n}catch(t){throw t instanceof Error&&r.set_context({error:t}),t}finally{!0!==o&&r.end()}},t=(t,e
|
1
|
+
var r=(r,t,...e)=>{try{var n=t(...e,r),o=n instanceof Promise;return o&&r.__add_promise(n.catch((t=>{r.set_context({error:t})})).finally((()=>r.end()))),n}catch(t){throw t instanceof Error&&r.set_context({error:t}),t}finally{!0!==o&&r.end()}},t=(t,e,...n)=>r(t,e,...n),e=(t,e)=>function(){return r(t,e,...arguments)};export{t as measure,r as measureFn,e as wrap};
|