From 8196b7004d6b4088ef8c98edd73d119115518dea Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 10 Jun 2026 12:42:35 -0400 Subject: [PATCH 1/2] refactor(log): adjust variable names and odering of logDetails() for clarity Signed-off-by: Josh --- lib/private/Log/LogDetails.php | 89 ++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 37 deletions(-) diff --git a/lib/private/Log/LogDetails.php b/lib/private/Log/LogDetails.php index 21abb6d85cb46..78817d67d563a 100644 --- a/lib/private/Log/LogDetails.php +++ b/lib/private/Log/LogDetails.php @@ -20,66 +20,81 @@ public function __construct( } public function logDetails(string $app, string|array $message, int $level): array { - // default to ISO8601 + $version = $this->config->getValue('version', ''); + // Default to ATOM/ISO8601 formatting and UTC timezone. $format = $this->config->getValue('logdateformat', \DateTimeInterface::ATOM); - $logTimeZone = $this->config->getValue('logtimezone', 'UTC'); + $configuredTimeZone = $this->config->getValue('logtimezone', 'UTC'); + try { - $timezone = new \DateTimeZone($logTimeZone); + $timezone = new \DateTimeZone($configuredTimeZone); } catch (\Exception $e) { $timezone = new \DateTimeZone('UTC'); } - $time = \DateTime::createFromFormat('U.u', number_format(microtime(true), 4, '.', '')); - if ($time === false) { - $time = new \DateTime('now', $timezone); - } else { - // apply timezone if $time is created from UNIX timestamp + + $timestamp = number_format(microtime(true), 4, '.', ''); + $time = \DateTime::createFromFormat('U.u', $timestamp); + if ($time !== false) { + // UNIX timestamps are timezone-independent; apply the configured display timezone. $time->setTimezone($timezone); + } else { + // Fall back to a current wall-clock time if parsing fails. + $time = new \DateTime('now', $timezone); } + $formattedTime = $time->format($format); + $request = Server::get(IRequest::class); + $reqId = $request->getId(); $remoteAddr = $request->getRemoteAddress(); - // remove username/passwords from URLs before writing the to the log file - $time = $time->format($format); - $url = ($request->getRequestUri() !== '') ? $request->getRequestUri() : '--'; $method = $request->getMethod(); - if ($this->config->getValue('installed', false)) { - $user = \OC_User::getUser() ?: '--'; - } else { - $user = '--'; - } + $url = $request->getRequestUri(); + $scriptName = $request->getScriptName(); $userAgent = $request->getHeader('User-Agent'); + $clientReqId = $request->getHeader('X-Request-Id'); + + if ($url === '') { + $url = '--'; + } + if ($userAgent === '') { $userAgent = '--'; } - $version = $this->config->getValue('version', ''); - $scriptName = $request->getScriptName(); - $entry = compact( - 'reqId', - 'level', - 'time', - 'remoteAddr', - 'user', - 'app', - 'method', - 'url', - 'scriptName', - 'message', - 'userAgent', - 'version', - ); - $clientReqId = $request->getHeader('X-Request-Id'); + + $user = '--'; + if ($this->config->getValue('installed', false)) { + $user = \OC_User::getUser() ?: '--'; + } + + $entry = [ + 'reqId' => $reqId, + 'level' => $level, + 'time' => $formattedTime, + 'remoteAddr' => $remoteAddr, + 'user' => $user, + 'app' => $app, + 'method' => $method, + 'url' => $url, + 'scriptName' => $scriptName, + 'message' => $message, + 'userAgent' => $userAgent, + 'version' => $version, + ]; + if ($clientReqId !== '') { $entry['clientReqId'] = $clientReqId; } + if (\OC::$CLI) { - /* Only logging the command, not the parameters */ + // Only logging the command, not the parameters $entry['occ_command'] = array_slice($_SERVER['argv'] ?? [], 0, 2); } if (is_array($message)) { - // Exception messages are extracted and the exception is put into a separate field - // anything else modern is split to 'message' (string) and - // data (array) fields + // Array messages are normalized into one of two forms: + // - exception payloads ('Exception' present): keep the full payload in 'exception' + // and derive the top-level 'message' from CustomMessage/Message + // - structured payloads: use 'message' as the top-level message and store the + // remaining fields under 'data' if (array_key_exists('Exception', $message)) { $entry['exception'] = $message; $entry['message'] = $message['CustomMessage'] !== '--' ? $message['CustomMessage'] : $message['Message']; From f9e803a1010f05a9ada24d371fac00c04ba7305a Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 10 Jun 2026 13:02:08 -0400 Subject: [PATCH 2/2] refactor(log): normalize $message before building $entry in logDetails() Signed-off-by: Josh --- lib/private/Log/LogDetails.php | 57 ++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/lib/private/Log/LogDetails.php b/lib/private/Log/LogDetails.php index 78817d67d563a..618ab43d7bc7f 100644 --- a/lib/private/Log/LogDetails.php +++ b/lib/private/Log/LogDetails.php @@ -19,12 +19,20 @@ public function __construct( ) { } + /** + * Build a structured log entry from request context and message data. + * + * Array messages are normalized into either an exception payload or a + * top-level message plus structured context data. + * + * @return array + */ public function logDetails(string $app, string|array $message, int $level): array { $version = $this->config->getValue('version', ''); // Default to ATOM/ISO8601 formatting and UTC timezone. $format = $this->config->getValue('logdateformat', \DateTimeInterface::ATOM); $configuredTimeZone = $this->config->getValue('logtimezone', 'UTC'); - + try { $timezone = new \DateTimeZone($configuredTimeZone); } catch (\Exception $e) { @@ -34,14 +42,14 @@ public function logDetails(string $app, string|array $message, int $level): arra $timestamp = number_format(microtime(true), 4, '.', ''); $time = \DateTime::createFromFormat('U.u', $timestamp); if ($time !== false) { - // UNIX timestamps are timezone-independent; apply the configured display timezone. + // UNIX timestamps are timezone-independent; apply the configured log timezone. $time->setTimezone($timezone); } else { - // Fall back to a current wall-clock time if parsing fails. + // Fall back to the current time in the configured timezone if parsing fails. $time = new \DateTime('now', $timezone); } $formattedTime = $time->format($format); - + $request = Server::get(IRequest::class); $reqId = $request->getId(); @@ -65,6 +73,26 @@ public function logDetails(string $app, string|array $message, int $level): arra $user = \OC_User::getUser() ?: '--'; } + $normalizedMessage = $message; + $exception = null; + $data = null; + + if (is_array($message)) { + // Normalize array messages into one of two forms: + // - exception payloads ('Exception' present): keep the full payload in 'exception' + // and derive the top-level 'message' from CustomMessage/Message + // - structured payloads: use 'message' as the top-level message and store the + // remaining fields under 'data' + if (array_key_exists('Exception', $message)) { + $exception = $message; + $normalizedMessage = $message['CustomMessage'] !== '--' ? $message['CustomMessage'] : $message['Message']; + } else { + $normalizedMessage = $message['message'] ?? '(no message provided)'; + unset($message['message']); + $data = $message; + } + } + $entry = [ 'reqId' => $reqId, 'level' => $level, @@ -75,7 +103,7 @@ public function logDetails(string $app, string|array $message, int $level): arra 'method' => $method, 'url' => $url, 'scriptName' => $scriptName, - 'message' => $message, + 'message' => $normalizedMessage, 'userAgent' => $userAgent, 'version' => $version, ]; @@ -89,20 +117,11 @@ public function logDetails(string $app, string|array $message, int $level): arra $entry['occ_command'] = array_slice($_SERVER['argv'] ?? [], 0, 2); } - if (is_array($message)) { - // Array messages are normalized into one of two forms: - // - exception payloads ('Exception' present): keep the full payload in 'exception' - // and derive the top-level 'message' from CustomMessage/Message - // - structured payloads: use 'message' as the top-level message and store the - // remaining fields under 'data' - if (array_key_exists('Exception', $message)) { - $entry['exception'] = $message; - $entry['message'] = $message['CustomMessage'] !== '--' ? $message['CustomMessage'] : $message['Message']; - } else { - $entry['message'] = $message['message'] ?? '(no message provided)'; - unset($message['message']); - $entry['data'] = $message; - } + if ($exception !== null) { + $entry['exception'] = $exception; + } + if ($data !== null) { + $entry['data'] = $data; } return $entry;