@voidcli/logging 0.1.0
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/dist/client/index.d.ts +3 -0
- package/dist/client/index.js +19 -0
- package/dist/client/logger.d.ts +9 -0
- package/dist/client/logger.js +27 -0
- package/dist/client/telemetry.d.ts +9 -0
- package/dist/client/telemetry.js +18 -0
- package/dist/client/telemetryLogger.d.ts +21 -0
- package/dist/client/telemetryLogger.js +117 -0
- package/dist/index.d.ts +0 -0
- package/dist/index.js +1 -0
- package/dist/models/index.d.ts +34 -0
- package/dist/models/index.js +12 -0
- package/package.json +13 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./telemetryLogger"), exports);
|
|
18
|
+
__exportStar(require("./logger"), exports);
|
|
19
|
+
__exportStar(require("./telemetry"), exports);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { TelemetryLogger } from "./telemetryLogger";
|
|
2
|
+
export declare class Logger<ProjectFields extends Record<string, unknown>> {
|
|
3
|
+
private readonly client;
|
|
4
|
+
constructor(client: TelemetryLogger<ProjectFields>);
|
|
5
|
+
log(verbosity: number, section: string, raw: Record<string, unknown>, projectFields: ProjectFields): void;
|
|
6
|
+
info(section: string, raw: Record<string, unknown>, projectFields: ProjectFields): void;
|
|
7
|
+
warn(section: string, raw: Record<string, unknown>, projectFields: ProjectFields): void;
|
|
8
|
+
error(section: string, raw: Record<string, unknown>, projectFields: ProjectFields): void;
|
|
9
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Logger = void 0;
|
|
4
|
+
const models_1 = require("../models");
|
|
5
|
+
class Logger {
|
|
6
|
+
constructor(client) {
|
|
7
|
+
this.client = client;
|
|
8
|
+
}
|
|
9
|
+
log(verbosity, section, raw, projectFields) {
|
|
10
|
+
this.client.enqueueLog({
|
|
11
|
+
verbosity,
|
|
12
|
+
section,
|
|
13
|
+
raw,
|
|
14
|
+
...projectFields,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
info(section, raw, projectFields) {
|
|
18
|
+
this.log(models_1.Verbosity.info, section, raw, projectFields);
|
|
19
|
+
}
|
|
20
|
+
warn(section, raw, projectFields) {
|
|
21
|
+
this.log(models_1.Verbosity.warn, section, raw, projectFields);
|
|
22
|
+
}
|
|
23
|
+
error(section, raw, projectFields) {
|
|
24
|
+
this.log(models_1.Verbosity.error, section, raw, projectFields);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.Logger = Logger;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { TelemetryLogger } from "./telemetryLogger";
|
|
2
|
+
export declare class Telemetry<ProjectFields extends Record<string, unknown>> {
|
|
3
|
+
private readonly client;
|
|
4
|
+
constructor(client: TelemetryLogger<ProjectFields>);
|
|
5
|
+
gauge(name: string, value: number, projectFields: ProjectFields, opts?: {
|
|
6
|
+
unit?: string;
|
|
7
|
+
tags?: Record<string, string>;
|
|
8
|
+
}): void;
|
|
9
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Telemetry = void 0;
|
|
4
|
+
class Telemetry {
|
|
5
|
+
constructor(client) {
|
|
6
|
+
this.client = client;
|
|
7
|
+
}
|
|
8
|
+
gauge(name, value, projectFields, opts) {
|
|
9
|
+
this.client.enqueueMetric({
|
|
10
|
+
name,
|
|
11
|
+
value,
|
|
12
|
+
unit: opts?.unit,
|
|
13
|
+
tags: opts?.tags,
|
|
14
|
+
...projectFields,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.Telemetry = Telemetry;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { LogEvent, MetricEvent, TelemetryClientConfig } from "../models";
|
|
2
|
+
export declare class TelemetryLogger<ProjectFields extends Record<string, unknown> = {}> {
|
|
3
|
+
private readonly config;
|
|
4
|
+
private static instance;
|
|
5
|
+
private logsQueue;
|
|
6
|
+
private metricsQueue;
|
|
7
|
+
private logVerbosityMask;
|
|
8
|
+
private flushIntervalSeconds;
|
|
9
|
+
private timer;
|
|
10
|
+
private flushing;
|
|
11
|
+
static init<P extends Record<string, unknown>>(config: TelemetryClientConfig): TelemetryLogger<P>;
|
|
12
|
+
static get<P extends Record<string, unknown>>(): TelemetryLogger<P>;
|
|
13
|
+
private constructor();
|
|
14
|
+
setLogVerbosity(mask: number): void;
|
|
15
|
+
setFlushIntervalSeconds(seconds: number): void;
|
|
16
|
+
private applyFlushSchedule;
|
|
17
|
+
enqueueLog(item: LogEvent<ProjectFields>): void;
|
|
18
|
+
enqueueMetric(item: MetricEvent<ProjectFields>): void;
|
|
19
|
+
flush(): void;
|
|
20
|
+
shutdown(): Promise<void>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TelemetryLogger = void 0;
|
|
4
|
+
const models_1 = require("../models");
|
|
5
|
+
class TelemetryLogger {
|
|
6
|
+
static init(config) {
|
|
7
|
+
const inst = new TelemetryLogger(config);
|
|
8
|
+
TelemetryLogger.instance = inst;
|
|
9
|
+
return inst;
|
|
10
|
+
}
|
|
11
|
+
static get() {
|
|
12
|
+
if (!TelemetryLogger.instance) {
|
|
13
|
+
throw new Error("TelemetryClient not initialized. Call TelemetryClient.init(...) first.");
|
|
14
|
+
}
|
|
15
|
+
return TelemetryLogger.instance;
|
|
16
|
+
}
|
|
17
|
+
constructor(config) {
|
|
18
|
+
this.config = config;
|
|
19
|
+
this.logsQueue = [];
|
|
20
|
+
this.metricsQueue = [];
|
|
21
|
+
this.logVerbosityMask = models_1.Verbosity.all;
|
|
22
|
+
this.timer = null;
|
|
23
|
+
this.flushing = false;
|
|
24
|
+
this.flushIntervalSeconds = config.flushIntervalSeconds ?? 10;
|
|
25
|
+
if (this.config.enabled !== false)
|
|
26
|
+
this.applyFlushSchedule();
|
|
27
|
+
}
|
|
28
|
+
setLogVerbosity(mask) {
|
|
29
|
+
this.logVerbosityMask = mask;
|
|
30
|
+
}
|
|
31
|
+
setFlushIntervalSeconds(seconds) {
|
|
32
|
+
if (seconds < 0 || !Number.isFinite(seconds)) {
|
|
33
|
+
throw new Error("flushIntervalSeconds must be a non-negative finite number.");
|
|
34
|
+
}
|
|
35
|
+
this.flushIntervalSeconds = seconds;
|
|
36
|
+
if (this.config.enabled !== false)
|
|
37
|
+
this.applyFlushSchedule();
|
|
38
|
+
}
|
|
39
|
+
applyFlushSchedule() {
|
|
40
|
+
// stop any existing timer
|
|
41
|
+
if (this.timer) {
|
|
42
|
+
clearInterval(this.timer);
|
|
43
|
+
this.timer = null;
|
|
44
|
+
}
|
|
45
|
+
// immediate mode => no timer
|
|
46
|
+
if (this.flushIntervalSeconds === 0)
|
|
47
|
+
return;
|
|
48
|
+
// timer-based mode
|
|
49
|
+
this.timer = setInterval(() => void this.flush(), this.flushIntervalSeconds * 1000);
|
|
50
|
+
this.timer?.unref?.();
|
|
51
|
+
}
|
|
52
|
+
enqueueLog(item) {
|
|
53
|
+
if (this.config.enabled === false)
|
|
54
|
+
return;
|
|
55
|
+
if ((this.logVerbosityMask & item.verbosity) === 0)
|
|
56
|
+
return;
|
|
57
|
+
this.logsQueue.push(item);
|
|
58
|
+
// immediate mode: flush right away (don’t await)
|
|
59
|
+
if (this.flushIntervalSeconds === 0)
|
|
60
|
+
void this.flush();
|
|
61
|
+
}
|
|
62
|
+
enqueueMetric(item) {
|
|
63
|
+
if (this.config.enabled === false)
|
|
64
|
+
return;
|
|
65
|
+
this.metricsQueue.push(item);
|
|
66
|
+
// immediate mode: flush right away (don’t await)
|
|
67
|
+
if (this.flushIntervalSeconds === 0)
|
|
68
|
+
void this.flush();
|
|
69
|
+
}
|
|
70
|
+
flush() {
|
|
71
|
+
if (this.config.enabled === false)
|
|
72
|
+
return;
|
|
73
|
+
if (this.flushing)
|
|
74
|
+
return;
|
|
75
|
+
if (this.logsQueue.length === 0 && this.metricsQueue.length === 0)
|
|
76
|
+
return;
|
|
77
|
+
this.flushing = true;
|
|
78
|
+
const logs = this.logsQueue;
|
|
79
|
+
const metrics = this.metricsQueue;
|
|
80
|
+
this.logsQueue = [];
|
|
81
|
+
this.metricsQueue = [];
|
|
82
|
+
const batch = {
|
|
83
|
+
ts: Date.now(),
|
|
84
|
+
logs,
|
|
85
|
+
metrics,
|
|
86
|
+
};
|
|
87
|
+
void fetch(`${this.config.url}/ingest`, {
|
|
88
|
+
method: "POST",
|
|
89
|
+
headers: {
|
|
90
|
+
"content-type": "application/json",
|
|
91
|
+
"x-api-key": this.config.apiKey,
|
|
92
|
+
"x-ingest-key": this.config.ingestKey,
|
|
93
|
+
},
|
|
94
|
+
body: JSON.stringify(batch),
|
|
95
|
+
keepalive: true,
|
|
96
|
+
})
|
|
97
|
+
.then((res) => {
|
|
98
|
+
})
|
|
99
|
+
.catch(() => {
|
|
100
|
+
// drop on network error (do nothing)
|
|
101
|
+
})
|
|
102
|
+
.finally(() => {
|
|
103
|
+
this.flushing = false;
|
|
104
|
+
// if new items arrived while sending, kick another flush
|
|
105
|
+
if (this.logsQueue.length || this.metricsQueue.length)
|
|
106
|
+
this.flush();
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
async shutdown() {
|
|
110
|
+
if (this.timer)
|
|
111
|
+
clearInterval(this.timer);
|
|
112
|
+
this.timer = null;
|
|
113
|
+
await this.flush();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
exports.TelemetryLogger = TelemetryLogger;
|
|
117
|
+
TelemetryLogger.instance = null;
|
package/dist/index.d.ts
ADDED
|
File without changes
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export declare const Verbosity: {
|
|
2
|
+
readonly trace: 2;
|
|
3
|
+
readonly debug: 4;
|
|
4
|
+
readonly info: 8;
|
|
5
|
+
readonly warn: 16;
|
|
6
|
+
readonly error: 32;
|
|
7
|
+
readonly fatal: 64;
|
|
8
|
+
readonly all: number;
|
|
9
|
+
};
|
|
10
|
+
export type Verbosity = (typeof Verbosity)[keyof typeof Verbosity];
|
|
11
|
+
export type TelemetryClientConfig = {
|
|
12
|
+
url: string;
|
|
13
|
+
apiKey: string;
|
|
14
|
+
ingestKey: string;
|
|
15
|
+
enabled?: boolean;
|
|
16
|
+
flushIntervalSeconds?: number;
|
|
17
|
+
};
|
|
18
|
+
export type LogEvent<ProjectFields extends Record<string, unknown>> = ProjectFields & {
|
|
19
|
+
verbosity: number;
|
|
20
|
+
section: string;
|
|
21
|
+
raw: Record<string, unknown>;
|
|
22
|
+
};
|
|
23
|
+
export type MetricEvent<ProjectFields extends Record<string, unknown>> = ProjectFields & {
|
|
24
|
+
name: string;
|
|
25
|
+
value: number;
|
|
26
|
+
unit?: string;
|
|
27
|
+
tags?: Record<string, string>;
|
|
28
|
+
};
|
|
29
|
+
export type TelemetryItem<ProjectFields extends Record<string, unknown>> = LogEvent<ProjectFields> | MetricEvent<ProjectFields>;
|
|
30
|
+
export type IngestBatch<ProjectFields extends Record<string, unknown>> = {
|
|
31
|
+
ts?: number;
|
|
32
|
+
logs: Array<LogEvent<ProjectFields>>;
|
|
33
|
+
metrics: Array<MetricEvent<ProjectFields>>;
|
|
34
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@voidcli/logging",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "VoidCLI Telemetry logging client",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": ["dist"],
|
|
8
|
+
"scripts": {
|
|
9
|
+
"clean": "rimraf dist",
|
|
10
|
+
"build": "tsc -p tsconfig.json"
|
|
11
|
+
},
|
|
12
|
+
"license": "MIT"
|
|
13
|
+
}
|