feat: Add centralized logging system with @link-stack/logger package

- Create new @link-stack/logger package wrapping Pino for structured logging
- Replace all console.log/error/warn statements across the monorepo
- Configure environment-aware logging (pretty-print in dev, JSON in prod)
- Add automatic redaction of sensitive fields (passwords, tokens, etc.)
- Remove dead commented-out logger file from bridge-worker
- Follow Pino's standard argument order (context object first, message second)
- Support log levels via LOG_LEVEL environment variable
- Export TypeScript types for better IDE support

This provides consistent, structured logging across all applications
and packages, making debugging easier and production logs more parseable.
This commit is contained in:
Darren Clarke 2025-08-20 11:37:39 +02:00
parent 5b89bfce7c
commit c1feaa4cb1
42 changed files with 3824 additions and 2422 deletions

View file

@ -1,6 +1,9 @@
import { db, getWorkerUtils } from "@link-stack/bridge-common";
import { createLogger } from "@link-stack/logger";
import * as signalApi from "@link-stack/signal-api";
const logger = createLogger('fetch-signal-messages');
const { Configuration, MessagesApi, AttachmentsApi } = signalApi;
const config = new Configuration({
basePath: process.env.BRIDGE_SIGNAL_URL,
@ -59,8 +62,7 @@ const processMessage = async ({
const { attachments } = dataMessage;
const rawTimestamp = dataMessage?.timestamp;
// Debug logging for group detection
console.log(`[fetch-signal-messages] Processing message:`, {
logger.debug({
sourceUuid,
source,
rawTimestamp,
@ -71,7 +73,7 @@ const processMessage = async ({
groupV2Id: dataMessage?.groupV2?.id,
groupContextType: dataMessage?.groupContext?.type,
groupInfoType: dataMessage?.groupInfo?.type,
});
}, 'Processing message');
const timestamp = new Date(rawTimestamp);
const formattedAttachments = await fetchAttachments(attachments);
@ -148,9 +150,7 @@ const fetchSignalMessagesTask = async ({
number: phoneNumber,
});
console.log(
`[fetch-signal-messages] Fetching messages for bot ${id} (${phoneNumber})`,
);
logger.debug({ botId: id, phoneNumber }, 'Fetching messages for bot');
for (const message of messages) {
const formattedMessages = await processMessage({
@ -160,14 +160,14 @@ const fetchSignalMessagesTask = async ({
});
for (const formattedMessage of formattedMessages) {
if (formattedMessage.to !== formattedMessage.from) {
console.log(`[fetch-signal-messages] Creating job for message:`, {
logger.debug({
messageId: formattedMessage.messageId,
from: formattedMessage.from,
to: formattedMessage.to,
isGroup: formattedMessage.isGroup,
hasMessage: !!formattedMessage.message,
hasAttachment: !!formattedMessage.attachment,
});
}, 'Creating job for message');
await worker.addJob(
"signal/receive-signal-message",