-
Notifications
You must be signed in to change notification settings - Fork 0
/
logreport.php
129 lines (107 loc) · 3.12 KB
/
logreport.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
<?php
chdir(__DIR__);
$configFile = 'config.php';
// create config file on first run
if (!file_exists($configFile)) {
copy($configFile . '.default', $configFile);
}
$config = require($configFile);
$defaults = array(
'dir' => './',
'match' => '/(error_log)|(\.log)$/i',
'exclude' => [],
'cacheFile' => './logreport.cache',
);
$config += $defaults;
// read cache
if (file_exists($config['cacheFile'])) {
$cache = unserialize(file_get_contents($config['cacheFile']));
} else {
$cache = array();
}
// start a fresh cache
$freshCache = array();
// script start time
$time = -microtime(true);
// find files
$directory = new RecursiveDirectoryIterator($config['dir']);
$flattened = new RecursiveIteratorIterator(new IgnoreFilterIterator($directory));
$files = new RegexIterator($flattened, $config['match']);
if (!empty($config['exclude'])) {
$files = new ExcludePathsIterator($files, $config['exclude']);
}
$fileChangedCount = 0;
// iterate through files
foreach ($files as $file) {
$path = $file->getRealPath();
$bytes = filesize($path);
$cachedBytes = isset($cache[$path]) ? $cache[$path] : 0;
// check if bytes have changed
if ($cachedBytes != $bytes && $bytes > 0) {
// if file is smaller than what it was, then we want the entire file
if ($bytes < $cachedBytes) {
$cachedBytes = 0;
}
// open file and get contents
$handle = fopen($path, 'r');
fseek($handle, $cachedBytes);
$wantBytes = $bytes - $cachedBytes;
$contents = fread($handle, $wantBytes);
fclose($handle);
// push contents of file to output, showing '...'
// if it looks like we didn't get all the text
echo decoratedPath($path) . PHP_EOL .
$contents . (strlen($contents) < ($wantBytes) ? '...' : '') .
PHP_EOL . PHP_EOL;
$fileChangedCount++;
}
$freshCache[$path] = $bytes;
}
// write cache
file_put_contents($config['cacheFile'], serialize($freshCache));
// script end time only if log files changed
if ($fileChangedCount) {
$time += microtime(true);
echo decoratedPath('Execution duration: ' . sprintf('%f', $time));
}
function decoratedPath($path)
{
$line = str_repeat('-', strlen($path)) . PHP_EOL;
return $line . $path . PHP_EOL . $line;
}
class IgnoreFilterIterator extends RecursiveFilterIterator
{
public static $FILTERS = array(
'.svn',
'.git',
'node_modules',
'vendor',
);
public function accept()
{
return !in_array(
$this->current()->getFilename(),
self::$FILTERS,
true
);
}
}
class ExcludePathsIterator extends FilterIterator
{
protected $patterns = [];
public function __construct(Iterator $iterator, array $patterns = [])
{
$this->patterns = $patterns;
parent::__construct($iterator);
}
public function accept()
{
$path = $this->current()->getRealPath();
foreach ($this->patterns as $pattern) {
if (preg_match($pattern, $path)) {
return false;
}
}
return true;
}
}