rian 0.3.0-next.9 β†’ 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
package/readme.md CHANGED
@@ -6,9 +6,6 @@
6
6
 
7
7
  <p><code>npm add rian</code> doesn't overcomplicate tracing</p>
8
8
  <span>
9
- <a href="https://github.com/maraisr/rian/actions/workflows/ci.yml">
10
- <img src="https://github.com/maraisr/rian/actions/workflows/ci.yml/badge.svg"/>
11
- </a>
12
9
  <a href="https://npm-stat.com/charts.html?package=rian">
13
10
  <img src="https://badgen.net/npm/dw/rian?labelColor=black&color=black&cache=600" alt="downloads"/>
14
11
  </a>
@@ -26,84 +23,136 @@
26
23
 
27
24
  ## ⚑ Features
28
25
 
29
- - πŸ€” **Familiar** β€” looks very much like OpenTracing.
26
+ - πŸ€” **Familiar** β€” looks very much like opentelemetry.
30
27
 
31
- - βœ… **Simple** β€” `create` a tracer, and `report()`, done.
28
+ - βœ… **Simple** β€” `configure()` an environment, create a `tracer()`, `report()` and done.
32
29
 
33
30
  - 🏎 **Performant** β€” check the [benchmarks](#-benchmark).
34
31
 
35
- - πŸͺΆ **Lightweight** β€” a mere 1Kb and next to no [dependencies](https://npm.anvaka.com/#/view/2d/rian/).
32
+ - πŸͺΆ **Lightweight** β€” a mere 1KB and next to no [dependencies](https://npm.anvaka.com/#/view/2d/rian/).
36
33
 
37
34
  ## πŸš€ Usage
38
35
 
39
- > Visit [/examples](/examples) for more info!
36
+ > Visit [/examples](/examples) for more!
40
37
 
41
38
  ```ts
42
- import { configure, create, report } from 'rian';
43
- import { measure } from 'rian/utils';
39
+ import { configure, tracer, report } from 'rian';
44
40
  import { exporter } from 'rian/exporter.otel.http';
45
41
 
46
- // ~> Where to send the spans.
47
- const otel_endpoint = exporter((payload) =>
48
- fetch('/traces/otlp', {
49
- method: 'POST',
50
- body: JSON.stringify(payload),
51
- }),
52
- );
53
-
54
- // ~> Configure the environment
55
-
42
+ // ~> configure the environment, all tracers will inherit this
56
43
  configure('my-service' {
57
44
  'service.version': 'DEV'
58
45
  });
59
46
 
60
- // ~> Create a tracer β€” typically "per request" or "per operation"
47
+ // ~> create a tracer β€” typically "per request" or "per operation".
61
48
  const trace = tracer('request');
62
49
 
63
- // Let us trace
50
+ function handler(req) {
51
+ // ~> start a span
52
+ return trace.span(`${req.method} ${req.path}`)(async (s) => {
53
+ // set some fields on this span's context
54
+ s.set_context({ user_id: req.params.user_id });
64
55
 
65
- const req = trace.span('GET ~> /data');
56
+ // ~> span again for `db::read`
57
+ const data = await s.span('db::read')(() => db_execute('SELECT * FROM users'));
66
58
 
67
- req.set_context({
68
- user: request_context.user_id,
69
- });
59
+ // ~> maybe have some manual spanning
60
+ const processing_span = s.span('process records');
70
61
 
71
- // ~> Wrap any method and be timed πŸ•ΊπŸ»
72
- const data = await measure(req.span('db::read'), get_data);
62
+ for (let row of data) {
63
+ processing_span.add_event('doing stuff', { id: row.id });
64
+ do_stuff(row);
65
+ }
73
66
 
74
- // ~> Maybe have some in-flow spanning
75
- const span = req.span('process records');
67
+ // don't forget to end
68
+ processing_span.end();
76
69
 
77
- for (let row of data) {
78
- span.add_event('doing stuff', { id: row.id });
79
- do_stuff(row);
70
+ return reply(200, { data });
71
+ });
80
72
  }
81
73
 
82
- span.end();
83
-
84
- req.end();
74
+ const otel_exporter = exporter((payload) =>
75
+ fetch('/traces/otlp', {
76
+ method: 'POST',
77
+ body: JSON.stringify(payload),
78
+ }),
79
+ );
85
80
 
86
- // ~> And finally let's export β€” will also end the root span.
87
- await report(otel_endpoint);
81
+ http.listen((req, executionCtx) => {
82
+ // ~> report all the spans once the response is sent
83
+ executionCtx.defer(() => report(otel_exporter));
84
+ return handler(req);
85
+ });
88
86
 
89
87
  /*
90
88
  And we end up with something like this in our reporting tool:
91
89
 
92
- [ GET ~> /data .................................... (1.2ms) ]
93
- [ db::read .... (0.5ms) ]
94
- [ process records .... (0.5ms) ]
90
+ [ GET /data .................,,...................... (1.2ms) ] { request }
91
+ [ db::read .... (0.5ms) ] [ process records .... (0.5ms) ]
92
+ ^ ^ ^ ^
93
+ { user_id } ev { id: 1 } | |
94
+ ev { id: 2 } |
95
+ ev { id: 3 }
95
96
  */
96
97
  ```
97
98
 
99
+ You only need to `report` in your application once somewhere. All spans are collected into the same "bucket".
100
+
98
101
  ## πŸ”Ž API
99
102
 
100
103
  #### Module: [`rian`](./packages/rian/src/index.ts)
101
104
 
102
105
  The main and _default_ module responsible for creating and provisioning spans.
103
106
 
104
- > πŸ’‘ Note ~> when providing span context values, please stick to
105
- > [Semantic Conventions](https://github.com/opentracing/specification/blob/master/semantic_conventions.md), but won't be
106
- > enforced.
107
+ > πŸ’‘ Note ~> when providing span context values, you can use
108
+ > [Semantic Conventions](https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/), but won't
109
+ > be enforced.
110
+
111
+ #### Module: [`rian/async`](./packages/rian/src/async.ts)
112
+
113
+ A module that utilizes the `async_hooks` API to provide a `tracer` and `spans` that can be used where the current span
114
+ isn't accessible.
115
+
116
+ > πŸ’‘ Note ~> this module should be used mutually exclusively with the main `rian` module.
117
+
118
+ <detials>
119
+
120
+ <summary>Example</summary>
121
+
122
+ ```ts
123
+ import { configure, tracer, span, currentSpan, report } from 'rian/async';
124
+ import { exporter } from 'rian/exporter.otel.http';
125
+
126
+ function handler(req) {
127
+ return span(`${req.method} ${req.path}`)(async () => {
128
+ const s = currentSpan();
129
+
130
+ s.set_context({ user_id: req.params.user_id });
131
+
132
+ const data = await s.span('db::read')(() => db_execute('SELECT * FROM users'));
133
+
134
+ const processing_span = s.span('process records');
135
+
136
+ for (let row of data) {
137
+ processing_span.add_event('doing stuff', { id: row.id });
138
+ do_stuff(row);
139
+ }
140
+
141
+ processing_span.end();
142
+
143
+ return reply(200, { data });
144
+ });
145
+ }
146
+
147
+ const httpTrace = tracer('http');
148
+
149
+ http.listen((req, executionCtx) => {
150
+ executionCtx.defer(() => report(exporter));
151
+ return httpTrace(() => handler(req));
152
+ });
153
+ ```
154
+
155
+ </details>
107
156
 
108
157
  #### Module: [`rian/exporter.zipkin`](./packages/rian/src/exporter.zipkin.ts)
109
158
 
@@ -118,7 +167,7 @@ Implements the OpenTelemetry protocol for use with http transports.
118
167
  <details><summary>NewRelic</summary>
119
168
 
120
169
  ```ts
121
- import { tracer, report } from 'rian';
170
+ import { configure, tracer, report } from 'rian';
122
171
  import { exporter } from 'rian/exporter.zipkin';
123
172
 
124
173
  const newrelic = exporter((payload) =>
@@ -134,7 +183,9 @@ const newrelic = exporter((payload) =>
134
183
  }),
135
184
  );
136
185
 
137
- const tracer = tracer('my-service');
186
+ configure('my-service');
187
+
188
+ const tracer = tracer('app');
138
189
 
139
190
  await report(newrelic);
140
191
  ```
@@ -143,14 +194,14 @@ await report(newrelic);
143
194
 
144
195
  </details>
145
196
 
146
- <details><summary>LightStep</summary>
197
+ <details><summary>Lightstep</summary>
147
198
 
148
199
  ```ts
149
- import { tracer, report } from 'rian';
200
+ import { configure, tracer, report } from 'rian';
150
201
  import { exporter } from 'rian/exporter.otel.http';
151
202
 
152
203
  const lightstep = exporter((payload) =>
153
- fetch('https://ingest.lightstep.com/traces/otlp/v0.6', {
204
+ fetch('https://ingest.lightstep.com/traces/otlp/v0.9', {
154
205
  method: 'POST',
155
206
  headers: {
156
207
  'lightstep-access-token': '<your api key>',
@@ -160,7 +211,9 @@ const lightstep = exporter((payload) =>
160
211
  }),
161
212
  );
162
213
 
163
- const tracer = tracer('my-service');
214
+ configure('my-service');
215
+
216
+ const tracer = tracer('app');
164
217
 
165
218
  await report(lightstep);
166
219
  ```
@@ -171,34 +224,23 @@ await report(lightstep);
171
224
 
172
225
  ## πŸ€” Motivation
173
226
 
174
- Firstly, what is `rian`? _trace_ in Irish is `rian`.
175
-
176
- In efforts to be better observant citizens, we generally reach for the β€” NewRelic, LightStep, DataDog's. Which, and in
177
- no offence to them, is bloated and slow! Where they more often than not do way too much or and relatively speaking, ship
178
- useless traces. Which ramp up your bill β€” see... every span you trace, costs.
179
-
180
- And here we are, introducing **rian** β€” a lightweight, fast effective tracer. Inspired by the giants in the industry,
181
- OpenTracing and OpenTelemetry.
182
-
183
- You might have not heard of those before β€” and that is okay. It means the design goals from OpenTelemetry or OpenTracing
184
- has been met. They are frameworks built to abstract the telemetry part from vendors. So folk like NewRelic can wrap
185
- their layers on top of open telemetry β€” and have libraries instrument theirs without knowing about the vendor. Which
186
- allows consumers to ship those spans to the vendor of their choosing. OpenTracing has a very similar design goal, so
187
- please do go checkout their documentation's, to help decide.
227
+ To clarify, `rian` is the Irish word for "trace".
188
228
 
189
- Rian does not intend to align or compete with them. rian's intent is to be used to instrument your application and
190
- **only** your application. Rian is primed in that critical business paths β€” where you don't care " which handlers
191
- MongoDB ran", or how many network calls your ORM made. Cardinality will destroy you. Although rian can scale to support
192
- those as well. But the reality is; there are profiler tools far more capable β€” "right tool for the job".
229
+ In our efforts to be observant citizens, we often rely on tools such as NewRelic, Lightstep, and Datadog. However, these
230
+ tools can be bloated and slow, often performing too many unnecessary tasks and driving up costs, as every span costs.
193
231
 
194
- Rian is simply a tracer you can use to see what your application is doing, have better insight into why something failed
195
- and stitch it with your logs. It starts by capturing a [`w3c trace-context`](https://www.w3.org/TR/trace-context/),
196
- tracing some business steps. "inbound request /data", "getting data", "sending email", or as granular as you'd like. And
197
- have that forwarded onto all sub-services.
232
+ This is where rian comes in as a lightweight, fast, and effective tracer inspired by industry giants OpenTracing and
233
+ OpenTelemetry. These frameworks were designed to abstract the telemetry part from vendors, allowing libraries to be
234
+ instrumented without needing to know about the vendor.
198
235
 
199
- You see, the primary design goal is targeted at edge or service workers β€” where lean quick tracers is favoured.
236
+ Rian does not intend to align or compete with them, slightly different goals. Rian aims to be used exclusively for
237
+ instrumenting your application, particularly critical business paths. While rian can scale to support more complex
238
+ constructs, there are profiler tools that are better suited for those jobs. Rian's primary design goal is to provide
239
+ better insights into your application's behavior, particularly for edge or service workers where a lean tracer is
240
+ favored.
200
241
 
201
- Rian is still in active development, but ready for production!
242
+ Rian does not by design handle injecting [`w3c trace-context`](https://www.w3.org/TR/trace-context/), or
243
+ [propagating baggage](https://www.w3.org/TR/baggage/). But we do expose api's for achieving this.
202
244
 
203
245
  ## πŸ’¨ Benchmark
204
246
 
@@ -207,19 +249,23 @@ Rian is still in active development, but ready for production!
207
249
  ```
208
250
  Validation :: single span
209
251
  βœ” rian
252
+ βœ” rian/async
210
253
  βœ” opentelemetry
211
254
 
212
255
  Benchmark :: single span
213
- rian x 385,085 ops/sec Β±4.26% (85 runs sampled)
214
- opentelemetry x 205,004 ops/sec Β±11.99% (65 runs sampled)
256
+ rian x 277,283 ops/sec Β±3.57% (90 runs sampled)
257
+ rian/async x 279,525 ops/sec Β±2.33% (91 runs sampled)
258
+ opentelemetry x 155,019 ops/sec Β±13.13% (70 runs sampled)
215
259
 
216
260
  Validation :: child span
217
261
  βœ” rian
262
+ βœ” rian/async
218
263
  βœ” opentelemetry
219
264
 
220
265
  Benchmark :: child span
221
- rian x 206,736 ops/sec Β±6.37% (86 runs sampled)
222
- opentelemetry x 128,298 ops/sec Β±14.82% (68 runs sampled)
266
+ rian x 146,793 ops/sec Β±3.38% (87 runs sampled)
267
+ rian/async x 180,488 ops/sec Β±1.64% (92 runs sampled)
268
+ opentelemetry x 102,541 ops/sec Β±9.77% (73 runs sampled)
223
269
  ```
224
270
 
225
271
  > And please... I know these results are anything but the full story. But it's a number and point on comparison.
@@ -231,5 +277,5 @@ MIT Β© [Marais Rossouw](https://marais.io)
231
277
  ##### Disclaimer
232
278
 
233
279
  <sup>- NewRelic is a registered trademark of https://newrelic.com/ and not affiliated with this project.</sup><br />
234
- <sup>- DataDog is a registered trademark of https://www.datadoghq.com/ and not affiliated with this project.</sup><br />
235
- <sup>- LightStep is a registered trademark of https://lightstep.com/ and not affiliated with this project.</sup>
280
+ <sup>- Datadog is a registered trademark of https://www.datadoghq.com/ and not affiliated with this project.</sup><br />
281
+ <sup>- Lightstep is a registered trademark of https://lightstep.com/ and not affiliated with this project.</sup>
package/utils.d.ts CHANGED
@@ -1,66 +1,25 @@
1
1
  import type { Scope } from 'rian';
2
2
 
3
- export type MeasureFn =
4
- | ((...args: [...args: any[]]) => any)
5
- | ((...args: [...args: any[], scope: Scope]) => any);
6
-
7
3
  /**
8
- * With a passed function β€” will start a span, and run the function, when the function finishes
9
- * the span finishes.
4
+ * With a passed function, `measure` will run the function and once finishes, will end the span.
10
5
  *
11
6
  * The measure method will return whatever the function is, so if it's a promise, it returns a
12
7
  * promise and so on. Any error is caught and re thrown, and automatically tracked in the
13
8
  * context under the `error` property.
14
9
  *
15
- * All promises are tracked, and awaited on a `tracer.end`.
10
+ * All promises are tracked, and awaited on a `report`.
16
11
  *
17
- * @example
18
- *
19
- * ```text
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
- * ```
30
- */
31
- export const measure: <Fn extends MeasureFn>(
32
- scope: Scope,
33
- fn: Fn, // TODO: fn doesnt see scope correctly
34
- ...args: RealMeasureFnParams<Parameters<Fn>>
35
- ) => ReturnType<Fn>;
36
-
37
- /**
38
- * Wraps any function with a measured scoped function. Useful for when defer function execution
39
- * till a later time.
12
+ * This is a utility method, but is functionally equivalent to `scope.span('name')(fn)`.
40
13
  *
41
14
  * @example
42
15
  *
43
- * ```js
44
- * const wrapped = wrap(scope, "run something", my_function);
45
- *
46
- * // ... lots of things, where the access to `scope` is lost.
47
- *
48
- * wrapped();
16
+ * ```text
17
+ * const data = await measure(scope, get_data);
18
+ * // or with arguments:
19
+ * const data = await measure(scope, () => get_data('foo', 'bar'));
49
20
  * ```
50
21
  */
51
- export const wrap: <Fn extends MeasureFn>(
22
+ export function measure<Fn extends (scope: Scope) => any>(
52
23
  scope: Scope,
53
- fn: Fn, // TODO: fn doesnt see scope correctly
54
- ) => Fn;
55
-
56
- // ==> internals
57
-
58
- /** @internal */
59
- export type RealMeasureFnParams<T extends unknown[]> = T extends []
60
- ? []
61
- : T extends [...rest: infer U, scope: Scope]
62
- ? U
63
- : T;
64
-
65
- /** @internal */
66
- export const measureFn: (scope: Scope, fn: any, ...args: any[]) => any;
24
+ fn: Fn,
25
+ ): ReturnType<Fn>;
package/utils.js CHANGED
@@ -1,26 +1 @@
1
- // src/utils.ts
2
- var measureFn = (scope, fn, ...args) => {
3
- try {
4
- var r = fn(...args, scope), is_promise = r instanceof Promise;
5
- return is_promise && scope.__add_promise(
6
- r.catch(
7
- (e) => void scope.set_context({
8
- error: e
9
- })
10
- ).finally(() => scope.end())
11
- ), r;
12
- } catch (e) {
13
- throw e instanceof Error && scope.set_context({
14
- error: e
15
- }), e;
16
- } finally {
17
- is_promise !== !0 && scope.end();
18
- }
19
- }, measure = (scope, fn, ...args) => measureFn(scope, fn, ...args), wrap = (scope, fn) => function() {
20
- return measureFn(scope, fn, ...arguments);
21
- };
22
-
23
-
24
- exports.measure = measure;
25
- exports.measureFn = measureFn;
26
- exports.wrap = wrap;
1
+ function r(r,t){try{var e=t(r),n=e instanceof Promise;return n&&r.__add_promise(e.catch((t=>{r.set_context({error:t})})).finally((()=>r.end()))),e}catch(t){throw t instanceof Error&&r.set_context({error:t}),t}finally{!0!==n&&r.end()}}exports.measure=r;
package/utils.mjs CHANGED
@@ -1,26 +1 @@
1
- // src/utils.ts
2
- var measureFn = (scope, fn, ...args) => {
3
- try {
4
- var r = fn(...args, scope), is_promise = r instanceof Promise;
5
- return is_promise && scope.__add_promise(
6
- r.catch(
7
- (e) => void scope.set_context({
8
- error: e
9
- })
10
- ).finally(() => scope.end())
11
- ), r;
12
- } catch (e) {
13
- throw e instanceof Error && scope.set_context({
14
- error: e
15
- }), e;
16
- } finally {
17
- is_promise !== !0 && scope.end();
18
- }
19
- }, measure = (scope, fn, ...args) => measureFn(scope, fn, ...args), wrap = (scope, fn) => function() {
20
- return measureFn(scope, fn, ...arguments);
21
- };
22
- export {
23
- measure,
24
- measureFn,
25
- wrap
26
- };
1
+ function r(r,t){try{var e=t(r),n=e instanceof Promise;return n&&r.__add_promise(e.catch((t=>{r.set_context({error:t})})).finally((()=>r.end()))),e}catch(t){throw t instanceof Error&&r.set_context({error:t}),t}finally{!0!==n&&r.end()}}export{r as measure};
@@ -1,3 +0,0 @@
1
- import type { Exporter } from 'rian';
2
-
3
- export const exporter: (request: (payload: any) => any) => Exporter;
@@ -1 +0,0 @@
1
- const { name:e, version:t } = require('rian/package.json');var r=e=>{let t=typeof e,n={};return"string"===t?n.stringValue=e:"number"===t?Number.isInteger(e)?n.intValue=e:n.doubleValue=e:"boolean"===t?n.boolValue=e:Array.isArray(e)?n.arrayValue={values:e.map((e=>r(e)))}:e&&(n.kvlistValue={values:a(e)}),n},a=e=>{let t=[];for(let a of Object.keys(e))t.push({key:a,value:r(e[a])});return t},n=e=>{switch(e){default:case"INTERNAL":return 1;case"SERVER":return 2;case"CLIENT":return 3;case"PRODUCER":return 4;case"CONSUMER":return 5}},s=r=>(s,i)=>{let u=[];for(let e of s){let t,{kind:r,error:s,...i}=e.context;s&&(t={code:2},"message"in s&&(t.message=s.message)),u.push({traceId:e.id.trace_id,spanId:e.id.parent_id,parentSpanId:e.parent?.parent_id,name:e.name,kind:n(r||"INTERNAL"),startTimeUnixNano:1e6*e.start,endTimeUnixNano:e.end?1e6*e.end:void 0,droppedAttributesCount:0,droppedEventsCount:0,droppedLinksCount:0,attributes:a(i),status:t||{code:0},events:e.events.map((e=>({name:e.name,attributes:a(e.attributes),droppedAttributesCount:0,timeUnixNano:1e6*e.timestamp})))})}return r({resourceSpans:[{resource:{attributes:a(i),droppedAttributesCount:0},instrumentationLibrarySpans:[{instrumentationLibrary:{name:e,version:t},spans:u}]}]})};exports.exporter=s;
@@ -1 +0,0 @@
1
- import{name as e,version as t}from"rian/package.json";var r=e=>{let t=typeof e,n={};return"string"===t?n.stringValue=e:"number"===t?Number.isInteger(e)?n.intValue=e:n.doubleValue=e:"boolean"===t?n.boolValue=e:Array.isArray(e)?n.arrayValue={values:e.map((e=>r(e)))}:e&&(n.kvlistValue={values:a(e)}),n},a=e=>{let t=[];for(let a of Object.keys(e))t.push({key:a,value:r(e[a])});return t},n=e=>{switch(e){default:case"INTERNAL":return 1;case"SERVER":return 2;case"CLIENT":return 3;case"PRODUCER":return 4;case"CONSUMER":return 5}},s=r=>(s,i)=>{let u=[];for(let e of s){let t,{kind:r,error:s,...i}=e.context;s&&(t={code:2},"message"in s&&(t.message=s.message)),u.push({traceId:e.id.trace_id,spanId:e.id.parent_id,parentSpanId:e.parent?.parent_id,name:e.name,kind:n(r||"INTERNAL"),startTimeUnixNano:1e6*e.start,endTimeUnixNano:e.end?1e6*e.end:void 0,droppedAttributesCount:0,droppedEventsCount:0,droppedLinksCount:0,attributes:a(i),status:t||{code:0},events:e.events.map((e=>({name:e.name,attributes:a(e.attributes),droppedAttributesCount:0,timeUnixNano:1e6*e.timestamp})))})}return r({resourceSpans:[{resource:{attributes:a(i),droppedAttributesCount:0},instrumentationLibrarySpans:[{instrumentationLibrary:{name:e,version:t},spans:u}]}]})};export{s as exporter};
@@ -1,3 +0,0 @@
1
- import type { Exporter } from 'rian';
2
-
3
- export const exporter: (request: (payload: any) => any) => Exporter;
@@ -1 +0,0 @@
1
- const { flattie:e } = require('flattie');var t=t=>(a,n)=>{let r=[];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}),r.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:n.localEndpoint||{serviceName:s["service.name"]},tags:e({...n,...s},".",!0),annotations:t.events.map((e=>({value:`${e.name} :: ${JSON.stringify(e.attributes)}`,timestamp:1e3*e.timestamp})))})}return t(r)};exports.exporter=t;
@@ -1 +0,0 @@
1
- import{flattie as e}from"flattie";var t=t=>(a,n)=>{let r=[];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}),r.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:n.localEndpoint||{serviceName:s["service.name"]},tags:e({...n,...s},".",!0),annotations:t.events.map((e=>({value:`${e.name} :: ${JSON.stringify(e.attributes)}`,timestamp:1e3*e.timestamp})))})}return t(r)};export{t as exporter};
package/utils/index.d.ts DELETED
@@ -1,68 +0,0 @@
1
- import type { Scope } from 'rian';
2
-
3
- export type MeasureFn =
4
- | ((...args: [...args: any[]]) => any)
5
- | ((...args: [...args: any[], scope: Scope]) => any);
6
-
7
- /**
8
- * With a passed function β€” will start a span, and run the function, when the function finishes
9
- * the span finishes.
10
- *
11
- * The measure method will return whatever the function is, so if it's a promise, it returns a
12
- * promise and so on. Any error is caught and re thrown, and automatically tracked in the
13
- * context under the `error` property.
14
- *
15
- * All promises are tracked, and awaited on a `tracer.end`.
16
- *
17
- * @example
18
- *
19
- * ```text
20
- * const data = await measure(scope, 'name', get_data, 'user_id_123');
21
- * ^ ^ ^ ^ ^
22
- * | | | | |
23
- * | | | | the first argument to get_data
24
- * | | | function to be called
25
- * | | the name of the sub scope
26
- * | |
27
- * | the parent scope
28
- * return value from get_data
29
- * ```
30
- */
31
- export const measure: <Fn extends MeasureFn>(
32
- scope: Scope,
33
- name: string,
34
- fn: Fn, // TODO: fn doesnt see scope correctly
35
- ...args: RealMeasureFnParams<Parameters<Fn>>
36
- ) => ReturnType<Fn>;
37
-
38
- /**
39
- * Wraps any function with a measured scoped function. Useful for when defer function execution
40
- * till a later time.
41
- *
42
- * @example
43
- *
44
- * ```js
45
- * const wrapped = wrap(scope, "run something", my_function);
46
- *
47
- * // ... lots of things, where the access to `scope` is lost.
48
- *
49
- * wrapped();
50
- * ```
51
- */
52
- export const wrap: <Fn extends MeasureFn>(
53
- scope: Scope,
54
- name: string,
55
- fn: Fn, // TODO: fn doesnt see scope correctly
56
- ) => Fn;
57
-
58
- // ==> internals
59
-
60
- /** @internal */
61
- export type RealMeasureFnParams<T extends unknown[]> = T extends []
62
- ? []
63
- : T extends [...rest: infer U, scope: Scope]
64
- ? U
65
- : T;
66
-
67
- /** @internal */
68
- export const measureFn: (scope: Scope, fn: any, ...args: any[]) => any;
package/utils/index.js DELETED
@@ -1 +0,0 @@
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,...o)=>r(t.fork(e),n,...o),e=(t,e,n)=>function(){return r(t.fork(e),n,...arguments)};exports.measure=t;exports.measureFn=r;exports.wrap=e;
package/utils/index.mjs DELETED
@@ -1 +0,0 @@
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,...o)=>r(t.fork(e),n,...o),e=(t,e,n)=>function(){return r(t.fork(e),n,...arguments)};export{t as measure,r as measureFn,e as wrap};