rian 0.3.0-next.9 β†’ 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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};