@dxos/log 0.10.0 → 0.11.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/dist/lib/chunk-context.mjs +307 -0
- package/dist/lib/chunk-context.mjs.map +1 -0
- package/dist/lib/index.mjs +619 -0
- package/dist/lib/index.mjs.map +1 -0
- package/dist/lib/platform/browser.mjs +18 -0
- package/dist/lib/platform/browser.mjs.map +1 -0
- package/dist/lib/platform/node.mjs +18 -0
- package/dist/lib/platform/node.mjs.map +1 -0
- package/dist/lib/processors/console-processor.mjs +86 -0
- package/dist/lib/processors/console-processor.mjs.map +1 -0
- package/dist/lib/processors/console-stub.mjs +6 -0
- package/dist/lib/processors/console-stub.mjs.map +1 -0
- package/dist/lib/processors/file-processor.mjs +62 -0
- package/dist/lib/processors/file-processor.mjs.map +1 -0
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/registry.d.ts +28 -0
- package/dist/types/src/registry.d.ts.map +1 -0
- package/dist/types/src/registry.test.d.ts +2 -0
- package/dist/types/src/registry.test.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -18
- package/src/context.ts +32 -3
- package/src/index.ts +1 -0
- package/src/platform/browser/index.ts +2 -2
- package/src/registry.test.ts +56 -0
- package/src/registry.ts +63 -0
- package/dist/lib/browser/chunk-ALZAGDFJ.mjs +0 -311
- package/dist/lib/browser/chunk-ALZAGDFJ.mjs.map +0 -7
- package/dist/lib/browser/chunk-IEP6GGEX.mjs +0 -23
- package/dist/lib/browser/chunk-IEP6GGEX.mjs.map +0 -7
- package/dist/lib/browser/index.mjs +0 -667
- package/dist/lib/browser/index.mjs.map +0 -7
- package/dist/lib/browser/meta.json +0 -1
- package/dist/lib/browser/platform/browser/index.mjs +0 -26
- package/dist/lib/browser/platform/browser/index.mjs.map +0 -7
- package/dist/lib/browser/platform/node/index.mjs +0 -21
- package/dist/lib/browser/platform/node/index.mjs.map +0 -7
- package/dist/lib/browser/processors/console-processor.mjs +0 -102
- package/dist/lib/browser/processors/console-processor.mjs.map +0 -7
- package/dist/lib/browser/processors/console-stub.mjs +0 -9
- package/dist/lib/browser/processors/console-stub.mjs.map +0 -7
- package/dist/lib/browser/processors/file-processor.mjs +0 -75
- package/dist/lib/browser/processors/file-processor.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-2SZHAWBN.mjs +0 -24
- package/dist/lib/node-esm/chunk-2SZHAWBN.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-RKEZ3A6V.mjs +0 -313
- package/dist/lib/node-esm/chunk-RKEZ3A6V.mjs.map +0 -7
- package/dist/lib/node-esm/index.mjs +0 -668
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
- package/dist/lib/node-esm/platform/browser/index.mjs +0 -27
- package/dist/lib/node-esm/platform/browser/index.mjs.map +0 -7
- package/dist/lib/node-esm/platform/node/index.mjs +0 -22
- package/dist/lib/node-esm/platform/node/index.mjs.map +0 -7
- package/dist/lib/node-esm/processors/console-processor.mjs +0 -103
- package/dist/lib/node-esm/processors/console-processor.mjs.map +0 -7
- package/dist/lib/node-esm/processors/console-stub.mjs +0 -10
- package/dist/lib/node-esm/processors/console-stub.mjs.map +0 -7
- package/dist/lib/node-esm/processors/file-processor.mjs +0 -76
- package/dist/lib/node-esm/processors/file-processor.mjs.map +0 -7
|
@@ -0,0 +1,619 @@
|
|
|
1
|
+
import { a as logInfo, c as LogProcessorType, i as gatherLogInfoFromScope, l as levels, n as getContextFromEntry, o as getRelativeFilename, r as shouldLog, s as LogLevel, t as LogEntry, u as shortLevelName } from "./chunk-context.mjs";
|
|
2
|
+
import { CircularBuffer, omit, pick, safariCheck } from "@dxos/util";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import { inspect } from "@dxos/node-std/util";
|
|
5
|
+
import defaultsDeep from "lodash.defaultsdeep";
|
|
6
|
+
export * from "#console-processor";
|
|
7
|
+
//#region \0rolldown/runtime.js
|
|
8
|
+
var __defProp = Object.defineProperty;
|
|
9
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
10
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
11
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
12
|
+
var __exportAll = (all, no_symbols) => {
|
|
13
|
+
let target = {};
|
|
14
|
+
for (var name in all) __defProp(target, name, {
|
|
15
|
+
get: all[name],
|
|
16
|
+
enumerable: true
|
|
17
|
+
});
|
|
18
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
19
|
+
return target;
|
|
20
|
+
};
|
|
21
|
+
var __copyProps = (to, from, except, desc) => {
|
|
22
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
23
|
+
key = keys[i];
|
|
24
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
25
|
+
get: ((k) => from[k]).bind(null, key),
|
|
26
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return to;
|
|
30
|
+
};
|
|
31
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region src/environment.ts
|
|
34
|
+
/**
|
|
35
|
+
* Per-tab session-storage key used to stabilize the random suffix for the main thread.
|
|
36
|
+
* `sessionStorage` is per-tab and survives reloads of the same tab.
|
|
37
|
+
*/
|
|
38
|
+
var TAB_SUFFIX_STORAGE_KEY = "@dxos/log:env-suffix";
|
|
39
|
+
var SUFFIX_LENGTH = 6;
|
|
40
|
+
/**
|
|
41
|
+
* Generate a 6-character lowercase-alphanumeric suffix.
|
|
42
|
+
* Cryptographically random when `crypto` is available; falls back to `Math.random`.
|
|
43
|
+
*/
|
|
44
|
+
var randomSuffix = () => {
|
|
45
|
+
const cryptoRef = globalThis.crypto;
|
|
46
|
+
if (cryptoRef?.getRandomValues) {
|
|
47
|
+
const bytes = new Uint8Array(SUFFIX_LENGTH);
|
|
48
|
+
cryptoRef.getRandomValues(bytes);
|
|
49
|
+
let suffix = "";
|
|
50
|
+
for (const byte of bytes) suffix += (byte % 36).toString(36);
|
|
51
|
+
return suffix;
|
|
52
|
+
}
|
|
53
|
+
return Math.random().toString(36).slice(2, 8).padEnd(SUFFIX_LENGTH, "0");
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Look up (or create) a stable per-tab suffix in `sessionStorage`.
|
|
57
|
+
* Same browser tab keeps the same suffix across reloads; different tabs get
|
|
58
|
+
* different suffixes; private/blocked storage falls back to a fresh random.
|
|
59
|
+
*/
|
|
60
|
+
var getOrCreateTabSuffix = (session) => {
|
|
61
|
+
if (!session) return randomSuffix();
|
|
62
|
+
try {
|
|
63
|
+
const existing = session.getItem(TAB_SUFFIX_STORAGE_KEY);
|
|
64
|
+
if (existing && existing.length > 0) return existing;
|
|
65
|
+
const suffix = randomSuffix();
|
|
66
|
+
session.setItem(TAB_SUFFIX_STORAGE_KEY, suffix);
|
|
67
|
+
return suffix;
|
|
68
|
+
} catch {
|
|
69
|
+
return randomSuffix();
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
var isInstanceOf = (scope, ctorName) => {
|
|
73
|
+
const ctor = scope?.[ctorName];
|
|
74
|
+
return typeof ctor === "function" && scope instanceof ctor;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Cloudflare Workers set `navigator.userAgent` to this exact string, regardless of
|
|
78
|
+
* whether the worker is using modules or service-worker syntax. This is the most
|
|
79
|
+
* stable signal and is checked before browser worker scopes because CF workers in
|
|
80
|
+
* service-worker syntax also expose a `ServiceWorkerGlobalScope`.
|
|
81
|
+
*/
|
|
82
|
+
var CF_WORKER_USER_AGENT = "Cloudflare-Workers";
|
|
83
|
+
/**
|
|
84
|
+
* Infer a writer/environment identifier from the current execution context.
|
|
85
|
+
*
|
|
86
|
+
* Safe to invoke in any JS runtime — never throws. Falls back to `unknown::<suffix>`
|
|
87
|
+
* when the runtime can't be classified.
|
|
88
|
+
*
|
|
89
|
+
* Format is always three colon-separated segments: `<scope>:<name>:<suffix>`.
|
|
90
|
+
* - `scope` — `tab | dedicated-worker | shared-worker | service-worker | cf-worker | node | unknown`.
|
|
91
|
+
* - `name` — `location.origin` for tabs, `self.name` for browser workers, `process.pid`
|
|
92
|
+
* for node, empty for cf-workers / service workers / anonymous workers.
|
|
93
|
+
* Note that `name` may itself contain `:` (e.g. `http://localhost:5173`); when parsing,
|
|
94
|
+
* take the first segment as scope and the last as suffix, and treat everything in
|
|
95
|
+
* between as the name.
|
|
96
|
+
* - `suffix` — 6-char random; stable per-tab via `sessionStorage`, fresh per worker / process instance.
|
|
97
|
+
*/
|
|
98
|
+
var inferEnvironmentName = (options = {}) => {
|
|
99
|
+
const scope = options.scope ?? globalThis;
|
|
100
|
+
if (scope.navigator?.userAgent === CF_WORKER_USER_AGENT) return `cf-worker::${randomSuffix()}`;
|
|
101
|
+
if (isInstanceOf(scope, "SharedWorkerGlobalScope")) return `shared-worker:${scope.name ?? ""}:${randomSuffix()}`;
|
|
102
|
+
if (isInstanceOf(scope, "ServiceWorkerGlobalScope")) return `service-worker::${randomSuffix()}`;
|
|
103
|
+
if (isInstanceOf(scope, "DedicatedWorkerGlobalScope")) return `dedicated-worker:${scope.name ?? ""}:${randomSuffix()}`;
|
|
104
|
+
if (scope.window !== void 0 && scope.window === scope) return `tab:${scope.location?.origin ?? ""}:${getOrCreateTabSuffix(scope.sessionStorage)}`;
|
|
105
|
+
const proc = scope.process;
|
|
106
|
+
if (proc && typeof proc === "object" && proc.versions?.node) return `node:${typeof proc.pid === "number" ? String(proc.pid) : ""}:${randomSuffix()}`;
|
|
107
|
+
return `unknown::${randomSuffix()}`;
|
|
108
|
+
};
|
|
109
|
+
//#endregion
|
|
110
|
+
//#region src/jsonl.ts
|
|
111
|
+
/**
|
|
112
|
+
* Serialize a {@link LogEntry} to a single compact JSON line (no trailing newline).
|
|
113
|
+
*
|
|
114
|
+
* Returns `undefined` for entries at TRACE level — callers can use this to skip them.
|
|
115
|
+
*
|
|
116
|
+
* The output is compatible with newline-delimited JSON (NDJSON / JSONL): join multiple
|
|
117
|
+
* results with `\n` for a stream / file representation.
|
|
118
|
+
*
|
|
119
|
+
* Context is taken from {@link LogEntry.computedContext}, which has already flattened
|
|
120
|
+
* nested objects to strings (see `stringifyOneLevel` in `context.ts`), so the resulting
|
|
121
|
+
* `c` field is a JSON string of a flat `Record<string, primitive>` map. The function
|
|
122
|
+
* does **not** truncate context — callers that care about line size should set their own
|
|
123
|
+
* cap before calling, or trim post-hoc.
|
|
124
|
+
*/
|
|
125
|
+
var serializeToJsonl = (entry, opts = {}) => {
|
|
126
|
+
if (entry.level <= LogLevel.TRACE) return;
|
|
127
|
+
const { filename, line, context: scopeName } = entry.computedMeta;
|
|
128
|
+
const record = {
|
|
129
|
+
t: new Date(entry.timestamp).toISOString(),
|
|
130
|
+
l: shortLevelName[entry.level] ?? "?",
|
|
131
|
+
m: entry.message ?? ""
|
|
132
|
+
};
|
|
133
|
+
if (filename !== void 0) record.f = filename;
|
|
134
|
+
if (line !== void 0) record.n = line;
|
|
135
|
+
if (scopeName !== void 0) record.o = scopeName;
|
|
136
|
+
if (entry.computedError !== void 0) record.e = entry.computedError;
|
|
137
|
+
if (opts.env !== void 0) record.i = opts.env;
|
|
138
|
+
const computedContext = entry.computedContext;
|
|
139
|
+
if (Object.keys(computedContext).length > 0) try {
|
|
140
|
+
record.c = JSON.stringify(computedContext);
|
|
141
|
+
} catch {}
|
|
142
|
+
try {
|
|
143
|
+
return JSON.stringify(record);
|
|
144
|
+
} catch {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
//#endregion
|
|
149
|
+
//#region src/decorators.ts
|
|
150
|
+
var nextPromiseId = 0;
|
|
151
|
+
var createMethodLogDecorator = (log) => (arg0, arg1, meta) => (target, propertyKey, descriptor) => {
|
|
152
|
+
const method = descriptor.value;
|
|
153
|
+
const methodName = propertyKey;
|
|
154
|
+
descriptor.value = function(...args) {
|
|
155
|
+
const combinedMeta = {
|
|
156
|
+
F: "",
|
|
157
|
+
L: 0,
|
|
158
|
+
...meta ?? {},
|
|
159
|
+
S: this
|
|
160
|
+
};
|
|
161
|
+
const formattedArgs = args.map((arg) => inspect(arg, false, 1, true)).join(", ");
|
|
162
|
+
try {
|
|
163
|
+
const startTime = performance.now();
|
|
164
|
+
const result = method.apply(this, args);
|
|
165
|
+
if (isThenable(result)) {
|
|
166
|
+
const id = nextPromiseId++;
|
|
167
|
+
logAsyncBegin(log, methodName, formattedArgs, id, combinedMeta);
|
|
168
|
+
result.then((resolvedValue) => {
|
|
169
|
+
logAsyncResolved(log, methodName, resolvedValue, id, startTime, combinedMeta);
|
|
170
|
+
}, (err) => {
|
|
171
|
+
logAsyncRejected(log, methodName, err, id, startTime, combinedMeta);
|
|
172
|
+
});
|
|
173
|
+
} else logSyncCall(log, methodName, formattedArgs, result, combinedMeta);
|
|
174
|
+
return result;
|
|
175
|
+
} catch (err) {
|
|
176
|
+
logSyncError(log, methodName, formattedArgs, err, combinedMeta);
|
|
177
|
+
throw err;
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
Object.defineProperty(descriptor.value, "name", { value: methodName + "$log" });
|
|
181
|
+
};
|
|
182
|
+
var createFunctionLogDecorator = (log) => (name, fn, opts = {}) => {
|
|
183
|
+
const decoratedFn = function(...args) {
|
|
184
|
+
const combinedMeta = {
|
|
185
|
+
F: "",
|
|
186
|
+
L: 0
|
|
187
|
+
};
|
|
188
|
+
const formattedArgs = args.map((arg) => inspect(arg, false, 1, true)).join(", ");
|
|
189
|
+
try {
|
|
190
|
+
const startTime = performance.now();
|
|
191
|
+
const result = fn.apply(this, args);
|
|
192
|
+
let transformedResult = result;
|
|
193
|
+
if (opts.transformOutput) if (isThenable(result)) transformedResult = result.then(opts.transformOutput);
|
|
194
|
+
else transformedResult = opts.transformOutput(result);
|
|
195
|
+
if (isThenable(transformedResult)) {
|
|
196
|
+
const id = nextPromiseId++;
|
|
197
|
+
logAsyncBegin(log, name, formattedArgs, id, combinedMeta);
|
|
198
|
+
transformedResult.then((resolvedValue) => {
|
|
199
|
+
logAsyncResolved(log, name, resolvedValue, id, startTime, combinedMeta);
|
|
200
|
+
}, (err) => {
|
|
201
|
+
logAsyncRejected(log, name, err, id, startTime, combinedMeta);
|
|
202
|
+
});
|
|
203
|
+
} else logSyncCall(log, name, formattedArgs, transformedResult, combinedMeta);
|
|
204
|
+
return result;
|
|
205
|
+
} catch (err) {
|
|
206
|
+
logSyncError(log, name, formattedArgs, err, combinedMeta);
|
|
207
|
+
throw err;
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
Object.defineProperty(decoratedFn, "name", { value: name + "$log" });
|
|
211
|
+
return decoratedFn;
|
|
212
|
+
};
|
|
213
|
+
var isThenable = (obj) => obj && typeof obj.then === "function";
|
|
214
|
+
var logSyncCall = (log, methodName, formattedArgs, result, combinedMeta) => {
|
|
215
|
+
log.info(`.${formatFunction(methodName)} (${formattedArgs}) ${chalk.gray("=>")} ${inspect(result, false, 1, true)}`, {}, combinedMeta);
|
|
216
|
+
};
|
|
217
|
+
var logSyncError = (log, methodName, formattedArgs, err, combinedMeta) => {
|
|
218
|
+
log.error(`.${formatFunction(methodName)} (${formattedArgs}) 🔥 ${err}`, {}, combinedMeta);
|
|
219
|
+
};
|
|
220
|
+
var logAsyncBegin = (log, methodName, formattedArgs, promiseId, combinedMeta) => {
|
|
221
|
+
log.info(`.${formatFunction(methodName)} ↴ (${formattedArgs}) ${chalk.gray("=>")} ${formatPromise(promiseId)}`, {}, combinedMeta);
|
|
222
|
+
};
|
|
223
|
+
var logAsyncResolved = (log, methodName, resolvedValue, promiseId, startTime, combinedMeta) => {
|
|
224
|
+
if (resolvedValue !== void 0) log.info(`.${formatFunction(methodName)} ↲ ${greenCheck} ${chalk.gray("resolve")} ${formatPromise(promiseId)} ${formatTimeElapsed(startTime)} ${chalk.gray("=>")} ${inspect(resolvedValue, false, 1, true)}`, {}, combinedMeta);
|
|
225
|
+
else log.info(`.${formatFunction(methodName)} ↲ ${greenCheck} ${chalk.gray("resolve")} ${formatPromise(promiseId)} ${formatTimeElapsed(startTime)}`, {}, combinedMeta);
|
|
226
|
+
};
|
|
227
|
+
var logAsyncRejected = (log, methodName, err, promiseId, startTime, combinedMeta) => {
|
|
228
|
+
log.info(`.${formatFunction(methodName)} ↲ 🔥 ${chalk.gray("reject")} ${formatPromise(promiseId)} ${formatTimeElapsed(startTime)} ${chalk.gray("=>")} ${err}`, {}, combinedMeta);
|
|
229
|
+
};
|
|
230
|
+
var COLOR_FUNCTION = [
|
|
231
|
+
220,
|
|
232
|
+
220,
|
|
233
|
+
170
|
|
234
|
+
];
|
|
235
|
+
var greenCheck = typeof chalk.green === "function" ? chalk.green("✔") : "✔";
|
|
236
|
+
var formatTimeElapsed = (startTime) => chalk.gray(`${(performance.now() - startTime).toFixed(0)}ms`);
|
|
237
|
+
var formatFunction = (name) => chalk.bold(chalk.rgb(...COLOR_FUNCTION)(name));
|
|
238
|
+
var formatPromise = (id) => chalk.blue(`Promise#${id}`);
|
|
239
|
+
//#endregion
|
|
240
|
+
//#region src/platform/index.ts
|
|
241
|
+
var platform_exports = /* @__PURE__ */ __exportAll({});
|
|
242
|
+
import * as import__platform from "#platform";
|
|
243
|
+
__reExport(platform_exports, import__platform);
|
|
244
|
+
//#endregion
|
|
245
|
+
//#region src/processors/browser-processor.ts
|
|
246
|
+
var CONFIG = {
|
|
247
|
+
useTestProcessor: false,
|
|
248
|
+
printFileLinks: false
|
|
249
|
+
};
|
|
250
|
+
/**
|
|
251
|
+
* For running apps in the browser normally.
|
|
252
|
+
*/
|
|
253
|
+
var APP_BROWSER_PROCESSOR = (config, entry) => {
|
|
254
|
+
if (!shouldLog(entry, config.filters)) return;
|
|
255
|
+
const LOG_BROWSER_PREFIX = config.prefix ?? "https://vscode.dev/github.com/dxos/dxos/blob/main/";
|
|
256
|
+
const LOG_BROWSER_CSS = [];
|
|
257
|
+
const { filename, line: lineNumber, context: scopeDebugName } = entry.computedMeta;
|
|
258
|
+
let link = "";
|
|
259
|
+
if (filename !== void 0 && lineNumber !== void 0) link = `${`${LOG_BROWSER_PREFIX.replace(/\/$/, "")}/${filename}`}#L${lineNumber}`;
|
|
260
|
+
let args = [];
|
|
261
|
+
const scope = entry.meta?.S;
|
|
262
|
+
if (scope) {
|
|
263
|
+
const scopeName = scope.name || scopeDebugName;
|
|
264
|
+
if (scopeName) {
|
|
265
|
+
const processPrefix = scope.hostSessionId ? "[worker] " : "";
|
|
266
|
+
args.push(`%c${processPrefix}${scopeName}`, "color:#C026D3;font-weight:bold");
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if (entry.message) args.push(entry.message);
|
|
270
|
+
const context = getContextFromEntry(entry);
|
|
271
|
+
if (context) if (Object.keys(context).length === 1 && "error" in context) args.push(unwrapEffectError(context.error));
|
|
272
|
+
else if (Object.keys(context).length === 1 && "err" in context) args.push(unwrapEffectError(context.err));
|
|
273
|
+
else args.push(context);
|
|
274
|
+
const levels = {
|
|
275
|
+
[LogLevel.ERROR]: console.error.bind(console),
|
|
276
|
+
[LogLevel.WARN]: console.warn.bind(console),
|
|
277
|
+
[LogLevel.DEBUG]: console.log.bind(console)
|
|
278
|
+
};
|
|
279
|
+
if (CONFIG.printFileLinks || safariCheck()) if (LOG_BROWSER_CSS?.length) args = [`%c${link}\n%c${args.join(" ")}`, ...LOG_BROWSER_CSS];
|
|
280
|
+
else args = [link + "\n", ...args];
|
|
281
|
+
const level = levels[entry.level] ?? console.log.bind(console);
|
|
282
|
+
if (typeof entry.meta?.C === "function") entry.meta.C(level, args);
|
|
283
|
+
else level(...args);
|
|
284
|
+
};
|
|
285
|
+
/**
|
|
286
|
+
* For running unit tests in the headless browser.
|
|
287
|
+
*/
|
|
288
|
+
var TEST_BROWSER_PROCESSOR = (config, entry) => {
|
|
289
|
+
if (!shouldLog(entry, config.filters)) return;
|
|
290
|
+
const { filename, line: lineNumber } = entry.computedMeta;
|
|
291
|
+
const path = filename !== void 0 && lineNumber !== void 0 ? `${filename}:${lineNumber}` : "";
|
|
292
|
+
let args = [];
|
|
293
|
+
const processPrefix = entry.meta?.S?.hostSessionId ? "[worker] " : "";
|
|
294
|
+
args.push(`${processPrefix}${entry.message}`);
|
|
295
|
+
const context = getContextFromEntry(entry);
|
|
296
|
+
if (context) args.push(context);
|
|
297
|
+
const levels = {
|
|
298
|
+
[LogLevel.ERROR]: console.error,
|
|
299
|
+
[LogLevel.WARN]: console.warn,
|
|
300
|
+
[LogLevel.DEBUG]: console.log
|
|
301
|
+
};
|
|
302
|
+
if (CONFIG.printFileLinks) args = [path, ...args];
|
|
303
|
+
const level = levels[entry.level] ?? console.log;
|
|
304
|
+
if (typeof entry.meta?.C === "function") entry.meta.C(level, args);
|
|
305
|
+
else level(...args);
|
|
306
|
+
};
|
|
307
|
+
var BROWSER_PROCESSOR = CONFIG.useTestProcessor ? TEST_BROWSER_PROCESSOR : APP_BROWSER_PROCESSOR;
|
|
308
|
+
var originalSymbol = Symbol.for("effect/OriginalAnnotation");
|
|
309
|
+
var unwrapEffectError = (error) => {
|
|
310
|
+
if (typeof error === "object" && error !== null && originalSymbol in error) return error[originalSymbol];
|
|
311
|
+
return error;
|
|
312
|
+
};
|
|
313
|
+
//#endregion
|
|
314
|
+
//#region src/processors/debug-processor.ts
|
|
315
|
+
var DEBUG_PROCESSOR = (config, entry) => {
|
|
316
|
+
console.log(inspect(entry, false, null, true));
|
|
317
|
+
};
|
|
318
|
+
//#endregion
|
|
319
|
+
//#region src/processors/index.ts
|
|
320
|
+
var processors_exports = /* @__PURE__ */ __exportAll({
|
|
321
|
+
BROWSER_PROCESSOR: () => BROWSER_PROCESSOR,
|
|
322
|
+
DEBUG_PROCESSOR: () => DEBUG_PROCESSOR,
|
|
323
|
+
getRelativeFilename: () => getRelativeFilename
|
|
324
|
+
});
|
|
325
|
+
import * as import__console_processor from "#console-processor";
|
|
326
|
+
__reExport(processors_exports, import__console_processor);
|
|
327
|
+
//#endregion
|
|
328
|
+
//#region src/options.ts
|
|
329
|
+
/**
|
|
330
|
+
* Processor variants.
|
|
331
|
+
*/
|
|
332
|
+
var processors = {
|
|
333
|
+
[LogProcessorType.CONSOLE]: processors_exports.CONSOLE_PROCESSOR,
|
|
334
|
+
[LogProcessorType.BROWSER]: BROWSER_PROCESSOR,
|
|
335
|
+
[LogProcessorType.DEBUG]: DEBUG_PROCESSOR
|
|
336
|
+
};
|
|
337
|
+
var DEFAULT_PROCESSORS = [(typeof window !== "undefined" || typeof navigator !== "undefined") && !(typeof process !== "undefined" && process?.env?.VITEST) ? BROWSER_PROCESSOR : processors_exports.CONSOLE_PROCESSOR];
|
|
338
|
+
var parseLogLevel = (level, defValue = LogLevel.WARN) => levels[level.toLowerCase()] ?? defValue;
|
|
339
|
+
/**
|
|
340
|
+
* @internal
|
|
341
|
+
*/
|
|
342
|
+
var parseFilter = (filter) => {
|
|
343
|
+
if (typeof filter === "number") return [{ level: filter }];
|
|
344
|
+
return (typeof filter === "string" ? filter.split(/,\s*/) : filter).map((filter) => {
|
|
345
|
+
const [pattern, level] = filter.split(":");
|
|
346
|
+
return level ? {
|
|
347
|
+
level: parseLogLevel(level),
|
|
348
|
+
pattern
|
|
349
|
+
} : { level: parseLogLevel(pattern) };
|
|
350
|
+
});
|
|
351
|
+
};
|
|
352
|
+
/**
|
|
353
|
+
* @internal
|
|
354
|
+
*/
|
|
355
|
+
var createConfig = (options) => {
|
|
356
|
+
const envOptions = "process" in globalThis ? {
|
|
357
|
+
file: process.env.LOG_CONFIG,
|
|
358
|
+
filter: process.env.LOG_FILTER,
|
|
359
|
+
processor: process.env.LOG_PROCESSOR
|
|
360
|
+
} : void 0;
|
|
361
|
+
const mergedOptions = defaultsDeep({}, (0, platform_exports.loadOptions)(envOptions?.file), envOptions, options);
|
|
362
|
+
return {
|
|
363
|
+
options: mergedOptions,
|
|
364
|
+
filters: parseFilter(mergedOptions.filter ?? LogLevel.INFO),
|
|
365
|
+
captureFilters: parseFilter(mergedOptions.captureFilter ?? LogLevel.WARN),
|
|
366
|
+
processors: mergedOptions.processor ? [processors[mergedOptions.processor]] : [...DEFAULT_PROCESSORS],
|
|
367
|
+
prefix: mergedOptions.prefix
|
|
368
|
+
};
|
|
369
|
+
};
|
|
370
|
+
//#endregion
|
|
371
|
+
//#region src/log.ts
|
|
372
|
+
var logCount = 0;
|
|
373
|
+
/**
|
|
374
|
+
* Create a logging function with properties.
|
|
375
|
+
* @internal
|
|
376
|
+
*/
|
|
377
|
+
var createLog = () => {
|
|
378
|
+
const log = ((...params) => processLog(LogLevel.DEBUG, ...params));
|
|
379
|
+
Object.assign(log, {
|
|
380
|
+
_id: `log-${++logCount}`,
|
|
381
|
+
_config: createConfig()
|
|
382
|
+
});
|
|
383
|
+
Object.defineProperty(log, "runtimeConfig", { get: () => log._config });
|
|
384
|
+
/**
|
|
385
|
+
* Process the current log call.
|
|
386
|
+
*/
|
|
387
|
+
const processLog = (level, message, context = {}, meta, error) => {
|
|
388
|
+
const entry = new LogEntry({
|
|
389
|
+
level,
|
|
390
|
+
message,
|
|
391
|
+
context,
|
|
392
|
+
meta,
|
|
393
|
+
error
|
|
394
|
+
});
|
|
395
|
+
log._config.processors.forEach((processor) => processor(log._config, entry));
|
|
396
|
+
};
|
|
397
|
+
/**
|
|
398
|
+
* API.
|
|
399
|
+
*/
|
|
400
|
+
Object.assign(log, {
|
|
401
|
+
/**
|
|
402
|
+
* Update config.
|
|
403
|
+
* NOTE: Preserves any processors that were already added to this logger instance
|
|
404
|
+
* unless an explicit processor option is provided.
|
|
405
|
+
*/
|
|
406
|
+
config: ({ processor, ...options } = {}) => {
|
|
407
|
+
const config = createConfig(options);
|
|
408
|
+
const processors = processor ? config.processors : log._config.processors;
|
|
409
|
+
log._config = {
|
|
410
|
+
...config,
|
|
411
|
+
processors
|
|
412
|
+
};
|
|
413
|
+
return log;
|
|
414
|
+
},
|
|
415
|
+
/**
|
|
416
|
+
* Adds a processor to the logger.
|
|
417
|
+
*/
|
|
418
|
+
addProcessor: (processor) => {
|
|
419
|
+
if (log._config.processors.filter((p) => p === processor).length === 0) log._config.processors.push(processor);
|
|
420
|
+
return () => {
|
|
421
|
+
log._config.processors = log._config.processors.filter((p) => p !== processor);
|
|
422
|
+
};
|
|
423
|
+
},
|
|
424
|
+
trace: (...params) => processLog(LogLevel.TRACE, ...params),
|
|
425
|
+
debug: (...params) => processLog(LogLevel.DEBUG, ...params),
|
|
426
|
+
verbose: (...params) => processLog(LogLevel.VERBOSE, ...params),
|
|
427
|
+
info: (...params) => processLog(LogLevel.INFO, ...params),
|
|
428
|
+
warn: (...params) => processLog(LogLevel.WARN, ...params),
|
|
429
|
+
error: (...params) => processLog(LogLevel.ERROR, ...params),
|
|
430
|
+
catch: (error, context, meta) => processLog(LogLevel.ERROR, void 0, context, meta, error),
|
|
431
|
+
method: createMethodLogDecorator(log),
|
|
432
|
+
function: createFunctionLogDecorator(log),
|
|
433
|
+
break: () => log.info("-".repeat(80)),
|
|
434
|
+
stack: (message, context, meta) => {
|
|
435
|
+
return processLog(LogLevel.INFO, `${message ?? "Stack Dump"}\n${getFormattedStackTrace()}`, context, meta);
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
return log;
|
|
439
|
+
};
|
|
440
|
+
/**
|
|
441
|
+
* Global logging function.
|
|
442
|
+
*/
|
|
443
|
+
var log = globalThis.DX_LOG ??= createLog();
|
|
444
|
+
var start = Date.now();
|
|
445
|
+
var last = start;
|
|
446
|
+
/**
|
|
447
|
+
* Log debug stack.
|
|
448
|
+
*/
|
|
449
|
+
var debug = (label, args) => {
|
|
450
|
+
const now = Date.now();
|
|
451
|
+
const err = /* @__PURE__ */ new Error();
|
|
452
|
+
console.group(`DEBUG[${label}]`, JSON.stringify({
|
|
453
|
+
t: Number(now - start).toLocaleString(),
|
|
454
|
+
dt: Number(now - last).toLocaleString(),
|
|
455
|
+
...args
|
|
456
|
+
}));
|
|
457
|
+
console.warn(err.stack);
|
|
458
|
+
console.groupEnd();
|
|
459
|
+
last = Date.now();
|
|
460
|
+
};
|
|
461
|
+
var getFormattedStackTrace = () => (/* @__PURE__ */ new Error()).stack.split("\n").slice(3).join("\n");
|
|
462
|
+
//#endregion
|
|
463
|
+
//#region src/registry.ts
|
|
464
|
+
/** Create an isolated {@link LogFileRegistry} backed by an in-memory set with change notification. */
|
|
465
|
+
var createLogFileRegistry = () => {
|
|
466
|
+
const files = /* @__PURE__ */ new Set();
|
|
467
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
468
|
+
const notify = () => {
|
|
469
|
+
for (const listener of listeners) listener();
|
|
470
|
+
};
|
|
471
|
+
return {
|
|
472
|
+
register: (file) => {
|
|
473
|
+
if (typeof file !== "string" || file.length === 0 || files.has(file)) return;
|
|
474
|
+
files.add(file);
|
|
475
|
+
notify();
|
|
476
|
+
},
|
|
477
|
+
getFiles: () => [...files].sort(),
|
|
478
|
+
subscribe: (listener) => {
|
|
479
|
+
listeners.add(listener);
|
|
480
|
+
return () => listeners.delete(listener);
|
|
481
|
+
},
|
|
482
|
+
clear: () => {
|
|
483
|
+
files.clear();
|
|
484
|
+
notify();
|
|
485
|
+
}
|
|
486
|
+
};
|
|
487
|
+
};
|
|
488
|
+
/**
|
|
489
|
+
* Global singleton so all (possibly duplicated) copies of `@dxos/log` and the
|
|
490
|
+
* transform-injected `globalThis.DX_LOG_FILES.register(...)` calls share one registry —
|
|
491
|
+
* mirrors how `log` is `globalThis.DX_LOG`.
|
|
492
|
+
*/
|
|
493
|
+
var logFileRegistry = globalThis.DX_LOG_FILES ??= createLogFileRegistry();
|
|
494
|
+
//#endregion
|
|
495
|
+
//#region src/meta.ts
|
|
496
|
+
/**
|
|
497
|
+
* Marker key + value injected on every {@link CallMetadata} object by the log transform plugin.
|
|
498
|
+
* Used by {@link isLogMeta} to detect a log-meta argument at runtime (e.g. for variadic
|
|
499
|
+
* `param_index: 'last'` callees that don't have a fixed meta slot).
|
|
500
|
+
*/
|
|
501
|
+
var LOG_META_MARKER = "~LogMeta";
|
|
502
|
+
/**
|
|
503
|
+
* Type guard: `true` when `value` is a {@link CallMetadata} object emitted by the log transform plugin.
|
|
504
|
+
* Detection is based on the presence of the {@link LOG_META_MARKER} marker key/value.
|
|
505
|
+
*/
|
|
506
|
+
var isLogMeta = (value) => {
|
|
507
|
+
return value != null && typeof value === "object" && value["~LogMeta"] === "~LogMeta";
|
|
508
|
+
};
|
|
509
|
+
//#endregion
|
|
510
|
+
//#region src/dbg.ts
|
|
511
|
+
/**
|
|
512
|
+
* Debug-log value to console.
|
|
513
|
+
* Log's the expression being evaluated.
|
|
514
|
+
*
|
|
515
|
+
* If only one argument is provided, it will also be returned.
|
|
516
|
+
*
|
|
517
|
+
* @example
|
|
518
|
+
* ```ts
|
|
519
|
+
* dbg(foo, bar);
|
|
520
|
+
* // foo = 1
|
|
521
|
+
* // bar = 2
|
|
522
|
+
*
|
|
523
|
+
* bar = dbg(foo * 2);
|
|
524
|
+
* // foo * 2 = 2
|
|
525
|
+
* ```
|
|
526
|
+
*
|
|
527
|
+
* NOTE: The second argument is injected by the log transform plugin.
|
|
528
|
+
*/
|
|
529
|
+
var dbg = (arg, meta) => {
|
|
530
|
+
if (meta?.A) console.log(`${meta.A[0]} =`, arg);
|
|
531
|
+
else console.log(arg);
|
|
532
|
+
return arg;
|
|
533
|
+
};
|
|
534
|
+
//#endregion
|
|
535
|
+
//#region src/log-buffer.ts
|
|
536
|
+
var DEFAULT_BUFFER_SIZE = 2e3;
|
|
537
|
+
var MAX_CONTEXT_LENGTH = 500;
|
|
538
|
+
/**
|
|
539
|
+
* Captures recent log entries in a circular buffer for debug log dump.
|
|
540
|
+
*/
|
|
541
|
+
var LogBuffer = class {
|
|
542
|
+
_buffer;
|
|
543
|
+
constructor(size = DEFAULT_BUFFER_SIZE) {
|
|
544
|
+
this._buffer = new CircularBuffer(size);
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* Log processor that can be registered with `log.runtimeConfig.processors`.
|
|
548
|
+
* Captures every level except TRACE (does not apply `shouldLog` / filter; use for full debug dumps).
|
|
549
|
+
*/
|
|
550
|
+
logProcessor = (_config, entry) => {
|
|
551
|
+
if (entry.level <= LogLevel.TRACE) return;
|
|
552
|
+
const { filename, line, context: scopeName } = entry.computedMeta;
|
|
553
|
+
const record = {
|
|
554
|
+
t: new Date(entry.timestamp).toISOString(),
|
|
555
|
+
l: shortLevelName[entry.level] ?? "?",
|
|
556
|
+
m: entry.message ?? ""
|
|
557
|
+
};
|
|
558
|
+
if (filename !== void 0) record.f = filename;
|
|
559
|
+
if (line !== void 0) record.n = line;
|
|
560
|
+
if (scopeName !== void 0) record.o = scopeName;
|
|
561
|
+
if (entry.computedError !== void 0) record.e = entry.computedError;
|
|
562
|
+
const computedContext = entry.computedContext;
|
|
563
|
+
if (Object.keys(computedContext).length > 0) try {
|
|
564
|
+
let json = JSON.stringify(computedContext);
|
|
565
|
+
if (json.length > MAX_CONTEXT_LENGTH) json = json.slice(0, MAX_CONTEXT_LENGTH);
|
|
566
|
+
record.c = json;
|
|
567
|
+
} catch {}
|
|
568
|
+
this._buffer.push(record);
|
|
569
|
+
};
|
|
570
|
+
/** Number of entries currently in the buffer. */
|
|
571
|
+
get size() {
|
|
572
|
+
return this._buffer.elementCount;
|
|
573
|
+
}
|
|
574
|
+
/** Discard all buffered entries. */
|
|
575
|
+
clear() {
|
|
576
|
+
this._buffer.clear();
|
|
577
|
+
}
|
|
578
|
+
/** Serialize buffer contents as NDJSON (newline-delimited JSON). */
|
|
579
|
+
serialize() {
|
|
580
|
+
const lines = [];
|
|
581
|
+
for (const record of this._buffer) lines.push(JSON.stringify(record));
|
|
582
|
+
return lines.join("\n");
|
|
583
|
+
}
|
|
584
|
+
};
|
|
585
|
+
inspect.custom;
|
|
586
|
+
var getCurrentOwnershipScope = (thisRef) => thisRef;
|
|
587
|
+
__reExport(/* @__PURE__ */ __exportAll({
|
|
588
|
+
BROWSER_PROCESSOR: () => BROWSER_PROCESSOR,
|
|
589
|
+
DEBUG_PROCESSOR: () => DEBUG_PROCESSOR,
|
|
590
|
+
LOG_META_MARKER: () => LOG_META_MARKER,
|
|
591
|
+
LogBuffer: () => LogBuffer,
|
|
592
|
+
LogEntry: () => LogEntry,
|
|
593
|
+
LogLevel: () => LogLevel,
|
|
594
|
+
LogProcessorType: () => LogProcessorType,
|
|
595
|
+
createLog: () => createLog,
|
|
596
|
+
createLogFileRegistry: () => createLogFileRegistry,
|
|
597
|
+
dbg: () => dbg,
|
|
598
|
+
debug: () => debug,
|
|
599
|
+
gatherLogInfoFromScope: () => gatherLogInfoFromScope,
|
|
600
|
+
getContextFromEntry: () => getContextFromEntry,
|
|
601
|
+
getCurrentOwnershipScope: () => getCurrentOwnershipScope,
|
|
602
|
+
getRelativeFilename: () => getRelativeFilename,
|
|
603
|
+
inferEnvironmentName: () => inferEnvironmentName,
|
|
604
|
+
isLogMeta: () => isLogMeta,
|
|
605
|
+
levels: () => levels,
|
|
606
|
+
log: () => log,
|
|
607
|
+
logFileRegistry: () => logFileRegistry,
|
|
608
|
+
logInfo: () => logInfo,
|
|
609
|
+
omit: () => omit,
|
|
610
|
+
parseFilter: () => parseFilter,
|
|
611
|
+
pick: () => pick,
|
|
612
|
+
serializeToJsonl: () => serializeToJsonl,
|
|
613
|
+
shortLevelName: () => shortLevelName,
|
|
614
|
+
shouldLog: () => shouldLog
|
|
615
|
+
}), processors_exports);
|
|
616
|
+
//#endregion
|
|
617
|
+
export { BROWSER_PROCESSOR, DEBUG_PROCESSOR, LOG_META_MARKER, LogBuffer, LogEntry, LogLevel, LogProcessorType, createLog, createLogFileRegistry, dbg, debug, gatherLogInfoFromScope, getContextFromEntry, getCurrentOwnershipScope, getRelativeFilename, inferEnvironmentName, isLogMeta, levels, log, logFileRegistry, logInfo, omit, parseFilter, pick, serializeToJsonl, shortLevelName, shouldLog };
|
|
618
|
+
|
|
619
|
+
//# sourceMappingURL=index.mjs.map
|