rian 0.3.7 → 0.4.0-beta.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.js +94 -1
- package/async.mjs +94 -1
- package/exporter.console.d.ts +3 -0
- package/exporter.console.js +67 -1
- package/exporter.console.mjs +67 -1
- package/exporter.otel.http.js +77 -1
- package/exporter.otel.http.mjs +77 -1
- package/exporter.zipkin.js +41 -1
- package/exporter.zipkin.mjs +41 -1
- package/index.d.ts +11 -7
- package/index.js +71 -1
- package/index.mjs +71 -1
- package/package.json +3 -3
- package/readme.md +3 -0
- package/utils.js +22 -1
- package/utils.mjs +22 -1
package/async.js
CHANGED
@@ -1 +1,94 @@
|
|
1
|
-
|
1
|
+
// src/async.ts
|
2
|
+
const async_hooks = require('node:async_hooks');
|
3
|
+
const { measure } = require('rian/utils');
|
4
|
+
const tctx = require('tctx');
|
5
|
+
|
6
|
+
// src/_internal/index.ts
|
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.4.0.beta.1"
|
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 [span2, scope] of span_buffer) {
|
20
|
+
let spans;
|
21
|
+
if (scopes.has(scope) ? spans = scopes.get(scope).spans : scopes.set(scope, {
|
22
|
+
scope,
|
23
|
+
spans: spans = []
|
24
|
+
}), spans.push(span2), wait_promises.has(scope)) {
|
25
|
+
let pss = wait_promises.get(scope);
|
26
|
+
ps.push(...pss), pss.clear();
|
27
|
+
}
|
28
|
+
}
|
29
|
+
return span_buffer.clear(), ps.length && await Promise.all(ps), exporter({
|
30
|
+
resource,
|
31
|
+
scopeSpans: scopes.values()
|
32
|
+
});
|
33
|
+
}
|
34
|
+
|
35
|
+
// src/async.ts
|
36
|
+
var resourceStore = new async_hooks.AsyncLocalStorage();
|
37
|
+
function currentSpan() {
|
38
|
+
let scope = resourceStore.getStore()?.[1];
|
39
|
+
if (scope == null)
|
40
|
+
throw new Error("no current span");
|
41
|
+
return scope;
|
42
|
+
}
|
43
|
+
function span(name, parent_id) {
|
44
|
+
let context = resourceStore.getStore();
|
45
|
+
if (!context)
|
46
|
+
throw Error("no current tracer");
|
47
|
+
let api = context[0], scope = api.scope, current_span = context[1], should_sample = api.sampler, parent = typeof parent_id == "string" ? tctx.parse(parent_id) : parent_id || current_span?.traceparent, id = parent?.child() || tctx.make(), is_sampling = typeof should_sample == "boolean" ? should_sample : should_sample(id.parent_id, parent, name, scope);
|
48
|
+
is_sampling ? tctx.sample(id) : tctx.unsample(id);
|
49
|
+
let span_obj = {
|
50
|
+
id,
|
51
|
+
parent,
|
52
|
+
name,
|
53
|
+
start: api.clock.now(),
|
54
|
+
events: [],
|
55
|
+
context: {}
|
56
|
+
};
|
57
|
+
is_sampling && span_buffer.add([span_obj, scope]);
|
58
|
+
let $ = (cb) => resourceStore.run([api, $], measure, $, cb);
|
59
|
+
$.traceparent = id, $.span = (name2) => resourceStore.run([api, $], span, name2), $.set_context = (ctx) => {
|
60
|
+
if (typeof ctx == "function")
|
61
|
+
return void (span_obj.context = ctx(span_obj.context));
|
62
|
+
Object.assign(span_obj.context, ctx);
|
63
|
+
}, $.add_event = (name2, attributes) => {
|
64
|
+
span_obj.events.push({
|
65
|
+
name: name2,
|
66
|
+
timestamp: api.clock.now(),
|
67
|
+
attributes: attributes || {}
|
68
|
+
});
|
69
|
+
}, $.end = () => {
|
70
|
+
span_obj.end == null && (span_obj.end = api.clock.now());
|
71
|
+
};
|
72
|
+
let ps = wait_promises.get(scope);
|
73
|
+
return $.__add_promise = (p) => {
|
74
|
+
ps.add(p), p.then(() => ps.delete(p));
|
75
|
+
}, $;
|
76
|
+
}
|
77
|
+
function tracer(name, options) {
|
78
|
+
let sampler = options?.sampler ?? !0, scope = { name }, api = {
|
79
|
+
scope,
|
80
|
+
sampler,
|
81
|
+
clock: options?.clock ?? Date
|
82
|
+
};
|
83
|
+
return wait_promises.set(scope, /* @__PURE__ */ new Set()), function(cb) {
|
84
|
+
let parent = resourceStore.getStore();
|
85
|
+
return resourceStore.run([api, parent?.[1] || null], cb);
|
86
|
+
};
|
87
|
+
}
|
88
|
+
|
89
|
+
|
90
|
+
exports.configure = configure;
|
91
|
+
exports.currentSpan = currentSpan;
|
92
|
+
exports.report = report;
|
93
|
+
exports.span = span;
|
94
|
+
exports.tracer = tracer;
|
package/async.mjs
CHANGED
@@ -1 +1,94 @@
|
|
1
|
-
|
1
|
+
// src/async.ts
|
2
|
+
import * as async_hooks from "node:async_hooks";
|
3
|
+
import { measure } from "rian/utils";
|
4
|
+
import * as tctx from "tctx";
|
5
|
+
|
6
|
+
// src/_internal/index.ts
|
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.4.0.beta.1"
|
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 [span2, scope] of span_buffer) {
|
20
|
+
let spans;
|
21
|
+
if (scopes.has(scope) ? spans = scopes.get(scope).spans : scopes.set(scope, {
|
22
|
+
scope,
|
23
|
+
spans: spans = []
|
24
|
+
}), spans.push(span2), wait_promises.has(scope)) {
|
25
|
+
let pss = wait_promises.get(scope);
|
26
|
+
ps.push(...pss), pss.clear();
|
27
|
+
}
|
28
|
+
}
|
29
|
+
return span_buffer.clear(), ps.length && await Promise.all(ps), exporter({
|
30
|
+
resource,
|
31
|
+
scopeSpans: scopes.values()
|
32
|
+
});
|
33
|
+
}
|
34
|
+
|
35
|
+
// src/async.ts
|
36
|
+
var resourceStore = new async_hooks.AsyncLocalStorage();
|
37
|
+
function currentSpan() {
|
38
|
+
let scope = resourceStore.getStore()?.[1];
|
39
|
+
if (scope == null)
|
40
|
+
throw new Error("no current span");
|
41
|
+
return scope;
|
42
|
+
}
|
43
|
+
function span(name, parent_id) {
|
44
|
+
let context = resourceStore.getStore();
|
45
|
+
if (!context)
|
46
|
+
throw Error("no current tracer");
|
47
|
+
let api = context[0], scope = api.scope, current_span = context[1], should_sample = api.sampler, parent = typeof parent_id == "string" ? tctx.parse(parent_id) : parent_id || current_span?.traceparent, id = parent?.child() || tctx.make(), is_sampling = typeof should_sample == "boolean" ? should_sample : should_sample(id.parent_id, parent, name, scope);
|
48
|
+
is_sampling ? tctx.sample(id) : tctx.unsample(id);
|
49
|
+
let span_obj = {
|
50
|
+
id,
|
51
|
+
parent,
|
52
|
+
name,
|
53
|
+
start: api.clock.now(),
|
54
|
+
events: [],
|
55
|
+
context: {}
|
56
|
+
};
|
57
|
+
is_sampling && span_buffer.add([span_obj, scope]);
|
58
|
+
let $ = (cb) => resourceStore.run([api, $], measure, $, cb);
|
59
|
+
$.traceparent = id, $.span = (name2) => resourceStore.run([api, $], span, name2), $.set_context = (ctx) => {
|
60
|
+
if (typeof ctx == "function")
|
61
|
+
return void (span_obj.context = ctx(span_obj.context));
|
62
|
+
Object.assign(span_obj.context, ctx);
|
63
|
+
}, $.add_event = (name2, attributes) => {
|
64
|
+
span_obj.events.push({
|
65
|
+
name: name2,
|
66
|
+
timestamp: api.clock.now(),
|
67
|
+
attributes: attributes || {}
|
68
|
+
});
|
69
|
+
}, $.end = () => {
|
70
|
+
span_obj.end == null && (span_obj.end = api.clock.now());
|
71
|
+
};
|
72
|
+
let ps = wait_promises.get(scope);
|
73
|
+
return $.__add_promise = (p) => {
|
74
|
+
ps.add(p), p.then(() => ps.delete(p));
|
75
|
+
}, $;
|
76
|
+
}
|
77
|
+
function tracer(name, options) {
|
78
|
+
let sampler = options?.sampler ?? !0, scope = { name }, api = {
|
79
|
+
scope,
|
80
|
+
sampler,
|
81
|
+
clock: options?.clock ?? Date
|
82
|
+
};
|
83
|
+
return wait_promises.set(scope, /* @__PURE__ */ new Set()), function(cb) {
|
84
|
+
let parent = resourceStore.getStore();
|
85
|
+
return resourceStore.run([api, parent?.[1] || null], cb);
|
86
|
+
};
|
87
|
+
}
|
88
|
+
export {
|
89
|
+
configure,
|
90
|
+
currentSpan,
|
91
|
+
report,
|
92
|
+
span,
|
93
|
+
tracer
|
94
|
+
};
|
package/exporter.console.js
CHANGED
@@ -1 +1,67 @@
|
|
1
|
-
|
1
|
+
// src/exporter.console.ts
|
2
|
+
var p = 1;
|
3
|
+
function exporter(max_cols = 120) {
|
4
|
+
if (max_cols < 24)
|
5
|
+
throw new Error("max_cols must be at least 24");
|
6
|
+
return function(trace) {
|
7
|
+
console.log(obj_string(trace.resource) + "─".repeat(max_cols)), max_cols = max_cols - 2;
|
8
|
+
for (let scope of trace.scopeSpans) {
|
9
|
+
let spans = scope.spans;
|
10
|
+
if (!spans.length)
|
11
|
+
return;
|
12
|
+
let tmp, i, max_time = 0, min_time = spans[0].start;
|
13
|
+
for (i = 0; tmp = scope.spans[i++]; )
|
14
|
+
max_time = Math.max(max_time, tmp.end ?? tmp.start), min_time = Math.min(min_time, tmp.start);
|
15
|
+
let t_dur = max_time - min_time, t_dur_str = format(t_dur), max_time_length = t_dur_str.length, max_time_col = max_time_length + 2, max_trace_col = Math.ceil(2 / 3 * (max_cols - max_time_col)), trace_cols = max_trace_col - (p * 2 + 2), max_name_col = max_cols - max_time_col - max_trace_col, mid = Math.ceil(trace_cols / 2), mid_str = format(t_dur / 2), mid_str_anchor = Math.ceil(mid_str.length / 2), out = "";
|
16
|
+
for (out += "╭─ ", out += scope.scope.name, out += `
|
17
|
+
`, out += "│ ", out += "╭".padStart(max_time_col), out += "─".repeat(max_trace_col), out += `╮
|
18
|
+
`, i = 0; tmp = scope.spans[i++]; ) {
|
19
|
+
let start_time = tmp.start - min_time, end_time = (tmp.end ?? max_time) - min_time, start_trace = Math.ceil(start_time / t_dur * trace_cols), end_trace = Math.ceil(end_time / t_dur * trace_cols), dur = end_time - start_time, dur_str = format(dur);
|
20
|
+
out += "│ ", out += dur_str.padStart(max_time_length), out += " │", out += " ".repeat(start_trace + p), out += "┣", out += (tmp.end ? "━" : "╍").repeat(end_trace - start_trace), out += "┫", out += " ".repeat(max_trace_col - end_trace - (p + 2)), out += "│◗ ", out += tmp.name.length + 4 > max_name_col ? tmp.name.substring(0, max_name_col - 4) + "…" : tmp.name, out += `
|
21
|
+
`;
|
22
|
+
}
|
23
|
+
out += "│ ", out += "╰".padStart(max_time_col), out += "┼", out += "┴".repeat(mid - 2), out += "┼", out += "┴".repeat(max_trace_col - mid - 1), out += "┼", out += `╯
|
24
|
+
`, out += "│ ", out += "0 ms".padStart(max_time_length + 2 + 4), out += mid_str.padStart(mid + mid_str_anchor - 4), out += t_dur_str.padStart(
|
25
|
+
trace_cols - mid + 2 - (mid_str_anchor + 4) + t_dur_str.length
|
26
|
+
), out += `
|
27
|
+
│
|
28
|
+
`, out += "│ ";
|
29
|
+
let t_dur_str_seg = format(t_dur / trace_cols), t_max_len = Math.max(t_dur_str_seg.length, t_dur_str.length);
|
30
|
+
out += tmp = `one └┘ unit is less than: ${t_dur_str_seg}
|
31
|
+
`, out += "│ ", out += `total time: ${t_dur_str.padStart(t_max_len)}`.padStart(
|
32
|
+
tmp.length - 1
|
33
|
+
), out += `
|
34
|
+
╰─`, console.log(out);
|
35
|
+
}
|
36
|
+
};
|
37
|
+
}
|
38
|
+
function obj_string(obj, line_prefix = "") {
|
39
|
+
let keys = Object.keys(obj), tmp, i, max_key = 0;
|
40
|
+
for (i = 0; tmp = keys[i++]; max_key = Math.max(max_key, tmp.length))
|
41
|
+
;
|
42
|
+
let out = "";
|
43
|
+
for (i = 0; tmp = keys[i++]; out += line_prefix + tmp.padStart(max_key) + ": " + obj[tmp] + `
|
44
|
+
`)
|
45
|
+
;
|
46
|
+
return out;
|
47
|
+
}
|
48
|
+
var MIN = 6e4, HOUR = MIN * 60, SEC = 1e3;
|
49
|
+
function dec_str(num) {
|
50
|
+
return num % 1 === 0 ? String(num) : num.toFixed(3);
|
51
|
+
}
|
52
|
+
function format(num) {
|
53
|
+
if (num < 0)
|
54
|
+
return "0 ms";
|
55
|
+
if (num < SEC)
|
56
|
+
return `${dec_str(num)} ms`;
|
57
|
+
if (num < MIN)
|
58
|
+
return `${dec_str(num / SEC)} s`;
|
59
|
+
if (num < HOUR) {
|
60
|
+
let m = Math.floor(num / MIN), s = Math.floor(num % MIN / SEC), ms = dec_str(num % SEC);
|
61
|
+
return `${m} m ${s} s ${ms} ms`;
|
62
|
+
}
|
63
|
+
return "> 1hr";
|
64
|
+
}
|
65
|
+
|
66
|
+
|
67
|
+
exports.exporter = exporter;
|
package/exporter.console.mjs
CHANGED
@@ -1 +1,67 @@
|
|
1
|
-
|
1
|
+
// src/exporter.console.ts
|
2
|
+
var p = 1;
|
3
|
+
function exporter(max_cols = 120) {
|
4
|
+
if (max_cols < 24)
|
5
|
+
throw new Error("max_cols must be at least 24");
|
6
|
+
return function(trace) {
|
7
|
+
console.log(obj_string(trace.resource) + "─".repeat(max_cols)), max_cols = max_cols - 2;
|
8
|
+
for (let scope of trace.scopeSpans) {
|
9
|
+
let spans = scope.spans;
|
10
|
+
if (!spans.length)
|
11
|
+
return;
|
12
|
+
let tmp, i, max_time = 0, min_time = spans[0].start;
|
13
|
+
for (i = 0; tmp = scope.spans[i++]; )
|
14
|
+
max_time = Math.max(max_time, tmp.end ?? tmp.start), min_time = Math.min(min_time, tmp.start);
|
15
|
+
let t_dur = max_time - min_time, t_dur_str = format(t_dur), max_time_length = t_dur_str.length, max_time_col = max_time_length + 2, max_trace_col = Math.ceil(2 / 3 * (max_cols - max_time_col)), trace_cols = max_trace_col - (p * 2 + 2), max_name_col = max_cols - max_time_col - max_trace_col, mid = Math.ceil(trace_cols / 2), mid_str = format(t_dur / 2), mid_str_anchor = Math.ceil(mid_str.length / 2), out = "";
|
16
|
+
for (out += "╭─ ", out += scope.scope.name, out += `
|
17
|
+
`, out += "│ ", out += "╭".padStart(max_time_col), out += "─".repeat(max_trace_col), out += `╮
|
18
|
+
`, i = 0; tmp = scope.spans[i++]; ) {
|
19
|
+
let start_time = tmp.start - min_time, end_time = (tmp.end ?? max_time) - min_time, start_trace = Math.ceil(start_time / t_dur * trace_cols), end_trace = Math.ceil(end_time / t_dur * trace_cols), dur = end_time - start_time, dur_str = format(dur);
|
20
|
+
out += "│ ", out += dur_str.padStart(max_time_length), out += " │", out += " ".repeat(start_trace + p), out += "┣", out += (tmp.end ? "━" : "╍").repeat(end_trace - start_trace), out += "┫", out += " ".repeat(max_trace_col - end_trace - (p + 2)), out += "│◗ ", out += tmp.name.length + 4 > max_name_col ? tmp.name.substring(0, max_name_col - 4) + "…" : tmp.name, out += `
|
21
|
+
`;
|
22
|
+
}
|
23
|
+
out += "│ ", out += "╰".padStart(max_time_col), out += "┼", out += "┴".repeat(mid - 2), out += "┼", out += "┴".repeat(max_trace_col - mid - 1), out += "┼", out += `╯
|
24
|
+
`, out += "│ ", out += "0 ms".padStart(max_time_length + 2 + 4), out += mid_str.padStart(mid + mid_str_anchor - 4), out += t_dur_str.padStart(
|
25
|
+
trace_cols - mid + 2 - (mid_str_anchor + 4) + t_dur_str.length
|
26
|
+
), out += `
|
27
|
+
│
|
28
|
+
`, out += "│ ";
|
29
|
+
let t_dur_str_seg = format(t_dur / trace_cols), t_max_len = Math.max(t_dur_str_seg.length, t_dur_str.length);
|
30
|
+
out += tmp = `one └┘ unit is less than: ${t_dur_str_seg}
|
31
|
+
`, out += "│ ", out += `total time: ${t_dur_str.padStart(t_max_len)}`.padStart(
|
32
|
+
tmp.length - 1
|
33
|
+
), out += `
|
34
|
+
╰─`, console.log(out);
|
35
|
+
}
|
36
|
+
};
|
37
|
+
}
|
38
|
+
function obj_string(obj, line_prefix = "") {
|
39
|
+
let keys = Object.keys(obj), tmp, i, max_key = 0;
|
40
|
+
for (i = 0; tmp = keys[i++]; max_key = Math.max(max_key, tmp.length))
|
41
|
+
;
|
42
|
+
let out = "";
|
43
|
+
for (i = 0; tmp = keys[i++]; out += line_prefix + tmp.padStart(max_key) + ": " + obj[tmp] + `
|
44
|
+
`)
|
45
|
+
;
|
46
|
+
return out;
|
47
|
+
}
|
48
|
+
var MIN = 6e4, HOUR = MIN * 60, SEC = 1e3;
|
49
|
+
function dec_str(num) {
|
50
|
+
return num % 1 === 0 ? String(num) : num.toFixed(3);
|
51
|
+
}
|
52
|
+
function format(num) {
|
53
|
+
if (num < 0)
|
54
|
+
return "0 ms";
|
55
|
+
if (num < SEC)
|
56
|
+
return `${dec_str(num)} ms`;
|
57
|
+
if (num < MIN)
|
58
|
+
return `${dec_str(num / SEC)} s`;
|
59
|
+
if (num < HOUR) {
|
60
|
+
let m = Math.floor(num / MIN), s = Math.floor(num % MIN / SEC), ms = dec_str(num % SEC);
|
61
|
+
return `${m} m ${s} s ${ms} ms`;
|
62
|
+
}
|
63
|
+
return "> 1hr";
|
64
|
+
}
|
65
|
+
export {
|
66
|
+
exporter
|
67
|
+
};
|
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
|
+
};
|
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.d.ts
CHANGED
@@ -27,7 +27,7 @@ export type Options = {
|
|
27
27
|
/**
|
28
28
|
* @borrows {@link Sampler}
|
29
29
|
*/
|
30
|
-
sampler?: Sampler | boolean;
|
30
|
+
sampler?: typeof Sampler | boolean;
|
31
31
|
|
32
32
|
clock?: ClockLike;
|
33
33
|
};
|
@@ -47,20 +47,24 @@ export type Context = {
|
|
47
47
|
* Return true if the span should be sampled, and reported to the {@link Exporter}.
|
48
48
|
* Return false if the span should not be sampled, and not reported to the {@link Exporter}.
|
49
49
|
*/
|
50
|
-
export
|
50
|
+
export function Sampler(
|
51
51
|
/**
|
52
|
-
* The
|
52
|
+
* The id of the new span looking for a sampling decision.
|
53
|
+
*/
|
54
|
+
id: string,
|
55
|
+
/**
|
56
|
+
* The traceparent of the new span looking for a sampling decision.
|
53
57
|
*/
|
54
|
-
|
58
|
+
parent: Traceparent | undefined,
|
55
59
|
/**
|
56
|
-
* The
|
60
|
+
* The name of the span.
|
57
61
|
*/
|
58
|
-
|
62
|
+
name: string,
|
59
63
|
/**
|
60
64
|
* The tracer this span belongs to.
|
61
65
|
*/
|
62
66
|
tracer: { readonly name: string },
|
63
|
-
)
|
67
|
+
): boolean;
|
64
68
|
|
65
69
|
// --- spans
|
66
70
|
|
package/index.js
CHANGED
@@ -1 +1,71 @@
|
|
1
|
-
|
1
|
+
// src/index.ts
|
2
|
+
const { measure } = require('rian/utils');
|
3
|
+
|
4
|
+
// src/_internal/index.ts
|
5
|
+
var resource = {};
|
6
|
+
function configure(name, attributes = {}) {
|
7
|
+
resource = {
|
8
|
+
...attributes,
|
9
|
+
["service.name"]: name,
|
10
|
+
["telemetry.sdk.name"]: "rian",
|
11
|
+
["telemetry.sdk.version"]: "0.4.0.beta.1"
|
12
|
+
};
|
13
|
+
}
|
14
|
+
var span_buffer = /* @__PURE__ */ new Set(), wait_promises = /* @__PURE__ */ new WeakMap();
|
15
|
+
async function report(exporter) {
|
16
|
+
let ps = [], scopes = /* @__PURE__ */ new Map();
|
17
|
+
for (let [span, scope] of span_buffer) {
|
18
|
+
let spans;
|
19
|
+
if (scopes.has(scope) ? spans = scopes.get(scope).spans : scopes.set(scope, {
|
20
|
+
scope,
|
21
|
+
spans: spans = []
|
22
|
+
}), spans.push(span), wait_promises.has(scope)) {
|
23
|
+
let pss = wait_promises.get(scope);
|
24
|
+
ps.push(...pss), pss.clear();
|
25
|
+
}
|
26
|
+
}
|
27
|
+
return span_buffer.clear(), ps.length && await Promise.all(ps), exporter({
|
28
|
+
resource,
|
29
|
+
scopeSpans: scopes.values()
|
30
|
+
});
|
31
|
+
}
|
32
|
+
|
33
|
+
// src/index.ts
|
34
|
+
const tctx = require('tctx');
|
35
|
+
function tracer(name, options) {
|
36
|
+
let should_sample = options?.sampler ?? !0, clock = options?.clock ?? Date, scope = { name }, ps = /* @__PURE__ */ new Set();
|
37
|
+
wait_promises.set(scope, ps);
|
38
|
+
let span = (name2, parent_id) => {
|
39
|
+
let parent = typeof parent_id == "string" ? tctx.parse(parent_id) : parent_id, id = parent?.child() || tctx.make(), is_sampling = typeof should_sample == "boolean" ? should_sample : should_sample(id.parent_id, parent, name2, scope);
|
40
|
+
is_sampling ? tctx.sample(id) : tctx.unsample(id);
|
41
|
+
let span_obj = {
|
42
|
+
id,
|
43
|
+
parent,
|
44
|
+
name: name2,
|
45
|
+
start: clock.now(),
|
46
|
+
events: [],
|
47
|
+
context: {}
|
48
|
+
};
|
49
|
+
is_sampling && span_buffer.add([span_obj, scope]);
|
50
|
+
let $ = (cb) => measure($, cb);
|
51
|
+
return $.traceparent = id, $.span = (name3, p_id) => span(name3, p_id || 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) => {
|
52
|
+
span_obj.events.push({
|
53
|
+
name: name3,
|
54
|
+
timestamp: clock.now(),
|
55
|
+
attributes: attributes || {}
|
56
|
+
});
|
57
|
+
}, $.end = () => {
|
58
|
+
span_obj.end == null && (span_obj.end = clock.now());
|
59
|
+
}, $.__add_promise = (p) => {
|
60
|
+
ps.add(p), p.then(() => ps.delete(p));
|
61
|
+
}, $;
|
62
|
+
};
|
63
|
+
return {
|
64
|
+
span
|
65
|
+
};
|
66
|
+
}
|
67
|
+
|
68
|
+
|
69
|
+
exports.configure = configure;
|
70
|
+
exports.report = report;
|
71
|
+
exports.tracer = tracer;
|
package/index.mjs
CHANGED
@@ -1 +1,71 @@
|
|
1
|
-
|
1
|
+
// src/index.ts
|
2
|
+
import { measure } from "rian/utils";
|
3
|
+
|
4
|
+
// src/_internal/index.ts
|
5
|
+
var resource = {};
|
6
|
+
function configure(name, attributes = {}) {
|
7
|
+
resource = {
|
8
|
+
...attributes,
|
9
|
+
["service.name"]: name,
|
10
|
+
["telemetry.sdk.name"]: "rian",
|
11
|
+
["telemetry.sdk.version"]: "0.4.0.beta.1"
|
12
|
+
};
|
13
|
+
}
|
14
|
+
var span_buffer = /* @__PURE__ */ new Set(), wait_promises = /* @__PURE__ */ new WeakMap();
|
15
|
+
async function report(exporter) {
|
16
|
+
let ps = [], scopes = /* @__PURE__ */ new Map();
|
17
|
+
for (let [span, scope] of span_buffer) {
|
18
|
+
let spans;
|
19
|
+
if (scopes.has(scope) ? spans = scopes.get(scope).spans : scopes.set(scope, {
|
20
|
+
scope,
|
21
|
+
spans: spans = []
|
22
|
+
}), spans.push(span), wait_promises.has(scope)) {
|
23
|
+
let pss = wait_promises.get(scope);
|
24
|
+
ps.push(...pss), pss.clear();
|
25
|
+
}
|
26
|
+
}
|
27
|
+
return span_buffer.clear(), ps.length && await Promise.all(ps), exporter({
|
28
|
+
resource,
|
29
|
+
scopeSpans: scopes.values()
|
30
|
+
});
|
31
|
+
}
|
32
|
+
|
33
|
+
// src/index.ts
|
34
|
+
import * as tctx from "tctx";
|
35
|
+
function tracer(name, options) {
|
36
|
+
let should_sample = options?.sampler ?? !0, clock = options?.clock ?? Date, scope = { name }, ps = /* @__PURE__ */ new Set();
|
37
|
+
wait_promises.set(scope, ps);
|
38
|
+
let span = (name2, parent_id) => {
|
39
|
+
let parent = typeof parent_id == "string" ? tctx.parse(parent_id) : parent_id, id = parent?.child() || tctx.make(), is_sampling = typeof should_sample == "boolean" ? should_sample : should_sample(id.parent_id, parent, name2, scope);
|
40
|
+
is_sampling ? tctx.sample(id) : tctx.unsample(id);
|
41
|
+
let span_obj = {
|
42
|
+
id,
|
43
|
+
parent,
|
44
|
+
name: name2,
|
45
|
+
start: clock.now(),
|
46
|
+
events: [],
|
47
|
+
context: {}
|
48
|
+
};
|
49
|
+
is_sampling && span_buffer.add([span_obj, scope]);
|
50
|
+
let $ = (cb) => measure($, cb);
|
51
|
+
return $.traceparent = id, $.span = (name3, p_id) => span(name3, p_id || 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) => {
|
52
|
+
span_obj.events.push({
|
53
|
+
name: name3,
|
54
|
+
timestamp: clock.now(),
|
55
|
+
attributes: attributes || {}
|
56
|
+
});
|
57
|
+
}, $.end = () => {
|
58
|
+
span_obj.end == null && (span_obj.end = clock.now());
|
59
|
+
}, $.__add_promise = (p) => {
|
60
|
+
ps.add(p), p.then(() => ps.delete(p));
|
61
|
+
}, $;
|
62
|
+
};
|
63
|
+
return {
|
64
|
+
span
|
65
|
+
};
|
66
|
+
}
|
67
|
+
export {
|
68
|
+
configure,
|
69
|
+
report,
|
70
|
+
tracer
|
71
|
+
};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "rian",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.4.0-beta.1",
|
4
4
|
"description": "Effective tracing for the edge and origins",
|
5
5
|
"keywords": [
|
6
6
|
"opentelemetry",
|
@@ -65,7 +65,7 @@
|
|
65
65
|
],
|
66
66
|
"scripts": {
|
67
67
|
"bench": "node -r tsm bench/index.ts",
|
68
|
-
"build": "bundt
|
68
|
+
"build": "bundt",
|
69
69
|
"format": "prettier --write \"{*,{src,test}/**/*,examples/*/**,bench/*,.github/**/*}.+(ts|js|json|yml|md)\"",
|
70
70
|
"test": "uvu src \".test.ts$\" -r tsm",
|
71
71
|
"typecheck": "tsc --noEmit"
|
@@ -73,7 +73,7 @@
|
|
73
73
|
"prettier": "@marais/prettier",
|
74
74
|
"dependencies": {
|
75
75
|
"flattie": "^1.1.0",
|
76
|
-
"tctx": "
|
76
|
+
"tctx": "tctx@0.2.1-beta.1"
|
77
77
|
},
|
78
78
|
"devDependencies": {
|
79
79
|
"@marais/prettier": "0.0.4",
|
package/readme.md
CHANGED
@@ -12,6 +12,9 @@
|
|
12
12
|
<a href="https://npm-stat.com/charts.html?package=rian">
|
13
13
|
<img src="https://badgen.net/npm/dm/rian?color=black&label=npm%20downloads" alt="js downloads">
|
14
14
|
</a>
|
15
|
+
<a href="https://licenses.dev/npm/rian">
|
16
|
+
<img src="https://licenses.dev/b/npm/rian?style=dark" alt="licenses" />
|
17
|
+
</a>
|
15
18
|
<a href="https://unpkg.com/rian/index.mjs">
|
16
19
|
<img src="https://img.badgesize.io/https://unpkg.com/rian/index.mjs?compression=gzip&label=gzip&color=black" alt="gzip size" />
|
17
20
|
</a>
|
package/utils.js
CHANGED
@@ -1 +1,22 @@
|
|
1
|
-
|
1
|
+
// src/utils.ts
|
2
|
+
function measure(scope, fn) {
|
3
|
+
try {
|
4
|
+
var r = fn(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
|
+
}
|
20
|
+
|
21
|
+
|
22
|
+
exports.measure = measure;
|
package/utils.mjs
CHANGED
@@ -1 +1,22 @@
|
|
1
|
-
|
1
|
+
// src/utils.ts
|
2
|
+
function measure(scope, fn) {
|
3
|
+
try {
|
4
|
+
var r = fn(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
|
+
}
|
20
|
+
export {
|
21
|
+
measure
|
22
|
+
};
|