@logickernel/logger 0.6.1 → 0.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
@@ -3,12 +3,13 @@
3
3
  Lightweight Node.js logger that automatically routes logs to **Google Cloud Logging** (when available) or the **local console**. Designed for small services and tools where you want structured logs in GCP without wiring up a full logging stack.
4
4
 
5
5
  ```ts
6
- import logger from "@logickernel/logger";
6
+ import { logger } from "@logickernel/logger";
7
7
 
8
- logger.info("server started", { port: 3000 });
9
- logger.debug("user action", { userId: "123", action: "login" });
10
- logger.error(new Error("something went wrong"));
11
- logger.warning("disk space low", { used: "92%", mount: "/data" });
8
+ const log = logger("api"); // optional scope label on every entry
9
+
10
+ log.info("server started", { port: 3000 });
11
+ log.debug("user action", { userId: "123", action: "login" });
12
+ log.warning("disk space low", { used: "92%", mount: "/data" });
12
13
  ```
13
14
 
14
15
  > Your code never has to care whether it's running on Cloud Run / GCP or locally – the logger picks the right backend at startup.
@@ -17,18 +18,21 @@ logger.warning("disk space low", { used: "92%", mount: "/data" });
17
18
 
18
19
  ## 1. Introduction
19
20
 
20
- - **What it is**: A tiny logging helper with the full GCP severity ladder and a smart backend:
21
- - In **GCP** (or when `SYSTEM_LOGS=gcp`): writes to Google Cloud Logging with proper severities and structured `jsonPayload` when a context object is provided.
22
- - Otherwise: writes to the local console with emoji prefixes, a local timestamp, and the context object inlined as compact JSON.
23
- - **Why it exists**: To avoid sprinkling environment-specific logging logic across your codebase. You import one `logger` and use it everywhere.
21
+ - **What it is**: A tiny logging helper with the full GCP severity ladder and a configurable backend:
22
+ - In **GCP** (or when `LOGGER_TARGET=gcp`): writes to Google Cloud Logging with proper severities and structured `jsonPayload` when a payload object is provided.
23
+ - On the **console**: writes with emoji prefixes, a local timestamp, and the payload inlined as compact JSON.
24
+ - **Both at once**: set `LOGGER_TARGET=gcp,console` to fan out to both.
25
+ - **Why it exists**: To avoid sprinkling environment-specific logging logic across your codebase. You import one factory and use it everywhere.
24
26
 
25
27
  **Key features**
26
28
 
27
29
  - **Zero config in GCP**: Uses `LOGGER_NAME` / `K_SERVICE` and `GCP_PROJECT` from the environment.
28
- - **Auto backend selection**: GCP vs console decided once at module load.
30
+ - **Auto backend selection**: GCP vs console decided once at module load; override with `LOGGER_TARGET`.
31
+ - **Multi-backend**: `LOGGER_TARGET` accepts a comma-separated list — `"gcp,console"` writes to both simultaneously.
29
32
  - **Full severity ladder**: `debug`, `info`, `notice`, `warning`, `error`, `critical`, `alert`, `emergency`.
30
- - **Structured context**: Pass a plain object as the last argument — it becomes a `jsonPayload` in GCP (queryable by field) and inline JSON in the console.
31
- - **Tiny API**: One default export (`logger`) plus a `formatMessage` helper if you need it.
33
+ - **Structured context**: Pass a plain object as the second argument — it becomes a `jsonPayload` in GCP (queryable by field) and inline JSON in the console.
34
+ - **Scope**: `logger("name")` attaches a `scope` label to every entry, great for filtering by component.
35
+ - **Per-call labels**: Pass a third argument to attach GCP labels to a single entry (e.g. `traceId`, `userId`).
32
36
 
33
37
  ---
34
38
 
@@ -43,26 +47,42 @@ npm install @logickernel/logger
43
47
  ### Basic usage
44
48
 
45
49
  ```ts
46
- import logger from "@logickernel/logger";
47
-
48
- // Message only
49
- logger.info("server started");
50
- logger.debug("cache miss");
51
- logger.error(new Error("connection refused"));
52
-
53
- // Message with structured context
54
- logger.info("server started", { port: 3000, env: "production" });
55
- logger.debug("cache miss", { key: "user:42", ttl: 300 });
56
- logger.warning("disk space low", { used: "92%", mount: "/data" });
57
- logger.error("request failed", { method: "POST", path: "/api/orders", status: 503 });
58
- logger.critical("primary db unreachable", { host: "db-1", retries: 3 });
50
+ import { logger } from "@logickernel/logger";
51
+
52
+ // Scopeless logger — fine for scripts and simple tools
53
+ const log = logger();
54
+
55
+ log.info("server started");
56
+ log.debug("cache miss");
57
+ log.warning("disk space low", { used: "92%", mount: "/data" });
58
+ log.error("request failed", { method: "POST", path: "/api/orders", status: 503 });
59
+ log.critical("primary db unreachable", { host: "db-1", retries: 3 });
60
+
61
+ // Scoped logger attaches scope: "api" to every entry as a GCP label
62
+ const apiLog = logger("api");
63
+ apiLog.info("request handled", { method: "GET", status: 200 });
64
+
65
+ // Per-call labels — merged with scope and env labels for that entry only
66
+ apiLog.info("request handled", { method: "GET", status: 200 }, { traceId: "abc-123" });
59
67
  ```
60
68
 
61
- The default export is a **singleton** whose backend is chosen at module load:
69
+ `logger(scope?)` returns a `Logger` instance. Call it once per module or service boundary. The backend (GCP or console) is chosen once at module load:
62
70
 
63
71
  - **GCP backend** is used when `GCP_PROJECT` is set.
64
72
  - Otherwise, the **console backend** is used.
65
73
 
74
+ ### Method signature
75
+
76
+ All eight severity methods share the same signature:
77
+
78
+ ```ts
79
+ log.info(message: string, payload?: Record<string, unknown>, labels?: Record<string, string>): void
80
+ ```
81
+
82
+ - **`message`** — required string.
83
+ - **`payload`** — optional plain object. Becomes `jsonPayload` in GCP (fields indexed and queryable); inlined as compact JSON on the console.
84
+ - **`labels`** — optional per-call labels merged with scope and env labels (GCP only; ignored on console).
85
+
66
86
  ### Severity methods
67
87
 
68
88
  | Method | GCP severity | Console emoji |
@@ -71,62 +91,92 @@ The default export is a **singleton** whose backend is chosen at module load:
71
91
  | `info` | `INFO` | ⚪️ |
72
92
  | `notice` | `NOTICE` | 🔵 |
73
93
  | `warning` | `WARNING` | 🟡 |
74
- | `error` | `ERROR` | ⛔️ |
75
- | `critical` | `CRITICAL` | ❗️ |
76
- | `alert` | `ALERT` | 🔴 |
94
+ | `error` | `ERROR` | 🔴 |
95
+ | `critical` | `CRITICAL` | ⛔️ |
96
+ | `alert` | `ALERT` | ❗️ |
77
97
  | `emergency` | `EMERGENCY` | 🚨 |
78
98
 
99
+ ### Scope
100
+
101
+ `logger(scope)` attaches a `scope` label to every entry, letting you filter by component in Cloud Logging:
102
+
103
+ ```ts
104
+ const db = logger("db");
105
+ db.warning("slow query", { ms: 412, query: "SELECT ..." });
106
+ // GCP entry: labels.scope = "db"
107
+ ```
108
+
79
109
  ### Structured context
80
110
 
81
- Pass a plain object as the last argument to attach structured data to a log entry:
111
+ Pass a plain object as the second argument to attach structured data to a log entry:
82
112
 
83
113
  ```ts
84
- logger.info("request complete", { method: "GET", path: "/api/users", status: 200, ms: 42 });
114
+ log.info("request complete", { method: "GET", path: "/api/users", status: 200, ms: 42 });
85
115
  ```
86
116
 
87
117
  - **GCP backend**: written as `jsonPayload` — fields are indexed and queryable in Cloud Logging.
88
118
  - **Console backend**: inlined as spaced JSON on the same line.
89
119
 
120
+ ### Per-call labels
121
+
122
+ Pass a `Record<string, string>` as the third argument to attach labels to a single entry (GCP only). They are merged with env labels and scope, with per-call values taking precedence:
123
+
124
+ ```ts
125
+ log.info("payment processed", { amount: 99 }, { traceId: "t-123", userId: "u-42" });
126
+ // GCP entry: labels = { ...envLabels, scope: "...", traceId: "t-123", userId: "u-42" }
127
+ ```
128
+
90
129
  ### Console format
91
130
 
92
- By default, console logs are plain: `message [payload]` without emoji or timestamp.
131
+ By default, console logs are plain: `[(scope) ]message[ {payload}]` without emoji or timestamp.
93
132
 
94
- When `LOGGER_FORMAT=pretty`, console logs look like:
133
+ When `LOGGER_CONSOLE_FORMAT=pretty`, console logs look like:
95
134
 
96
135
  ```
97
136
  ⚪️ 2026-02-26 13:04:22.120 server started
98
- 🐞 2026-02-26 13:04:22.341 cache miss { "key": "user:42", "ttl": 300 }
137
+ 🐞 2026-02-26 13:04:22.341 (api) cache miss { "key": "user:42", "ttl": 300 }
99
138
  🟡 2026-02-26 13:04:22.512 disk space low { "used": "92%", "mount": "/data" }
100
139
  ```
101
140
 
102
- This "pretty" format (emoji + local timestamp + message + optional payload) is meant to roughly emulate what you see in the GCP Logging console when browsing entries by severity and time.
141
+ Scope (if set) appears in parentheses before the message. Labels are GCP metadata and are not shown on the console.
103
142
 
104
143
  ### Environment variables
105
144
 
106
- - `GCP_PROJECT`
107
- Project ID for Google Cloud Logging. When set (and `LOGGER_TARGET` isn’t forcing console), the GCP backend is used.
145
+ - `LOGGER_NAME`
146
+ Log name in Google Cloud Logging. This is a very important attribute that is the primary group in reports — logs are usually grouped by system instance/environment so entries stay together. Falls back to `K_SERVICE`, then `"local"`.
147
+
148
+ - `GCP_PROJECT`
149
+ Project ID for Google Cloud Logging. When set (and `LOGGER_TARGET` isn't forcing console), the GCP backend is used.
108
150
 
109
- - `LOGGER_NAME`
110
- Log name in Google Cloud Logging. Falls back to `K_SERVICE`, then `"local"`.
151
+ - `LOGGER_TARGET`
152
+ Comma-separated list of backends to activate: `"gcp"`, `"console"`, or `"gcp,console"` for both simultaneously. When unset, GCP is used if `GCP_PROJECT` is set, otherwise console.
111
153
 
112
- - `LOGGER_TARGET`
113
- Optional override for the backend: `"gcp"` forces the GCP logger when possible, `"console"` forces the console logger.
154
+ - `LOGGER_CONSOLE_FORMAT`
155
+ Controls the console output format. When set to `"pretty"`, uses emoji + timestamp lines; otherwise (default) prints plain `message [payload]` without emoji or timestamp.
114
156
 
115
- - `LOGGER_FORMAT`
116
- Controls the console output format. When set to `"pretty"`, uses emoji + timestamp lines (mirroring the feel of GCP Logging's console UI); otherwise (default) prints plain `message [payload]` without emoji or timestamp.
157
+ - `ENVIRONMENT`
158
+ Attached as `labels.environment` on every GCP entry. Useful for filtering by `"production"`, `"staging"`, etc.
117
159
 
118
- - `K_SERVICE`
119
- Fallback log name in Google Cloud Logging when `LOGGER_NAME` is not set. Usually set up by Google Cloud Run. If neither is set, `"local"` is used.
160
+ - `SERVICE_ID`
161
+ Attached as `labels.service_id` on every GCP entry.
162
+
163
+ - `VERSION`
164
+ Attached as `labels.version` on every GCP entry.
165
+
166
+ - `K_SERVICE`
167
+ Fallback log name in Google Cloud Logging when `LOGGER_NAME` is not set. Usually set automatically by Google Cloud Run.
120
168
 
121
169
  ### Named exports
122
170
 
123
171
  ```ts
124
- import logger, { Logger, formatMessage } from "@logickernel/logger";
172
+ import { logger } from "@logickernel/logger";
173
+ import type { Logger } from "@logickernel/logger";
125
174
 
126
- const myLogger: Logger = logger;
127
- const message = formatMessage(["hello", { id: 1 }]); // "hello {"id":1}"
175
+ const log: Logger = logger("my-scope");
128
176
  ```
129
177
 
178
+ `logger` is also the default export: `import logger from "@logickernel/logger"`.
179
+
130
180
  ---
131
181
 
132
182
  ## 3. Local Setup (Development)
package/dist/index.cjs CHANGED
@@ -21,150 +21,170 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  default: () => index_default,
24
- formatMessage: () => formatMessage,
25
24
  logger: () => logger
26
25
  });
27
26
  module.exports = __toCommonJS(index_exports);
28
27
  var import_logging = require("@google-cloud/logging");
29
- function formatMessage(args) {
30
- return args.map((arg) => {
31
- if (typeof arg === "string") return arg;
32
- if (arg instanceof Error) return arg.message + (arg.stack ? `
33
- ${arg.stack}` : "");
34
- try {
35
- return JSON.stringify(arg);
36
- } catch {
37
- return String(arg);
38
- }
39
- }).join(" ");
40
- }
41
- var LOGGER_TARGET = process.env.LOGGER_TARGET?.toLowerCase();
42
- var LOGGER_FORMAT = process.env.LOGGER_FORMAT?.toLowerCase();
43
- var FORCE_GCP = LOGGER_TARGET === "gcp";
44
- var FORCE_CONSOLE = LOGGER_TARGET === "console";
45
- var USE_GCP = !FORCE_CONSOLE && (FORCE_GCP || !!process.env.GCP_PROJECT);
46
- var CONSOLE_PRETTY = LOGGER_FORMAT === "pretty";
28
+ var rawTargets = process.env.LOGGER_TARGET;
29
+ var targets = rawTargets ? new Set(rawTargets.toLowerCase().split(",").map((s) => s.trim()).filter(Boolean)) : null;
30
+ var USE_GCP = targets ? targets.has("gcp") : !!process.env.GCP_PROJECT;
31
+ var USE_CONSOLE = targets ? targets.has("console") : !process.env.GCP_PROJECT;
32
+ var CONSOLE_PRETTY = process.env.LOGGER_CONSOLE_FORMAT?.toLowerCase() === "pretty";
47
33
  var noop = () => {
48
34
  };
49
- var gcpLabels = {};
50
- if (process.env.ENVIRONMENT) gcpLabels.environment = process.env.ENVIRONMENT;
51
- if (process.env.SERVICE_ID) gcpLabels.service_id = process.env.SERVICE_ID;
52
- if (process.env.VERSION) gcpLabels.version = process.env.VERSION;
53
- var GCP_ENV_LABEL = Object.keys(gcpLabels).length ? { labels: gcpLabels } : {};
54
- function consoleLine(emoji, args) {
35
+ var envLabels = {};
36
+ if (process.env.ENVIRONMENT) envLabels.environment = process.env.ENVIRONMENT;
37
+ if (process.env.SERVICE_ID) envLabels.service_id = process.env.SERVICE_ID;
38
+ if (process.env.VERSION) envLabels.version = process.env.VERSION;
39
+ var gcpLog = USE_GCP ? (() => {
40
+ try {
41
+ const logName = process.env.LOGGER_NAME ?? process.env.K_SERVICE ?? "local";
42
+ return new import_logging.Logging({ projectId: process.env.GCP_PROJECT }).log(logName);
43
+ } catch {
44
+ return null;
45
+ }
46
+ })() : null;
47
+ function consoleLine(emoji, message, payload, scope) {
55
48
  const d = /* @__PURE__ */ new Date();
56
49
  const ts = d.toLocaleString("sv-SE") + "." + String(d.getMilliseconds()).padStart(3, "0");
57
- const last = args[args.length - 1];
58
- const hasPayload = args.length >= 2 && last !== null && typeof last === "object" && !Array.isArray(last) && !(last instanceof Error);
59
- const msg = formatMessage(hasPayload ? args.slice(0, -1) : args);
60
- const suffix = hasPayload ? " " + JSON.stringify(last, null, 2).replace(/\n\s*/g, " ") : "";
61
- return `${emoji} ${ts} ${msg}${suffix}`;
50
+ const scopePart = scope ? `(${scope}) ` : "";
51
+ const suffix = payload ? " " + JSON.stringify(payload, null, 2).replace(/\n\s*/g, " ") : "";
52
+ return `${emoji} ${ts} ${scopePart}${message}${suffix}`;
62
53
  }
63
- function consolePlain(args) {
64
- const last = args[args.length - 1];
65
- const hasPayload = args.length >= 2 && last !== null && typeof last === "object" && !Array.isArray(last) && !(last instanceof Error);
66
- const msg = formatMessage(hasPayload ? args.slice(0, -1) : args);
67
- const suffix = hasPayload ? " " + JSON.stringify(last, null, 2).replace(/\n\s*/g, " ") : "";
68
- return `${msg}${suffix}`;
54
+ function consolePlain(message, payload, scope) {
55
+ const scopePart = scope ? `(${scope}) ` : "";
56
+ const suffix = payload ? " " + JSON.stringify(payload, null, 2).replace(/\n\s*/g, " ") : "";
57
+ return `${scopePart}${message}${suffix}`;
69
58
  }
70
- function gcpPayload(args) {
71
- const last = args[args.length - 1];
72
- if (args.length >= 2 && last !== null && typeof last === "object" && !Array.isArray(last) && !(last instanceof Error)) {
73
- return { message: formatMessage(args.slice(0, -1)), ...last };
59
+ function logger(scope) {
60
+ const instanceLabels = {
61
+ ...envLabels,
62
+ ...scope ? { scope } : {}
63
+ };
64
+ function resolveLabels(callLabels) {
65
+ const merged = { ...instanceLabels, ...callLabels };
66
+ return Object.keys(merged).length ? merged : void 0;
74
67
  }
75
- return formatMessage(args);
76
- }
77
- var gcpLog = null;
78
- if (USE_GCP) {
79
- try {
80
- const logName = process.env.LOGGER_NAME ?? process.env.K_SERVICE ?? "local";
81
- gcpLog = new import_logging.Logging({ projectId: process.env.GCP_PROJECT }).log(logName);
82
- } catch {
68
+ function gcpMeta(severity, callLabels) {
69
+ const labels = resolveLabels(callLabels);
70
+ return labels ? { severity, labels } : { severity };
83
71
  }
84
- }
85
- var logger = gcpLog ? /* @__PURE__ */ (() => {
86
- const g = gcpLog;
87
- return {
88
- debug: (...args) => {
89
- g.write(g.entry({ severity: "DEBUG", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);
72
+ function gcpData(message, payload) {
73
+ return payload ? { message, ...payload } : message;
74
+ }
75
+ const backends = [];
76
+ if (gcpLog) {
77
+ const g = gcpLog;
78
+ backends.push({
79
+ debug: (message, payload, labels) => {
80
+ g.write(g.entry(gcpMeta("DEBUG", labels), gcpData(message, payload))).catch(noop);
81
+ },
82
+ info: (message, payload, labels) => {
83
+ g.write(g.entry(gcpMeta("INFO", labels), gcpData(message, payload))).catch(noop);
84
+ },
85
+ notice: (message, payload, labels) => {
86
+ g.write(g.entry(gcpMeta("NOTICE", labels), gcpData(message, payload))).catch(noop);
87
+ },
88
+ warning: (message, payload, labels) => {
89
+ g.write(g.entry(gcpMeta("WARNING", labels), gcpData(message, payload))).catch(noop);
90
+ },
91
+ error: (message, payload, labels) => {
92
+ g.write(g.entry(gcpMeta("ERROR", labels), gcpData(message, payload))).catch(noop);
93
+ },
94
+ critical: (message, payload, labels) => {
95
+ g.write(g.entry(gcpMeta("CRITICAL", labels), gcpData(message, payload))).catch(noop);
96
+ },
97
+ alert: (message, payload, labels) => {
98
+ g.write(g.entry(gcpMeta("ALERT", labels), gcpData(message, payload))).catch(noop);
99
+ },
100
+ emergency: (message, payload, labels) => {
101
+ g.write(g.entry(gcpMeta("EMERGENCY", labels), gcpData(message, payload))).catch(noop);
102
+ }
103
+ });
104
+ }
105
+ if (USE_CONSOLE || backends.length === 0) {
106
+ backends.push(CONSOLE_PRETTY ? {
107
+ debug: (message, payload) => {
108
+ console.log(consoleLine("\u{1F41E}", message, payload, scope));
109
+ },
110
+ info: (message, payload) => {
111
+ console.log(consoleLine("\u26AA\uFE0F", message, payload, scope));
112
+ },
113
+ notice: (message, payload) => {
114
+ console.log(consoleLine("\u{1F535}", message, payload, scope));
115
+ },
116
+ warning: (message, payload) => {
117
+ console.log(consoleLine("\u{1F7E1}", message, payload, scope));
118
+ },
119
+ error: (message, payload) => {
120
+ console.log(consoleLine("\u{1F534}", message, payload, scope));
121
+ },
122
+ critical: (message, payload) => {
123
+ console.log(consoleLine("\u26D4\uFE0F", message, payload, scope));
124
+ },
125
+ alert: (message, payload) => {
126
+ console.log(consoleLine("\u2757\uFE0F", message, payload, scope));
127
+ },
128
+ emergency: (message, payload) => {
129
+ console.log(consoleLine("\u{1F6A8}", message, payload, scope));
130
+ }
131
+ } : {
132
+ debug: (message, payload) => {
133
+ console.log(consolePlain(message, payload, scope));
134
+ },
135
+ info: (message, payload) => {
136
+ console.log(consolePlain(message, payload, scope));
137
+ },
138
+ notice: (message, payload) => {
139
+ console.log(consolePlain(message, payload, scope));
140
+ },
141
+ warning: (message, payload) => {
142
+ console.log(consolePlain(message, payload, scope));
143
+ },
144
+ error: (message, payload) => {
145
+ console.log(consolePlain(message, payload, scope));
146
+ },
147
+ critical: (message, payload) => {
148
+ console.log(consolePlain(message, payload, scope));
149
+ },
150
+ alert: (message, payload) => {
151
+ console.log(consolePlain(message, payload, scope));
152
+ },
153
+ emergency: (message, payload) => {
154
+ console.log(consolePlain(message, payload, scope));
155
+ }
156
+ });
157
+ }
158
+ return backends.length === 1 ? backends[0] : {
159
+ debug: (message, payload, labels) => {
160
+ backends.forEach((b) => b.debug(message, payload, labels));
90
161
  },
91
- info: (...args) => {
92
- g.write(g.entry({ severity: "INFO", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);
162
+ info: (message, payload, labels) => {
163
+ backends.forEach((b) => b.info(message, payload, labels));
93
164
  },
94
- notice: (...args) => {
95
- g.write(g.entry({ severity: "NOTICE", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);
165
+ notice: (message, payload, labels) => {
166
+ backends.forEach((b) => b.notice(message, payload, labels));
96
167
  },
97
- warning: (...args) => {
98
- g.write(g.entry({ severity: "WARNING", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);
168
+ warning: (message, payload, labels) => {
169
+ backends.forEach((b) => b.warning(message, payload, labels));
99
170
  },
100
- error: (...args) => {
101
- g.write(g.entry({ severity: "ERROR", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);
171
+ error: (message, payload, labels) => {
172
+ backends.forEach((b) => b.error(message, payload, labels));
102
173
  },
103
- critical: (...args) => {
104
- g.write(g.entry({ severity: "CRITICAL", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);
174
+ critical: (message, payload, labels) => {
175
+ backends.forEach((b) => b.critical(message, payload, labels));
105
176
  },
106
- alert: (...args) => {
107
- g.write(g.entry({ severity: "ALERT", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);
177
+ alert: (message, payload, labels) => {
178
+ backends.forEach((b) => b.alert(message, payload, labels));
108
179
  },
109
- emergency: (...args) => {
110
- g.write(g.entry({ severity: "EMERGENCY", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);
180
+ emergency: (message, payload, labels) => {
181
+ backends.forEach((b) => b.emergency(message, payload, labels));
111
182
  }
112
183
  };
113
- })() : CONSOLE_PRETTY ? {
114
- debug: (...args) => {
115
- console.log(consoleLine("\u{1F41E}", args));
116
- },
117
- info: (...args) => {
118
- console.log(consoleLine("\u26AA\uFE0F", args));
119
- },
120
- notice: (...args) => {
121
- console.log(consoleLine("\u{1F535}", args));
122
- },
123
- warning: (...args) => {
124
- console.log(consoleLine("\u{1F7E1}", args));
125
- },
126
- error: (...args) => {
127
- console.log(consoleLine("\u{1F534}", args));
128
- },
129
- critical: (...args) => {
130
- console.log(consoleLine("\u26D4\uFE0F", args));
131
- },
132
- alert: (...args) => {
133
- console.log(consoleLine("\u2757\uFE0F", args));
134
- },
135
- emergency: (...args) => {
136
- console.log(consoleLine("\u{1F6A8}", args));
137
- }
138
- } : {
139
- debug: (...args) => {
140
- console.log(consolePlain(args));
141
- },
142
- info: (...args) => {
143
- console.log(consolePlain(args));
144
- },
145
- notice: (...args) => {
146
- console.log(consolePlain(args));
147
- },
148
- warning: (...args) => {
149
- console.log(consolePlain(args));
150
- },
151
- error: (...args) => {
152
- console.log(consolePlain(args));
153
- },
154
- critical: (...args) => {
155
- console.log(consolePlain(args));
156
- },
157
- alert: (...args) => {
158
- console.log(consolePlain(args));
159
- },
160
- emergency: (...args) => {
161
- console.log(consolePlain(args));
162
- }
163
- };
184
+ }
164
185
  var index_default = logger;
165
186
  // Annotate the CommonJS export names for ESM import in node:
166
187
  0 && (module.exports = {
167
- formatMessage,
168
188
  logger
169
189
  });
170
190
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { Logging } from \"@google-cloud/logging\";\n\nexport interface Logger {\n debug: (...args: unknown[]) => void;\n info: (...args: unknown[]) => void;\n notice: (...args: unknown[]) => void;\n warning: (...args: unknown[]) => void;\n error: (...args: unknown[]) => void;\n critical: (...args: unknown[]) => void;\n alert: (...args: unknown[]) => void;\n emergency: (...args: unknown[]) => void;\n}\n\nexport function formatMessage(args: unknown[]): string {\n return args.map(arg => {\n if (typeof arg === \"string\") return arg;\n if (arg instanceof Error) return arg.message + (arg.stack ? `\\n${arg.stack}` : \"\");\n try {\n return JSON.stringify(arg);\n } catch {\n return String(arg);\n }\n }).join(\" \");\n}\n\n// Resolved once at module load — no per-call branching.\nconst LOGGER_TARGET = process.env.LOGGER_TARGET?.toLowerCase();\nconst LOGGER_FORMAT = process.env.LOGGER_FORMAT?.toLowerCase();\nconst FORCE_GCP = LOGGER_TARGET === \"gcp\";\nconst FORCE_CONSOLE = LOGGER_TARGET === \"console\";\nconst USE_GCP = !FORCE_CONSOLE && (FORCE_GCP || !!process.env.GCP_PROJECT);\nconst CONSOLE_PRETTY = LOGGER_FORMAT === \"pretty\";\nconst noop = (): void => {};\nconst gcpLabels: Record<string, string> = {};\nif (process.env.ENVIRONMENT) gcpLabels.environment = process.env.ENVIRONMENT;\nif (process.env.SERVICE_ID) gcpLabels.service_id = process.env.SERVICE_ID;\nif (process.env.VERSION) gcpLabels.version = process.env.VERSION;\nconst GCP_ENV_LABEL = Object.keys(gcpLabels).length ? { labels: gcpLabels } : {};\n\n// Formats a single console log line: \"{emoji} {local timestamp} {message} [{payload}]\"\nfunction consoleLine(emoji: string, args: unknown[]): string {\n const d = new Date();\n const ts = d.toLocaleString(\"sv-SE\") + \".\" + String(d.getMilliseconds()).padStart(3, \"0\");\n const last = args[args.length - 1];\n const hasPayload = args.length >= 2 && last !== null && typeof last === \"object\" && !Array.isArray(last) && !(last instanceof Error);\n const msg = formatMessage(hasPayload ? args.slice(0, -1) : args);\n const suffix = hasPayload ? \" \" + JSON.stringify(last, null, 2).replace(/\\n\\s*/g, \" \") : \"\";\n return `${emoji} ${ts} ${msg}${suffix}`;\n}\n\n// Plain console line: \"message [{payload}]\"\nfunction consolePlain(args: unknown[]): string {\n const last = args[args.length - 1];\n const hasPayload =\n args.length >= 2 &&\n last !== null &&\n typeof last === \"object\" &&\n !Array.isArray(last) &&\n !(last instanceof Error);\n const msg = formatMessage(hasPayload ? args.slice(0, -1) : args);\n const suffix = hasPayload ? \" \" + JSON.stringify(last, null, 2).replace(/\\n\\s*/g, \" \") : \"\";\n return `${msg}${suffix}`;\n}\n\n// If the last arg is a plain object, return a jsonPayload so Cloud Logging\n// indexes its fields. Otherwise return a plain string (textPayload).\nfunction gcpPayload(args: unknown[]): string | Record<string, unknown> {\n const last = args[args.length - 1];\n if (\n args.length >= 2 &&\n last !== null &&\n typeof last === \"object\" &&\n !Array.isArray(last) &&\n !(last instanceof Error)\n ) {\n return { message: formatMessage(args.slice(0, -1)), ...(last as Record<string, unknown>) };\n }\n return formatMessage(args);\n}\n\nlet gcpLog: ReturnType<Logging[\"log\"]> | null = null;\nif (USE_GCP) {\n try {\n const logName = process.env.LOGGER_NAME ?? process.env.K_SERVICE ?? \"local\";\n gcpLog = new Logging({ projectId: process.env.GCP_PROJECT }).log(logName);\n } catch {\n // GCP init failed; fall back to console\n }\n}\n\nexport const logger: Logger = gcpLog\n ? (() => {\n const g = gcpLog!;\n return {\n debug: (...args: unknown[]): void => {\n g.write(g.entry({ severity: \"DEBUG\", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);\n },\n info: (...args: unknown[]): void => {\n g.write(g.entry({ severity: \"INFO\", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);\n },\n notice: (...args: unknown[]): void => {\n g.write(g.entry({ severity: \"NOTICE\", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);\n },\n warning: (...args: unknown[]): void => {\n g.write(g.entry({ severity: \"WARNING\", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);\n },\n error: (...args: unknown[]): void => {\n g.write(g.entry({ severity: \"ERROR\", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);\n },\n critical: (...args: unknown[]): void => {\n g.write(g.entry({ severity: \"CRITICAL\", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);\n },\n alert: (...args: unknown[]): void => {\n g.write(g.entry({ severity: \"ALERT\", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);\n },\n emergency: (...args: unknown[]): void => {\n g.write(g.entry({ severity: \"EMERGENCY\", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);\n },\n };\n })()\n : CONSOLE_PRETTY\n ? {\n debug: (...args: unknown[]): void => { console.log(consoleLine(\"🐞\", args)); },\n info: (...args: unknown[]): void => { console.log(consoleLine(\"⚪️\", args)); },\n notice: (...args: unknown[]): void => { console.log(consoleLine(\"🔵\", args)); },\n warning: (...args: unknown[]): void => { console.log(consoleLine(\"🟡\", args)); },\n error: (...args: unknown[]): void => { console.log(consoleLine(\"🔴\", args)); },\n critical: (...args: unknown[]): void => { console.log(consoleLine(\"⛔️\", args)); },\n alert: (...args: unknown[]): void => { console.log(consoleLine(\"❗️\", args)); },\n emergency: (...args: unknown[]): void => { console.log(consoleLine(\"🚨\", args)); },\n }\n : {\n debug: (...args: unknown[]): void => { console.log(consolePlain(args)); },\n info: (...args: unknown[]): void => { console.log(consolePlain(args)); },\n notice: (...args: unknown[]): void => { console.log(consolePlain(args)); },\n warning: (...args: unknown[]): void => { console.log(consolePlain(args)); },\n error: (...args: unknown[]): void => { console.log(consolePlain(args)); },\n critical: (...args: unknown[]): void => { console.log(consolePlain(args)); },\n alert: (...args: unknown[]): void => { console.log(consolePlain(args)); },\n emergency: (...args: unknown[]): void => { console.log(consolePlain(args)); },\n };\n\nexport default logger;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { Logging } from \"@google-cloud/logging\";\n\ntype LogMethod = (message: string, payload?: Record<string, unknown>, labels?: Record<string, string>) => void;\n\nexport interface Logger {\n debug: LogMethod;\n info: LogMethod;\n notice: LogMethod;\n warning: LogMethod;\n error: LogMethod;\n critical: LogMethod;\n alert: LogMethod;\n emergency: LogMethod;\n}\n\n// Resolved once at module load — no per-call branching.\n// LOGGER_TARGET accepts a comma-separated list of backends: \"gcp\", \"console\", or \"gcp,console\".\nconst rawTargets = process.env.LOGGER_TARGET;\nconst targets = rawTargets\n ? new Set(rawTargets.toLowerCase().split(\",\").map(s => s.trim()).filter(Boolean))\n : null;\n\nconst USE_GCP = targets ? targets.has(\"gcp\") : !!process.env.GCP_PROJECT;\nconst USE_CONSOLE = targets ? targets.has(\"console\") : !process.env.GCP_PROJECT;\nconst CONSOLE_PRETTY = process.env.LOGGER_CONSOLE_FORMAT?.toLowerCase() === \"pretty\";\nconst noop = (): void => {};\n\nconst envLabels: Record<string, string> = {};\nif (process.env.ENVIRONMENT) envLabels.environment = process.env.ENVIRONMENT;\nif (process.env.SERVICE_ID) envLabels.service_id = process.env.SERVICE_ID;\nif (process.env.VERSION) envLabels.version = process.env.VERSION;\n\n// GCP Log singleton — shared across all logger() calls.\nconst gcpLog = USE_GCP ? (() => {\n try {\n const logName = process.env.LOGGER_NAME ?? process.env.K_SERVICE ?? \"local\";\n return new Logging({ projectId: process.env.GCP_PROJECT }).log(logName);\n } catch {\n return null;\n }\n})() : null;\n\n// Formats a pretty console log line: \"{emoji} {local timestamp} [(scope) ]{message}[ {payload}]\"\nfunction consoleLine(emoji: string, message: string, payload?: Record<string, unknown>, scope?: string): string {\n const d = new Date();\n const ts = d.toLocaleString(\"sv-SE\") + \".\" + String(d.getMilliseconds()).padStart(3, \"0\");\n const scopePart = scope ? `(${scope}) ` : \"\";\n const suffix = payload ? \" \" + JSON.stringify(payload, null, 2).replace(/\\n\\s*/g, \" \") : \"\";\n return `${emoji} ${ts} ${scopePart}${message}${suffix}`;\n}\n\n// Plain console line: \"[(scope) ]{message}[ {payload}]\"\nfunction consolePlain(message: string, payload?: Record<string, unknown>, scope?: string): string {\n const scopePart = scope ? `(${scope}) ` : \"\";\n const suffix = payload ? \" \" + JSON.stringify(payload, null, 2).replace(/\\n\\s*/g, \" \") : \"\";\n return `${scopePart}${message}${suffix}`;\n}\n\nexport function logger(scope?: string): Logger {\n const instanceLabels: Record<string, string> = {\n ...envLabels,\n ...(scope ? { scope } : {}),\n };\n\n function resolveLabels(callLabels?: Record<string, string>): Record<string, string> | undefined {\n const merged = { ...instanceLabels, ...callLabels };\n return Object.keys(merged).length ? merged : undefined;\n }\n\n function gcpMeta(severity: string, callLabels?: Record<string, string>): Record<string, unknown> {\n const labels = resolveLabels(callLabels);\n return labels ? { severity, labels } : { severity };\n }\n\n function gcpData(message: string, payload?: Record<string, unknown>): string | Record<string, unknown> {\n return payload ? { message, ...payload } : message;\n }\n\n const backends: Logger[] = [];\n\n if (gcpLog) {\n const g = gcpLog;\n backends.push({\n debug: (message, payload, labels): void => { g.write(g.entry(gcpMeta(\"DEBUG\", labels), gcpData(message, payload))).catch(noop); },\n info: (message, payload, labels): void => { g.write(g.entry(gcpMeta(\"INFO\", labels), gcpData(message, payload))).catch(noop); },\n notice: (message, payload, labels): void => { g.write(g.entry(gcpMeta(\"NOTICE\", labels), gcpData(message, payload))).catch(noop); },\n warning: (message, payload, labels): void => { g.write(g.entry(gcpMeta(\"WARNING\", labels), gcpData(message, payload))).catch(noop); },\n error: (message, payload, labels): void => { g.write(g.entry(gcpMeta(\"ERROR\", labels), gcpData(message, payload))).catch(noop); },\n critical: (message, payload, labels): void => { g.write(g.entry(gcpMeta(\"CRITICAL\", labels), gcpData(message, payload))).catch(noop); },\n alert: (message, payload, labels): void => { g.write(g.entry(gcpMeta(\"ALERT\", labels), gcpData(message, payload))).catch(noop); },\n emergency: (message, payload, labels): void => { g.write(g.entry(gcpMeta(\"EMERGENCY\", labels), gcpData(message, payload))).catch(noop); },\n });\n }\n\n if (USE_CONSOLE || backends.length === 0) {\n backends.push(CONSOLE_PRETTY\n ? {\n debug: (message, payload): void => { console.log(consoleLine(\"🐞\", message, payload, scope)); },\n info: (message, payload): void => { console.log(consoleLine(\"⚪️\", message, payload, scope)); },\n notice: (message, payload): void => { console.log(consoleLine(\"🔵\", message, payload, scope)); },\n warning: (message, payload): void => { console.log(consoleLine(\"🟡\", message, payload, scope)); },\n error: (message, payload): void => { console.log(consoleLine(\"🔴\", message, payload, scope)); },\n critical: (message, payload): void => { console.log(consoleLine(\"⛔️\", message, payload, scope)); },\n alert: (message, payload): void => { console.log(consoleLine(\"❗️\", message, payload, scope)); },\n emergency: (message, payload): void => { console.log(consoleLine(\"🚨\", message, payload, scope)); },\n }\n : {\n debug: (message, payload): void => { console.log(consolePlain(message, payload, scope)); },\n info: (message, payload): void => { console.log(consolePlain(message, payload, scope)); },\n notice: (message, payload): void => { console.log(consolePlain(message, payload, scope)); },\n warning: (message, payload): void => { console.log(consolePlain(message, payload, scope)); },\n error: (message, payload): void => { console.log(consolePlain(message, payload, scope)); },\n critical: (message, payload): void => { console.log(consolePlain(message, payload, scope)); },\n alert: (message, payload): void => { console.log(consolePlain(message, payload, scope)); },\n emergency: (message, payload): void => { console.log(consolePlain(message, payload, scope)); },\n });\n }\n\n return backends.length === 1\n ? backends[0]\n : {\n debug: (message, payload, labels): void => { backends.forEach(b => b.debug(message, payload, labels)); },\n info: (message, payload, labels): void => { backends.forEach(b => b.info(message, payload, labels)); },\n notice: (message, payload, labels): void => { backends.forEach(b => b.notice(message, payload, labels)); },\n warning: (message, payload, labels): void => { backends.forEach(b => b.warning(message, payload, labels)); },\n error: (message, payload, labels): void => { backends.forEach(b => b.error(message, payload, labels)); },\n critical: (message, payload, labels): void => { backends.forEach(b => b.critical(message, payload, labels)); },\n alert: (message, payload, labels): void => { backends.forEach(b => b.alert(message, payload, labels)); },\n emergency: (message, payload, labels): void => { backends.forEach(b => b.emergency(message, payload, labels)); },\n };\n}\n\nexport default logger;\n"],"mappings":"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","names":[]}
package/dist/index.d.cts CHANGED
@@ -1,14 +1,14 @@
1
+ type LogMethod = (message: string, payload?: Record<string, unknown>, labels?: Record<string, string>) => void;
1
2
  interface Logger {
2
- debug: (...args: unknown[]) => void;
3
- info: (...args: unknown[]) => void;
4
- notice: (...args: unknown[]) => void;
5
- warning: (...args: unknown[]) => void;
6
- error: (...args: unknown[]) => void;
7
- critical: (...args: unknown[]) => void;
8
- alert: (...args: unknown[]) => void;
9
- emergency: (...args: unknown[]) => void;
3
+ debug: LogMethod;
4
+ info: LogMethod;
5
+ notice: LogMethod;
6
+ warning: LogMethod;
7
+ error: LogMethod;
8
+ critical: LogMethod;
9
+ alert: LogMethod;
10
+ emergency: LogMethod;
10
11
  }
11
- declare function formatMessage(args: unknown[]): string;
12
- declare const logger: Logger;
12
+ declare function logger(scope?: string): Logger;
13
13
 
14
- export { type Logger, logger as default, formatMessage, logger };
14
+ export { type Logger, logger as default, logger };
package/dist/index.d.ts CHANGED
@@ -1,14 +1,14 @@
1
+ type LogMethod = (message: string, payload?: Record<string, unknown>, labels?: Record<string, string>) => void;
1
2
  interface Logger {
2
- debug: (...args: unknown[]) => void;
3
- info: (...args: unknown[]) => void;
4
- notice: (...args: unknown[]) => void;
5
- warning: (...args: unknown[]) => void;
6
- error: (...args: unknown[]) => void;
7
- critical: (...args: unknown[]) => void;
8
- alert: (...args: unknown[]) => void;
9
- emergency: (...args: unknown[]) => void;
3
+ debug: LogMethod;
4
+ info: LogMethod;
5
+ notice: LogMethod;
6
+ warning: LogMethod;
7
+ error: LogMethod;
8
+ critical: LogMethod;
9
+ alert: LogMethod;
10
+ emergency: LogMethod;
10
11
  }
11
- declare function formatMessage(args: unknown[]): string;
12
- declare const logger: Logger;
12
+ declare function logger(scope?: string): Logger;
13
13
 
14
- export { type Logger, logger as default, formatMessage, logger };
14
+ export { type Logger, logger as default, logger };
package/dist/index.js CHANGED
@@ -1,144 +1,165 @@
1
1
  // src/index.ts
2
2
  import { Logging } from "@google-cloud/logging";
3
- function formatMessage(args) {
4
- return args.map((arg) => {
5
- if (typeof arg === "string") return arg;
6
- if (arg instanceof Error) return arg.message + (arg.stack ? `
7
- ${arg.stack}` : "");
8
- try {
9
- return JSON.stringify(arg);
10
- } catch {
11
- return String(arg);
12
- }
13
- }).join(" ");
14
- }
15
- var LOGGER_TARGET = process.env.LOGGER_TARGET?.toLowerCase();
16
- var LOGGER_FORMAT = process.env.LOGGER_FORMAT?.toLowerCase();
17
- var FORCE_GCP = LOGGER_TARGET === "gcp";
18
- var FORCE_CONSOLE = LOGGER_TARGET === "console";
19
- var USE_GCP = !FORCE_CONSOLE && (FORCE_GCP || !!process.env.GCP_PROJECT);
20
- var CONSOLE_PRETTY = LOGGER_FORMAT === "pretty";
3
+ var rawTargets = process.env.LOGGER_TARGET;
4
+ var targets = rawTargets ? new Set(rawTargets.toLowerCase().split(",").map((s) => s.trim()).filter(Boolean)) : null;
5
+ var USE_GCP = targets ? targets.has("gcp") : !!process.env.GCP_PROJECT;
6
+ var USE_CONSOLE = targets ? targets.has("console") : !process.env.GCP_PROJECT;
7
+ var CONSOLE_PRETTY = process.env.LOGGER_CONSOLE_FORMAT?.toLowerCase() === "pretty";
21
8
  var noop = () => {
22
9
  };
23
- var gcpLabels = {};
24
- if (process.env.ENVIRONMENT) gcpLabels.environment = process.env.ENVIRONMENT;
25
- if (process.env.SERVICE_ID) gcpLabels.service_id = process.env.SERVICE_ID;
26
- if (process.env.VERSION) gcpLabels.version = process.env.VERSION;
27
- var GCP_ENV_LABEL = Object.keys(gcpLabels).length ? { labels: gcpLabels } : {};
28
- function consoleLine(emoji, args) {
10
+ var envLabels = {};
11
+ if (process.env.ENVIRONMENT) envLabels.environment = process.env.ENVIRONMENT;
12
+ if (process.env.SERVICE_ID) envLabels.service_id = process.env.SERVICE_ID;
13
+ if (process.env.VERSION) envLabels.version = process.env.VERSION;
14
+ var gcpLog = USE_GCP ? (() => {
15
+ try {
16
+ const logName = process.env.LOGGER_NAME ?? process.env.K_SERVICE ?? "local";
17
+ return new Logging({ projectId: process.env.GCP_PROJECT }).log(logName);
18
+ } catch {
19
+ return null;
20
+ }
21
+ })() : null;
22
+ function consoleLine(emoji, message, payload, scope) {
29
23
  const d = /* @__PURE__ */ new Date();
30
24
  const ts = d.toLocaleString("sv-SE") + "." + String(d.getMilliseconds()).padStart(3, "0");
31
- const last = args[args.length - 1];
32
- const hasPayload = args.length >= 2 && last !== null && typeof last === "object" && !Array.isArray(last) && !(last instanceof Error);
33
- const msg = formatMessage(hasPayload ? args.slice(0, -1) : args);
34
- const suffix = hasPayload ? " " + JSON.stringify(last, null, 2).replace(/\n\s*/g, " ") : "";
35
- return `${emoji} ${ts} ${msg}${suffix}`;
25
+ const scopePart = scope ? `(${scope}) ` : "";
26
+ const suffix = payload ? " " + JSON.stringify(payload, null, 2).replace(/\n\s*/g, " ") : "";
27
+ return `${emoji} ${ts} ${scopePart}${message}${suffix}`;
36
28
  }
37
- function consolePlain(args) {
38
- const last = args[args.length - 1];
39
- const hasPayload = args.length >= 2 && last !== null && typeof last === "object" && !Array.isArray(last) && !(last instanceof Error);
40
- const msg = formatMessage(hasPayload ? args.slice(0, -1) : args);
41
- const suffix = hasPayload ? " " + JSON.stringify(last, null, 2).replace(/\n\s*/g, " ") : "";
42
- return `${msg}${suffix}`;
29
+ function consolePlain(message, payload, scope) {
30
+ const scopePart = scope ? `(${scope}) ` : "";
31
+ const suffix = payload ? " " + JSON.stringify(payload, null, 2).replace(/\n\s*/g, " ") : "";
32
+ return `${scopePart}${message}${suffix}`;
43
33
  }
44
- function gcpPayload(args) {
45
- const last = args[args.length - 1];
46
- if (args.length >= 2 && last !== null && typeof last === "object" && !Array.isArray(last) && !(last instanceof Error)) {
47
- return { message: formatMessage(args.slice(0, -1)), ...last };
34
+ function logger(scope) {
35
+ const instanceLabels = {
36
+ ...envLabels,
37
+ ...scope ? { scope } : {}
38
+ };
39
+ function resolveLabels(callLabels) {
40
+ const merged = { ...instanceLabels, ...callLabels };
41
+ return Object.keys(merged).length ? merged : void 0;
48
42
  }
49
- return formatMessage(args);
50
- }
51
- var gcpLog = null;
52
- if (USE_GCP) {
53
- try {
54
- const logName = process.env.LOGGER_NAME ?? process.env.K_SERVICE ?? "local";
55
- gcpLog = new Logging({ projectId: process.env.GCP_PROJECT }).log(logName);
56
- } catch {
43
+ function gcpMeta(severity, callLabels) {
44
+ const labels = resolveLabels(callLabels);
45
+ return labels ? { severity, labels } : { severity };
57
46
  }
58
- }
59
- var logger = gcpLog ? /* @__PURE__ */ (() => {
60
- const g = gcpLog;
61
- return {
62
- debug: (...args) => {
63
- g.write(g.entry({ severity: "DEBUG", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);
47
+ function gcpData(message, payload) {
48
+ return payload ? { message, ...payload } : message;
49
+ }
50
+ const backends = [];
51
+ if (gcpLog) {
52
+ const g = gcpLog;
53
+ backends.push({
54
+ debug: (message, payload, labels) => {
55
+ g.write(g.entry(gcpMeta("DEBUG", labels), gcpData(message, payload))).catch(noop);
56
+ },
57
+ info: (message, payload, labels) => {
58
+ g.write(g.entry(gcpMeta("INFO", labels), gcpData(message, payload))).catch(noop);
59
+ },
60
+ notice: (message, payload, labels) => {
61
+ g.write(g.entry(gcpMeta("NOTICE", labels), gcpData(message, payload))).catch(noop);
62
+ },
63
+ warning: (message, payload, labels) => {
64
+ g.write(g.entry(gcpMeta("WARNING", labels), gcpData(message, payload))).catch(noop);
65
+ },
66
+ error: (message, payload, labels) => {
67
+ g.write(g.entry(gcpMeta("ERROR", labels), gcpData(message, payload))).catch(noop);
68
+ },
69
+ critical: (message, payload, labels) => {
70
+ g.write(g.entry(gcpMeta("CRITICAL", labels), gcpData(message, payload))).catch(noop);
71
+ },
72
+ alert: (message, payload, labels) => {
73
+ g.write(g.entry(gcpMeta("ALERT", labels), gcpData(message, payload))).catch(noop);
74
+ },
75
+ emergency: (message, payload, labels) => {
76
+ g.write(g.entry(gcpMeta("EMERGENCY", labels), gcpData(message, payload))).catch(noop);
77
+ }
78
+ });
79
+ }
80
+ if (USE_CONSOLE || backends.length === 0) {
81
+ backends.push(CONSOLE_PRETTY ? {
82
+ debug: (message, payload) => {
83
+ console.log(consoleLine("\u{1F41E}", message, payload, scope));
84
+ },
85
+ info: (message, payload) => {
86
+ console.log(consoleLine("\u26AA\uFE0F", message, payload, scope));
87
+ },
88
+ notice: (message, payload) => {
89
+ console.log(consoleLine("\u{1F535}", message, payload, scope));
90
+ },
91
+ warning: (message, payload) => {
92
+ console.log(consoleLine("\u{1F7E1}", message, payload, scope));
93
+ },
94
+ error: (message, payload) => {
95
+ console.log(consoleLine("\u{1F534}", message, payload, scope));
96
+ },
97
+ critical: (message, payload) => {
98
+ console.log(consoleLine("\u26D4\uFE0F", message, payload, scope));
99
+ },
100
+ alert: (message, payload) => {
101
+ console.log(consoleLine("\u2757\uFE0F", message, payload, scope));
102
+ },
103
+ emergency: (message, payload) => {
104
+ console.log(consoleLine("\u{1F6A8}", message, payload, scope));
105
+ }
106
+ } : {
107
+ debug: (message, payload) => {
108
+ console.log(consolePlain(message, payload, scope));
109
+ },
110
+ info: (message, payload) => {
111
+ console.log(consolePlain(message, payload, scope));
112
+ },
113
+ notice: (message, payload) => {
114
+ console.log(consolePlain(message, payload, scope));
115
+ },
116
+ warning: (message, payload) => {
117
+ console.log(consolePlain(message, payload, scope));
118
+ },
119
+ error: (message, payload) => {
120
+ console.log(consolePlain(message, payload, scope));
121
+ },
122
+ critical: (message, payload) => {
123
+ console.log(consolePlain(message, payload, scope));
124
+ },
125
+ alert: (message, payload) => {
126
+ console.log(consolePlain(message, payload, scope));
127
+ },
128
+ emergency: (message, payload) => {
129
+ console.log(consolePlain(message, payload, scope));
130
+ }
131
+ });
132
+ }
133
+ return backends.length === 1 ? backends[0] : {
134
+ debug: (message, payload, labels) => {
135
+ backends.forEach((b) => b.debug(message, payload, labels));
64
136
  },
65
- info: (...args) => {
66
- g.write(g.entry({ severity: "INFO", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);
137
+ info: (message, payload, labels) => {
138
+ backends.forEach((b) => b.info(message, payload, labels));
67
139
  },
68
- notice: (...args) => {
69
- g.write(g.entry({ severity: "NOTICE", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);
140
+ notice: (message, payload, labels) => {
141
+ backends.forEach((b) => b.notice(message, payload, labels));
70
142
  },
71
- warning: (...args) => {
72
- g.write(g.entry({ severity: "WARNING", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);
143
+ warning: (message, payload, labels) => {
144
+ backends.forEach((b) => b.warning(message, payload, labels));
73
145
  },
74
- error: (...args) => {
75
- g.write(g.entry({ severity: "ERROR", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);
146
+ error: (message, payload, labels) => {
147
+ backends.forEach((b) => b.error(message, payload, labels));
76
148
  },
77
- critical: (...args) => {
78
- g.write(g.entry({ severity: "CRITICAL", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);
149
+ critical: (message, payload, labels) => {
150
+ backends.forEach((b) => b.critical(message, payload, labels));
79
151
  },
80
- alert: (...args) => {
81
- g.write(g.entry({ severity: "ALERT", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);
152
+ alert: (message, payload, labels) => {
153
+ backends.forEach((b) => b.alert(message, payload, labels));
82
154
  },
83
- emergency: (...args) => {
84
- g.write(g.entry({ severity: "EMERGENCY", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);
155
+ emergency: (message, payload, labels) => {
156
+ backends.forEach((b) => b.emergency(message, payload, labels));
85
157
  }
86
158
  };
87
- })() : CONSOLE_PRETTY ? {
88
- debug: (...args) => {
89
- console.log(consoleLine("\u{1F41E}", args));
90
- },
91
- info: (...args) => {
92
- console.log(consoleLine("\u26AA\uFE0F", args));
93
- },
94
- notice: (...args) => {
95
- console.log(consoleLine("\u{1F535}", args));
96
- },
97
- warning: (...args) => {
98
- console.log(consoleLine("\u{1F7E1}", args));
99
- },
100
- error: (...args) => {
101
- console.log(consoleLine("\u{1F534}", args));
102
- },
103
- critical: (...args) => {
104
- console.log(consoleLine("\u26D4\uFE0F", args));
105
- },
106
- alert: (...args) => {
107
- console.log(consoleLine("\u2757\uFE0F", args));
108
- },
109
- emergency: (...args) => {
110
- console.log(consoleLine("\u{1F6A8}", args));
111
- }
112
- } : {
113
- debug: (...args) => {
114
- console.log(consolePlain(args));
115
- },
116
- info: (...args) => {
117
- console.log(consolePlain(args));
118
- },
119
- notice: (...args) => {
120
- console.log(consolePlain(args));
121
- },
122
- warning: (...args) => {
123
- console.log(consolePlain(args));
124
- },
125
- error: (...args) => {
126
- console.log(consolePlain(args));
127
- },
128
- critical: (...args) => {
129
- console.log(consolePlain(args));
130
- },
131
- alert: (...args) => {
132
- console.log(consolePlain(args));
133
- },
134
- emergency: (...args) => {
135
- console.log(consolePlain(args));
136
- }
137
- };
159
+ }
138
160
  var index_default = logger;
139
161
  export {
140
162
  index_default as default,
141
- formatMessage,
142
163
  logger
143
164
  };
144
165
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { Logging } from \"@google-cloud/logging\";\n\nexport interface Logger {\n debug: (...args: unknown[]) => void;\n info: (...args: unknown[]) => void;\n notice: (...args: unknown[]) => void;\n warning: (...args: unknown[]) => void;\n error: (...args: unknown[]) => void;\n critical: (...args: unknown[]) => void;\n alert: (...args: unknown[]) => void;\n emergency: (...args: unknown[]) => void;\n}\n\nexport function formatMessage(args: unknown[]): string {\n return args.map(arg => {\n if (typeof arg === \"string\") return arg;\n if (arg instanceof Error) return arg.message + (arg.stack ? `\\n${arg.stack}` : \"\");\n try {\n return JSON.stringify(arg);\n } catch {\n return String(arg);\n }\n }).join(\" \");\n}\n\n// Resolved once at module load — no per-call branching.\nconst LOGGER_TARGET = process.env.LOGGER_TARGET?.toLowerCase();\nconst LOGGER_FORMAT = process.env.LOGGER_FORMAT?.toLowerCase();\nconst FORCE_GCP = LOGGER_TARGET === \"gcp\";\nconst FORCE_CONSOLE = LOGGER_TARGET === \"console\";\nconst USE_GCP = !FORCE_CONSOLE && (FORCE_GCP || !!process.env.GCP_PROJECT);\nconst CONSOLE_PRETTY = LOGGER_FORMAT === \"pretty\";\nconst noop = (): void => {};\nconst gcpLabels: Record<string, string> = {};\nif (process.env.ENVIRONMENT) gcpLabels.environment = process.env.ENVIRONMENT;\nif (process.env.SERVICE_ID) gcpLabels.service_id = process.env.SERVICE_ID;\nif (process.env.VERSION) gcpLabels.version = process.env.VERSION;\nconst GCP_ENV_LABEL = Object.keys(gcpLabels).length ? { labels: gcpLabels } : {};\n\n// Formats a single console log line: \"{emoji} {local timestamp} {message} [{payload}]\"\nfunction consoleLine(emoji: string, args: unknown[]): string {\n const d = new Date();\n const ts = d.toLocaleString(\"sv-SE\") + \".\" + String(d.getMilliseconds()).padStart(3, \"0\");\n const last = args[args.length - 1];\n const hasPayload = args.length >= 2 && last !== null && typeof last === \"object\" && !Array.isArray(last) && !(last instanceof Error);\n const msg = formatMessage(hasPayload ? args.slice(0, -1) : args);\n const suffix = hasPayload ? \" \" + JSON.stringify(last, null, 2).replace(/\\n\\s*/g, \" \") : \"\";\n return `${emoji} ${ts} ${msg}${suffix}`;\n}\n\n// Plain console line: \"message [{payload}]\"\nfunction consolePlain(args: unknown[]): string {\n const last = args[args.length - 1];\n const hasPayload =\n args.length >= 2 &&\n last !== null &&\n typeof last === \"object\" &&\n !Array.isArray(last) &&\n !(last instanceof Error);\n const msg = formatMessage(hasPayload ? args.slice(0, -1) : args);\n const suffix = hasPayload ? \" \" + JSON.stringify(last, null, 2).replace(/\\n\\s*/g, \" \") : \"\";\n return `${msg}${suffix}`;\n}\n\n// If the last arg is a plain object, return a jsonPayload so Cloud Logging\n// indexes its fields. Otherwise return a plain string (textPayload).\nfunction gcpPayload(args: unknown[]): string | Record<string, unknown> {\n const last = args[args.length - 1];\n if (\n args.length >= 2 &&\n last !== null &&\n typeof last === \"object\" &&\n !Array.isArray(last) &&\n !(last instanceof Error)\n ) {\n return { message: formatMessage(args.slice(0, -1)), ...(last as Record<string, unknown>) };\n }\n return formatMessage(args);\n}\n\nlet gcpLog: ReturnType<Logging[\"log\"]> | null = null;\nif (USE_GCP) {\n try {\n const logName = process.env.LOGGER_NAME ?? process.env.K_SERVICE ?? \"local\";\n gcpLog = new Logging({ projectId: process.env.GCP_PROJECT }).log(logName);\n } catch {\n // GCP init failed; fall back to console\n }\n}\n\nexport const logger: Logger = gcpLog\n ? (() => {\n const g = gcpLog!;\n return {\n debug: (...args: unknown[]): void => {\n g.write(g.entry({ severity: \"DEBUG\", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);\n },\n info: (...args: unknown[]): void => {\n g.write(g.entry({ severity: \"INFO\", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);\n },\n notice: (...args: unknown[]): void => {\n g.write(g.entry({ severity: \"NOTICE\", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);\n },\n warning: (...args: unknown[]): void => {\n g.write(g.entry({ severity: \"WARNING\", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);\n },\n error: (...args: unknown[]): void => {\n g.write(g.entry({ severity: \"ERROR\", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);\n },\n critical: (...args: unknown[]): void => {\n g.write(g.entry({ severity: \"CRITICAL\", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);\n },\n alert: (...args: unknown[]): void => {\n g.write(g.entry({ severity: \"ALERT\", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);\n },\n emergency: (...args: unknown[]): void => {\n g.write(g.entry({ severity: \"EMERGENCY\", ...GCP_ENV_LABEL }, gcpPayload(args))).catch(noop);\n },\n };\n })()\n : CONSOLE_PRETTY\n ? {\n debug: (...args: unknown[]): void => { console.log(consoleLine(\"🐞\", args)); },\n info: (...args: unknown[]): void => { console.log(consoleLine(\"⚪️\", args)); },\n notice: (...args: unknown[]): void => { console.log(consoleLine(\"🔵\", args)); },\n warning: (...args: unknown[]): void => { console.log(consoleLine(\"🟡\", args)); },\n error: (...args: unknown[]): void => { console.log(consoleLine(\"🔴\", args)); },\n critical: (...args: unknown[]): void => { console.log(consoleLine(\"⛔️\", args)); },\n alert: (...args: unknown[]): void => { console.log(consoleLine(\"❗️\", args)); },\n emergency: (...args: unknown[]): void => { console.log(consoleLine(\"🚨\", args)); },\n }\n : {\n debug: (...args: unknown[]): void => { console.log(consolePlain(args)); },\n info: (...args: unknown[]): void => { console.log(consolePlain(args)); },\n notice: (...args: unknown[]): void => { console.log(consolePlain(args)); },\n warning: (...args: unknown[]): void => { console.log(consolePlain(args)); },\n error: (...args: unknown[]): void => { console.log(consolePlain(args)); },\n critical: (...args: unknown[]): void => { console.log(consolePlain(args)); },\n alert: (...args: unknown[]): void => { console.log(consolePlain(args)); },\n emergency: (...args: unknown[]): void => { console.log(consolePlain(args)); },\n };\n\nexport default logger;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { Logging } from \"@google-cloud/logging\";\n\ntype LogMethod = (message: string, payload?: Record<string, unknown>, labels?: Record<string, string>) => void;\n\nexport interface Logger {\n debug: LogMethod;\n info: LogMethod;\n notice: LogMethod;\n warning: LogMethod;\n error: LogMethod;\n critical: LogMethod;\n alert: LogMethod;\n emergency: LogMethod;\n}\n\n// Resolved once at module load — no per-call branching.\n// LOGGER_TARGET accepts a comma-separated list of backends: \"gcp\", \"console\", or \"gcp,console\".\nconst rawTargets = process.env.LOGGER_TARGET;\nconst targets = rawTargets\n ? new Set(rawTargets.toLowerCase().split(\",\").map(s => s.trim()).filter(Boolean))\n : null;\n\nconst USE_GCP = targets ? targets.has(\"gcp\") : !!process.env.GCP_PROJECT;\nconst USE_CONSOLE = targets ? targets.has(\"console\") : !process.env.GCP_PROJECT;\nconst CONSOLE_PRETTY = process.env.LOGGER_CONSOLE_FORMAT?.toLowerCase() === \"pretty\";\nconst noop = (): void => {};\n\nconst envLabels: Record<string, string> = {};\nif (process.env.ENVIRONMENT) envLabels.environment = process.env.ENVIRONMENT;\nif (process.env.SERVICE_ID) envLabels.service_id = process.env.SERVICE_ID;\nif (process.env.VERSION) envLabels.version = process.env.VERSION;\n\n// GCP Log singleton — shared across all logger() calls.\nconst gcpLog = USE_GCP ? (() => {\n try {\n const logName = process.env.LOGGER_NAME ?? process.env.K_SERVICE ?? \"local\";\n return new Logging({ projectId: process.env.GCP_PROJECT }).log(logName);\n } catch {\n return null;\n }\n})() : null;\n\n// Formats a pretty console log line: \"{emoji} {local timestamp} [(scope) ]{message}[ {payload}]\"\nfunction consoleLine(emoji: string, message: string, payload?: Record<string, unknown>, scope?: string): string {\n const d = new Date();\n const ts = d.toLocaleString(\"sv-SE\") + \".\" + String(d.getMilliseconds()).padStart(3, \"0\");\n const scopePart = scope ? `(${scope}) ` : \"\";\n const suffix = payload ? \" \" + JSON.stringify(payload, null, 2).replace(/\\n\\s*/g, \" \") : \"\";\n return `${emoji} ${ts} ${scopePart}${message}${suffix}`;\n}\n\n// Plain console line: \"[(scope) ]{message}[ {payload}]\"\nfunction consolePlain(message: string, payload?: Record<string, unknown>, scope?: string): string {\n const scopePart = scope ? `(${scope}) ` : \"\";\n const suffix = payload ? \" \" + JSON.stringify(payload, null, 2).replace(/\\n\\s*/g, \" \") : \"\";\n return `${scopePart}${message}${suffix}`;\n}\n\nexport function logger(scope?: string): Logger {\n const instanceLabels: Record<string, string> = {\n ...envLabels,\n ...(scope ? { scope } : {}),\n };\n\n function resolveLabels(callLabels?: Record<string, string>): Record<string, string> | undefined {\n const merged = { ...instanceLabels, ...callLabels };\n return Object.keys(merged).length ? merged : undefined;\n }\n\n function gcpMeta(severity: string, callLabels?: Record<string, string>): Record<string, unknown> {\n const labels = resolveLabels(callLabels);\n return labels ? { severity, labels } : { severity };\n }\n\n function gcpData(message: string, payload?: Record<string, unknown>): string | Record<string, unknown> {\n return payload ? { message, ...payload } : message;\n }\n\n const backends: Logger[] = [];\n\n if (gcpLog) {\n const g = gcpLog;\n backends.push({\n debug: (message, payload, labels): void => { g.write(g.entry(gcpMeta(\"DEBUG\", labels), gcpData(message, payload))).catch(noop); },\n info: (message, payload, labels): void => { g.write(g.entry(gcpMeta(\"INFO\", labels), gcpData(message, payload))).catch(noop); },\n notice: (message, payload, labels): void => { g.write(g.entry(gcpMeta(\"NOTICE\", labels), gcpData(message, payload))).catch(noop); },\n warning: (message, payload, labels): void => { g.write(g.entry(gcpMeta(\"WARNING\", labels), gcpData(message, payload))).catch(noop); },\n error: (message, payload, labels): void => { g.write(g.entry(gcpMeta(\"ERROR\", labels), gcpData(message, payload))).catch(noop); },\n critical: (message, payload, labels): void => { g.write(g.entry(gcpMeta(\"CRITICAL\", labels), gcpData(message, payload))).catch(noop); },\n alert: (message, payload, labels): void => { g.write(g.entry(gcpMeta(\"ALERT\", labels), gcpData(message, payload))).catch(noop); },\n emergency: (message, payload, labels): void => { g.write(g.entry(gcpMeta(\"EMERGENCY\", labels), gcpData(message, payload))).catch(noop); },\n });\n }\n\n if (USE_CONSOLE || backends.length === 0) {\n backends.push(CONSOLE_PRETTY\n ? {\n debug: (message, payload): void => { console.log(consoleLine(\"🐞\", message, payload, scope)); },\n info: (message, payload): void => { console.log(consoleLine(\"⚪️\", message, payload, scope)); },\n notice: (message, payload): void => { console.log(consoleLine(\"🔵\", message, payload, scope)); },\n warning: (message, payload): void => { console.log(consoleLine(\"🟡\", message, payload, scope)); },\n error: (message, payload): void => { console.log(consoleLine(\"🔴\", message, payload, scope)); },\n critical: (message, payload): void => { console.log(consoleLine(\"⛔️\", message, payload, scope)); },\n alert: (message, payload): void => { console.log(consoleLine(\"❗️\", message, payload, scope)); },\n emergency: (message, payload): void => { console.log(consoleLine(\"🚨\", message, payload, scope)); },\n }\n : {\n debug: (message, payload): void => { console.log(consolePlain(message, payload, scope)); },\n info: (message, payload): void => { console.log(consolePlain(message, payload, scope)); },\n notice: (message, payload): void => { console.log(consolePlain(message, payload, scope)); },\n warning: (message, payload): void => { console.log(consolePlain(message, payload, scope)); },\n error: (message, payload): void => { console.log(consolePlain(message, payload, scope)); },\n critical: (message, payload): void => { console.log(consolePlain(message, payload, scope)); },\n alert: (message, payload): void => { console.log(consolePlain(message, payload, scope)); },\n emergency: (message, payload): void => { console.log(consolePlain(message, payload, scope)); },\n });\n }\n\n return backends.length === 1\n ? backends[0]\n : {\n debug: (message, payload, labels): void => { backends.forEach(b => b.debug(message, payload, labels)); },\n info: (message, payload, labels): void => { backends.forEach(b => b.info(message, payload, labels)); },\n notice: (message, payload, labels): void => { backends.forEach(b => b.notice(message, payload, labels)); },\n warning: (message, payload, labels): void => { backends.forEach(b => b.warning(message, payload, labels)); },\n error: (message, payload, labels): void => { backends.forEach(b => b.error(message, payload, labels)); },\n critical: (message, payload, labels): void => { backends.forEach(b => b.critical(message, payload, labels)); },\n alert: (message, payload, labels): void => { backends.forEach(b => b.alert(message, payload, labels)); },\n emergency: (message, payload, labels): void => { backends.forEach(b => b.emergency(message, payload, labels)); },\n };\n}\n\nexport default logger;\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logickernel/logger",
3
- "version": "0.6.1",
3
+ "version": "0.8.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",