Skip to content

Commit

Permalink
Merge tag '0.7.1'
Browse files Browse the repository at this point in the history
LogTape 0.7.1
  • Loading branch information
dahlia committed Oct 30, 2024
2 parents 61cc87c + 705ff0c commit 5c38a54
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 6 deletions.
10 changes: 10 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@ Version 0.8.0
To be released.


Version 0.7.1
-------------

Released on October 30, 2024.

- The `withContext()` function no more throws an error
even if no `contextLocalStorage` is configured. Instead, it will log
a warning message to the `["logtape", "meta"]` logger.


Version 0.7.0
-------------

Expand Down
4 changes: 2 additions & 2 deletions docs/manual/contexts.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ across multiple log messages made by different loggers in different modules.
> [!CAUTION]
> In order to use implicit context, your JavaScript runtime must support
> context-local states (like Node.js's [`node:async_hooks`] module). If your
> JavaScript runtime doesn't support context-local states, LogTape will throw
> an error when you try to use implicit contexts.
> JavaScript runtime doesn't support context-local states, LogTape will silently
> ignore implicit contexts and log messages will not have implicit contexts.
>
> As of October 2024, Node.js, Deno, and Bun support implicit contexts.
> Web browsers don't support implicit contexts yet.
Expand Down
41 changes: 38 additions & 3 deletions logtape/context.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { assertEquals } from "@std/assert/assert-equals";
import { assertThrows } from "@std/assert/assert-throws";
import { delay } from "@std/async/delay";
import { AsyncLocalStorage } from "node:async_hooks";
import { configure, reset } from "./config.ts";
Expand Down Expand Up @@ -131,21 +130,57 @@ Deno.test("withContext()", async (t) => {
await reset();
});

const metaBuffer: LogRecord[] = [];

await t.step("set up", async () => {
await configure({
sinks: {
buffer: buffer.push.bind(buffer),
metaBuffer: metaBuffer.push.bind(metaBuffer),
},
loggers: [
{ category: "my-app", sinks: ["buffer"], level: "debug" },
{ category: ["logtape", "meta"], sinks: [], level: "warning" },
{
category: ["logtape", "meta"],
sinks: ["metaBuffer"],
level: "warning",
},
],
reset: true,
});
});

await t.step("without settings", () => {
assertThrows(() => withContext({}, () => {}), TypeError);
while (buffer.length > 0) buffer.pop();
const rv = withContext({ foo: 1 }, () => {
getLogger("my-app").debug("hello", { bar: 2 });
return 123;
});
assertEquals(rv, 123);
assertEquals(buffer, [
{
category: ["my-app"],
level: "debug",
message: ["hello"],
rawMessage: "hello",
properties: { bar: 2 },
timestamp: buffer[0].timestamp,
},
]);
assertEquals(metaBuffer, [
{
category: ["logtape", "meta"],
level: "warning",
message: [
"Context-local storage is not configured. " +
"Specify contextLocalStorage option in the configure() function.",
],
properties: {},
rawMessage: "Context-local storage is not configured. " +
"Specify contextLocalStorage option in the configure() function.",
timestamp: metaBuffer[0].timestamp,
},
]);
});

await t.step("tear down", async () => {
Expand Down
7 changes: 6 additions & 1 deletion logtape/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ export interface ContextLocalStorage<T> {
/**
* Runs a callback with the given implicit context. Every single log record
* in the callback will have the given context.
*
* If no `contextLocalStorage` is configured, this function does nothing and
* just returns the return value of the callback. It also logs a warning to
* the `["logtape", "meta"]` logger in this case.
* @param context The context to inject.
* @param callback The callback to run.
* @returns The return value of the callback.
Expand All @@ -37,10 +41,11 @@ export function withContext<T>(
): T {
const rootLogger = LoggerImpl.getLogger();
if (rootLogger.contextLocalStorage == null) {
throw new TypeError(
LoggerImpl.getLogger(["logtape", "meta"]).warn(
"Context-local storage is not configured. " +
"Specify contextLocalStorage option in the configure() function.",
);
return callback();
}
const parentContext = rootLogger.contextLocalStorage.getStore() ?? {};
return rootLogger.contextLocalStorage.run(
Expand Down

0 comments on commit 5c38a54

Please sign in to comment.