Файловый менеджер - Редактировать - /var/www/html/monolog.zip
Ðазад
PK ! ����� � MwlogHandler.phpnu �Iw�� <?php /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * http://www.gnu.org/copyleft/gpl.html * * @file */ namespace MediaWiki\Logger\Monolog; use Monolog\Handler\SyslogUdpHandler; use Monolog\Logger; /** * Write logs to syslog with the channel appended to the application name. * * This use case for this handler is to emulate Wikimedia Foundation's * udp2log system by leveraging syslog (and e.g. Rsyslog/Kafka) and * allow an unstructured string to pass through mostly as-is, with the * exception of the channel name, which is encoded in transit as part * of the syslog "application name". It is intended that the syslog * consumer "wildcard" subscribes to all messages with the app prefix, * and then * strips it off at some point before writing the messages * to a log file named after the channel. * * Transition plan (2016): * - https://phabricator.wikimedia.org/T205856#4957430 * - https://phabricator.wikimedia.org/T126989 * * @unstable * @since 1.32 * @ingroup Debug * @copyright © 2019 Wikimedia Foundation and contributors */ class MwlogHandler extends SyslogUdpHandler { /** * @var string */ private $appprefix; /** * @var string */ private $hostname; /** * @param string $appprefix Application prefix to use, channel will be appended. * @param string $host Syslog host * @param int $port Syslog port * @param int $facility Syslog message facility * @param int $level The minimum logging level at which this handler * will be triggered * @param bool $bubble Whether the messages that are handled can bubble up * the stack or not */ public function __construct( $appprefix, $host, $port = 514, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true ) { parent::__construct( $host, $port, $facility, $level, $bubble ); $this->appprefix = $appprefix; $this->hostname = php_uname( 'n' ); } protected function syslogHeader( $severity, $app ) { $pri = $severity + $this->facility; // Goofy date format courtesy of RFC 3164 :( // RFC 3164 actually specifies that the day of month should be space // padded rather than unpadded but this seems to work with rsyslog and // Logstash. $timestamp = date( 'M j H:i:s' ); return "<{$pri}>{$timestamp} {$this->hostname} {$app}: "; } private function splitMessageIntoLines( $message ): array { if ( is_array( $message ) ) { $message = implode( "\n", $message ); } return preg_split( '/$\R?^/m', (string)$message, -1, PREG_SPLIT_NO_EMPTY ); } protected function write( array $record ): void { $lines = $this->splitMessageIntoLines( $record['formatted'] ); $header = $this->syslogHeader( $this->logLevels[$record['level']], $this->appprefix . $record['channel'] ); foreach ( $lines as $line ) { $this->socket->write( $line, $header ); } } } PK ! w�~S� � LegacyHandler.phpnu �Iw�� <?php /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * http://www.gnu.org/copyleft/gpl.html * * @file */ namespace MediaWiki\Logger\Monolog; use LogicException; use MediaWiki\Logger\LegacyLogger; use Monolog\Handler\AbstractProcessingHandler; use Monolog\Logger; use Socket; use UnexpectedValueException; /** * Monolog imitation of MediaWiki\Logger\LegacyLogger * * This replicates the behavior of LegacyLogger, which in turn replicates * MediaWiki's former wfErrorLog() function. * * The main use case of the LegacyHandler is to enable adoption of Monolog * features (such as alternate formatters, extra processors, and enabling multiple * destinations/handlers at the same time), where one of the handlers (this one) * essentiallly does what the LegacySpi would do if you hadn't enabled * MonologSpi. In particular: writing to a file like $wgDebugLogFile, * and sending messages to a PHP stream or udp2log server. * * For udp2log output, the stream specification must have the form: * "udp://HOST:PORT[/PREFIX]" * where: * * - HOST: IPv4, IPv6 or hostname * - PORT: server port * - PREFIX: optional (but recommended) prefix telling udp2log how to route * the log event. The special prefix "{channel}" will use the log event's * channel as the prefix value. * * When not targeting a udp2log server, this class will act as a drop-in * replacement for \Monolog\Handler\StreamHandler. * * @since 1.25 * @ingroup Debug * @copyright © 2013 Wikimedia Foundation and contributors */ class LegacyHandler extends AbstractProcessingHandler { /** * Log sink descriptor * @var string */ protected $uri; /** * Filter log events using legacy rules * @var bool */ protected $useLegacyFilter; /** * Log sink * @var Socket|resource|null */ protected $sink; /** * @var string|null */ protected $error; /** * @var string */ protected $host; /** * @var int */ protected $port; /** * @var string */ protected $prefix; /** * @param string $stream Stream URI * @param bool $useLegacyFilter Filter log events using legacy rules * @param int $level Minimum logging level that will trigger handler * @param bool $bubble Can handled messages bubble up the handler stack? */ public function __construct( $stream, $useLegacyFilter = false, $level = Logger::DEBUG, $bubble = true ) { parent::__construct( $level, $bubble ); $this->uri = $stream; $this->useLegacyFilter = $useLegacyFilter; } /** * Open the log sink described by our stream URI. */ protected function openSink() { if ( !$this->uri ) { throw new LogicException( 'Missing stream uri, the stream can not be opened.' ); } $this->error = null; set_error_handler( [ $this, 'errorTrap' ] ); if ( str_starts_with( $this->uri, 'udp:' ) ) { $parsed = parse_url( $this->uri ); if ( !isset( $parsed['host'] ) ) { throw new UnexpectedValueException( sprintf( 'Udp transport "%s" must specify a host', $this->uri ) ); } if ( !isset( $parsed['port'] ) ) { throw new UnexpectedValueException( sprintf( 'Udp transport "%s" must specify a port', $this->uri ) ); } $this->host = $parsed['host']; $this->port = $parsed['port']; $this->prefix = ''; if ( isset( $parsed['path'] ) ) { $this->prefix = ltrim( $parsed['path'], '/' ); } if ( filter_var( $this->host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) ) { $domain = AF_INET6; } else { $domain = AF_INET; } $this->sink = socket_create( $domain, SOCK_DGRAM, SOL_UDP ); } else { $this->sink = fopen( $this->uri, 'a' ); } restore_error_handler(); if ( !$this->sink ) { $this->sink = null; throw new UnexpectedValueException( sprintf( 'The stream or file "%s" could not be opened: %s', // @phan-suppress-next-line PhanTypeMismatchArgumentInternalProbablyReal Set by error handler $this->uri, $this->error ) ); } } /** * Custom error handler. * @param int $code Error number * @param string $msg Error message */ protected function errorTrap( $code, $msg ) { $this->error = $msg; } /** * Should we use UDP to send messages to the sink? * @return bool */ protected function useUdp() { return $this->host !== null; } protected function write( array $record ): void { if ( $this->useLegacyFilter && !LegacyLogger::shouldEmit( $record['channel'], $record['message'], $record['level'], $record ) ) { // Do not write record if we are enforcing legacy rules and they // do not pass this message. This used to be done in isHandling(), // but Monolog 1.12.0 made a breaking change that removed access // to the needed channel and context information. return; } if ( $this->sink === null ) { $this->openSink(); } $text = (string)$record['formatted']; if ( $this->useUdp() ) { // Clean it up for the multiplexer if ( $this->prefix !== '' ) { $leader = ( $this->prefix === '{channel}' ) ? $record['channel'] : $this->prefix; $text = preg_replace( '/^/m', "{$leader} ", $text ); // Limit to 64 KiB if ( strlen( $text ) > 65506 ) { $text = substr( $text, 0, 65506 ); } if ( !str_ends_with( $text, "\n" ) ) { $text .= "\n"; } } elseif ( strlen( $text ) > 65507 ) { $text = substr( $text, 0, 65507 ); } socket_sendto( $this->sink, $text, strlen( $text ), 0, $this->host, $this->port ); } else { fwrite( $this->sink, $text ); } } public function close(): void { if ( $this->sink ) { if ( $this->useUdp() ) { socket_close( $this->sink ); } else { fclose( $this->sink ); } } $this->sink = null; } } PK ! ��M) ) LegacyFormatter.phpnu �Iw�� <?php /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * http://www.gnu.org/copyleft/gpl.html * * @file */ namespace MediaWiki\Logger\Monolog; use MediaWiki\Logger\LegacyLogger; use Monolog\Formatter\NormalizerFormatter; /** * Log message formatter that mimics the legacy log message formatting of `wfDebug`, `wfDebugLog`, * `wfLogDBError` and the former `wfErrorLog` global functions by delegating the formatting to * \MediaWiki\Logger\LegacyLogger. * * @deprecated since 1.32 * @since 1.25 * @ingroup Debug * @copyright © 2013 Wikimedia Foundation and contributors */ class LegacyFormatter extends NormalizerFormatter { public function __construct() { parent::__construct( 'c' ); } public function format( array $record ): string { $normalized = parent::format( $record ); return LegacyLogger::format( $normalized['channel'], $normalized['message'], $normalized ); } } PK ! l�_�# # SyslogHandler.phpnu �Iw�� <?php /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * http://www.gnu.org/copyleft/gpl.html * * @file */ namespace MediaWiki\Logger\Monolog; use DateTimeInterface; use Monolog\Handler\SyslogUdpHandler; use Monolog\Logger; /** * Write logs to a syslog server, using RFC 3164 formatted UDP packets. * * This builds on Monolog's SyslogUdpHandler, which creates only a partial * RFC 5424 header (PRI and VERSION), with rest intending to come * from a specifically configured LineFormatter. * * This makes use of SyslogUdpHandler it impossible with a formatter like * \Monolog\Formatter\LogstashFormatter. Additionally, the direct syslog * input for Logstash requires and accepts only RFC 3164 formatted packets. * * This is a complete syslog handler and should work with any formatter. The * formatted message will be prepended with a complete RFC 3164 message * header and a partial message body. The resulting packet looks like: * * <PRI>DATETIME HOSTNAME PROGRAM: MESSAGE * * This format works as input to rsyslog and can also be processed by the * default Logstash syslog input handler. * * @since 1.25 * @ingroup Debug * @copyright © 2015 Wikimedia Foundation and contributors */ class SyslogHandler extends SyslogUdpHandler { private string $appname; private string $hostname; /** * @param string $appname Application name to report to syslog * @param string $host Syslog host * @param int $port Syslog port * @param int $facility Syslog message facility * @param int $level The minimum logging level at which this handler * will be triggered * @param bool $bubble Whether the messages that are handled can bubble up * the stack or not */ public function __construct( $appname, $host, $port = 514, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true ) { parent::__construct( $host, $port, $facility, $level, $bubble ); $this->appname = $appname; $this->hostname = php_uname( 'n' ); } protected function makeCommonSyslogHeader( int $severity, DateTimeInterface $datetime ): string { $pri = $severity + $this->facility; // Goofy date format courtesy of RFC 3164 :( // RFC 3164 actually specifies that the day of month should be space // padded rather than unpadded but this seems to work with rsyslog and // Logstash. $timestamp = date( 'M j H:i:s' ); return "<{$pri}>{$timestamp} {$this->hostname} {$this->appname}: "; } } PK ! ?�yD D CeeFormatter.phpnu �Iw�� <?php namespace MediaWiki\Logger\Monolog; /** * Prefixed version of LogstashFormatter that adds a "cee cookie" for Rsyslog. * * The prefix lets Ryslog differentiate between JSON and non-JSON messages. * * See also: https://www.rsyslog.com/doc/v8-stable/configuration/modules/mmjsonparse.html * * @since 1.33 * @ingroup Debug */ class CeeFormatter extends LogstashFormatter { /** * Format records with a cee cookie * @param array $record * @return string */ public function format( array $record ): string { return "@cee: " . parent::format( $record ); } } PK ! ���c c LineFormatter.phpnu �Iw�� <?php /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * http://www.gnu.org/copyleft/gpl.html * * @file */ namespace MediaWiki\Logger\Monolog; use Error; use Monolog\Formatter\LineFormatter as MonologLineFormatter; use MWExceptionHandler; use Throwable; /** * Formats incoming records into a one-line string. * * An 'exeception' in the log record's context will be treated specially. * It will be output for an '%exception%' placeholder in the format and * excluded from '%context%' output if the '%exception%' placeholder is * present. * * Throwables that are logged with this formatter will optional have their * stack traces appended. If that is done, MWExceptionHandler::redactedTrace() * will be used to redact the trace information. * * @since 1.26 * @ingroup Debug * @copyright © 2015 Wikimedia Foundation and contributors */ class LineFormatter extends MonologLineFormatter { /** * @param string|null $format The format of the message * @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format * @param bool $allowInlineLineBreaks Whether to allow inline line breaks in log entries * @param bool $ignoreEmptyContextAndExtra * @param bool $includeStacktraces */ public function __construct( $format = null, $dateFormat = null, $allowInlineLineBreaks = false, $ignoreEmptyContextAndExtra = false, $includeStacktraces = false ) { parent::__construct( $format, $dateFormat, $allowInlineLineBreaks, $ignoreEmptyContextAndExtra ); $this->includeStacktraces( $includeStacktraces ); } /** * @inheritDoc */ public function format( array $record ): string { // Drop the 'private' flag from the context unset( $record['context']['private'] ); // Handle throwables specially: pretty format and remove from context // Will be output for a '%exception%' placeholder in format $prettyException = ''; if ( isset( $record['context']['exception'] ) && str_contains( $this->format, '%exception%' ) ) { $e = $record['context']['exception']; unset( $record['context']['exception'] ); if ( $e instanceof Throwable ) { $prettyException = $this->normalizeException( $e ); } elseif ( is_array( $e ) ) { $prettyException = $this->normalizeExceptionArray( $e ); } else { $prettyException = $this->stringify( $e ); } } $output = parent::format( $record ); if ( str_contains( $output, '%exception%' ) ) { $output = str_replace( '%exception%', $prettyException, $output ); } return $output; } /** * Convert a Throwable to a string. * * @param Throwable $e * @param int $depth * @return string */ protected function normalizeException( Throwable $e, int $depth = 0 ): string { // Can't use typehint. Must match Monolog\Formatter\LineFormatter::normalizeException($e) return $this->normalizeExceptionArray( $this->exceptionAsArray( $e ) ); } /** * Convert a throwable to an array of structured data. * * @param Throwable $e * @return array */ protected function exceptionAsArray( Throwable $e ) { $out = [ 'class' => get_class( $e ), 'message' => $e->getMessage(), 'code' => $e->getCode(), 'file' => $e->getFile(), 'line' => $e->getLine(), 'trace' => MWExceptionHandler::redactTrace( $e->getTrace() ), ]; $prev = $e->getPrevious(); if ( $prev ) { $out['previous'] = $this->exceptionAsArray( $prev ); } return $out; } /** * Convert an array of Throwable data to a string. * * @param array $e * @return string */ protected function normalizeExceptionArray( array $e ) { $defaults = [ 'class' => 'Unknown', 'file' => 'unknown', 'line' => null, 'message' => 'unknown', 'trace' => [], ]; $e = array_merge( $defaults, $e ); // @phan-suppress-next-line PhanTypeMismatchArgumentNullableInternal class is always set $which = is_a( $e['class'], Error::class, true ) ? 'Error' : 'Exception'; $str = "\n[$which {$e['class']}] (" . "{$e['file']}:{$e['line']}) {$e['message']}"; if ( $this->includeStacktraces && $e['trace'] ) { $str .= "\n" . // @phan-suppress-next-line PhanTypeMismatchArgumentNullable trace is always set MWExceptionHandler::prettyPrintTrace( $e['trace'], ' ' ); } if ( isset( $e['previous'] ) ) { $prev = $e['previous']; while ( $prev ) { $prev = array_merge( $defaults, $prev ); $which = is_a( $prev['class'], Error::class, true ) ? 'Error' : 'Exception'; $str .= "\nCaused by: [$which {$prev['class']}] (" . "{$prev['file']}:{$prev['line']}) {$prev['message']}"; if ( $this->includeStacktraces && $prev['trace'] ) { $str .= "\n" . MWExceptionHandler::prettyPrintTrace( $prev['trace'], ' ' ); } $prev = $prev['previous'] ?? null; } } return $str; } } PK ! �Q�� � BufferHandler.phpnu �Iw�� <?php /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * http://www.gnu.org/copyleft/gpl.html * * @file */ namespace MediaWiki\Logger\Monolog; use MediaWiki\Deferred\DeferredUpdates; use Monolog\Handler\BufferHandler as BaseBufferHandler; /** * Helper class for the index.php entry point. * * Updates \Monolog\Handler\BufferHandler to use DeferredUpdates rather * than register_shutdown_function. On supported platforms this will * use register_postsend_function or fastcgi_finish_request() to delay * until after the request has shutdown and we are no longer delaying * the web request. * * TODO: shutdown is later than postsend. Is this class still useful? * * @since 1.26 * @ingroup Debug */ class BufferHandler extends BaseBufferHandler { /** * @inheritDoc */ public function handle( array $record ): bool { if ( !$this->initialized ) { DeferredUpdates::addCallableUpdate( [ $this, 'close' ] ); $this->initialized = true; } return parent::handle( $record ); } } PK ! \!cAU U WikiProcessor.phpnu �Iw�� <?php /** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * http://www.gnu.org/copyleft/gpl.html * * @file */ namespace MediaWiki\Logger\Monolog; use MediaWiki\Http\Telemetry; use MediaWiki\WikiMap\WikiMap; /** * Annotate log records with request-global metadata, such as the hostname, * wiki / request ID, and MediaWiki version. * * @since 1.25 * @ingroup Debug * @copyright © 2013 Wikimedia Foundation and contributors */ class WikiProcessor { /** * @param array $record * @return array */ public function __invoke( array $record ) { $telemetry = Telemetry::getInstance(); $record['extra']['host'] = wfHostname(); $record['extra']['wiki'] = WikiMap::getCurrentWikiId(); $record['extra']['mwversion'] = MW_VERSION; $record['extra']['reqId'] = $telemetry->getRequestId(); if ( wfIsCLI() && isset( $_SERVER['argv'] ) ) { $record['extra']['cli_argv'] = implode( ' ', $_SERVER['argv'] ); } return $record; } } PK ! �S�Z� � LogstashFormatter.phpnu �Iw�� <?php namespace MediaWiki\Logger\Monolog; /** * Modified version of Monolog\Formatter\LogstashFormatter * * - Squash the base message array, the context and extra subarrays into one. * This can result in unfortunately named context fields overwriting other data (T145133). * - Improve exception JSON-ification, which is done poorly by the standard class. * * @since 1.29 * @ingroup Debug */ class LogstashFormatter extends \Monolog\Formatter\LogstashFormatter { public const V0 = 0; public const V1 = 1; /** @var array Keys which should not be used in log context */ protected $reservedKeys = [ // from LogstashFormatter 'message', 'channel', 'level', 'type', // from WebProcessor 'url', 'ip', 'http_method', 'server', 'referrer', // from WikiProcessor 'host', 'wiki', 'reqId', 'mwversion', // from config magic 'normalized_message', ]; /** * @var int Logstash format version to use */ protected $version; /** * TODO: See T247675 for removing this override. * * @param string $applicationName The application that sends the data, used as the "type" * field of logstash * @param string|null $systemName The system/machine name, used as the "source" field of * logstash, defaults to the hostname of the machine * @param string $extraKey The key for extra keys inside logstash "fields", defaults to '' * @param string $contextKey The key for context keys inside logstash "fields", defaults * @param int $version The logstash format version to use, defaults to V0 * to '' */ public function __construct( string $applicationName, ?string $systemName = null, string $extraKey = '', string $contextKey = 'ctxt_', $version = self::V0 ) { $this->version = $version; parent::__construct( $applicationName, $systemName, $extraKey, $contextKey ); } public function format( array $record ): string { $record = \Monolog\Formatter\NormalizerFormatter::format( $record ); if ( $this->version === self::V1 ) { $message = $this->formatV1( $record ); } elseif ( $this->version === self::V0 ) { $message = $this->formatV0( $record ); } else { $message = __METHOD__ . ' unknown version ' . $this->version; } return $this->toJson( $message ) . "\n"; } /** * Prevent key conflicts * @param array $record * @return array */ protected function formatV0( array $record ) { if ( $this->contextKey !== '' ) { return $this->formatMonologV0( $record ); } $context = !empty( $record['context'] ) ? $record['context'] : []; $record['context'] = []; $formatted = $this->formatMonologV0( $record ); $formatted['@fields'] = $this->fixKeyConflicts( $formatted['@fields'], $context ); return $formatted; } /** * Borrowed from monolog/monolog 1.25.3 * https://github.com/Seldaek/monolog/blob/1.x/src/Monolog/Formatter/LogstashFormatter.php#L87-L128 * * @param array $record * @return array */ protected function formatMonologV0( array $record ) { if ( empty( $record['datetime'] ) ) { $record['datetime'] = gmdate( 'c' ); } $message = [ '@timestamp' => $record['datetime'], '@source' => $this->systemName, '@fields' => [], ]; if ( isset( $record['message'] ) ) { $message['@message'] = $record['message']; } if ( isset( $record['channel'] ) ) { $message['@tags'] = [ $record['channel'] ]; $message['@fields']['channel'] = $record['channel']; } if ( isset( $record['level'] ) ) { $message['@fields']['level'] = $record['level']; } if ( $this->applicationName ) { $message['@type'] = $this->applicationName; } if ( isset( $record['extra']['server'] ) ) { $message['@source_host'] = $record['extra']['server']; } if ( isset( $record['extra']['url'] ) ) { $message['@source_path'] = $record['extra']['url']; } if ( !empty( $record['extra'] ) ) { foreach ( $record['extra'] as $key => $val ) { $message['@fields'][$this->extraKey . $key] = $val; } } if ( !empty( $record['context'] ) ) { foreach ( $record['context'] as $key => $val ) { $message['@fields'][$this->contextKey . $key] = $val; } } return $message; } /** * Prevent key conflicts * @param array $record * @return array */ protected function formatV1( array $record ) { if ( $this->contextKey ) { return $this->formatMonologV1( $record ); } $context = !empty( $record['context'] ) ? $record['context'] : []; $record['context'] = []; $formatted = $this->formatMonologV1( $record ); return $this->fixKeyConflicts( $formatted, $context ); } /** * Borrowed mostly from monolog/monolog 1.25.3 * https://github.com/Seldaek/monolog/blob/1.25.3/src/Monolog/Formatter/LogstashFormatter.php#L130-165 * * @param array $record * @return array */ protected function formatMonologV1( array $record ) { if ( empty( $record['datetime'] ) ) { $record['datetime'] = gmdate( 'c' ); } $message = [ '@timestamp' => $record['datetime'], '@version' => 1, 'host' => $this->systemName, ]; if ( isset( $record['message'] ) ) { $message['message'] = $record['message']; } if ( isset( $record['channel'] ) ) { $message['type'] = $record['channel']; $message['channel'] = $record['channel']; } if ( isset( $record['level_name'] ) ) { $message['level'] = $record['level_name']; } // level -> monolog_level is new in 2.0 // https://github.com/Seldaek/monolog/blob/2.0.2/src/Monolog/Formatter/LogstashFormatter.php#L86-L88 if ( isset( $record['level'] ) ) { $message['monolog_level'] = $record['level']; } if ( $this->applicationName ) { $message['type'] = $this->applicationName; } if ( !empty( $record['extra'] ) ) { foreach ( $record['extra'] as $key => $val ) { $message[$this->extraKey . $key] = $val; } } if ( !empty( $record['context'] ) ) { foreach ( $record['context'] as $key => $val ) { $message[$this->contextKey . $key] = $val; } } return $message; } /** * Rename any context field that would otherwise overwrite a message key. * * @param array $fields Fields to be sent to logstash * @param array $context Copy of the original $record['context'] * @return array Updated version of $fields */ protected function fixKeyConflicts( array $fields, array $context ) { foreach ( $context as $key => $val ) { if ( in_array( $key, $this->reservedKeys, true ) && isset( $fields[$key] ) && $fields[$key] !== $val ) { $fields['logstash_formatter_key_conflict'][] = $key; $key = 'c_' . $key; } $fields[$key] = $val; } return $fields; } /** * Use a more user-friendly trace format than Monolog\Formatter\NormalizerFormatter. * * @param \Throwable $e * @param int $depth * @return array */ protected function normalizeException( \Throwable $e, int $depth = 0 ) { $data = [ 'class' => get_class( $e ), 'message' => $e->getMessage(), 'code' => $e->getCode(), 'file' => $e->getFile() . ':' . $e->getLine(), 'trace' => \MWExceptionHandler::getRedactedTraceAsString( $e ), ]; $previous = $e->getPrevious(); if ( $previous ) { $data['previous'] = $this->normalizeException( $previous ); } return $data; } } PK ! ����� � MwlogHandler.phpnu �Iw�� PK ! w�~S� � � LegacyHandler.phpnu �Iw�� PK ! ��M) ) !'