LogrotateCollector::getIdentifier()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
namespace Startwind\Inventorio\Collector\System\Logs;
4
5
use Startwind\Inventorio\Collector\Collector;
6
use Startwind\Inventorio\Exec\File;
7
use Startwind\Inventorio\Exec\Runner;
8
use Startwind\Inventorio\Exec\System;
9
10
class LogrotateCollector implements Collector
11
{
12
    public function getIdentifier(): string
13
    {
14
        return 'SystemLogLogrotate';
15
    }
16
17
    public function collect(): array
18
    {
19
        return [
20
            'logfiles' => $this->getLogFileStatus()
21
        ];
22
    }
23
24
    private function getLogFileStatus(): array
25
    {
26
        $fileHandler = File::getInstance();
27
28
        $searchPath = '/var/log';
29
30
        $logrotateConfigurations = ['/etc/logrotate.conf'];
31
32
        if ($fileHandler->isDir('/etc/logrotate.d')) {
33
            $entries = $fileHandler->scanDir('/etc/logrotate.d');
34
            foreach ($entries as $entry) {
35
                if ($entry === '.' || $entry === '..') continue;
36
                $fullPath = '/etc/logrotate.d/' . $entry;
37
                $logrotateConfigurations[] = $fullPath;
38
            }
39
        }
40
41
        $allLogs = $this->getLogFilesWithStats($searchPath);
42
43
        // Step 2: Extract managed log paths from logrotate config files
44
        $explicitManaged = [];
45
        foreach ($logrotateConfigurations as $confFile) {
46
            $lines = $fileHandler->getContents($confFile, true);
47
            foreach ($lines as $line) {
48
                if (preg_match('#^\s*/[^\s{}]+\.log#', $line, $matches)) {
49
                    // $path = $fileHandler->realPath($matches[0]);
50
                    $path = $matches[0];
51
                    $explicitManaged[] = $path;
52
                }
53
            }
54
        }
55
56
        $explicitManaged = array_unique($explicitManaged);
57
58
        // Step 3: Check for rotated versions (*.log.1, *.log.2.gz, etc.)
59
        $rotatedManaged = [];
60
61
        foreach (array_keys($allLogs) as $logFile) {
62
            $dir = dirname($logFile);
63
            $base = basename($logFile);
64
65
            $entries = $fileHandler->scanDir($dir);
66
            $found = false;
67
68
            foreach ($entries as $entry) {
69
                if (
70
                    str_starts_with($entry, $base . '.') &&
71
                    $fileHandler->isFile($dir . '/' . $entry)
72
                ) {
73
                    $found = true;
74
                    break;
75
                }
76
            }
77
78
            if ($found) {
79
                $rotatedManaged[] = $logFile;
80
            }
81
        }
82
83
        // Combine explicit config-based and detected rotated logs
84
        $allManaged = array_unique(array_merge($explicitManaged, $rotatedManaged));
85
86
        // Step 4: Build result
87
        $result = [
88
            'managed' => [],
89
            'unmanaged' => []
90
        ];
91
92
        foreach ($allLogs as $path => $info) {
93
            $entry = [
94
                'path' => $path,
95
                'size' => $info['size'],
96
                'last_modified' => date('c', $info['last_modified'])
97
            ];
98
99
            $index = str_replace('/', '-', $path);
100
101
            if (in_array($path, $allManaged)) {
102
                $result['managed'][$index] = $entry;
103
            } else {
104
                $result['unmanaged'][$index] = $entry;
105
            }
106
        }
107
108
        return $result;
109
    }
110
111
    function getLogFilesWithStats(string $dir): array
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
112
    {
113
        $result = [];
114
115
        $os = strtolower(System::getInstance()->getPlatform());
116
117
        if ($os === 'linux') {
118
            $cmd = "find " . escapeshellarg($dir) . " -type f -name '*.log' -exec stat --format='%n\t%s\t%Y' {} + 2>/dev/null";
119
        } elseif ($os === 'darwin') {
120
            $cmd = "find " . escapeshellarg($dir) . " -type f -name '*.log' -exec stat -f '%N\t%z\t%m' {} + 2>/dev/null";
121
        } else {
122
            return [];
123
        }
124
125
        $output = Runner::getInstance()->run($cmd)->getOutput();
126
        $output = explode("\n", $output);
127
128
        foreach ($output as $line) {
129
            $parts = preg_split('/\s+/', $line, 3);
130
131
            if (count($parts) !== 3) {
132
                continue;
133
            }
134
135
            [$file, $size, $mtime] = $parts;
136
137
            $result[$file] = [
138
                'size' => (int)$size,
139
                'last_modified' => (int)$mtime,
140
            ];
141
        }
142
143
        return $result;
144
    }
145
}
146