Skip to content

Commit 1364386

Browse files
committed
test(client): debuggability with console logging
- log extra error from test process to console without mocha redirection - use FLUID_TEST_VERBOSE to control child logging that now optional outputs messaging and select telemetry
1 parent 71f55fd commit 1364386

File tree

3 files changed

+69
-8
lines changed

3 files changed

+69
-8
lines changed

packages/service-clients/end-to-end-tests/azure-client/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@
3535
"test:realsvc:tinylicious": "start-server-and-test start:tinylicious:test 7071 test:realsvc:tinylicious:run",
3636
"test:realsvc:tinylicious:report": "npm run test:realsvc:tinylicious",
3737
"test:realsvc:tinylicious:run": "npm run test:realsvc:azure:run -- --driver=t9s",
38-
"test:realsvc:verbose": "cross-env FLUID_TEST_VERBOSE=1 npm run test:realsvc"
38+
"test:realsvc:verbose": "cross-env FLUID_TEST_VERBOSE=msgs npm run test:realsvc",
39+
"test:realsvc:veryverbose": "cross-env FLUID_TEST_VERBOSE=msgs+telem npm run test:realsvc"
3940
},
4041
"c8": {
4142
"all": true,

packages/service-clients/end-to-end-tests/azure-client/src/test/multiprocess/childClient.ts

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ import {
1010
type AzureContainerServices,
1111
type AzureLocalConnectionConfig,
1212
type AzureRemoteConnectionConfig,
13+
type ITelemetryBaseEvent,
1314
} from "@fluidframework/azure-client";
1415
import { AttachState } from "@fluidframework/container-definitions";
1516
import { ConnectionState } from "@fluidframework/container-loader";
17+
import { LogLevel } from "@fluidframework/core-interfaces";
1618
import type { ScopeType } from "@fluidframework/driver-definitions/legacy";
1719
import type { ContainerSchema, IFluidContainer } from "@fluidframework/fluid-static";
1820
import {
@@ -37,6 +39,7 @@ type MessageToParent = Required<MessageFromChild>;
3739
const connectTimeoutMs = 10_000;
3840
// Identifier given to child process
3941
const process_id = process.argv[2];
42+
const verbosity = process.argv[3] ?? "";
4043

4144
const useAzure = process.env.FLUID_CLIENT === "azure";
4245
const tenantId = useAzure
@@ -47,6 +50,24 @@ if (useAzure && endPoint === undefined) {
4750
throw new Error("Azure Fluid Relay service endpoint is missing");
4851
}
4952

53+
function selectiveVerboseLog(event: ITelemetryBaseEvent, logLevel?: LogLevel): void {
54+
if (event.eventName.includes(":Signal") || event.eventName.includes(":Join")) {
55+
console.log(`[${process_id}] [${logLevel ?? LogLevel.default}]`, {
56+
eventName: event.eventName,
57+
details: event.details,
58+
containerConnectionState: event.containerConnectionState,
59+
});
60+
} else if (
61+
event.eventName.includes(":Container:") ||
62+
event.eventName.includes(":Presence:")
63+
) {
64+
console.log(`[${process_id}] [${logLevel ?? LogLevel.default}]`, {
65+
eventName: event.eventName,
66+
containerConnectionState: event.containerConnectionState,
67+
});
68+
}
69+
}
70+
5071
/**
5172
* Get or create a Fluid container with Presence in initialObjects.
5273
*/
@@ -81,7 +102,12 @@ const getOrCreatePresenceContainer = async (
81102
endpoint: "http://localhost:7071",
82103
type: "local",
83104
};
84-
const client = new AzureClient({ connection: connectionProps });
105+
const client = new AzureClient({
106+
connection: connectionProps,
107+
logger: {
108+
send: verbosity.includes("telem") ? selectiveVerboseLog : () => {},
109+
},
110+
});
85111
const schema: ContainerSchema = {
86112
initialObjects: {
87113
// A DataObject is added as otherwise fluid-static complains "Container cannot be initialized without any DataTypes"
@@ -120,7 +146,14 @@ const getOrCreatePresenceContainer = async (
120146
};
121147
function createSendFunction(): (msg: MessageToParent) => void {
122148
if (process.send) {
123-
return process.send.bind(process);
149+
const sendFn = process.send.bind(process);
150+
if (verbosity.includes("msgs")) {
151+
return (msg: MessageToParent) => {
152+
console.log(`[${process_id}] Sending`, msg);
153+
sendFn(msg);
154+
};
155+
}
156+
return sendFn;
124157
}
125158
throw new Error("process.send is not defined");
126159
}
@@ -262,6 +295,9 @@ class MessageHandler {
262295
}
263296

264297
public async onMessage(msg: MessageFromParent): Promise<void> {
298+
if (verbosity.includes("msgs")) {
299+
console.log(`[${process_id}] Received`, msg);
300+
}
265301
switch (msg.command) {
266302
case "ping": {
267303
this.handlePing();

packages/service-clients/end-to-end-tests/azure-client/src/test/multiprocess/orchestratorUtils.ts

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,27 @@ import type {
1818
LatestMapValueGetResponseEvent,
1919
} from "./messageTypes.js";
2020

21+
/**
22+
* Child process to console logging verbosity
23+
*
24+
* @remarks
25+
* Meaningful substrings:
26+
* - "msgs"
27+
* - "telem"
28+
*
29+
* @example "msgs+telem"
30+
*/
31+
const childLoggingVerbosity = process.env.FLUID_TEST_VERBOSE ?? "none";
32+
33+
/**
34+
* Capture console./warn/error before test infrastructure alters it.
35+
*/
36+
const testConsole = {
37+
log: console.log,
38+
warn: console.warn,
39+
error: console.error,
40+
};
41+
2142
/**
2243
* Fork child processes to simulate multiple Fluid clients.
2344
*
@@ -44,7 +65,8 @@ export async function forkChildProcesses(
4465
const childErrorPromises: Promise<never>[] = [];
4566
for (let i = 0; i < numProcesses; i++) {
4667
const child = fork("./lib/test/multiprocess/childClient.js", [
47-
`child${i}` /* identifier passed to child process */,
68+
`child ${i}` /* identifier passed to child process */,
69+
childLoggingVerbosity /* console logging verbosity */,
4870
]);
4971
cleanUpAccumulator.push(() => {
5072
child.kill();
@@ -189,12 +211,14 @@ export async function connectAndWaitForAttendees(
189211
});
190212
});
191213
const connectResult = await connectChildProcesses(children, childConnectTimeoutMs);
192-
Promise.all(connectResult.attendeeIdPromises).catch((error) => {
193-
console.error("Error connecting children:", error);
194-
});
214+
Promise.all(connectResult.attendeeIdPromises)
215+
.then(() => console.log("All attendees connected."))
216+
.catch((error) => {
217+
testConsole.error("Error connecting children:", error);
218+
});
195219
await timeoutAwait(Promise.race([attendeeConnectedPromise, earlyExitPromise]), {
196220
durationMs: attendeesJoinedTimeoutMs,
197-
errorMsg: "did not receive all 'attendeeConnected' events",
221+
errorMsg: "child 0 did not receive all 'attendeeConnected' events",
198222
});
199223
return connectResult;
200224
}

0 commit comments

Comments
 (0)