This guide explains how to extend the Audit/Insight system: register custom filters for the Insight UI, define new event types, and emit structured audit events from your code. All surfaces described here are stable and safe for use by third-party plugins.
What the audit log is
Order Daemon emits structured audit events whenever rules run, webhooks arrive, security checks pass/fail, etc. These entries power the Insight timeline UI and the REST API used by the dashboards.
As an integrator you can:
- Register additional filter controls for the Insight UI.
- Define and use new event type IDs so your entries render consistently.
- Emit events using the global
odcm_log_event()helper.
All user-visible strings must be internationalized with the order-daemon text domain.
Registering custom Insight filters
Use the FilterRegistry to declare new filters for the Insight UI.
- Class:
OrderDaemonCompletionManagerCoreFilterRegistry(src/Core/FilterRegistry.php) - Pattern: retrieve the singleton instance, then call
register_filter([...]).
Required arguments for register_filter:
id– unique slug (lowercase, snake_case)label– translatable label for the UIrender_callback– callable that renders the filter input
use OrderDaemonCompletionManagerCoreFilterRegistry;
add_action('init', function () {
$registry = odcm_get_filter_registry_instance();
$registry->register_filter([
'id' => 'source',
'label' => __('admin.insight_dashboard.filters.source.label', 'order-daemon'),
'render_callback' => function (array $filter, bool $has_permission, string $current_value): void {
$disabled = $has_permission ? '' : ' disabled';
echo '<select name="source"' . $disabled . '>';
echo '<option value="">' . esc_html__('admin.insight_dashboard.filters.source.any', 'order-daemon') . '</option>';
echo '<option value="rules">' . esc_html__('admin.insight_dashboard.filters.source.rules', 'order-daemon') . '</option>';
echo '<option value="webhook">' . esc_html__('admin.insight_dashboard.filters.source.webhook', 'order-daemon') . '</option>';
echo '</select>';
},
]);
});Notes:
- Use stable i18n string IDs – do not hardcode English.
- Sanitize input server-side if you also implement a query hook.
- The render callback receives: filter array, has_permission boolean, current_value string.
Adding custom event types
To make your events render with consistent titles and statuses, define event types using the registry in src/Core/LogRegistries.php. Adding new types allows the UI to present them with friendly labels and default statuses.
Recommended approach:
- Use existing event types when possible – only introduce new IDs when needed.
- If your integration ships in a separate plugin, maintain your own mapping and use your IDs in
odcm_log_event().
Event type structure:
id– unique slug (e.g.,my_integration_sync)label– translatable title for admin UIsummary_template– sprintf-style template for concise summariesdefault_status– one ofsuccess,warning,error,infocategory–customfor third-party events (Core usescore,debug,premium)
function my_odcm_event_types(): array {
return [
'my_integration_sync' => [
'id' => 'my_integration_sync',
'label' => __('my_integration.sync.label', 'order-daemon'),
'summary_template' => __('my_integration.sync.summary', 'order-daemon'),
'default_status' => 'success',
'category' => 'custom',
],
'my_integration_error' => [
'id' => 'my_integration_error',
'label' => __('my_integration.error.label', 'order-daemon'),
'summary_template' => __('my_integration.error.summary', 'order-daemon'),
'default_status' => 'error',
'category' => 'custom',
],
];
}Emitting audit events
Use the global helper odcm_log_event() (defined in src/Includes/functions.php):
odcm_log_event(
string $summary,
array $data = [],
?int $order_id = null,
string $status = 'info', // success | warning | error | info | notice | debug | critical | pending | skipped | completed
string $event_type = 'event',
bool $is_test = false,
?string $process_id = null,
?string $parent_event_type = null
);Simple log line:
odcm_log_event(
__('my_integration.sync.summary', 'order-daemon'),
['synced' => 3],
$order_id,
'success',
'my_integration_sync'
);Error with context:
odcm_log_event(
__('my_integration.error.summary', 'order-daemon'),
['reason' => 'signature_mismatch', 'webhook_id' => $id],
$order_id,
'error',
'my_integration_error'
);Tips:
- Keep summaries concise; put details in the data array. The Insight detail view renders structured payloads.
- Pass
process_idto correlate related events in the timeline view.
Process timelines and correlation
Order Daemon groups related audit entries into a single process timeline whenever a unit of work runs (a webhook received, a rule evaluated, a batch job executed). Correlate your custom entries by including a stable process_id.
Webhook adapter example:
$event_id = $headers['x-event-id'] ?? null;
odcm_log_event(
__('my_integration.received', 'order-daemon'),
['bytes' => strlen($raw)],
$order_id,
'info',
'my_integration_sync',
false,
$event_id
);WooCommerce status change handler:
$process_id = sprintf('status-change-%d-%s', $order_id, gmdate('YmdHis'));
odcm_log_event(
__('dev.order_status.transition', 'order-daemon'),
['from' => $from, 'to' => $to],
$order_id,
'info',
'custom',
false,
$process_id
);To inspect correlated entries via REST:
GET /wp-json/odcm/v1/audit-log/process/{process_id}Troubleshooting correlation: ensure the exact same process_id value is used across all related odcm_log_event() calls within a single unit of work.
Extending with Pro features
Order Daemon Pro extends the core audit logging system with:
- Log Retention Policy – configurable retention periods and automatic cleanup
- Export Functionality – CSV and JSON export with advanced filtering
- CLI Commands –
wp odcm log export,wp odcm log bulk-delete(see CLI and automation) - Premium Event Types – advanced logging for Pro-specific features
Querying results via REST
The Insight UI uses REST endpoints exposed by Core to list and filter audit entries. When you add a filter control, ensure the server interprets the incoming parameter securely – sanitize with sanitize_text_field, absint, etc. Permission checks are enforced via the plugin’s Guard and WordPress capabilities.
The AuditLogEndpoint controller handles listing, rendering, filter options, and batch deletes.
Troubleshooting
Events appear but have generic labels: Provide event-type-specific labels in your mapping and use those IDs in the event_type argument.
403 on REST endpoints: Permission callbacks enforce admin caps – ensure you are authenticated and have the required nonce/capabilities.
Translations not showing: Ensure the order-daemon text domain is loaded and JSON script translations are registered for admin bundles.