Skip to content

Commit 1ae21ef

Browse files
committed
feat(sdk): add configureLogger method with modeAware option
Replace setCustomLogger() with configureLogger() that accepts LoggerConfig object with customLogger and modeAware options. The modeAware flag controls whether logs are suppressed during replay mode (default: false). Changes: - Add configureLogger(config: LoggerConfig) method to DurableContext - Add LoggerConfig interface with customLogger and modeAware properties - Update createModeAwareLogger to accept modeAwareEnabled parameter - Change default modeAware behavior to false (show logs during replay) - Update all tests to reflect new default behavior - Add logger-test example with file-based logging (local-only tests) - Update documentation: README, API_SPECIFICATION.md with new API - Add TSDoc comments for Logger types and configureLogger method
1 parent efa419a commit 1ae21ef

File tree

20 files changed

+715
-133
lines changed

20 files changed

+715
-133
lines changed

packages/aws-durable-execution-sdk-js-examples/src/examples/logger-example/logger-example.test.ts

Lines changed: 0 additions & 25 deletions
This file was deleted.

packages/aws-durable-execution-sdk-js-examples/src/examples/logger-example/logger-example.ts

Lines changed: 0 additions & 70 deletions
This file was deleted.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { handler } from "./logger-after-callback";
2+
import { createTests } from "../../../utils/test-helper";
3+
import {
4+
InvocationType,
5+
WaitingOperationStatus,
6+
} from "@aws/durable-execution-sdk-js-testing";
7+
8+
createTests({
9+
name: "logger-after-callback",
10+
functionName: "logger-after-callback",
11+
handler,
12+
invocationType: InvocationType.Event,
13+
tests: (runner) => {
14+
it("should log after createCallback in execution mode", async () => {
15+
const executionPromise = runner.run();
16+
17+
const callbackOp = runner.getOperationByIndex(0);
18+
await callbackOp.waitForData(WaitingOperationStatus.STARTED);
19+
await callbackOp.sendCallbackSuccess("test-result");
20+
21+
const execution = await executionPromise;
22+
23+
const result = execution.getResult() as any;
24+
expect(result.message).toBe("Success");
25+
expect(result.callbackId).toBeDefined();
26+
expect(result.result).toBe("test-result");
27+
});
28+
},
29+
});
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { withDurableExecution } from "@aws/durable-execution-sdk-js";
2+
import { ExampleConfig } from "../../../types";
3+
4+
export const config: ExampleConfig = {
5+
name: "Logger After Callback",
6+
description: "Test logger mode switching after createCallback operation",
7+
};
8+
9+
export const handler = withDurableExecution(async (_event, context) => {
10+
context.configureLogger({ modeAware: true });
11+
12+
context.logger.info("Before createCallback");
13+
14+
const [callbackPromise, callbackId] = await context.createCallback<string>();
15+
16+
context.logger.info("After createCallback");
17+
18+
const result = await callbackPromise;
19+
20+
return { message: "Success", callbackId, result };
21+
});
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { handler } from "./logger-after-invoke";
2+
import { createTests } from "../../../utils/test-helper";
3+
4+
createTests({
5+
name: "logger-after-invoke",
6+
functionName: "logger-after-invoke",
7+
handler,
8+
tests: (runner) => {
9+
it("should execute successfully with modeAware logging", async () => {
10+
const execution = await runner.run();
11+
12+
expect(execution.getResult()).toEqual({ message: "Success" });
13+
14+
// Verify step operation was recorded
15+
const stepOp = runner.getOperationByIndex(0);
16+
expect(stepOp.getType()).toBe("STEP");
17+
});
18+
},
19+
});
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { withDurableExecution } from "@aws/durable-execution-sdk-js";
2+
import { ExampleConfig } from "../../../types";
3+
4+
export const config: ExampleConfig = {
5+
name: "Logger After Invoke",
6+
description:
7+
"Test logger mode switching after backend-completed operation (using step as proxy)",
8+
};
9+
10+
export const handler = withDurableExecution(async (_event, context) => {
11+
context.configureLogger({ modeAware: true });
12+
13+
context.logger.info("Before step");
14+
15+
await context.step(async () => {
16+
return { data: "step result" };
17+
});
18+
19+
context.logger.info("After step");
20+
21+
return { message: "Success" };
22+
});
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { handler } from "./logger-after-wait";
2+
import { createTests } from "../../../utils/test-helper";
3+
import * as fs from "fs";
4+
import * as path from "path";
5+
import * as os from "os";
6+
7+
createTests({
8+
name: "logger-after-wait",
9+
functionName: "logger-after-wait",
10+
handler,
11+
tests: (runner, isCloud) => {
12+
if (!isCloud) {
13+
it("should log after wait in execution mode with modeAware=true", async () => {
14+
const logFilePath = path.join(
15+
os.tmpdir(),
16+
`logger-test-${Date.now()}.log`,
17+
);
18+
19+
if (fs.existsSync(logFilePath)) {
20+
fs.unlinkSync(logFilePath);
21+
}
22+
23+
try {
24+
const execution = await runner.run({
25+
payload: { logFilePath, modeAware: true },
26+
});
27+
28+
expect(execution.getResult()).toEqual({ message: "Success" });
29+
30+
const logContent = fs.readFileSync(logFilePath, "utf-8");
31+
const logLines = logContent
32+
.trim()
33+
.split("\n")
34+
.map((line) => JSON.parse(line));
35+
36+
const beforeWaitLogs = logLines.filter(
37+
(log) => log.message === "Before wait",
38+
);
39+
const afterWaitLogs = logLines.filter(
40+
(log) => log.message === "After wait",
41+
);
42+
43+
// With modeAware: true, both logs appear once (execution mode only)
44+
expect(beforeWaitLogs.length).toBe(1);
45+
expect(afterWaitLogs.length).toBe(1);
46+
} finally {
47+
if (fs.existsSync(logFilePath)) {
48+
fs.unlinkSync(logFilePath);
49+
}
50+
}
51+
});
52+
}
53+
54+
it("should execute successfully", async () => {
55+
const execution = await runner.run();
56+
expect(execution.getResult()).toEqual({ message: "Success" });
57+
});
58+
},
59+
});
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { withDurableExecution, Logger } from "@aws/durable-execution-sdk-js";
2+
import { ExampleConfig } from "../../../types";
3+
import * as fs from "fs";
4+
5+
export const config: ExampleConfig = {
6+
name: "Logger After Wait",
7+
description: "Test logger mode switching after wait operation",
8+
};
9+
10+
interface LoggerTestEvent {
11+
logFilePath?: string;
12+
modeAware?: boolean;
13+
}
14+
15+
export const handler = withDurableExecution(
16+
async (event: LoggerTestEvent, context) => {
17+
if (event.logFilePath) {
18+
const fileLogger: Logger = {
19+
log: (level, message, data) => {
20+
fs.appendFileSync(
21+
event.logFilePath!,
22+
JSON.stringify({ level, message, data }) + "\n",
23+
);
24+
},
25+
info: (message, data) => {
26+
fs.appendFileSync(
27+
event.logFilePath!,
28+
JSON.stringify({ level: "info", message, data }) + "\n",
29+
);
30+
},
31+
error: (message, error, data) => {
32+
fs.appendFileSync(
33+
event.logFilePath!,
34+
JSON.stringify({ level: "error", message, error, data }) + "\n",
35+
);
36+
},
37+
warn: (message, data) => {
38+
fs.appendFileSync(
39+
event.logFilePath!,
40+
JSON.stringify({ level: "warn", message, data }) + "\n",
41+
);
42+
},
43+
debug: (message, data) => {
44+
fs.appendFileSync(
45+
event.logFilePath!,
46+
JSON.stringify({ level: "debug", message, data }) + "\n",
47+
);
48+
},
49+
};
50+
51+
context.configureLogger({
52+
customLogger: fileLogger,
53+
modeAware: event.modeAware ?? true,
54+
});
55+
} else {
56+
context.configureLogger({ modeAware: event.modeAware ?? true });
57+
}
58+
59+
context.logger.info("Before wait");
60+
await context.wait({ seconds: 2 });
61+
context.logger.info("After wait");
62+
63+
return { message: "Success" };
64+
},
65+
);

0 commit comments

Comments
 (0)