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/async.d.ts +56 -3
- package/async.js +1 -93
- package/async.mjs +1 -93
- package/exporter.otel.http.js +1 -77
- package/exporter.otel.http.mjs +1 -77
- package/exporter.zipkin.js +1 -41
- package/exporter.zipkin.mjs +1 -41
- package/index.d.ts +76 -22
- package/index.js +1 -74
- package/index.mjs +1 -74
- package/package.json +2 -2
- package/readme.md +125 -79
- package/utils.d.ts +10 -51
- package/utils.js +1 -26
- package/utils.mjs +1 -26
- package/exporter.otel.http/index.d.ts +0 -3
- package/exporter.otel.http/index.js +0 -1
- package/exporter.otel.http/index.mjs +0 -1
- package/exporter.zipkin/index.d.ts +0 -3
- package/exporter.zipkin/index.js +0 -1
- package/exporter.zipkin/index.mjs +0 -1
- package/utils/index.d.ts +0 -68
- package/utils/index.js +0 -1
- package/utils/index.mjs +0 -1
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
|
26
|
+
- π€ **Familiar** β looks very much like opentelemetry.
|
30
27
|
|
31
|
-
- β
**Simple** β `
|
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
|
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
|
36
|
+
> Visit [/examples](/examples) for more!
|
40
37
|
|
41
38
|
```ts
|
42
|
-
import { configure,
|
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
|
-
// ~>
|
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
|
-
// ~>
|
47
|
+
// ~> create a tracer β typically "per request" or "per operation".
|
61
48
|
const trace = tracer('request');
|
62
49
|
|
63
|
-
|
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
|
-
|
56
|
+
// ~> span again for `db::read`
|
57
|
+
const data = await s.span('db::read')(() => db_execute('SELECT * FROM users'));
|
66
58
|
|
67
|
-
|
68
|
-
|
69
|
-
});
|
59
|
+
// ~> maybe have some manual spanning
|
60
|
+
const processing_span = s.span('process records');
|
70
61
|
|
71
|
-
|
72
|
-
|
62
|
+
for (let row of data) {
|
63
|
+
processing_span.add_event('doing stuff', { id: row.id });
|
64
|
+
do_stuff(row);
|
65
|
+
}
|
73
66
|
|
74
|
-
//
|
75
|
-
|
67
|
+
// don't forget to end
|
68
|
+
processing_span.end();
|
76
69
|
|
77
|
-
|
78
|
-
|
79
|
-
do_stuff(row);
|
70
|
+
return reply(200, { data });
|
71
|
+
});
|
80
72
|
}
|
81
73
|
|
82
|
-
|
83
|
-
|
84
|
-
|
74
|
+
const otel_exporter = exporter((payload) =>
|
75
|
+
fetch('/traces/otlp', {
|
76
|
+
method: 'POST',
|
77
|
+
body: JSON.stringify(payload),
|
78
|
+
}),
|
79
|
+
);
|
85
80
|
|
86
|
-
|
87
|
-
|
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
|
93
|
-
[ db::read .... (0.5ms) ]
|
94
|
-
|
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,
|
105
|
-
> [Semantic Conventions](https://
|
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
|
-
|
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>
|
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.
|
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
|
-
|
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
|
-
|
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
|
-
|
190
|
-
|
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
|
-
|
195
|
-
|
196
|
-
|
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
|
-
|
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
|
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
|
214
|
-
|
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
|
222
|
-
|
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>-
|
235
|
-
<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
|
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 `
|
10
|
+
* All promises are tracked, and awaited on a `report`.
|
16
11
|
*
|
17
|
-
*
|
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
|
-
* ```
|
44
|
-
* const
|
45
|
-
*
|
46
|
-
*
|
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
|
22
|
+
export function measure<Fn extends (scope: Scope) => any>(
|
52
23
|
scope: Scope,
|
53
|
-
fn: Fn,
|
54
|
-
)
|
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
|
-
|
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
|
-
|
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 +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};
|
package/exporter.zipkin/index.js
DELETED
@@ -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};
|