Skip to main content
Bull provides methods to track progress and log information during job execution.

progress()

progress(progress?: number | object): Promise
Updates a job’s progress if called with an argument. Returns a promise resolving to the current job’s progress if called without an argument.
progress
number | object
Job progress as a number (0-100) or any serializable object representing progress

Setting Progress

You can report progress as a percentage (number) or as a custom object:
queue.process(async (job) => {
  // Report progress as percentage
  await job.progress(10);
  // Do some work...
  
  await job.progress(50);
  // Do more work...
  
  await job.progress(100);
  
  return { success: true };
});

Custom Progress Objects

For more detailed progress tracking, use an object:
queue.process(async (job) => {
  const total = job.data.items.length;
  
  for (let i = 0; i < total; i++) {
    // Process item
    processItem(job.data.items[i]);
    
    // Report detailed progress
    await job.progress({
      processed: i + 1,
      total: total,
      percentage: Math.round(((i + 1) / total) * 100),
      currentItem: job.data.items[i].name
    });
  }
  
  return { success: true };
});

Reading Progress

Call progress() without arguments to read the current progress:
const currentProgress = await job.progress();
console.log('Current progress:', currentProgress);

Listening to Progress Events

queue.on('progress', (job, progress) => {
  console.log(`Job ${job.id} is ${progress}% complete`);
});

// Global progress events (across all workers)
queue.on('global:progress', (jobId, progress) => {
  console.log(`Job ${jobId} is ${progress}% complete`);
});

log()

log(row: string): Promise
Adds a log entry to this specific job. Logs can be retrieved using Queue#getJobLogs().
row
string
required
The log message to add

Adding Logs

queue.process(async (job) => {
  await job.log('Starting job processing');
  
  try {
    await job.log('Fetching data from API...');
    const data = await fetchData(job.data.url);
    
    await job.log(`Received ${data.length} items`);
    
    await job.log('Processing items...');
    const result = await processData(data);
    
    await job.log('Job completed successfully');
    return result;
    
  } catch (error) {
    await job.log(`Error: ${error.message}`);
    throw error;
  }
});

Error Logging

queue.process(async (job) => {
  for (let i = 0; i < job.data.items.length; i++) {
    try {
      await processItem(job.data.items[i]);
      await job.log(`✓ Processed item ${i + 1}`);
    } catch (error) {
      await job.log(`✗ Failed to process item ${i + 1}: ${error.message}`);
    }
  }
});

Queue#getJobLogs()

getJobLogs(jobId: string, start?: number, end?: number): Promise<{
  logs: string[],
  count: number
}>
Retrieves logs for a specific job. Returns an object with the logs and the total count.
jobId
string
required
The ID of the job
start
number
Start index for pagination (default: 0)
end
number
End index for pagination (default: -1, meaning all logs)
logs
string[]
Array of log messages
count
number
Total number of logs (useful for pagination)

Retrieving Logs

// Get all logs for a job
const { logs, count } = await queue.getJobLogs('job-123');
console.log(`Job has ${count} log entries:`);
logs.forEach(log => console.log(log));

Paginated Logs

// Get first 10 logs
const page1 = await queue.getJobLogs('job-123', 0, 9);
console.log(`Showing 10 of ${page1.count} logs:`);
page1.logs.forEach(log => console.log(log));

// Get next 10 logs
const page2 = await queue.getJobLogs('job-123', 10, 19);

Full Example

const queue = new Queue('processing');

queue.process(async (job) => {
  await job.log('Job started');
  await job.progress(0);
  
  const steps = 5;
  for (let i = 1; i <= steps; i++) {
    await job.log(`Step ${i}/${steps}`);
    await performStep(i);
    await job.progress((i / steps) * 100);
  }
  
  await job.log('Job completed');
  return { success: true };
});

// Later, retrieve logs
const job = await queue.add({ data: 'test' });
await job.finished();

const { logs } = await queue.getJobLogs(job.id);
console.log('Job logs:');
logs.forEach(log => console.log(`  ${log}`));

Build docs developers (and LLMs) love