Add comprehensive logging for OMG API debugging and application tracking
OMG API Debug Logging: - Log full URL being called - Log API key (first 20 chars for security) - Log HTTP response code - Log response body (first 500 chars) - Log campaign number and business area extraction - Log business unit mapping result ApplicationLogger Class: - Structured JSON logging to logs/application.log - Track all actions: master_asset_submission, global_to_local_transform, box_upload - Capture user email, timestamp, IP address, user agent - Methods for reporting: getRecentLogs(), getLogsByAction(), getLogsByUser() - Generate statistics: total actions, by user, by action, errors Email Configuration: - Configured SMTP via Mailgun (smtp.mailgun.org:587) - Using twist@mail.dev.oliver.solutions - Emails sent to logged-in user This enables full audit trail and troubleshooting capability. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
9b8dbbf20c
commit
0571ce403f
3 changed files with 217 additions and 0 deletions
200
ApplicationLogger.php
Normal file
200
ApplicationLogger.php
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
<?php
|
||||
/**
|
||||
* Application Logger
|
||||
* Tracks all application actions for reporting and auditing
|
||||
*/
|
||||
|
||||
class ApplicationLogger {
|
||||
private $logFile;
|
||||
private $config;
|
||||
|
||||
public function __construct() {
|
||||
$appConfig = require __DIR__ . '/config.php';
|
||||
$this->config = $appConfig;
|
||||
|
||||
// Create logs directory if it doesn't exist
|
||||
$logsDir = __DIR__ . '/logs';
|
||||
if (!file_exists($logsDir)) {
|
||||
mkdir($logsDir, 0755, true);
|
||||
}
|
||||
|
||||
$this->logFile = $logsDir . '/application.log';
|
||||
}
|
||||
|
||||
/**
|
||||
* Log action with structured data
|
||||
*/
|
||||
public function log($action, $user, $data = [], $status = 'success') {
|
||||
$logEntry = [
|
||||
'timestamp' => date('Y-m-d H:i:s'),
|
||||
'action' => $action,
|
||||
'user_email' => $user['email'] ?? 'unknown',
|
||||
'user_name' => $user['name'] ?? 'unknown',
|
||||
'status' => $status,
|
||||
'data' => $data,
|
||||
'ip_address' => $_SERVER['REMOTE_ADDR'] ?? 'unknown',
|
||||
'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'unknown'
|
||||
];
|
||||
|
||||
$logLine = json_encode($logEntry) . "\n";
|
||||
|
||||
// Append to log file
|
||||
file_put_contents($this->logFile, $logLine, FILE_APPEND | LOCK_EX);
|
||||
|
||||
// Also log to PHP error log for debugging
|
||||
error_log('[APP LOG] ' . $action . ' - ' . $status . ' - ' . ($user['email'] ?? 'unknown'));
|
||||
|
||||
return $logEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log Master Asset Submission
|
||||
*/
|
||||
public function logAssetSubmission($user, $boxId, $masterCampaignNumber, $dates, $status = 'success', $error = null) {
|
||||
return $this->log('master_asset_submission', $user, [
|
||||
'box_id' => $boxId,
|
||||
'master_campaign_number' => $masterCampaignNumber,
|
||||
'supply_date' => $dates['supply'] ?? null,
|
||||
'live_date' => $dates['live'] ?? null,
|
||||
'end_date' => $dates['end'] ?? null,
|
||||
'error' => $error
|
||||
], $status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log Global to Local Transformation
|
||||
*/
|
||||
public function logGlobalToLocal($user, $campaignNumber, $businessUnit, $inputRows, $outputFiles, $status = 'success', $error = null) {
|
||||
return $this->log('global_to_local_transform', $user, [
|
||||
'campaign_number' => $campaignNumber,
|
||||
'business_unit' => $businessUnit,
|
||||
'input_rows' => $inputRows,
|
||||
'output_file_count' => $outputFiles,
|
||||
'total_output_rows' => $inputRows * $outputFiles,
|
||||
'error' => $error
|
||||
], $status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log Box Upload
|
||||
*/
|
||||
public function logBoxUpload($user, $fileCount, $folderId, $status = 'success', $error = null) {
|
||||
return $this->log('box_upload', $user, [
|
||||
'file_count' => $fileCount,
|
||||
'folder_id' => $folderId,
|
||||
'error' => $error
|
||||
], $status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log OMG API Call
|
||||
*/
|
||||
public function logOMGAPICall($user, $campaignNumber, $businessArea, $businessUnit, $status = 'success', $error = null) {
|
||||
return $this->log('omg_api_lookup', $user, [
|
||||
'campaign_number' => $campaignNumber,
|
||||
'business_area' => $businessArea,
|
||||
'business_unit' => $businessUnit,
|
||||
'error' => $error
|
||||
], $status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get recent logs
|
||||
*/
|
||||
public function getRecentLogs($limit = 100) {
|
||||
if (!file_exists($this->logFile)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$lines = file($this->logFile, FILE_IGNORE_NEW_LINES);
|
||||
$lines = array_reverse($lines); // Most recent first
|
||||
$lines = array_slice($lines, 0, $limit);
|
||||
|
||||
$logs = [];
|
||||
foreach ($lines as $line) {
|
||||
$log = json_decode($line, true);
|
||||
if ($log) {
|
||||
$logs[] = $log;
|
||||
}
|
||||
}
|
||||
|
||||
return $logs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get logs by action type
|
||||
*/
|
||||
public function getLogsByAction($action, $limit = 100) {
|
||||
$allLogs = $this->getRecentLogs(1000);
|
||||
|
||||
$filtered = array_filter($allLogs, function($log) use ($action) {
|
||||
return $log['action'] === $action;
|
||||
});
|
||||
|
||||
return array_slice(array_values($filtered), 0, $limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get logs by user
|
||||
*/
|
||||
public function getLogsByUser($userEmail, $limit = 100) {
|
||||
$allLogs = $this->getRecentLogs(1000);
|
||||
|
||||
$filtered = array_filter($allLogs, function($log) use ($userEmail) {
|
||||
return $log['user_email'] === $userEmail;
|
||||
});
|
||||
|
||||
return array_slice(array_values($filtered), 0, $limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate report statistics
|
||||
*/
|
||||
public function getStatistics($startDate = null, $endDate = null) {
|
||||
$allLogs = $this->getRecentLogs(10000);
|
||||
|
||||
// Filter by date if provided
|
||||
if ($startDate || $endDate) {
|
||||
$allLogs = array_filter($allLogs, function($log) use ($startDate, $endDate) {
|
||||
$timestamp = strtotime($log['timestamp']);
|
||||
if ($startDate && $timestamp < strtotime($startDate)) return false;
|
||||
if ($endDate && $timestamp > strtotime($endDate)) return false;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
$stats = [
|
||||
'total_actions' => count($allLogs),
|
||||
'by_action' => [],
|
||||
'by_user' => [],
|
||||
'by_status' => [],
|
||||
'errors' => []
|
||||
];
|
||||
|
||||
foreach ($allLogs as $log) {
|
||||
// Count by action
|
||||
$action = $log['action'];
|
||||
$stats['by_action'][$action] = ($stats['by_action'][$action] ?? 0) + 1;
|
||||
|
||||
// Count by user
|
||||
$user = $log['user_email'];
|
||||
$stats['by_user'][$user] = ($stats['by_user'][$user] ?? 0) + 1;
|
||||
|
||||
// Count by status
|
||||
$status = $log['status'];
|
||||
$stats['by_status'][$status] = ($stats['by_status'][$status] ?? 0) + 1;
|
||||
|
||||
// Collect errors
|
||||
if ($status === 'error') {
|
||||
$stats['errors'][] = [
|
||||
'timestamp' => $log['timestamp'],
|
||||
'action' => $log['action'],
|
||||
'user' => $log['user_email'],
|
||||
'error' => $log['data']['error'] ?? 'Unknown error'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $stats;
|
||||
}
|
||||
}
|
||||
|
|
@ -27,6 +27,10 @@ class OMGService {
|
|||
$url = $this->baseUrl . '/getProject';
|
||||
$url .= '?project_number=' . urlencode($projectNumber);
|
||||
|
||||
error_log('===== OMG API CALL START =====');
|
||||
error_log('OMG API: Base URL: ' . $this->baseUrl);
|
||||
error_log('OMG API: Full URL: ' . $url);
|
||||
error_log('OMG API: API Key (first 20 chars): ' . substr($this->apiKey, 0, 20) . '...');
|
||||
error_log('OMG API: Requesting project ' . $projectNumber);
|
||||
|
||||
$ch = curl_init($url);
|
||||
|
|
@ -44,6 +48,10 @@ class OMGService {
|
|||
$curlError = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
error_log('OMG API: Response code ' . $httpCode);
|
||||
error_log('OMG API: Response body (first 500 chars): ' . substr($response, 0, 500));
|
||||
error_log('===== OMG API CALL END =====');
|
||||
|
||||
if ($curlError) {
|
||||
return [
|
||||
'success' => false,
|
||||
|
|
|
|||
|
|
@ -114,8 +114,13 @@ try {
|
|||
// STAGE 4: Call OMG API
|
||||
$progress[] = ['stage' => 'omg_api', 'status' => 'processing', 'message' => 'Looking up campaign in OMG...'];
|
||||
|
||||
error_log('=== OMG API LOOKUP ===');
|
||||
error_log('Campaign Number: ' . $campaignNumber);
|
||||
|
||||
$projectResult = $omgService->getProject($campaignNumber);
|
||||
|
||||
error_log('OMG API Result: ' . json_encode($projectResult));
|
||||
|
||||
if (!$projectResult['success']) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
|
|
@ -138,6 +143,8 @@ try {
|
|||
|
||||
$businessArea = $omgService->getBusinessArea($projectData);
|
||||
|
||||
error_log('Extracted Business Area: ' . ($businessArea ?? 'NULL'));
|
||||
|
||||
if (empty($businessArea)) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
|
|
@ -153,6 +160,8 @@ try {
|
|||
|
||||
$mappingResult = $omgService->mapBusinessUnit($businessArea);
|
||||
|
||||
error_log('Business Unit Mapping Result: ' . json_encode($mappingResult));
|
||||
|
||||
if (!$mappingResult['success']) {
|
||||
// Non-fatal warning - continue with "ERROR" value
|
||||
$progress[] = [
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue