Skip to content

Commit

Permalink
feat: Introduce LogMessageProcessors and their factory
Browse files Browse the repository at this point in the history
  • Loading branch information
jeromegamez committed Nov 29, 2022
1 parent eeb4272 commit bf29fc7
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 11 deletions.
33 changes: 33 additions & 0 deletions Logging/src/LogMessageProcessor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php
/**
* Copyright 2022 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

namespace Google\Cloud\Logging;

/**
* Interface representing a Message Processor used by the {@see PsrLogger}
*/
interface LogMessageProcessor
{
/**
* @param string|\Stringable $message
* @param array $context
*
* @phpstan-return array{message: string, context: array}
* @return array
*/
public function processLogMessage($message, $context);
}
55 changes: 55 additions & 0 deletions Logging/src/LogMessageProcessor/MonologMessageProcessor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php
/**
* Copyright 2022 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

namespace Google\Cloud\Logging\LogMessageProcessor;

use Google\Cloud\Logging\LogMessageProcessor;
use Monolog\Formatter\NormalizerFormatter;
use Monolog\Processor\PsrLogMessageProcessor;

/**
* Uses the Monolog 1/2 PsrLogMessageProcessor to process a
* record's message according to PSR-3 rules.
*/
final class MonologMessageProcessor implements LogMessageProcessor
{
/**
* @var NormalizerFormatter
*/
private $formatter;

/**
* @var PsrLogMessageProcessor
*/
private $processor;

public function __construct()
{
$this->formatter = new NormalizerFormatter();
$this->processor = new PsrLogMessageProcessor();
}

public function processLogMessage($message, $context)
{
$processor = $this->processor;

return $processor([
'message' => (string) $message,
'context' => $this->formatter->format($context)
]);
}
}
60 changes: 60 additions & 0 deletions Logging/src/LogMessageProcessor/MonologV3MessageProcessor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php
/**
* Copyright 2022 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

namespace Google\Cloud\Logging\LogMessageProcessor;

use Google\Cloud\Logging\LogMessageProcessor;
use Monolog\Level;
use Monolog\LogRecord;
use Monolog\Processor\PsrLogMessageProcessor;

/**
* Uses the Monolog 3 PsrLogMessageProcessor to process a
* record's message according to PSR-3 rules.
*/
final class MonologV3MessageProcessor implements LogMessageProcessor
{
/**
* @var PsrLogMessageProcessor
*/
private $processor;

public function __construct()
{
$this->processor = new PsrLogMessageProcessor();
}

public function processLogMessage($message, $context)
{
// The datetime, channel, and level are required but not relevant here
$logRecord = new LogRecord(
new \DateTimeImmutable(),
'channel',
Level::Info,
(string) $message,
$context
);

$processor = $this->processor;
$processed = $processor($logRecord);

return [
'message' => $processed['message'],
'context' => $processed['context'],
];
}
}
47 changes: 47 additions & 0 deletions Logging/src/LogMessageProcessorFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php
/**
* Copyright 2022 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

namespace Google\Cloud\Logging;

use Google\Cloud\Logging\LogMessageProcessor\MonologMessageProcessor;
use Google\Cloud\Logging\LogMessageProcessor\MonologV3MessageProcessor;
use Monolog\Logger as MonologLogger;
use RuntimeException;

/**
* Returns a LogMessageProcessor that can be used with the currently install Monolog version
*/
class LogMessageProcessorFactory
{
/**
* @return LogMessageProcessor
*/
public static function build()
{
$version = defined('\Monolog\Logger::API') ? MonologLogger::API : 1;

switch ($version) {
case 1:
case 2:
return new MonologMessageProcessor();
case 3:
return new MonologV3MessageProcessor();
default:
throw new RuntimeException('Version not supported');
}
}
}
15 changes: 7 additions & 8 deletions Logging/src/PsrLogger.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
use Google\Cloud\Core\Report\MetadataProviderInterface;
use Google\Cloud\Core\Report\MetadataProviderUtils;
use Google\Cloud\Core\Timestamp;
use Monolog\Formatter\NormalizerFormatter;
use Monolog\Processor\PsrLogMessageProcessor;
use Psr\Log\InvalidArgumentException;
use Psr\Log\LoggerInterface;

Expand Down Expand Up @@ -89,6 +87,11 @@ class PsrLogger implements LoggerInterface, \Serializable
*/
private $logName;

/**
* @var LogMessageProcessor
*/
private $logMessageProcessor;

/**
* @param Logger $logger The logger used to write entries.
* @param string $messageKey The key in the `jsonPayload` used to contain
Expand Down Expand Up @@ -138,6 +141,7 @@ public function __construct(
) {
$this->logger = $logger;
$this->logName = $logger->name();
$this->logMessageProcessor = LogMessageProcessorFactory::build();
$this->messageKey = $messageKey ?: 'message';
$this->metadataProvider = isset($options['metadataProvider'])
? $options['metadataProvider']
Expand Down Expand Up @@ -383,12 +387,7 @@ public function log($level, $message, array $context = [])
unset($context['stackdriverOptions']);
}

$formatter = new NormalizerFormatter();
$processor = new PsrLogMessageProcessor();
$processedData = $processor([
'message' => (string) $message,
'context' => $formatter->format($context)
]);
$processedData = $this->logMessageProcessor->processLogMessage($message, $context);
$jsonPayload = [$this->messageKey => $processedData['message']];

// Adding labels for log request correlation.
Expand Down
3 changes: 0 additions & 3 deletions Logging/tests/Unit/PsrLoggerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,10 @@

namespace Google\Cloud\Logging\Tests\Unit;

use Google\Cloud\Core\Batch\BatchRunner;
use Google\Cloud\Core\Batch\OpisClosureSerializer;
use Google\Cloud\Core\Report\EmptyMetadataProvider;
use Google\Cloud\Logging\Logger;
use Google\Cloud\Logging\PsrLogger;
use Google\Cloud\Logging\Connection\ConnectionInterface;
use Prophecy\Argument;
use Yoast\PHPUnitPolyfills\TestCases\TestCase;
use Yoast\PHPUnitPolyfills\Polyfills\ExpectException;

Expand Down

0 comments on commit bf29fc7

Please sign in to comment.