src.nth.io/

summaryrefslogtreecommitdiff
path: root/src/logging.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/logging.ts')
-rw-r--r--src/logging.ts71
1 files changed, 71 insertions, 0 deletions
diff --git a/src/logging.ts b/src/logging.ts
new file mode 100644
index 0000000..c8c75d7
--- /dev/null
+++ b/src/logging.ts
@@ -0,0 +1,71 @@
+/**
+ * Structured, level-filtered logging for the service's own messages.
+ *
+ * matter.js library logging is configured separately (see controller.ts); this
+ * logger covers service-level events in the format:
+ *
+ * 2026-07-26T20:00:00.100Z INFO controller Connected to Matter node 1
+ */
+
+export const LOG_LEVELS = ["debug", "info", "warn", "error"] as const;
+export type LogLevel = (typeof LOG_LEVELS)[number];
+
+export function isLogLevel(value: unknown): value is LogLevel {
+ return typeof value === "string" && (LOG_LEVELS as readonly string[]).includes(value);
+}
+
+const LEVEL_RANK: Record<LogLevel, number> = { debug: 0, info: 1, warn: 2, error: 3 };
+const LEVEL_LABEL: Record<LogLevel, string> = {
+ debug: "DEBUG",
+ info: "INFO ",
+ warn: "WARN ",
+ error: "ERROR",
+};
+
+let globalLevel: LogLevel = "info";
+
+export function setLogLevel(level: LogLevel): void {
+ globalLevel = level;
+}
+
+export function getLogLevel(): LogLevel {
+ return globalLevel;
+}
+
+function write(level: LogLevel, module: string, message: string): void {
+ if (LEVEL_RANK[level] < LEVEL_RANK[globalLevel]) return;
+ const line = `${new Date().toISOString()} ${LEVEL_LABEL[level]} ${module} ${message}`;
+ if (level === "error" || level === "warn") {
+ process.stderr.write(line + "\n");
+ } else {
+ process.stdout.write(line + "\n");
+ }
+}
+
+/** A logger bound to a module name (e.g. "controller", "sync"). */
+export class Log {
+ constructor(private readonly module: string) {}
+
+ debug(message: string): void {
+ write("debug", this.module, message);
+ }
+
+ info(message: string): void {
+ write("info", this.module, message);
+ }
+
+ warn(message: string): void {
+ write("warn", this.module, message);
+ }
+
+ error(message: string, cause?: unknown): void {
+ write("error", this.module, cause === undefined ? message : `${message}: ${describeError(cause)}`);
+ }
+}
+
+export function describeError(cause: unknown): string {
+ if (cause instanceof Error) {
+ return cause.message;
+ }
+ return String(cause);
+}