evlog 1.6.0 → 1.8.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/README.md +96 -0
- package/dist/_http-DVDwNag0.mjs +76 -0
- package/dist/_http-DVDwNag0.mjs.map +1 -0
- package/dist/_severity-CXfyvxQi.mjs +17 -0
- package/dist/_severity-CXfyvxQi.mjs.map +1 -0
- package/dist/adapters/axiom.d.mts +17 -15
- package/dist/adapters/axiom.d.mts.map +1 -0
- package/dist/adapters/axiom.mjs +91 -50
- package/dist/adapters/axiom.mjs.map +1 -0
- package/dist/adapters/better-stack.d.mts +63 -0
- package/dist/adapters/better-stack.d.mts.map +1 -0
- package/dist/adapters/better-stack.mjs +98 -0
- package/dist/adapters/better-stack.mjs.map +1 -0
- package/dist/adapters/otlp.d.mts +32 -30
- package/dist/adapters/otlp.d.mts.map +1 -0
- package/dist/adapters/otlp.mjs +181 -181
- package/dist/adapters/otlp.mjs.map +1 -0
- package/dist/adapters/posthog.d.mts +54 -19
- package/dist/adapters/posthog.d.mts.map +1 -0
- package/dist/adapters/posthog.mjs +156 -63
- package/dist/adapters/posthog.mjs.map +1 -0
- package/dist/adapters/sentry.d.mts +25 -23
- package/dist/adapters/sentry.d.mts.map +1 -0
- package/dist/adapters/sentry.mjs +198 -153
- package/dist/adapters/sentry.mjs.map +1 -0
- package/dist/browser.d.mts +63 -0
- package/dist/browser.d.mts.map +1 -0
- package/dist/browser.mjs +95 -0
- package/dist/browser.mjs.map +1 -0
- package/dist/enrichers.d.mts +74 -0
- package/dist/enrichers.d.mts.map +1 -0
- package/dist/enrichers.mjs +172 -0
- package/dist/enrichers.mjs.map +1 -0
- package/dist/error.d.mts +24 -22
- package/dist/error.d.mts.map +1 -0
- package/dist/error.mjs +107 -76
- package/dist/error.mjs.map +1 -0
- package/dist/index.d.mts +6 -5
- package/dist/index.mjs +6 -5
- package/dist/logger.d.mts +11 -5
- package/dist/logger.d.mts.map +1 -0
- package/dist/logger.mjs +255 -186
- package/dist/logger.mjs.map +1 -0
- package/dist/nitro/errorHandler.d.mts +4 -2
- package/dist/nitro/errorHandler.d.mts.map +1 -0
- package/dist/nitro/errorHandler.mjs +38 -38
- package/dist/nitro/errorHandler.mjs.map +1 -0
- package/dist/nitro/module.d.mts +11 -0
- package/dist/nitro/module.d.mts.map +1 -0
- package/dist/nitro/module.mjs +23 -0
- package/dist/nitro/module.mjs.map +1 -0
- package/dist/nitro/plugin.d.mts +4 -2
- package/dist/nitro/plugin.d.mts.map +1 -0
- package/dist/nitro/plugin.mjs +135 -140
- package/dist/nitro/plugin.mjs.map +1 -0
- package/dist/nitro/v3/errorHandler.d.mts +24 -0
- package/dist/nitro/v3/errorHandler.d.mts.map +1 -0
- package/dist/nitro/v3/errorHandler.mjs +36 -0
- package/dist/nitro/v3/errorHandler.mjs.map +1 -0
- package/dist/nitro/v3/index.d.mts +4 -0
- package/dist/nitro/v3/index.mjs +4 -0
- package/dist/nitro/v3/module.d.mts +10 -0
- package/dist/nitro/v3/module.d.mts.map +1 -0
- package/dist/nitro/v3/module.mjs +22 -0
- package/dist/nitro/v3/module.mjs.map +1 -0
- package/dist/nitro/v3/plugin.d.mts +14 -0
- package/dist/nitro/v3/plugin.d.mts.map +1 -0
- package/dist/nitro/v3/plugin.mjs +157 -0
- package/dist/nitro/v3/plugin.mjs.map +1 -0
- package/dist/nitro/v3/useLogger.d.mts +24 -0
- package/dist/nitro/v3/useLogger.d.mts.map +1 -0
- package/dist/nitro/v3/useLogger.mjs +27 -0
- package/dist/nitro/v3/useLogger.mjs.map +1 -0
- package/dist/nitro-D57TWGyN.mjs +73 -0
- package/dist/nitro-D57TWGyN.mjs.map +1 -0
- package/dist/nitro-D81NBVPi.d.mts +42 -0
- package/dist/nitro-D81NBVPi.d.mts.map +1 -0
- package/dist/nuxt/module.d.mts +155 -168
- package/dist/nuxt/module.d.mts.map +1 -0
- package/dist/nuxt/module.mjs +75 -65
- package/dist/nuxt/module.mjs.map +1 -0
- package/dist/pipeline.d.mts +46 -0
- package/dist/pipeline.d.mts.map +1 -0
- package/dist/pipeline.mjs +122 -0
- package/dist/pipeline.mjs.map +1 -0
- package/dist/runtime/client/log.d.mts +12 -7
- package/dist/runtime/client/log.d.mts.map +1 -0
- package/dist/runtime/client/log.mjs +72 -64
- package/dist/runtime/client/log.mjs.map +1 -0
- package/dist/runtime/client/plugin.d.mts +3 -1
- package/dist/runtime/client/plugin.d.mts.map +1 -0
- package/dist/runtime/client/plugin.mjs +14 -12
- package/dist/runtime/client/plugin.mjs.map +1 -0
- package/dist/runtime/server/routes/_evlog/ingest.post.d.mts +4 -2
- package/dist/runtime/server/routes/_evlog/ingest.post.d.mts.map +1 -0
- package/dist/runtime/server/routes/_evlog/ingest.post.mjs +113 -76
- package/dist/runtime/server/routes/_evlog/ingest.post.mjs.map +1 -0
- package/dist/runtime/server/useLogger.d.mts +14 -3
- package/dist/runtime/server/useLogger.d.mts.map +1 -0
- package/dist/runtime/server/useLogger.mjs +39 -10
- package/dist/runtime/server/useLogger.mjs.map +1 -0
- package/dist/runtime/utils/parseError.d.mts +5 -3
- package/dist/runtime/utils/parseError.d.mts.map +1 -0
- package/dist/runtime/utils/parseError.mjs +25 -26
- package/dist/runtime/utils/parseError.mjs.map +1 -0
- package/dist/types.d.mts +378 -246
- package/dist/types.d.mts.map +1 -0
- package/dist/types.mjs +1 -1
- package/dist/utils.d.mts +19 -14
- package/dist/utils.d.mts.map +1 -0
- package/dist/utils.mjs +59 -50
- package/dist/utils.mjs.map +1 -0
- package/dist/workers.d.mts +10 -9
- package/dist/workers.d.mts.map +1 -0
- package/dist/workers.mjs +68 -39
- package/dist/workers.mjs.map +1 -0
- package/package.json +55 -10
- package/dist/adapters/axiom.d.ts +0 -62
- package/dist/adapters/otlp.d.ts +0 -83
- package/dist/adapters/posthog.d.ts +0 -72
- package/dist/adapters/sentry.d.ts +0 -78
- package/dist/error.d.ts +0 -63
- package/dist/index.d.ts +0 -5
- package/dist/logger.d.ts +0 -40
- package/dist/nitro/errorHandler.d.ts +0 -13
- package/dist/nitro/plugin.d.ts +0 -5
- package/dist/nuxt/module.d.ts +0 -171
- package/dist/runtime/client/log.d.ts +0 -10
- package/dist/runtime/client/plugin.d.ts +0 -3
- package/dist/runtime/server/routes/_evlog/ingest.post.d.ts +0 -5
- package/dist/runtime/server/useLogger.d.ts +0 -28
- package/dist/runtime/utils/parseError.d.ts +0 -5
- package/dist/shared/evlog.Bc35pxiY.mjs +0 -10
- package/dist/types.d.ts +0 -364
- package/dist/utils.d.ts +0 -29
- package/dist/workers.d.ts +0 -45
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
//#region src/enrichers/index.ts
|
|
2
|
+
function getHeader(headers, name) {
|
|
3
|
+
if (!headers) return void 0;
|
|
4
|
+
if (headers[name] !== void 0) return headers[name];
|
|
5
|
+
const lowerName = name.toLowerCase();
|
|
6
|
+
if (headers[lowerName] !== void 0) return headers[lowerName];
|
|
7
|
+
for (const [key, value] of Object.entries(headers)) if (key.toLowerCase() === lowerName) return value;
|
|
8
|
+
}
|
|
9
|
+
function parseUserAgent(ua) {
|
|
10
|
+
const lower = ua.toLowerCase();
|
|
11
|
+
let deviceType = { type: "unknown" };
|
|
12
|
+
if (/bot|crawl|spider|slurp|bingpreview/.test(lower)) deviceType = { type: "bot" };
|
|
13
|
+
else if (/ipad|tablet/.test(lower)) deviceType = { type: "tablet" };
|
|
14
|
+
else if (/mobi|iphone|android/.test(lower)) deviceType = { type: "mobile" };
|
|
15
|
+
else if (ua.length > 0) deviceType = { type: "desktop" };
|
|
16
|
+
const browserMatchers = [
|
|
17
|
+
{
|
|
18
|
+
name: "Edge",
|
|
19
|
+
regex: /edg\/([\d.]+)/i
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
name: "Chrome",
|
|
23
|
+
regex: /chrome\/([\d.]+)/i
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: "Firefox",
|
|
27
|
+
regex: /firefox\/([\d.]+)/i
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: "Safari",
|
|
31
|
+
regex: /version\/([\d.]+).*safari/i
|
|
32
|
+
}
|
|
33
|
+
];
|
|
34
|
+
let browser;
|
|
35
|
+
for (const matcher of browserMatchers) {
|
|
36
|
+
const match = ua.match(matcher.regex);
|
|
37
|
+
if (match) {
|
|
38
|
+
browser = {
|
|
39
|
+
name: matcher.name,
|
|
40
|
+
version: match[1]
|
|
41
|
+
};
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
let os;
|
|
46
|
+
if (/windows nt/i.test(ua)) os = {
|
|
47
|
+
name: "Windows",
|
|
48
|
+
version: ua.match(/windows nt ([\d.]+)/i)?.[1]
|
|
49
|
+
};
|
|
50
|
+
else if (/mac os x/i.test(ua) && !/iphone|ipad|ipod/i.test(ua)) os = {
|
|
51
|
+
name: "macOS",
|
|
52
|
+
version: ua.match(/mac os x ([\d_]+)/i)?.[1]?.replace(/_/g, ".")
|
|
53
|
+
};
|
|
54
|
+
else if (/iphone|ipad|ipod/i.test(ua)) os = {
|
|
55
|
+
name: "iOS",
|
|
56
|
+
version: ua.match(/os ([\d_]+)/i)?.[1]?.replace(/_/g, ".")
|
|
57
|
+
};
|
|
58
|
+
else if (/android/i.test(ua)) os = {
|
|
59
|
+
name: "Android",
|
|
60
|
+
version: ua.match(/android ([\d.]+)/i)?.[1]
|
|
61
|
+
};
|
|
62
|
+
else if (/linux/i.test(ua)) os = { name: "Linux" };
|
|
63
|
+
return {
|
|
64
|
+
raw: ua,
|
|
65
|
+
browser,
|
|
66
|
+
os,
|
|
67
|
+
device: deviceType
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function parseTraceparent(traceparent) {
|
|
71
|
+
const match = traceparent.match(/^[\da-f]{2}-([\da-f]{32})-([\da-f]{16})-[\da-f]{2}$/i);
|
|
72
|
+
if (!match) return void 0;
|
|
73
|
+
return {
|
|
74
|
+
traceId: match[1],
|
|
75
|
+
spanId: match[2]
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function mergeEventField(existing, computed, overwrite) {
|
|
79
|
+
if (overwrite || existing === void 0 || existing === null || typeof existing !== "object") return computed;
|
|
80
|
+
return {
|
|
81
|
+
...computed,
|
|
82
|
+
...existing
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function normalizeNumber(value) {
|
|
86
|
+
if (!value) return void 0;
|
|
87
|
+
const parsed = Number(value);
|
|
88
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Enrich events with parsed user agent data.
|
|
92
|
+
* Sets `event.userAgent` with `UserAgentInfo` shape: `{ raw, browser?, os?, device? }`.
|
|
93
|
+
*/
|
|
94
|
+
function createUserAgentEnricher(options = {}) {
|
|
95
|
+
return (ctx) => {
|
|
96
|
+
const ua = getHeader(ctx.headers, "user-agent");
|
|
97
|
+
if (!ua) return;
|
|
98
|
+
const info = parseUserAgent(ua);
|
|
99
|
+
ctx.event.userAgent = mergeEventField(ctx.event.userAgent, info, options.overwrite);
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Enrich events with geo data from platform headers.
|
|
104
|
+
* Sets `event.geo` with `GeoInfo` shape: `{ country?, region?, regionCode?, city?, latitude?, longitude? }`.
|
|
105
|
+
*
|
|
106
|
+
* Supports Vercel (`x-vercel-ip-*`) headers out of the box.
|
|
107
|
+
*
|
|
108
|
+
* **Cloudflare note:** Only `cf-ipcountry` is an actual HTTP header added by Cloudflare.
|
|
109
|
+
* The `cf-region`, `cf-city`, `cf-latitude`, `cf-longitude` headers are NOT standard
|
|
110
|
+
* Cloudflare headers — they are properties of `request.cf` which is not exposed as HTTP
|
|
111
|
+
* headers. For full geo data on Cloudflare, write a custom enricher that reads `request.cf`
|
|
112
|
+
* or use a Workers middleware to copy `cf` properties into custom headers.
|
|
113
|
+
*/
|
|
114
|
+
function createGeoEnricher(options = {}) {
|
|
115
|
+
return (ctx) => {
|
|
116
|
+
const { headers } = ctx;
|
|
117
|
+
if (!headers) return;
|
|
118
|
+
const geo = {
|
|
119
|
+
country: getHeader(headers, "x-vercel-ip-country") ?? getHeader(headers, "cf-ipcountry"),
|
|
120
|
+
region: getHeader(headers, "x-vercel-ip-country-region") ?? getHeader(headers, "cf-region"),
|
|
121
|
+
regionCode: getHeader(headers, "x-vercel-ip-country-region-code") ?? getHeader(headers, "cf-region-code"),
|
|
122
|
+
city: getHeader(headers, "x-vercel-ip-city") ?? getHeader(headers, "cf-city"),
|
|
123
|
+
latitude: normalizeNumber(getHeader(headers, "x-vercel-ip-latitude") ?? getHeader(headers, "cf-latitude")),
|
|
124
|
+
longitude: normalizeNumber(getHeader(headers, "x-vercel-ip-longitude") ?? getHeader(headers, "cf-longitude"))
|
|
125
|
+
};
|
|
126
|
+
if (Object.values(geo).every((value) => value === void 0)) return;
|
|
127
|
+
ctx.event.geo = mergeEventField(ctx.event.geo, geo, options.overwrite);
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Enrich events with request/response payload sizes.
|
|
132
|
+
* Sets `event.requestSize` with `RequestSizeInfo` shape: `{ requestBytes?, responseBytes? }`.
|
|
133
|
+
*/
|
|
134
|
+
function createRequestSizeEnricher(options = {}) {
|
|
135
|
+
return (ctx) => {
|
|
136
|
+
const requestBytes = normalizeNumber(getHeader(ctx.headers, "content-length"));
|
|
137
|
+
const responseBytes = normalizeNumber(getHeader(ctx.response?.headers, "content-length"));
|
|
138
|
+
const sizes = {
|
|
139
|
+
requestBytes,
|
|
140
|
+
responseBytes
|
|
141
|
+
};
|
|
142
|
+
if (requestBytes === void 0 && responseBytes === void 0) return;
|
|
143
|
+
ctx.event.requestSize = mergeEventField(ctx.event.requestSize, sizes, options.overwrite);
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Enrich events with W3C trace context data.
|
|
148
|
+
* Sets `event.traceContext` with `TraceContextInfo` shape: `{ traceparent?, tracestate?, traceId?, spanId? }`.
|
|
149
|
+
* Also sets `event.traceId` and `event.spanId` at the top level.
|
|
150
|
+
*/
|
|
151
|
+
function createTraceContextEnricher(options = {}) {
|
|
152
|
+
return (ctx) => {
|
|
153
|
+
const traceparent = getHeader(ctx.headers, "traceparent");
|
|
154
|
+
const tracestate = getHeader(ctx.headers, "tracestate");
|
|
155
|
+
if (!traceparent && !tracestate) return;
|
|
156
|
+
const parsed = traceparent ? parseTraceparent(traceparent) : void 0;
|
|
157
|
+
const incomingTraceContext = {
|
|
158
|
+
traceparent,
|
|
159
|
+
tracestate,
|
|
160
|
+
traceId: parsed?.traceId ?? ctx.event.traceId,
|
|
161
|
+
spanId: parsed?.spanId ?? ctx.event.spanId
|
|
162
|
+
};
|
|
163
|
+
const mergedTraceContext = mergeEventField(ctx.event.traceContext, incomingTraceContext, options.overwrite);
|
|
164
|
+
ctx.event.traceContext = mergedTraceContext;
|
|
165
|
+
if (mergedTraceContext.traceId && (options.overwrite || ctx.event.traceId === void 0)) ctx.event.traceId = mergedTraceContext.traceId;
|
|
166
|
+
if (mergedTraceContext.spanId && (options.overwrite || ctx.event.spanId === void 0)) ctx.event.spanId = mergedTraceContext.spanId;
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
//#endregion
|
|
171
|
+
export { createGeoEnricher, createRequestSizeEnricher, createTraceContextEnricher, createUserAgentEnricher };
|
|
172
|
+
//# sourceMappingURL=enrichers.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enrichers.mjs","names":[],"sources":["../src/enrichers/index.ts"],"sourcesContent":["import type { EnrichContext } from '../types'\n\nexport interface EnricherOptions {\n /**\n * When true, overwrite any existing fields in the event.\n * Defaults to false to preserve user-provided data.\n */\n overwrite?: boolean\n}\n\nexport interface UserAgentInfo {\n raw: string\n browser?: { name: string; version?: string }\n os?: { name: string; version?: string }\n device?: { type: 'mobile' | 'tablet' | 'desktop' | 'bot' | 'unknown' }\n}\n\nexport interface GeoInfo {\n country?: string\n region?: string\n regionCode?: string\n city?: string\n latitude?: number\n longitude?: number\n}\n\nexport interface RequestSizeInfo {\n requestBytes?: number\n responseBytes?: number\n}\n\nexport interface TraceContextInfo {\n traceparent?: string\n tracestate?: string\n traceId?: string\n spanId?: string\n}\n\nfunction getHeader(headers: Record<string, string> | undefined, name: string): string | undefined {\n if (!headers) return undefined\n if (headers[name] !== undefined) return headers[name]\n const lowerName = name.toLowerCase()\n if (headers[lowerName] !== undefined) return headers[lowerName]\n for (const [key, value] of Object.entries(headers)) {\n if (key.toLowerCase() === lowerName) return value\n }\n return undefined\n}\n\nfunction parseUserAgent(ua: string): UserAgentInfo {\n const lower = ua.toLowerCase()\n\n let deviceType: UserAgentInfo['device'] = { type: 'unknown' }\n if (/bot|crawl|spider|slurp|bingpreview/.test(lower)) {\n deviceType = { type: 'bot' }\n } else if (/ipad|tablet/.test(lower)) {\n deviceType = { type: 'tablet' }\n } else if (/mobi|iphone|android/.test(lower)) {\n deviceType = { type: 'mobile' }\n } else if (ua.length > 0) {\n deviceType = { type: 'desktop' }\n }\n\n const browserMatchers: Array<{ name: string, regex: RegExp }> = [\n { name: 'Edge', regex: /edg\\/([\\d.]+)/i },\n { name: 'Chrome', regex: /chrome\\/([\\d.]+)/i },\n { name: 'Firefox', regex: /firefox\\/([\\d.]+)/i },\n { name: 'Safari', regex: /version\\/([\\d.]+).*safari/i },\n ]\n\n let browser: UserAgentInfo['browser']\n for (const matcher of browserMatchers) {\n const match = ua.match(matcher.regex)\n if (match) {\n browser = { name: matcher.name, version: match[1] }\n break\n }\n }\n\n let os: UserAgentInfo['os']\n if (/windows nt/i.test(ua)) {\n const match = ua.match(/windows nt ([\\d.]+)/i)\n os = { name: 'Windows', version: match?.[1] }\n } else if (/mac os x/i.test(ua) && !/iphone|ipad|ipod/i.test(ua)) {\n const match = ua.match(/mac os x ([\\d_]+)/i)\n os = { name: 'macOS', version: match?.[1]?.replace(/_/g, '.') }\n } else if (/iphone|ipad|ipod/i.test(ua)) {\n const match = ua.match(/os ([\\d_]+)/i)\n os = { name: 'iOS', version: match?.[1]?.replace(/_/g, '.') }\n } else if (/android/i.test(ua)) {\n const match = ua.match(/android ([\\d.]+)/i)\n os = { name: 'Android', version: match?.[1] }\n } else if (/linux/i.test(ua)) {\n os = { name: 'Linux' }\n }\n\n return {\n raw: ua,\n browser,\n os,\n device: deviceType,\n }\n}\n\nfunction parseTraceparent(traceparent: string): Pick<TraceContextInfo, 'traceId' | 'spanId'> | undefined {\n const match = traceparent.match(/^[\\da-f]{2}-([\\da-f]{32})-([\\da-f]{16})-[\\da-f]{2}$/i)\n if (!match) return undefined\n return { traceId: match[1], spanId: match[2] }\n}\n\nfunction mergeEventField<T extends object>(\n existing: unknown,\n computed: T,\n overwrite?: boolean,\n): T {\n if (overwrite || existing === undefined || existing === null || typeof existing !== 'object') {\n return computed\n }\n return { ...computed, ...(existing as T) }\n}\n\nfunction normalizeNumber(value: string | undefined): number | undefined {\n if (!value) return undefined\n const parsed = Number(value)\n return Number.isFinite(parsed) ? parsed : undefined\n}\n\n/**\n * Enrich events with parsed user agent data.\n * Sets `event.userAgent` with `UserAgentInfo` shape: `{ raw, browser?, os?, device? }`.\n */\nexport function createUserAgentEnricher(options: EnricherOptions = {}): (ctx: EnrichContext) => void {\n return (ctx) => {\n const ua = getHeader(ctx.headers, 'user-agent')\n if (!ua) return\n const info = parseUserAgent(ua)\n ctx.event.userAgent = mergeEventField<UserAgentInfo>(ctx.event.userAgent, info, options.overwrite)\n }\n}\n\n/**\n * Enrich events with geo data from platform headers.\n * Sets `event.geo` with `GeoInfo` shape: `{ country?, region?, regionCode?, city?, latitude?, longitude? }`.\n *\n * Supports Vercel (`x-vercel-ip-*`) headers out of the box.\n *\n * **Cloudflare note:** Only `cf-ipcountry` is an actual HTTP header added by Cloudflare.\n * The `cf-region`, `cf-city`, `cf-latitude`, `cf-longitude` headers are NOT standard\n * Cloudflare headers — they are properties of `request.cf` which is not exposed as HTTP\n * headers. For full geo data on Cloudflare, write a custom enricher that reads `request.cf`\n * or use a Workers middleware to copy `cf` properties into custom headers.\n */\nexport function createGeoEnricher(options: EnricherOptions = {}): (ctx: EnrichContext) => void {\n return (ctx) => {\n const { headers } = ctx\n if (!headers) return\n\n const geo: GeoInfo = {\n country: getHeader(headers, 'x-vercel-ip-country') ?? getHeader(headers, 'cf-ipcountry'),\n region: getHeader(headers, 'x-vercel-ip-country-region') ?? getHeader(headers, 'cf-region'),\n regionCode: getHeader(headers, 'x-vercel-ip-country-region-code') ?? getHeader(headers, 'cf-region-code'),\n city: getHeader(headers, 'x-vercel-ip-city') ?? getHeader(headers, 'cf-city'),\n latitude: normalizeNumber(getHeader(headers, 'x-vercel-ip-latitude') ?? getHeader(headers, 'cf-latitude')),\n longitude: normalizeNumber(getHeader(headers, 'x-vercel-ip-longitude') ?? getHeader(headers, 'cf-longitude')),\n }\n\n if (Object.values(geo).every(value => value === undefined)) return\n ctx.event.geo = mergeEventField<GeoInfo>(ctx.event.geo, geo, options.overwrite)\n }\n}\n\n/**\n * Enrich events with request/response payload sizes.\n * Sets `event.requestSize` with `RequestSizeInfo` shape: `{ requestBytes?, responseBytes? }`.\n */\nexport function createRequestSizeEnricher(options: EnricherOptions = {}): (ctx: EnrichContext) => void {\n return (ctx) => {\n const requestBytes = normalizeNumber(getHeader(ctx.headers, 'content-length'))\n const responseBytes = normalizeNumber(getHeader(ctx.response?.headers, 'content-length'))\n\n const sizes: RequestSizeInfo = {\n requestBytes,\n responseBytes,\n }\n\n if (requestBytes === undefined && responseBytes === undefined) return\n ctx.event.requestSize = mergeEventField<RequestSizeInfo>(ctx.event.requestSize, sizes, options.overwrite)\n }\n}\n\n/**\n * Enrich events with W3C trace context data.\n * Sets `event.traceContext` with `TraceContextInfo` shape: `{ traceparent?, tracestate?, traceId?, spanId? }`.\n * Also sets `event.traceId` and `event.spanId` at the top level.\n */\nexport function createTraceContextEnricher(options: EnricherOptions = {}): (ctx: EnrichContext) => void {\n return (ctx) => {\n const traceparent = getHeader(ctx.headers, 'traceparent')\n const tracestate = getHeader(ctx.headers, 'tracestate')\n if (!traceparent && !tracestate) return\n\n const parsed = traceparent ? parseTraceparent(traceparent) : undefined\n const incomingTraceContext: TraceContextInfo = {\n traceparent,\n tracestate,\n traceId: parsed?.traceId ?? (ctx.event.traceId as string | undefined),\n spanId: parsed?.spanId ?? (ctx.event.spanId as string | undefined),\n }\n\n const mergedTraceContext = mergeEventField<TraceContextInfo>(\n ctx.event.traceContext,\n incomingTraceContext,\n options.overwrite,\n )\n ctx.event.traceContext = mergedTraceContext\n\n if (mergedTraceContext.traceId && (options.overwrite || ctx.event.traceId === undefined)) {\n ctx.event.traceId = mergedTraceContext.traceId\n }\n if (mergedTraceContext.spanId && (options.overwrite || ctx.event.spanId === undefined)) {\n ctx.event.spanId = mergedTraceContext.spanId\n }\n }\n}\n"],"mappings":"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"}
|
package/dist/error.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { ErrorOptions } from
|
|
1
|
+
import { ErrorOptions } from "./types.mjs";
|
|
2
2
|
|
|
3
|
+
//#region src/error.d.ts
|
|
3
4
|
/**
|
|
4
5
|
* Structured error with context for better debugging
|
|
5
6
|
*
|
|
@@ -16,26 +17,26 @@ import { ErrorOptions } from './types.mjs';
|
|
|
16
17
|
* ```
|
|
17
18
|
*/
|
|
18
19
|
declare class EvlogError extends Error {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
20
|
+
/** HTTP status code */
|
|
21
|
+
readonly status: number;
|
|
22
|
+
readonly why?: string;
|
|
23
|
+
readonly fix?: string;
|
|
24
|
+
readonly link?: string;
|
|
25
|
+
constructor(options: ErrorOptions | string);
|
|
26
|
+
/** HTTP status text (alias for message) */
|
|
27
|
+
get statusText(): string;
|
|
28
|
+
/** HTTP status code (alias for compatibility) */
|
|
29
|
+
get statusCode(): number;
|
|
30
|
+
/** HTTP status message (alias for compatibility) */
|
|
31
|
+
get statusMessage(): string;
|
|
32
|
+
/** Structured data for serialization */
|
|
33
|
+
get data(): {
|
|
34
|
+
why?: string;
|
|
35
|
+
fix?: string;
|
|
36
|
+
link?: string;
|
|
37
|
+
} | undefined;
|
|
38
|
+
toString(): string;
|
|
39
|
+
toJSON(): Record<string, unknown>;
|
|
39
40
|
}
|
|
40
41
|
/**
|
|
41
42
|
* Create a structured error with context for debugging and user-facing messages.
|
|
@@ -59,5 +60,6 @@ declare class EvlogError extends Error {
|
|
|
59
60
|
* ```
|
|
60
61
|
*/
|
|
61
62
|
declare function createError(options: ErrorOptions | string): EvlogError;
|
|
62
|
-
|
|
63
|
+
//#endregion
|
|
63
64
|
export { EvlogError, createError, createError as createEvlogError };
|
|
65
|
+
//# sourceMappingURL=error.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.d.mts","names":[],"sources":["../src/error.ts"],"mappings":";;;;;AAkBA;;;;;;;;;;;;;cAAa,UAAA,SAAmB,KAAA;EAQT;EAAA,SALZ,MAAA;EAAA,SACA,GAAA;EAAA,SACA,GAAA;EAAA,SACA,IAAA;cAEG,OAAA,EAAS,YAAA;EAiCP;EAAA,IAfV,UAAA,CAAA;EAesC;EAAA,IAVtC,UAAA,CAAA;EAkDJ;EAAA,IA7CI,aAAA,CAAA;EA6CY;EAAA,IAxCZ,IAAA,CAAA;IAAU,GAAA;IAAc,GAAA;IAAc,IAAA;EAAA;EAOjC,QAAA,CAAA;EAiCT,MAAA,CAAA,GAAU,MAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;iBAoCI,WAAA,CAAY,OAAA,EAAS,YAAA,YAAwB,UAAA"}
|
package/dist/error.mjs
CHANGED
|
@@ -1,81 +1,112 @@
|
|
|
1
|
-
import { colors, isServer } from
|
|
1
|
+
import { colors, isServer } from "./utils.mjs";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
3
|
+
//#region src/error.ts
|
|
4
|
+
/**
|
|
5
|
+
* Structured error with context for better debugging
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* throw new EvlogError({
|
|
10
|
+
* message: 'Failed to sync repository',
|
|
11
|
+
* status: 503,
|
|
12
|
+
* why: 'GitHub API rate limit exceeded',
|
|
13
|
+
* fix: 'Wait 1 hour or use a different token',
|
|
14
|
+
* link: 'https://docs.github.com/en/rest/rate-limit',
|
|
15
|
+
* cause: originalError,
|
|
16
|
+
* })
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
var EvlogError = class EvlogError extends Error {
|
|
20
|
+
/** HTTP status code */
|
|
21
|
+
status;
|
|
22
|
+
why;
|
|
23
|
+
fix;
|
|
24
|
+
link;
|
|
25
|
+
constructor(options) {
|
|
26
|
+
const opts = typeof options === "string" ? { message: options } : options;
|
|
27
|
+
super(opts.message, { cause: opts.cause });
|
|
28
|
+
this.name = "EvlogError";
|
|
29
|
+
this.status = opts.status ?? 500;
|
|
30
|
+
this.why = opts.why;
|
|
31
|
+
this.fix = opts.fix;
|
|
32
|
+
this.link = opts.link;
|
|
33
|
+
if (Error.captureStackTrace) Error.captureStackTrace(this, EvlogError);
|
|
34
|
+
}
|
|
35
|
+
/** HTTP status text (alias for message) */
|
|
36
|
+
get statusText() {
|
|
37
|
+
return this.message;
|
|
38
|
+
}
|
|
39
|
+
/** HTTP status code (alias for compatibility) */
|
|
40
|
+
get statusCode() {
|
|
41
|
+
return this.status;
|
|
42
|
+
}
|
|
43
|
+
/** HTTP status message (alias for compatibility) */
|
|
44
|
+
get statusMessage() {
|
|
45
|
+
return this.message;
|
|
46
|
+
}
|
|
47
|
+
/** Structured data for serialization */
|
|
48
|
+
get data() {
|
|
49
|
+
if (this.why || this.fix || this.link) return {
|
|
50
|
+
why: this.why,
|
|
51
|
+
fix: this.fix,
|
|
52
|
+
link: this.link
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
toString() {
|
|
56
|
+
const useColors = isServer();
|
|
57
|
+
const red = useColors ? colors.red : "";
|
|
58
|
+
const yellow = useColors ? colors.yellow : "";
|
|
59
|
+
const cyan = useColors ? colors.cyan : "";
|
|
60
|
+
const dim = useColors ? colors.dim : "";
|
|
61
|
+
const reset = useColors ? colors.reset : "";
|
|
62
|
+
const bold = useColors ? colors.bold : "";
|
|
63
|
+
const lines = [];
|
|
64
|
+
lines.push(`${red}${bold}Error:${reset} ${this.message}`);
|
|
65
|
+
if (this.why) lines.push(`${yellow}Why:${reset} ${this.why}`);
|
|
66
|
+
if (this.fix) lines.push(`${cyan}Fix:${reset} ${this.fix}`);
|
|
67
|
+
if (this.link) lines.push(`${dim}More info:${reset} ${this.link}`);
|
|
68
|
+
if (this.cause) lines.push(`${dim}Caused by:${reset} ${this.cause.message}`);
|
|
69
|
+
return lines.join("\n");
|
|
70
|
+
}
|
|
71
|
+
toJSON() {
|
|
72
|
+
const { data } = this;
|
|
73
|
+
return {
|
|
74
|
+
name: this.name,
|
|
75
|
+
message: this.message,
|
|
76
|
+
status: this.status,
|
|
77
|
+
...data && { data },
|
|
78
|
+
...this.cause instanceof Error && { cause: {
|
|
79
|
+
name: this.cause.name,
|
|
80
|
+
message: this.cause.message
|
|
81
|
+
} }
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Create a structured error with context for debugging and user-facing messages.
|
|
87
|
+
*
|
|
88
|
+
* @param options - Error message string or full options object
|
|
89
|
+
* @returns EvlogError with HTTP metadata (`status`, `statusText`) and `data`; also includes `statusCode` and `statusMessage` for legacy compatibility
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```ts
|
|
93
|
+
* // Simple error
|
|
94
|
+
* throw createError('Something went wrong')
|
|
95
|
+
*
|
|
96
|
+
* // Structured error with context
|
|
97
|
+
* throw createError({
|
|
98
|
+
* message: 'Payment failed',
|
|
99
|
+
* status: 402,
|
|
100
|
+
* why: 'Card declined by issuer',
|
|
101
|
+
* fix: 'Try a different payment method',
|
|
102
|
+
* link: 'https://docs.example.com/payments',
|
|
103
|
+
* })
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
77
106
|
function createError(options) {
|
|
78
|
-
|
|
107
|
+
return new EvlogError(options);
|
|
79
108
|
}
|
|
80
109
|
|
|
110
|
+
//#endregion
|
|
81
111
|
export { EvlogError, createError, createError as createEvlogError };
|
|
112
|
+
//# sourceMappingURL=error.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.mjs","names":[],"sources":["../src/error.ts"],"sourcesContent":["import type { ErrorOptions } from './types'\nimport { colors, isServer } from './utils'\n\n/**\n * Structured error with context for better debugging\n *\n * @example\n * ```ts\n * throw new EvlogError({\n * message: 'Failed to sync repository',\n * status: 503,\n * why: 'GitHub API rate limit exceeded',\n * fix: 'Wait 1 hour or use a different token',\n * link: 'https://docs.github.com/en/rest/rate-limit',\n * cause: originalError,\n * })\n * ```\n */\nexport class EvlogError extends Error {\n\n /** HTTP status code */\n readonly status: number\n readonly why?: string\n readonly fix?: string\n readonly link?: string\n\n constructor(options: ErrorOptions | string) {\n const opts = typeof options === 'string' ? { message: options } : options\n\n super(opts.message, { cause: opts.cause })\n\n this.name = 'EvlogError'\n this.status = opts.status ?? 500\n this.why = opts.why\n this.fix = opts.fix\n this.link = opts.link\n\n // Maintain proper stack trace in V8\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, EvlogError)\n }\n }\n\n /** HTTP status text (alias for message) */\n get statusText(): string {\n return this.message\n }\n\n /** HTTP status code (alias for compatibility) */\n get statusCode(): number {\n return this.status\n }\n\n /** HTTP status message (alias for compatibility) */\n get statusMessage(): string {\n return this.message\n }\n\n /** Structured data for serialization */\n get data(): { why?: string, fix?: string, link?: string } | undefined {\n if (this.why || this.fix || this.link) {\n return { why: this.why, fix: this.fix, link: this.link }\n }\n return undefined\n }\n\n override toString(): string {\n const useColors = isServer()\n\n const red = useColors ? colors.red : ''\n const yellow = useColors ? colors.yellow : ''\n const cyan = useColors ? colors.cyan : ''\n const dim = useColors ? colors.dim : ''\n const reset = useColors ? colors.reset : ''\n const bold = useColors ? colors.bold : ''\n\n const lines: string[] = []\n\n lines.push(`${red}${bold}Error:${reset} ${this.message}`)\n\n if (this.why) {\n lines.push(`${yellow}Why:${reset} ${this.why}`)\n }\n\n if (this.fix) {\n lines.push(`${cyan}Fix:${reset} ${this.fix}`)\n }\n\n if (this.link) {\n lines.push(`${dim}More info:${reset} ${this.link}`)\n }\n\n if (this.cause) {\n lines.push(`${dim}Caused by:${reset} ${(this.cause as Error).message}`)\n }\n\n return lines.join('\\n')\n }\n\n toJSON(): Record<string, unknown> {\n const { data } = this\n return {\n name: this.name,\n message: this.message,\n status: this.status,\n ...(data && { data }),\n ...(this.cause instanceof Error && {\n cause: { name: this.cause.name, message: this.cause.message },\n }),\n }\n }\n\n}\n\n/**\n * Create a structured error with context for debugging and user-facing messages.\n *\n * @param options - Error message string or full options object\n * @returns EvlogError with HTTP metadata (`status`, `statusText`) and `data`; also includes `statusCode` and `statusMessage` for legacy compatibility\n *\n * @example\n * ```ts\n * // Simple error\n * throw createError('Something went wrong')\n *\n * // Structured error with context\n * throw createError({\n * message: 'Payment failed',\n * status: 402,\n * why: 'Card declined by issuer',\n * fix: 'Try a different payment method',\n * link: 'https://docs.example.com/payments',\n * })\n * ```\n */\nexport function createError(options: ErrorOptions | string): EvlogError {\n return new EvlogError(options)\n}\n\nexport { createError as createEvlogError }\n"],"mappings":";;;;;;;;;;;;;;;;;;AAkBA,IAAa,aAAb,MAAa,mBAAmB,MAAM;;CAGpC,AAAS;CACT,AAAS;CACT,AAAS;CACT,AAAS;CAET,YAAY,SAAgC;EAC1C,MAAM,OAAO,OAAO,YAAY,WAAW,EAAE,SAAS,SAAS,GAAG;AAElE,QAAM,KAAK,SAAS,EAAE,OAAO,KAAK,OAAO,CAAC;AAE1C,OAAK,OAAO;AACZ,OAAK,SAAS,KAAK,UAAU;AAC7B,OAAK,MAAM,KAAK;AAChB,OAAK,MAAM,KAAK;AAChB,OAAK,OAAO,KAAK;AAGjB,MAAI,MAAM,kBACR,OAAM,kBAAkB,MAAM,WAAW;;;CAK7C,IAAI,aAAqB;AACvB,SAAO,KAAK;;;CAId,IAAI,aAAqB;AACvB,SAAO,KAAK;;;CAId,IAAI,gBAAwB;AAC1B,SAAO,KAAK;;;CAId,IAAI,OAAkE;AACpE,MAAI,KAAK,OAAO,KAAK,OAAO,KAAK,KAC/B,QAAO;GAAE,KAAK,KAAK;GAAK,KAAK,KAAK;GAAK,MAAM,KAAK;GAAM;;CAK5D,AAAS,WAAmB;EAC1B,MAAM,YAAY,UAAU;EAE5B,MAAM,MAAM,YAAY,OAAO,MAAM;EACrC,MAAM,SAAS,YAAY,OAAO,SAAS;EAC3C,MAAM,OAAO,YAAY,OAAO,OAAO;EACvC,MAAM,MAAM,YAAY,OAAO,MAAM;EACrC,MAAM,QAAQ,YAAY,OAAO,QAAQ;EACzC,MAAM,OAAO,YAAY,OAAO,OAAO;EAEvC,MAAM,QAAkB,EAAE;AAE1B,QAAM,KAAK,GAAG,MAAM,KAAK,QAAQ,MAAM,GAAG,KAAK,UAAU;AAEzD,MAAI,KAAK,IACP,OAAM,KAAK,GAAG,OAAO,MAAM,MAAM,GAAG,KAAK,MAAM;AAGjD,MAAI,KAAK,IACP,OAAM,KAAK,GAAG,KAAK,MAAM,MAAM,GAAG,KAAK,MAAM;AAG/C,MAAI,KAAK,KACP,OAAM,KAAK,GAAG,IAAI,YAAY,MAAM,GAAG,KAAK,OAAO;AAGrD,MAAI,KAAK,MACP,OAAM,KAAK,GAAG,IAAI,YAAY,MAAM,GAAI,KAAK,MAAgB,UAAU;AAGzE,SAAO,MAAM,KAAK,KAAK;;CAGzB,SAAkC;EAChC,MAAM,EAAE,SAAS;AACjB,SAAO;GACL,MAAM,KAAK;GACX,SAAS,KAAK;GACd,QAAQ,KAAK;GACb,GAAI,QAAQ,EAAE,MAAM;GACpB,GAAI,KAAK,iBAAiB,SAAS,EACjC,OAAO;IAAE,MAAM,KAAK,MAAM;IAAM,SAAS,KAAK,MAAM;IAAS,EAC9D;GACF;;;;;;;;;;;;;;;;;;;;;;;;AA0BL,SAAgB,YAAY,SAA4C;AACtE,QAAO,IAAI,WAAW,QAAQ"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { BaseWideEvent, DeepPartial, DrainContext, EnrichContext, EnvironmentContext, ErrorOptions, FieldContext, H3EventContext, IngestPayload, InternalFields, Log, LogLevel, LoggerConfig, ParsedError, RequestLogger, RequestLoggerOptions, SamplingConfig, SamplingRates, ServerEvent, TailSamplingCondition, TailSamplingContext, TransportConfig, WideEvent } from "./types.mjs";
|
|
2
|
+
import { EvlogError, createError } from "./error.mjs";
|
|
3
|
+
import { createRequestLogger, getEnvironment, initLogger, isEnabled, log as _log, shouldKeep } from "./logger.mjs";
|
|
4
|
+
import { useLogger } from "./runtime/server/useLogger.mjs";
|
|
5
|
+
import { parseError } from "./runtime/utils/parseError.mjs";
|
|
6
|
+
export { type BaseWideEvent, type DeepPartial, type DrainContext, type EnrichContext, type EnvironmentContext, type ErrorOptions, EvlogError, type FieldContext, type H3EventContext, type IngestPayload, type InternalFields, type Log, type LogLevel, type LoggerConfig, type ParsedError, type RequestLogger, type RequestLoggerOptions, type SamplingConfig, type SamplingRates, type ServerEvent, type TailSamplingCondition, type TailSamplingContext, type TransportConfig, type WideEvent, createError, createError as createEvlogError, createRequestLogger, getEnvironment, initLogger, isEnabled, _log as log, parseError, shouldKeep, useLogger };
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { EvlogError, createError } from "./error.mjs";
|
|
2
|
+
import { createRequestLogger, getEnvironment, initLogger, isEnabled, log as _log, shouldKeep } from "./logger.mjs";
|
|
3
|
+
import { useLogger } from "./runtime/server/useLogger.mjs";
|
|
4
|
+
import { parseError } from "./runtime/utils/parseError.mjs";
|
|
5
|
+
|
|
6
|
+
export { EvlogError, createError, createError as createEvlogError, createRequestLogger, getEnvironment, initLogger, isEnabled, _log as log, parseError, shouldKeep, useLogger };
|
package/dist/logger.d.mts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { EnvironmentContext, Log, LoggerConfig, RequestLogger, RequestLoggerOptions, TailSamplingContext } from "./types.mjs";
|
|
2
2
|
|
|
3
|
+
//#region src/logger.d.ts
|
|
3
4
|
/**
|
|
4
5
|
* Initialize the logger with configuration.
|
|
5
6
|
* Call this once at application startup.
|
|
6
7
|
*/
|
|
7
8
|
declare function initLogger(config?: LoggerConfig): void;
|
|
9
|
+
/**
|
|
10
|
+
* Check if logging is globally enabled.
|
|
11
|
+
*/
|
|
12
|
+
declare function isEnabled(): boolean;
|
|
8
13
|
/**
|
|
9
14
|
* Evaluate tail sampling conditions to determine if a log should be force-kept.
|
|
10
15
|
* Returns true if ANY condition matches (OR logic).
|
|
@@ -19,7 +24,7 @@ declare function shouldKeep(ctx: TailSamplingContext): boolean;
|
|
|
19
24
|
* log.error({ action: 'payment', error: 'failed' })
|
|
20
25
|
* ```
|
|
21
26
|
*/
|
|
22
|
-
declare const
|
|
27
|
+
declare const _log: Log;
|
|
23
28
|
/**
|
|
24
29
|
* Create a request-scoped logger for building wide events.
|
|
25
30
|
*
|
|
@@ -31,10 +36,11 @@ declare const log: Log;
|
|
|
31
36
|
* log.emit()
|
|
32
37
|
* ```
|
|
33
38
|
*/
|
|
34
|
-
declare function createRequestLogger(options?: RequestLoggerOptions): RequestLogger
|
|
39
|
+
declare function createRequestLogger<T extends object = Record<string, unknown>>(options?: RequestLoggerOptions): RequestLogger<T>;
|
|
35
40
|
/**
|
|
36
41
|
* Get the current environment context.
|
|
37
42
|
*/
|
|
38
43
|
declare function getEnvironment(): EnvironmentContext;
|
|
39
|
-
|
|
40
|
-
export { createRequestLogger, getEnvironment, initLogger, log, shouldKeep };
|
|
44
|
+
//#endregion
|
|
45
|
+
export { createRequestLogger, getEnvironment, initLogger, isEnabled, _log as log, shouldKeep };
|
|
46
|
+
//# sourceMappingURL=logger.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.mts","names":[],"sources":["../src/logger.ts"],"mappings":";;;;;AAoCA;;iBAAgB,UAAA,CAAW,MAAA,GAAQ,YAAA;;;AAqBnC;iBAAgB,SAAA,CAAA;;;;AA8BhB;iBAAgB,UAAA,CAAW,GAAA,EAAK,mBAAA;;;;AAgB/B;;;;;AAkKD;cAjCM,IAAA,EAAM,GAAA;;;;;;;;;;;;iBAiCI,mBAAA,oBAAuC,MAAA,kBAAA,CAAyB,OAAA,GAAS,oBAAA,GAA4B,aAAA,CAAc,CAAA;;;AAiHnI;iBAAgB,cAAA,CAAA,GAAkB,kBAAA"}
|