Error Rate Monitor
Summarizes errors by route, severity, time period, and trend.
Function signature
ogCalculateErrorRateSummary(records = array(), options = array())
Categories
- SEO and Routing
Parameters
recordsError records with route, severity, and timestamp keys.optionsReport options: total_requests, bucket_format. Recognized keys: `bucket_format`, `total_requests`.Return value
Short public-safe status message.
- total_errors
- total_requests
- error_rate_percent
- by_route
- by_severity
- by_bucket
Compatibility
Existing function name and call order preserved; metadata signature corrected to source.
Minimum PHP version: 7.4
Security notes
Validate request method, identity, permissions, policy arrays, URLs, signatures, and caller-owned allowlists before use; keep secrets and internal paths out of public output.
Code
<?php
/*
* Copyright (c) 2026 Jeffery L. Paris <jparis@phpog.com>.
* Free for personal and internal use. Paid project use requires visible credit
* to Jeffery L. Paris. Corporate use requires a paid license fee unless a
* separate written license states otherwise.
*/
/**
* Summarizes application error records by route, severity, and time bucket.
*
* This helper redacts obvious token-like values from route strings before
* building the report so diagnostics remain useful without exposing secrets.
*
* @param array $records Error records with route, severity, and timestamp keys.
* @param array $options Report options: total_requests, bucket_format.
* @return array Structured error-rate summary.
*/
function ogCalculateErrorRateSummary($records = array(), $options = array()) {
$result = array(
'success' => false,
'message' => '',
'data' => array()
);
if (!is_array($records)) {
$result['message'] = 'Records must be an array.';
return $result;
}
if (!is_array($options)) {
$options = array();
}
$bucket_format = 'Y-m-d H:00:00';
if (!empty($options['bucket_format'])) {
$bucket_format = (string)$options['bucket_format'];
}
$total_requests = 0;
if (!empty($options['total_requests'])) {
$total_requests = (int)$options['total_requests'];
}
$total_errors = 0;
$by_route = array();
$by_severity = array();
$by_bucket = array();
foreach ($records as $record) {
if (!is_array($record)) {
continue;
}
$route = '/unknown';
if (!empty($record['route'])) {
$route = (string)$record['route'];
}
$route = preg_replace('/([?&](token|key|secret|password|session)=)[^&]+/i', '$1[redacted]', $route);
$severity = 'error';
if (!empty($record['severity'])) {
$severity = strtolower(trim((string)$record['severity']));
}
if (empty($severity)) {
$severity = 'error';
}
$timestamp = time();
if (!empty($record['timestamp'])) {
$timestamp = strtotime((string)$record['timestamp']);
if (empty($timestamp)) {
$timestamp = time();
}
}
$bucket = date($bucket_format, $timestamp);
$total_errors++;
if (empty($by_route[$route])) {
$by_route[$route] = 0;
}
$by_route[$route]++;
if (empty($by_severity[$severity])) {
$by_severity[$severity] = 0;
}
$by_severity[$severity]++;
if (empty($by_bucket[$bucket])) {
$by_bucket[$bucket] = 0;
}
$by_bucket[$bucket]++;
}
arsort($by_route);
arsort($by_severity);
ksort($by_bucket);
$error_rate = 0;
if ($total_requests > 0) {
$error_rate = ($total_errors / $total_requests) * 100;
}
$result['success'] = true;
$result['message'] = 'Error rate summary built.';
$result['data'] = array(
'total_errors' => $total_errors,
'total_requests' => $total_requests,
'error_rate_percent' => $error_rate,
'by_route' => $by_route,
'by_severity' => $by_severity,
'by_bucket' => $by_bucket
);
return $result;
}