4 Commits

Author SHA1 Message Date
25d42b4653 0.0.36 2025-09-09 13:52:11 +02:00
73c8c20c4b Improve logging system with environment variable control
- Change default log level to 'warn' for production
- Add PAYLOAD_AUTOMATION_LOG_LEVEL environment variable
- Remove all verbose config-phase logs
- Add documentation for log level control
2025-09-09 13:52:06 +02:00
e138176878 0.0.35 2025-09-09 12:47:47 +02:00
6245a71516 Remove all debugging and verbose logs for production
- Remove detailed trigger matching debug logs
- Remove verbose config initialization console output
- Clean up all 🚨 console.log debugging statements
- Change overly verbose logs to debug level
- Production-ready clean logging output
- Maintain essential error logging and workflow execution info
2025-09-09 12:46:37 +02:00
8 changed files with 67 additions and 70 deletions

View File

@@ -155,6 +155,34 @@ Use JSONPath to access workflow data:
- Node.js ^18.20.2 || >=20.9.0 - Node.js ^18.20.2 || >=20.9.0
- pnpm ^9 || ^10 - pnpm ^9 || ^10
## Environment Variables
Control plugin logging with these environment variables:
### `PAYLOAD_AUTOMATION_LOG_LEVEL`
Controls both configuration-time and runtime logging.
- **Values**: `silent`, `error`, `warn`, `info`, `debug`, `trace`
- **Default**: `warn`
- **Example**: `PAYLOAD_AUTOMATION_LOG_LEVEL=debug`
### `PAYLOAD_AUTOMATION_CONFIG_LOG_LEVEL` (optional)
Override log level specifically for configuration-time logs (plugin setup).
- **Values**: Same as above
- **Default**: Falls back to `PAYLOAD_AUTOMATION_LOG_LEVEL` or `warn`
- **Example**: `PAYLOAD_AUTOMATION_CONFIG_LOG_LEVEL=silent`
### Production Usage
For production, keep the default (`warn`) or use `error` or `silent`:
```bash
PAYLOAD_AUTOMATION_LOG_LEVEL=error npm start
```
### Development Usage
For debugging, use `debug` or `info`:
```bash
PAYLOAD_AUTOMATION_LOG_LEVEL=debug npm run dev
```
## Documentation ## Documentation
Full documentation coming soon. For now, explore the development environment in the repository for examples and patterns. Full documentation coming soon. For now, explore the development environment in the repository for examples and patterns.

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "@xtr-dev/payload-workflows", "name": "@xtr-dev/payload-workflows",
"version": "0.0.34", "version": "0.0.36",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@xtr-dev/payload-workflows", "name": "@xtr-dev/payload-workflows",
"version": "0.0.34", "version": "0.0.36",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"jsonpath-plus": "^10.3.0", "jsonpath-plus": "^10.3.0",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@xtr-dev/payload-automation", "name": "@xtr-dev/payload-automation",
"version": "0.0.34", "version": "0.0.36",
"description": "PayloadCMS Automation Plugin - Comprehensive workflow automation system with visual workflow building, execution tracking, and step types", "description": "PayloadCMS Automation Plugin - Comprehensive workflow automation system with visual workflow building, execution tracking, and step types",
"license": "MIT", "license": "MIT",
"type": "module", "type": "module",

View File

@@ -990,12 +990,6 @@ export class WorkflowExecutor {
previousDoc: unknown, previousDoc: unknown,
req: PayloadRequest req: PayloadRequest
): Promise<void> { ): Promise<void> {
console.log('🚨 EXECUTOR: executeTriggeredWorkflows called!')
console.log('🚨 EXECUTOR: Collection =', collection)
console.log('🚨 EXECUTOR: Operation =', operation)
console.log('🚨 EXECUTOR: Doc ID =', (doc as any)?.id)
console.log('🚨 EXECUTOR: Has payload?', !!this.payload)
console.log('🚨 EXECUTOR: Has logger?', !!this.logger)
this.logger.info({ this.logger.info({
collection, collection,
@@ -1029,24 +1023,11 @@ export class WorkflowExecutor {
} }
}> }>
this.logger.info({ this.logger.debug({
workflowId: workflow.id, workflowId: workflow.id,
workflowName: workflow.name, workflowName: workflow.name,
triggerCount: triggers?.length || 0, triggerCount: triggers?.length || 0
triggers: triggers?.map(t => ({ }, 'Checking workflow triggers')
type: t.type,
parameters: t.parameters,
collection: t.parameters?.collection,
collectionSlug: t.parameters?.collectionSlug,
operation: t.parameters?.operation,
// Debug matching criteria
typeMatch: t.type === 'collection-trigger',
collectionMatch: (t.parameters?.collection === collection || t.parameters?.collectionSlug === collection),
operationMatch: t.parameters?.operation === operation
})),
targetCollection: collection,
targetOperation: operation
}, 'Checking workflow triggers with detailed matching info')
const matchingTriggers = triggers?.filter(trigger => const matchingTriggers = triggers?.filter(trigger =>
trigger.type === 'collection-trigger' && trigger.type === 'collection-trigger' &&
@@ -1090,18 +1071,13 @@ export class WorkflowExecutor {
// Check trigger condition if present // Check trigger condition if present
if (trigger.condition) { if (trigger.condition) {
this.logger.info({ this.logger.debug({
collection, collection,
operation, operation,
condition: trigger.condition, condition: trigger.condition,
docId: (doc as any)?.id,
docFields: doc ? Object.keys(doc) : [],
previousDocId: (previousDoc as any)?.id,
workflowId: workflow.id, workflowId: workflow.id,
workflowName: workflow.name, workflowName: workflow.name
docStatus: (doc as any)?.status, }, 'Evaluating trigger condition')
previousDocStatus: (previousDoc as any)?.status
}, 'Evaluating trigger condition before execution')
const conditionMet = this.evaluateCondition(trigger.condition, context) const conditionMet = this.evaluateCondition(trigger.condition, context)

View File

@@ -145,7 +145,6 @@ export const workflowsPlugin =
// CRITICAL: Modify existing collection configs BEFORE PayloadCMS processes them // CRITICAL: Modify existing collection configs BEFORE PayloadCMS processes them
// This is the ONLY time we can add hooks that will actually work // This is the ONLY time we can add hooks that will actually work
const logger = getConfigLogger() const logger = getConfigLogger()
logger.info('Attempting to modify collection configs before PayloadCMS initialization...')
if (config.collections && pluginOptions.collectionTriggers) { if (config.collections && pluginOptions.collectionTriggers) {
for (const [triggerSlug, triggerConfig] of Object.entries(pluginOptions.collectionTriggers)) { for (const [triggerSlug, triggerConfig] of Object.entries(pluginOptions.collectionTriggers)) {
@@ -159,7 +158,6 @@ export const workflowsPlugin =
} }
const collection = config.collections[collectionIndex] const collection = config.collections[collectionIndex]
logger.debug(`Found collection '${triggerSlug}' - modifying its hooks...`)
// Initialize hooks if needed // Initialize hooks if needed
if (!collection.hooks) { if (!collection.hooks) {
@@ -266,7 +264,6 @@ export const workflowsPlugin =
// Add the hook to the collection config // Add the hook to the collection config
collection.hooks.afterChange.push(automationHook) collection.hooks.afterChange.push(automationHook)
logger.debug(`Added automation hook to '${triggerSlug}' - hook count: ${collection.hooks.afterChange.length}`)
} }
} }
@@ -275,17 +272,13 @@ export const workflowsPlugin =
} }
const configLogger = getConfigLogger() const configLogger = getConfigLogger()
configLogger.debug(`Configuring workflow plugin with ${Object.keys(pluginOptions.collectionTriggers || {}).length} collection triggers`)
// Generate cron tasks for workflows with cron triggers // Generate cron tasks for workflows with cron triggers
generateCronTasks(config) generateCronTasks(config)
for (const step of pluginOptions.steps) { for (const step of pluginOptions.steps) {
if (!config.jobs?.tasks?.find(task => task.slug === step.slug)) { if (!config.jobs?.tasks?.find(task => task.slug === step.slug)) {
configLogger.debug(`Registering task: ${step.slug}`)
config.jobs?.tasks?.push(step) config.jobs?.tasks?.push(step)
} else {
configLogger.debug(`Task ${step.slug} already registered, skipping`)
} }
} }
@@ -295,11 +288,9 @@ export const workflowsPlugin =
// Set up onInit to register collection hooks and initialize features // Set up onInit to register collection hooks and initialize features
const incomingOnInit = config.onInit const incomingOnInit = config.onInit
config.onInit = async (payload) => { config.onInit = async (payload) => {
configLogger.info(`onInit called - collections: ${Object.keys(payload.collections).length}`)
// Execute any existing onInit functions first // Execute any existing onInit functions first
if (incomingOnInit) { if (incomingOnInit) {
configLogger.debug('Executing existing onInit function')
await incomingOnInit(payload) await incomingOnInit(payload)
} }
@@ -311,10 +302,8 @@ export const workflowsPlugin =
logger.info(`Plugin configuration: ${Object.keys(pluginOptions.collectionTriggers || {}).length} collection triggers, ${pluginOptions.steps?.length || 0} steps`) logger.info(`Plugin configuration: ${Object.keys(pluginOptions.collectionTriggers || {}).length} collection triggers, ${pluginOptions.steps?.length || 0} steps`)
// Create workflow executor instance // Create workflow executor instance
console.log('🚨 CREATING WORKFLOW EXECUTOR INSTANCE') logger.debug('Creating workflow executor instance')
const executor = new WorkflowExecutor(payload, logger) const executor = new WorkflowExecutor(payload, logger)
console.log('🚨 EXECUTOR CREATED:', typeof executor)
console.log('🚨 EXECUTOR METHODS:', Object.getOwnPropertyNames(Object.getPrototypeOf(executor)))
// Register executor with proper dependency injection // Register executor with proper dependency injection
setWorkflowExecutor(executor, logger) setWorkflowExecutor(executor, logger)

View File

@@ -40,13 +40,6 @@ export function initCollectionHooks<T extends string>(pluginOptions: WorkflowsPl
collection.config.hooks.afterChange.push(async (change) => { collection.config.hooks.afterChange.push(async (change) => {
const operation = change.operation as 'create' | 'update' const operation = change.operation as 'create' | 'update'
// AGGRESSIVE LOGGING - this should ALWAYS appear
console.log('🚨 AUTOMATION PLUGIN HOOK CALLED! 🚨')
console.log('Collection:', change.collection.slug)
console.log('Operation:', operation)
console.log('Doc ID:', change.doc?.id)
console.log('Has executor?', !!executor)
console.log('Executor type:', typeof executor)
logger.info({ logger.info({
slug: change.collection.slug, slug: change.collection.slug,
@@ -55,10 +48,9 @@ export function initCollectionHooks<T extends string>(pluginOptions: WorkflowsPl
previousDocId: change.previousDoc?.id, previousDocId: change.previousDoc?.id,
hasExecutor: !!executor, hasExecutor: !!executor,
executorType: typeof executor executorType: typeof executor
}, 'AUTOMATION PLUGIN: Collection hook triggered') }, 'Collection automation hook triggered')
try { try {
console.log('🚨 About to call executeTriggeredWorkflows')
// Execute workflows for this trigger // Execute workflows for this trigger
await executor.executeTriggeredWorkflows( await executor.executeTriggeredWorkflows(
@@ -69,15 +61,13 @@ export function initCollectionHooks<T extends string>(pluginOptions: WorkflowsPl
change.req change.req
) )
console.log('🚨 executeTriggeredWorkflows completed without error')
logger.info({ logger.info({
slug: change.collection.slug, slug: change.collection.slug,
operation, operation,
docId: change.doc?.id docId: change.doc?.id
}, 'AUTOMATION PLUGIN: executeTriggeredWorkflows completed successfully') }, 'Workflow execution completed successfully')
} catch (error) { } catch (error) {
console.log('🚨 AUTOMATION PLUGIN ERROR:', error)
logger.error({ logger.error({
slug: change.collection.slug, slug: change.collection.slug,

View File

@@ -7,8 +7,6 @@ export function initWebhookEndpoint(config: Config, webhookPrefix = 'webhook'):
const logger = getConfigLogger() const logger = getConfigLogger()
// Ensure the prefix starts with a slash // Ensure the prefix starts with a slash
const normalizedPrefix = webhookPrefix.startsWith('/') ? webhookPrefix : `/${webhookPrefix}` const normalizedPrefix = webhookPrefix.startsWith('/') ? webhookPrefix : `/${webhookPrefix}`
logger.debug(`Adding webhook endpoint to config with prefix: ${normalizedPrefix}`)
logger.debug('Current config.endpoints length:', config.endpoints?.length || 0)
// Define webhook endpoint // Define webhook endpoint
const webhookEndpoint = { const webhookEndpoint = {
@@ -171,9 +169,5 @@ export function initWebhookEndpoint(config: Config, webhookPrefix = 'webhook'):
if (!existingEndpoint) { if (!existingEndpoint) {
// Combine existing endpoints with the webhook endpoint // Combine existing endpoints with the webhook endpoint
config.endpoints = [...(config.endpoints || []), webhookEndpoint] config.endpoints = [...(config.endpoints || []), webhookEndpoint]
logger.debug(`Webhook endpoint added at path: ${webhookEndpoint.path}`)
logger.debug('New config.endpoints length:', config.endpoints.length)
} else {
logger.debug(`Webhook endpoint already exists at path: ${webhookEndpoint.path}`)
} }
} }

View File

@@ -3,25 +3,40 @@ import type { Payload } from 'payload'
// Global logger instance - use Payload's logger type // Global logger instance - use Payload's logger type
let pluginLogger: null | Payload['logger'] = null let pluginLogger: null | Payload['logger'] = null
/**
* Get the configured log level from environment variables
* Supports: PAYLOAD_AUTOMATION_LOG_LEVEL for unified control
* Or separate: PAYLOAD_AUTOMATION_CONFIG_LOG_LEVEL and PAYLOAD_AUTOMATION_LOG_LEVEL
*/
function getConfigLogLevel(): string {
return process.env.PAYLOAD_AUTOMATION_CONFIG_LOG_LEVEL ||
process.env.PAYLOAD_AUTOMATION_LOG_LEVEL ||
'warn' // Default to warn level for production
}
/** /**
* Simple config-time logger for use during plugin configuration * Simple config-time logger for use during plugin configuration
* Uses console with plugin prefix since Payload logger isn't available yet * Uses console with plugin prefix since Payload logger isn't available yet
*/ */
const configLogger = { const configLogger = {
debug: <T>(message: string, ...args: T[]) => { debug: <T>(message: string, ...args: T[]) => {
if (!process.env.PAYLOAD_AUTOMATION_CONFIG_LOGGING) {return} const level = getConfigLogLevel()
console.log(`[payload-automation] ${message}`, ...args) if (level === 'silent' || (level !== 'debug' && level !== 'trace')) {return}
console.debug(`[payload-automation] ${message}`, ...args)
}, },
error: <T>(message: string, ...args: T[]) => { error: <T>(message: string, ...args: T[]) => {
if (!process.env.PAYLOAD_AUTOMATION_CONFIG_LOGGING) {return} const level = getConfigLogLevel()
if (level === 'silent') {return}
console.error(`[payload-automation] ${message}`, ...args) console.error(`[payload-automation] ${message}`, ...args)
}, },
info: <T>(message: string, ...args: T[]) => { info: <T>(message: string, ...args: T[]) => {
if (!process.env.PAYLOAD_AUTOMATION_CONFIG_LOGGING) {return} const level = getConfigLogLevel()
console.log(`[payload-automation] ${message}`, ...args) if (level === 'silent' || level === 'error' || level === 'warn') {return}
console.info(`[payload-automation] ${message}`, ...args)
}, },
warn: <T>(message: string, ...args: T[]) => { warn: <T>(message: string, ...args: T[]) => {
if (!process.env.PAYLOAD_AUTOMATION_CONFIG_LOGGING) {return} const level = getConfigLogLevel()
if (level === 'silent' || level === 'error') {return}
console.warn(`[payload-automation] ${message}`, ...args) console.warn(`[payload-automation] ${message}`, ...args)
} }
} }
@@ -39,8 +54,13 @@ export function getConfigLogger() {
*/ */
export function initializeLogger(payload: Payload): Payload['logger'] { export function initializeLogger(payload: Payload): Payload['logger'] {
// Create a child logger with plugin identification // Create a child logger with plugin identification
// Use PAYLOAD_AUTOMATION_LOG_LEVEL as the primary env var
const logLevel = process.env.PAYLOAD_AUTOMATION_LOG_LEVEL ||
process.env.PAYLOAD_AUTOMATION_LOGGING || // Legacy support
'warn' // Default to warn level for production
pluginLogger = payload.logger.child({ pluginLogger = payload.logger.child({
level: process.env.PAYLOAD_AUTOMATION_LOGGING || 'silent', level: logLevel,
plugin: '@xtr-dev/payload-automation' plugin: '@xtr-dev/payload-automation'
}) })
return pluginLogger return pluginLogger