Loading .vscode/settings.json +1 −0 Original line number Diff line number Diff line Loading @@ -132,6 +132,7 @@ "superproperty", "supertypes", "tempserver", "traceparent", "ts-nocheck", "twoslash", "typeof", Loading CHANGES.md +6 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,9 @@ To be released. - `new Service()` constructor now accepts `followedMessage` option. - `Service.clone()` method now accepts `followedMessage` option. - Log messages now can be traced using [LogTape]'s [implicit contexts]. [[#118]] - Added options for an AMQP driver to `fedify init` command. - Added `amqp` value to the `-q`/`--message-queue` option of Loading @@ -51,6 +54,9 @@ To be released. - `["fedify", "nodeinfo", "client"]` [implicit contexts]: https://logtape.org/manual/contexts#implicit-contexts [#118]: https://github.com/dahlia/fedify/issues/118 Version 1.1.2 ------------- Loading cli/import_map.g.json +1 −1 Original line number Diff line number Diff line Loading @@ -15,7 +15,7 @@ "@fedify/fedify/x/hono": "../src/./x/hono.ts", "@hongminhee/aitertools": "jsr:@hongminhee/aitertools@^0.6.0", "@hugoalh/http-header-link": "jsr:@hugoalh/http-header-link@^1.0.2", "@logtape/logtape": "jsr:@logtape/logtape@^0.6.2", "@logtape/logtape": "jsr:@logtape/logtape@^0.7.1", "@phensley/language-tag": "npm:@phensley/language-tag@^1.9.0", "@std/assert": "jsr:@std/assert@^0.226.0", "@std/async": "jsr:@std/async@^1.0.5", Loading cli/import_map.json +1 −1 Original line number Diff line number Diff line Loading @@ -9,7 +9,7 @@ "@hongminhee/localtunnel": "jsr:@hongminhee/localtunnel@^0.2.0", "@jimp/core": "npm:@jimp/core@^1.6.0", "@jimp/wasm-webp": "npm:@jimp/wasm-webp@^1.6.0", "@logtape/logtape": "jsr:@logtape/logtape@^0.6.2", "@logtape/logtape": "jsr:@logtape/logtape@^0.7.1", "@poppanator/http-constants": "npm:@poppanator/http-constants@^1.1.1", "@std/dotenv": "jsr:@std/dotenv@^0.225.2", "@std/fs": "jsr:@std/fs@^0.229.3", Loading docs/manual/log.md +103 −1 Original line number Diff line number Diff line Loading @@ -45,15 +45,27 @@ bun add @logtape/logtape Then, you can [`configure()`] the logger in the entry point of your app: ~~~~ typescript twoslash // @noErrors: 2307 import { type ContextLocalStorage } from "@logtape/logtape"; class AsyncLocalStorage<T> implements ContextLocalStorage<T> { getStore(): T | undefined { return undefined; } run<R>(store: T, callback: () => R): R { return callback(); } } // ---cut-before--- import { AsyncLocalStorage } from "node:async_hooks"; import { configure, getConsoleSink } from "@logtape/logtape"; await configure({ sinks: { console: getConsoleSink() }, filters: {}, loggers: [ { category: "your-app", sinks: ["console"], level: "debug" }, { category: "fedify", sinks: ["console"], level: "error" }, ], contextLocalStorage: new AsyncLocalStorage(), }); ~~~~ Loading Loading @@ -89,9 +101,18 @@ The `configure()` function takes an object with three properties: level can be one of the following: `"debug"`, `"info"`, `"warning"`, `"error"`, or `"fatal"`. `contextLocalStorage` (recommended) : *This property is available since LogTape 0.7.0.* An instance of [`AsyncLocalStorage`] that is used to store [implicit contexts] of the log messages. This is useful when you want to trace the log messages in a specific context. [JSR]: https://jsr.io/@logtape/logtape [npm]: https://www.npmjs.com/package/@logtape/logtape [`configure()`]: https://jsr.io/@logtape/logtape/doc/~/configure [`AsyncLocalStorage`]: https://nodejs.org/api/async_context.html#class-asynclocalstorage [implicit contexts]: https://logtape.org/manual/contexts#implicit-contexts Categories Loading Loading @@ -281,3 +302,84 @@ log messages. The deprecation warnings are logged with the `"warning"` level in each category where the deprecated API is used. If you want to see all deprecation warnings, you can set the log level to `"warning"` for the [`"fedify"` category](#fedify). Tracing ------- *This feature is available since Fedify 1.2.0.* > [!CAUTION] > Traceable log messages rely on [implicit contexts] which was introduced in > LogTape 0.7.0. If you don't configure `contextLocalStorage` in > [`configure()`], you cannot trace log messages. The most of log messages made by Fedify can be traced by either below two properties: `requestId` : If the log message is made in the context of an HTTP request, the `requestId` property is included in it. The `requestId` is a unique identifier for the HTTP request, which is derived from one of the following headers: - [`X-Request-Id`] - `X-Correlation-Id` - [`Traceparent`] - Otherwise, the `requestId` is a unique string derived from the current timestamp and the random number. `messageId` : If the log message is made in the context of a background task, the `messageId` property is included in it. The `messageId` is a unique identifier for the background task, which is a UUID. When you want to trace log messages, first of all you need to use a sink that writes log messages as structured data. For example, you can use a [file sink] with a [JSON Lines] formatter. Oh, and don't forget to set `contextLocalStorage` in [`configure()`]! To sum up, you can configure loggers like this: ~~~~ typescript twoslash // @noErrors: 2307 import { type ContextLocalStorage } from "@logtape/logtape"; class AsyncLocalStorage<T> implements ContextLocalStorage<T> { getStore(): T | undefined { return undefined; } run<R>(store: T, callback: () => R): R { return callback(); } } // ---cut-before--- import { AsyncLocalStorage } from "node:async_hooks"; import { type LogRecord, configure, getFileSink } from "@logtape/logtape"; await configure({ sinks: { file: getFileSink("fedify-logs.jsonld", { formatter(record: LogRecord): string { return JSON.stringify(record) + "\n"; } }) }, loggers: [ { category: "fedify", sinks: ["file"], level: "info" }, ], contextLocalStorage: new AsyncLocalStorage(), }); ~~~~ If your loggers are configured like this, you can filter log messages by `requestId` or `messageId` in the log file. For example, you can filter log messages by `requestId` using [`jq`]: ~~~~ sh jq -r 'select(.properties.requestId == "your-request-id")' fedify-logs.jsonl ~~~~ [`X-Request-Id`]: https://http.dev/x-request-id [`Traceparent`]: https://www.w3.org/TR/trace-context/#traceparent-header [file sink]: https://logtape.org/manual/sinks#file-sink [JSON Lines]: https://jsonlines.org/ [`jq`]: https://jqlang.github.io/jq/ Loading
.vscode/settings.json +1 −0 Original line number Diff line number Diff line Loading @@ -132,6 +132,7 @@ "superproperty", "supertypes", "tempserver", "traceparent", "ts-nocheck", "twoslash", "typeof", Loading
CHANGES.md +6 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,9 @@ To be released. - `new Service()` constructor now accepts `followedMessage` option. - `Service.clone()` method now accepts `followedMessage` option. - Log messages now can be traced using [LogTape]'s [implicit contexts]. [[#118]] - Added options for an AMQP driver to `fedify init` command. - Added `amqp` value to the `-q`/`--message-queue` option of Loading @@ -51,6 +54,9 @@ To be released. - `["fedify", "nodeinfo", "client"]` [implicit contexts]: https://logtape.org/manual/contexts#implicit-contexts [#118]: https://github.com/dahlia/fedify/issues/118 Version 1.1.2 ------------- Loading
cli/import_map.g.json +1 −1 Original line number Diff line number Diff line Loading @@ -15,7 +15,7 @@ "@fedify/fedify/x/hono": "../src/./x/hono.ts", "@hongminhee/aitertools": "jsr:@hongminhee/aitertools@^0.6.0", "@hugoalh/http-header-link": "jsr:@hugoalh/http-header-link@^1.0.2", "@logtape/logtape": "jsr:@logtape/logtape@^0.6.2", "@logtape/logtape": "jsr:@logtape/logtape@^0.7.1", "@phensley/language-tag": "npm:@phensley/language-tag@^1.9.0", "@std/assert": "jsr:@std/assert@^0.226.0", "@std/async": "jsr:@std/async@^1.0.5", Loading
cli/import_map.json +1 −1 Original line number Diff line number Diff line Loading @@ -9,7 +9,7 @@ "@hongminhee/localtunnel": "jsr:@hongminhee/localtunnel@^0.2.0", "@jimp/core": "npm:@jimp/core@^1.6.0", "@jimp/wasm-webp": "npm:@jimp/wasm-webp@^1.6.0", "@logtape/logtape": "jsr:@logtape/logtape@^0.6.2", "@logtape/logtape": "jsr:@logtape/logtape@^0.7.1", "@poppanator/http-constants": "npm:@poppanator/http-constants@^1.1.1", "@std/dotenv": "jsr:@std/dotenv@^0.225.2", "@std/fs": "jsr:@std/fs@^0.229.3", Loading
docs/manual/log.md +103 −1 Original line number Diff line number Diff line Loading @@ -45,15 +45,27 @@ bun add @logtape/logtape Then, you can [`configure()`] the logger in the entry point of your app: ~~~~ typescript twoslash // @noErrors: 2307 import { type ContextLocalStorage } from "@logtape/logtape"; class AsyncLocalStorage<T> implements ContextLocalStorage<T> { getStore(): T | undefined { return undefined; } run<R>(store: T, callback: () => R): R { return callback(); } } // ---cut-before--- import { AsyncLocalStorage } from "node:async_hooks"; import { configure, getConsoleSink } from "@logtape/logtape"; await configure({ sinks: { console: getConsoleSink() }, filters: {}, loggers: [ { category: "your-app", sinks: ["console"], level: "debug" }, { category: "fedify", sinks: ["console"], level: "error" }, ], contextLocalStorage: new AsyncLocalStorage(), }); ~~~~ Loading Loading @@ -89,9 +101,18 @@ The `configure()` function takes an object with three properties: level can be one of the following: `"debug"`, `"info"`, `"warning"`, `"error"`, or `"fatal"`. `contextLocalStorage` (recommended) : *This property is available since LogTape 0.7.0.* An instance of [`AsyncLocalStorage`] that is used to store [implicit contexts] of the log messages. This is useful when you want to trace the log messages in a specific context. [JSR]: https://jsr.io/@logtape/logtape [npm]: https://www.npmjs.com/package/@logtape/logtape [`configure()`]: https://jsr.io/@logtape/logtape/doc/~/configure [`AsyncLocalStorage`]: https://nodejs.org/api/async_context.html#class-asynclocalstorage [implicit contexts]: https://logtape.org/manual/contexts#implicit-contexts Categories Loading Loading @@ -281,3 +302,84 @@ log messages. The deprecation warnings are logged with the `"warning"` level in each category where the deprecated API is used. If you want to see all deprecation warnings, you can set the log level to `"warning"` for the [`"fedify"` category](#fedify). Tracing ------- *This feature is available since Fedify 1.2.0.* > [!CAUTION] > Traceable log messages rely on [implicit contexts] which was introduced in > LogTape 0.7.0. If you don't configure `contextLocalStorage` in > [`configure()`], you cannot trace log messages. The most of log messages made by Fedify can be traced by either below two properties: `requestId` : If the log message is made in the context of an HTTP request, the `requestId` property is included in it. The `requestId` is a unique identifier for the HTTP request, which is derived from one of the following headers: - [`X-Request-Id`] - `X-Correlation-Id` - [`Traceparent`] - Otherwise, the `requestId` is a unique string derived from the current timestamp and the random number. `messageId` : If the log message is made in the context of a background task, the `messageId` property is included in it. The `messageId` is a unique identifier for the background task, which is a UUID. When you want to trace log messages, first of all you need to use a sink that writes log messages as structured data. For example, you can use a [file sink] with a [JSON Lines] formatter. Oh, and don't forget to set `contextLocalStorage` in [`configure()`]! To sum up, you can configure loggers like this: ~~~~ typescript twoslash // @noErrors: 2307 import { type ContextLocalStorage } from "@logtape/logtape"; class AsyncLocalStorage<T> implements ContextLocalStorage<T> { getStore(): T | undefined { return undefined; } run<R>(store: T, callback: () => R): R { return callback(); } } // ---cut-before--- import { AsyncLocalStorage } from "node:async_hooks"; import { type LogRecord, configure, getFileSink } from "@logtape/logtape"; await configure({ sinks: { file: getFileSink("fedify-logs.jsonld", { formatter(record: LogRecord): string { return JSON.stringify(record) + "\n"; } }) }, loggers: [ { category: "fedify", sinks: ["file"], level: "info" }, ], contextLocalStorage: new AsyncLocalStorage(), }); ~~~~ If your loggers are configured like this, you can filter log messages by `requestId` or `messageId` in the log file. For example, you can filter log messages by `requestId` using [`jq`]: ~~~~ sh jq -r 'select(.properties.requestId == "your-request-id")' fedify-logs.jsonl ~~~~ [`X-Request-Id`]: https://http.dev/x-request-id [`Traceparent`]: https://www.w3.org/TR/trace-context/#traceparent-header [file sink]: https://logtape.org/manual/sinks#file-sink [JSON Lines]: https://jsonlines.org/ [`jq`]: https://jqlang.github.io/jq/