@logickernel/logger 0.10.3 → 0.10.5
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 +92 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ log.warning("disk space low", { used: "92%", mount: "/data" });
|
|
|
22
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
23
|
- On the **console**: writes with emoji prefixes, a local timestamp, and the payload inlined as compact JSON.
|
|
24
24
|
- **Both at once**: set `LOGGER_TARGET=gcp,console` to fan out to both.
|
|
25
|
-
- **Why it exists**: To
|
|
25
|
+
- **Why it exists**: To make it easy to produce structured, queryable telemetry from any Node.js service without wiring up a separate metrics stack. Log entries are first-class data points: their `jsonPayload` fields and labels feed directly into Cloud Monitoring log-based metrics and dashboards.
|
|
26
26
|
|
|
27
27
|
**Key features**
|
|
28
28
|
|
|
@@ -32,7 +32,7 @@ log.warning("disk space low", { used: "92%", mount: "/data" });
|
|
|
32
32
|
- **Full severity ladder**: `debug`, `info`, `notice`, `warning`, `error`, `critical`, `alert`, `emergency`.
|
|
33
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
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. `
|
|
35
|
+
- **Per-call labels**: Pass a third argument to attach GCP labels to a single entry (e.g. `provider`, `region`, `method`).
|
|
36
36
|
|
|
37
37
|
---
|
|
38
38
|
|
|
@@ -63,7 +63,7 @@ const apiLog = logger("api");
|
|
|
63
63
|
apiLog.info("request handled", { method: "GET", status: 200 });
|
|
64
64
|
|
|
65
65
|
// Per-call labels — merged with scope and env labels for that entry only
|
|
66
|
-
apiLog.info("request handled", {
|
|
66
|
+
apiLog.info("request handled", { ms: 42, status: 200 }, { method: "GET", route: "/users" });
|
|
67
67
|
```
|
|
68
68
|
|
|
69
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:
|
|
@@ -122,8 +122,8 @@ log.info("request complete", { method: "GET", path: "/api/users", status: 200, m
|
|
|
122
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
123
|
|
|
124
124
|
```ts
|
|
125
|
-
log.info("payment processed", { amount: 99 }, {
|
|
126
|
-
// GCP entry: labels = { ...envLabels, scope: "...",
|
|
125
|
+
log.info("payment processed", { amount: 99, orderId: "o-4421" }, { provider: "stripe", currency: "usd" });
|
|
126
|
+
// GCP entry: labels = { ...envLabels, scope: "...", provider: "stripe", currency: "usd" }
|
|
127
127
|
```
|
|
128
128
|
|
|
129
129
|
### Console format
|
|
@@ -187,7 +187,92 @@ const log: Logger = logger("my-scope");
|
|
|
187
187
|
|
|
188
188
|
---
|
|
189
189
|
|
|
190
|
-
## 3.
|
|
190
|
+
## 3. Best Practices
|
|
191
|
+
|
|
192
|
+
### Purpose: structured telemetry, not just log lines
|
|
193
|
+
|
|
194
|
+
Every log entry written to Cloud Logging is a queryable data point. The goal is to make those entries useful beyond text search: payload fields become extractable metric values (latency, counts, sizes), and labels become the dimensions you filter and group by in Cloud Monitoring dashboards and alerting policies.
|
|
195
|
+
|
|
196
|
+
### Payload carries values; labels carry categories
|
|
197
|
+
|
|
198
|
+
The two data arguments serve distinct roles and should not be mixed:
|
|
199
|
+
|
|
200
|
+
| | `payload` — 2nd arg | `labels` — scope + 3rd arg |
|
|
201
|
+
|---|---|---|
|
|
202
|
+
| Type | `Record<string, unknown>` | `Record<string, string>` — strings only |
|
|
203
|
+
| Purpose | Measurements and event data | Categorization and filtering |
|
|
204
|
+
| GCP storage | Indexed as `jsonPayload` fields | Stored as entry labels |
|
|
205
|
+
| Metrics use | Field values extracted into metric data points | Dimensions for aggregation and segmentation |
|
|
206
|
+
| Cardinality | Can be high (IDs, URLs, queries) | Must be low (bounded enums and categories) |
|
|
207
|
+
|
|
208
|
+
**Put measurements and context in payload:**
|
|
209
|
+
|
|
210
|
+
```ts
|
|
211
|
+
log.info("request handled", { ms: 42, status: 200, bytes: 1024 });
|
|
212
|
+
log.info("cache result", { hit: true, ttl: 300 });
|
|
213
|
+
log.warning("slow query", { ms: 850, rowsScanned: 12000 });
|
|
214
|
+
log.info("job complete", { processed: 142, failed: 3, durationMs: 5400 });
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
**Put grouping dimensions in labels:**
|
|
218
|
+
|
|
219
|
+
```ts
|
|
220
|
+
// scope sets a label on every entry from this logger
|
|
221
|
+
const log = logger("payments");
|
|
222
|
+
|
|
223
|
+
// per-call labels add event-specific dimensions
|
|
224
|
+
log.info("charge processed", { amount: 99.95 }, { provider: "stripe", currency: "usd" });
|
|
225
|
+
log.error("charge failed", { code: "card_declined" }, { provider: "stripe" });
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Keep label cardinality low
|
|
229
|
+
|
|
230
|
+
Labels become metric dimensions. High-cardinality values — user IDs, request IDs, raw URLs with path parameters — will explode the cardinality of any metric built on them and will be rejected or silently dropped by Cloud Monitoring. Put those values in the payload instead.
|
|
231
|
+
|
|
232
|
+
```ts
|
|
233
|
+
// Good — labels are bounded, payload carries the variable data
|
|
234
|
+
log.info("payment processed", { amount: 99.95, userId: "u-9182", orderId: "o-4421" }, { provider: "stripe" });
|
|
235
|
+
|
|
236
|
+
// Avoid — userId in labels has unbounded cardinality
|
|
237
|
+
log.info("payment processed", { amount: 99.95 }, { provider: "stripe", userId: "u-9182" });
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Instantiate once per module or service boundary
|
|
241
|
+
|
|
242
|
+
Create the logger at module scope, not inside request handlers or loops. The factory is lightweight, but calling it repeatedly is unnecessary and loses the benefit of a stable scope label.
|
|
243
|
+
|
|
244
|
+
```ts
|
|
245
|
+
// Good — created once, reused everywhere in this module
|
|
246
|
+
const log = logger("orders");
|
|
247
|
+
|
|
248
|
+
export async function createOrder(data: OrderData) {
|
|
249
|
+
log.info("order created", { orderId: data.id, total: data.total });
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Avoid — recreated on every call
|
|
253
|
+
export async function createOrder(data: OrderData) {
|
|
254
|
+
logger("orders").info("order created", { orderId: data.id, total: data.total });
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Building log-based metrics in Cloud Monitoring
|
|
259
|
+
|
|
260
|
+
Once entries flow into Cloud Logging you can create log-based metrics in a few steps:
|
|
261
|
+
|
|
262
|
+
1. Open **Cloud Logging → Log-based Metrics → Create metric**.
|
|
263
|
+
2. Set a filter to scope the metric, e.g.:
|
|
264
|
+
```
|
|
265
|
+
logName="projects/MY_PROJECT/logs/MY_LOG"
|
|
266
|
+
severity="INFO"
|
|
267
|
+
jsonPayload.ms > 0
|
|
268
|
+
```
|
|
269
|
+
3. For a **distribution metric** (e.g. request latency), set the **field extractor** to `jsonPayload.ms`.
|
|
270
|
+
4. Add **label extractors** for the dimensions you want to slice by, e.g. `labels.scope`, `labels."service_id"`.
|
|
271
|
+
5. Chart the metric in **Cloud Monitoring** or attach an alerting policy (e.g. p99 latency > 500 ms).
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## 4. Local Setup (Development)
|
|
191
276
|
|
|
192
277
|
### Prerequisites
|
|
193
278
|
|
|
@@ -217,7 +302,7 @@ npm run build
|
|
|
217
302
|
|
|
218
303
|
---
|
|
219
304
|
|
|
220
|
-
##
|
|
305
|
+
## 5. Additional Resources
|
|
221
306
|
|
|
222
307
|
- **Package**: `@logickernel/logger` on npm.
|
|
223
308
|
- **License**: MIT (see `LICENSE` in this repository).
|