Scheduled Actions, also known as cron jobs, are one of the most important automation tools within Odoo. They execute tasks in the background, like emails, record updates, reporting, data synchronization, and business workflows.
Although cron jobs are useful in automating business processes, Odoo lacks tools that allow monitoring the performance of these jobs. When there is a problem with your cron job (it fails or takes too much time), you may face difficulties in pinpointing the root cause of the problem.
Why Monitor Cron Jobs?
Consider an action that is scheduled to:
- Send invoices to customers
- Check inventory balances
- Update data externally
- Send out reminders automatically
If any of these jobs fail unnoticed, then there would be trouble within the business process.
Monitoring will enable you to:
- Detect any failures
- Know how fast it runs
- Discover any jobs that take too long
Solution Overview
Our approach will be to develop a specific module named cron_monitoring to track each occurrence of a cron task. The solution involves:
- Log model that will hold the history of execution
- Logic to track the activity of cron tasks
- UI elements for viewing the logs directly in Odoo
Step 1: Create a Log Model
First, create a model that stores information about every cron execution.
from odoo import models, fields, api
class CronLog(models.Model):
_name = 'cron.log'
_description = 'Execution Audit Log'
_order = 'start_time desc'
cron_id = fields.Many2one('ir.cron', string='Scheduled Action', ondelete='cascade', required=True)
start_time = fields.Datetime(string='Start Timestamp', default=fields.Datetime.now)
end_time = fields.Datetime(string='End Timestamp')
# Precise duration calculation for performance benchmarking
duration = fields.Float(string='Duration (Sec)', compute='_compute_duration', store=True)
status = fields.Selection([
('success', 'Successful'),
('fail', 'Failed')
], string='Execution Status')
error_message = fields.Text(string='Incident Details / Traceback')
user_id = fields.Many2one('res.users', string='Triggered By', default=lambda self: self.env.user)
@api.depends('start_time', 'end_time')
def _compute_duration(self):
for log in self:
if log.start_time and log.end_time:
log.duration = (log.end_time - log.start_time).total_seconds()
What Does This Model Store?
Each log entry contains critical information regarding the execution of the cron job:
- Scheduled Action - Shows the cron job that was executed.
- Start Time - Shows the date and time at which the cron job began execution.
- End Time - Shows the date and time at which the cron job execution ends.
- Duration - Automatically records the duration of the cron job in seconds for determining slow cron jobs.
- Status - Tells the status of the cron job execution to determine its success or failure.
- Error Message - Contains the error message that occurred due to any exception in the execution of the cron job.
- Executed By - Shows the user who executed the cron job.
Step 2: Capture Cron Executions
In this solution, we extend the model of ir.cron provided by Odoo to include logging for the execution process. An entry is made at the beginning of a cron, with updates on its status as well as errors encountered, if any. The log is then closed with the end date and the total duration of the execution process.
from odoo import models, fields
import traceback
class IrCron(models.Model):
_inherit = 'ir.cron'
def _callback(self, cron_name, server_action_id, job_id):
log_obj = self.env['cron.log'].sudo()
log = log_obj.create({
'cron_id': job_id,
'start_time': fields.Datetime.now(),
})
try:
super()._callback(cron_name, server_action_id, job_id)
log.write({
'end_time': fields.Datetime.now(),
'status': 'success',
})
except Exception:
log.write({
'end_time': fields.Datetime.now(),
'status': 'fail',
'error_message': traceback.format_exc(),
})
raise
Step 3: Add a User Interface
Monitoring data is only useful if users can easily access it.
<record id="action_cron_log" model="ir.actions.act_window">
<field name="name">Audit Logs</field>
<field name="res_model">cron.log</field>
<field name="view_mode">list,form</field>
</record>
This defines the action that the smart button triggers. It tells Odoo to open the cron.log model in list and form view, displaying all execution logs.
We can add a Smart Button to the Scheduled Action form view that opens all related execution logs.
<record id="view_ir_cron_form_inherit_cron_log" model="ir.ui.view">
<field name="name">ir.cron.form.inherit.cron.log</field>
<field name="model">ir.cron</field>
<field name="inherit_id" ref="base.ir_cron_view_form"/>
<field name="arch" type="xml">
<xpath expr="//div[hasclass('oe_button_box')]" position="inside">
<button name="%(action_cron_log)d" type="action" class="oe_stat_button" icon="fa-list" context="{'search_default_cron_id': active_id}">
<div class="o_field_widget o_stat_info">
<span class="o_stat_text">Audit Logs</span>
</div>
</button>
</xpath>
</field>
</record>
With this button, administrators can open execution history directly from a cron record and quickly review past runs.
Odoo Cron jobs are an important element of automation processes in the Odoo environment; at the same time, monitoring such Cron jobs is an equally important matter.
By using the Cron Monitoring Framework, one would gain better knowledge about automation processes, spot failures quickly, and boost the stability of their Odoo environment.
Thus, the proposed framework provides an opportunity to make cron jobs visible in the Odoo environment.
To read more about How to Monitor Cron Failures in Odoo 19, refer to our blog How to Monitor Cron Failures in Odoo 19.