friendica-addons/monolog/vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php

200 lines
6.1 KiB
PHP
Raw Normal View History

2022-10-17 21:25:03 +02:00
<?php declare(strict_types=1);
/*
* This file is part of the Monolog package.
*
* (c) Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Monolog\Handler;
2023-01-18 00:17:49 +01:00
use Monolog\Logger;
2022-10-17 21:25:03 +02:00
use Monolog\Utils;
use Monolog\Formatter\NormalizerFormatter;
use Monolog\Formatter\FormatterInterface;
/**
* Class to record a log on a NewRelic application.
* Enabling New Relic High Security mode may prevent capture of useful information.
*
2023-01-18 00:17:49 +01:00
* This handler requires a NormalizerFormatter to function and expects an array in $record['formatted']
2022-10-17 21:25:03 +02:00
*
* @see https://docs.newrelic.com/docs/agents/php-agent
* @see https://docs.newrelic.com/docs/accounts-partnerships/accounts/security/high-security
*/
class NewRelicHandler extends AbstractProcessingHandler
{
/**
2023-01-18 00:17:49 +01:00
* Name of the New Relic application that will receive logs from this handler.
*
* @var ?string
*/
protected $appName;
/**
* Name of the current transaction
*
* @var ?string
*/
protected $transactionName;
/**
* Some context and extra data is passed into the handler as arrays of values. Do we send them as is
* (useful if we are using the API), or explode them for display on the NewRelic RPM website?
*
* @var bool
*/
protected $explodeArrays;
/**
* {@inheritDoc}
*
* @param string|null $appName
* @param bool $explodeArrays
* @param string|null $transactionName
2022-10-17 21:25:03 +02:00
*/
public function __construct(
2023-01-18 00:17:49 +01:00
$level = Logger::ERROR,
2022-10-17 21:25:03 +02:00
bool $bubble = true,
2023-01-18 00:17:49 +01:00
?string $appName = null,
bool $explodeArrays = false,
?string $transactionName = null
2022-10-17 21:25:03 +02:00
) {
parent::__construct($level, $bubble);
2023-01-18 00:17:49 +01:00
$this->appName = $appName;
$this->explodeArrays = $explodeArrays;
$this->transactionName = $transactionName;
2022-10-17 21:25:03 +02:00
}
/**
2023-01-18 00:17:49 +01:00
* {@inheritDoc}
2022-10-17 21:25:03 +02:00
*/
2023-01-18 00:17:49 +01:00
protected function write(array $record): void
2022-10-17 21:25:03 +02:00
{
if (!$this->isNewRelicEnabled()) {
throw new MissingExtensionException('The newrelic PHP extension is required to use the NewRelicHandler');
}
2023-01-18 00:17:49 +01:00
if ($appName = $this->getAppName($record['context'])) {
2022-10-17 21:25:03 +02:00
$this->setNewRelicAppName($appName);
}
2023-01-18 00:17:49 +01:00
if ($transactionName = $this->getTransactionName($record['context'])) {
2022-10-17 21:25:03 +02:00
$this->setNewRelicTransactionName($transactionName);
2023-01-18 00:17:49 +01:00
unset($record['formatted']['context']['transaction_name']);
2022-10-17 21:25:03 +02:00
}
2023-01-18 00:17:49 +01:00
if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Throwable) {
newrelic_notice_error($record['message'], $record['context']['exception']);
unset($record['formatted']['context']['exception']);
2022-10-17 21:25:03 +02:00
} else {
2023-01-18 00:17:49 +01:00
newrelic_notice_error($record['message']);
2022-10-17 21:25:03 +02:00
}
2023-01-18 00:17:49 +01:00
if (isset($record['formatted']['context']) && is_array($record['formatted']['context'])) {
foreach ($record['formatted']['context'] as $key => $parameter) {
2022-10-17 21:25:03 +02:00
if (is_array($parameter) && $this->explodeArrays) {
foreach ($parameter as $paramKey => $paramValue) {
$this->setNewRelicParameter('context_' . $key . '_' . $paramKey, $paramValue);
}
} else {
$this->setNewRelicParameter('context_' . $key, $parameter);
}
}
}
2023-01-18 00:17:49 +01:00
if (isset($record['formatted']['extra']) && is_array($record['formatted']['extra'])) {
foreach ($record['formatted']['extra'] as $key => $parameter) {
2022-10-17 21:25:03 +02:00
if (is_array($parameter) && $this->explodeArrays) {
foreach ($parameter as $paramKey => $paramValue) {
$this->setNewRelicParameter('extra_' . $key . '_' . $paramKey, $paramValue);
}
} else {
$this->setNewRelicParameter('extra_' . $key, $parameter);
}
}
}
}
/**
* Checks whether the NewRelic extension is enabled in the system.
2023-01-18 00:17:49 +01:00
*
* @return bool
2022-10-17 21:25:03 +02:00
*/
protected function isNewRelicEnabled(): bool
{
return extension_loaded('newrelic');
}
/**
* Returns the appname where this log should be sent. Each log can override the default appname, set in this
* handler's constructor, by providing the appname in it's context.
*
* @param mixed[] $context
*/
protected function getAppName(array $context): ?string
{
if (isset($context['appname'])) {
return $context['appname'];
}
return $this->appName;
}
/**
* Returns the name of the current transaction. Each log can override the default transaction name, set in this
* handler's constructor, by providing the transaction_name in it's context
*
* @param mixed[] $context
*/
protected function getTransactionName(array $context): ?string
{
if (isset($context['transaction_name'])) {
return $context['transaction_name'];
}
return $this->transactionName;
}
/**
* Sets the NewRelic application that should receive this log.
*/
protected function setNewRelicAppName(string $appName): void
{
newrelic_set_appname($appName);
}
/**
* Overwrites the name of the current transaction
*/
protected function setNewRelicTransactionName(string $transactionName): void
{
newrelic_name_transaction($transactionName);
}
/**
2023-01-18 00:17:49 +01:00
* @param string $key
* @param mixed $value
2022-10-17 21:25:03 +02:00
*/
protected function setNewRelicParameter(string $key, $value): void
{
if (null === $value || is_scalar($value)) {
newrelic_add_custom_parameter($key, $value);
} else {
newrelic_add_custom_parameter($key, Utils::jsonEncode($value, null, true));
}
}
/**
2023-01-18 00:17:49 +01:00
* {@inheritDoc}
2022-10-17 21:25:03 +02:00
*/
protected function getDefaultFormatter(): FormatterInterface
{
return new NormalizerFormatter();
}
}