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/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};
|