1
|
|
|
<?php declare(strict_types=1); |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* ___ _ |
5
|
|
|
* | _ \__ _ _ _ __| |___ __ _ |
6
|
|
|
* | _/ _` | '_(_-< / _ \/ _` | |
7
|
|
|
* |_| \__,_|_| /__/_\___/\__, | |
8
|
|
|
* |___/ |
9
|
|
|
* |
10
|
|
|
* (c) Kristuff <[email protected]> |
11
|
|
|
* |
12
|
|
|
* For the full copyright and license information, please view the LICENSE |
13
|
|
|
* file that was distributed with this source code. |
14
|
|
|
* |
15
|
|
|
* @version 0.7.2 |
16
|
|
|
* @copyright 2017-2021 Kristuff |
17
|
|
|
*/ |
18
|
|
|
|
19
|
|
|
namespace Kristuff\Parselog\Software; |
20
|
|
|
|
21
|
|
|
use Kristuff\Parselog\Core\LogEntryFactoryInterface; |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* |
25
|
|
|
* |
26
|
|
|
* @see https://httpd.apache.org/docs/2.4/en/logs.html |
27
|
|
|
* @see https://httpd.apache.org/docs/2.4/en/mod/mod_log_config.html#formats |
28
|
|
|
*/ |
29
|
|
|
class ApacheAccessLogParser extends SoftwareLogParser |
30
|
|
|
{ |
31
|
|
|
|
32
|
|
|
const FORMAT_COMMON = '%h %l %u %t "%r" %>s %b'; |
33
|
|
|
const FORMAT_COMMON_VHOST = '%v %h %l %u %t "%r" %>s %b'; |
34
|
|
|
const FORMAT_COMBINED = '%h %l %u %t "%r" %>s %O "%{Referer}i" "%{User-Agent}i"'; |
35
|
|
|
const FORMAT_COMBINED_VHOST = '%v:%p %h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i"'; |
36
|
|
|
const FORMAT_REFERER = '%{Referer}i'; |
37
|
|
|
const FORMAT_AGENT = '%{User-Agent}i'; // TODO |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* Constructor |
41
|
|
|
* |
42
|
|
|
* @access public |
43
|
|
|
* @param string $format |
44
|
|
|
* @param LogEntryFactoryInterface $factory |
45
|
|
|
* |
46
|
|
|
* @return void |
47
|
|
|
*/ |
48
|
|
|
public function __construct(string $format = null, LogEntryFactoryInterface $factory = null) |
49
|
|
|
{ |
50
|
|
|
$this->software = 'Apache'; |
51
|
|
|
$this->prettyName = 'Apache Access'; |
52
|
|
|
$this->defaultFormat = self::FORMAT_COMMON; |
53
|
|
|
$this->timeFormat = 'd/M/Y:H:i:s P'; |
54
|
|
|
|
55
|
|
|
$this->addPath("/var/log/"); |
56
|
|
|
$this->addPath("/var/log/apache/"); |
57
|
|
|
$this->addPath("/var/log/apache2/"); |
58
|
|
|
$this->addPath("/var/log/httpd/"); |
59
|
|
|
$this->addPath("/usr/local/var/log/apache/"); |
60
|
|
|
$this->addPath("/usr/local/var/log/apache2/"); |
61
|
|
|
$this->addPath("/usr/local/var/log/httpd/"); |
62
|
|
|
$this->addPath("/opt/local/apache/logs/"); |
63
|
|
|
$this->addPath("/opt/local/apache2/logs/"); |
64
|
|
|
$this->addPath("/opt/local/httpd/logs/"); |
65
|
|
|
$this->addPath("C:/wamp/logs/"); |
66
|
|
|
|
67
|
|
|
$this->addFile('access.log'); |
68
|
|
|
$this->addFile('access_log'); |
69
|
|
|
$this->addFile('apache.log'); |
70
|
|
|
$this->addFile('apache_access.log'); |
71
|
|
|
|
72
|
|
|
$this->addFormat('apache_common', '%h %l %u %t \"%r\" %>s %O"'); |
73
|
|
|
$this->addFormat('apache_combined_vhost', '%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"'); |
74
|
|
|
$this->addFormat('apache_combined', '%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"'); |
75
|
|
|
$this->addFormat('apache_common_vhost', '%v %l %u %t \"%r\" %>s %b'); |
76
|
|
|
|
77
|
|
|
|
78
|
|
|
$this->addNamedPattern('%%' , 'percent', '\%'); |
79
|
|
|
|
80
|
|
|
// time |
81
|
|
|
$this->addPattern('%t' , '\[(?P<time>\d{2}/(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)/\d{4}:\d{2}:\d{2}:\d{2} (?:-|\+)\d{4})\]'); |
82
|
|
|
|
83
|
|
|
$this->addNamedPattern('%v' , 'serverName', '([a-zA-Z0-9]+)([a-z0-9.-]*)'); |
84
|
|
|
$this->addNamedPattern('%V' , 'canonicalServerName', '([a-zA-Z0-9]+)([a-z0-9.-]*)'); |
85
|
|
|
|
86
|
|
|
// port |
87
|
|
|
$this->addNamedPattern('%p' , 'port', '\d+'); |
88
|
|
|
|
89
|
|
|
// Client IP address of the request |
90
|
|
|
$this->addNamedPattern('%a', 'remoteIp', self::PATTERN_IP_ALL); |
91
|
|
|
|
92
|
|
|
// Remote hostname |
93
|
|
|
$this->addNamedPattern('%h' , 'host', '[a-zA-Z0-9\-\._:]+'); |
94
|
|
|
|
95
|
|
|
// Local IP-address |
96
|
|
|
$this->addNamedPattern('%A', 'localIp', self::PATTERN_IP_ALL); |
97
|
|
|
|
98
|
|
|
// Remote user if the request was authenticated. May be bogus if return status (%s) is 401 (unauthorized). |
99
|
|
|
$this->addNamedPattern('%u', 'user', '(?:-|[\w\-\.]+)'); |
100
|
|
|
|
101
|
|
|
$this->addNamedPattern('%l', 'logname', '(?:-|[\w-]+)'); |
102
|
|
|
$this->addNamedPattern('%m', 'requestMethod', 'OPTIONS|GET|HEAD|POST|PUT|DELETE|TRACE|CONNECT|PATCH|PROPFIND'); |
103
|
|
|
$this->addNamedPattern('%U', 'URL', '.+?'); |
104
|
|
|
$this->addNamedPattern('%H', 'requestProtocol', 'HTTP/(1\.0|1\.1|2\.0)'); |
105
|
|
|
$this->addNamedPattern('%r', 'request', '(?:(?:[A-Z]+) .+? HTTP/(1\.0|1\.1|2\.0))|-|'); |
106
|
|
|
|
107
|
|
|
// Status of the final request |
108
|
|
|
$this->addNamedPattern('%>s', 'status', '\d{3}|-'); |
109
|
|
|
|
110
|
|
|
// Bytes sent, including headers. May be zero in rare cases such as when a request is aborted before a |
111
|
|
|
// response is sent. You need to enable mod_logio to use this. |
112
|
|
|
$this->addNamedPattern('%O', 'sentBytes', '[0-9]+'); |
113
|
|
|
|
114
|
|
|
// Size of response in bytes, excluding HTTP headers. In CLF format, i.e. a '-' rather than a 0 when no bytes are sent. |
115
|
|
|
$this->addNamedPattern('%b', 'responseBytes', '(\d+|-)'); |
116
|
|
|
|
117
|
|
|
//The time taken to serve the request, in seconds. |
118
|
|
|
$this->addNamedPattern('%T', 'requestTime', '(\d+\.?\d*)'); |
119
|
|
|
|
120
|
|
|
// The time taken to serve the request, in microseconds |
121
|
|
|
$this->addNamedPattern('%D', 'timeServeRequest', '[0-9]+'); |
122
|
|
|
|
123
|
|
|
$this->addNamedPattern('%I', 'receivedBytes', '[0-9]+'); |
124
|
|
|
|
125
|
|
|
// dymanic named header columns |
126
|
|
|
$this->addPattern('\%\{(?P<name>[a-zA-Z]+)(?P<name2>[-]?)(?P<name3>[a-zA-Z]+)\}i', '(?P<header\\1\\3>.*?)'); |
127
|
|
|
|
128
|
|
|
|
129
|
|
|
parent::__construct($format, $factory); |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
} |