rian 0.3.0-next.8 → 0.3.0-next.9
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.js +93 -1
- package/async.mjs +93 -1
- package/exporter.otel.http/index.d.ts +3 -0
- package/exporter.otel.http/index.js +1 -0
- package/exporter.otel.http/index.mjs +1 -0
- package/exporter.otel.http.js +77 -1
- package/exporter.otel.http.mjs +77 -1
- package/exporter.zipkin/index.d.ts +3 -0
- package/exporter.zipkin/index.js +1 -0
- package/exporter.zipkin/index.mjs +1 -0
- package/exporter.zipkin.js +41 -1
- package/exporter.zipkin.mjs +41 -1
- package/index.js +74 -1
- package/index.mjs +74 -1
- package/package.json +2 -2
- package/readme.md +13 -7
- package/utils/index.d.ts +68 -0
- package/utils/index.js +1 -0
- package/utils/index.mjs +1 -0
- package/utils.js +26 -1
- package/utils.mjs +26 -1
package/async.js
CHANGED
@@ -1 +1,93 @@
|
|
1
|
-
|
1
|
+
// src/async.ts
|
2
|
+
const async_hooks = require('node:async_hooks');
|
3
|
+
const { measure } = require('rian/utils');
|
4
|
+
const { make, parse, SAMPLED_FLAG } = require('tctx');
|
5
|
+
|
6
|
+
// src/_internal/index.ts
|
7
|
+
const { is_sampled } = require('tctx');
|
8
|
+
var resource = {};
|
9
|
+
function configure(name, attributes = {}) {
|
10
|
+
resource = {
|
11
|
+
...attributes,
|
12
|
+
["service.name"]: name,
|
13
|
+
["telemetry.sdk.name"]: "rian",
|
14
|
+
["telemetry.sdk.version"]: "0.3.0-next.9"
|
15
|
+
};
|
16
|
+
}
|
17
|
+
var span_buffer = /* @__PURE__ */ new Set(), wait_promises = /* @__PURE__ */ new WeakMap();
|
18
|
+
async function report(exporter) {
|
19
|
+
let ps = [], scopes = /* @__PURE__ */ new Map();
|
20
|
+
for (let [span2, scope] of span_buffer) {
|
21
|
+
let spans;
|
22
|
+
scopes.has(scope) ? spans = scopes.get(scope).spans : scopes.set(scope, {
|
23
|
+
scope,
|
24
|
+
spans: spans = []
|
25
|
+
}), spans.push(span2), wait_promises.has(scope) && (ps.push(...wait_promises.get(scope)), wait_promises.delete(scope));
|
26
|
+
}
|
27
|
+
return span_buffer.clear(), ps.length && await Promise.all(ps), exporter({
|
28
|
+
resource,
|
29
|
+
scopeSpans: scopes.values()
|
30
|
+
});
|
31
|
+
}
|
32
|
+
function defaultSampler(_name, id) {
|
33
|
+
return is_sampled(id);
|
34
|
+
}
|
35
|
+
|
36
|
+
// src/async.ts
|
37
|
+
var resourceStore = new async_hooks.AsyncLocalStorage();
|
38
|
+
function currentSpan() {
|
39
|
+
return resourceStore.getStore()?.[1] || null;
|
40
|
+
}
|
41
|
+
function span(name) {
|
42
|
+
let context = resourceStore.getStore();
|
43
|
+
if (!context)
|
44
|
+
throw Error("TODO");
|
45
|
+
let api = context[0], scope = api.scope, current_span = context[1], sampler = api.sampler, parent = current_span?.traceparent ?? api.root_id, id = parent ? parent.child() : make(), should_sample = typeof sampler != "boolean" ? sampler(name, id, scope) : sampler;
|
46
|
+
should_sample ? id.flags | SAMPLED_FLAG : id.flags & ~SAMPLED_FLAG;
|
47
|
+
let span_obj = {
|
48
|
+
id,
|
49
|
+
parent,
|
50
|
+
start: Date.now(),
|
51
|
+
name,
|
52
|
+
events: [],
|
53
|
+
context: {}
|
54
|
+
};
|
55
|
+
should_sample && span_buffer.add([span_obj, scope]);
|
56
|
+
let $ = (cb) => resourceStore.run([api, $], measure, $, cb);
|
57
|
+
$.traceparent = id, $.span = span, $.set_context = (ctx) => {
|
58
|
+
if (typeof ctx == "function")
|
59
|
+
return void (span_obj.context = ctx(span_obj.context));
|
60
|
+
Object.assign(span_obj.context, ctx);
|
61
|
+
}, $.add_event = (name2, attributes) => {
|
62
|
+
span_obj.events.push({
|
63
|
+
name: name2,
|
64
|
+
timestamp: Date.now(),
|
65
|
+
attributes: attributes || {}
|
66
|
+
});
|
67
|
+
}, $.end = () => {
|
68
|
+
span_obj.end == null && (span_obj.end = Date.now());
|
69
|
+
};
|
70
|
+
let ps = wait_promises.get(scope);
|
71
|
+
return $.__add_promise = (p) => {
|
72
|
+
ps.add(p), p.then(() => ps.delete(p));
|
73
|
+
}, resourceStore.run([api, $], () => $);
|
74
|
+
}
|
75
|
+
function tracer(name, options) {
|
76
|
+
let sampler = options?.sampler ?? defaultSampler, scope = { name }, api = {
|
77
|
+
root_id: typeof options?.traceparent == "string" ? parse(options.traceparent) : resourceStore.getStore()?.[0].root_id,
|
78
|
+
scope,
|
79
|
+
sampler
|
80
|
+
};
|
81
|
+
return wait_promises.set(scope, /* @__PURE__ */ new Set()), {
|
82
|
+
span(name2) {
|
83
|
+
return resourceStore.run([api, null], span, name2);
|
84
|
+
}
|
85
|
+
};
|
86
|
+
}
|
87
|
+
|
88
|
+
|
89
|
+
exports.configure = configure;
|
90
|
+
exports.currentSpan = currentSpan;
|
91
|
+
exports.report = report;
|
92
|
+
exports.span = span;
|
93
|
+
exports.tracer = tracer;
|
package/async.mjs
CHANGED
@@ -1 +1,93 @@
|
|
1
|
-
|
1
|
+
// src/async.ts
|
2
|
+
import * as async_hooks from "node:async_hooks";
|
3
|
+
import { measure } from "rian/utils";
|
4
|
+
import { make, parse, SAMPLED_FLAG } from "tctx";
|
5
|
+
|
6
|
+
// src/_internal/index.ts
|
7
|
+
import { is_sampled } from "tctx";
|
8
|
+
var resource = {};
|
9
|
+
function configure(name, attributes = {}) {
|
10
|
+
resource = {
|
11
|
+
...attributes,
|
12
|
+
["service.name"]: name,
|
13
|
+
["telemetry.sdk.name"]: "rian",
|
14
|
+
["telemetry.sdk.version"]: "0.3.0-next.9"
|
15
|
+
};
|
16
|
+
}
|
17
|
+
var span_buffer = /* @__PURE__ */ new Set(), wait_promises = /* @__PURE__ */ new WeakMap();
|
18
|
+
async function report(exporter) {
|
19
|
+
let ps = [], scopes = /* @__PURE__ */ new Map();
|
20
|
+
for (let [span2, scope] of span_buffer) {
|
21
|
+
let spans;
|
22
|
+
scopes.has(scope) ? spans = scopes.get(scope).spans : scopes.set(scope, {
|
23
|
+
scope,
|
24
|
+
spans: spans = []
|
25
|
+
}), spans.push(span2), wait_promises.has(scope) && (ps.push(...wait_promises.get(scope)), wait_promises.delete(scope));
|
26
|
+
}
|
27
|
+
return span_buffer.clear(), ps.length && await Promise.all(ps), exporter({
|
28
|
+
resource,
|
29
|
+
scopeSpans: scopes.values()
|
30
|
+
});
|
31
|
+
}
|
32
|
+
function defaultSampler(_name, id) {
|
33
|
+
return is_sampled(id);
|
34
|
+
}
|
35
|
+
|
36
|
+
// src/async.ts
|
37
|
+
var resourceStore = new async_hooks.AsyncLocalStorage();
|
38
|
+
function currentSpan() {
|
39
|
+
return resourceStore.getStore()?.[1] || null;
|
40
|
+
}
|
41
|
+
function span(name) {
|
42
|
+
let context = resourceStore.getStore();
|
43
|
+
if (!context)
|
44
|
+
throw Error("TODO");
|
45
|
+
let api = context[0], scope = api.scope, current_span = context[1], sampler = api.sampler, parent = current_span?.traceparent ?? api.root_id, id = parent ? parent.child() : make(), should_sample = typeof sampler != "boolean" ? sampler(name, id, scope) : sampler;
|
46
|
+
should_sample ? id.flags | SAMPLED_FLAG : id.flags & ~SAMPLED_FLAG;
|
47
|
+
let span_obj = {
|
48
|
+
id,
|
49
|
+
parent,
|
50
|
+
start: Date.now(),
|
51
|
+
name,
|
52
|
+
events: [],
|
53
|
+
context: {}
|
54
|
+
};
|
55
|
+
should_sample && span_buffer.add([span_obj, scope]);
|
56
|
+
let $ = (cb) => resourceStore.run([api, $], measure, $, cb);
|
57
|
+
$.traceparent = id, $.span = span, $.set_context = (ctx) => {
|
58
|
+
if (typeof ctx == "function")
|
59
|
+
return void (span_obj.context = ctx(span_obj.context));
|
60
|
+
Object.assign(span_obj.context, ctx);
|
61
|
+
}, $.add_event = (name2, attributes) => {
|
62
|
+
span_obj.events.push({
|
63
|
+
name: name2,
|
64
|
+
timestamp: Date.now(),
|
65
|
+
attributes: attributes || {}
|
66
|
+
});
|
67
|
+
}, $.end = () => {
|
68
|
+
span_obj.end == null && (span_obj.end = Date.now());
|
69
|
+
};
|
70
|
+
let ps = wait_promises.get(scope);
|
71
|
+
return $.__add_promise = (p) => {
|
72
|
+
ps.add(p), p.then(() => ps.delete(p));
|
73
|
+
}, resourceStore.run([api, $], () => $);
|
74
|
+
}
|
75
|
+
function tracer(name, options) {
|
76
|
+
let sampler = options?.sampler ?? defaultSampler, scope = { name }, api = {
|
77
|
+
root_id: typeof options?.traceparent == "string" ? parse(options.traceparent) : resourceStore.getStore()?.[0].root_id,
|
78
|
+
scope,
|
79
|
+
sampler
|
80
|
+
};
|
81
|
+
return wait_promises.set(scope, /* @__PURE__ */ new Set()), {
|
82
|
+
span(name2) {
|
83
|
+
return resourceStore.run([api, null], span, name2);
|
84
|
+
}
|
85
|
+
};
|
86
|
+
}
|
87
|
+
export {
|
88
|
+
configure,
|
89
|
+
currentSpan,
|
90
|
+
report,
|
91
|
+
span,
|
92
|
+
tracer
|
93
|
+
};
|
@@ -0,0 +1 @@
|
|
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;
|
@@ -0,0 +1 @@
|
|
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.otel.http.js
CHANGED
@@ -1 +1,77 @@
|
|
1
|
-
|
1
|
+
// src/exporter.otel.http.ts
|
2
|
+
var convert_value_to_anyvalue = (value) => {
|
3
|
+
let type = typeof value, any_value = {};
|
4
|
+
return type === "string" ? any_value.stringValue = value : type === "number" ? Number.isInteger(value) ? any_value.intValue = value : any_value.doubleValue = value : type === "boolean" ? any_value.boolValue = value : Array.isArray(value) ? any_value.arrayValue = {
|
5
|
+
values: value.map((i) => convert_value_to_anyvalue(i))
|
6
|
+
} : value && (any_value.kvlistValue = { values: convert_object_to_kv(value) }), any_value;
|
7
|
+
}, convert_object_to_kv = (input) => {
|
8
|
+
let value = [];
|
9
|
+
for (let key of Object.keys(input))
|
10
|
+
value.push({
|
11
|
+
key,
|
12
|
+
value: convert_value_to_anyvalue(input[key])
|
13
|
+
});
|
14
|
+
return value;
|
15
|
+
}, map_kind = (kind) => {
|
16
|
+
switch (kind) {
|
17
|
+
default:
|
18
|
+
case "INTERNAL":
|
19
|
+
return 1;
|
20
|
+
case "SERVER":
|
21
|
+
return 2;
|
22
|
+
case "CLIENT":
|
23
|
+
return 3;
|
24
|
+
case "PRODUCER":
|
25
|
+
return 4;
|
26
|
+
case "CONSUMER":
|
27
|
+
return 5;
|
28
|
+
}
|
29
|
+
}, exporter = (request) => (trace) => {
|
30
|
+
let scopeSpans = [];
|
31
|
+
for (let scope of trace.scopeSpans) {
|
32
|
+
let spans = [];
|
33
|
+
scopeSpans.push({
|
34
|
+
scope: scope.scope,
|
35
|
+
spans
|
36
|
+
});
|
37
|
+
for (let span of scope.spans) {
|
38
|
+
let { kind, error, ...span_ctx } = span.context, status;
|
39
|
+
error && (status = {
|
40
|
+
code: 2
|
41
|
+
}, "message" in error && (status.message = error.message)), spans.push({
|
42
|
+
traceId: span.id.trace_id,
|
43
|
+
spanId: span.id.parent_id,
|
44
|
+
parentSpanId: span.parent?.parent_id,
|
45
|
+
name: span.name,
|
46
|
+
kind: map_kind(kind || "INTERNAL"),
|
47
|
+
startTimeUnixNano: span.start * 1e6,
|
48
|
+
endTimeUnixNano: span.end ? span.end * 1e6 : void 0,
|
49
|
+
droppedAttributesCount: 0,
|
50
|
+
droppedEventsCount: 0,
|
51
|
+
droppedLinksCount: 0,
|
52
|
+
attributes: convert_object_to_kv(span_ctx),
|
53
|
+
status: status || { code: 0 },
|
54
|
+
events: span.events.map((i) => ({
|
55
|
+
name: i.name,
|
56
|
+
attributes: convert_object_to_kv(i.attributes),
|
57
|
+
droppedAttributesCount: 0,
|
58
|
+
timeUnixNano: i.timestamp * 1e6
|
59
|
+
}))
|
60
|
+
});
|
61
|
+
}
|
62
|
+
}
|
63
|
+
return request({
|
64
|
+
resourceSpans: [
|
65
|
+
{
|
66
|
+
resource: {
|
67
|
+
attributes: convert_object_to_kv(trace.resource),
|
68
|
+
droppedAttributesCount: 0
|
69
|
+
},
|
70
|
+
scopeSpans
|
71
|
+
}
|
72
|
+
]
|
73
|
+
});
|
74
|
+
};
|
75
|
+
|
76
|
+
|
77
|
+
exports.exporter = exporter;
|
package/exporter.otel.http.mjs
CHANGED
@@ -1 +1,77 @@
|
|
1
|
-
|
1
|
+
// src/exporter.otel.http.ts
|
2
|
+
var convert_value_to_anyvalue = (value) => {
|
3
|
+
let type = typeof value, any_value = {};
|
4
|
+
return type === "string" ? any_value.stringValue = value : type === "number" ? Number.isInteger(value) ? any_value.intValue = value : any_value.doubleValue = value : type === "boolean" ? any_value.boolValue = value : Array.isArray(value) ? any_value.arrayValue = {
|
5
|
+
values: value.map((i) => convert_value_to_anyvalue(i))
|
6
|
+
} : value && (any_value.kvlistValue = { values: convert_object_to_kv(value) }), any_value;
|
7
|
+
}, convert_object_to_kv = (input) => {
|
8
|
+
let value = [];
|
9
|
+
for (let key of Object.keys(input))
|
10
|
+
value.push({
|
11
|
+
key,
|
12
|
+
value: convert_value_to_anyvalue(input[key])
|
13
|
+
});
|
14
|
+
return value;
|
15
|
+
}, map_kind = (kind) => {
|
16
|
+
switch (kind) {
|
17
|
+
default:
|
18
|
+
case "INTERNAL":
|
19
|
+
return 1;
|
20
|
+
case "SERVER":
|
21
|
+
return 2;
|
22
|
+
case "CLIENT":
|
23
|
+
return 3;
|
24
|
+
case "PRODUCER":
|
25
|
+
return 4;
|
26
|
+
case "CONSUMER":
|
27
|
+
return 5;
|
28
|
+
}
|
29
|
+
}, exporter = (request) => (trace) => {
|
30
|
+
let scopeSpans = [];
|
31
|
+
for (let scope of trace.scopeSpans) {
|
32
|
+
let spans = [];
|
33
|
+
scopeSpans.push({
|
34
|
+
scope: scope.scope,
|
35
|
+
spans
|
36
|
+
});
|
37
|
+
for (let span of scope.spans) {
|
38
|
+
let { kind, error, ...span_ctx } = span.context, status;
|
39
|
+
error && (status = {
|
40
|
+
code: 2
|
41
|
+
}, "message" in error && (status.message = error.message)), spans.push({
|
42
|
+
traceId: span.id.trace_id,
|
43
|
+
spanId: span.id.parent_id,
|
44
|
+
parentSpanId: span.parent?.parent_id,
|
45
|
+
name: span.name,
|
46
|
+
kind: map_kind(kind || "INTERNAL"),
|
47
|
+
startTimeUnixNano: span.start * 1e6,
|
48
|
+
endTimeUnixNano: span.end ? span.end * 1e6 : void 0,
|
49
|
+
droppedAttributesCount: 0,
|
50
|
+
droppedEventsCount: 0,
|
51
|
+
droppedLinksCount: 0,
|
52
|
+
attributes: convert_object_to_kv(span_ctx),
|
53
|
+
status: status || { code: 0 },
|
54
|
+
events: span.events.map((i) => ({
|
55
|
+
name: i.name,
|
56
|
+
attributes: convert_object_to_kv(i.attributes),
|
57
|
+
droppedAttributesCount: 0,
|
58
|
+
timeUnixNano: i.timestamp * 1e6
|
59
|
+
}))
|
60
|
+
});
|
61
|
+
}
|
62
|
+
}
|
63
|
+
return request({
|
64
|
+
resourceSpans: [
|
65
|
+
{
|
66
|
+
resource: {
|
67
|
+
attributes: convert_object_to_kv(trace.resource),
|
68
|
+
droppedAttributesCount: 0
|
69
|
+
},
|
70
|
+
scopeSpans
|
71
|
+
}
|
72
|
+
]
|
73
|
+
});
|
74
|
+
};
|
75
|
+
export {
|
76
|
+
exporter
|
77
|
+
};
|
@@ -0,0 +1 @@
|
|
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;
|
@@ -0,0 +1 @@
|
|
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/exporter.zipkin.js
CHANGED
@@ -1 +1,41 @@
|
|
1
|
-
|
1
|
+
// src/exporter.zipkin.ts
|
2
|
+
const { flattie } = require('flattie');
|
3
|
+
var exporter = (request) => (trace) => {
|
4
|
+
let zipkin = [];
|
5
|
+
for (let scope of trace.scopeSpans)
|
6
|
+
for (let span of scope.spans) {
|
7
|
+
let { kind, error, ...span_ctx } = span.context;
|
8
|
+
error && ("message" in error ? span_ctx.error = {
|
9
|
+
name: error.name,
|
10
|
+
message: error.message,
|
11
|
+
stack: error.stack
|
12
|
+
} : span_ctx.error = !0), zipkin.push({
|
13
|
+
id: span.id.parent_id,
|
14
|
+
traceId: span.id.trace_id,
|
15
|
+
parentId: span.parent ? span.parent.parent_id : void 0,
|
16
|
+
name: span.name,
|
17
|
+
kind: kind === "INTERNAL" ? void 0 : kind,
|
18
|
+
timestamp: span.start * 1e3,
|
19
|
+
duration: span.end ? (span.end - span.start) * 1e3 : void 0,
|
20
|
+
localEndpoint: {
|
21
|
+
serviceName: `${trace.resource["service.name"]}@${scope.scope.name}`
|
22
|
+
},
|
23
|
+
tags: flattie(
|
24
|
+
{
|
25
|
+
...trace.resource,
|
26
|
+
...span_ctx
|
27
|
+
},
|
28
|
+
".",
|
29
|
+
!0
|
30
|
+
),
|
31
|
+
annotations: span.events.map((i) => ({
|
32
|
+
value: `${i.name} :: ${JSON.stringify(i.attributes)}`,
|
33
|
+
timestamp: i.timestamp * 1e3
|
34
|
+
}))
|
35
|
+
});
|
36
|
+
}
|
37
|
+
return request(zipkin);
|
38
|
+
};
|
39
|
+
|
40
|
+
|
41
|
+
exports.exporter = exporter;
|
package/exporter.zipkin.mjs
CHANGED
@@ -1 +1,41 @@
|
|
1
|
-
|
1
|
+
// src/exporter.zipkin.ts
|
2
|
+
import { flattie } from "flattie";
|
3
|
+
var exporter = (request) => (trace) => {
|
4
|
+
let zipkin = [];
|
5
|
+
for (let scope of trace.scopeSpans)
|
6
|
+
for (let span of scope.spans) {
|
7
|
+
let { kind, error, ...span_ctx } = span.context;
|
8
|
+
error && ("message" in error ? span_ctx.error = {
|
9
|
+
name: error.name,
|
10
|
+
message: error.message,
|
11
|
+
stack: error.stack
|
12
|
+
} : span_ctx.error = !0), zipkin.push({
|
13
|
+
id: span.id.parent_id,
|
14
|
+
traceId: span.id.trace_id,
|
15
|
+
parentId: span.parent ? span.parent.parent_id : void 0,
|
16
|
+
name: span.name,
|
17
|
+
kind: kind === "INTERNAL" ? void 0 : kind,
|
18
|
+
timestamp: span.start * 1e3,
|
19
|
+
duration: span.end ? (span.end - span.start) * 1e3 : void 0,
|
20
|
+
localEndpoint: {
|
21
|
+
serviceName: `${trace.resource["service.name"]}@${scope.scope.name}`
|
22
|
+
},
|
23
|
+
tags: flattie(
|
24
|
+
{
|
25
|
+
...trace.resource,
|
26
|
+
...span_ctx
|
27
|
+
},
|
28
|
+
".",
|
29
|
+
!0
|
30
|
+
),
|
31
|
+
annotations: span.events.map((i) => ({
|
32
|
+
value: `${i.name} :: ${JSON.stringify(i.attributes)}`,
|
33
|
+
timestamp: i.timestamp * 1e3
|
34
|
+
}))
|
35
|
+
});
|
36
|
+
}
|
37
|
+
return request(zipkin);
|
38
|
+
};
|
39
|
+
export {
|
40
|
+
exporter
|
41
|
+
};
|
package/index.js
CHANGED
@@ -1 +1,74 @@
|
|
1
|
-
|
1
|
+
// src/index.ts
|
2
|
+
const { measureFn } = require('rian/utils');
|
3
|
+
const { make, parse, SAMPLED_FLAG } = require('tctx');
|
4
|
+
|
5
|
+
// src/_internal/index.ts
|
6
|
+
const { is_sampled } = require('tctx');
|
7
|
+
var resource = {};
|
8
|
+
function configure(name, attributes = {}) {
|
9
|
+
resource = {
|
10
|
+
...attributes,
|
11
|
+
["service.name"]: name,
|
12
|
+
["telemetry.sdk.name"]: "rian",
|
13
|
+
["telemetry.sdk.version"]: "0.3.0-next.9"
|
14
|
+
};
|
15
|
+
}
|
16
|
+
var span_buffer = /* @__PURE__ */ new Set(), wait_promises = /* @__PURE__ */ new WeakMap();
|
17
|
+
async function report(exporter) {
|
18
|
+
let ps = [], scopes = /* @__PURE__ */ new Map();
|
19
|
+
for (let [span, scope] of span_buffer) {
|
20
|
+
let spans;
|
21
|
+
scopes.has(scope) ? spans = scopes.get(scope).spans : scopes.set(scope, {
|
22
|
+
scope,
|
23
|
+
spans: spans = []
|
24
|
+
}), spans.push(span), wait_promises.has(scope) && (ps.push(...wait_promises.get(scope)), wait_promises.delete(scope));
|
25
|
+
}
|
26
|
+
return span_buffer.clear(), ps.length && await Promise.all(ps), exporter({
|
27
|
+
resource,
|
28
|
+
scopeSpans: scopes.values()
|
29
|
+
});
|
30
|
+
}
|
31
|
+
function defaultSampler(_name, id) {
|
32
|
+
return is_sampled(id);
|
33
|
+
}
|
34
|
+
|
35
|
+
// src/index.ts
|
36
|
+
function tracer(name, options) {
|
37
|
+
let sampler = options?.sampler ?? defaultSampler, scope = { name }, ps = /* @__PURE__ */ new Set();
|
38
|
+
wait_promises.set(scope, ps);
|
39
|
+
let root_id = typeof options?.traceparent == "string" ? parse(options.traceparent) : void 0, span = (name2, parent) => {
|
40
|
+
let id = parent ? parent.child() : make(), should_sample = typeof sampler != "boolean" ? sampler(name2, id, scope) : sampler;
|
41
|
+
should_sample ? id.flags | SAMPLED_FLAG : id.flags & ~SAMPLED_FLAG;
|
42
|
+
let span_obj = {
|
43
|
+
id,
|
44
|
+
parent,
|
45
|
+
start: Date.now(),
|
46
|
+
name: name2,
|
47
|
+
events: [],
|
48
|
+
context: {}
|
49
|
+
};
|
50
|
+
should_sample && span_buffer.add([span_obj, scope]);
|
51
|
+
let $ = (cb) => measureFn($, cb);
|
52
|
+
return $.traceparent = id, $.span = (name3) => span(name3, id), $.set_context = (ctx) => typeof ctx == "function" ? void (span_obj.context = ctx(span_obj.context)) : void Object.assign(span_obj.context, ctx), $.add_event = (name3, attributes) => {
|
53
|
+
span_obj.events.push({
|
54
|
+
name: name3,
|
55
|
+
timestamp: Date.now(),
|
56
|
+
attributes: attributes || {}
|
57
|
+
});
|
58
|
+
}, $.end = () => {
|
59
|
+
span_obj.end == null && (span_obj.end = Date.now());
|
60
|
+
}, $.__add_promise = (p) => {
|
61
|
+
ps.add(p), p.then(() => ps.delete(p));
|
62
|
+
}, $;
|
63
|
+
};
|
64
|
+
return {
|
65
|
+
span(name2) {
|
66
|
+
return span(name2, root_id);
|
67
|
+
}
|
68
|
+
};
|
69
|
+
}
|
70
|
+
|
71
|
+
|
72
|
+
exports.configure = configure;
|
73
|
+
exports.report = report;
|
74
|
+
exports.tracer = tracer;
|
package/index.mjs
CHANGED
@@ -1 +1,74 @@
|
|
1
|
-
|
1
|
+
// src/index.ts
|
2
|
+
import { measureFn } from "rian/utils";
|
3
|
+
import { make, parse, SAMPLED_FLAG } from "tctx";
|
4
|
+
|
5
|
+
// src/_internal/index.ts
|
6
|
+
import { is_sampled } from "tctx";
|
7
|
+
var resource = {};
|
8
|
+
function configure(name, attributes = {}) {
|
9
|
+
resource = {
|
10
|
+
...attributes,
|
11
|
+
["service.name"]: name,
|
12
|
+
["telemetry.sdk.name"]: "rian",
|
13
|
+
["telemetry.sdk.version"]: "0.3.0-next.9"
|
14
|
+
};
|
15
|
+
}
|
16
|
+
var span_buffer = /* @__PURE__ */ new Set(), wait_promises = /* @__PURE__ */ new WeakMap();
|
17
|
+
async function report(exporter) {
|
18
|
+
let ps = [], scopes = /* @__PURE__ */ new Map();
|
19
|
+
for (let [span, scope] of span_buffer) {
|
20
|
+
let spans;
|
21
|
+
scopes.has(scope) ? spans = scopes.get(scope).spans : scopes.set(scope, {
|
22
|
+
scope,
|
23
|
+
spans: spans = []
|
24
|
+
}), spans.push(span), wait_promises.has(scope) && (ps.push(...wait_promises.get(scope)), wait_promises.delete(scope));
|
25
|
+
}
|
26
|
+
return span_buffer.clear(), ps.length && await Promise.all(ps), exporter({
|
27
|
+
resource,
|
28
|
+
scopeSpans: scopes.values()
|
29
|
+
});
|
30
|
+
}
|
31
|
+
function defaultSampler(_name, id) {
|
32
|
+
return is_sampled(id);
|
33
|
+
}
|
34
|
+
|
35
|
+
// src/index.ts
|
36
|
+
function tracer(name, options) {
|
37
|
+
let sampler = options?.sampler ?? defaultSampler, scope = { name }, ps = /* @__PURE__ */ new Set();
|
38
|
+
wait_promises.set(scope, ps);
|
39
|
+
let root_id = typeof options?.traceparent == "string" ? parse(options.traceparent) : void 0, span = (name2, parent) => {
|
40
|
+
let id = parent ? parent.child() : make(), should_sample = typeof sampler != "boolean" ? sampler(name2, id, scope) : sampler;
|
41
|
+
should_sample ? id.flags | SAMPLED_FLAG : id.flags & ~SAMPLED_FLAG;
|
42
|
+
let span_obj = {
|
43
|
+
id,
|
44
|
+
parent,
|
45
|
+
start: Date.now(),
|
46
|
+
name: name2,
|
47
|
+
events: [],
|
48
|
+
context: {}
|
49
|
+
};
|
50
|
+
should_sample && span_buffer.add([span_obj, scope]);
|
51
|
+
let $ = (cb) => measureFn($, cb);
|
52
|
+
return $.traceparent = id, $.span = (name3) => span(name3, id), $.set_context = (ctx) => typeof ctx == "function" ? void (span_obj.context = ctx(span_obj.context)) : void Object.assign(span_obj.context, ctx), $.add_event = (name3, attributes) => {
|
53
|
+
span_obj.events.push({
|
54
|
+
name: name3,
|
55
|
+
timestamp: Date.now(),
|
56
|
+
attributes: attributes || {}
|
57
|
+
});
|
58
|
+
}, $.end = () => {
|
59
|
+
span_obj.end == null && (span_obj.end = Date.now());
|
60
|
+
}, $.__add_promise = (p) => {
|
61
|
+
ps.add(p), p.then(() => ps.delete(p));
|
62
|
+
}, $;
|
63
|
+
};
|
64
|
+
return {
|
65
|
+
span(name2) {
|
66
|
+
return span(name2, root_id);
|
67
|
+
}
|
68
|
+
};
|
69
|
+
}
|
70
|
+
export {
|
71
|
+
configure,
|
72
|
+
report,
|
73
|
+
tracer
|
74
|
+
};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "rian",
|
3
|
-
"version": "0.3.0-next.
|
3
|
+
"version": "0.3.0-next.9",
|
4
4
|
"description": "Effective tracing for the edge and origins",
|
5
5
|
"keywords": [
|
6
6
|
"opentelemetry",
|
@@ -60,7 +60,7 @@
|
|
60
60
|
],
|
61
61
|
"scripts": {
|
62
62
|
"bench": "node -r tsm bench/index.ts",
|
63
|
-
"build": "bundt
|
63
|
+
"build": "bundt",
|
64
64
|
"format": "prettier --write \"{*,{src,test}/**/*,examples/*/**,bench/*,.github/**/*}.+(ts|js|json|yml|md)\"",
|
65
65
|
"pretest": "pnpm run build",
|
66
66
|
"test": "uvu -r tsm test \".spec.m?ts$\"",
|
package/readme.md
CHANGED
@@ -39,7 +39,7 @@
|
|
39
39
|
> Visit [/examples](/examples) for more info!
|
40
40
|
|
41
41
|
```ts
|
42
|
-
import { create, report } from 'rian';
|
42
|
+
import { configure, create, report } from 'rian';
|
43
43
|
import { measure } from 'rian/utils';
|
44
44
|
import { exporter } from 'rian/exporter.otel.http';
|
45
45
|
|
@@ -51,12 +51,18 @@ const otel_endpoint = exporter((payload) =>
|
|
51
51
|
}),
|
52
52
|
);
|
53
53
|
|
54
|
+
// ~> Configure the environment
|
55
|
+
|
56
|
+
configure('my-service' {
|
57
|
+
'service.version': 'DEV'
|
58
|
+
});
|
59
|
+
|
54
60
|
// ~> Create a tracer — typically "per request" or "per operation"
|
55
|
-
const
|
61
|
+
const trace = tracer('request');
|
56
62
|
|
57
63
|
// Let us trace
|
58
64
|
|
59
|
-
const req =
|
65
|
+
const req = trace.span('GET ~> /data');
|
60
66
|
|
61
67
|
req.set_context({
|
62
68
|
user: request_context.user_id,
|
@@ -112,7 +118,7 @@ Implements the OpenTelemetry protocol for use with http transports.
|
|
112
118
|
<details><summary>NewRelic</summary>
|
113
119
|
|
114
120
|
```ts
|
115
|
-
import {
|
121
|
+
import { tracer, report } from 'rian';
|
116
122
|
import { exporter } from 'rian/exporter.zipkin';
|
117
123
|
|
118
124
|
const newrelic = exporter((payload) =>
|
@@ -128,7 +134,7 @@ const newrelic = exporter((payload) =>
|
|
128
134
|
}),
|
129
135
|
);
|
130
136
|
|
131
|
-
const tracer =
|
137
|
+
const tracer = tracer('my-service');
|
132
138
|
|
133
139
|
await report(newrelic);
|
134
140
|
```
|
@@ -140,7 +146,7 @@ await report(newrelic);
|
|
140
146
|
<details><summary>LightStep</summary>
|
141
147
|
|
142
148
|
```ts
|
143
|
-
import {
|
149
|
+
import { tracer, report } from 'rian';
|
144
150
|
import { exporter } from 'rian/exporter.otel.http';
|
145
151
|
|
146
152
|
const lightstep = exporter((payload) =>
|
@@ -154,7 +160,7 @@ const lightstep = exporter((payload) =>
|
|
154
160
|
}),
|
155
161
|
);
|
156
162
|
|
157
|
-
const tracer =
|
163
|
+
const tracer = tracer('my-service');
|
158
164
|
|
159
165
|
await report(lightstep);
|
160
166
|
```
|
package/utils/index.d.ts
ADDED
@@ -0,0 +1,68 @@
|
|
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
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
var r=(r,t,...e)=>{try{var n=t(...e,r),o=n instanceof Promise;return o&&r.__add_promise(n.catch((t=>{r.set_context({error:t})})).finally((()=>r.end()))),n}catch(t){throw t instanceof Error&&r.set_context({error:t}),t}finally{!0!==o&&r.end()}},t=(t,e,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
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
var r=(r,t,...e)=>{try{var n=t(...e,r),o=n instanceof Promise;return o&&r.__add_promise(n.catch((t=>{r.set_context({error:t})})).finally((()=>r.end()))),n}catch(t){throw t instanceof Error&&r.set_context({error:t}),t}finally{!0!==o&&r.end()}},t=(t,e,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};
|
package/utils.js
CHANGED
@@ -1 +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;
|
package/utils.mjs
CHANGED
@@ -1 +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
|
+
};
|