fix(docs):Docs and Exports
- Add documentation for recently released changes - Update some exports to include enums
This commit is contained in:
@@ -3,10 +3,11 @@
|
||||
Intentional, namespaced logging for TypeScript browser and Node.js applications.
|
||||
|
||||
```ts
|
||||
import { createLogger } from "@mifi/logger";
|
||||
import { createLogger } from '@mifi/logger';
|
||||
|
||||
const logger = createLogger({ environment: "production", namespace: "WIDGET" });
|
||||
logger.child("Button").debug("Rendered", () => ({ expensive: "only evaluated when shown" }));
|
||||
const logger = createLogger({ environment: 'production', namespace: 'WIDGET' });
|
||||
logger.child('Button').debug('Rendered', () => ({ expensive: 'only evaluated when shown' }));
|
||||
logger.debug('response', async () => ({ data: await fetchBody() })); // settled before sinks
|
||||
```
|
||||
|
||||
## Install
|
||||
@@ -20,22 +21,23 @@ Requires Node.js `>=24`. Published to the private `@mifi` registry.
|
||||
## Quick start
|
||||
|
||||
```ts
|
||||
import { createLogger } from "@mifi/logger";
|
||||
import { createLogger } from '@mifi/logger';
|
||||
|
||||
const logger = createLogger({
|
||||
environment: "development", // "development" | "staging" | "production"
|
||||
namespace: "API", // optional; string or string[] joined with ":"
|
||||
environment: 'development', // "development" | "staging" | "production"
|
||||
namespace: 'API', // optional; string or string[] joined with ":"
|
||||
});
|
||||
|
||||
logger.trace("very detailed");
|
||||
logger.debug("diagnostic", () => ({ snapshot: heavyWork() }));
|
||||
logger.info("ready");
|
||||
logger.warn("slow response", { ms: 1200 });
|
||||
logger.error("request failed", error);
|
||||
logger.assert(userId, "missing user id");
|
||||
logger.trace('very detailed');
|
||||
logger.debug('diagnostic', () => ({ snapshot: heavyWork() }));
|
||||
logger.debug('response', async () => ({ data: await res.json(), url: res.url }));
|
||||
logger.info('ready');
|
||||
logger.warn('slow response', { ms: 1200 });
|
||||
logger.error('request failed', error);
|
||||
logger.assert(userId, 'missing user id');
|
||||
|
||||
const auth = logger.child("auth"); // namespace → "API:auth"
|
||||
auth.info("token refreshed");
|
||||
const auth = logger.child('auth'); // namespace → "API:auth"
|
||||
auth.info('token refreshed');
|
||||
```
|
||||
|
||||
Console utility methods (`group`, `groupCollapsed`, `table`, `time`, `count`, `dir`, …) are available and gated by the same level policy as `info`.
|
||||
@@ -64,9 +66,9 @@ Highest wins:
|
||||
### Browser session override
|
||||
|
||||
```js
|
||||
sessionStorage.setItem("showLoggingFor", "debug");
|
||||
sessionStorage.setItem('showLoggingFor', 'debug');
|
||||
// or restrict to namespaces (exact or descendants):
|
||||
sessionStorage.setItem("showLoggingFor", "debug:WIDGET,API");
|
||||
sessionStorage.setItem('showLoggingFor', 'debug:WIDGET,API');
|
||||
```
|
||||
|
||||
`WIDGET` matches `WIDGET` and `WIDGET:Button`.
|
||||
@@ -127,20 +129,20 @@ Override with `logLevel` on `createSentrySink`. Console policy stays independent
|
||||
`trace` / `debug` / `log` / `info` / `warn` / `error` (and `assert`) accept a trailing options object. Console utilities (`group`, `time`, …) do not.
|
||||
|
||||
```ts
|
||||
import * as Sentry from "@sentry/nextjs";
|
||||
import { createLogger } from "@mifi/logger";
|
||||
import { createSentrySink } from "@mifi/logger/sentry";
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
import { createLogger } from '@mifi/logger';
|
||||
import { createSentrySink } from '@mifi/logger/sentry';
|
||||
|
||||
const logger = createLogger({
|
||||
environment: "production",
|
||||
namespace: "API",
|
||||
environment: 'production',
|
||||
namespace: 'API',
|
||||
sentry: createSentrySink(Sentry, { logs: true }),
|
||||
});
|
||||
|
||||
logger.error("Request failed", error, { requestId: "req_1" });
|
||||
logger.warn("slow", { ms: 1200 }); // → Sentry Logs in production
|
||||
logger.info("investigating", { orderId }, { sentry: true }); // force Logs
|
||||
logger.error("expected", err, { suppressSentry: true }); // console only (when enabled)
|
||||
logger.error('Request failed', error, { requestId: 'req_1' });
|
||||
logger.warn('slow', { ms: 1200 }); // → Sentry Logs in production
|
||||
logger.info('investigating', { orderId }, { sentry: true }); // force Logs
|
||||
logger.error('expected', err, { suppressSentry: true }); // console only (when enabled)
|
||||
```
|
||||
|
||||
| Option | Effect |
|
||||
@@ -150,7 +152,7 @@ logger.error("expected", err, { suppressSentry: true }); // console only (when e
|
||||
|
||||
A last argument is treated as options only when every key is `sentry` or `suppressSentry`. Prefer the third-argument form when you also pass data.
|
||||
|
||||
Logs payload: string message + flat primitive attributes (including `logger.namespace`). Nested objects are not unfurled.
|
||||
Logs payload: string message + flat primitive attributes (including `logger.namespace`). Nested objects are not unfurled. When emit was deferred for thenables, the payload also includes `async: true`.
|
||||
|
||||
Issue severities use Sentry’s union (`warning`, not logger `warn`). The sink maps `warn` → `warning` and `trace` → `debug` for Issues only; Logs keep logger level names (`sentry.logger.warn`).
|
||||
|
||||
@@ -159,16 +161,17 @@ Issue severities use Sentry’s union (`warning`, not logger `warn`). The sink m
|
||||
Replace the default destinations entirely with `sinks`:
|
||||
|
||||
```ts
|
||||
import { createLogger, createConsoleSink, type LogSink } from "@mifi/logger";
|
||||
import { createLogger, createConsoleSink, type LogSink } from '@mifi/logger';
|
||||
|
||||
const analyticsSink: LogSink = {
|
||||
emit(event) {
|
||||
if (event.sendToConsole) analytics.track("log", event);
|
||||
if (event.sendToConsole) analytics.track('log', event);
|
||||
// event.async === true when args were settled asynchronously
|
||||
},
|
||||
};
|
||||
|
||||
const logger = createLogger({
|
||||
environment: "production",
|
||||
environment: 'production',
|
||||
sinks: [createConsoleSink(), analyticsSink],
|
||||
});
|
||||
```
|
||||
@@ -192,16 +195,46 @@ All public APIs include JSDoc with parameter and example documentation in the Ty
|
||||
|
||||
## Lazy arguments
|
||||
|
||||
Any function passed **after** the first argument is invoked only if the event is emitted:
|
||||
Any function passed **after** the first argument is invoked only if the event will actually be emitted (console and/or Sentry). That keeps expensive snapshots cheap when the level is suppressed.
|
||||
|
||||
```ts
|
||||
logger.debug("state", () => buildHugeSnapshot()); // skipped when debug is suppressed
|
||||
logger.debug("response", async () => ({ data: await res.json(), url }));
|
||||
logger.debug('state', () => buildHugeSnapshot()); // skipped when debug is suppressed
|
||||
logger.error('failed', error, () => ({ body: pendingBody }));
|
||||
```
|
||||
|
||||
Top-level thenables (including Promises returned from lazy factories, or a Promise passed directly as an argument) are settled before sinks run. The log call stays fire-and-forget (`void`). Settled events set `LogEvent.async`, and the console sink renders an `[async]` label suffix. Nested promises inside plain objects are not walked — compose them inside the async factory. Async emits may appear out of order relative to sync logs.
|
||||
### Async factories and Promises
|
||||
|
||||
Rejection reasons replace rejected thenables in that argument slot; other arguments still emit.
|
||||
Factories may be `async`, or you may pass a top-level `Promise` as an argument. Thenables are **settled before sinks run**; the log method stays fire-and-forget (`void`).
|
||||
|
||||
```ts
|
||||
logger.debug('response', async () => ({
|
||||
data: await res.json(),
|
||||
url: res.url,
|
||||
}));
|
||||
|
||||
logger.error('failed', { id }, responsePromise);
|
||||
```
|
||||
|
||||
| Behavior | Detail |
|
||||
| ----------------- | -------------------------------------------------------------------------------------------- |
|
||||
| Unwrap scope | **Shallow** — only top-level thenables in the argument list |
|
||||
| Nested promises | Not walked; compose with `await` / `Promise.all` inside the factory |
|
||||
| Call return type | Still `void` (no `await logger.debug(...)`) |
|
||||
| Timestamp | Captured at call time (before settle), so async logs correlate with the failure moment |
|
||||
| `LogEvent.async` | `true` when emit was deferred; omitted for fully sync emits |
|
||||
| Console | Label gains an `[async]` suffix, e.g. `[API][async]` |
|
||||
| Sentry Logs | Attribute `async: true` when set |
|
||||
| Ordering | Async emits may appear after later sync logs |
|
||||
| Rejections | Rejection `reason` replaces that argument slot; other args still emit (`Promise.allSettled`) |
|
||||
| Console utilities | `group` / `time` / etc. do not settle thenables (emit path only) |
|
||||
|
||||
```ts
|
||||
// Nested promises — compose inside the factory:
|
||||
logger.debug('route', async () => {
|
||||
const [body, next] = await Promise.all([res.json(), nextRoute]);
|
||||
return { body, next };
|
||||
});
|
||||
```
|
||||
|
||||
## Releases
|
||||
|
||||
|
||||
Reference in New Issue
Block a user