fix(logger): respect configured logger in auth request context

This commit is contained in:
Taesu
2026-08-22 17:18:09 +09:00
parent c7a5c1a7ed
commit 716bc585dd
4 changed files with 117 additions and 4 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@better-auth/core": patch
---
Logs emitted while handling auth requests now respect the configured custom logger, log level, and disabled setting.
@@ -32,6 +32,18 @@ export async function getCurrentAuthContextAsyncLocalStorage() {
return ensureAsyncStorage();
}
/**
* Returns the current auth context without initializing async storage.
*
* @internal
*/
export function tryGetCurrentAuthContext(): AuthEndpointContext | undefined {
const storage = __getBetterAuthGlobal().context.endpointContextAsyncStorage as
| AsyncLocalStorage<AuthEndpointContext>
| undefined;
return storage?.getStore();
}
export async function getCurrentAuthContext(): Promise<AuthEndpointContext> {
const als = await ensureAsyncStorage();
const context = als.getStore();
+80 -3
View File
@@ -1,6 +1,9 @@
import { describe, expect, it } from "vitest";
import type { LogLevel } from "./logger";
import { shouldPublishLog } from "./logger";
import { describe, expect, it, onTestFinished, vi } from "vitest";
import type { AuthEndpointContext } from "../context";
import { runWithEndpointContext } from "../context";
import { safeJSONParse } from "../utils/json";
import type { InternalLogger, LogLevel } from "./logger";
import { createLogger, logger, shouldPublishLog } from "./logger";
describe("shouldPublishLog", () => {
const testCases: {
@@ -32,3 +35,77 @@ describe("shouldPublishLog", () => {
});
});
});
describe("logger", () => {
const endpointContext = (logger: InternalLogger) =>
({ context: { logger } }) as unknown as AuthEndpointContext;
it("uses the default logger outside an auth context", () => {
const defaultWarn = vi.spyOn(console, "warn").mockImplementation(() => {});
onTestFinished(() => defaultWarn.mockRestore());
logger.warn("default warning");
expect(defaultWarn).toHaveBeenCalledTimes(1);
});
it("delegates to the logger in the current auth context", async () => {
const defaultWarn = vi.spyOn(console, "warn").mockImplementation(() => {});
onTestFinished(() => defaultWarn.mockRestore());
const firstLog = vi.fn();
const secondLog = vi.fn();
const firstLogger = createLogger({ level: "info", log: firstLog });
const secondLogger = createLogger({ level: "error", log: secondLog });
await Promise.all([
runWithEndpointContext(endpointContext(firstLogger), async () => {
await Promise.resolve();
expect(logger.level).toBe("info");
logger.warn("first warning");
}),
runWithEndpointContext(endpointContext(secondLogger), async () => {
await Promise.resolve();
expect(logger.level).toBe("error");
logger.warn("second warning");
}),
]);
expect(firstLog).toHaveBeenCalledWith("warn", "first warning");
expect(secondLog).not.toHaveBeenCalled();
expect(defaultWarn).not.toHaveBeenCalled();
});
it("routes utility logs through the current auth context", async () => {
const defaultError = vi
.spyOn(console, "error")
.mockImplementation(() => {});
onTestFinished(() => defaultError.mockRestore());
const log = vi.fn();
const configuredLogger = createLogger({ log });
await runWithEndpointContext(endpointContext(configuredLogger), () => {
expect(safeJSONParse("{")).toBeNull();
});
expect(log).toHaveBeenCalledWith(
"error",
"Error parsing JSON",
expect.objectContaining({ error: expect.any(SyntaxError) }),
);
expect(defaultError).not.toHaveBeenCalled();
});
it("honors disabled logging in the current auth context", async () => {
const defaultWarn = vi.spyOn(console, "warn").mockImplementation(() => {});
onTestFinished(() => defaultWarn.mockRestore());
const log = vi.fn();
const configuredLogger = createLogger({ disabled: true, log });
await runWithEndpointContext(endpointContext(configuredLogger), () => {
logger.warn("hidden warning");
});
expect(log).not.toHaveBeenCalled();
expect(defaultWarn).not.toHaveBeenCalled();
});
});
+20 -1
View File
@@ -1,3 +1,4 @@
import { tryGetCurrentAuthContext } from "../context/endpoint-context";
import { getColorDepth } from "./color-depth";
export const TTY_COLORS = {
@@ -142,4 +143,22 @@ export const createLogger = (options?: Logger | undefined): InternalLogger => {
};
};
export const logger = createLogger();
const defaultLogger = createLogger();
const getCurrentLogger = (): InternalLogger => {
const currentLogger = tryGetCurrentAuthContext()?.context.logger;
return currentLogger && currentLogger !== logger
? currentLogger
: defaultLogger;
};
export const logger: InternalLogger = {
debug: (...params) => getCurrentLogger().debug(...params),
info: (...params) => getCurrentLogger().info(...params),
success: (...params) => getCurrentLogger().success(...params),
warn: (...params) => getCurrentLogger().warn(...params),
error: (...params) => getCurrentLogger().error(...params),
get level() {
return getCurrentLogger().level;
},
};