chore: replace standard logging with signale

This commit is contained in:
Dries Augustyns
2025-12-10 14:21:42 +01:00
parent 3225c5005b
commit 1430f31e2d
18 changed files with 85 additions and 68 deletions
+4 -3
View File
@@ -1,4 +1,5 @@
import type {Prisma} from '@plunk/db';
import signale from 'signale';
import {prisma} from '../database/prisma.js';
import {redis} from '../database/redis.js';
@@ -178,7 +179,7 @@ export class ActivityService {
return JSON.parse(cached);
}
} catch (error) {
console.warn('[ACTIVITY] Failed to get stats from cache:', error);
signale.warn('[ACTIVITY] Failed to get stats from cache:', error);
}
// Default date range to last 30 days if not specified
@@ -241,7 +242,7 @@ export class ActivityService {
try {
await redis.setex(cacheKey, this.STATS_CACHE_TTL, JSON.stringify(stats));
} catch (error) {
console.warn('[ACTIVITY] Failed to cache stats:', error);
signale.warn('[ACTIVITY] Failed to cache stats:', error);
}
return stats;
@@ -261,7 +262,7 @@ export class ActivityService {
await redis.del(...keys);
}
} catch (error) {
console.warn('[ACTIVITY] Failed to invalidate stats cache:', error);
signale.warn('[ACTIVITY] Failed to invalidate stats cache:', error);
}
}
+3 -2
View File
@@ -1,6 +1,7 @@
import type {Campaign, Contact, Prisma} from '@plunk/db';
import {CampaignAudienceType, CampaignStatus, EmailSourceType} from '@plunk/db';
import type {FilterCondition} from '@plunk/types';
import signale from 'signale';
import {prisma} from '../database/prisma.js';
import {HttpException} from '../exceptions/index.js';
@@ -461,7 +462,7 @@ export class CampaignService {
}
if (campaign.status !== CampaignStatus.SENDING) {
console.warn(`[CAMPAIGN] Campaign ${campaignId} is not in SENDING status, skipping batch ${batchNumber}`);
signale.warn(`[CAMPAIGN] Campaign ${campaignId} is not in SENDING status, skipping batch ${batchNumber}`);
return;
}
@@ -507,7 +508,7 @@ export class CampaignService {
replyTo: campaign.replyTo || undefined,
});
} catch (error) {
console.error(`[CAMPAIGN] Failed to queue email for contact ${contact.id}:`, error);
signale.error(`[CAMPAIGN] Failed to queue email for contact ${contact.id}:`, error);
// Continue with other contacts even if one fails
}
}
+1 -1
View File
@@ -407,7 +407,7 @@ export class EmailService {
sentAt: new Date().toISOString(),
});
} catch (error) {
console.error(`[EMAIL] Failed to send email ${emailId}:`, error);
signale.error(`[EMAIL] Failed to send email ${emailId}:`, error);
// Mark as failed
await prisma.email.update({
+9 -8
View File
@@ -1,6 +1,7 @@
import type {Event} from '@plunk/db';
import {Prisma} from '@plunk/db';
import type {FilterCondition, FilterGroup} from '@plunk/types';
import signale from 'signale';
import {prisma} from '../database/prisma.js';
import {redis} from '../database/redis.js';
@@ -52,7 +53,7 @@ export class EventService {
try {
await redis.del(cacheKey);
} catch (error) {
console.warn('[EVENT] Failed to invalidate workflow cache:', error);
signale.warn('[EVENT] Failed to invalidate workflow cache:', error);
}
}
@@ -331,7 +332,7 @@ export class EventService {
workflows = JSON.parse(cached);
}
} catch (error) {
console.warn('[EVENT] Failed to get workflows from cache:', error);
signale.warn('[EVENT] Failed to get workflows from cache:', error);
}
// If not in cache, fetch from database
@@ -353,7 +354,7 @@ export class EventService {
try {
await redis.setex(cacheKey, 300, JSON.stringify(workflows));
} catch (error) {
console.warn('[EVENT] Failed to cache workflows:', error);
signale.warn('[EVENT] Failed to cache workflows:', error);
}
}
@@ -368,7 +369,7 @@ export class EventService {
} else {
// If event is not contact-specific, you might want different logic
// For example, trigger for all contacts, or skip
console.log(`[EVENT] Event ${eventName} triggered workflow ${workflow.id}, but no contact specified`);
signale.info(`[EVENT] Event ${eventName} triggered workflow ${workflow.id}, but no contact specified`);
}
}
}
@@ -394,7 +395,7 @@ export class EventService {
});
if (!workflow || workflow.steps.length === 0) {
console.error(`[EVENT] Workflow ${workflowId} has no trigger step`);
signale.error(`[EVENT] Workflow ${workflowId} has no trigger step`);
return;
}
@@ -429,7 +430,7 @@ export class EventService {
const triggerStep = workflow.steps[0];
if (!triggerStep) {
console.error(`[EVENT] Workflow ${workflowId} trigger step not found`);
signale.error(`[EVENT] Workflow ${workflowId} trigger step not found`);
return;
}
@@ -444,14 +445,14 @@ export class EventService {
},
});
console.log(
signale.info(
`[EVENT] Started workflow ${workflowId} execution ${execution.id} for contact ${contactId}${workflow.allowReentry ? ' (re-entry allowed)' : ''}`,
);
// Start executing the workflow
await WorkflowExecutionService.processStepExecution(execution.id, triggerStep.id);
} catch (error) {
console.error(`[EVENT] Error starting workflow ${workflowId}:`, error);
signale.error(`[EVENT] Error starting workflow ${workflowId}:`, error);
}
}
+7 -5
View File
@@ -6,6 +6,8 @@ import {
PutBucketPolicyCommand,
} from '@aws-sdk/client-s3';
import crypto from 'crypto';
import signale from 'signale';
import {
S3_ENDPOINT,
S3_ACCESS_KEY_ID,
@@ -69,13 +71,13 @@ export async function initializeBucket(): Promise<void> {
Bucket: S3_BUCKET,
}),
);
console.log(`[S3] Created bucket: ${S3_BUCKET}`);
signale.info(`[S3] Created bucket: ${S3_BUCKET}`);
} catch (createError) {
console.error('[S3] Failed to create bucket:', createError);
signale.error('[S3] Failed to create bucket:', createError);
throw createError;
}
} else {
console.error('[S3] Failed to check bucket:', error);
signale.error('[S3] Failed to check bucket:', error);
throw error;
}
}
@@ -103,10 +105,10 @@ export async function initializeBucket(): Promise<void> {
);
if (!bucketExists) {
console.log(`[S3] Set public read policy for bucket: ${S3_BUCKET}`);
signale.info(`[S3] Set public read policy for bucket: ${S3_BUCKET}`);
}
} catch (policyError) {
console.error('[S3] Failed to set bucket policy:', policyError);
signale.error('[S3] Failed to set bucket policy:', policyError);
// Don't throw - bucket was created but policy failed
}
}
+2 -1
View File
@@ -1,4 +1,5 @@
import {SES} from '@aws-sdk/client-ses';
import signale from 'signale';
import {
AWS_SES_ACCESS_KEY_ID,
@@ -275,7 +276,7 @@ export const getSendingQuota = async (): Promise<{
sentLast24Hours: quota.SentLast24Hours ?? 0,
};
} catch (error) {
console.error('[SES] Failed to fetch sending quota:', error);
signale.error('[SES] Failed to fetch sending quota:', error);
return null;
}
};
+5 -4
View File
@@ -1,5 +1,6 @@
import {type Contact, Prisma, type Segment} from '@plunk/db';
import type {FilterCondition, FilterGroup, SegmentFilter} from '@plunk/types';
import signale from 'signale';
import {prisma} from '../database/prisma.js';
import {HttpException} from '../exceptions/index.js';
@@ -276,7 +277,7 @@ export class SegmentService {
data: {memberCount},
});
} catch (error) {
console.error(`Failed to update count for segment ${segment.id}:`, error);
signale.error(`Failed to update count for segment ${segment.id}:`, error);
}
}),
);
@@ -383,7 +384,7 @@ export class SegmentService {
segmentName: segment.name,
});
} catch (error) {
console.error(`[SEGMENT] Failed to track segment entry event for contact ${contactId}:`, error);
signale.error(`[SEGMENT] Failed to track segment entry event for contact ${contactId}:`, error);
}
}
}
@@ -414,7 +415,7 @@ export class SegmentService {
segmentName: segment.name,
});
} catch (error) {
console.error(`[SEGMENT] Failed to track segment exit event for contact ${contactId}:`, error);
signale.error(`[SEGMENT] Failed to track segment exit event for contact ${contactId}:`, error);
}
}
}
@@ -425,7 +426,7 @@ export class SegmentService {
data: {memberCount: matchingContactIds.size},
});
console.log(
signale.info(
`[SEGMENT] Computed membership for segment ${segmentId}: added ${toAdd.length}, removed ${toRemove.length}, total ${matchingContactIds.size}`,
);
+2 -1
View File
@@ -1,5 +1,6 @@
import type {Workflow, WorkflowExecution, WorkflowStep, WorkflowStepExecution, WorkflowTransition} from '@plunk/db';
import {Prisma, WorkflowExecutionStatus} from '@plunk/db';
import signale from 'signale';
import {prisma} from '../database/prisma.js';
import {HttpException} from '../exceptions/index.js';
@@ -786,7 +787,7 @@ export class WorkflowService {
// Start executing the workflow asynchronously
// Don't await - let it run in background
WorkflowExecutionService.processStepExecution(execution.id, triggerStep.id).catch(error => {
console.error('Error executing workflow:', error);
signale.error('Error executing workflow:', error);
});
return execution;