feat: now supports async functions for logging data
- `logger.debug('message', async () => ({ asyncReturn: await asyncFn() }))` is now supported
- NOTE: this may result in logging occurring out of band for these calls if other events fire befor they settle
Update CI labels to direct jobs to correct servers
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { createConsoleSink } from "../src/index";
|
||||
import type { LogEvent } from "../src/index";
|
||||
|
||||
function event(overrides: Partial<LogEvent> = {}): LogEvent {
|
||||
return {
|
||||
level: "debug",
|
||||
namespace: "API",
|
||||
arguments: ["hello"],
|
||||
timestamp: new Date(),
|
||||
environment: "development",
|
||||
sendToSentryLogs: false,
|
||||
sendToSentryIssue: false,
|
||||
sendToConsole: true,
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
describe("createConsoleSink", () => {
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("appends [async] to the namespace label when event.async is set", () => {
|
||||
const debug = vi.spyOn(console, "debug").mockImplementation(() => undefined);
|
||||
createConsoleSink().emit(event({ async: true }));
|
||||
expect(debug).toHaveBeenCalled();
|
||||
const first = debug.mock.calls[0]?.[0];
|
||||
expect(String(first)).toContain("[API][async]");
|
||||
});
|
||||
|
||||
it("omits [async] for synchronous events", () => {
|
||||
const debug = vi.spyOn(console, "debug").mockImplementation(() => undefined);
|
||||
createConsoleSink().emit(event());
|
||||
expect(debug).toHaveBeenCalled();
|
||||
const first = debug.mock.calls[0]?.[0];
|
||||
expect(String(first)).toContain("[API]");
|
||||
expect(String(first)).not.toContain("[async]");
|
||||
});
|
||||
});
|
||||
@@ -40,6 +40,43 @@ describe("createLogger", () => {
|
||||
expect(expensive).toHaveBeenCalledTimes(1);
|
||||
expect(destination.events).toHaveLength(1);
|
||||
expect(destination.events[0]?.arguments).toEqual(["kept", { huge: "snapshot" }]);
|
||||
expect(destination.events[0]?.async).toBeUndefined();
|
||||
});
|
||||
|
||||
it("never starts suppressed async lazy factories", () => {
|
||||
const destination = sink();
|
||||
const expensive = vi.fn(async () => ({ huge: "snapshot" }));
|
||||
const logger = createLogger({ environment: "production", sinks: [destination.sink] });
|
||||
logger.debug("ignored", expensive);
|
||||
expect(expensive).not.toHaveBeenCalled();
|
||||
expect(destination.events).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("settles async lazy factories before emitting and sets async", async () => {
|
||||
const destination = sink();
|
||||
const factory = vi.fn(async () => ({ data: 1 }));
|
||||
const logger = createLogger({ environment: "development", sinks: [destination.sink] });
|
||||
logger.debug("response", factory);
|
||||
expect(factory).toHaveBeenCalledTimes(1);
|
||||
expect(destination.events).toHaveLength(0);
|
||||
await vi.waitFor(() => expect(destination.events).toHaveLength(1));
|
||||
expect(destination.events[0]).toMatchObject({
|
||||
arguments: ["response", { data: 1 }],
|
||||
async: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("unwraps direct Promise arguments and keeps rejection reasons", async () => {
|
||||
const destination = sink();
|
||||
const reason = new Error("boom");
|
||||
const logger = createLogger({ environment: "development", sinks: [destination.sink] });
|
||||
logger.error("failed", { id: 1 }, Promise.reject(reason));
|
||||
expect(destination.events).toHaveLength(0);
|
||||
await vi.waitFor(() => expect(destination.events).toHaveLength(1));
|
||||
expect(destination.events[0]).toMatchObject({
|
||||
arguments: ["failed", { id: 1 }, reason],
|
||||
async: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("applies session namespace filtering to namespace descendants", () => {
|
||||
|
||||
@@ -66,6 +66,21 @@ describe("toSentryLogPayload", () => {
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("includes async when the event was deferred for thenables", () => {
|
||||
expect(
|
||||
toSentryLogPayload({
|
||||
level: "debug",
|
||||
arguments: ["response"],
|
||||
timestamp: new Date(),
|
||||
environment: "development",
|
||||
sendToSentryLogs: true,
|
||||
sendToSentryIssue: false,
|
||||
sendToConsole: true,
|
||||
async: true,
|
||||
}).attributes,
|
||||
).toEqual({ async: true });
|
||||
});
|
||||
});
|
||||
|
||||
describe("createSentrySink", () => {
|
||||
|
||||
Reference in New Issue
Block a user