Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php declare(strict_types=1);
2
 
3
/*
4
 * This file is part of the Monolog package.
5
 *
6
 * (c) Jordi Boggiano <j.boggiano@seld.be>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
 
12
namespace Monolog\Handler;
13
 
14
use Monolog\Logger;
15
use Monolog\Utils;
16
use Monolog\Formatter\NormalizerFormatter;
17
use Monolog\Formatter\FormatterInterface;
18
 
19
/**
20
 * Class to record a log on a NewRelic application.
21
 * Enabling New Relic High Security mode may prevent capture of useful information.
22
 *
23
 * This handler requires a NormalizerFormatter to function and expects an array in $record['formatted']
24
 *
25
 * @see https://docs.newrelic.com/docs/agents/php-agent
26
 * @see https://docs.newrelic.com/docs/accounts-partnerships/accounts/security/high-security
27
 */
28
class NewRelicHandler extends AbstractProcessingHandler
29
{
30
    /**
31
     * Name of the New Relic application that will receive logs from this handler.
32
     *
33
     * @var ?string
34
     */
35
    protected $appName;
36
 
37
    /**
38
     * Name of the current transaction
39
     *
40
     * @var ?string
41
     */
42
    protected $transactionName;
43
 
44
    /**
45
     * Some context and extra data is passed into the handler as arrays of values. Do we send them as is
46
     * (useful if we are using the API), or explode them for display on the NewRelic RPM website?
47
     *
48
     * @var bool
49
     */
50
    protected $explodeArrays;
51
 
52
    /**
53
     * {@inheritDoc}
54
     *
55
     * @param string|null $appName
56
     * @param bool        $explodeArrays
57
     * @param string|null $transactionName
58
     */
59
    public function __construct(
60
        $level = Logger::ERROR,
61
        bool $bubble = true,
62
        ?string $appName = null,
63
        bool $explodeArrays = false,
64
        ?string $transactionName = null
65
    ) {
66
        parent::__construct($level, $bubble);
67
 
68
        $this->appName       = $appName;
69
        $this->explodeArrays = $explodeArrays;
70
        $this->transactionName = $transactionName;
71
    }
72
 
73
    /**
74
     * {@inheritDoc}
75
     */
76
    protected function write(array $record): void
77
    {
78
        if (!$this->isNewRelicEnabled()) {
79
            throw new MissingExtensionException('The newrelic PHP extension is required to use the NewRelicHandler');
80
        }
81
 
82
        if ($appName = $this->getAppName($record['context'])) {
83
            $this->setNewRelicAppName($appName);
84
        }
85
 
86
        if ($transactionName = $this->getTransactionName($record['context'])) {
87
            $this->setNewRelicTransactionName($transactionName);
88
            unset($record['formatted']['context']['transaction_name']);
89
        }
90
 
91
        if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Throwable) {
92
            newrelic_notice_error($record['message'], $record['context']['exception']);
93
            unset($record['formatted']['context']['exception']);
94
        } else {
95
            newrelic_notice_error($record['message']);
96
        }
97
 
98
        if (isset($record['formatted']['context']) && is_array($record['formatted']['context'])) {
99
            foreach ($record['formatted']['context'] as $key => $parameter) {
100
                if (is_array($parameter) && $this->explodeArrays) {
101
                    foreach ($parameter as $paramKey => $paramValue) {
102
                        $this->setNewRelicParameter('context_' . $key . '_' . $paramKey, $paramValue);
103
                    }
104
                } else {
105
                    $this->setNewRelicParameter('context_' . $key, $parameter);
106
                }
107
            }
108
        }
109
 
110
        if (isset($record['formatted']['extra']) && is_array($record['formatted']['extra'])) {
111
            foreach ($record['formatted']['extra'] as $key => $parameter) {
112
                if (is_array($parameter) && $this->explodeArrays) {
113
                    foreach ($parameter as $paramKey => $paramValue) {
114
                        $this->setNewRelicParameter('extra_' . $key . '_' . $paramKey, $paramValue);
115
                    }
116
                } else {
117
                    $this->setNewRelicParameter('extra_' . $key, $parameter);
118
                }
119
            }
120
        }
121
    }
122
 
123
    /**
124
     * Checks whether the NewRelic extension is enabled in the system.
125
     *
126
     * @return bool
127
     */
128
    protected function isNewRelicEnabled(): bool
129
    {
130
        return extension_loaded('newrelic');
131
    }
132
 
133
    /**
134
     * Returns the appname where this log should be sent. Each log can override the default appname, set in this
135
     * handler's constructor, by providing the appname in it's context.
136
     *
137
     * @param mixed[] $context
138
     */
139
    protected function getAppName(array $context): ?string
140
    {
141
        if (isset($context['appname'])) {
142
            return $context['appname'];
143
        }
144
 
145
        return $this->appName;
146
    }
147
 
148
    /**
149
     * Returns the name of the current transaction. Each log can override the default transaction name, set in this
150
     * handler's constructor, by providing the transaction_name in it's context
151
     *
152
     * @param mixed[] $context
153
     */
154
    protected function getTransactionName(array $context): ?string
155
    {
156
        if (isset($context['transaction_name'])) {
157
            return $context['transaction_name'];
158
        }
159
 
160
        return $this->transactionName;
161
    }
162
 
163
    /**
164
     * Sets the NewRelic application that should receive this log.
165
     */
166
    protected function setNewRelicAppName(string $appName): void
167
    {
168
        newrelic_set_appname($appName);
169
    }
170
 
171
    /**
172
     * Overwrites the name of the current transaction
173
     */
174
    protected function setNewRelicTransactionName(string $transactionName): void
175
    {
176
        newrelic_name_transaction($transactionName);
177
    }
178
 
179
    /**
180
     * @param string $key
181
     * @param mixed  $value
182
     */
183
    protected function setNewRelicParameter(string $key, $value): void
184
    {
185
        if (null === $value || is_scalar($value)) {
186
            newrelic_add_custom_parameter($key, $value);
187
        } else {
188
            newrelic_add_custom_parameter($key, Utils::jsonEncode($value, null, true));
189
        }
190
    }
191
 
192
    /**
193
     * {@inheritDoc}
194
     */
195
    protected function getDefaultFormatter(): FormatterInterface
196
    {
197
        return new NormalizerFormatter();
198
    }
199
}