hotelme-nuxt-logger 1.0.5 → 1.1.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/module.cjs +20 -1
- package/dist/module.d.cts +18 -0
- package/dist/module.d.mts +18 -0
- package/dist/module.d.ts +18 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +21 -2
- package/dist/runtime/logger.js +2 -2
- package/dist/runtime/middleware/logger.server.js +2 -1
- package/dist/runtime/plugins/error.d.ts +8 -0
- package/dist/runtime/plugins/error.js +73 -0
- package/dist/runtime/server/plugin.d.ts +12 -0
- package/dist/runtime/server/plugin.js +36 -0
- package/dist/runtime/server/routes/client-error.post.d.ts +8 -0
- package/dist/runtime/server/routes/client-error.post.js +14 -0
- package/package.json +1 -1
package/dist/module.cjs
CHANGED
|
@@ -14,12 +14,17 @@ const module$1 = kit.defineNuxtModule({
|
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
16
|
defaults: {
|
|
17
|
-
enableRequestLogging: true
|
|
17
|
+
enableRequestLogging: true,
|
|
18
|
+
enableErrorLogging: true,
|
|
19
|
+
enableClientErrorLogging: true,
|
|
20
|
+
clientErrorEndpoint: "/_logger/client-error"
|
|
18
21
|
},
|
|
19
22
|
setup(options, nuxt) {
|
|
20
23
|
const moduleDir = typeof __dirname !== "undefined" ? __dirname : path.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('module.cjs', document.baseURI).href))));
|
|
21
24
|
const resolver = kit.createResolver(moduleDir);
|
|
22
25
|
nuxt.options.runtimeConfig.public.projectName = options.projectName || process.env.NUXT_PUBLIC_PROJECT_NAME || "hotelme";
|
|
26
|
+
const clientErrorEndpoint = options.clientErrorEndpoint || "/_logger/client-error";
|
|
27
|
+
nuxt.options.runtimeConfig.public.loggerClientErrorEndpoint = clientErrorEndpoint;
|
|
23
28
|
kit.addImportsDir(resolver.resolve("./runtime"));
|
|
24
29
|
if (options.enableRequestLogging) {
|
|
25
30
|
kit.addServerHandler({
|
|
@@ -27,6 +32,20 @@ const module$1 = kit.defineNuxtModule({
|
|
|
27
32
|
middleware: true
|
|
28
33
|
});
|
|
29
34
|
}
|
|
35
|
+
if (options.enableErrorLogging) {
|
|
36
|
+
kit.addServerPlugin(resolver.resolve("./runtime/server/plugin"));
|
|
37
|
+
}
|
|
38
|
+
if (options.enableClientErrorLogging) {
|
|
39
|
+
kit.addPlugin({
|
|
40
|
+
src: resolver.resolve("./runtime/plugins/error"),
|
|
41
|
+
mode: "all"
|
|
42
|
+
});
|
|
43
|
+
kit.addServerHandler({
|
|
44
|
+
route: clientErrorEndpoint,
|
|
45
|
+
method: "post",
|
|
46
|
+
handler: resolver.resolve("./runtime/server/routes/client-error.post")
|
|
47
|
+
});
|
|
48
|
+
}
|
|
30
49
|
}
|
|
31
50
|
});
|
|
32
51
|
|
package/dist/module.d.cts
CHANGED
|
@@ -9,6 +9,24 @@ interface ModuleOptions {
|
|
|
9
9
|
* @default true
|
|
10
10
|
*/
|
|
11
11
|
enableRequestLogging?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Глобальний відлов помилок на сервері: Nitro `error` hook,
|
|
14
|
+
* `unhandledRejection` та `uncaughtException`.
|
|
15
|
+
* @default true
|
|
16
|
+
*/
|
|
17
|
+
enableErrorLogging?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Vue / Nuxt error hooks (SSR + браузер) та серверна ручка
|
|
20
|
+
* `/_logger/client-error`, через яку клієнтські помилки потрапляють
|
|
21
|
+
* у той самий stdout, що й серверні.
|
|
22
|
+
* @default true
|
|
23
|
+
*/
|
|
24
|
+
enableClientErrorLogging?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Шлях ручки, на яку браузерний плагін шле звіти про помилки.
|
|
27
|
+
* @default '/_logger/client-error'
|
|
28
|
+
*/
|
|
29
|
+
clientErrorEndpoint?: string;
|
|
12
30
|
}
|
|
13
31
|
declare const _default: any;
|
|
14
32
|
|
package/dist/module.d.mts
CHANGED
|
@@ -9,6 +9,24 @@ interface ModuleOptions {
|
|
|
9
9
|
* @default true
|
|
10
10
|
*/
|
|
11
11
|
enableRequestLogging?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Глобальний відлов помилок на сервері: Nitro `error` hook,
|
|
14
|
+
* `unhandledRejection` та `uncaughtException`.
|
|
15
|
+
* @default true
|
|
16
|
+
*/
|
|
17
|
+
enableErrorLogging?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Vue / Nuxt error hooks (SSR + браузер) та серверна ручка
|
|
20
|
+
* `/_logger/client-error`, через яку клієнтські помилки потрапляють
|
|
21
|
+
* у той самий stdout, що й серверні.
|
|
22
|
+
* @default true
|
|
23
|
+
*/
|
|
24
|
+
enableClientErrorLogging?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Шлях ручки, на яку браузерний плагін шле звіти про помилки.
|
|
27
|
+
* @default '/_logger/client-error'
|
|
28
|
+
*/
|
|
29
|
+
clientErrorEndpoint?: string;
|
|
12
30
|
}
|
|
13
31
|
declare const _default: any;
|
|
14
32
|
|
package/dist/module.d.ts
CHANGED
|
@@ -9,6 +9,24 @@ interface ModuleOptions {
|
|
|
9
9
|
* @default true
|
|
10
10
|
*/
|
|
11
11
|
enableRequestLogging?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Глобальний відлов помилок на сервері: Nitro `error` hook,
|
|
14
|
+
* `unhandledRejection` та `uncaughtException`.
|
|
15
|
+
* @default true
|
|
16
|
+
*/
|
|
17
|
+
enableErrorLogging?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Vue / Nuxt error hooks (SSR + браузер) та серверна ручка
|
|
20
|
+
* `/_logger/client-error`, через яку клієнтські помилки потрапляють
|
|
21
|
+
* у той самий stdout, що й серверні.
|
|
22
|
+
* @default true
|
|
23
|
+
*/
|
|
24
|
+
enableClientErrorLogging?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Шлях ручки, на яку браузерний плагін шле звіти про помилки.
|
|
27
|
+
* @default '/_logger/client-error'
|
|
28
|
+
*/
|
|
29
|
+
clientErrorEndpoint?: string;
|
|
12
30
|
}
|
|
13
31
|
declare const _default: any;
|
|
14
32
|
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineNuxtModule, createResolver, addImportsDir, addServerHandler } from '@nuxt/kit';
|
|
1
|
+
import { defineNuxtModule, createResolver, addImportsDir, addServerHandler, addServerPlugin, addPlugin } from '@nuxt/kit';
|
|
2
2
|
import { fileURLToPath } from 'url';
|
|
3
3
|
import { dirname } from 'path';
|
|
4
4
|
|
|
@@ -20,12 +20,17 @@ const module = defineNuxtModule({
|
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
22
|
defaults: {
|
|
23
|
-
enableRequestLogging: true
|
|
23
|
+
enableRequestLogging: true,
|
|
24
|
+
enableErrorLogging: true,
|
|
25
|
+
enableClientErrorLogging: true,
|
|
26
|
+
clientErrorEndpoint: "/_logger/client-error"
|
|
24
27
|
},
|
|
25
28
|
setup(options, nuxt) {
|
|
26
29
|
const moduleDir = typeof __dirname !== "undefined" ? __dirname : dirname(fileURLToPath(import.meta.url));
|
|
27
30
|
const resolver = createResolver(moduleDir);
|
|
28
31
|
nuxt.options.runtimeConfig.public.projectName = options.projectName || process.env.NUXT_PUBLIC_PROJECT_NAME || "hotelme";
|
|
32
|
+
const clientErrorEndpoint = options.clientErrorEndpoint || "/_logger/client-error";
|
|
33
|
+
nuxt.options.runtimeConfig.public.loggerClientErrorEndpoint = clientErrorEndpoint;
|
|
29
34
|
addImportsDir(resolver.resolve("./runtime"));
|
|
30
35
|
if (options.enableRequestLogging) {
|
|
31
36
|
addServerHandler({
|
|
@@ -33,6 +38,20 @@ const module = defineNuxtModule({
|
|
|
33
38
|
middleware: true
|
|
34
39
|
});
|
|
35
40
|
}
|
|
41
|
+
if (options.enableErrorLogging) {
|
|
42
|
+
addServerPlugin(resolver.resolve("./runtime/server/plugin"));
|
|
43
|
+
}
|
|
44
|
+
if (options.enableClientErrorLogging) {
|
|
45
|
+
addPlugin({
|
|
46
|
+
src: resolver.resolve("./runtime/plugins/error"),
|
|
47
|
+
mode: "all"
|
|
48
|
+
});
|
|
49
|
+
addServerHandler({
|
|
50
|
+
route: clientErrorEndpoint,
|
|
51
|
+
method: "post",
|
|
52
|
+
handler: resolver.resolve("./runtime/server/routes/client-error.post")
|
|
53
|
+
});
|
|
54
|
+
}
|
|
36
55
|
}
|
|
37
56
|
});
|
|
38
57
|
|
package/dist/runtime/logger.js
CHANGED
|
@@ -8,8 +8,8 @@ export var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
|
8
8
|
LogLevel2["Fatal"] = "Fatal";
|
|
9
9
|
return LogLevel2;
|
|
10
10
|
})(LogLevel || {});
|
|
11
|
-
const PROJECT_NAME = process.env.NUXT_PUBLIC_PROJECT_NAME || "hotelme";
|
|
12
|
-
const PID = process.pid;
|
|
11
|
+
const PROJECT_NAME = import.meta.server ? process.env.NUXT_PUBLIC_PROJECT_NAME || "hotelme" : "hotelme";
|
|
12
|
+
const PID = import.meta.server ? process.pid : void 0;
|
|
13
13
|
export function getRequestId() {
|
|
14
14
|
return uuidv4().replace(/-/g, "");
|
|
15
15
|
}
|
|
@@ -29,7 +29,8 @@ export default defineEventHandler(async (event) => {
|
|
|
29
29
|
const statusCode = res.statusCode;
|
|
30
30
|
const isApiRequest = fullUrl.startsWith("/api/");
|
|
31
31
|
const msg = isApiRequest ? "api request" : "stats";
|
|
32
|
-
|
|
32
|
+
const level = statusCode >= 500 ? "error" : statusCode >= 400 ? "warn" : "info";
|
|
33
|
+
logger[level](msg, {
|
|
33
34
|
reqid,
|
|
34
35
|
project: projectName,
|
|
35
36
|
stage: "after",
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Captures errors that the Nitro `error` hook does not see:
|
|
3
|
+
* - SSR Vue render errors (`vue:error`, `app:error`) — logged directly through the JSON logger.
|
|
4
|
+
* - Browser Vue/JS errors and unhandled promise rejections — POSTed to `/_logger/client-error`,
|
|
5
|
+
* which then re-emits them through the same logger on the server.
|
|
6
|
+
*/
|
|
7
|
+
declare const _default: any;
|
|
8
|
+
export default _default;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { defineNuxtPlugin, useRequestEvent, useRuntimeConfig } from "#imports";
|
|
2
|
+
import { logger } from "../logger.js";
|
|
3
|
+
export default defineNuxtPlugin((nuxtApp) => {
|
|
4
|
+
if (import.meta.server) {
|
|
5
|
+
const event = useRequestEvent();
|
|
6
|
+
const reqid = event?.context?.reqid;
|
|
7
|
+
const request = event?.path;
|
|
8
|
+
nuxtApp.hook("vue:error", (err, _instance, info) => {
|
|
9
|
+
logger.error("vue_ssr_error", {
|
|
10
|
+
reqid,
|
|
11
|
+
request,
|
|
12
|
+
info,
|
|
13
|
+
error: err?.message ?? String(err),
|
|
14
|
+
error_name: err?.name,
|
|
15
|
+
stack: err?.stack
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
nuxtApp.hook("app:error", (err) => {
|
|
19
|
+
logger.error("app_ssr_error", {
|
|
20
|
+
reqid,
|
|
21
|
+
request,
|
|
22
|
+
error: err?.message ?? String(err),
|
|
23
|
+
error_name: err?.name,
|
|
24
|
+
stack: err?.stack
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const endpoint = useRuntimeConfig().public.loggerClientErrorEndpoint || "/_logger/client-error";
|
|
30
|
+
const post = (msg, payload) => {
|
|
31
|
+
try {
|
|
32
|
+
fetch(endpoint, {
|
|
33
|
+
method: "POST",
|
|
34
|
+
headers: { "content-type": "application/json" },
|
|
35
|
+
body: JSON.stringify({
|
|
36
|
+
msg,
|
|
37
|
+
page: typeof location !== "undefined" ? location.pathname + location.search : void 0,
|
|
38
|
+
...payload
|
|
39
|
+
}),
|
|
40
|
+
keepalive: true
|
|
41
|
+
}).catch(() => {
|
|
42
|
+
});
|
|
43
|
+
} catch {
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
nuxtApp.hook("vue:error", (err, _i, info) => {
|
|
47
|
+
post("vue_client_error", {
|
|
48
|
+
info,
|
|
49
|
+
error: err?.message ?? String(err),
|
|
50
|
+
error_name: err?.name,
|
|
51
|
+
stack: err?.stack
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
window.addEventListener("error", (e) => {
|
|
55
|
+
const err = e.error;
|
|
56
|
+
post("window_error", {
|
|
57
|
+
error: err?.message ?? e.message,
|
|
58
|
+
error_name: err?.name,
|
|
59
|
+
stack: err?.stack,
|
|
60
|
+
file: e.filename,
|
|
61
|
+
line: e.lineno,
|
|
62
|
+
col: e.colno
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
window.addEventListener("unhandledrejection", (e) => {
|
|
66
|
+
const reason = e.reason;
|
|
67
|
+
post("window_unhandled_rejection", {
|
|
68
|
+
error: reason?.message ?? String(reason),
|
|
69
|
+
error_name: reason?.name,
|
|
70
|
+
stack: reason?.stack
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nitro plugin that turns every unhandled error into a structured JSON log line.
|
|
3
|
+
*
|
|
4
|
+
* Sources covered:
|
|
5
|
+
* - All errors thrown from server middleware / event handlers (`nitroApp.hooks.hook('error')`).
|
|
6
|
+
* - `unhandledRejection` and `uncaughtException` at the Node process level.
|
|
7
|
+
*
|
|
8
|
+
* `reqid` is read from `event.context.reqid` set by `logger.server.ts` middleware,
|
|
9
|
+
* so SSR and backend logs stay correlated by the same id.
|
|
10
|
+
*/
|
|
11
|
+
declare const _default: import("nitropack").NitroAppPlugin;
|
|
12
|
+
export default _default;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { defineNitroPlugin } from "nitropack/runtime";
|
|
2
|
+
import { logger } from "../logger.js";
|
|
3
|
+
export default defineNitroPlugin((nitroApp) => {
|
|
4
|
+
nitroApp.hooks.hook("error", (error, ctx) => {
|
|
5
|
+
const event = ctx?.event;
|
|
6
|
+
const req = event?.node?.req;
|
|
7
|
+
const res = event?.node?.res;
|
|
8
|
+
logger.error("unhandled_error", {
|
|
9
|
+
reqid: event?.context?.reqid,
|
|
10
|
+
domain: req?.headers?.host,
|
|
11
|
+
request: event?.path || req?.url,
|
|
12
|
+
method: req?.method,
|
|
13
|
+
response: res?.statusCode,
|
|
14
|
+
error: error instanceof Error ? error.message : String(error),
|
|
15
|
+
error_name: error instanceof Error ? error.name : void 0,
|
|
16
|
+
stack: error instanceof Error ? error.stack : void 0
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
const g = globalThis;
|
|
20
|
+
if (g.__hotelmeLoggerProcessHooks) return;
|
|
21
|
+
g.__hotelmeLoggerProcessHooks = true;
|
|
22
|
+
process.on("unhandledRejection", (reason) => {
|
|
23
|
+
logger.fatal("unhandled_rejection", {
|
|
24
|
+
error: reason instanceof Error ? reason.message : String(reason),
|
|
25
|
+
error_name: reason instanceof Error ? reason.name : void 0,
|
|
26
|
+
stack: reason instanceof Error ? reason.stack : void 0
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
process.on("uncaughtException", (err) => {
|
|
30
|
+
logger.fatal("uncaught_exception", {
|
|
31
|
+
error: err.message,
|
|
32
|
+
error_name: err.name,
|
|
33
|
+
stack: err.stack
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Receives error reports from the browser plugin and emits them through the
|
|
3
|
+
* same JSON logger, so server stdout becomes the single sink for all errors.
|
|
4
|
+
*/
|
|
5
|
+
declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{
|
|
6
|
+
ok: boolean;
|
|
7
|
+
}>>;
|
|
8
|
+
export default _default;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { defineEventHandler, readBody } from "h3";
|
|
2
|
+
import { logger } from "../../logger.js";
|
|
3
|
+
export default defineEventHandler(async (event) => {
|
|
4
|
+
const body = await readBody(event).catch(() => ({}));
|
|
5
|
+
const { msg, ...rest } = body || {};
|
|
6
|
+
logger.error(typeof msg === "string" && msg ? msg : "client_error", {
|
|
7
|
+
reqid: event.context.reqid,
|
|
8
|
+
domain: event.node.req.headers.host,
|
|
9
|
+
referer: event.node.req.headers.referer,
|
|
10
|
+
user_agent: event.node.req.headers["user-agent"],
|
|
11
|
+
...rest
|
|
12
|
+
});
|
|
13
|
+
return { ok: true };
|
|
14
|
+
});
|