diff --git a/bin/analyzelogs.php b/bin/analyzelogs.php
index 64b7cc1..6dc5ab0 100755
--- a/bin/analyzelogs.php
+++ b/bin/analyzelogs.php
@@ -1,142 +1,149 @@
#!/usr/bin/env php
|
| |
| This program is free software: you can redistribute it and/or modify |
| it under the terms of the GNU Affero General Public License as published |
| by the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public License |
| along with this program. If not, see |
+--------------------------------------------------------------------------+
| Author: Christian Mollekopf |
+--------------------------------------------------------------------------+
*/
define('RCUBE_INSTALL_PATH', realpath(dirname(__FILE__) . '/../') . '/');
// Define include path
$include_path = RCUBE_INSTALL_PATH . 'lib' . PATH_SEPARATOR;
$include_path .= RCUBE_INSTALL_PATH . 'lib/ext' . PATH_SEPARATOR;
$include_path .= ini_get('include_path');
set_include_path($include_path);
require_once "Syncroton/Command/ICommand.php";
require_once "Syncroton/Command/Wbxml.php";
require_once "Syncroton/Command/Sync.php";
require_once "Syncroton/Command/Ping.php";
require_once "Syncroton/Command/MoveItems.php";
+require_once "Syncroton/Command/FolderSync.php";
$filename = $argv[1];
$content = file_get_contents($filename);
// Split up the log files into chunks that hopefully match the commands
$parts = preg_split("/\[.*\]: " . preg_quote("[DEBUG] Syncroton_Server::handle::65 REQUEST METHOD: POST", '/') . "/", $content, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
function getStatusConstants($classname)
{
$reflect = new ReflectionClass($classname);
$result = $reflect->getConstants();
$result = array_filter($result, function ($val) {
return str_starts_with($val, "STATUS_");
}, ARRAY_FILTER_USE_KEY);
$result = array_flip($result);
return $result;
}
function explainStatus($command, $status)
{
+ if (!$status) {
+ return "none";
+ }
switch ($command) {
case "Ping":
$result = getStatusConstants("Syncroton_Command_Ping");
return $result[$status] ?? "Unknown";
case "Sync":
$result = getStatusConstants("Syncroton_Command_Sync");
return $result[$status] ?? "Unknown";
case "MoveItems":
$result = getStatusConstants("Syncroton_Command_MoveItems");
return $result[$status] ?? "Unknown";
+ case "FolderSync":
+ $result = getStatusConstants("Syncroton_Command_FolderSync");
+ return $result[$status] ?? "Unknown";
}
- return "Unkonwn";
+ return "Unknown command";
}
foreach ($parts as $part) {
preg_match('/\[(.*)\]: /', $part, $matches);
$timestamp = $matches[1];
preg_match('/\[command\] => (.*)/', $part, $matches);
$command = $matches[1];
preg_match('/\(.*)\<\/Status\>/', $part, $matches);
$status = $matches[1] ?? null;
$statusExplained = explainStatus($command, $status);
print(" Command: " . str_pad($command, 10) . str_pad("\tStatus: $status ($statusExplained)", 45) . "\tTimestamp: $timestamp\n");
if ($command == "Sync") {
// Find collections within this sync
// [25-Sep-2024 09:16:35.347730]: [INFO] Syncroton_Command_Sync::handle::221 SyncKey is 7301 Class: Email CollectionId: 38b950ebd62cd9a66929c89615d0fc04
if (preg_match_all('/SyncKey is (.*) Class: (.*) CollectionId: (.*)/', $part, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) {
foreach ($matches as $set) {
$offset = $set[0][1];
$collectionId = $set[3][0];
$class = $set[2][0];
$synckey = $set[1][0];
print(str_pad(" Collection: $collectionId ($class)", 58) . "\tSyncKey: $synckey\n");
//Find the offset for this collections messages
if (preg_match("/Processing $collectionId\.\.\./", $part, $match, PREG_OFFSET_CAPTURE, $offset)) {
// print_r($match);
$offset = $match[0][1] ?? null;
//Find the actual changes
if ($offset && preg_match('/found \(added\/changed\/deleted\) (.*)\/(.*)\/(.*) entries for sync from server to client/', $part, $changesMatch, PREG_OFFSET_CAPTURE, $offset)) {
// If the offset is too large we are looking at the next collection.
if ($changesMatch[0][1] - $offset < 200) {
print(" " . $changesMatch[0][0] . "\n");
}
}
}
//TODO We could figure out what the diff per collection was in terms of synckey to the last sync
//TODO We could figure out what we actually return in the response compared to the detected changeset
//TODO Warn if a collection is repeatedly synced with the same synckey, but changes are detected. It may be stuck in a sync loop.
}
}
// Detect entries that are being added from the client
if (preg_match_all('/found (.*) entries to be added on server/', $part, $matches)) {
foreach ($matches[0] ?? [] as $match) {
print(" " . $match . "\n");
}
}
if (preg_match_all('/found (.*) entries to be updated on server/', $part, $matches)) {
foreach ($matches[0] ?? [] as $match) {
print(" " . $match . "\n");
}
}
if (preg_match_all('/found (.*) entries to be deleted on server/', $part, $matches)) {
foreach ($matches[0] ?? [] as $match) {
print(" " . $match . "\n");
}
}
}
//TODO on Sync:
//* number of Add/Change/Remove from client and from server
//* Synckey
//* list involved folders
//TODO on Sync:
//* Reason for interruption
}