@ultimat3/core 10.0.0 → 11.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/package.json +1 -1
- package/src/logger.ts +23 -1
- package/src/metrics.ts +15 -5
package/package.json
CHANGED
package/src/logger.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Single responsibility: structured JSON logging. One line per event, machine-readable by
|
|
2
2
|
// default because the primary reader is an agent tailing `x logs --json`.
|
|
3
3
|
|
|
4
|
+
import { assert } from './assert';
|
|
4
5
|
import { type Clock, systemClock } from './clock';
|
|
5
6
|
import { renderCauseValue } from './error-render';
|
|
6
7
|
import { isUltimateError } from './errors';
|
|
@@ -244,8 +245,29 @@ function envLevel(): LogLevel {
|
|
|
244
245
|
: 'info';
|
|
245
246
|
}
|
|
246
247
|
|
|
248
|
+
/**
|
|
249
|
+
* The level this logger enforces, refused when it is not one.
|
|
250
|
+
*
|
|
251
|
+
* `LEVEL_WEIGHT[level]` on anything else is `undefined`, and every `weight < undefined` is false —
|
|
252
|
+
* so the threshold failed OPEN and the logger emitted every line at every level. That is a `trace`
|
|
253
|
+
* stream out of a production process from one typo, which is the direction this read must never
|
|
254
|
+
* fail in. `LOG_LEVELS`, the same list `envLevel()` filters `LOG_LEVEL` through, because a level
|
|
255
|
+
* is typed here and arrives untyped: an `app.config.ts` value, a JSON file, a CLI flag.
|
|
256
|
+
*/
|
|
257
|
+
function resolveLevel(declared: LogLevel): LogLevel {
|
|
258
|
+
assert(
|
|
259
|
+
(LOG_LEVELS as readonly unknown[]).includes(declared),
|
|
260
|
+
// `renderCauseValue`, never `JSON.stringify`: it raises on a bigint and on a cycle, and a
|
|
261
|
+
// level that arrived from a config file can be either — the refusal must not be replaced by
|
|
262
|
+
// a `TypeError` from building its own message.
|
|
263
|
+
`${renderCauseValue(declared)} is not a log level`,
|
|
264
|
+
`pass one of ${LOG_LEVELS.join(', ')} to createLogger({ level })`,
|
|
265
|
+
);
|
|
266
|
+
return declared;
|
|
267
|
+
}
|
|
268
|
+
|
|
247
269
|
export function createLogger(options?: LoggerOptions): Logger {
|
|
248
|
-
const level = options?.level
|
|
270
|
+
const level = options?.level === undefined ? envLevel() : resolveLevel(options.level);
|
|
249
271
|
const bound = options?.fields ?? {};
|
|
250
272
|
const clock = options?.clock ?? systemClock;
|
|
251
273
|
const writer = options?.writer ?? defaultWriter;
|
package/src/metrics.ts
CHANGED
|
@@ -174,14 +174,24 @@ export function resetMetrics(): void {
|
|
|
174
174
|
}
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
-
/**
|
|
177
|
+
/**
|
|
178
|
+
* Stable series key: attribute order must not create a second series for one label set, and no
|
|
179
|
+
* label set may spell another one's key.
|
|
180
|
+
*
|
|
181
|
+
* `JSON.stringify` over the sorted pairs, because a DELIMITER cannot carry the second property:
|
|
182
|
+
* the key was the pairs joined by control characters (U+0000 inside a pair, U+0001 between them),
|
|
183
|
+
* and a value holding those bytes IS another set's key — `{ a: 'b\u0001c\u0000d' }` was
|
|
184
|
+
* `{ a: 'b', c: 'd' }`, so the point landed on whichever series arrived first and was exported
|
|
185
|
+
* under labels the caller never passed. Attribute values are app data. Quoting is the only total
|
|
186
|
+
* answer and is not slower: 644 ns/op against the join's 709, on a 3-label set. `String(value)`
|
|
187
|
+
* stays, so `1` and `'1'` are still one series rather than two rows an exporter renders alike.
|
|
188
|
+
*/
|
|
178
189
|
function seriesKey(attributes: MetricAttributes): string {
|
|
179
190
|
const entries = Object.entries(attributes);
|
|
180
191
|
if (entries.length === 0) return '';
|
|
181
|
-
return
|
|
182
|
-
.sort(([a], [b]) => (a < b ? -1 : 1))
|
|
183
|
-
|
|
184
|
-
.join('');
|
|
192
|
+
return JSON.stringify(
|
|
193
|
+
entries.sort(([a], [b]) => (a < b ? -1 : 1)).map(([key, value]) => [key, String(value)]),
|
|
194
|
+
);
|
|
185
195
|
}
|
|
186
196
|
|
|
187
197
|
function finite(name: string, value: number): number {
|