mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-01-11 19:56:44 +00:00
Some checks are pending
Build / docker-build-accounts (push) Waiting to run
Build / docker-build-isolated-vm (push) Waiting to run
Build / docker-build-home (push) Waiting to run
Build / docker-build-worker (push) Waiting to run
Build / docker-build-workflow (push) Waiting to run
Build / docker-build-api-reference (push) Waiting to run
Build / docker-build-docs (push) Waiting to run
Build / docker-build-otel-collector (push) Waiting to run
Build / docker-build-app (push) Waiting to run
Build / docker-build-copilot (push) Waiting to run
Build / docker-build-e2e (push) Waiting to run
Build / docker-build-admin-dashboard (push) Waiting to run
Build / docker-build-dashboard (push) Waiting to run
Build / docker-build-probe (push) Waiting to run
Compile / compile-accounts (push) Waiting to run
Compile / compile-isolated-vm (push) Waiting to run
Compile / compile-common (push) Waiting to run
Compile / compile-app (push) Waiting to run
Compile / compile-home (push) Waiting to run
Compile / compile-worker (push) Waiting to run
Compile / compile-workflow (push) Waiting to run
Compile / compile-api-reference (push) Waiting to run
Compile / compile-docs-reference (push) Waiting to run
Compile / compile-copilot (push) Waiting to run
Compile / compile-nginx (push) Waiting to run
Compile / compile-infrastructure-agent (push) Waiting to run
Compile / compile-admin-dashboard (push) Waiting to run
Compile / compile-dashboard (push) Waiting to run
Compile / compile-e2e (push) Waiting to run
Compile / compile-probe (push) Waiting to run
Build / docker-build-probe-ingest (push) Waiting to run
Build / docker-build-server-monitor-ingest (push) Waiting to run
Build / docker-build-telemetry (push) Waiting to run
Build / docker-build-incoming-request-ingest (push) Waiting to run
Build / docker-build-status-page (push) Waiting to run
Build / docker-build-test-server (push) Waiting to run
CodeQL / Analyze (push) Waiting to run
Common Jobs / helm-lint (push) Waiting to run
Common Jobs / js-lint (push) Waiting to run
Push Test Images to Docker Hub and GitHub Container Registry / incoming-request-ingest-docker-image-deploy (push) Blocked by required conditions
Compile / compile-probe-ingest (push) Waiting to run
Compile / compile-server-monitor-ingest (push) Waiting to run
Compile / compile-telemetry (push) Waiting to run
Compile / compile-incoming-request-ingest (push) Waiting to run
Compile / compile-status-page (push) Waiting to run
Compile / compile-test-server (push) Waiting to run
Compile / compile-mcp (push) Waiting to run
OpenAPI Spec Generation / generate-openapi-spec (push) Waiting to run
Terraform Provider Generation / generate-terraform-provider (push) Waiting to run
Push Test Images to Docker Hub and GitHub Container Registry / generate-build-number (push) Waiting to run
Push Test Images to Docker Hub and GitHub Container Registry / read-version (push) Waiting to run
Push Test Images to Docker Hub and GitHub Container Registry / publish-mcp-server (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / nginx-docker-image-deploy (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / e2e-docker-image-deploy (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / test-server-docker-image-deploy (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / otel-collector-docker-image-deploy (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / isolated-vm-docker-image-deploy (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / home-docker-image-deploy (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / status-page-docker-image-deploy (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / test-docker-image-deploy (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / probe-ingest-docker-image-deploy (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / server-monitor-ingest-docker-image-deploy (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / telemetry-docker-image-deploy (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / probe-docker-image-deploy (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / dashboard-docker-image-deploy (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / admin-dashboard-docker-image-deploy (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / app-docker-image-deploy (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / api-reference-docker-image-deploy (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / accounts-docker-image-deploy (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / worker-docker-image-deploy (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / copilot-docker-image-deploy (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / workflow-docker-image-deploy (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / docs-docker-image-deploy (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / publish-terraform-provider (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / test-helm-chart (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / test-e2e-test-saas (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / test-e2e-test-self-hosted (push) Blocked by required conditions
Push Test Images to Docker Hub and GitHub Container Registry / infrastructure-agent-deploy (push) Blocked by required conditions
Common Test / test (push) Waiting to run
Incoming Request Ingest Test / test (push) Waiting to run
MCP Server Test / test (push) Waiting to run
ProbeIngest Test / test (push) Waiting to run
Probe Test / test (push) Waiting to run
Telemetry Test / test (push) Waiting to run
Tests / test-app (push) Waiting to run
Tests / test-home (push) Waiting to run
Tests / test-worker (push) Waiting to run
158 lines
4.6 KiB
TypeScript
158 lines
4.6 KiB
TypeScript
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import logger, { LogBody } from "Common/Server/Utils/Logger";
|
|
|
|
/** Supported log levels for the agent-maintained file logs. */
|
|
export type AgentLogLevel = "DEBUG" | "INFO" | "WARN" | "ERROR";
|
|
|
|
/**
|
|
* Extends the shared logger by optionally mirroring output to a persistent file
|
|
* for auditing agent activity.
|
|
*/
|
|
export class AgentLogger {
|
|
private static logStream: fs.WriteStream | null = null;
|
|
private static logFilePath: string | null = null;
|
|
private static exitHandlersRegistered: boolean = false;
|
|
private static fileWriteFailed: boolean = false;
|
|
|
|
/** Enables/disables file logging depending on whether a path is provided. */
|
|
public static async configure(options: {
|
|
logFilePath?: string | undefined;
|
|
}): Promise<void> {
|
|
const targetPath: string | undefined = options.logFilePath?.trim()
|
|
? path.resolve(options.logFilePath)
|
|
: undefined;
|
|
|
|
if (!targetPath) {
|
|
await this.closeStream();
|
|
this.logFilePath = null;
|
|
logger.debug("File logging disabled");
|
|
return;
|
|
}
|
|
|
|
if (this.logFilePath === targetPath && this.logStream) {
|
|
return;
|
|
}
|
|
|
|
await this.closeStream();
|
|
await fs.promises.mkdir(path.dirname(targetPath), { recursive: true });
|
|
|
|
// Remove existing debug file to start fresh for each command run
|
|
try {
|
|
await fs.promises.unlink(targetPath);
|
|
} catch {
|
|
// File doesn't exist, ignore
|
|
}
|
|
|
|
this.logStream = fs.createWriteStream(targetPath, { flags: "w" });
|
|
this.logFilePath = targetPath;
|
|
this.fileWriteFailed = false;
|
|
this.registerExitHandlers();
|
|
this.info(`File logging enabled at ${targetPath}`);
|
|
}
|
|
|
|
/** Writes a debug entry to the console logger and file stream. */
|
|
public static debug(message: LogBody, meta?: unknown): void {
|
|
logger.debug(message);
|
|
this.writeToFile("DEBUG", message, meta);
|
|
}
|
|
|
|
/** Writes an informational entry to the console logger and file stream. */
|
|
public static info(message: LogBody, meta?: unknown): void {
|
|
logger.info(message);
|
|
this.writeToFile("INFO", message, meta);
|
|
}
|
|
|
|
/** Writes a warning entry to the console logger and file stream. */
|
|
public static warn(message: LogBody, meta?: unknown): void {
|
|
logger.warn(message);
|
|
this.writeToFile("WARN", message, meta);
|
|
}
|
|
|
|
/** Writes an error entry to the console logger and file stream. */
|
|
public static error(message: LogBody, meta?: unknown): void {
|
|
logger.error(message);
|
|
this.writeToFile("ERROR", message, meta);
|
|
}
|
|
|
|
/** Closes the file stream if one is currently open. */
|
|
private static async closeStream(): Promise<void> {
|
|
if (!this.logStream) {
|
|
return;
|
|
}
|
|
|
|
await new Promise<void>((resolve: () => void) => {
|
|
this.logStream?.end(resolve);
|
|
});
|
|
|
|
this.logStream = null;
|
|
logger.debug("File logging stream closed");
|
|
}
|
|
|
|
/**
|
|
* Serializes a log entry and safely writes it to the currently configured
|
|
* file stream.
|
|
*/
|
|
private static writeToFile(
|
|
level: AgentLogLevel,
|
|
message: LogBody,
|
|
meta?: unknown,
|
|
): void {
|
|
if (!this.logStream) {
|
|
return;
|
|
}
|
|
|
|
const timestamp: string = new Date().toISOString();
|
|
const serializedMessage: string = logger.serializeLogBody(message);
|
|
const serializedMeta: string | null = this.serializeMeta(meta);
|
|
const line: string = serializedMeta
|
|
? `${timestamp} [${level}] ${serializedMessage} ${serializedMeta}`
|
|
: `${timestamp} [${level}] ${serializedMessage}`;
|
|
|
|
try {
|
|
this.logStream.write(line + "\n");
|
|
} catch (error) {
|
|
if (!this.fileWriteFailed) {
|
|
this.fileWriteFailed = true;
|
|
logger.error(
|
|
`Failed to write logs to ${this.logFilePath ?? "<unknown>"}: ${(error as Error).message}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Converts metadata into a string representation for log lines. */
|
|
private static serializeMeta(meta?: unknown): string | null {
|
|
if (meta === undefined || meta === null) {
|
|
return null;
|
|
}
|
|
|
|
if (typeof meta === "string") {
|
|
return meta;
|
|
}
|
|
|
|
try {
|
|
return JSON.stringify(meta);
|
|
} catch (error) {
|
|
return `"<unserializable meta: ${(error as Error).message}>"`;
|
|
}
|
|
}
|
|
|
|
/** Installs once-only handlers to flush file logs during process exit. */
|
|
private static registerExitHandlers(): void {
|
|
if (this.exitHandlersRegistered) {
|
|
return;
|
|
}
|
|
|
|
const cleanup: () => void = () => {
|
|
void this.closeStream();
|
|
};
|
|
|
|
process.once("exit", cleanup);
|
|
process.once("SIGINT", cleanup);
|
|
process.once("SIGTERM", cleanup);
|
|
this.exitHandlersRegistered = true;
|
|
}
|
|
}
|
|
|
|
export default AgentLogger;
|