hotelme-nuxt-logger 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 CHANGED
@@ -63,24 +63,20 @@ export default defineNuxtConfig({
63
63
  modules: ['@hotelme/nuxt-logger'],
64
64
 
65
65
  logger: {
66
- // Назва проекту для логів
66
+ // Назва проекту для всіх записів (запити, помилки Nitro, SSR, клієнтські
67
+ // помилки, ручні logger.*). Без неї — env NUXT_PUBLIC_PROJECT_NAME на збірці,
68
+ // далі 'hotelme'. Env NUXT_PUBLIC_PROJECT_NAME на рантаймі перекриває її.
67
69
  projectName: 'my-project',
68
70
 
69
71
  // Увімкнути автоматичне логування запитів
70
72
  enableRequestLogging: true
71
- },
72
-
73
- // Назва потрапляє в runtimeConfig.public.projectName і використовується для всіх
74
- // записів (запити, помилки Nitro, SSR, клієнтські помилки, ручні logger.*).
75
- // Альтернативно через env
76
- runtimeConfig: {
77
- public: {
78
- projectName: process.env.NUXT_PUBLIC_PROJECT_NAME || 'my-project'
79
- }
80
73
  }
81
74
  })
82
75
  ```
83
76
 
77
+ Назва лежить у приватному runtimeConfig (`logger.projectName`) і не потрапляє у
78
+ `window.__NUXT__` (з 1.7.0). Дублювати її в `runtimeConfig.public` не треба: модуль звідти не читає.
79
+
84
80
  ## Використання
85
81
 
86
82
  ### Автоматичне логування запитів
@@ -164,6 +160,8 @@ logger: {
164
160
  ignorePaths: ['/nuxt_img/'], // + типові /_nuxt/, /_ipx/, /__nuxt, clientErrorEndpoint
165
161
  ignoreUserAgents: ['^Slackbot-LinkExpanding ', '^kube-probe/'],
166
162
  slowMs: 1000, // порятунок повільних, env OTEL_TRACES_SLOW_MS
163
+ clientSpanName: 'upstream', // лише якщо хостів тисячі, див. нижче
164
+ clientSpanPaths: ['^/api-json/[a-z_]+$'], // шляхи, що лишаються в імені
167
165
  },
168
166
  }
169
167
  ```
@@ -194,8 +192,8 @@ OTEL_TRACES_SLOW_MS: "1000"
194
192
 
195
193
  - **Активний контекст на весь запит.** Плагін обгортає `nitroApp.h3App.handler`, тож middleware, handler'и та SSR-рендер виконуються всередині `context.with(serverSpan)` — span'и з коду застосунку стають дочірніми без обгорток.
196
194
  - **Server span** на кожен запит, батько — вхідний `traceparent`. Без нього trace id = `X-Request-ID` без дефісів (`2e285875-f20c-…` → `2e285875f20c…`, як у libwts3), якщо це UUID / 32 hex; інакше випадковий. У `event.context`: `otelSpan`; у відповіді — `X-Trace-Id`. 5xx → статус ERROR, 4xx — ні.
197
- - **Вихідні fetch** (native `fetch`, `$fetch`, ofetch на зовнішній URL) — `@opentelemetry/instrumentation-undici` через diagnostics_channel: CLIENT span `GET <host>` (повний URL — в `url.full`), `traceparent` і `X-Request-ID` сторінки, якщо виклик не поставив свій. Поза запитом span'и не пишуться.
198
- - **Внутрішні SSR-виклики** (`$fetch('/api/…')` → Nitro localFetch) ідуть у тому ж async-ланцюжку, тож span роуту стає дочірнім span'а сторінки, а logger-middleware бере reqid сторінки. Заголовки руками не потрібні.
195
+ - **Вихідні fetch** (native `fetch`, `$fetch`, ofetch на зовнішній URL) — `@opentelemetry/instrumentation-undici` через diagnostics_channel: CLIENT span `GET <host>` (повний URL — в `url.full`; з `clientSpanName` — `GET upstream` або `GET /api-json/<module>` за `clientSpanPaths`, хост лишається в `server.address`: ім'я span'а — вимір span-метрик, а домени кобрендів дають окрему серію кожен), `traceparent` і `X-Request-ID` сторінки, якщо виклик не поставив свій. Поза запитом span'и не пишуться.
196
+ - **Внутрішні SSR-виклики** (`$fetch('/api/…')` → Nitro localFetch) ідуть у тому ж async-ланцюжку, тож span роуту стає дочірнім span'а сторінки, а logger-middleware бере reqid сторінки. Заголовки руками не потрібні. Внутрішній підзапит на відфільтрований шлях (`/__nuxt_island/…`) span'а не отримує, але лишається в контексті сторінки — його `/api/…`-виклики стають прямими дітьми span'а сторінки.
199
197
  - **Назва span'а** — шаблон, ніколи сирий шлях (кожна назва — окремий stream у VictoriaTraces), визначається сама після роутингу:
200
198
  - сторінка → `route.name` з Vue Router без i18n-суфікса: `GET weather-citynameid`, `GET index` (аліаси теж). Локаль — в атрибуті `i18n.locale`;
201
199
  - Nitro-хендлер → шаблон з файлової структури: `GET /api/city_info`, `GET /record/**`;
package/dist/module.cjs CHANGED
@@ -28,9 +28,8 @@ const module$1 = kit.defineNuxtModule({
28
28
  setup(options, nuxt) {
29
29
  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))));
30
30
  const resolver = kit.createResolver(moduleDir);
31
- nuxt.options.runtimeConfig.public.projectName = options.projectName || process.env.NUXT_PUBLIC_PROJECT_NAME || "hotelme";
31
+ const projectName = options.projectName || process.env.NUXT_PUBLIC_PROJECT_NAME || "hotelme";
32
32
  const clientErrorEndpoint = options.clientErrorEndpoint || "/_logger/client-error";
33
- nuxt.options.runtimeConfig.public.loggerClientErrorEndpoint = clientErrorEndpoint;
34
33
  kit.addImportsDir(resolver.resolve("./runtime"));
35
34
  kit.addServerImports([
36
35
  { name: "logger", from: resolver.resolve("./runtime/logger") },
@@ -40,6 +39,7 @@ const module$1 = kit.defineNuxtModule({
40
39
  const { enabled: otelEnabled, ignorePaths = [], ...otel } = options.otel ?? {};
41
40
  nuxt.options.runtimeConfig.logger = {
42
41
  ...nuxt.options.runtimeConfig.logger,
42
+ projectName,
43
43
  otel: { ...otel, ignorePaths: [.../* @__PURE__ */ new Set([...ignorePaths, clientErrorEndpoint])] }
44
44
  };
45
45
  if (options.enableRequestLogging) {
@@ -52,6 +52,11 @@ const module$1 = kit.defineNuxtModule({
52
52
  kit.addServerPlugin(resolver.resolve("./runtime/server/plugin"));
53
53
  }
54
54
  if (options.enableClientErrorLogging) {
55
+ kit.addTemplate({
56
+ filename: "hotelme-nuxt-logger.mjs",
57
+ getContents: () => `export const clientErrorEndpoint = ${JSON.stringify(clientErrorEndpoint)}
58
+ `
59
+ });
55
60
  kit.addPlugin({
56
61
  src: resolver.resolve("./runtime/plugins/error"),
57
62
  mode: "all"
package/dist/module.d.cts CHANGED
@@ -64,6 +64,19 @@ interface OtelOptions {
64
64
  * `OTEL_TRACES_SLOW_MS`. 0 — вимкнено.
65
65
  */
66
66
  slowMs?: number;
67
+ /**
68
+ * Замість hostname в імені вихідних span'ів (`GET upstream`). Ім'я span'а —
69
+ * вимір span-метрик: коли хостів тисячі (домени кобрендів), кожен дає окрему
70
+ * серію. Hostname лишається в `server.address`, URL — в `url.full`.
71
+ * Без опції — `GET <hostname>`.
72
+ */
73
+ clientSpanName?: string;
74
+ /**
75
+ * Regex-рядки шляхів, що лишаються в імені замість `clientSpanName`, напр.
76
+ * `'^/api-json/[a-z_]+$'` → `GET /api-json/hotel_info_json`. Лише обмежений
77
+ * набір, без id. Діє разом з `clientSpanName`.
78
+ */
79
+ clientSpanPaths?: string[];
67
80
  }
68
81
  declare const _default: any;
69
82
 
package/dist/module.d.mts CHANGED
@@ -64,6 +64,19 @@ interface OtelOptions {
64
64
  * `OTEL_TRACES_SLOW_MS`. 0 — вимкнено.
65
65
  */
66
66
  slowMs?: number;
67
+ /**
68
+ * Замість hostname в імені вихідних span'ів (`GET upstream`). Ім'я span'а —
69
+ * вимір span-метрик: коли хостів тисячі (домени кобрендів), кожен дає окрему
70
+ * серію. Hostname лишається в `server.address`, URL — в `url.full`.
71
+ * Без опції — `GET <hostname>`.
72
+ */
73
+ clientSpanName?: string;
74
+ /**
75
+ * Regex-рядки шляхів, що лишаються в імені замість `clientSpanName`, напр.
76
+ * `'^/api-json/[a-z_]+$'` → `GET /api-json/hotel_info_json`. Лише обмежений
77
+ * набір, без id. Діє разом з `clientSpanName`.
78
+ */
79
+ clientSpanPaths?: string[];
67
80
  }
68
81
  declare const _default: any;
69
82
 
package/dist/module.d.ts CHANGED
@@ -64,6 +64,19 @@ interface OtelOptions {
64
64
  * `OTEL_TRACES_SLOW_MS`. 0 — вимкнено.
65
65
  */
66
66
  slowMs?: number;
67
+ /**
68
+ * Замість hostname в імені вихідних span'ів (`GET upstream`). Ім'я span'а —
69
+ * вимір span-метрик: коли хостів тисячі (домени кобрендів), кожен дає окрему
70
+ * серію. Hostname лишається в `server.address`, URL — в `url.full`.
71
+ * Без опції — `GET <hostname>`.
72
+ */
73
+ clientSpanName?: string;
74
+ /**
75
+ * Regex-рядки шляхів, що лишаються в імені замість `clientSpanName`, напр.
76
+ * `'^/api-json/[a-z_]+$'` → `GET /api-json/hotel_info_json`. Лише обмежений
77
+ * набір, без id. Діє разом з `clientSpanName`.
78
+ */
79
+ clientSpanPaths?: string[];
67
80
  }
68
81
  declare const _default: any;
69
82
 
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": "^3.0.0 || ^4.0.0"
6
6
  },
7
- "version": "1.6.0",
7
+ "version": "1.8.0",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "0.8.4",
10
10
  "unbuild": "2.0.0"
package/dist/module.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { defineNuxtModule, createResolver, addImportsDir, addServerImports, addServerHandler, addServerPlugin, addPlugin } from '@nuxt/kit';
1
+ import { defineNuxtModule, createResolver, addImportsDir, addServerImports, addServerHandler, addServerPlugin, addTemplate, addPlugin } from '@nuxt/kit';
2
2
  import { fileURLToPath } from 'url';
3
3
  import { dirname } from 'path';
4
4
 
@@ -34,9 +34,8 @@ const module = defineNuxtModule({
34
34
  setup(options, nuxt) {
35
35
  const moduleDir = typeof __dirname !== "undefined" ? __dirname : dirname(fileURLToPath(import.meta.url));
36
36
  const resolver = createResolver(moduleDir);
37
- nuxt.options.runtimeConfig.public.projectName = options.projectName || process.env.NUXT_PUBLIC_PROJECT_NAME || "hotelme";
37
+ const projectName = options.projectName || process.env.NUXT_PUBLIC_PROJECT_NAME || "hotelme";
38
38
  const clientErrorEndpoint = options.clientErrorEndpoint || "/_logger/client-error";
39
- nuxt.options.runtimeConfig.public.loggerClientErrorEndpoint = clientErrorEndpoint;
40
39
  addImportsDir(resolver.resolve("./runtime"));
41
40
  addServerImports([
42
41
  { name: "logger", from: resolver.resolve("./runtime/logger") },
@@ -46,6 +45,7 @@ const module = defineNuxtModule({
46
45
  const { enabled: otelEnabled, ignorePaths = [], ...otel } = options.otel ?? {};
47
46
  nuxt.options.runtimeConfig.logger = {
48
47
  ...nuxt.options.runtimeConfig.logger,
48
+ projectName,
49
49
  otel: { ...otel, ignorePaths: [.../* @__PURE__ */ new Set([...ignorePaths, clientErrorEndpoint])] }
50
50
  };
51
51
  if (options.enableRequestLogging) {
@@ -58,6 +58,11 @@ const module = defineNuxtModule({
58
58
  addServerPlugin(resolver.resolve("./runtime/server/plugin"));
59
59
  }
60
60
  if (options.enableClientErrorLogging) {
61
+ addTemplate({
62
+ filename: "hotelme-nuxt-logger.mjs",
63
+ getContents: () => `export const clientErrorEndpoint = ${JSON.stringify(clientErrorEndpoint)}
64
+ `
65
+ });
61
66
  addPlugin({
62
67
  src: resolver.resolve("./runtime/plugins/error"),
63
68
  mode: "all"
@@ -1,14 +1,13 @@
1
1
  import { defineEventHandler, getRequestURL } from "h3";
2
- import { useRuntimeConfig } from "#imports";
3
2
  import { logger, setProjectName } from "../logger.js";
3
+ import { projectNameFromConfig } from "../server/projectName.js";
4
4
  import { v4 as uuidv4 } from "uuid";
5
5
  export default defineEventHandler(async (event) => {
6
6
  if (event.context.reqid) {
7
7
  return;
8
8
  }
9
9
  try {
10
- const config = useRuntimeConfig();
11
- const projectName = config.public.projectName || "hotelme";
10
+ const projectName = projectNameFromConfig();
12
11
  setProjectName(projectName);
13
12
  let reqid = event.node.req.headers["x-request-id"];
14
13
  if (!reqid) {
@@ -1,9 +1,11 @@
1
- import { defineNuxtPlugin, useRequestEvent, useRuntimeConfig } from "#imports";
1
+ import { defineNuxtPlugin, useRequestEvent } from "#imports";
2
+ import { clientErrorEndpoint } from "#build/hotelme-nuxt-logger.mjs";
2
3
  import { logger, setProjectName } from "../logger.js";
4
+ import { projectNameFromConfig } from "../server/projectName.js";
3
5
  import { isBrowserExtensionError } from "../browserExtensionFilter.js";
4
6
  export default defineNuxtPlugin((nuxtApp) => {
5
7
  if (import.meta.server) {
6
- setProjectName(useRuntimeConfig().public.projectName);
8
+ setProjectName(projectNameFromConfig());
7
9
  const event = useRequestEvent();
8
10
  const reqid = event?.context?.reqid;
9
11
  const request = event?.path;
@@ -28,11 +30,10 @@ export default defineNuxtPlugin((nuxtApp) => {
28
30
  });
29
31
  return;
30
32
  }
31
- const endpoint = useRuntimeConfig().public.loggerClientErrorEndpoint || "/_logger/client-error";
32
33
  const post = (msg, payload) => {
33
34
  if (isBrowserExtensionError(payload)) return;
34
35
  try {
35
- fetch(endpoint, {
36
+ fetch(clientErrorEndpoint, {
36
37
  method: "POST",
37
38
  headers: { "content-type": "application/json" },
38
39
  body: JSON.stringify({
@@ -0,0 +1,26 @@
1
+ /** Налаштування імені вихідних (CLIENT) span'ів, див. `clientSpanName`. */
2
+ export interface ClientSpanNaming {
3
+ /**
4
+ * Замість hostname в імені: `GET upstream`. Без нього ім'я — `GET <hostname>`.
5
+ * Hostname лишається в `server.address`.
6
+ */
7
+ clientSpanName?: string;
8
+ /**
9
+ * Regex-рядки шляхів, які можна лишити в імені (`^/api-json/[a-z_]+$`) —
10
+ * лише обмежений набір, без id. Діє разом з `clientSpanName`; решта шляхів
11
+ * отримують `clientSpanName`.
12
+ */
13
+ clientSpanPaths?: string[];
14
+ }
15
+ /**
16
+ * Ім'я вихідного HTTP-span'а. Ім'я span'а — вимір span-метрик, тож hostname у
17
+ * ньому (домен кобренда в hotel-renderer) дає окрему серію на кожен домен.
18
+ *
19
+ * - без `clientSpanName` — `METHOD hostname`, як у 1.6.2;
20
+ * - шлях з `clientSpanPaths` — `METHOD /path`;
21
+ * - решта — `METHOD <clientSpanName>`.
22
+ *
23
+ * Чиста функція без `#imports`: нею користуються й проєкти, які самі відкривають
24
+ * CLIENT span (raw `node:http`).
25
+ */
26
+ export declare function clientSpanName(method: string, origin: string, path: string, naming?: ClientSpanNaming): string;
@@ -0,0 +1,15 @@
1
+ const compiled = /* @__PURE__ */ new WeakMap();
2
+ function patterns(paths) {
3
+ let regexps = compiled.get(paths);
4
+ if (!regexps) {
5
+ regexps = paths.map((path) => new RegExp(path));
6
+ compiled.set(paths, regexps);
7
+ }
8
+ return regexps;
9
+ }
10
+ export function clientSpanName(method, origin, path, naming = {}) {
11
+ const { clientSpanName: label, clientSpanPaths = [] } = naming;
12
+ if (!label) return `${method} ${new URL(origin).hostname}`;
13
+ const pathname = path.split("?")[0];
14
+ return `${method} ${patterns(clientSpanPaths).some((re) => re.test(pathname)) ? pathname : label}`;
15
+ }
@@ -1,6 +1,7 @@
1
1
  import { type Sampler } from '@opentelemetry/sdk-trace-base';
2
+ import type { ClientSpanNaming } from './clientSpanName.js';
2
3
  /** Серіалізована форма `logger.otel` з nuxt.config (див. module.ts). */
3
- export interface OtelRuntimeConfig {
4
+ export interface OtelRuntimeConfig extends ClientSpanNaming {
4
5
  ignorePaths?: string[];
5
6
  ignoreStaticAssets?: boolean;
6
7
  ignoreUserAgents?: string[];
@@ -1,5 +1,4 @@
1
1
  import { defineNitroPlugin } from "nitropack/runtime";
2
- import { useRuntimeConfig } from "#imports";
3
2
  import { context, diag, DiagLogLevel, propagation, trace } from "@opentelemetry/api";
4
3
  import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
5
4
  import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
@@ -9,9 +8,11 @@ import { registerInstrumentations } from "@opentelemetry/instrumentation";
9
8
  import { UndiciInstrumentation } from "@opentelemetry/instrumentation-undici";
10
9
  import { logger } from "../../logger.js";
11
10
  import { currentRequestEvent, requestIdOf } from "../requestContext.js";
11
+ import { projectNameFromConfig } from "../projectName.js";
12
12
  import { serverSpanContext } from "./serverSpan.js";
13
13
  import { requestIdGenerator } from "./requestTraceId.js";
14
- import { envSampler, otelSampling } from "./config.js";
14
+ import { envSampler, otelRuntimeConfig, otelSampling } from "./config.js";
15
+ import { clientSpanName } from "./clientSpanName.js";
15
16
  import { ForceSampler, HeadSampler, SlowTraceSpanProcessor } from "./sampling.js";
16
17
  const diagLogger = {
17
18
  error: (message, ...args) => logger.error("otel_diag", { error: message, args }),
@@ -35,7 +36,7 @@ function undiciInstrumentation() {
35
36
  return new UndiciInstrumentation({
36
37
  requireParentforSpans: true,
37
38
  requestHook: (span, request) => {
38
- span.updateName(`${request.method} ${new URL(request.origin).hostname}`);
39
+ span.updateName(clientSpanName(request.method, request.origin, request.path, otelRuntimeConfig()));
39
40
  const reqid = requestIdOf(currentRequestEvent());
40
41
  if (reqid && !hasHeader(request, "x-request-id")) request.addHeader("x-request-id", reqid);
41
42
  }
@@ -48,7 +49,7 @@ export default defineNitroPlugin((nitroApp) => {
48
49
  return;
49
50
  }
50
51
  diag.setLogger(diagLogger, DiagLogLevel.WARN);
51
- const serviceName = process.env.OTEL_SERVICE_NAME || String(useRuntimeConfig().public.projectName || "hotelme");
52
+ const serviceName = process.env.OTEL_SERVICE_NAME || projectNameFromConfig();
52
53
  const batchProcessor = new BatchSpanProcessor(new OTLPTraceExporter(), {
53
54
  maxQueueSize: 2048,
54
55
  maxExportBatchSize: 512,
@@ -19,6 +19,8 @@ declare module 'h3' {
19
19
  * невибраний контекст, а не просто відсутність span'а: інакше їхні внутрішні
20
20
  * /api-виклики, вихідні fetch і span'и бекенда стали б осиротілими
21
21
  * root-трейсами. Дочірні запити успадковують його через parent-based семплер.
22
+ * Виняток — внутрішній підзапит з локальним span'ом у контексті: він
23
+ * лишається в контексті сторінки без власного span'а.
22
24
  *
23
25
  * `?force_otel=1` (як у libwts3) — трейс вибраний попри фільтри, частку
24
26
  * семплера й вхідний `traceparent …-00`, root з `sampling.kept_by: "force"`.
@@ -26,6 +26,8 @@ export function serverSpanContext(event) {
26
26
  if (isTracingSuppressed(active)) return active;
27
27
  const forced = new URLSearchParams(query).get("force_otel") === "1";
28
28
  if (!forced && (settings.ignoreUserAgent?.test(userAgent) || settings.ignorePaths.some((prefix) => pathname.startsWith(prefix)) || settings.ignoreStaticAssets && STATIC_ASSET.test(pathname))) {
29
+ const parent = trace.getSpan(active)?.spanContext();
30
+ if (parent && !parent.isRemote && isSpanContextValid(parent)) return active;
29
31
  return unsampledContext(active);
30
32
  }
31
33
  const carrier = {};
@@ -1,5 +1,6 @@
1
1
  import type { H3Event } from 'h3';
2
2
  import type { Span } from '@opentelemetry/api';
3
+ export { clientSpanName, type ClientSpanNaming } from './clientSpanName.js';
3
4
  declare module 'h3' {
4
5
  interface H3EventContext {
5
6
  otelSpan?: Span;
@@ -1,4 +1,5 @@
1
1
  import { currentRequestEvent, requestIdOf } from "../requestContext.js";
2
+ export { clientSpanName } from "./clientSpanName.js";
2
3
  export function traceHeaders(event = currentRequestEvent()) {
3
4
  const reqid = requestIdOf(event);
4
5
  return reqid ? { "X-Request-ID": reqid } : {};
@@ -1,9 +1,9 @@
1
1
  import { defineNitroPlugin } from "nitropack/runtime";
2
- import { useRuntimeConfig } from "#imports";
3
2
  import { logger, setProjectName } from "../logger.js";
3
+ import { projectNameFromConfig } from "./projectName.js";
4
4
  import { httpStatusOf, isClientError, errorText } from "../httpError.js";
5
5
  export default defineNitroPlugin((nitroApp) => {
6
- setProjectName(useRuntimeConfig().public.projectName);
6
+ setProjectName(projectNameFromConfig());
7
7
  nitroApp.hooks.hook("error", (error, ctx) => {
8
8
  const event = ctx?.event;
9
9
  const req = event?.node?.req;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Назва проекту з nuxt.config (`logger.projectName`). Лежить у приватному
3
+ * runtimeConfig (`logger.projectName`), бо потрібна лише серверу: з
4
+ * `runtimeConfig.public` вона потрапляла у window.__NUXT__.
5
+ *
6
+ * Env `NUXT_PUBLIC_PROJECT_NAME` на рантаймі перекриває її, як і до 1.7.0, коли
7
+ * назва лежала в `runtimeConfig.public.projectName`.
8
+ */
9
+ export declare function projectNameFromConfig(): string;
@@ -0,0 +1,4 @@
1
+ import { useRuntimeConfig } from "#imports";
2
+ export function projectNameFromConfig() {
3
+ return process.env.NUXT_PUBLIC_PROJECT_NAME || useRuntimeConfig().logger?.projectName || "hotelme";
4
+ }
@@ -1,7 +1,7 @@
1
1
  import { defineEventHandler, readBody } from "h3";
2
- import { useRuntimeConfig } from "#imports";
3
2
  import { logger } from "../../logger.js";
4
3
  import { isBrowserExtensionError } from "../../browserExtensionFilter.js";
4
+ import { projectNameFromConfig } from "../projectName.js";
5
5
  export default defineEventHandler(async (event) => {
6
6
  const body = await readBody(event).catch(() => ({}));
7
7
  const { msg, ...rest } = body || {};
@@ -10,7 +10,7 @@ export default defineEventHandler(async (event) => {
10
10
  }
11
11
  logger.error(typeof msg === "string" && msg ? msg : "client_error", {
12
12
  reqid: event.context.reqid,
13
- project: useRuntimeConfig().public.projectName,
13
+ project: projectNameFromConfig(),
14
14
  domain: event.node.req.headers.host,
15
15
  referer: event.node.req.headers.referer,
16
16
  user_agent: event.node.req.headers["user-agent"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hotelme-nuxt-logger",
3
- "version": "1.6.0",
3
+ "version": "1.8.0",
4
4
  "description": "Стандартний logger для Nuxt проектів з JSON виводом сумісним з бекенд-логами",
5
5
  "keywords": [
6
6
  "nuxt",