Use loggers
Most of Workleap's frontend platform libraries can produce meaningful logs when provided with logger instances. Once configured, these libraries use a five-level logging system: debug, information, warning, error, and critical.
The following libraries integrate with loggers that implement the RootLogger interface 👇
Log levels
A logger can output log entries with different levels: debug, information, warning, error, critical. This allows to filter logs according to a minimum severity:
import { BrowserConsoleLogger, LogLevel } from "@workleap/logging";
const logger = new BrowserConsoleLogger({
logLevel: LogLevel.error
});
In the previous example, the logger instance would process only error and critical entries ☝️.
For development environments, we generally recommend setting the minimum severity to debug. For production environments, we recommend setting the minimum severity to information. The information level provides a good balance as it is detailed enough for basic troubleshooting, while reducing noise in production.
For reference, here's a description of each level:
Debug
- Very detailed, often verbose, logs used mainly during development.
- Example: API request/response bodies, lifecycle hooks, variable state.
Information
- General events that show the normal flow of the application.
- Example: User login, component mounted, scheduled task started.
Warning
- Non-critical issues that might need attention but don't break functionality.
- Example: Deprecated API usage, retries after a failed network call.
Error
- Failures that prevent part of the system from working as intended.
- Example: Unhandled exceptions, failed database query, API call failed with 500.
Critical
- Severe errors that cause the application to stop functioning or risk data integrity.
- Example: Application crash, loss of critical service connection.
Example
The following example shows how to integrate loggers into a Squide application (loggers are also supported in both React and non-React applications):
import { createRoot } from "react-dom/client";
import { initializeWidgets } from "@workleap-widgets/squide-firefly";
import { initializeFirefly, FireflyProvider } from "@squide/firefly";
import { BrowserConsoleLogger, LogLevel, type RootLogger } from "@workleap/logging";
import { LogRocketLogger, } from "@workleap/logrocket";
import { initializeTelemetry, TelemetryProvider } from "@workleap/telemetry/react";
import { registerCommonRoomInstrumentation } from "@workleap/common-room/react";
// Do not do this, it's only for demo purpose.
const isDev = process.env === "development";
const loggers: RootLogger[] = [isDev ? new BrowserConsoleLogger() : new LogRocketLogger(LogLevel.information)];
const telemetryClient = initializeTelemetry({
logRocket: {
appId: "my-app-id"
},
honeycomb: {
namespace: "sample",
serviceName: "my-app",
apiServiceUrls: [/.+/g],
options: {
proxy: "https://sample-proxy"
}
},
mixpanel: {
productId: "wlp",
envOrTrackingApiBaseUrl: "development"
},
loggers
});
registerCommonRoomInstrumentation("my-site-id", {
loggers
});
// IMPORTANT: Squide loggers are propagated to platform widgets under the hood.
const fireflyRuntime = initializeFirefly({
loggers
});
const widgetsRuntime = initializeWidgets(fireflyRuntime, "wlp", "development", {
colorScheme: "light",
language: "en-US",
widgets: {
fte: {
invitationModal: true
}
}
});
const root = createRoot(document.getElementById("root")!);
root.render(
<FireflyProvider runtime={runtime}>
<TelemetryProvider client={telemetryClient}>
<App />
</TelemetryProvider>
</FireflyProvider>
);
Create the LogRocketLogger instance with a minimum log level of LogLevel.information to reduce noise in production environments.
Troubleshoot a production issue
To troubleshoot an issue in production, remove the LogLevel from the LogRocketLogger constructor options and set the verbose option to true when applicable:
import { createRoot } from "react-dom/client";
import { initializeWidgets } from "@workleap-widgets/squide-firefly";
import { initializeFirefly, FireflyProvider } from "@squide/firefly";
import { BrowserConsoleLogger, type RootLogger } from "@workleap/logging";
import { LogRocketLogger, } from "@workleap/logrocket";
import { initializeTelemetry, TelemetryProvider } from "@workleap/telemetry/react";
import { registerCommonRoomInstrumentation } from "@workleap/common-room/react";
// Do not do this, it's only for demo purpose.
const isDev = process.env === "development";
const loggers: RootLogger[] = [isDev ? new BrowserConsoleLogger() : new LogRocketLogger()];
const telemetryClient = initializeTelemetry({
logRocket: {
appId: "my-app-id"
},
honeycomb: {
namespace: "sample",
serviceName: "my-app",
apiServiceUrls: [/.+/g],
options: {
proxy: "https://sample-proxy"
}
},
mixpanel: {
productId: "wlp",
envOrTrackingApiBaseUrl: "development"
},
verbose: true,
loggers
});
registerCommonRoomInstrumentation("my-site-id", {
verbose: true,
loggers
});
// IMPORTANT: Squide loggers are propagated to platform widgets under the hood.
const fireflyRuntime = initializeFirefly({
loggers
});
const widgetsRuntime = initializeWidgets(fireflyRuntime, "wlp", "development", {
colorScheme: "light",
language: "en-US",
widgets: {
fte: {
invitationModal: true
}
},
verbose: true
});
const root = createRoot(document.getElementById("root")!);
root.render(
<FireflyProvider runtime={runtime}>
<TelemetryProvider client={telemetryClient}>
<App />
</TelemetryProvider>
</FireflyProvider>
);
Application logs
Once loggers are configured, Squide applications can write log entries using the FireflyRuntime instance:
import { useLogger } from "@squide/firefly";
const logger = useLogger();
logger.debug("Hello!");
import { useRuntime } from "@squide/firefly";
const runtime = useRuntime();
runtime.logger.debug("Hello!");
Never log any Personally Identifiable Information (PII).
API responses frequently contain sensitive user data such as names, email addresses, phone numbers, or IDs. Remove all logs outputting API response before deploying to production, as these can expose private information that will be included in session replays.
For debugging, use console.log instead, since its output is not captured in LogRocket session replays.