-
-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implemented logging to Graylog server #14847
Conversation
Considering the CI check... Shall / must I rebase my branch onto master? |
The autoloaders are not up to date |
Added the appropriate logging class. Provided the necessary system config examples. Added loading the log class from the LogFactory. Extended the LogFactory unit tests to include the graylog class. Added Graylog test class skeleton. Signed-off-by: Thomas Pulzer <[email protected]>
Changed method of how to connect to remote server for writing logs. Wrote unit tests for chunked udp, unchunked udp and tcp connections. Signed-off-by: Thomas Pulzer <[email protected]>
Fixed wrong byte packing when sending chunked UDP packets. Improved test code and comments. Signed-off-by: Thomas Pulzer <[email protected]>
Signed-off-by: Thomas Pulzer <[email protected]>
…l with occ Signed-off-by: Thomas Pulzer <[email protected]>
Signed-off-by: Thomas Pulzer <[email protected]>
This revealed former incorrect encoding of field 'level' (is nuber, but was encoded as string. Therefore, the test method had to be adjusted as well. Signed-off-by: Thomas Pulzer <[email protected]>
Signed-off-by: Thomas Pulzer <[email protected]>
e8d007a
to
c5a4be7
Compare
Rebased onto master to have all the checks passed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the great contribution 👍 Please excuse the late code review 😞
@@ -0,0 +1,109 @@ | |||
<?php | |||
/** | |||
* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* |
@@ -0,0 +1,109 @@ | |||
<?php |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<?php | |
<?php | |
declare(strict_types=1); |
@@ -0,0 +1,147 @@ | |||
<?php |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<?php | |
<?php | |
declare(strict_types=1); |
@@ -0,0 +1,147 @@ | |||
<?php | |||
/** | |||
* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* |
$address = $config->getSystemValue('graylog_host', ''); | ||
if (false !== strpos($address, ':')) { | ||
$this->target = explode(':', $address)[0]; | ||
$this->port = intval(explode(':', $address)[1]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$this->port = intval(explode(':', $address)[1]); | |
$this->port = (int) explode(':', $address)[1]; |
$host = $this->config->getSystemValue('graylog_host'); | ||
$output->writeln('Log server: '.$host); | ||
$protocol = $this->config->getSystemValue('graylog_proto', 'udp'); | ||
$output->writeln('Connection protocol: '.$protocol); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$output->writeln('Connection protocol: '.$protocol); | |
$output->writeln('Connection protocol: ' . $protocol); |
* @throws \InvalidArgumentException | ||
*/ | ||
protected function isBackendGraylogSet($new=null) { | ||
$old = $this->config->getSystemValue('log_type', self::DEFAULT_BACKEND); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about this 🤔 It's not possible to set greylog_host
or greylog_proto
if the current log_type
or the new log_type
is not greylog. That makes sense but is very strict. There is no harm if greylog_host
or greylog_proto
are set with another log_type
. I think we need some input from another reviewer.
@@ -99,6 +112,20 @@ protected function execute(InputInterface $input, OutputInterface $output) { | |||
$toBeSet['logtimezone'] = $timezone; | |||
} | |||
|
|||
if ($host = $input->getOption('host')) { | |||
array_key_exists('log_type', $toBeSet) ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to suggest to change this a bit. Its quite hard to read and we have the same logic two times. The isBackendGraylogSet
method should accept an array $toBeSet and do the array_key_exists check.
public function __construct(IConfig $config) { | ||
$this->host = gethostname(); | ||
$this->protocol = $config->getSystemValue('graylog_proto', 'udp'); | ||
$address = $config->getSystemValue('graylog_host', ''); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code is fine. I would pick a slightly different approach but everyone has a different code style so this is up to you.
$address = explode(':', $config->getSystemValue('graylog_host'));
if (count($address) === 2) {
$this->target = $address[0];
$this->port = (int)$address[1];
} else {
$this->target = $address[0];
$this->port = 514;
}
* @param string $new | ||
* @throws \InvalidArgumentException | ||
*/ | ||
protected function isBackendGraylogSet($new=null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should find another name for it.
$msg = json_encode([ | ||
'version' => self::$VERSION, | ||
'host' => $this->host, | ||
'short_message' => '{'.$app.'} '.$message, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You might want to use the new way here as well:
'short_message' => '{'.$app.'} '.$message, | |
'short_message' => $this->logDetailsAsJSON($app, $message, $level), |
Was added just now via #16416
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe the non-encoded one is better here: logDetails()
, because it does not return a string with JSON, but an object with keys.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, if Graylog can handle nested data in the short_message key that should be the way to go.
Lets merge this early in 18. |
Lot's of unaddressed review comments. Some unanswered questions. This needs triage. Not assigning to 19 because pushing this from release to release has no point. |
What might make more sense IMO is to use some existing packages like https://packagist.org/packages/giacomofurlan/php-graylog-gelf in combination with #18200. And preferably make this an app. Like
|
Let's close this due to lack of activity. If anyone would like to bring this feature to life, please do so as an app as described in my previous comment. |
For an old feature request, I implemented logging as GELF to a Graylog server.
Features
Implementation
Added a new class handling writing the logs to the configured server through a socket connection. If the connection fails, it returns silently.
GELF supports chunking of UDP messages up to 128 chunks. So a log message can be approx. 126kB in size or it is silently discarded.
I also added the ability to configure the logging method through the occ log:manage command scope.
Closes #95