first commit
This commit is contained in:
19
wp-content/plugins/wp-optimize/vendor/monolog/monolog/LICENSE
vendored
Normal file
19
wp-content/plugins/wp-optimize/vendor/monolog/monolog/LICENSE
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2011-2020 Jordi Boggiano
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
1
wp-content/plugins/wp-optimize/vendor/monolog/monolog/_config.yml
vendored
Normal file
1
wp-content/plugins/wp-optimize/vendor/monolog/monolog/_config.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
theme: jekyll-theme-slate
|
||||
244
wp-content/plugins/wp-optimize/vendor/monolog/monolog/doc/01-usage.md
vendored
Normal file
244
wp-content/plugins/wp-optimize/vendor/monolog/monolog/doc/01-usage.md
vendored
Normal file
@@ -0,0 +1,244 @@
|
||||
# Using Monolog
|
||||
|
||||
- [Installation](#installation)
|
||||
- [Core Concepts](#core-concepts)
|
||||
- [Log Levels](#log-levels)
|
||||
- [Configuring a logger](#configuring-a-logger)
|
||||
- [Adding extra data in the records](#adding-extra-data-in-the-records)
|
||||
- [Leveraging channels](#leveraging-channels)
|
||||
- [Customizing the log format](#customizing-the-log-format)
|
||||
- [Long running processes and avoiding memory leaks](#long-running-processes-and-avoiding-memory-leaks)
|
||||
|
||||
## Installation
|
||||
|
||||
Monolog is available on Packagist ([monolog/monolog](http://packagist.org/packages/monolog/monolog))
|
||||
and as such installable via [Composer](http://getcomposer.org/).
|
||||
|
||||
```bash
|
||||
composer require monolog/monolog
|
||||
```
|
||||
|
||||
## Core Concepts
|
||||
|
||||
Every `Logger` instance has a channel (name) and a stack of handlers. Whenever
|
||||
you add a [record](message-structure.md) to the logger, it traverses the handler stack. Each handler
|
||||
decides whether it fully handled the record, and if so, the propagation of the
|
||||
record ends there.
|
||||
|
||||
This allows for flexible logging setups, for example having a `StreamHandler` at
|
||||
the bottom of the stack that will log anything to disk, and on top of that add
|
||||
a `MailHandler` that will send emails only when an error message is logged.
|
||||
Handlers also have a `$bubble` property which defines whether they block the
|
||||
record or not if they handled it. In this example, setting the `MailHandler`'s
|
||||
`$bubble` argument to false means that records handled by the `MailHandler` will
|
||||
not propagate to the `StreamHandler` anymore.
|
||||
|
||||
You can create many `Logger`s, each defining a channel (e.g.: db, request,
|
||||
router, ..) and each of them combining various handlers, which can be shared
|
||||
or not. The channel is reflected in the logs and allows you to easily see or
|
||||
filter records.
|
||||
|
||||
Each Handler also has a Formatter, a default one with settings that make sense
|
||||
will be created if you don't set one. The formatters normalize and format
|
||||
incoming records so that they can be used by the handlers to output useful
|
||||
information.
|
||||
|
||||
Custom severity levels are not available. Only the eight
|
||||
[RFC 5424](http://tools.ietf.org/html/rfc5424) levels (debug, info, notice,
|
||||
warning, error, critical, alert, emergency) are present for basic filtering
|
||||
purposes, but for sorting and other use cases that would require
|
||||
flexibility, you should add Processors to the Logger that can add extra
|
||||
information (tags, user ip, ..) to the records before they are handled.
|
||||
|
||||
## Log Levels
|
||||
|
||||
Monolog supports the logging levels described by [RFC 5424](http://tools.ietf.org/html/rfc5424).
|
||||
|
||||
- **DEBUG** (100): Detailed debug information.
|
||||
|
||||
- **INFO** (200): Interesting events. Examples: User logs in, SQL logs.
|
||||
|
||||
- **NOTICE** (250): Normal but significant events.
|
||||
|
||||
- **WARNING** (300): Exceptional occurrences that are not errors. Examples:
|
||||
Use of deprecated APIs, poor use of an API, undesirable things that are not
|
||||
necessarily wrong.
|
||||
|
||||
- **ERROR** (400): Runtime errors that do not require immediate action but
|
||||
should typically be logged and monitored.
|
||||
|
||||
- **CRITICAL** (500): Critical conditions. Example: Application component
|
||||
unavailable, unexpected exception.
|
||||
|
||||
- **ALERT** (550): Action must be taken immediately. Example: Entire website
|
||||
down, database unavailable, etc. This should trigger the SMS alerts and wake
|
||||
you up.
|
||||
|
||||
- **EMERGENCY** (600): Emergency: system is unusable.
|
||||
|
||||
## Configuring a logger
|
||||
|
||||
Here is a basic setup to log to a file and to firephp on the DEBUG level:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\Handler\StreamHandler;
|
||||
use Monolog\Handler\FirePHPHandler;
|
||||
|
||||
// Create the logger
|
||||
$logger = new Logger('my_logger');
|
||||
// Now add some handlers
|
||||
$logger->pushHandler(new StreamHandler(__DIR__.'/my_app.log', Logger::DEBUG));
|
||||
$logger->pushHandler(new FirePHPHandler());
|
||||
|
||||
// You can now use your logger
|
||||
$logger->info('My logger is now ready');
|
||||
```
|
||||
|
||||
Let's explain it. The first step is to create the logger instance which will
|
||||
be used in your code. The argument is a channel name, which is useful when
|
||||
you use several loggers (see below for more details about it).
|
||||
|
||||
The logger itself does not know how to handle a record. It delegates it to
|
||||
some handlers. The code above registers two handlers in the stack to allow
|
||||
handling records in two different ways.
|
||||
|
||||
Note that the FirePHPHandler is called first as it is added on top of the
|
||||
stack. This allows you to temporarily add a logger with bubbling disabled if
|
||||
you want to override other configured loggers.
|
||||
|
||||
## Adding extra data in the records
|
||||
|
||||
Monolog provides two different ways to add extra information along the simple
|
||||
textual message.
|
||||
|
||||
### Using the logging context
|
||||
|
||||
The first way is the context, allowing to pass an array of data along the
|
||||
record:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
$logger->info('Adding a new user', ['username' => 'Seldaek']);
|
||||
```
|
||||
|
||||
Simple handlers (like the StreamHandler for instance) will simply format
|
||||
the array to a string but richer handlers can take advantage of the context
|
||||
(FirePHP is able to display arrays in pretty way for instance).
|
||||
|
||||
### Using processors
|
||||
|
||||
The second way is to add extra data for all records by using a processor.
|
||||
Processors can be any callable. They will get the record as parameter and
|
||||
must return it after having eventually changed the `extra` part of it. Let's
|
||||
write a processor adding some dummy data in the record:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
$logger->pushProcessor(function ($record) {
|
||||
$record['extra']['dummy'] = 'Hello world!';
|
||||
|
||||
return $record;
|
||||
});
|
||||
```
|
||||
|
||||
Monolog provides some built-in processors that can be used in your project.
|
||||
Look at the [dedicated chapter](https://github.com/Seldaek/monolog/blob/master/doc/02-handlers-formatters-processors.md#processors) for the list.
|
||||
|
||||
> Tip: processors can also be registered on a specific handler instead of
|
||||
the logger to apply only for this handler.
|
||||
|
||||
## Leveraging channels
|
||||
|
||||
Channels are a great way to identify to which part of the application a record
|
||||
is related. This is useful in big applications (and is leveraged by
|
||||
MonologBundle in Symfony).
|
||||
|
||||
Picture two loggers sharing a handler that writes to a single log file.
|
||||
Channels would allow you to identify the logger that issued every record.
|
||||
You can easily grep through the log files filtering this or that channel.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\Handler\StreamHandler;
|
||||
use Monolog\Handler\FirePHPHandler;
|
||||
|
||||
// Create some handlers
|
||||
$stream = new StreamHandler(__DIR__.'/my_app.log', Logger::DEBUG);
|
||||
$firephp = new FirePHPHandler();
|
||||
|
||||
// Create the main logger of the app
|
||||
$logger = new Logger('my_logger');
|
||||
$logger->pushHandler($stream);
|
||||
$logger->pushHandler($firephp);
|
||||
|
||||
// Create a logger for the security-related stuff with a different channel
|
||||
$securityLogger = new Logger('security');
|
||||
$securityLogger->pushHandler($stream);
|
||||
$securityLogger->pushHandler($firephp);
|
||||
|
||||
// Or clone the first one to only change the channel
|
||||
$securityLogger = $logger->withName('security');
|
||||
```
|
||||
|
||||
## Customizing the log format
|
||||
|
||||
In Monolog it's easy to customize the format of the logs written into files,
|
||||
sockets, mails, databases and other handlers. Most of the handlers use the
|
||||
|
||||
```php
|
||||
$record['formatted']
|
||||
```
|
||||
|
||||
value to be automatically put into the log device. This value depends on the
|
||||
formatter settings. You can choose between predefined formatter classes or
|
||||
write your own (e.g. a multiline text file for human-readable output).
|
||||
|
||||
To configure a predefined formatter class, just set it as the handler's field:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
// the default date format is "Y-m-d\TH:i:sP"
|
||||
$dateFormat = "Y n j, g:i a";
|
||||
// the default output format is "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n"
|
||||
$output = "%datetime% > %level_name% > %message% %context% %extra%\n";
|
||||
// finally, create a formatter
|
||||
$formatter = new LineFormatter($output, $dateFormat);
|
||||
|
||||
// Create a handler
|
||||
$stream = new StreamHandler(__DIR__.'/my_app.log', Logger::DEBUG);
|
||||
$stream->setFormatter($formatter);
|
||||
// bind it to a logger object
|
||||
$securityLogger = new Logger('security');
|
||||
$securityLogger->pushHandler($stream);
|
||||
```
|
||||
|
||||
You may also reuse the same formatter between multiple handlers and share those
|
||||
handlers between multiple loggers.
|
||||
|
||||
## Long running processes and avoiding memory leaks
|
||||
|
||||
When logging lots of data or especially when running background workers which
|
||||
are long-lived processes and do lots of logging over long periods of time, the
|
||||
memory usage of buffered handlers like FingersCrossedHandler or BufferHandler
|
||||
can rise quickly.
|
||||
|
||||
Monolog provides the `ResettableInterface` for this use case, allowing you to
|
||||
end a log cycle and get things back to their initial state.
|
||||
|
||||
Calling `$logger->reset();` means flushing/cleaning all buffers, resetting internal
|
||||
state, and getting it back to a state in which it can receive log records again.
|
||||
|
||||
This is the conceptual equivalent of ending a web request, and can be done
|
||||
between every background job you process, or whenever appropriate. It reduces memory
|
||||
usage and also helps keep logs focused on the task at hand, avoiding log leaks
|
||||
between different jobs.
|
||||
|
||||
[Handlers, Formatters and Processors](02-handlers-formatters-processors.md) →
|
||||
180
wp-content/plugins/wp-optimize/vendor/monolog/monolog/doc/02-handlers-formatters-processors.md
vendored
Normal file
180
wp-content/plugins/wp-optimize/vendor/monolog/monolog/doc/02-handlers-formatters-processors.md
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
# Handlers, Formatters and Processors
|
||||
|
||||
- [Handlers](#handlers)
|
||||
- [Log to files and syslog](#log-to-files-and-syslog)
|
||||
- [Send alerts and emails](#send-alerts-and-emails)
|
||||
- [Log specific servers and networked logging](#log-specific-servers-and-networked-logging)
|
||||
- [Logging in development](#logging-in-development)
|
||||
- [Log to databases](#log-to-databases)
|
||||
- [Wrappers / Special Handlers](#wrappers--special-handlers)
|
||||
- [Formatters](#formatters)
|
||||
- [Processors](#processors)
|
||||
- [Third Party Packages](#third-party-packages)
|
||||
|
||||
## Handlers
|
||||
|
||||
### Log to files and syslog
|
||||
|
||||
- [_StreamHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/StreamHandler.php): Logs records into any PHP stream, use this for log files.
|
||||
- [_RotatingFileHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/RotatingFileHandler.php): Logs records to a file and creates one logfile per day.
|
||||
It will also delete files older than `$maxFiles`. You should use
|
||||
[logrotate](https://linux.die.net/man/8/logrotate) for high profile
|
||||
setups though, this is just meant as a quick and dirty solution.
|
||||
- [_SyslogHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/SyslogHandler.php): Logs records to the syslog.
|
||||
- [_ErrorLogHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/ErrorLogHandler.php): Logs records to PHP's
|
||||
[`error_log()`](http://docs.php.net/manual/en/function.error-log.php) function.
|
||||
- [_ProcessHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/ProcessHandler.php): Logs records to the [STDIN](https://en.wikipedia.org/wiki/Standard_streams#Standard_input_.28stdin.29) of any process, specified by a command.
|
||||
|
||||
### Send alerts and emails
|
||||
|
||||
- [_NativeMailerHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/NativeMailerHandler.php): Sends emails using PHP's
|
||||
[`mail()`](http://php.net/manual/en/function.mail.php) function.
|
||||
- [_SwiftMailerHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/SwiftMailerHandler.php): Sends emails using a [`Swift_Mailer`](http://swiftmailer.org/) instance.
|
||||
- [_PushoverHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/PushoverHandler.php): Sends mobile notifications via the [Pushover](https://www.pushover.net/) API.
|
||||
- [_FlowdockHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/FlowdockHandler.php): Logs records to a [Flowdock](https://www.flowdock.com/) account.
|
||||
- [_SlackWebhookHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/SlackWebhookHandler.php): Logs records to a [Slack](https://www.slack.com/) account using Slack Webhooks.
|
||||
- [_SlackHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/SlackHandler.php): Logs records to a [Slack](https://www.slack.com/) account using the Slack API (complex setup).
|
||||
- [_SendGridHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/SendGridHandler.php): Sends emails via the SendGrid API.
|
||||
- [_MandrillHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/MandrillHandler.php): Sends emails via the [`Mandrill API`](https://mandrillapp.com/api/docs/) using a [`Swift_Message`](http://swiftmailer.org/) instance.
|
||||
- [_FleepHookHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/FleepHookHandler.php): Logs records to a [Fleep](https://fleep.io/) conversation using Webhooks.
|
||||
- [_IFTTTHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/IFTTTHandler.php): Notifies an [IFTTT](https://ifttt.com/maker) trigger with the log channel, level name and message.
|
||||
- [_TelegramBotHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/TelegramBotHandler.php): Logs records to a [Telegram](https://core.telegram.org/bots/api) bot account.
|
||||
- [_HipChatHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/HipChatHandler.php): Logs records to a [HipChat](http://hipchat.com) chat room using its API. **Deprecated** and removed in Monolog 2.0, use Slack handlers instead, see [Atlassian's announcement](https://www.atlassian.com/partnerships/slack)
|
||||
|
||||
### Log specific servers and networked logging
|
||||
|
||||
- [_SocketHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/SocketHandler.php): Logs records to [sockets](http://php.net/fsockopen), use this
|
||||
for UNIX and TCP sockets. See an [example](sockets.md).
|
||||
- [_AmqpHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/AmqpHandler.php): Logs records to an [AMQP](http://www.amqp.org/) compatible
|
||||
server. Requires the [php-amqp](http://pecl.php.net/package/amqp) extension (1.0+) or
|
||||
[php-amqplib](https://github.com/php-amqplib/php-amqplib) library.
|
||||
- [_GelfHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/GelfHandler.php): Logs records to a [Graylog2](http://www.graylog2.org) server.
|
||||
Requires package [graylog2/gelf-php](https://github.com/bzikarsky/gelf-php).
|
||||
- [_CubeHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/CubeHandler.php): Logs records to a [Cube](http://square.github.com/cube/) server.
|
||||
- [_ZendMonitorHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/ZendMonitorHandler.php): Logs records to the Zend Monitor present in Zend Server.
|
||||
- [_NewRelicHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/NewRelicHandler.php): Logs records to a [NewRelic](http://newrelic.com/) application.
|
||||
- [_LogglyHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/LogglyHandler.php): Logs records to a [Loggly](http://www.loggly.com/) account.
|
||||
- [_RollbarHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/RollbarHandler.php): Logs records to a [Rollbar](https://rollbar.com/) account.
|
||||
- [_SyslogUdpHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/SyslogUdpHandler.php): Logs records to a remote [Syslogd](http://www.rsyslog.com/) server.
|
||||
- [_LogEntriesHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/LogEntriesHandler.php): Logs records to a [LogEntries](http://logentries.com/) account.
|
||||
- [_InsightOpsHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/InsightOpsHandler.php): Logs records to an [InsightOps](https://www.rapid7.com/products/insightops/) account.
|
||||
- [_LogmaticHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/LogmaticHandler.php): Logs records to a [Logmatic](http://logmatic.io/) account.
|
||||
- [_SqsHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/SqsHandler.php): Logs records to an [AWS SQS](http://docs.aws.amazon.com/aws-sdk-php/v2/guide/service-sqs.html) queue.
|
||||
- [_RavenHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/RavenHandler.php): Logs records to a [Sentry](http://getsentry.com/) server using
|
||||
[raven](https://packagist.org/packages/raven/raven). **Deprecated** and removed in Monolog 2.0, use sentry/sentry 2.x and the [Sentry\Monolog\Handler](https://github.com/getsentry/sentry-php/blob/master/src/Monolog/Handler.php) class instead.
|
||||
|
||||
### Logging in development
|
||||
|
||||
- [_FirePHPHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/FirePHPHandler.php): Handler for [FirePHP](http://www.firephp.org/), providing
|
||||
inline `console` messages within [FireBug](http://getfirebug.com/).
|
||||
- [_ChromePHPHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/ChromePHPHandler.php): Handler for [ChromePHP](http://www.chromephp.com/), providing
|
||||
inline `console` messages within Chrome.
|
||||
- [_BrowserConsoleHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/BrowserConsoleHandler.php): Handler to send logs to browser's Javascript `console` with
|
||||
no browser extension required. Most browsers supporting `console` API are supported.
|
||||
- [_PHPConsoleHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/PHPConsoleHandler.php): Handler for [PHP Console](https://chrome.google.com/webstore/detail/php-console/nfhmhhlpfleoednkpnnnkolmclajemef), providing
|
||||
inline `console` and notification popup messages within Chrome.
|
||||
|
||||
### Log to databases
|
||||
|
||||
- [_RedisHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/RedisHandler.php): Logs records to a [redis](http://redis.io) server's key via RPUSH.
|
||||
- [_RedisPubSubHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/RedisPubSubHandler.php): Logs records to a [redis](http://redis.io) server's channel via PUBLISH.
|
||||
- [_MongoDBHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/MongoDBHandler.php): Handler to write records in MongoDB via a
|
||||
[Mongo](http://pecl.php.net/package/mongo) extension connection.
|
||||
- [_CouchDBHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/CouchDBHandler.php): Logs records to a CouchDB server.
|
||||
- [_DoctrineCouchDBHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/DoctrineCouchDBHandler.php): Logs records to a CouchDB server via the Doctrine CouchDB ODM.
|
||||
- [_ElasticsearchHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/ElasticsearchHandler.php): Logs records to an Elasticsearch server.
|
||||
- [_DynamoDbHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/DynamoDbHandler.php): Logs records to a DynamoDB table with the [AWS SDK](https://github.com/aws/aws-sdk-php).
|
||||
|
||||
### Wrappers / Special Handlers
|
||||
|
||||
- [_FingersCrossedHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/FingersCrossedHandler.php): A very interesting wrapper. It takes a handler as
|
||||
a parameter and will accumulate log records of all levels until a record
|
||||
exceeds the defined severity level. At which point it delivers all records,
|
||||
including those of lower severity, to the handler it wraps. This means that
|
||||
until an error actually happens you will not see anything in your logs, but
|
||||
when it happens you will have the full information, including debug and info
|
||||
records. This provides you with all the information you need, but only when
|
||||
you need it.
|
||||
- [_DeduplicationHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/DeduplicationHandler.php): Useful if you are sending notifications or emails
|
||||
when critical errors occur. It takes a handler as a parameter and will
|
||||
accumulate log records of all levels until the end of the request (or
|
||||
`flush()` is called). At that point it delivers all records to the handler
|
||||
it wraps, but only if the records are unique over a given time period
|
||||
(60seconds by default). If the records are duplicates they are simply
|
||||
discarded. The main use of this is in case of critical failure like if your
|
||||
database is unreachable for example all your requests will fail and that
|
||||
can result in a lot of notifications being sent. Adding this handler reduces
|
||||
the amount of notifications to a manageable level.
|
||||
- [_WhatFailureGroupHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/WhatFailureGroupHandler.php): This handler extends the _GroupHandler_ ignoring
|
||||
exceptions raised by each child handler. This allows you to ignore issues
|
||||
where a remote tcp connection may have died but you do not want your entire
|
||||
application to crash and may wish to continue to log to other handlers.
|
||||
- [_FallbackGroupHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/FallbackGroupHandler.php): This handler extends the _GroupHandler_ ignoring
|
||||
exceptions raised by each child handler, until one has handled without throwing.
|
||||
This allows you to ignore issues where a remote tcp connection may have died
|
||||
but you do not want your entire application to crash and may wish to continue
|
||||
to attempt log to other handlers, until one does not throw.
|
||||
- [_BufferHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/BufferHandler.php): This handler will buffer all the log records it receives
|
||||
until `close()` is called at which point it will call `handleBatch()` on the
|
||||
handler it wraps with all the log messages at once. This is very useful to
|
||||
send an email with all records at once for example instead of having one mail
|
||||
for every log record.
|
||||
- [_GroupHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/GroupHandler.php): This handler groups other handlers. Every record received is
|
||||
sent to all the handlers it is configured with.
|
||||
- [_FilterHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/FilterHandler.php): This handler only lets records of the given levels through
|
||||
to the wrapped handler.
|
||||
- [_SamplingHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/SamplingHandler.php): Wraps around another handler and lets you sample records
|
||||
if you only want to store some of them.
|
||||
- [_NoopHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/NoopHandler.php): This handler handles anything by doing nothing. It does not stop
|
||||
processing the rest of the stack. This can be used for testing, or to disable a handler when overriding a configuration.
|
||||
- [_NullHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/NullHandler.php): Any record it can handle will be thrown away. This can be used
|
||||
to put on top of an existing handler stack to disable it temporarily.
|
||||
- [_PsrHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/PsrHandler.php): Can be used to forward log records to an existing PSR-3 logger
|
||||
- [_TestHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/TestHandler.php): Used for testing, it records everything that is sent to it and
|
||||
has accessors to read out the information.
|
||||
- [_HandlerWrapper_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/HandlerWrapper.php): A simple handler wrapper you can inherit from to create
|
||||
your own wrappers easily.
|
||||
- [_OverflowHandler_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Handler/OverflowHandler.php): This handler will buffer all the log messages it
|
||||
receives, up until a configured threshold of number of messages of a certain level is reached, after it will pass all
|
||||
log messages to the wrapped handler. Useful for applying in batch processing when you're only interested in significant
|
||||
failures instead of minor, single erroneous events.
|
||||
|
||||
## Formatters
|
||||
|
||||
- [_LineFormatter_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Formatter/LineFormatter.php): Formats a log record into a one-line string.
|
||||
- [_HtmlFormatter_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Formatter/HtmlFormatter.php): Used to format log records into a human readable html table, mainly suitable for emails.
|
||||
- [_NormalizerFormatter_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Formatter/NormalizerFormatter.php): Normalizes objects/resources down to strings so a record can easily be serialized/encoded.
|
||||
- [_ScalarFormatter_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Formatter/ScalarFormatter.php): Used to format log records into an associative array of scalar values.
|
||||
- [_JsonFormatter_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Formatter/JsonFormatter.php): Encodes a log record into json.
|
||||
- [_WildfireFormatter_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Formatter/WildfireFormatter.php): Used to format log records into the Wildfire/FirePHP protocol, only useful for the FirePHPHandler.
|
||||
- [_ChromePHPFormatter_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Formatter/ChromePHPFormatter.php): Used to format log records into the ChromePHP format, only useful for the ChromePHPHandler.
|
||||
- [_GelfMessageFormatter_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Formatter/GelfMessageFormatter.php): Used to format log records into Gelf message instances, only useful for the GelfHandler.
|
||||
- [_LogstashFormatter_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Formatter/LogstashFormatter.php): Used to format log records into [logstash](http://logstash.net/) event json, useful for any handler listed under inputs [here](http://logstash.net/docs/latest).
|
||||
- [_ElasticaFormatter_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Formatter/ElasticaFormatter.php): Used to format log records into an Elastica\Document object, only useful for the ElasticSearchHandler.
|
||||
- [_LogglyFormatter_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Formatter/LogglyFormatter.php): Used to format log records into Loggly messages, only useful for the LogglyHandler.
|
||||
- [_FlowdockFormatter_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Formatter/FlowdockFormatter.php): Used to format log records into Flowdock messages, only useful for the FlowdockHandler.
|
||||
- [_MongoDBFormatter_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Formatter/MongoDBFormatter.php): Converts \DateTime instances to \MongoDate and objects recursively to arrays, only useful with the MongoDBHandler.
|
||||
- [_LogmaticFormatter_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Formatter/LogmaticFormatter.php): Used to format log records to [Logmatic](http://logmatic.io/) messages, only useful for the LogmaticHandler.
|
||||
- [_FluentdFormatter_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Formatter/FluentdFormatter.php): Used to format log records to [Fluentd](https://www.fluentd.org/) logs, only useful with the SocketHandler.
|
||||
|
||||
## Processors
|
||||
|
||||
- [_PsrLogMessageProcessor_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Processor/PsrLogMessageProcessor.php): Processes a log record's message according to PSR-3 rules, replacing `{foo}` with the value from `$context['foo']`.
|
||||
- [_IntrospectionProcessor_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Processor/IntrospectionProcessor.php): Adds the line/file/class/method from which the log call originated.
|
||||
- [_WebProcessor_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Processor/WebProcessor.php): Adds the current request URI, request method and client IP to a log record.
|
||||
- [_MemoryUsageProcessor_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Processor/MemoryUsageProcessor.php): Adds the current memory usage to a log record.
|
||||
- [_MemoryPeakUsageProcessor_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Processor/MemoryPeakUsageProcessor.php): Adds the peak memory usage to a log record.
|
||||
- [_ProcessIdProcessor_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Processor/ProcessIdProcessor.php): Adds the process id to a log record.
|
||||
- [_UidProcessor_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Processor/UidProcessor.php): Adds a unique identifier to a log record.
|
||||
- [_GitProcessor_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Processor/GitProcessor.php): Adds the current git branch and commit to a log record.
|
||||
- [_MercurialProcessor_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Processor/MercurialProcessor.php): Adds the current hg branch and commit to a log record.
|
||||
- [_TagProcessor_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Processor/TagProcessor.php): Adds an array of predefined tags to a log record.
|
||||
- [_HostnameProcessor_](https://github.com/Seldaek/monolog/blob/main/src/Monolog/Processor/HostnameProcessor.php): Adds the current hostname to a log record.
|
||||
|
||||
## Third Party Packages
|
||||
|
||||
Third party handlers, formatters and processors are
|
||||
[listed in the wiki](https://github.com/Seldaek/monolog/wiki/Third-Party-Packages). You
|
||||
can also add your own there if you publish one.
|
||||
|
||||
← [Usage](01-usage.md) | [Utility classes](03-utilities.md) →
|
||||
15
wp-content/plugins/wp-optimize/vendor/monolog/monolog/doc/03-utilities.md
vendored
Normal file
15
wp-content/plugins/wp-optimize/vendor/monolog/monolog/doc/03-utilities.md
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
# Utilities
|
||||
|
||||
- _Registry_: The `Monolog\Registry` class lets you configure global loggers that you
|
||||
can then statically access from anywhere. It is not really a best practice but can
|
||||
help in some older codebases or for ease of use.
|
||||
- _ErrorHandler_: The `Monolog\ErrorHandler` class allows you to easily register
|
||||
a Logger instance as an exception handler, error handler or fatal error handler.
|
||||
- _SignalHandler_: The `Monolog\SignalHandler` class allows you to easily register
|
||||
a Logger instance as a POSIX signal handler.
|
||||
- _ErrorLevelActivationStrategy_: Activates a FingersCrossedHandler when a certain log
|
||||
level is reached.
|
||||
- _ChannelLevelActivationStrategy_: Activates a FingersCrossedHandler when a certain
|
||||
log level is reached, depending on which channel received the log record.
|
||||
|
||||
← [Handlers, Formatters and Processors](02-handlers-formatters-processors.md) | [Extending Monolog](04-extending.md) →
|
||||
83
wp-content/plugins/wp-optimize/vendor/monolog/monolog/doc/04-extending.md
vendored
Normal file
83
wp-content/plugins/wp-optimize/vendor/monolog/monolog/doc/04-extending.md
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
# Extending Monolog
|
||||
|
||||
Monolog is fully extensible, allowing you to adapt your logger to your needs.
|
||||
|
||||
## Understanding log records
|
||||
|
||||
See [the page about log records](message-structure.md) to learn what makes up
|
||||
a log record before going further. This is essential to understand as all
|
||||
Handlers/Formatters/Processors need to deal with log records in one way or
|
||||
another.
|
||||
|
||||
## Writing your own handler
|
||||
|
||||
Monolog provides many built-in handlers. But if the one you need does not
|
||||
exist, you can write it and use it in your logger. The only requirement is
|
||||
to implement `Monolog\Handler\HandlerInterface`.
|
||||
|
||||
Let's write a PDOHandler to log records to a database. We will extend the
|
||||
abstract class provided by Monolog to keep things DRY.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\Handler\AbstractProcessingHandler;
|
||||
|
||||
class PDOHandler extends AbstractProcessingHandler
|
||||
{
|
||||
private $initialized = false;
|
||||
private $pdo;
|
||||
private $statement;
|
||||
|
||||
public function __construct(PDO $pdo, $level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
$this->pdo = $pdo;
|
||||
parent::__construct($level, $bubble);
|
||||
}
|
||||
|
||||
protected function write(array $record): void
|
||||
{
|
||||
if (!$this->initialized) {
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
$this->statement->execute(array(
|
||||
'channel' => $record['channel'],
|
||||
'level' => $record['level'],
|
||||
'message' => $record['formatted'],
|
||||
'time' => $record['datetime']->format('U'),
|
||||
));
|
||||
}
|
||||
|
||||
private function initialize()
|
||||
{
|
||||
$this->pdo->exec(
|
||||
'CREATE TABLE IF NOT EXISTS monolog '
|
||||
.'(channel VARCHAR(255), level INTEGER, message LONGTEXT, time INTEGER UNSIGNED)'
|
||||
);
|
||||
$this->statement = $this->pdo->prepare(
|
||||
'INSERT INTO monolog (channel, level, message, time) VALUES (:channel, :level, :message, :time)'
|
||||
);
|
||||
|
||||
$this->initialized = true;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can now use this handler in your logger:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
$logger->pushHandler(new PDOHandler(new PDO('sqlite:logs.sqlite')));
|
||||
|
||||
// You can now use your logger
|
||||
$logger->info('My logger is now ready');
|
||||
```
|
||||
|
||||
The `Monolog\Handler\AbstractProcessingHandler` class provides most of the
|
||||
logic needed for the handler, including the use of processors and the formatting
|
||||
of the record (which is why we use ``$record['formatted']`` instead of ``$record['message']``).
|
||||
|
||||
← [Utility classes](03-utilities.md)
|
||||
18
wp-content/plugins/wp-optimize/vendor/monolog/monolog/doc/message-structure.md
vendored
Normal file
18
wp-content/plugins/wp-optimize/vendor/monolog/monolog/doc/message-structure.md
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
# Log message structure
|
||||
|
||||
Within monolog log messages are passed around as arrays, for example to processors or handlers.
|
||||
The table below describes which keys are always available for every log message.
|
||||
|
||||
key | type | description
|
||||
-----------|---------------------------|-------------------------------------------------------------------------------
|
||||
message | string | The log message. When the `PsrLogMessageProcessor` is used this string may contain placeholders that will be replaced by variables from the context, e.g., "User {username} logged in" with `['username' => 'John']` as context will be written as "User John logged in".
|
||||
level | int | Severity of the log message. See log levels described in [01-usage.md](01-usage.md#log-levels).
|
||||
level_name | string | String representation of log level.
|
||||
context | array | Arbitrary data passed with the construction of the message. For example the username of the current user or their IP address.
|
||||
channel | string | The channel this message was logged to. This is the name that was passed when the logger was created with `new Logger($channel)`.
|
||||
datetime | Monolog\DateTimeImmutable | Date and time when the message was logged. Class extends `\DateTimeImmutable`.
|
||||
extra | array | A placeholder array where processors can put additional data. Always available, but empty if there are no processors registered.
|
||||
|
||||
At first glance `context` and `extra` look very similar, and they are in the sense that they both carry arbitrary data that is related to the log message somehow.
|
||||
The main difference is that `context` can be supplied in user land (it is the 3rd parameter to `Logger::addRecord()`) whereas `extra` is internal only and can be filled by processors.
|
||||
The reason processors write to `extra` and not to `context` is to prevent overriding any user provided data in `context`.
|
||||
39
wp-content/plugins/wp-optimize/vendor/monolog/monolog/doc/sockets.md
vendored
Normal file
39
wp-content/plugins/wp-optimize/vendor/monolog/monolog/doc/sockets.md
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
Sockets Handler
|
||||
===============
|
||||
|
||||
This handler allows you to write your logs to sockets using [fsockopen](http://php.net/fsockopen)
|
||||
or [pfsockopen](http://php.net/pfsockopen).
|
||||
|
||||
Persistent sockets are mainly useful in web environments where you gain some performance not closing/opening
|
||||
the connections between requests.
|
||||
|
||||
You can use a `unix://` prefix to access unix sockets and `udp://` to open UDP sockets instead of the default TCP.
|
||||
|
||||
Basic Example
|
||||
-------------
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\Handler\SocketHandler;
|
||||
|
||||
// Create the logger
|
||||
$logger = new Logger('my_logger');
|
||||
|
||||
// Create the handler
|
||||
$handler = new SocketHandler('unix:///var/log/httpd_app_log.socket');
|
||||
$handler->setPersistent(true);
|
||||
|
||||
// Now add the handler
|
||||
$logger->pushHandler($handler, Logger::DEBUG);
|
||||
|
||||
// You can now use your logger
|
||||
$logger->info('My logger is now ready');
|
||||
|
||||
```
|
||||
|
||||
In this example, using syslog-ng, you should see the log on the log server:
|
||||
|
||||
cweb1 [2012-02-26 00:12:03] my_logger.INFO: My logger is now ready [] []
|
||||
|
||||
40
wp-content/plugins/wp-optimize/vendor/monolog/monolog/phpstan.neon.dist
vendored
Normal file
40
wp-content/plugins/wp-optimize/vendor/monolog/monolog/phpstan.neon.dist
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
parameters:
|
||||
level: 8
|
||||
|
||||
treatPhpDocTypesAsCertain: false
|
||||
reportUnmatchedIgnoredErrors: false
|
||||
|
||||
paths:
|
||||
- src/
|
||||
# - tests/
|
||||
|
||||
ignoreErrors:
|
||||
- '#zend_monitor_|ZEND_MONITOR_#'
|
||||
- '#MongoDB\\(Client|Collection)#'
|
||||
# Invalid type info on Redis multi
|
||||
- '#^Cannot call method ltrim\(\) on int\|false.$#'
|
||||
|
||||
# Cannot resolve this cleanly as different normalizers return different types but it is safe
|
||||
- message: '#Return type \(string\) of method Monolog\\Formatter\\LineFormatter::normalizeException\(\) should be compatible with return type \(array\) of method Monolog\\Formatter\\NormalizerFormatter::normalizeException\(\)#'
|
||||
paths:
|
||||
- src/Monolog/Formatter/LineFormatter.php
|
||||
|
||||
# blocked until we only support php8+
|
||||
- '#Parameter \#1 \$socket of function (socket_close|socket_sendto|socket_send) expects Socket, resource\|Socket(\|null)? given\.#'
|
||||
- '#Parameter \#1 \$handle of function (curl_exec|curl_close|curl_error|curl_errno|curl_setopt) expects CurlHandle, CurlHandle\|resource(\|null)? given\.#'
|
||||
- message: '#Method Monolog\\Handler\\LogglyHandler::loadCurlHandle\(\) never returns resource so it can be removed from the return typehint.#'
|
||||
paths:
|
||||
- src/Monolog/Handler/LogglyHandler.php
|
||||
|
||||
# blocked by https://github.com/phpstan/phpstan/issues/5091
|
||||
- '#has unknown class Monolog\\Handler\\Record#'
|
||||
- '#::processRecord\(\) should return array#'
|
||||
- '#::processRecord\(\) has invalid type#'
|
||||
- '#::processRecord\(\) return type has no value type#'
|
||||
- '#::processRecord\(\) has parameter \$record with no value type#'
|
||||
- '#::popProcessor\(\) should return callable#'
|
||||
- '#Parameter \#1 \$ of callable \(callable\(Monolog\\Handler\\Record\): Monolog\\Handler\\Record\)#'
|
||||
- '#is incompatible with native type array.#'
|
||||
|
||||
# can be removed when https://github.com/rollbar/rollbar-php/pull/536 will be merged
|
||||
- '#Rollbar\\RollbarLogger#'
|
||||
24
wp-content/plugins/wp-optimize/vendor/monolog/monolog/phpunit.xml.dist
vendored
Normal file
24
wp-content/plugins/wp-optimize/vendor/monolog/monolog/phpunit.xml.dist
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<phpunit
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
|
||||
bootstrap="tests/bootstrap.php" colors="true"
|
||||
beStrictAboutTestsThatDoNotTestAnything="false"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="Monolog Test Suite">
|
||||
<directory>tests/Monolog/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory suffix=".php">src/Monolog/</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
|
||||
<php>
|
||||
<ini name="date.timezone" value="UTC"/>
|
||||
</php>
|
||||
</phpunit>
|
||||
49
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/DateTimeImmutable.php
vendored
Normal file
49
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/DateTimeImmutable.php
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
<?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;
|
||||
|
||||
use DateTimeZone;
|
||||
|
||||
/**
|
||||
* Overrides default json encoding of date time objects
|
||||
*
|
||||
* @author Menno Holtkamp
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
class DateTimeImmutable extends \DateTimeImmutable implements \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $useMicroseconds;
|
||||
|
||||
public function __construct(bool $useMicroseconds, ?DateTimeZone $timezone = null)
|
||||
{
|
||||
$this->useMicroseconds = $useMicroseconds;
|
||||
|
||||
parent::__construct('now', $timezone);
|
||||
}
|
||||
|
||||
public function jsonSerialize(): string
|
||||
{
|
||||
if ($this->useMicroseconds) {
|
||||
return $this->format('Y-m-d\TH:i:s.uP');
|
||||
}
|
||||
|
||||
return $this->format('Y-m-d\TH:i:sP');
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->jsonSerialize();
|
||||
}
|
||||
}
|
||||
301
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/ErrorHandler.php
vendored
Normal file
301
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/ErrorHandler.php
vendored
Normal file
@@ -0,0 +1,301 @@
|
||||
<?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;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
* Monolog error handler
|
||||
*
|
||||
* A facility to enable logging of runtime errors, exceptions and fatal errors.
|
||||
*
|
||||
* Quick setup: <code>ErrorHandler::register($logger);</code>
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
class ErrorHandler
|
||||
{
|
||||
/** @var LoggerInterface */
|
||||
private $logger;
|
||||
|
||||
/** @var ?callable */
|
||||
private $previousExceptionHandler = null;
|
||||
/** @var array<class-string, LogLevel::*> an array of class name to LogLevel::* constant mapping */
|
||||
private $uncaughtExceptionLevelMap = [];
|
||||
|
||||
/** @var callable|true|null */
|
||||
private $previousErrorHandler = null;
|
||||
/** @var array<int, LogLevel::*> an array of E_* constant to LogLevel::* constant mapping */
|
||||
private $errorLevelMap = [];
|
||||
/** @var bool */
|
||||
private $handleOnlyReportedErrors = true;
|
||||
|
||||
/** @var bool */
|
||||
private $hasFatalErrorHandler = false;
|
||||
/** @var LogLevel::* */
|
||||
private $fatalLevel = LogLevel::ALERT;
|
||||
/** @var ?string */
|
||||
private $reservedMemory = null;
|
||||
/** @var ?mixed */
|
||||
private $lastFatalTrace;
|
||||
/** @var int[] */
|
||||
private static $fatalErrors = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR];
|
||||
|
||||
public function __construct(LoggerInterface $logger)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new ErrorHandler for a given Logger
|
||||
*
|
||||
* By default it will handle errors, exceptions and fatal errors
|
||||
*
|
||||
* @param LoggerInterface $logger
|
||||
* @param array<int, LogLevel::*>|false $errorLevelMap an array of E_* constant to LogLevel::* constant mapping, or false to disable error handling
|
||||
* @param array<class-string, LogLevel::*>|false $exceptionLevelMap an array of class name to LogLevel::* constant mapping, or false to disable exception handling
|
||||
* @param LogLevel::*|null|false $fatalLevel a LogLevel::* constant, null to use the default LogLevel::ALERT or false to disable fatal error handling
|
||||
* @return ErrorHandler
|
||||
*/
|
||||
public static function register(LoggerInterface $logger, $errorLevelMap = [], $exceptionLevelMap = [], $fatalLevel = null): self
|
||||
{
|
||||
/** @phpstan-ignore-next-line */
|
||||
$handler = new static($logger);
|
||||
if ($errorLevelMap !== false) {
|
||||
$handler->registerErrorHandler($errorLevelMap);
|
||||
}
|
||||
if ($exceptionLevelMap !== false) {
|
||||
$handler->registerExceptionHandler($exceptionLevelMap);
|
||||
}
|
||||
if ($fatalLevel !== false) {
|
||||
$handler->registerFatalHandler($fatalLevel);
|
||||
}
|
||||
|
||||
return $handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<class-string, LogLevel::*> $levelMap an array of class name to LogLevel::* constant mapping
|
||||
* @return $this
|
||||
*/
|
||||
public function registerExceptionHandler(array $levelMap = [], bool $callPrevious = true): self
|
||||
{
|
||||
$prev = set_exception_handler(function (\Throwable $e): void {
|
||||
$this->handleException($e);
|
||||
});
|
||||
$this->uncaughtExceptionLevelMap = $levelMap;
|
||||
foreach ($this->defaultExceptionLevelMap() as $class => $level) {
|
||||
if (!isset($this->uncaughtExceptionLevelMap[$class])) {
|
||||
$this->uncaughtExceptionLevelMap[$class] = $level;
|
||||
}
|
||||
}
|
||||
if ($callPrevious && $prev) {
|
||||
$this->previousExceptionHandler = $prev;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, LogLevel::*> $levelMap an array of E_* constant to LogLevel::* constant mapping
|
||||
* @return $this
|
||||
*/
|
||||
public function registerErrorHandler(array $levelMap = [], bool $callPrevious = true, int $errorTypes = -1, bool $handleOnlyReportedErrors = true): self
|
||||
{
|
||||
$prev = set_error_handler([$this, 'handleError'], $errorTypes);
|
||||
$this->errorLevelMap = array_replace($this->defaultErrorLevelMap(), $levelMap);
|
||||
if ($callPrevious) {
|
||||
$this->previousErrorHandler = $prev ?: true;
|
||||
} else {
|
||||
$this->previousErrorHandler = null;
|
||||
}
|
||||
|
||||
$this->handleOnlyReportedErrors = $handleOnlyReportedErrors;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param LogLevel::*|null $level a LogLevel::* constant, null to use the default LogLevel::ALERT
|
||||
* @param int $reservedMemorySize Amount of KBs to reserve in memory so that it can be freed when handling fatal errors giving Monolog some room in memory to get its job done
|
||||
*/
|
||||
public function registerFatalHandler($level = null, int $reservedMemorySize = 20): self
|
||||
{
|
||||
register_shutdown_function([$this, 'handleFatalError']);
|
||||
|
||||
$this->reservedMemory = str_repeat(' ', 1024 * $reservedMemorySize);
|
||||
$this->fatalLevel = null === $level ? LogLevel::ALERT : $level;
|
||||
$this->hasFatalErrorHandler = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<class-string, LogLevel::*>
|
||||
*/
|
||||
protected function defaultExceptionLevelMap(): array
|
||||
{
|
||||
return [
|
||||
'ParseError' => LogLevel::CRITICAL,
|
||||
'Throwable' => LogLevel::ERROR,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, LogLevel::*>
|
||||
*/
|
||||
protected function defaultErrorLevelMap(): array
|
||||
{
|
||||
return [
|
||||
E_ERROR => LogLevel::CRITICAL,
|
||||
E_WARNING => LogLevel::WARNING,
|
||||
E_PARSE => LogLevel::ALERT,
|
||||
E_NOTICE => LogLevel::NOTICE,
|
||||
E_CORE_ERROR => LogLevel::CRITICAL,
|
||||
E_CORE_WARNING => LogLevel::WARNING,
|
||||
E_COMPILE_ERROR => LogLevel::ALERT,
|
||||
E_COMPILE_WARNING => LogLevel::WARNING,
|
||||
E_USER_ERROR => LogLevel::ERROR,
|
||||
E_USER_WARNING => LogLevel::WARNING,
|
||||
E_USER_NOTICE => LogLevel::NOTICE,
|
||||
E_STRICT => LogLevel::NOTICE,
|
||||
E_RECOVERABLE_ERROR => LogLevel::ERROR,
|
||||
E_DEPRECATED => LogLevel::NOTICE,
|
||||
E_USER_DEPRECATED => LogLevel::NOTICE,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-return never
|
||||
*/
|
||||
private function handleException(\Throwable $e): void
|
||||
{
|
||||
$level = LogLevel::ERROR;
|
||||
foreach ($this->uncaughtExceptionLevelMap as $class => $candidate) {
|
||||
if ($e instanceof $class) {
|
||||
$level = $candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->logger->log(
|
||||
$level,
|
||||
sprintf('Uncaught Exception %s: "%s" at %s line %s', Utils::getClass($e), $e->getMessage(), $e->getFile(), $e->getLine()),
|
||||
['exception' => $e]
|
||||
);
|
||||
|
||||
if ($this->previousExceptionHandler) {
|
||||
($this->previousExceptionHandler)($e);
|
||||
}
|
||||
|
||||
if (!headers_sent() && !ini_get('display_errors')) {
|
||||
http_response_code(500);
|
||||
}
|
||||
|
||||
exit(255);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*
|
||||
* @param mixed[] $context
|
||||
*/
|
||||
public function handleError(int $code, string $message, string $file = '', int $line = 0, array $context = []): bool
|
||||
{
|
||||
if ($this->handleOnlyReportedErrors && !(error_reporting() & $code)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// fatal error codes are ignored if a fatal error handler is present as well to avoid duplicate log entries
|
||||
if (!$this->hasFatalErrorHandler || !in_array($code, self::$fatalErrors, true)) {
|
||||
$level = $this->errorLevelMap[$code] ?? LogLevel::CRITICAL;
|
||||
$this->logger->log($level, self::codeToString($code).': '.$message, ['code' => $code, 'message' => $message, 'file' => $file, 'line' => $line]);
|
||||
} else {
|
||||
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
|
||||
array_shift($trace); // Exclude handleError from trace
|
||||
$this->lastFatalTrace = $trace;
|
||||
}
|
||||
|
||||
if ($this->previousErrorHandler === true) {
|
||||
return false;
|
||||
} elseif ($this->previousErrorHandler) {
|
||||
return (bool) ($this->previousErrorHandler)($code, $message, $file, $line, $context);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
public function handleFatalError(): void
|
||||
{
|
||||
$this->reservedMemory = '';
|
||||
|
||||
$lastError = error_get_last();
|
||||
if ($lastError && in_array($lastError['type'], self::$fatalErrors, true)) {
|
||||
$this->logger->log(
|
||||
$this->fatalLevel,
|
||||
'Fatal Error ('.self::codeToString($lastError['type']).'): '.$lastError['message'],
|
||||
['code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line'], 'trace' => $this->lastFatalTrace]
|
||||
);
|
||||
|
||||
if ($this->logger instanceof Logger) {
|
||||
foreach ($this->logger->getHandlers() as $handler) {
|
||||
$handler->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $code
|
||||
*/
|
||||
private static function codeToString($code): string
|
||||
{
|
||||
switch ($code) {
|
||||
case E_ERROR:
|
||||
return 'E_ERROR';
|
||||
case E_WARNING:
|
||||
return 'E_WARNING';
|
||||
case E_PARSE:
|
||||
return 'E_PARSE';
|
||||
case E_NOTICE:
|
||||
return 'E_NOTICE';
|
||||
case E_CORE_ERROR:
|
||||
return 'E_CORE_ERROR';
|
||||
case E_CORE_WARNING:
|
||||
return 'E_CORE_WARNING';
|
||||
case E_COMPILE_ERROR:
|
||||
return 'E_COMPILE_ERROR';
|
||||
case E_COMPILE_WARNING:
|
||||
return 'E_COMPILE_WARNING';
|
||||
case E_USER_ERROR:
|
||||
return 'E_USER_ERROR';
|
||||
case E_USER_WARNING:
|
||||
return 'E_USER_WARNING';
|
||||
case E_USER_NOTICE:
|
||||
return 'E_USER_NOTICE';
|
||||
case E_STRICT:
|
||||
return 'E_STRICT';
|
||||
case E_RECOVERABLE_ERROR:
|
||||
return 'E_RECOVERABLE_ERROR';
|
||||
case E_DEPRECATED:
|
||||
return 'E_DEPRECATED';
|
||||
case E_USER_DEPRECATED:
|
||||
return 'E_USER_DEPRECATED';
|
||||
}
|
||||
|
||||
return 'Unknown PHP error';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?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\Formatter;
|
||||
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* Formats a log message according to the ChromePHP array format
|
||||
*
|
||||
* @author Christophe Coevoet <stof@notk.org>
|
||||
*/
|
||||
class ChromePHPFormatter implements FormatterInterface
|
||||
{
|
||||
/**
|
||||
* Translates Monolog log levels to Wildfire levels.
|
||||
*
|
||||
* @var array<int, 'log'|'info'|'warn'|'error'>
|
||||
*/
|
||||
private $logLevels = [
|
||||
Logger::DEBUG => 'log',
|
||||
Logger::INFO => 'info',
|
||||
Logger::NOTICE => 'info',
|
||||
Logger::WARNING => 'warn',
|
||||
Logger::ERROR => 'error',
|
||||
Logger::CRITICAL => 'error',
|
||||
Logger::ALERT => 'error',
|
||||
Logger::EMERGENCY => 'error',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function format(array $record)
|
||||
{
|
||||
// Retrieve the line and file if set and remove them from the formatted extra
|
||||
$backtrace = 'unknown';
|
||||
if (isset($record['extra']['file'], $record['extra']['line'])) {
|
||||
$backtrace = $record['extra']['file'].' : '.$record['extra']['line'];
|
||||
unset($record['extra']['file'], $record['extra']['line']);
|
||||
}
|
||||
|
||||
$message = ['message' => $record['message']];
|
||||
if ($record['context']) {
|
||||
$message['context'] = $record['context'];
|
||||
}
|
||||
if ($record['extra']) {
|
||||
$message['extra'] = $record['extra'];
|
||||
}
|
||||
if (count($message) === 1) {
|
||||
$message = reset($message);
|
||||
}
|
||||
|
||||
return [
|
||||
$record['channel'],
|
||||
$message,
|
||||
$backtrace,
|
||||
$this->logLevels[$record['level']],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function formatBatch(array $records)
|
||||
{
|
||||
$formatted = [];
|
||||
|
||||
foreach ($records as $record) {
|
||||
$formatted[] = $this->format($record);
|
||||
}
|
||||
|
||||
return $formatted;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?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\Formatter;
|
||||
|
||||
use Elastica\Document;
|
||||
|
||||
/**
|
||||
* Format a log message into an Elastica Document
|
||||
*
|
||||
* @author Jelle Vink <jelle.vink@gmail.com>
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
*/
|
||||
class ElasticaFormatter extends NormalizerFormatter
|
||||
{
|
||||
/**
|
||||
* @var string Elastic search index name
|
||||
*/
|
||||
protected $index;
|
||||
|
||||
/**
|
||||
* @var ?string Elastic search document type
|
||||
*/
|
||||
protected $type;
|
||||
|
||||
/**
|
||||
* @param string $index Elastic Search index name
|
||||
* @param ?string $type Elastic Search document type, deprecated as of Elastica 7
|
||||
*/
|
||||
public function __construct(string $index, ?string $type)
|
||||
{
|
||||
// elasticsearch requires a ISO 8601 format date with optional millisecond precision.
|
||||
parent::__construct('Y-m-d\TH:i:s.uP');
|
||||
|
||||
$this->index = $index;
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function format(array $record)
|
||||
{
|
||||
$record = parent::format($record);
|
||||
|
||||
return $this->getDocument($record);
|
||||
}
|
||||
|
||||
public function getIndex(): string
|
||||
{
|
||||
return $this->index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since Elastica 7 type has no effect
|
||||
*/
|
||||
public function getType(): string
|
||||
{
|
||||
/** @phpstan-ignore-next-line */
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a log message into an Elastica Document
|
||||
*
|
||||
* @phpstan-param Record $record
|
||||
*/
|
||||
protected function getDocument(array $record): Document
|
||||
{
|
||||
$document = new Document();
|
||||
$document->setData($record);
|
||||
if (method_exists($document, 'setType')) {
|
||||
/** @phpstan-ignore-next-line */
|
||||
$document->setType($this->type);
|
||||
}
|
||||
$document->setIndex($this->index);
|
||||
|
||||
return $document;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?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\Formatter;
|
||||
|
||||
use DateTimeInterface;
|
||||
|
||||
/**
|
||||
* Format a log message into an Elasticsearch record
|
||||
*
|
||||
* @author Avtandil Kikabidze <akalongman@gmail.com>
|
||||
*/
|
||||
class ElasticsearchFormatter extends NormalizerFormatter
|
||||
{
|
||||
/**
|
||||
* @var string Elasticsearch index name
|
||||
*/
|
||||
protected $index;
|
||||
|
||||
/**
|
||||
* @var string Elasticsearch record type
|
||||
*/
|
||||
protected $type;
|
||||
|
||||
/**
|
||||
* @param string $index Elasticsearch index name
|
||||
* @param string $type Elasticsearch record type
|
||||
*/
|
||||
public function __construct(string $index, string $type)
|
||||
{
|
||||
// Elasticsearch requires an ISO 8601 format date with optional millisecond precision.
|
||||
parent::__construct(DateTimeInterface::ISO8601);
|
||||
|
||||
$this->index = $index;
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function format(array $record)
|
||||
{
|
||||
$record = parent::format($record);
|
||||
|
||||
return $this->getDocument($record);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter index
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIndex(): string
|
||||
{
|
||||
return $this->index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter type
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getType(): string
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a log message into an Elasticsearch record
|
||||
*
|
||||
* @param mixed[] $record Log message
|
||||
* @return mixed[]
|
||||
*/
|
||||
protected function getDocument(array $record): array
|
||||
{
|
||||
$record['_index'] = $this->index;
|
||||
$record['_type'] = $this->type;
|
||||
|
||||
return $record;
|
||||
}
|
||||
}
|
||||
111
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php
vendored
Normal file
111
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
<?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\Formatter;
|
||||
|
||||
/**
|
||||
* formats the record to be used in the FlowdockHandler
|
||||
*
|
||||
* @author Dominik Liebler <liebler.dominik@gmail.com>
|
||||
*/
|
||||
class FlowdockFormatter implements FormatterInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $source;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sourceEmail;
|
||||
|
||||
public function __construct(string $source, string $sourceEmail)
|
||||
{
|
||||
$this->source = $source;
|
||||
$this->sourceEmail = $sourceEmail;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function format(array $record): array
|
||||
{
|
||||
$tags = [
|
||||
'#logs',
|
||||
'#' . strtolower($record['level_name']),
|
||||
'#' . $record['channel'],
|
||||
];
|
||||
|
||||
foreach ($record['extra'] as $value) {
|
||||
$tags[] = '#' . $value;
|
||||
}
|
||||
|
||||
$subject = sprintf(
|
||||
'in %s: %s - %s',
|
||||
$this->source,
|
||||
$record['level_name'],
|
||||
$this->getShortMessage($record['message'])
|
||||
);
|
||||
|
||||
$record['flowdock'] = [
|
||||
'source' => $this->source,
|
||||
'from_address' => $this->sourceEmail,
|
||||
'subject' => $subject,
|
||||
'content' => $record['message'],
|
||||
'tags' => $tags,
|
||||
'project' => $this->source,
|
||||
];
|
||||
|
||||
return $record;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return mixed[][]
|
||||
*/
|
||||
public function formatBatch(array $records): array
|
||||
{
|
||||
$formatted = [];
|
||||
|
||||
foreach ($records as $record) {
|
||||
$formatted[] = $this->format($record);
|
||||
}
|
||||
|
||||
return $formatted;
|
||||
}
|
||||
|
||||
public function getShortMessage(string $message): string
|
||||
{
|
||||
static $hasMbString;
|
||||
|
||||
if (null === $hasMbString) {
|
||||
$hasMbString = function_exists('mb_strlen');
|
||||
}
|
||||
|
||||
$maxLength = 45;
|
||||
|
||||
if ($hasMbString) {
|
||||
if (mb_strlen($message, 'UTF-8') > $maxLength) {
|
||||
$message = mb_substr($message, 0, $maxLength - 4, 'UTF-8') . ' ...';
|
||||
}
|
||||
} else {
|
||||
if (strlen($message) > $maxLength) {
|
||||
$message = substr($message, 0, $maxLength - 4) . ' ...';
|
||||
}
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
}
|
||||
88
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php
vendored
Normal file
88
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
<?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\Formatter;
|
||||
|
||||
use Monolog\Utils;
|
||||
|
||||
/**
|
||||
* Class FluentdFormatter
|
||||
*
|
||||
* Serializes a log message to Fluentd unix socket protocol
|
||||
*
|
||||
* Fluentd config:
|
||||
*
|
||||
* <source>
|
||||
* type unix
|
||||
* path /var/run/td-agent/td-agent.sock
|
||||
* </source>
|
||||
*
|
||||
* Monolog setup:
|
||||
*
|
||||
* $logger = new Monolog\Logger('fluent.tag');
|
||||
* $fluentHandler = new Monolog\Handler\SocketHandler('unix:///var/run/td-agent/td-agent.sock');
|
||||
* $fluentHandler->setFormatter(new Monolog\Formatter\FluentdFormatter());
|
||||
* $logger->pushHandler($fluentHandler);
|
||||
*
|
||||
* @author Andrius Putna <fordnox@gmail.com>
|
||||
*/
|
||||
class FluentdFormatter implements FormatterInterface
|
||||
{
|
||||
/**
|
||||
* @var bool $levelTag should message level be a part of the fluentd tag
|
||||
*/
|
||||
protected $levelTag = false;
|
||||
|
||||
public function __construct(bool $levelTag = false)
|
||||
{
|
||||
if (!function_exists('json_encode')) {
|
||||
throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s FluentdUnixFormatter');
|
||||
}
|
||||
|
||||
$this->levelTag = $levelTag;
|
||||
}
|
||||
|
||||
public function isUsingLevelsInTag(): bool
|
||||
{
|
||||
return $this->levelTag;
|
||||
}
|
||||
|
||||
public function format(array $record): string
|
||||
{
|
||||
$tag = $record['channel'];
|
||||
if ($this->levelTag) {
|
||||
$tag .= '.' . strtolower($record['level_name']);
|
||||
}
|
||||
|
||||
$message = [
|
||||
'message' => $record['message'],
|
||||
'context' => $record['context'],
|
||||
'extra' => $record['extra'],
|
||||
];
|
||||
|
||||
if (!$this->levelTag) {
|
||||
$message['level'] = $record['level'];
|
||||
$message['level_name'] = $record['level_name'];
|
||||
}
|
||||
|
||||
return Utils::jsonEncode([$tag, $record['datetime']->getTimestamp(), $message]);
|
||||
}
|
||||
|
||||
public function formatBatch(array $records): string
|
||||
{
|
||||
$message = '';
|
||||
foreach ($records as $record) {
|
||||
$message .= $this->format($record);
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?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\Formatter;
|
||||
|
||||
/**
|
||||
* Interface for formatters
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
*/
|
||||
interface FormatterInterface
|
||||
{
|
||||
/**
|
||||
* Formats a log record.
|
||||
*
|
||||
* @param array $record A record to format
|
||||
* @return mixed The formatted record
|
||||
*
|
||||
* @phpstan-param Record $record
|
||||
*/
|
||||
public function format(array $record);
|
||||
|
||||
/**
|
||||
* Formats a set of log records.
|
||||
*
|
||||
* @param array $records A set of records to format
|
||||
* @return mixed The formatted set of records
|
||||
*
|
||||
* @phpstan-param Record[] $records
|
||||
*/
|
||||
public function formatBatch(array $records);
|
||||
}
|
||||
156
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php
vendored
Normal file
156
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
<?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\Formatter;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Gelf\Message;
|
||||
use Monolog\Utils;
|
||||
|
||||
/**
|
||||
* Serializes a log message to GELF
|
||||
* @see http://docs.graylog.org/en/latest/pages/gelf.html
|
||||
*
|
||||
* @author Matt Lehner <mlehner@gmail.com>
|
||||
*
|
||||
* @phpstan-import-type Level from \Monolog\Logger
|
||||
*/
|
||||
class GelfMessageFormatter extends NormalizerFormatter
|
||||
{
|
||||
protected const DEFAULT_MAX_LENGTH = 32766;
|
||||
|
||||
/**
|
||||
* @var string the name of the system for the Gelf log message
|
||||
*/
|
||||
protected $systemName;
|
||||
|
||||
/**
|
||||
* @var string a prefix for 'extra' fields from the Monolog record (optional)
|
||||
*/
|
||||
protected $extraPrefix;
|
||||
|
||||
/**
|
||||
* @var string a prefix for 'context' fields from the Monolog record (optional)
|
||||
*/
|
||||
protected $contextPrefix;
|
||||
|
||||
/**
|
||||
* @var int max length per field
|
||||
*/
|
||||
protected $maxLength;
|
||||
|
||||
/**
|
||||
* Translates Monolog log levels to Graylog2 log priorities.
|
||||
*
|
||||
* @var array<int, int>
|
||||
*
|
||||
* @phpstan-var array<Level, int>
|
||||
*/
|
||||
private $logLevels = [
|
||||
Logger::DEBUG => 7,
|
||||
Logger::INFO => 6,
|
||||
Logger::NOTICE => 5,
|
||||
Logger::WARNING => 4,
|
||||
Logger::ERROR => 3,
|
||||
Logger::CRITICAL => 2,
|
||||
Logger::ALERT => 1,
|
||||
Logger::EMERGENCY => 0,
|
||||
];
|
||||
|
||||
public function __construct(?string $systemName = null, ?string $extraPrefix = null, string $contextPrefix = 'ctxt_', ?int $maxLength = null)
|
||||
{
|
||||
parent::__construct('U.u');
|
||||
|
||||
$this->systemName = (is_null($systemName) || $systemName === '') ? (string) gethostname() : $systemName;
|
||||
|
||||
$this->extraPrefix = is_null($extraPrefix) ? '' : $extraPrefix;
|
||||
$this->contextPrefix = $contextPrefix;
|
||||
$this->maxLength = is_null($maxLength) ? self::DEFAULT_MAX_LENGTH : $maxLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function format(array $record): Message
|
||||
{
|
||||
$context = $extra = [];
|
||||
if (isset($record['context'])) {
|
||||
/** @var mixed[] $context */
|
||||
$context = parent::normalize($record['context']);
|
||||
}
|
||||
if (isset($record['extra'])) {
|
||||
/** @var mixed[] $extra */
|
||||
$extra = parent::normalize($record['extra']);
|
||||
}
|
||||
|
||||
if (!isset($record['datetime'], $record['message'], $record['level'])) {
|
||||
throw new \InvalidArgumentException('The record should at least contain datetime, message and level keys, '.var_export($record, true).' given');
|
||||
}
|
||||
|
||||
$message = new Message();
|
||||
$message
|
||||
->setTimestamp($record['datetime'])
|
||||
->setShortMessage((string) $record['message'])
|
||||
->setHost($this->systemName)
|
||||
->setLevel($this->logLevels[$record['level']]);
|
||||
|
||||
// message length + system name length + 200 for padding / metadata
|
||||
$len = 200 + strlen((string) $record['message']) + strlen($this->systemName);
|
||||
|
||||
if ($len > $this->maxLength) {
|
||||
$message->setShortMessage(Utils::substr($record['message'], 0, $this->maxLength));
|
||||
}
|
||||
|
||||
if (isset($record['channel'])) {
|
||||
$message->setFacility($record['channel']);
|
||||
}
|
||||
if (isset($extra['line'])) {
|
||||
$message->setLine($extra['line']);
|
||||
unset($extra['line']);
|
||||
}
|
||||
if (isset($extra['file'])) {
|
||||
$message->setFile($extra['file']);
|
||||
unset($extra['file']);
|
||||
}
|
||||
|
||||
foreach ($extra as $key => $val) {
|
||||
$val = is_scalar($val) || null === $val ? $val : $this->toJson($val);
|
||||
$len = strlen($this->extraPrefix . $key . $val);
|
||||
if ($len > $this->maxLength) {
|
||||
$message->setAdditional($this->extraPrefix . $key, Utils::substr((string) $val, 0, $this->maxLength));
|
||||
|
||||
continue;
|
||||
}
|
||||
$message->setAdditional($this->extraPrefix . $key, $val);
|
||||
}
|
||||
|
||||
foreach ($context as $key => $val) {
|
||||
$val = is_scalar($val) || null === $val ? $val : $this->toJson($val);
|
||||
$len = strlen($this->contextPrefix . $key . $val);
|
||||
if ($len > $this->maxLength) {
|
||||
$message->setAdditional($this->contextPrefix . $key, Utils::substr((string) $val, 0, $this->maxLength));
|
||||
|
||||
continue;
|
||||
}
|
||||
$message->setAdditional($this->contextPrefix . $key, $val);
|
||||
}
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
if (null === $message->getFile() && isset($context['exception']['file'])) {
|
||||
if (preg_match("/^(.+):([0-9]+)$/", $context['exception']['file'], $matches)) {
|
||||
$message->setFile($matches[1]);
|
||||
$message->setLine($matches[2]);
|
||||
}
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
}
|
||||
142
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php
vendored
Normal file
142
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
<?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\Formatter;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\Utils;
|
||||
|
||||
/**
|
||||
* Formats incoming records into an HTML table
|
||||
*
|
||||
* This is especially useful for html email logging
|
||||
*
|
||||
* @author Tiago Brito <tlfbrito@gmail.com>
|
||||
*/
|
||||
class HtmlFormatter extends NormalizerFormatter
|
||||
{
|
||||
/**
|
||||
* Translates Monolog log levels to html color priorities.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $logLevels = [
|
||||
Logger::DEBUG => '#CCCCCC',
|
||||
Logger::INFO => '#28A745',
|
||||
Logger::NOTICE => '#17A2B8',
|
||||
Logger::WARNING => '#FFC107',
|
||||
Logger::ERROR => '#FD7E14',
|
||||
Logger::CRITICAL => '#DC3545',
|
||||
Logger::ALERT => '#821722',
|
||||
Logger::EMERGENCY => '#000000',
|
||||
];
|
||||
|
||||
/**
|
||||
* @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format
|
||||
*/
|
||||
public function __construct(?string $dateFormat = null)
|
||||
{
|
||||
parent::__construct($dateFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an HTML table row
|
||||
*
|
||||
* @param string $th Row header content
|
||||
* @param string $td Row standard cell content
|
||||
* @param bool $escapeTd false if td content must not be html escaped
|
||||
*/
|
||||
protected function addRow(string $th, string $td = ' ', bool $escapeTd = true): string
|
||||
{
|
||||
$th = htmlspecialchars($th, ENT_NOQUOTES, 'UTF-8');
|
||||
if ($escapeTd) {
|
||||
$td = '<pre>'.htmlspecialchars($td, ENT_NOQUOTES, 'UTF-8').'</pre>';
|
||||
}
|
||||
|
||||
return "<tr style=\"padding: 4px;text-align: left;\">\n<th style=\"vertical-align: top;background: #ccc;color: #000\" width=\"100\">$th:</th>\n<td style=\"padding: 4px;text-align: left;vertical-align: top;background: #eee;color: #000\">".$td."</td>\n</tr>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a HTML h1 tag
|
||||
*
|
||||
* @param string $title Text to be in the h1
|
||||
* @param int $level Error level
|
||||
* @return string
|
||||
*/
|
||||
protected function addTitle(string $title, int $level): string
|
||||
{
|
||||
$title = htmlspecialchars($title, ENT_NOQUOTES, 'UTF-8');
|
||||
|
||||
return '<h1 style="background: '.$this->logLevels[$level].';color: #ffffff;padding: 5px;" class="monolog-output">'.$title.'</h1>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a log record.
|
||||
*
|
||||
* @return string The formatted record
|
||||
*/
|
||||
public function format(array $record): string
|
||||
{
|
||||
$output = $this->addTitle($record['level_name'], $record['level']);
|
||||
$output .= '<table cellspacing="1" width="100%" class="monolog-output">';
|
||||
|
||||
$output .= $this->addRow('Message', (string) $record['message']);
|
||||
$output .= $this->addRow('Time', $this->formatDate($record['datetime']));
|
||||
$output .= $this->addRow('Channel', $record['channel']);
|
||||
if ($record['context']) {
|
||||
$embeddedTable = '<table cellspacing="1" width="100%">';
|
||||
foreach ($record['context'] as $key => $value) {
|
||||
$embeddedTable .= $this->addRow((string) $key, $this->convertToString($value));
|
||||
}
|
||||
$embeddedTable .= '</table>';
|
||||
$output .= $this->addRow('Context', $embeddedTable, false);
|
||||
}
|
||||
if ($record['extra']) {
|
||||
$embeddedTable = '<table cellspacing="1" width="100%">';
|
||||
foreach ($record['extra'] as $key => $value) {
|
||||
$embeddedTable .= $this->addRow((string) $key, $this->convertToString($value));
|
||||
}
|
||||
$embeddedTable .= '</table>';
|
||||
$output .= $this->addRow('Extra', $embeddedTable, false);
|
||||
}
|
||||
|
||||
return $output.'</table>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a set of log records.
|
||||
*
|
||||
* @return string The formatted set of records
|
||||
*/
|
||||
public function formatBatch(array $records): string
|
||||
{
|
||||
$message = '';
|
||||
foreach ($records as $record) {
|
||||
$message .= $this->format($record);
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $data
|
||||
*/
|
||||
protected function convertToString($data): string
|
||||
{
|
||||
if (null === $data || is_scalar($data)) {
|
||||
return (string) $data;
|
||||
}
|
||||
|
||||
$data = $this->normalize($data);
|
||||
|
||||
return Utils::jsonEncode($data, JSON_PRETTY_PRINT | Utils::DEFAULT_JSON_FLAGS, true);
|
||||
}
|
||||
}
|
||||
208
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php
vendored
Normal file
208
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php
vendored
Normal file
@@ -0,0 +1,208 @@
|
||||
<?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\Formatter;
|
||||
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Encodes whatever record data is passed to it as json
|
||||
*
|
||||
* This can be useful to log to databases or remote APIs
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
*/
|
||||
class JsonFormatter extends NormalizerFormatter
|
||||
{
|
||||
public const BATCH_MODE_JSON = 1;
|
||||
public const BATCH_MODE_NEWLINES = 2;
|
||||
|
||||
/** @var self::BATCH_MODE_* */
|
||||
protected $batchMode;
|
||||
/** @var bool */
|
||||
protected $appendNewline;
|
||||
/** @var bool */
|
||||
protected $ignoreEmptyContextAndExtra;
|
||||
/** @var bool */
|
||||
protected $includeStacktraces = false;
|
||||
|
||||
/**
|
||||
* @param self::BATCH_MODE_* $batchMode
|
||||
*/
|
||||
public function __construct(int $batchMode = self::BATCH_MODE_JSON, bool $appendNewline = true, bool $ignoreEmptyContextAndExtra = false)
|
||||
{
|
||||
$this->batchMode = $batchMode;
|
||||
$this->appendNewline = $appendNewline;
|
||||
$this->ignoreEmptyContextAndExtra = $ignoreEmptyContextAndExtra;
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* The batch mode option configures the formatting style for
|
||||
* multiple records. By default, multiple records will be
|
||||
* formatted as a JSON-encoded array. However, for
|
||||
* compatibility with some API endpoints, alternative styles
|
||||
* are available.
|
||||
*/
|
||||
public function getBatchMode(): int
|
||||
{
|
||||
return $this->batchMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* True if newlines are appended to every formatted record
|
||||
*/
|
||||
public function isAppendingNewlines(): bool
|
||||
{
|
||||
return $this->appendNewline;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function format(array $record): string
|
||||
{
|
||||
$normalized = $this->normalize($record);
|
||||
|
||||
if (isset($normalized['context']) && $normalized['context'] === []) {
|
||||
if ($this->ignoreEmptyContextAndExtra) {
|
||||
unset($normalized['context']);
|
||||
} else {
|
||||
$normalized['context'] = new \stdClass;
|
||||
}
|
||||
}
|
||||
if (isset($normalized['extra']) && $normalized['extra'] === []) {
|
||||
if ($this->ignoreEmptyContextAndExtra) {
|
||||
unset($normalized['extra']);
|
||||
} else {
|
||||
$normalized['extra'] = new \stdClass;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->toJson($normalized, true) . ($this->appendNewline ? "\n" : '');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function formatBatch(array $records): string
|
||||
{
|
||||
switch ($this->batchMode) {
|
||||
case static::BATCH_MODE_NEWLINES:
|
||||
return $this->formatBatchNewlines($records);
|
||||
|
||||
case static::BATCH_MODE_JSON:
|
||||
default:
|
||||
return $this->formatBatchJson($records);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function includeStacktraces(bool $include = true)
|
||||
{
|
||||
$this->includeStacktraces = $include;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a JSON-encoded array of records.
|
||||
*
|
||||
* @phpstan-param Record[] $records
|
||||
*/
|
||||
protected function formatBatchJson(array $records): string
|
||||
{
|
||||
return $this->toJson($this->normalize($records), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use new lines to separate records instead of a
|
||||
* JSON-encoded array.
|
||||
*
|
||||
* @phpstan-param Record[] $records
|
||||
*/
|
||||
protected function formatBatchNewlines(array $records): string
|
||||
{
|
||||
$instance = $this;
|
||||
|
||||
$oldNewline = $this->appendNewline;
|
||||
$this->appendNewline = false;
|
||||
array_walk($records, function (&$value, $key) use ($instance) {
|
||||
$value = $instance->format($value);
|
||||
});
|
||||
$this->appendNewline = $oldNewline;
|
||||
|
||||
return implode("\n", $records);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes given $data.
|
||||
*
|
||||
* @param mixed $data
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function normalize($data, int $depth = 0)
|
||||
{
|
||||
if ($depth > $this->maxNormalizeDepth) {
|
||||
return 'Over '.$this->maxNormalizeDepth.' levels deep, aborting normalization';
|
||||
}
|
||||
|
||||
if (is_array($data)) {
|
||||
$normalized = [];
|
||||
|
||||
$count = 1;
|
||||
foreach ($data as $key => $value) {
|
||||
if ($count++ > $this->maxNormalizeItemCount) {
|
||||
$normalized['...'] = 'Over '.$this->maxNormalizeItemCount.' items ('.count($data).' total), aborting normalization';
|
||||
break;
|
||||
}
|
||||
|
||||
$normalized[$key] = $this->normalize($value, $depth + 1);
|
||||
}
|
||||
|
||||
return $normalized;
|
||||
}
|
||||
|
||||
if ($data instanceof \DateTimeInterface) {
|
||||
return $this->formatDate($data);
|
||||
}
|
||||
|
||||
if ($data instanceof Throwable) {
|
||||
return $this->normalizeException($data, $depth);
|
||||
}
|
||||
|
||||
if (is_resource($data)) {
|
||||
return parent::normalize($data);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes given exception with or without its own stack trace based on
|
||||
* `includeStacktraces` property.
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function normalizeException(Throwable $e, int $depth = 0): array
|
||||
{
|
||||
$data = parent::normalizeException($e, $depth);
|
||||
if (!$this->includeStacktraces) {
|
||||
unset($data['trace']);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
210
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php
vendored
Normal file
210
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php
vendored
Normal file
@@ -0,0 +1,210 @@
|
||||
<?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\Formatter;
|
||||
|
||||
use Monolog\Utils;
|
||||
|
||||
/**
|
||||
* Formats incoming records into a one-line string
|
||||
*
|
||||
* This is especially useful for logging to files
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @author Christophe Coevoet <stof@notk.org>
|
||||
*/
|
||||
class LineFormatter extends NormalizerFormatter
|
||||
{
|
||||
public const SIMPLE_FORMAT = "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n";
|
||||
|
||||
/** @var string */
|
||||
protected $format;
|
||||
/** @var bool */
|
||||
protected $allowInlineLineBreaks;
|
||||
/** @var bool */
|
||||
protected $ignoreEmptyContextAndExtra;
|
||||
/** @var bool */
|
||||
protected $includeStacktraces;
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
public function __construct(?string $format = null, ?string $dateFormat = null, bool $allowInlineLineBreaks = false, bool $ignoreEmptyContextAndExtra = false)
|
||||
{
|
||||
$this->format = $format === null ? static::SIMPLE_FORMAT : $format;
|
||||
$this->allowInlineLineBreaks = $allowInlineLineBreaks;
|
||||
$this->ignoreEmptyContextAndExtra = $ignoreEmptyContextAndExtra;
|
||||
parent::__construct($dateFormat);
|
||||
}
|
||||
|
||||
public function includeStacktraces(bool $include = true): void
|
||||
{
|
||||
$this->includeStacktraces = $include;
|
||||
if ($this->includeStacktraces) {
|
||||
$this->allowInlineLineBreaks = true;
|
||||
}
|
||||
}
|
||||
|
||||
public function allowInlineLineBreaks(bool $allow = true): void
|
||||
{
|
||||
$this->allowInlineLineBreaks = $allow;
|
||||
}
|
||||
|
||||
public function ignoreEmptyContextAndExtra(bool $ignore = true): void
|
||||
{
|
||||
$this->ignoreEmptyContextAndExtra = $ignore;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function format(array $record): string
|
||||
{
|
||||
$vars = parent::format($record);
|
||||
|
||||
$output = $this->format;
|
||||
|
||||
foreach ($vars['extra'] as $var => $val) {
|
||||
if (false !== strpos($output, '%extra.'.$var.'%')) {
|
||||
$output = str_replace('%extra.'.$var.'%', $this->stringify($val), $output);
|
||||
unset($vars['extra'][$var]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($vars['context'] as $var => $val) {
|
||||
if (false !== strpos($output, '%context.'.$var.'%')) {
|
||||
$output = str_replace('%context.'.$var.'%', $this->stringify($val), $output);
|
||||
unset($vars['context'][$var]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->ignoreEmptyContextAndExtra) {
|
||||
if (empty($vars['context'])) {
|
||||
unset($vars['context']);
|
||||
$output = str_replace('%context%', '', $output);
|
||||
}
|
||||
|
||||
if (empty($vars['extra'])) {
|
||||
unset($vars['extra']);
|
||||
$output = str_replace('%extra%', '', $output);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($vars as $var => $val) {
|
||||
if (false !== strpos($output, '%'.$var.'%')) {
|
||||
$output = str_replace('%'.$var.'%', $this->stringify($val), $output);
|
||||
}
|
||||
}
|
||||
|
||||
// remove leftover %extra.xxx% and %context.xxx% if any
|
||||
if (false !== strpos($output, '%')) {
|
||||
$output = preg_replace('/%(?:extra|context)\..+?%/', '', $output);
|
||||
if (null === $output) {
|
||||
$pcreErrorCode = preg_last_error();
|
||||
throw new \RuntimeException('Failed to run preg_replace: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode));
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
public function formatBatch(array $records): string
|
||||
{
|
||||
$message = '';
|
||||
foreach ($records as $record) {
|
||||
$message .= $this->format($record);
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function stringify($value): string
|
||||
{
|
||||
return $this->replaceNewlines($this->convertToString($value));
|
||||
}
|
||||
|
||||
protected function normalizeException(\Throwable $e, int $depth = 0): string
|
||||
{
|
||||
$str = $this->formatException($e);
|
||||
|
||||
if ($previous = $e->getPrevious()) {
|
||||
do {
|
||||
$str .= "\n[previous exception] " . $this->formatException($previous);
|
||||
} while ($previous = $previous->getPrevious());
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $data
|
||||
*/
|
||||
protected function convertToString($data): string
|
||||
{
|
||||
if (null === $data || is_bool($data)) {
|
||||
return var_export($data, true);
|
||||
}
|
||||
|
||||
if (is_scalar($data)) {
|
||||
return (string) $data;
|
||||
}
|
||||
|
||||
return $this->toJson($data, true);
|
||||
}
|
||||
|
||||
protected function replaceNewlines(string $str): string
|
||||
{
|
||||
if ($this->allowInlineLineBreaks) {
|
||||
if (0 === strpos($str, '{')) {
|
||||
return str_replace(array('\r', '\n'), array("\r", "\n"), $str);
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
return str_replace(["\r\n", "\r", "\n"], ' ', $str);
|
||||
}
|
||||
|
||||
private function formatException(\Throwable $e): string
|
||||
{
|
||||
$str = '[object] (' . Utils::getClass($e) . '(code: ' . $e->getCode();
|
||||
if ($e instanceof \SoapFault) {
|
||||
if (isset($e->faultcode)) {
|
||||
$str .= ' faultcode: ' . $e->faultcode;
|
||||
}
|
||||
|
||||
if (isset($e->faultactor)) {
|
||||
$str .= ' faultactor: ' . $e->faultactor;
|
||||
}
|
||||
|
||||
if (isset($e->detail)) {
|
||||
if (is_string($e->detail)) {
|
||||
$str .= ' detail: ' . $e->detail;
|
||||
} elseif (is_object($e->detail) || is_array($e->detail)) {
|
||||
$str .= ' detail: ' . $this->toJson($e->detail, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
$str .= '): ' . $e->getMessage() . ' at ' . $e->getFile() . ':' . $e->getLine() . ')';
|
||||
|
||||
if ($this->includeStacktraces) {
|
||||
$str .= "\n[stacktrace]\n" . $e->getTraceAsString() . "\n";
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
}
|
||||
45
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php
vendored
Normal file
45
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
<?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\Formatter;
|
||||
|
||||
/**
|
||||
* Encodes message information into JSON in a format compatible with Loggly.
|
||||
*
|
||||
* @author Adam Pancutt <adam@pancutt.com>
|
||||
*/
|
||||
class LogglyFormatter extends JsonFormatter
|
||||
{
|
||||
/**
|
||||
* Overrides the default batch mode to new lines for compatibility with the
|
||||
* Loggly bulk API.
|
||||
*/
|
||||
public function __construct(int $batchMode = self::BATCH_MODE_NEWLINES, bool $appendNewline = false)
|
||||
{
|
||||
parent::__construct($batchMode, $appendNewline);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the 'timestamp' parameter for indexing by Loggly.
|
||||
*
|
||||
* @see https://www.loggly.com/docs/automated-parsing/#json
|
||||
* @see \Monolog\Formatter\JsonFormatter::format()
|
||||
*/
|
||||
public function format(array $record): string
|
||||
{
|
||||
if (isset($record["datetime"]) && ($record["datetime"] instanceof \DateTimeInterface)) {
|
||||
$record["timestamp"] = $record["datetime"]->format("Y-m-d\TH:i:s.uO");
|
||||
unset($record["datetime"]);
|
||||
}
|
||||
|
||||
return parent::format($record);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?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\Formatter;
|
||||
|
||||
/**
|
||||
* Encodes message information into JSON in a format compatible with Logmatic.
|
||||
*
|
||||
* @author Julien Breux <julien.breux@gmail.com>
|
||||
*/
|
||||
class LogmaticFormatter extends JsonFormatter
|
||||
{
|
||||
protected const MARKERS = ["sourcecode", "php"];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $hostname = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $appname = '';
|
||||
|
||||
public function setHostname(string $hostname): self
|
||||
{
|
||||
$this->hostname = $hostname;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setAppname(string $appname): self
|
||||
{
|
||||
$this->appname = $appname;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the 'hostname' and 'appname' parameter for indexing by Logmatic.
|
||||
*
|
||||
* @see http://doc.logmatic.io/docs/basics-to-send-data
|
||||
* @see \Monolog\Formatter\JsonFormatter::format()
|
||||
*/
|
||||
public function format(array $record): string
|
||||
{
|
||||
if (!empty($this->hostname)) {
|
||||
$record["hostname"] = $this->hostname;
|
||||
}
|
||||
if (!empty($this->appname)) {
|
||||
$record["appname"] = $this->appname;
|
||||
}
|
||||
|
||||
$record["@marker"] = static::MARKERS;
|
||||
|
||||
return parent::format($record);
|
||||
}
|
||||
}
|
||||
101
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php
vendored
Normal file
101
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
<?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\Formatter;
|
||||
|
||||
/**
|
||||
* Serializes a log message to Logstash Event Format
|
||||
*
|
||||
* @see https://www.elastic.co/products/logstash
|
||||
* @see https://github.com/elastic/logstash/blob/master/logstash-core/src/main/java/org/logstash/Event.java
|
||||
*
|
||||
* @author Tim Mower <timothy.mower@gmail.com>
|
||||
*/
|
||||
class LogstashFormatter extends NormalizerFormatter
|
||||
{
|
||||
/**
|
||||
* @var string the name of the system for the Logstash log message, used to fill the @source field
|
||||
*/
|
||||
protected $systemName;
|
||||
|
||||
/**
|
||||
* @var string an application name for the Logstash log message, used to fill the @type field
|
||||
*/
|
||||
protected $applicationName;
|
||||
|
||||
/**
|
||||
* @var string the key for 'extra' fields from the Monolog record
|
||||
*/
|
||||
protected $extraKey;
|
||||
|
||||
/**
|
||||
* @var string the key for 'context' fields from the Monolog record
|
||||
*/
|
||||
protected $contextKey;
|
||||
|
||||
/**
|
||||
* @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 extra
|
||||
* @param string $contextKey The key for context keys inside logstash "fields", defaults to context
|
||||
*/
|
||||
public function __construct(string $applicationName, ?string $systemName = null, string $extraKey = 'extra', string $contextKey = 'context')
|
||||
{
|
||||
// logstash requires a ISO 8601 format date with optional millisecond precision.
|
||||
parent::__construct('Y-m-d\TH:i:s.uP');
|
||||
|
||||
$this->systemName = $systemName === null ? (string) gethostname() : $systemName;
|
||||
$this->applicationName = $applicationName;
|
||||
$this->extraKey = $extraKey;
|
||||
$this->contextKey = $contextKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function format(array $record): string
|
||||
{
|
||||
$record = parent::format($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'];
|
||||
}
|
||||
if (isset($record['level'])) {
|
||||
$message['monolog_level'] = $record['level'];
|
||||
}
|
||||
if ($this->applicationName) {
|
||||
$message['type'] = $this->applicationName;
|
||||
}
|
||||
if (!empty($record['extra'])) {
|
||||
$message[$this->extraKey] = $record['extra'];
|
||||
}
|
||||
if (!empty($record['context'])) {
|
||||
$message[$this->contextKey] = $record['context'];
|
||||
}
|
||||
|
||||
return $this->toJson($message) . "\n";
|
||||
}
|
||||
}
|
||||
161
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php
vendored
Normal file
161
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php
vendored
Normal file
@@ -0,0 +1,161 @@
|
||||
<?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\Formatter;
|
||||
|
||||
use MongoDB\BSON\UTCDateTime;
|
||||
use Monolog\Utils;
|
||||
|
||||
/**
|
||||
* Formats a record for use with the MongoDBHandler.
|
||||
*
|
||||
* @author Florian Plattner <me@florianplattner.de>
|
||||
*/
|
||||
class MongoDBFormatter implements FormatterInterface
|
||||
{
|
||||
/** @var bool */
|
||||
private $exceptionTraceAsString;
|
||||
/** @var int */
|
||||
private $maxNestingLevel;
|
||||
/** @var bool */
|
||||
private $isLegacyMongoExt;
|
||||
|
||||
/**
|
||||
* @param int $maxNestingLevel 0 means infinite nesting, the $record itself is level 1, $record['context'] is 2
|
||||
* @param bool $exceptionTraceAsString set to false to log exception traces as a sub documents instead of strings
|
||||
*/
|
||||
public function __construct(int $maxNestingLevel = 3, bool $exceptionTraceAsString = true)
|
||||
{
|
||||
$this->maxNestingLevel = max($maxNestingLevel, 0);
|
||||
$this->exceptionTraceAsString = $exceptionTraceAsString;
|
||||
|
||||
$this->isLegacyMongoExt = extension_loaded('mongodb') && version_compare((string) phpversion('mongodb'), '1.1.9', '<=');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function format(array $record): array
|
||||
{
|
||||
/** @var mixed[] $res */
|
||||
$res = $this->formatArray($record);
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return array<mixed[]>
|
||||
*/
|
||||
public function formatBatch(array $records): array
|
||||
{
|
||||
$formatted = [];
|
||||
foreach ($records as $key => $record) {
|
||||
$formatted[$key] = $this->format($record);
|
||||
}
|
||||
|
||||
return $formatted;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $array
|
||||
* @return mixed[]|string Array except when max nesting level is reached then a string "[...]"
|
||||
*/
|
||||
protected function formatArray(array $array, int $nestingLevel = 0)
|
||||
{
|
||||
if ($this->maxNestingLevel > 0 && $nestingLevel > $this->maxNestingLevel) {
|
||||
return '[...]';
|
||||
}
|
||||
|
||||
foreach ($array as $name => $value) {
|
||||
if ($value instanceof \DateTimeInterface) {
|
||||
$array[$name] = $this->formatDate($value, $nestingLevel + 1);
|
||||
} elseif ($value instanceof \Throwable) {
|
||||
$array[$name] = $this->formatException($value, $nestingLevel + 1);
|
||||
} elseif (is_array($value)) {
|
||||
$array[$name] = $this->formatArray($value, $nestingLevel + 1);
|
||||
} elseif (is_object($value)) {
|
||||
$array[$name] = $this->formatObject($value, $nestingLevel + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @return mixed[]|string
|
||||
*/
|
||||
protected function formatObject($value, int $nestingLevel)
|
||||
{
|
||||
$objectVars = get_object_vars($value);
|
||||
$objectVars['class'] = Utils::getClass($value);
|
||||
|
||||
return $this->formatArray($objectVars, $nestingLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]|string
|
||||
*/
|
||||
protected function formatException(\Throwable $exception, int $nestingLevel)
|
||||
{
|
||||
$formattedException = [
|
||||
'class' => Utils::getClass($exception),
|
||||
'message' => $exception->getMessage(),
|
||||
'code' => (int) $exception->getCode(),
|
||||
'file' => $exception->getFile() . ':' . $exception->getLine(),
|
||||
];
|
||||
|
||||
if ($this->exceptionTraceAsString === true) {
|
||||
$formattedException['trace'] = $exception->getTraceAsString();
|
||||
} else {
|
||||
$formattedException['trace'] = $exception->getTrace();
|
||||
}
|
||||
|
||||
return $this->formatArray($formattedException, $nestingLevel);
|
||||
}
|
||||
|
||||
protected function formatDate(\DateTimeInterface $value, int $nestingLevel): UTCDateTime
|
||||
{
|
||||
if ($this->isLegacyMongoExt) {
|
||||
return $this->legacyGetMongoDbDateTime($value);
|
||||
}
|
||||
|
||||
return $this->getMongoDbDateTime($value);
|
||||
}
|
||||
|
||||
private function getMongoDbDateTime(\DateTimeInterface $value): UTCDateTime
|
||||
{
|
||||
return new UTCDateTime((int) floor(((float) $value->format('U.u')) * 1000));
|
||||
}
|
||||
|
||||
/**
|
||||
* This is needed to support MongoDB Driver v1.19 and below
|
||||
*
|
||||
* See https://github.com/mongodb/mongo-php-driver/issues/426
|
||||
*
|
||||
* It can probably be removed in 2.1 or later once MongoDB's 1.2 is released and widely adopted
|
||||
*/
|
||||
private function legacyGetMongoDbDateTime(\DateTimeInterface $value): UTCDateTime
|
||||
{
|
||||
$milliseconds = floor(((float) $value->format('U.u')) * 1000);
|
||||
|
||||
$milliseconds = (PHP_INT_SIZE == 8) //64-bit OS?
|
||||
? (int) $milliseconds
|
||||
: (string) $milliseconds;
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
return new UTCDateTime($milliseconds);
|
||||
}
|
||||
}
|
||||
279
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php
vendored
Normal file
279
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php
vendored
Normal file
@@ -0,0 +1,279 @@
|
||||
<?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\Formatter;
|
||||
|
||||
use Monolog\DateTimeImmutable;
|
||||
use Monolog\Utils;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Normalizes incoming records to remove objects/resources so it's easier to dump to various targets
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
class NormalizerFormatter implements FormatterInterface
|
||||
{
|
||||
public const SIMPLE_DATE = "Y-m-d\TH:i:sP";
|
||||
|
||||
/** @var string */
|
||||
protected $dateFormat;
|
||||
/** @var int */
|
||||
protected $maxNormalizeDepth = 9;
|
||||
/** @var int */
|
||||
protected $maxNormalizeItemCount = 1000;
|
||||
|
||||
/** @var int */
|
||||
private $jsonEncodeOptions = Utils::DEFAULT_JSON_FLAGS;
|
||||
|
||||
/**
|
||||
* @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format
|
||||
*/
|
||||
public function __construct(?string $dateFormat = null)
|
||||
{
|
||||
$this->dateFormat = null === $dateFormat ? static::SIMPLE_DATE : $dateFormat;
|
||||
if (!function_exists('json_encode')) {
|
||||
throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s NormalizerFormatter');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @param mixed[] $record
|
||||
*/
|
||||
public function format(array $record)
|
||||
{
|
||||
return $this->normalize($record);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function formatBatch(array $records)
|
||||
{
|
||||
foreach ($records as $key => $record) {
|
||||
$records[$key] = $this->format($record);
|
||||
}
|
||||
|
||||
return $records;
|
||||
}
|
||||
|
||||
public function getDateFormat(): string
|
||||
{
|
||||
return $this->dateFormat;
|
||||
}
|
||||
|
||||
public function setDateFormat(string $dateFormat): self
|
||||
{
|
||||
$this->dateFormat = $dateFormat;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum number of normalization levels to go through
|
||||
*/
|
||||
public function getMaxNormalizeDepth(): int
|
||||
{
|
||||
return $this->maxNormalizeDepth;
|
||||
}
|
||||
|
||||
public function setMaxNormalizeDepth(int $maxNormalizeDepth): self
|
||||
{
|
||||
$this->maxNormalizeDepth = $maxNormalizeDepth;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum number of items to normalize per level
|
||||
*/
|
||||
public function getMaxNormalizeItemCount(): int
|
||||
{
|
||||
return $this->maxNormalizeItemCount;
|
||||
}
|
||||
|
||||
public function setMaxNormalizeItemCount(int $maxNormalizeItemCount): self
|
||||
{
|
||||
$this->maxNormalizeItemCount = $maxNormalizeItemCount;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables `json_encode` pretty print.
|
||||
*/
|
||||
public function setJsonPrettyPrint(bool $enable): self
|
||||
{
|
||||
if ($enable) {
|
||||
$this->jsonEncodeOptions |= JSON_PRETTY_PRINT;
|
||||
} else {
|
||||
$this->jsonEncodeOptions &= ~JSON_PRETTY_PRINT;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $data
|
||||
* @return null|scalar|array<array|scalar|null>
|
||||
*/
|
||||
protected function normalize($data, int $depth = 0)
|
||||
{
|
||||
if ($depth > $this->maxNormalizeDepth) {
|
||||
return 'Over ' . $this->maxNormalizeDepth . ' levels deep, aborting normalization';
|
||||
}
|
||||
|
||||
if (null === $data || is_scalar($data)) {
|
||||
if (is_float($data)) {
|
||||
if (is_infinite($data)) {
|
||||
return ($data > 0 ? '' : '-') . 'INF';
|
||||
}
|
||||
if (is_nan($data)) {
|
||||
return 'NaN';
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
if (is_array($data)) {
|
||||
$normalized = [];
|
||||
|
||||
$count = 1;
|
||||
foreach ($data as $key => $value) {
|
||||
if ($count++ > $this->maxNormalizeItemCount) {
|
||||
$normalized['...'] = 'Over ' . $this->maxNormalizeItemCount . ' items ('.count($data).' total), aborting normalization';
|
||||
break;
|
||||
}
|
||||
|
||||
$normalized[$key] = $this->normalize($value, $depth + 1);
|
||||
}
|
||||
|
||||
return $normalized;
|
||||
}
|
||||
|
||||
if ($data instanceof \DateTimeInterface) {
|
||||
return $this->formatDate($data);
|
||||
}
|
||||
|
||||
if (is_object($data)) {
|
||||
if ($data instanceof Throwable) {
|
||||
return $this->normalizeException($data, $depth);
|
||||
}
|
||||
|
||||
if ($data instanceof \JsonSerializable) {
|
||||
/** @var null|scalar|array<array|scalar|null> $value */
|
||||
$value = $data->jsonSerialize();
|
||||
} elseif (method_exists($data, '__toString')) {
|
||||
/** @var string $value */
|
||||
$value = $data->__toString();
|
||||
} else {
|
||||
// the rest is normalized by json encoding and decoding it
|
||||
/** @var null|scalar|array<array|scalar|null> $value */
|
||||
$value = json_decode($this->toJson($data, true), true);
|
||||
}
|
||||
|
||||
return [Utils::getClass($data) => $value];
|
||||
}
|
||||
|
||||
if (is_resource($data)) {
|
||||
return sprintf('[resource(%s)]', get_resource_type($data));
|
||||
}
|
||||
|
||||
return '[unknown('.gettype($data).')]';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
protected function normalizeException(Throwable $e, int $depth = 0)
|
||||
{
|
||||
if ($e instanceof \JsonSerializable) {
|
||||
return (array) $e->jsonSerialize();
|
||||
}
|
||||
|
||||
$data = [
|
||||
'class' => Utils::getClass($e),
|
||||
'message' => $e->getMessage(),
|
||||
'code' => (int) $e->getCode(),
|
||||
'file' => $e->getFile().':'.$e->getLine(),
|
||||
];
|
||||
|
||||
if ($e instanceof \SoapFault) {
|
||||
if (isset($e->faultcode)) {
|
||||
$data['faultcode'] = $e->faultcode;
|
||||
}
|
||||
|
||||
if (isset($e->faultactor)) {
|
||||
$data['faultactor'] = $e->faultactor;
|
||||
}
|
||||
|
||||
if (isset($e->detail)) {
|
||||
if (is_string($e->detail)) {
|
||||
$data['detail'] = $e->detail;
|
||||
} elseif (is_object($e->detail) || is_array($e->detail)) {
|
||||
$data['detail'] = $this->toJson($e->detail, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$trace = $e->getTrace();
|
||||
foreach ($trace as $frame) {
|
||||
if (isset($frame['file'])) {
|
||||
$data['trace'][] = $frame['file'].':'.$frame['line'];
|
||||
}
|
||||
}
|
||||
|
||||
if ($previous = $e->getPrevious()) {
|
||||
$data['previous'] = $this->normalizeException($previous, $depth + 1);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JSON representation of a value
|
||||
*
|
||||
* @param mixed $data
|
||||
* @throws \RuntimeException if encoding fails and errors are not ignored
|
||||
* @return string if encoding fails and ignoreErrors is true 'null' is returned
|
||||
*/
|
||||
protected function toJson($data, bool $ignoreErrors = false): string
|
||||
{
|
||||
return Utils::jsonEncode($data, $this->jsonEncodeOptions, $ignoreErrors);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function formatDate(\DateTimeInterface $date)
|
||||
{
|
||||
// in case the date format isn't custom then we defer to the custom DateTimeImmutable
|
||||
// formatting logic, which will pick the right format based on whether useMicroseconds is on
|
||||
if ($this->dateFormat === self::SIMPLE_DATE && $date instanceof DateTimeImmutable) {
|
||||
return (string) $date;
|
||||
}
|
||||
|
||||
return $date->format($this->dateFormat);
|
||||
}
|
||||
|
||||
public function addJsonEncodeOption(int $option): void
|
||||
{
|
||||
$this->jsonEncodeOptions |= $option;
|
||||
}
|
||||
|
||||
public function removeJsonEncodeOption(int $option): void
|
||||
{
|
||||
$this->jsonEncodeOptions &= ~$option;
|
||||
}
|
||||
}
|
||||
51
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php
vendored
Normal file
51
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
<?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\Formatter;
|
||||
|
||||
/**
|
||||
* Formats data into an associative array of scalar values.
|
||||
* Objects and arrays will be JSON encoded.
|
||||
*
|
||||
* @author Andrew Lawson <adlawson@gmail.com>
|
||||
*/
|
||||
class ScalarFormatter extends NormalizerFormatter
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @phpstan-return array<string, scalar|null> $record
|
||||
*/
|
||||
public function format(array $record): array
|
||||
{
|
||||
$result = [];
|
||||
foreach ($record as $key => $value) {
|
||||
$result[$key] = $this->normalizeValue($value);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @return scalar|null
|
||||
*/
|
||||
protected function normalizeValue($value)
|
||||
{
|
||||
$normalized = $this->normalize($value);
|
||||
|
||||
if (is_array($normalized)) {
|
||||
return $this->toJson($normalized, true);
|
||||
}
|
||||
|
||||
return $normalized;
|
||||
}
|
||||
}
|
||||
139
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php
vendored
Normal file
139
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
<?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\Formatter;
|
||||
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* Serializes a log message according to Wildfire's header requirements
|
||||
*
|
||||
* @author Eric Clemmons (@ericclemmons) <eric@uxdriven.com>
|
||||
* @author Christophe Coevoet <stof@notk.org>
|
||||
* @author Kirill chEbba Chebunin <iam@chebba.org>
|
||||
*
|
||||
* @phpstan-import-type Level from \Monolog\Logger
|
||||
*/
|
||||
class WildfireFormatter extends NormalizerFormatter
|
||||
{
|
||||
/**
|
||||
* Translates Monolog log levels to Wildfire levels.
|
||||
*
|
||||
* @var array<Level, string>
|
||||
*/
|
||||
private $logLevels = [
|
||||
Logger::DEBUG => 'LOG',
|
||||
Logger::INFO => 'INFO',
|
||||
Logger::NOTICE => 'INFO',
|
||||
Logger::WARNING => 'WARN',
|
||||
Logger::ERROR => 'ERROR',
|
||||
Logger::CRITICAL => 'ERROR',
|
||||
Logger::ALERT => 'ERROR',
|
||||
Logger::EMERGENCY => 'ERROR',
|
||||
];
|
||||
|
||||
/**
|
||||
* @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format
|
||||
*/
|
||||
public function __construct(?string $dateFormat = null)
|
||||
{
|
||||
parent::__construct($dateFormat);
|
||||
|
||||
// http headers do not like non-ISO-8559-1 characters
|
||||
$this->removeJsonEncodeOption(JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function format(array $record): string
|
||||
{
|
||||
// Retrieve the line and file if set and remove them from the formatted extra
|
||||
$file = $line = '';
|
||||
if (isset($record['extra']['file'])) {
|
||||
$file = $record['extra']['file'];
|
||||
unset($record['extra']['file']);
|
||||
}
|
||||
if (isset($record['extra']['line'])) {
|
||||
$line = $record['extra']['line'];
|
||||
unset($record['extra']['line']);
|
||||
}
|
||||
|
||||
/** @var mixed[] $record */
|
||||
$record = $this->normalize($record);
|
||||
$message = ['message' => $record['message']];
|
||||
$handleError = false;
|
||||
if ($record['context']) {
|
||||
$message['context'] = $record['context'];
|
||||
$handleError = true;
|
||||
}
|
||||
if ($record['extra']) {
|
||||
$message['extra'] = $record['extra'];
|
||||
$handleError = true;
|
||||
}
|
||||
if (count($message) === 1) {
|
||||
$message = reset($message);
|
||||
}
|
||||
|
||||
if (isset($record['context']['table'])) {
|
||||
$type = 'TABLE';
|
||||
$label = $record['channel'] .': '. $record['message'];
|
||||
$message = $record['context']['table'];
|
||||
} else {
|
||||
$type = $this->logLevels[$record['level']];
|
||||
$label = $record['channel'];
|
||||
}
|
||||
|
||||
// Create JSON object describing the appearance of the message in the console
|
||||
$json = $this->toJson([
|
||||
[
|
||||
'Type' => $type,
|
||||
'File' => $file,
|
||||
'Line' => $line,
|
||||
'Label' => $label,
|
||||
],
|
||||
$message,
|
||||
], $handleError);
|
||||
|
||||
// The message itself is a serialization of the above JSON object + it's length
|
||||
return sprintf(
|
||||
'%d|%s|',
|
||||
strlen($json),
|
||||
$json
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @phpstan-return never
|
||||
*/
|
||||
public function formatBatch(array $records)
|
||||
{
|
||||
throw new \BadMethodCallException('Batch formatting does not make sense for the WildfireFormatter');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return null|scalar|array<array|scalar|null>|object
|
||||
*/
|
||||
protected function normalize($data, int $depth = 0)
|
||||
{
|
||||
if (is_object($data) && !$data instanceof \DateTimeInterface) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
return parent::normalize($data, $depth);
|
||||
}
|
||||
}
|
||||
112
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php
vendored
Normal file
112
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\ResettableInterface;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
* Base Handler class providing basic level/bubble support
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* @phpstan-import-type Level from \Monolog\Logger
|
||||
* @phpstan-import-type LevelName from \Monolog\Logger
|
||||
*/
|
||||
abstract class AbstractHandler extends Handler implements ResettableInterface
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
* @phpstan-var Level
|
||||
*/
|
||||
protected $level = Logger::DEBUG;
|
||||
/** @var bool */
|
||||
protected $bubble = true;
|
||||
|
||||
/**
|
||||
* @param int|string $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
|
||||
*
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $level
|
||||
*/
|
||||
public function __construct($level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
$this->setLevel($level);
|
||||
$this->bubble = $bubble;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function isHandling(array $record): bool
|
||||
{
|
||||
return $record['level'] >= $this->level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets minimum logging level at which this handler will be triggered.
|
||||
*
|
||||
* @param Level|LevelName|LogLevel::* $level Level or level name
|
||||
* @return self
|
||||
*/
|
||||
public function setLevel($level): self
|
||||
{
|
||||
$this->level = Logger::toMonologLevel($level);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets minimum logging level at which this handler will be triggered.
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @phpstan-return Level
|
||||
*/
|
||||
public function getLevel(): int
|
||||
{
|
||||
return $this->level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bubbling behavior.
|
||||
*
|
||||
* @param bool $bubble true means that this handler allows bubbling.
|
||||
* false means that bubbling is not permitted.
|
||||
* @return self
|
||||
*/
|
||||
public function setBubble(bool $bubble): self
|
||||
{
|
||||
$this->bubble = $bubble;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bubbling behavior.
|
||||
*
|
||||
* @return bool true means that this handler allows bubbling.
|
||||
* false means that bubbling is not permitted.
|
||||
*/
|
||||
public function getBubble(): bool
|
||||
{
|
||||
return $this->bubble;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Base Handler class providing the Handler structure, including processors and formatters
|
||||
*
|
||||
* Classes extending it should (in most cases) only implement write($record)
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @author Christophe Coevoet <stof@notk.org>
|
||||
*
|
||||
* @phpstan-import-type LevelName from \Monolog\Logger
|
||||
* @phpstan-import-type Level from \Monolog\Logger
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
* @phpstan-type FormattedRecord array{message: string, context: mixed[], level: Level, level_name: LevelName, channel: string, datetime: \DateTimeImmutable, extra: mixed[], formatted: mixed}
|
||||
*/
|
||||
abstract class AbstractProcessingHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface
|
||||
{
|
||||
use ProcessableHandlerTrait;
|
||||
use FormattableHandlerTrait;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handle(array $record): bool
|
||||
{
|
||||
if (!$this->isHandling($record)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->processors) {
|
||||
/** @var Record $record */
|
||||
$record = $this->processRecord($record);
|
||||
}
|
||||
|
||||
$record['formatted'] = $this->getFormatter()->format($record);
|
||||
|
||||
$this->write($record);
|
||||
|
||||
return false === $this->bubble;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the record down to the log of the implementing handler
|
||||
*
|
||||
* @phpstan-param FormattedRecord $record
|
||||
*/
|
||||
abstract protected function write(array $record): void;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
parent::reset();
|
||||
|
||||
$this->resetProcessors();
|
||||
}
|
||||
}
|
||||
106
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php
vendored
Normal file
106
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
|
||||
/**
|
||||
* Common syslog functionality
|
||||
*
|
||||
* @phpstan-import-type Level from \Monolog\Logger
|
||||
*/
|
||||
abstract class AbstractSyslogHandler extends AbstractProcessingHandler
|
||||
{
|
||||
/** @var int */
|
||||
protected $facility;
|
||||
|
||||
/**
|
||||
* Translates Monolog log levels to syslog log priorities.
|
||||
* @var array
|
||||
* @phpstan-var array<Level, int>
|
||||
*/
|
||||
protected $logLevels = [
|
||||
Logger::DEBUG => LOG_DEBUG,
|
||||
Logger::INFO => LOG_INFO,
|
||||
Logger::NOTICE => LOG_NOTICE,
|
||||
Logger::WARNING => LOG_WARNING,
|
||||
Logger::ERROR => LOG_ERR,
|
||||
Logger::CRITICAL => LOG_CRIT,
|
||||
Logger::ALERT => LOG_ALERT,
|
||||
Logger::EMERGENCY => LOG_EMERG,
|
||||
];
|
||||
|
||||
/**
|
||||
* List of valid log facility names.
|
||||
* @var array<string, int>
|
||||
*/
|
||||
protected $facilities = [
|
||||
'auth' => LOG_AUTH,
|
||||
'authpriv' => LOG_AUTHPRIV,
|
||||
'cron' => LOG_CRON,
|
||||
'daemon' => LOG_DAEMON,
|
||||
'kern' => LOG_KERN,
|
||||
'lpr' => LOG_LPR,
|
||||
'mail' => LOG_MAIL,
|
||||
'news' => LOG_NEWS,
|
||||
'syslog' => LOG_SYSLOG,
|
||||
'user' => LOG_USER,
|
||||
'uucp' => LOG_UUCP,
|
||||
];
|
||||
|
||||
/**
|
||||
* @param string|int $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant
|
||||
*/
|
||||
public function __construct($facility = LOG_USER, $level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
parent::__construct($level, $bubble);
|
||||
|
||||
if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
|
||||
$this->facilities['local0'] = LOG_LOCAL0;
|
||||
$this->facilities['local1'] = LOG_LOCAL1;
|
||||
$this->facilities['local2'] = LOG_LOCAL2;
|
||||
$this->facilities['local3'] = LOG_LOCAL3;
|
||||
$this->facilities['local4'] = LOG_LOCAL4;
|
||||
$this->facilities['local5'] = LOG_LOCAL5;
|
||||
$this->facilities['local6'] = LOG_LOCAL6;
|
||||
$this->facilities['local7'] = LOG_LOCAL7;
|
||||
} else {
|
||||
$this->facilities['local0'] = 128; // LOG_LOCAL0
|
||||
$this->facilities['local1'] = 136; // LOG_LOCAL1
|
||||
$this->facilities['local2'] = 144; // LOG_LOCAL2
|
||||
$this->facilities['local3'] = 152; // LOG_LOCAL3
|
||||
$this->facilities['local4'] = 160; // LOG_LOCAL4
|
||||
$this->facilities['local5'] = 168; // LOG_LOCAL5
|
||||
$this->facilities['local6'] = 176; // LOG_LOCAL6
|
||||
$this->facilities['local7'] = 184; // LOG_LOCAL7
|
||||
}
|
||||
|
||||
// convert textual description of facility to syslog constant
|
||||
if (is_string($facility) && array_key_exists(strtolower($facility), $this->facilities)) {
|
||||
$facility = $this->facilities[strtolower($facility)];
|
||||
} elseif (!in_array($facility, array_values($this->facilities), true)) {
|
||||
throw new \UnexpectedValueException('Unknown facility value "'.$facility.'" given');
|
||||
}
|
||||
|
||||
$this->facility = $facility;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getDefaultFormatter(): FormatterInterface
|
||||
{
|
||||
return new LineFormatter('%channel%.%level_name%: %message% %context% %extra%');
|
||||
}
|
||||
}
|
||||
141
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php
vendored
Normal file
141
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Monolog\Formatter\JsonFormatter;
|
||||
use PhpAmqpLib\Message\AMQPMessage;
|
||||
use PhpAmqpLib\Channel\AMQPChannel;
|
||||
use AMQPExchange;
|
||||
|
||||
/**
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
*/
|
||||
class AmqpHandler extends AbstractProcessingHandler
|
||||
{
|
||||
/**
|
||||
* @var AMQPExchange|AMQPChannel $exchange
|
||||
*/
|
||||
protected $exchange;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $exchangeName;
|
||||
|
||||
/**
|
||||
* @param AMQPExchange|AMQPChannel $exchange AMQPExchange (php AMQP ext) or PHP AMQP lib channel, ready for use
|
||||
* @param string|null $exchangeName Optional exchange name, for AMQPChannel (PhpAmqpLib) only
|
||||
*/
|
||||
public function __construct($exchange, ?string $exchangeName = null, $level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
if ($exchange instanceof AMQPChannel) {
|
||||
$this->exchangeName = (string) $exchangeName;
|
||||
} elseif (!$exchange instanceof AMQPExchange) {
|
||||
throw new \InvalidArgumentException('PhpAmqpLib\Channel\AMQPChannel or AMQPExchange instance required');
|
||||
} elseif ($exchangeName) {
|
||||
@trigger_error('The $exchangeName parameter can only be passed when using PhpAmqpLib, if using an AMQPExchange instance configure it beforehand', E_USER_DEPRECATED);
|
||||
}
|
||||
$this->exchange = $exchange;
|
||||
|
||||
parent::__construct($level, $bubble);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
$data = $record["formatted"];
|
||||
$routingKey = $this->getRoutingKey($record);
|
||||
|
||||
if ($this->exchange instanceof AMQPExchange) {
|
||||
$this->exchange->publish(
|
||||
$data,
|
||||
$routingKey,
|
||||
0,
|
||||
[
|
||||
'delivery_mode' => 2,
|
||||
'content_type' => 'application/json',
|
||||
]
|
||||
);
|
||||
} else {
|
||||
$this->exchange->basic_publish(
|
||||
$this->createAmqpMessage($data),
|
||||
$this->exchangeName,
|
||||
$routingKey
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handleBatch(array $records): void
|
||||
{
|
||||
if ($this->exchange instanceof AMQPExchange) {
|
||||
parent::handleBatch($records);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($records as $record) {
|
||||
if (!$this->isHandling($record)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/** @var Record $record */
|
||||
$record = $this->processRecord($record);
|
||||
$data = $this->getFormatter()->format($record);
|
||||
|
||||
$this->exchange->batch_basic_publish(
|
||||
$this->createAmqpMessage($data),
|
||||
$this->exchangeName,
|
||||
$this->getRoutingKey($record)
|
||||
);
|
||||
}
|
||||
|
||||
$this->exchange->publish_batch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the routing key for the AMQP exchange
|
||||
*
|
||||
* @phpstan-param Record $record
|
||||
*/
|
||||
protected function getRoutingKey(array $record): string
|
||||
{
|
||||
$routingKey = sprintf('%s.%s', $record['level_name'], $record['channel']);
|
||||
|
||||
return strtolower($routingKey);
|
||||
}
|
||||
|
||||
private function createAmqpMessage(string $data): AMQPMessage
|
||||
{
|
||||
return new AMQPMessage(
|
||||
$data,
|
||||
[
|
||||
'delivery_mode' => 2,
|
||||
'content_type' => 'application/json',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getDefaultFormatter(): FormatterInterface
|
||||
{
|
||||
return new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, false);
|
||||
}
|
||||
}
|
||||
270
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php
vendored
Normal file
270
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php
vendored
Normal file
@@ -0,0 +1,270 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Monolog\Utils;
|
||||
|
||||
/**
|
||||
* Handler sending logs to browser's javascript console with no browser extension required
|
||||
*
|
||||
* @author Olivier Poitrey <rs@dailymotion.com>
|
||||
*
|
||||
* @phpstan-import-type FormattedRecord from AbstractProcessingHandler
|
||||
*/
|
||||
class BrowserConsoleHandler extends AbstractProcessingHandler
|
||||
{
|
||||
/** @var bool */
|
||||
protected static $initialized = false;
|
||||
/** @var FormattedRecord[] */
|
||||
protected static $records = [];
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* Formatted output may contain some formatting markers to be transferred to `console.log` using the %c format.
|
||||
*
|
||||
* Example of formatted string:
|
||||
*
|
||||
* You can do [[blue text]]{color: blue} or [[green background]]{background-color: green; color: white}
|
||||
*/
|
||||
protected function getDefaultFormatter(): FormatterInterface
|
||||
{
|
||||
return new LineFormatter('[[%channel%]]{macro: autolabel} [[%level_name%]]{font-weight: bold} %message%');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
// Accumulate records
|
||||
static::$records[] = $record;
|
||||
|
||||
// Register shutdown handler if not already done
|
||||
if (!static::$initialized) {
|
||||
static::$initialized = true;
|
||||
$this->registerShutdownFunction();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert records to javascript console commands and send it to the browser.
|
||||
* This method is automatically called on PHP shutdown if output is HTML or Javascript.
|
||||
*/
|
||||
public static function send(): void
|
||||
{
|
||||
$format = static::getResponseFormat();
|
||||
if ($format === 'unknown') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (count(static::$records)) {
|
||||
if ($format === 'html') {
|
||||
static::writeOutput('<script>' . static::generateScript() . '</script>');
|
||||
} elseif ($format === 'js') {
|
||||
static::writeOutput(static::generateScript());
|
||||
}
|
||||
static::resetStatic();
|
||||
}
|
||||
}
|
||||
|
||||
public function close(): void
|
||||
{
|
||||
self::resetStatic();
|
||||
}
|
||||
|
||||
public function reset()
|
||||
{
|
||||
parent::reset();
|
||||
|
||||
self::resetStatic();
|
||||
}
|
||||
|
||||
/**
|
||||
* Forget all logged records
|
||||
*/
|
||||
public static function resetStatic(): void
|
||||
{
|
||||
static::$records = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for register_shutdown_function to allow overriding
|
||||
*/
|
||||
protected function registerShutdownFunction(): void
|
||||
{
|
||||
if (PHP_SAPI !== 'cli') {
|
||||
register_shutdown_function(['Monolog\Handler\BrowserConsoleHandler', 'send']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for echo to allow overriding
|
||||
*/
|
||||
protected static function writeOutput(string $str): void
|
||||
{
|
||||
echo $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the format of the response
|
||||
*
|
||||
* If Content-Type is set to application/javascript or text/javascript -> js
|
||||
* If Content-Type is set to text/html, or is unset -> html
|
||||
* If Content-Type is anything else -> unknown
|
||||
*
|
||||
* @return string One of 'js', 'html' or 'unknown'
|
||||
*/
|
||||
protected static function getResponseFormat(): string
|
||||
{
|
||||
// Check content type
|
||||
foreach (headers_list() as $header) {
|
||||
if (stripos($header, 'content-type:') === 0) {
|
||||
// This handler only works with HTML and javascript outputs
|
||||
// text/javascript is obsolete in favour of application/javascript, but still used
|
||||
if (stripos($header, 'application/javascript') !== false || stripos($header, 'text/javascript') !== false) {
|
||||
return 'js';
|
||||
}
|
||||
if (stripos($header, 'text/html') === false) {
|
||||
return 'unknown';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 'html';
|
||||
}
|
||||
|
||||
private static function generateScript(): string
|
||||
{
|
||||
$script = [];
|
||||
foreach (static::$records as $record) {
|
||||
$context = static::dump('Context', $record['context']);
|
||||
$extra = static::dump('Extra', $record['extra']);
|
||||
|
||||
if (empty($context) && empty($extra)) {
|
||||
$script[] = static::call_array('log', static::handleStyles($record['formatted']));
|
||||
} else {
|
||||
$script = array_merge(
|
||||
$script,
|
||||
[static::call_array('groupCollapsed', static::handleStyles($record['formatted']))],
|
||||
$context,
|
||||
$extra,
|
||||
[static::call('groupEnd')]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return "(function (c) {if (c && c.groupCollapsed) {\n" . implode("\n", $script) . "\n}})(console);";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
private static function handleStyles(string $formatted): array
|
||||
{
|
||||
$args = [];
|
||||
$format = '%c' . $formatted;
|
||||
preg_match_all('/\[\[(.*?)\]\]\{([^}]*)\}/s', $format, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
|
||||
|
||||
foreach (array_reverse($matches) as $match) {
|
||||
$args[] = '"font-weight: normal"';
|
||||
$args[] = static::quote(static::handleCustomStyles($match[2][0], $match[1][0]));
|
||||
|
||||
$pos = $match[0][1];
|
||||
$format = Utils::substr($format, 0, $pos) . '%c' . $match[1][0] . '%c' . Utils::substr($format, $pos + strlen($match[0][0]));
|
||||
}
|
||||
|
||||
$args[] = static::quote('font-weight: normal');
|
||||
$args[] = static::quote($format);
|
||||
|
||||
return array_reverse($args);
|
||||
}
|
||||
|
||||
private static function handleCustomStyles(string $style, string $string): string
|
||||
{
|
||||
static $colors = ['blue', 'green', 'red', 'magenta', 'orange', 'black', 'grey'];
|
||||
static $labels = [];
|
||||
|
||||
$style = preg_replace_callback('/macro\s*:(.*?)(?:;|$)/', function (array $m) use ($string, &$colors, &$labels) {
|
||||
if (trim($m[1]) === 'autolabel') {
|
||||
// Format the string as a label with consistent auto assigned background color
|
||||
if (!isset($labels[$string])) {
|
||||
$labels[$string] = $colors[count($labels) % count($colors)];
|
||||
}
|
||||
$color = $labels[$string];
|
||||
|
||||
return "background-color: $color; color: white; border-radius: 3px; padding: 0 2px 0 2px";
|
||||
}
|
||||
|
||||
return $m[1];
|
||||
}, $style);
|
||||
|
||||
if (null === $style) {
|
||||
$pcreErrorCode = preg_last_error();
|
||||
throw new \RuntimeException('Failed to run preg_replace_callback: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode));
|
||||
}
|
||||
|
||||
return $style;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $dict
|
||||
* @return mixed[]
|
||||
*/
|
||||
private static function dump(string $title, array $dict): array
|
||||
{
|
||||
$script = [];
|
||||
$dict = array_filter($dict);
|
||||
if (empty($dict)) {
|
||||
return $script;
|
||||
}
|
||||
$script[] = static::call('log', static::quote('%c%s'), static::quote('font-weight: bold'), static::quote($title));
|
||||
foreach ($dict as $key => $value) {
|
||||
$value = json_encode($value);
|
||||
if (empty($value)) {
|
||||
$value = static::quote('');
|
||||
}
|
||||
$script[] = static::call('log', static::quote('%s: %o'), static::quote((string) $key), $value);
|
||||
}
|
||||
|
||||
return $script;
|
||||
}
|
||||
|
||||
private static function quote(string $arg): string
|
||||
{
|
||||
return '"' . addcslashes($arg, "\"\n\\") . '"';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $args
|
||||
*/
|
||||
private static function call(...$args): string
|
||||
{
|
||||
$method = array_shift($args);
|
||||
if (!is_string($method)) {
|
||||
throw new \UnexpectedValueException('Expected the first arg to be a string, got: '.var_export($method, true));
|
||||
}
|
||||
|
||||
return static::call_array($method, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $args
|
||||
*/
|
||||
private static function call_array(string $method, array $args): string
|
||||
{
|
||||
return 'c.' . $method . '(' . implode(', ', $args) . ');';
|
||||
}
|
||||
}
|
||||
167
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php
vendored
Normal file
167
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\ResettableInterface;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
|
||||
/**
|
||||
* Buffers all records until closing the handler and then pass them as batch.
|
||||
*
|
||||
* This is useful for a MailHandler to send only one mail per request instead of
|
||||
* sending one per log message.
|
||||
*
|
||||
* @author Christophe Coevoet <stof@notk.org>
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
*/
|
||||
class BufferHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface
|
||||
{
|
||||
use ProcessableHandlerTrait;
|
||||
|
||||
/** @var HandlerInterface */
|
||||
protected $handler;
|
||||
/** @var int */
|
||||
protected $bufferSize = 0;
|
||||
/** @var int */
|
||||
protected $bufferLimit;
|
||||
/** @var bool */
|
||||
protected $flushOnOverflow;
|
||||
/** @var Record[] */
|
||||
protected $buffer = [];
|
||||
/** @var bool */
|
||||
protected $initialized = false;
|
||||
|
||||
/**
|
||||
* @param HandlerInterface $handler Handler.
|
||||
* @param int $bufferLimit How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
|
||||
* @param bool $flushOnOverflow If true, the buffer is flushed when the max size has been reached, by default oldest entries are discarded
|
||||
*/
|
||||
public function __construct(HandlerInterface $handler, int $bufferLimit = 0, $level = Logger::DEBUG, bool $bubble = true, bool $flushOnOverflow = false)
|
||||
{
|
||||
parent::__construct($level, $bubble);
|
||||
$this->handler = $handler;
|
||||
$this->bufferLimit = $bufferLimit;
|
||||
$this->flushOnOverflow = $flushOnOverflow;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handle(array $record): bool
|
||||
{
|
||||
if ($record['level'] < $this->level) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->initialized) {
|
||||
// __destructor() doesn't get called on Fatal errors
|
||||
register_shutdown_function([$this, 'close']);
|
||||
$this->initialized = true;
|
||||
}
|
||||
|
||||
if ($this->bufferLimit > 0 && $this->bufferSize === $this->bufferLimit) {
|
||||
if ($this->flushOnOverflow) {
|
||||
$this->flush();
|
||||
} else {
|
||||
array_shift($this->buffer);
|
||||
$this->bufferSize--;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->processors) {
|
||||
/** @var Record $record */
|
||||
$record = $this->processRecord($record);
|
||||
}
|
||||
|
||||
$this->buffer[] = $record;
|
||||
$this->bufferSize++;
|
||||
|
||||
return false === $this->bubble;
|
||||
}
|
||||
|
||||
public function flush(): void
|
||||
{
|
||||
if ($this->bufferSize === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->handler->handleBatch($this->buffer);
|
||||
$this->clear();
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
// suppress the parent behavior since we already have register_shutdown_function()
|
||||
// to call close(), and the reference contained there will prevent this from being
|
||||
// GC'd until the end of the request
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function close(): void
|
||||
{
|
||||
$this->flush();
|
||||
|
||||
$this->handler->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the buffer without flushing any messages down to the wrapped handler.
|
||||
*/
|
||||
public function clear(): void
|
||||
{
|
||||
$this->bufferSize = 0;
|
||||
$this->buffer = [];
|
||||
}
|
||||
|
||||
public function reset()
|
||||
{
|
||||
$this->flush();
|
||||
|
||||
parent::reset();
|
||||
|
||||
$this->resetProcessors();
|
||||
|
||||
if ($this->handler instanceof ResettableInterface) {
|
||||
$this->handler->reset();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function setFormatter(FormatterInterface $formatter): HandlerInterface
|
||||
{
|
||||
if ($this->handler instanceof FormattableHandlerInterface) {
|
||||
$this->handler->setFormatter($formatter);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
throw new \UnexpectedValueException('The nested handler of type '.get_class($this->handler).' does not support formatters.');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getFormatter(): FormatterInterface
|
||||
{
|
||||
if ($this->handler instanceof FormattableHandlerInterface) {
|
||||
return $this->handler->getFormatter();
|
||||
}
|
||||
|
||||
throw new \UnexpectedValueException('The nested handler of type '.get_class($this->handler).' does not support formatters.');
|
||||
}
|
||||
}
|
||||
196
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php
vendored
Normal file
196
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php
vendored
Normal file
@@ -0,0 +1,196 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Formatter\ChromePHPFormatter;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Monolog\Logger;
|
||||
use Monolog\Utils;
|
||||
|
||||
/**
|
||||
* Handler sending logs to the ChromePHP extension (http://www.chromephp.com/)
|
||||
*
|
||||
* This also works out of the box with Firefox 43+
|
||||
*
|
||||
* @author Christophe Coevoet <stof@notk.org>
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
*/
|
||||
class ChromePHPHandler extends AbstractProcessingHandler
|
||||
{
|
||||
use WebRequestRecognizerTrait;
|
||||
|
||||
/**
|
||||
* Version of the extension
|
||||
*/
|
||||
protected const VERSION = '4.0';
|
||||
|
||||
/**
|
||||
* Header name
|
||||
*/
|
||||
protected const HEADER_NAME = 'X-ChromeLogger-Data';
|
||||
|
||||
/**
|
||||
* Regular expression to detect supported browsers (matches any Chrome, or Firefox 43+)
|
||||
*/
|
||||
protected const USER_AGENT_REGEX = '{\b(?:Chrome/\d+(?:\.\d+)*|HeadlessChrome|Firefox/(?:4[3-9]|[5-9]\d|\d{3,})(?:\.\d)*)\b}';
|
||||
|
||||
/** @var bool */
|
||||
protected static $initialized = false;
|
||||
|
||||
/**
|
||||
* Tracks whether we sent too much data
|
||||
*
|
||||
* Chrome limits the headers to 4KB, so when we sent 3KB we stop sending
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected static $overflowed = false;
|
||||
|
||||
/** @var mixed[] */
|
||||
protected static $json = [
|
||||
'version' => self::VERSION,
|
||||
'columns' => ['label', 'log', 'backtrace', 'type'],
|
||||
'rows' => [],
|
||||
];
|
||||
|
||||
/** @var bool */
|
||||
protected static $sendHeaders = true;
|
||||
|
||||
public function __construct($level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
parent::__construct($level, $bubble);
|
||||
if (!function_exists('json_encode')) {
|
||||
throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s ChromePHPHandler');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handleBatch(array $records): void
|
||||
{
|
||||
if (!$this->isWebRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$messages = [];
|
||||
|
||||
foreach ($records as $record) {
|
||||
if ($record['level'] < $this->level) {
|
||||
continue;
|
||||
}
|
||||
/** @var Record $message */
|
||||
$message = $this->processRecord($record);
|
||||
$messages[] = $message;
|
||||
}
|
||||
|
||||
if (!empty($messages)) {
|
||||
$messages = $this->getFormatter()->formatBatch($messages);
|
||||
self::$json['rows'] = array_merge(self::$json['rows'], $messages);
|
||||
$this->send();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getDefaultFormatter(): FormatterInterface
|
||||
{
|
||||
return new ChromePHPFormatter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates & sends header for a record
|
||||
*
|
||||
* @see sendHeader()
|
||||
* @see send()
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
if (!$this->isWebRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
self::$json['rows'][] = $record['formatted'];
|
||||
|
||||
$this->send();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the log header
|
||||
*
|
||||
* @see sendHeader()
|
||||
*/
|
||||
protected function send(): void
|
||||
{
|
||||
if (self::$overflowed || !self::$sendHeaders) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self::$initialized) {
|
||||
self::$initialized = true;
|
||||
|
||||
self::$sendHeaders = $this->headersAccepted();
|
||||
if (!self::$sendHeaders) {
|
||||
return;
|
||||
}
|
||||
|
||||
self::$json['request_uri'] = $_SERVER['REQUEST_URI'] ?? '';
|
||||
}
|
||||
|
||||
$json = Utils::jsonEncode(self::$json, Utils::DEFAULT_JSON_FLAGS & ~JSON_UNESCAPED_UNICODE, true);
|
||||
$data = base64_encode(utf8_encode($json));
|
||||
if (strlen($data) > 3 * 1024) {
|
||||
self::$overflowed = true;
|
||||
|
||||
$record = [
|
||||
'message' => 'Incomplete logs, chrome header size limit reached',
|
||||
'context' => [],
|
||||
'level' => Logger::WARNING,
|
||||
'level_name' => Logger::getLevelName(Logger::WARNING),
|
||||
'channel' => 'monolog',
|
||||
'datetime' => new \DateTimeImmutable(),
|
||||
'extra' => [],
|
||||
];
|
||||
self::$json['rows'][count(self::$json['rows']) - 1] = $this->getFormatter()->format($record);
|
||||
$json = Utils::jsonEncode(self::$json, null, true);
|
||||
$data = base64_encode(utf8_encode($json));
|
||||
}
|
||||
|
||||
if (trim($data) !== '') {
|
||||
$this->sendHeader(static::HEADER_NAME, $data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send header string to the client
|
||||
*/
|
||||
protected function sendHeader(string $header, string $content): void
|
||||
{
|
||||
if (!headers_sent() && self::$sendHeaders) {
|
||||
header(sprintf('%s: %s', $header, $content));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies if the headers are accepted by the current user agent
|
||||
*/
|
||||
protected function headersAccepted(): bool
|
||||
{
|
||||
if (empty($_SERVER['HTTP_USER_AGENT'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return preg_match(static::USER_AGENT_REGEX, $_SERVER['HTTP_USER_AGENT']) === 1;
|
||||
}
|
||||
}
|
||||
77
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php
vendored
Normal file
77
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Monolog\Formatter\JsonFormatter;
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* CouchDB handler
|
||||
*
|
||||
* @author Markus Bachmann <markus.bachmann@bachi.biz>
|
||||
*/
|
||||
class CouchDBHandler extends AbstractProcessingHandler
|
||||
{
|
||||
/** @var mixed[] */
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* @param mixed[] $options
|
||||
*/
|
||||
public function __construct(array $options = [], $level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
$this->options = array_merge([
|
||||
'host' => 'localhost',
|
||||
'port' => 5984,
|
||||
'dbname' => 'logger',
|
||||
'username' => null,
|
||||
'password' => null,
|
||||
], $options);
|
||||
|
||||
parent::__construct($level, $bubble);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
$basicAuth = null;
|
||||
if ($this->options['username']) {
|
||||
$basicAuth = sprintf('%s:%s@', $this->options['username'], $this->options['password']);
|
||||
}
|
||||
|
||||
$url = 'http://'.$basicAuth.$this->options['host'].':'.$this->options['port'].'/'.$this->options['dbname'];
|
||||
$context = stream_context_create([
|
||||
'http' => [
|
||||
'method' => 'POST',
|
||||
'content' => $record['formatted'],
|
||||
'ignore_errors' => true,
|
||||
'max_redirects' => 0,
|
||||
'header' => 'Content-type: application/json',
|
||||
],
|
||||
]);
|
||||
|
||||
if (false === @file_get_contents($url, false, $context)) {
|
||||
throw new \RuntimeException(sprintf('Could not connect to %s', $url));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getDefaultFormatter(): FormatterInterface
|
||||
{
|
||||
return new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, false);
|
||||
}
|
||||
}
|
||||
166
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php
vendored
Normal file
166
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\Utils;
|
||||
|
||||
/**
|
||||
* Logs to Cube.
|
||||
*
|
||||
* @link http://square.github.com/cube/
|
||||
* @author Wan Chen <kami@kamisama.me>
|
||||
*/
|
||||
class CubeHandler extends AbstractProcessingHandler
|
||||
{
|
||||
/** @var resource|\Socket|null */
|
||||
private $udpConnection = null;
|
||||
/** @var resource|\CurlHandle|null */
|
||||
private $httpConnection = null;
|
||||
/** @var string */
|
||||
private $scheme;
|
||||
/** @var string */
|
||||
private $host;
|
||||
/** @var int */
|
||||
private $port;
|
||||
/** @var string[] */
|
||||
private $acceptedSchemes = ['http', 'udp'];
|
||||
|
||||
/**
|
||||
* Create a Cube handler
|
||||
*
|
||||
* @throws \UnexpectedValueException when given url is not a valid url.
|
||||
* A valid url must consist of three parts : protocol://host:port
|
||||
* Only valid protocols used by Cube are http and udp
|
||||
*/
|
||||
public function __construct(string $url, $level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
$urlInfo = parse_url($url);
|
||||
|
||||
if ($urlInfo === false || !isset($urlInfo['scheme'], $urlInfo['host'], $urlInfo['port'])) {
|
||||
throw new \UnexpectedValueException('URL "'.$url.'" is not valid');
|
||||
}
|
||||
|
||||
if (!in_array($urlInfo['scheme'], $this->acceptedSchemes)) {
|
||||
throw new \UnexpectedValueException(
|
||||
'Invalid protocol (' . $urlInfo['scheme'] . ').'
|
||||
. ' Valid options are ' . implode(', ', $this->acceptedSchemes)
|
||||
);
|
||||
}
|
||||
|
||||
$this->scheme = $urlInfo['scheme'];
|
||||
$this->host = $urlInfo['host'];
|
||||
$this->port = (int) $urlInfo['port'];
|
||||
|
||||
parent::__construct($level, $bubble);
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish a connection to an UDP socket
|
||||
*
|
||||
* @throws \LogicException when unable to connect to the socket
|
||||
* @throws MissingExtensionException when there is no socket extension
|
||||
*/
|
||||
protected function connectUdp(): void
|
||||
{
|
||||
if (!extension_loaded('sockets')) {
|
||||
throw new MissingExtensionException('The sockets extension is required to use udp URLs with the CubeHandler');
|
||||
}
|
||||
|
||||
$udpConnection = socket_create(AF_INET, SOCK_DGRAM, 0);
|
||||
if (false === $udpConnection) {
|
||||
throw new \LogicException('Unable to create a socket');
|
||||
}
|
||||
|
||||
$this->udpConnection = $udpConnection;
|
||||
if (!socket_connect($this->udpConnection, $this->host, $this->port)) {
|
||||
throw new \LogicException('Unable to connect to the socket at ' . $this->host . ':' . $this->port);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish a connection to an http server
|
||||
*
|
||||
* @throws \LogicException when unable to connect to the socket
|
||||
* @throws MissingExtensionException when no curl extension
|
||||
*/
|
||||
protected function connectHttp(): void
|
||||
{
|
||||
if (!extension_loaded('curl')) {
|
||||
throw new MissingExtensionException('The curl extension is required to use http URLs with the CubeHandler');
|
||||
}
|
||||
|
||||
$httpConnection = curl_init('http://'.$this->host.':'.$this->port.'/1.0/event/put');
|
||||
if (false === $httpConnection) {
|
||||
throw new \LogicException('Unable to connect to ' . $this->host . ':' . $this->port);
|
||||
}
|
||||
|
||||
$this->httpConnection = $httpConnection;
|
||||
curl_setopt($this->httpConnection, CURLOPT_CUSTOMREQUEST, "POST");
|
||||
curl_setopt($this->httpConnection, CURLOPT_RETURNTRANSFER, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
$date = $record['datetime'];
|
||||
|
||||
$data = ['time' => $date->format('Y-m-d\TH:i:s.uO')];
|
||||
unset($record['datetime']);
|
||||
|
||||
if (isset($record['context']['type'])) {
|
||||
$data['type'] = $record['context']['type'];
|
||||
unset($record['context']['type']);
|
||||
} else {
|
||||
$data['type'] = $record['channel'];
|
||||
}
|
||||
|
||||
$data['data'] = $record['context'];
|
||||
$data['data']['level'] = $record['level'];
|
||||
|
||||
if ($this->scheme === 'http') {
|
||||
$this->writeHttp(Utils::jsonEncode($data));
|
||||
} else {
|
||||
$this->writeUdp(Utils::jsonEncode($data));
|
||||
}
|
||||
}
|
||||
|
||||
private function writeUdp(string $data): void
|
||||
{
|
||||
if (!$this->udpConnection) {
|
||||
$this->connectUdp();
|
||||
}
|
||||
|
||||
socket_send($this->udpConnection, $data, strlen($data), 0);
|
||||
}
|
||||
|
||||
private function writeHttp(string $data): void
|
||||
{
|
||||
if (!$this->httpConnection) {
|
||||
$this->connectHttp();
|
||||
}
|
||||
|
||||
if (null === $this->httpConnection) {
|
||||
throw new \LogicException('No connection could be established');
|
||||
}
|
||||
|
||||
curl_setopt($this->httpConnection, CURLOPT_POSTFIELDS, '['.$data.']');
|
||||
curl_setopt($this->httpConnection, CURLOPT_HTTPHEADER, [
|
||||
'Content-Type: application/json',
|
||||
'Content-Length: ' . strlen('['.$data.']'),
|
||||
]);
|
||||
|
||||
Curl\Util::execute($this->httpConnection, 5, false);
|
||||
}
|
||||
}
|
||||
71
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/Curl/Util.php
vendored
Normal file
71
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/Curl/Util.php
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
<?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\Curl;
|
||||
|
||||
use CurlHandle;
|
||||
|
||||
/**
|
||||
* This class is marked as internal and it is not under the BC promise of the package.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class Util
|
||||
{
|
||||
/** @var array<int> */
|
||||
private static $retriableErrorCodes = [
|
||||
CURLE_COULDNT_RESOLVE_HOST,
|
||||
CURLE_COULDNT_CONNECT,
|
||||
CURLE_HTTP_NOT_FOUND,
|
||||
CURLE_READ_ERROR,
|
||||
CURLE_OPERATION_TIMEOUTED,
|
||||
CURLE_HTTP_POST_ERROR,
|
||||
CURLE_SSL_CONNECT_ERROR,
|
||||
];
|
||||
|
||||
/**
|
||||
* Executes a CURL request with optional retries and exception on failure
|
||||
*
|
||||
* @param resource|CurlHandle $ch curl handler
|
||||
* @param int $retries
|
||||
* @param bool $closeAfterDone
|
||||
* @return bool|string @see curl_exec
|
||||
*/
|
||||
public static function execute($ch, int $retries = 5, bool $closeAfterDone = true)
|
||||
{
|
||||
while ($retries--) {
|
||||
$curlResponse = curl_exec($ch);
|
||||
if ($curlResponse === false) {
|
||||
$curlErrno = curl_errno($ch);
|
||||
|
||||
if (false === in_array($curlErrno, self::$retriableErrorCodes, true) || !$retries) {
|
||||
$curlError = curl_error($ch);
|
||||
|
||||
if ($closeAfterDone) {
|
||||
curl_close($ch);
|
||||
}
|
||||
|
||||
throw new \RuntimeException(sprintf('Curl error (code %d): %s', $curlErrno, $curlError));
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($closeAfterDone) {
|
||||
curl_close($ch);
|
||||
}
|
||||
|
||||
return $curlResponse;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
186
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php
vendored
Normal file
186
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php
vendored
Normal file
@@ -0,0 +1,186 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
* Simple handler wrapper that deduplicates log records across multiple requests
|
||||
*
|
||||
* It also includes the BufferHandler functionality and will buffer
|
||||
* all messages until the end of the request or flush() is called.
|
||||
*
|
||||
* This works by storing all log records' messages above $deduplicationLevel
|
||||
* to the file specified by $deduplicationStore. When further logs come in at the end of the
|
||||
* request (or when flush() is called), all those above $deduplicationLevel are checked
|
||||
* against the existing stored logs. If they match and the timestamps in the stored log is
|
||||
* not older than $time seconds, the new log record is discarded. If no log record is new, the
|
||||
* whole data set is discarded.
|
||||
*
|
||||
* This is mainly useful in combination with Mail handlers or things like Slack or HipChat handlers
|
||||
* that send messages to people, to avoid spamming with the same message over and over in case of
|
||||
* a major component failure like a database server being down which makes all requests fail in the
|
||||
* same way.
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
* @phpstan-import-type LevelName from \Monolog\Logger
|
||||
* @phpstan-import-type Level from \Monolog\Logger
|
||||
*/
|
||||
class DeduplicationHandler extends BufferHandler
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $deduplicationStore;
|
||||
|
||||
/**
|
||||
* @var Level
|
||||
*/
|
||||
protected $deduplicationLevel;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $time;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $gc = false;
|
||||
|
||||
/**
|
||||
* @param HandlerInterface $handler Handler.
|
||||
* @param string $deduplicationStore The file/path where the deduplication log should be kept
|
||||
* @param string|int $deduplicationLevel The minimum logging level for log records to be looked at for deduplication purposes
|
||||
* @param int $time The period (in seconds) during which duplicate entries should be suppressed after a given log is sent through
|
||||
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
|
||||
*
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $deduplicationLevel
|
||||
*/
|
||||
public function __construct(HandlerInterface $handler, ?string $deduplicationStore = null, $deduplicationLevel = Logger::ERROR, int $time = 60, bool $bubble = true)
|
||||
{
|
||||
parent::__construct($handler, 0, Logger::DEBUG, $bubble, false);
|
||||
|
||||
$this->deduplicationStore = $deduplicationStore === null ? sys_get_temp_dir() . '/monolog-dedup-' . substr(md5(__FILE__), 0, 20) .'.log' : $deduplicationStore;
|
||||
$this->deduplicationLevel = Logger::toMonologLevel($deduplicationLevel);
|
||||
$this->time = $time;
|
||||
}
|
||||
|
||||
public function flush(): void
|
||||
{
|
||||
if ($this->bufferSize === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$passthru = null;
|
||||
|
||||
foreach ($this->buffer as $record) {
|
||||
if ($record['level'] >= $this->deduplicationLevel) {
|
||||
$passthru = $passthru || !$this->isDuplicate($record);
|
||||
if ($passthru) {
|
||||
$this->appendRecord($record);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// default of null is valid as well as if no record matches duplicationLevel we just pass through
|
||||
if ($passthru === true || $passthru === null) {
|
||||
$this->handler->handleBatch($this->buffer);
|
||||
}
|
||||
|
||||
$this->clear();
|
||||
|
||||
if ($this->gc) {
|
||||
$this->collectLogs();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param Record $record
|
||||
*/
|
||||
private function isDuplicate(array $record): bool
|
||||
{
|
||||
if (!file_exists($this->deduplicationStore)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$store = file($this->deduplicationStore, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
if (!is_array($store)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$yesterday = time() - 86400;
|
||||
$timestampValidity = $record['datetime']->getTimestamp() - $this->time;
|
||||
$expectedMessage = preg_replace('{[\r\n].*}', '', $record['message']);
|
||||
|
||||
for ($i = count($store) - 1; $i >= 0; $i--) {
|
||||
list($timestamp, $level, $message) = explode(':', $store[$i], 3);
|
||||
|
||||
if ($level === $record['level_name'] && $message === $expectedMessage && $timestamp > $timestampValidity) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($timestamp < $yesterday) {
|
||||
$this->gc = true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function collectLogs(): void
|
||||
{
|
||||
if (!file_exists($this->deduplicationStore)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$handle = fopen($this->deduplicationStore, 'rw+');
|
||||
|
||||
if (!$handle) {
|
||||
throw new \RuntimeException('Failed to open file for reading and writing: ' . $this->deduplicationStore);
|
||||
}
|
||||
|
||||
flock($handle, LOCK_EX);
|
||||
$validLogs = [];
|
||||
|
||||
$timestampValidity = time() - $this->time;
|
||||
|
||||
while (!feof($handle)) {
|
||||
$log = fgets($handle);
|
||||
if ($log && substr($log, 0, 10) >= $timestampValidity) {
|
||||
$validLogs[] = $log;
|
||||
}
|
||||
}
|
||||
|
||||
ftruncate($handle, 0);
|
||||
rewind($handle);
|
||||
foreach ($validLogs as $log) {
|
||||
fwrite($handle, $log);
|
||||
}
|
||||
|
||||
flock($handle, LOCK_UN);
|
||||
fclose($handle);
|
||||
|
||||
$this->gc = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param Record $record
|
||||
*/
|
||||
private function appendRecord(array $record): void
|
||||
{
|
||||
file_put_contents($this->deduplicationStore, $record['datetime']->getTimestamp() . ':' . $record['level_name'] . ':' . preg_replace('{[\r\n].*}', '', $record['message']) . "\n", FILE_APPEND);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\Formatter\NormalizerFormatter;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Doctrine\CouchDB\CouchDBClient;
|
||||
|
||||
/**
|
||||
* CouchDB handler for Doctrine CouchDB ODM
|
||||
*
|
||||
* @author Markus Bachmann <markus.bachmann@bachi.biz>
|
||||
*/
|
||||
class DoctrineCouchDBHandler extends AbstractProcessingHandler
|
||||
{
|
||||
/** @var CouchDBClient */
|
||||
private $client;
|
||||
|
||||
public function __construct(CouchDBClient $client, $level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
$this->client = $client;
|
||||
parent::__construct($level, $bubble);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
$this->client->postDocument($record['formatted']);
|
||||
}
|
||||
|
||||
protected function getDefaultFormatter(): FormatterInterface
|
||||
{
|
||||
return new NormalizerFormatter;
|
||||
}
|
||||
}
|
||||
104
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php
vendored
Normal file
104
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
<?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;
|
||||
|
||||
use Aws\Sdk;
|
||||
use Aws\DynamoDb\DynamoDbClient;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Aws\DynamoDb\Marshaler;
|
||||
use Monolog\Formatter\ScalarFormatter;
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* Amazon DynamoDB handler (http://aws.amazon.com/dynamodb/)
|
||||
*
|
||||
* @link https://github.com/aws/aws-sdk-php/
|
||||
* @author Andrew Lawson <adlawson@gmail.com>
|
||||
*/
|
||||
class DynamoDbHandler extends AbstractProcessingHandler
|
||||
{
|
||||
public const DATE_FORMAT = 'Y-m-d\TH:i:s.uO';
|
||||
|
||||
/**
|
||||
* @var DynamoDbClient
|
||||
*/
|
||||
protected $client;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $table;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $version;
|
||||
|
||||
/**
|
||||
* @var Marshaler
|
||||
*/
|
||||
protected $marshaler;
|
||||
|
||||
public function __construct(DynamoDbClient $client, string $table, $level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
/** @phpstan-ignore-next-line */
|
||||
if (defined('Aws\Sdk::VERSION') && version_compare(Sdk::VERSION, '3.0', '>=')) {
|
||||
$this->version = 3;
|
||||
$this->marshaler = new Marshaler;
|
||||
} else {
|
||||
$this->version = 2;
|
||||
}
|
||||
|
||||
$this->client = $client;
|
||||
$this->table = $table;
|
||||
|
||||
parent::__construct($level, $bubble);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
$filtered = $this->filterEmptyFields($record['formatted']);
|
||||
if ($this->version === 3) {
|
||||
$formatted = $this->marshaler->marshalItem($filtered);
|
||||
} else {
|
||||
/** @phpstan-ignore-next-line */
|
||||
$formatted = $this->client->formatAttributes($filtered);
|
||||
}
|
||||
|
||||
$this->client->putItem([
|
||||
'TableName' => $this->table,
|
||||
'Item' => $formatted,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $record
|
||||
* @return mixed[]
|
||||
*/
|
||||
protected function filterEmptyFields(array $record): array
|
||||
{
|
||||
return array_filter($record, function ($value) {
|
||||
return !empty($value) || false === $value || 0 === $value;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getDefaultFormatter(): FormatterInterface
|
||||
{
|
||||
return new ScalarFormatter(self::DATE_FORMAT);
|
||||
}
|
||||
}
|
||||
129
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/ElasticaHandler.php
vendored
Normal file
129
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/ElasticaHandler.php
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
<?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;
|
||||
|
||||
use Elastica\Document;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Monolog\Formatter\ElasticaFormatter;
|
||||
use Monolog\Logger;
|
||||
use Elastica\Client;
|
||||
use Elastica\Exception\ExceptionInterface;
|
||||
|
||||
/**
|
||||
* Elastic Search handler
|
||||
*
|
||||
* Usage example:
|
||||
*
|
||||
* $client = new \Elastica\Client();
|
||||
* $options = array(
|
||||
* 'index' => 'elastic_index_name',
|
||||
* 'type' => 'elastic_doc_type', Types have been removed in Elastica 7
|
||||
* );
|
||||
* $handler = new ElasticaHandler($client, $options);
|
||||
* $log = new Logger('application');
|
||||
* $log->pushHandler($handler);
|
||||
*
|
||||
* @author Jelle Vink <jelle.vink@gmail.com>
|
||||
*/
|
||||
class ElasticaHandler extends AbstractProcessingHandler
|
||||
{
|
||||
/**
|
||||
* @var Client
|
||||
*/
|
||||
protected $client;
|
||||
|
||||
/**
|
||||
* @var mixed[] Handler config options
|
||||
*/
|
||||
protected $options = [];
|
||||
|
||||
/**
|
||||
* @param Client $client Elastica Client object
|
||||
* @param mixed[] $options Handler configuration
|
||||
*/
|
||||
public function __construct(Client $client, array $options = [], $level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
parent::__construct($level, $bubble);
|
||||
$this->client = $client;
|
||||
$this->options = array_merge(
|
||||
[
|
||||
'index' => 'monolog', // Elastic index name
|
||||
'type' => 'record', // Elastic document type
|
||||
'ignore_error' => false, // Suppress Elastica exceptions
|
||||
],
|
||||
$options
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
$this->bulkSend([$record['formatted']]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function setFormatter(FormatterInterface $formatter): HandlerInterface
|
||||
{
|
||||
if ($formatter instanceof ElasticaFormatter) {
|
||||
return parent::setFormatter($formatter);
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException('ElasticaHandler is only compatible with ElasticaFormatter');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function getOptions(): array
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getDefaultFormatter(): FormatterInterface
|
||||
{
|
||||
return new ElasticaFormatter($this->options['index'], $this->options['type']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handleBatch(array $records): void
|
||||
{
|
||||
$documents = $this->getFormatter()->formatBatch($records);
|
||||
$this->bulkSend($documents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use Elasticsearch bulk API to send list of documents
|
||||
*
|
||||
* @param Document[] $documents
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function bulkSend(array $documents): void
|
||||
{
|
||||
try {
|
||||
$this->client->addDocuments($documents);
|
||||
} catch (ExceptionInterface $e) {
|
||||
if (!$this->options['ignore_error']) {
|
||||
throw new \RuntimeException("Error sending messages to Elasticsearch", 0, $e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
187
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.php
vendored
Normal file
187
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.php
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
<?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;
|
||||
|
||||
use Throwable;
|
||||
use RuntimeException;
|
||||
use Monolog\Logger;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Monolog\Formatter\ElasticsearchFormatter;
|
||||
use InvalidArgumentException;
|
||||
use Elasticsearch\Common\Exceptions\RuntimeException as ElasticsearchRuntimeException;
|
||||
use Elasticsearch\Client;
|
||||
|
||||
/**
|
||||
* Elasticsearch handler
|
||||
*
|
||||
* @link https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/index.html
|
||||
*
|
||||
* Simple usage example:
|
||||
*
|
||||
* $client = \Elasticsearch\ClientBuilder::create()
|
||||
* ->setHosts($hosts)
|
||||
* ->build();
|
||||
*
|
||||
* $options = array(
|
||||
* 'index' => 'elastic_index_name',
|
||||
* 'type' => 'elastic_doc_type',
|
||||
* );
|
||||
* $handler = new ElasticsearchHandler($client, $options);
|
||||
* $log = new Logger('application');
|
||||
* $log->pushHandler($handler);
|
||||
*
|
||||
* @author Avtandil Kikabidze <akalongman@gmail.com>
|
||||
*/
|
||||
class ElasticsearchHandler extends AbstractProcessingHandler
|
||||
{
|
||||
/**
|
||||
* @var Client
|
||||
*/
|
||||
protected $client;
|
||||
|
||||
/**
|
||||
* @var mixed[] Handler config options
|
||||
*/
|
||||
protected $options = [];
|
||||
|
||||
/**
|
||||
* @param Client $client Elasticsearch Client object
|
||||
* @param mixed[] $options Handler configuration
|
||||
*/
|
||||
public function __construct(Client $client, array $options = [], $level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
parent::__construct($level, $bubble);
|
||||
$this->client = $client;
|
||||
$this->options = array_merge(
|
||||
[
|
||||
'index' => 'monolog', // Elastic index name
|
||||
'type' => '_doc', // Elastic document type
|
||||
'ignore_error' => false, // Suppress Elasticsearch exceptions
|
||||
],
|
||||
$options
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
$this->bulkSend([$record['formatted']]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function setFormatter(FormatterInterface $formatter): HandlerInterface
|
||||
{
|
||||
if ($formatter instanceof ElasticsearchFormatter) {
|
||||
return parent::setFormatter($formatter);
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException('ElasticsearchHandler is only compatible with ElasticsearchFormatter');
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter options
|
||||
*
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function getOptions(): array
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getDefaultFormatter(): FormatterInterface
|
||||
{
|
||||
return new ElasticsearchFormatter($this->options['index'], $this->options['type']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handleBatch(array $records): void
|
||||
{
|
||||
$documents = $this->getFormatter()->formatBatch($records);
|
||||
$this->bulkSend($documents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use Elasticsearch bulk API to send list of documents
|
||||
*
|
||||
* @param array[] $records Records + _index/_type keys
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function bulkSend(array $records): void
|
||||
{
|
||||
try {
|
||||
$params = [
|
||||
'body' => [],
|
||||
];
|
||||
|
||||
foreach ($records as $record) {
|
||||
$params['body'][] = [
|
||||
'index' => [
|
||||
'_index' => $record['_index'],
|
||||
'_type' => $record['_type'],
|
||||
],
|
||||
];
|
||||
unset($record['_index'], $record['_type']);
|
||||
|
||||
$params['body'][] = $record;
|
||||
}
|
||||
|
||||
$responses = $this->client->bulk($params);
|
||||
|
||||
if ($responses['errors'] === true) {
|
||||
throw $this->createExceptionFromResponses($responses);
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
if (! $this->options['ignore_error']) {
|
||||
throw new RuntimeException('Error sending messages to Elasticsearch', 0, $e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates elasticsearch exception from responses array
|
||||
*
|
||||
* Only the first error is converted into an exception.
|
||||
*
|
||||
* @param mixed[] $responses returned by $this->client->bulk()
|
||||
*/
|
||||
protected function createExceptionFromResponses(array $responses): ElasticsearchRuntimeException
|
||||
{
|
||||
foreach ($responses['items'] ?? [] as $item) {
|
||||
if (isset($item['index']['error'])) {
|
||||
return $this->createExceptionFromError($item['index']['error']);
|
||||
}
|
||||
}
|
||||
|
||||
return new ElasticsearchRuntimeException('Elasticsearch failed to index one or more records.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates elasticsearch exception from error array
|
||||
*
|
||||
* @param mixed[] $error
|
||||
*/
|
||||
protected function createExceptionFromError(array $error): ElasticsearchRuntimeException
|
||||
{
|
||||
$previous = isset($error['caused_by']) ? $this->createExceptionFromError($error['caused_by']) : null;
|
||||
|
||||
return new ElasticsearchRuntimeException($error['type'] . ': ' . $error['reason'], 0, $previous);
|
||||
}
|
||||
}
|
||||
91
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php
vendored
Normal file
91
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Monolog\Logger;
|
||||
use Monolog\Utils;
|
||||
|
||||
/**
|
||||
* Stores to PHP error_log() handler.
|
||||
*
|
||||
* @author Elan Ruusamäe <glen@delfi.ee>
|
||||
*/
|
||||
class ErrorLogHandler extends AbstractProcessingHandler
|
||||
{
|
||||
public const OPERATING_SYSTEM = 0;
|
||||
public const SAPI = 4;
|
||||
|
||||
/** @var int */
|
||||
protected $messageType;
|
||||
/** @var bool */
|
||||
protected $expandNewlines;
|
||||
|
||||
/**
|
||||
* @param int $messageType Says where the error should go.
|
||||
* @param bool $expandNewlines If set to true, newlines in the message will be expanded to be take multiple log entries
|
||||
*/
|
||||
public function __construct(int $messageType = self::OPERATING_SYSTEM, $level = Logger::DEBUG, bool $bubble = true, bool $expandNewlines = false)
|
||||
{
|
||||
parent::__construct($level, $bubble);
|
||||
|
||||
if (false === in_array($messageType, self::getAvailableTypes(), true)) {
|
||||
$message = sprintf('The given message type "%s" is not supported', print_r($messageType, true));
|
||||
|
||||
throw new \InvalidArgumentException($message);
|
||||
}
|
||||
|
||||
$this->messageType = $messageType;
|
||||
$this->expandNewlines = $expandNewlines;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[] With all available types
|
||||
*/
|
||||
public static function getAvailableTypes(): array
|
||||
{
|
||||
return [
|
||||
self::OPERATING_SYSTEM,
|
||||
self::SAPI,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getDefaultFormatter(): FormatterInterface
|
||||
{
|
||||
return new LineFormatter('[%datetime%] %channel%.%level_name%: %message% %context% %extra%');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
if (!$this->expandNewlines) {
|
||||
error_log((string) $record['formatted'], $this->messageType);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$lines = preg_split('{[\r\n]+}', (string) $record['formatted']);
|
||||
if ($lines === false) {
|
||||
$pcreErrorCode = preg_last_error();
|
||||
throw new \RuntimeException('Failed to preg_split formatted string: ' . $pcreErrorCode . ' / '. Utils::pcreLastErrorMessage($pcreErrorCode));
|
||||
}
|
||||
foreach ($lines as $line) {
|
||||
error_log($line, $this->messageType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?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;
|
||||
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Forwards records to at most one handler
|
||||
*
|
||||
* If a handler fails, the exception is suppressed and the record is forwarded to the next handler.
|
||||
*
|
||||
* As soon as one handler handles a record successfully, the handling stops there.
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
*/
|
||||
class FallbackGroupHandler extends GroupHandler
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handle(array $record): bool
|
||||
{
|
||||
if ($this->processors) {
|
||||
/** @var Record $record */
|
||||
$record = $this->processRecord($record);
|
||||
}
|
||||
foreach ($this->handlers as $handler) {
|
||||
try {
|
||||
$handler->handle($record);
|
||||
break;
|
||||
} catch (Throwable $e) {
|
||||
// What throwable?
|
||||
}
|
||||
}
|
||||
|
||||
return false === $this->bubble;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handleBatch(array $records): void
|
||||
{
|
||||
if ($this->processors) {
|
||||
$processed = [];
|
||||
foreach ($records as $record) {
|
||||
$processed[] = $this->processRecord($record);
|
||||
}
|
||||
/** @var Record[] $records */
|
||||
$records = $processed;
|
||||
}
|
||||
|
||||
foreach ($this->handlers as $handler) {
|
||||
try {
|
||||
$handler->handleBatch($records);
|
||||
break;
|
||||
} catch (Throwable $e) {
|
||||
// What throwable?
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
212
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php
vendored
Normal file
212
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.php
vendored
Normal file
@@ -0,0 +1,212 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\ResettableInterface;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
* Simple handler wrapper that filters records based on a list of levels
|
||||
*
|
||||
* It can be configured with an exact list of levels to allow, or a min/max level.
|
||||
*
|
||||
* @author Hennadiy Verkh
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
* @phpstan-import-type Level from \Monolog\Logger
|
||||
* @phpstan-import-type LevelName from \Monolog\Logger
|
||||
*/
|
||||
class FilterHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface, FormattableHandlerInterface
|
||||
{
|
||||
use ProcessableHandlerTrait;
|
||||
|
||||
/**
|
||||
* Handler or factory callable($record, $this)
|
||||
*
|
||||
* @var callable|HandlerInterface
|
||||
* @phpstan-var callable(?Record, HandlerInterface): HandlerInterface|HandlerInterface
|
||||
*/
|
||||
protected $handler;
|
||||
|
||||
/**
|
||||
* Minimum level for logs that are passed to handler
|
||||
*
|
||||
* @var int[]
|
||||
* @phpstan-var array<Level, int>
|
||||
*/
|
||||
protected $acceptedLevels;
|
||||
|
||||
/**
|
||||
* Whether the messages that are handled can bubble up the stack or not
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $bubble;
|
||||
|
||||
/**
|
||||
* @psalm-param HandlerInterface|callable(?Record, HandlerInterface): HandlerInterface $handler
|
||||
*
|
||||
* @param callable|HandlerInterface $handler Handler or factory callable($record|null, $filterHandler).
|
||||
* @param int|array $minLevelOrList A list of levels to accept or a minimum level if maxLevel is provided
|
||||
* @param int|string $maxLevel Maximum level to accept, only used if $minLevelOrList is not an array
|
||||
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
|
||||
*
|
||||
* @phpstan-param Level|LevelName|LogLevel::*|array<Level|LevelName|LogLevel::*> $minLevelOrList
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $maxLevel
|
||||
*/
|
||||
public function __construct($handler, $minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY, bool $bubble = true)
|
||||
{
|
||||
$this->handler = $handler;
|
||||
$this->bubble = $bubble;
|
||||
$this->setAcceptedLevels($minLevelOrList, $maxLevel);
|
||||
|
||||
if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) {
|
||||
throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-return array<int, Level>
|
||||
*/
|
||||
public function getAcceptedLevels(): array
|
||||
{
|
||||
return array_flip($this->acceptedLevels);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|string|array $minLevelOrList A list of levels to accept or a minimum level or level name if maxLevel is provided
|
||||
* @param int|string $maxLevel Maximum level or level name to accept, only used if $minLevelOrList is not an array
|
||||
*
|
||||
* @phpstan-param Level|LevelName|LogLevel::*|array<Level|LevelName|LogLevel::*> $minLevelOrList
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $maxLevel
|
||||
*/
|
||||
public function setAcceptedLevels($minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY): self
|
||||
{
|
||||
if (is_array($minLevelOrList)) {
|
||||
$acceptedLevels = array_map('Monolog\Logger::toMonologLevel', $minLevelOrList);
|
||||
} else {
|
||||
$minLevelOrList = Logger::toMonologLevel($minLevelOrList);
|
||||
$maxLevel = Logger::toMonologLevel($maxLevel);
|
||||
$acceptedLevels = array_values(array_filter(Logger::getLevels(), function ($level) use ($minLevelOrList, $maxLevel) {
|
||||
return $level >= $minLevelOrList && $level <= $maxLevel;
|
||||
}));
|
||||
}
|
||||
$this->acceptedLevels = array_flip($acceptedLevels);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function isHandling(array $record): bool
|
||||
{
|
||||
return isset($this->acceptedLevels[$record['level']]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handle(array $record): bool
|
||||
{
|
||||
if (!$this->isHandling($record)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->processors) {
|
||||
/** @var Record $record */
|
||||
$record = $this->processRecord($record);
|
||||
}
|
||||
|
||||
$this->getHandler($record)->handle($record);
|
||||
|
||||
return false === $this->bubble;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handleBatch(array $records): void
|
||||
{
|
||||
$filtered = [];
|
||||
foreach ($records as $record) {
|
||||
if ($this->isHandling($record)) {
|
||||
$filtered[] = $record;
|
||||
}
|
||||
}
|
||||
|
||||
if (count($filtered) > 0) {
|
||||
$this->getHandler($filtered[count($filtered) - 1])->handleBatch($filtered);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the nested handler
|
||||
*
|
||||
* If the handler was provided as a factory callable, this will trigger the handler's instantiation.
|
||||
*
|
||||
* @return HandlerInterface
|
||||
*
|
||||
* @phpstan-param Record $record
|
||||
*/
|
||||
public function getHandler(array $record = null)
|
||||
{
|
||||
if (!$this->handler instanceof HandlerInterface) {
|
||||
$this->handler = ($this->handler)($record, $this);
|
||||
if (!$this->handler instanceof HandlerInterface) {
|
||||
throw new \RuntimeException("The factory callable should return a HandlerInterface");
|
||||
}
|
||||
}
|
||||
|
||||
return $this->handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function setFormatter(FormatterInterface $formatter): HandlerInterface
|
||||
{
|
||||
$handler = $this->getHandler();
|
||||
if ($handler instanceof FormattableHandlerInterface) {
|
||||
$handler->setFormatter($formatter);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
throw new \UnexpectedValueException('The nested handler of type '.get_class($handler).' does not support formatters.');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getFormatter(): FormatterInterface
|
||||
{
|
||||
$handler = $this->getHandler();
|
||||
if ($handler instanceof FormattableHandlerInterface) {
|
||||
return $handler->getFormatter();
|
||||
}
|
||||
|
||||
throw new \UnexpectedValueException('The nested handler of type '.get_class($handler).' does not support formatters.');
|
||||
}
|
||||
|
||||
public function reset()
|
||||
{
|
||||
$this->resetProcessors();
|
||||
|
||||
if ($this->getHandler() instanceof ResettableInterface) {
|
||||
$this->getHandler()->reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?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\FingersCrossed;
|
||||
|
||||
/**
|
||||
* Interface for activation strategies for the FingersCrossedHandler.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
*/
|
||||
interface ActivationStrategyInterface
|
||||
{
|
||||
/**
|
||||
* Returns whether the given record activates the handler.
|
||||
*
|
||||
* @phpstan-param Record $record
|
||||
*/
|
||||
public function isHandlerActivated(array $record): bool;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?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\FingersCrossed;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
* Channel and Error level based monolog activation strategy. Allows to trigger activation
|
||||
* based on level per channel. e.g. trigger activation on level 'ERROR' by default, except
|
||||
* for records of the 'sql' channel; those should trigger activation on level 'WARN'.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* <code>
|
||||
* $activationStrategy = new ChannelLevelActivationStrategy(
|
||||
* Logger::CRITICAL,
|
||||
* array(
|
||||
* 'request' => Logger::ALERT,
|
||||
* 'sensitive' => Logger::ERROR,
|
||||
* )
|
||||
* );
|
||||
* $handler = new FingersCrossedHandler(new StreamHandler('php://stderr'), $activationStrategy);
|
||||
* </code>
|
||||
*
|
||||
* @author Mike Meessen <netmikey@gmail.com>
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
* @phpstan-import-type Level from \Monolog\Logger
|
||||
* @phpstan-import-type LevelName from \Monolog\Logger
|
||||
*/
|
||||
class ChannelLevelActivationStrategy implements ActivationStrategyInterface
|
||||
{
|
||||
/**
|
||||
* @var Level
|
||||
*/
|
||||
private $defaultActionLevel;
|
||||
|
||||
/**
|
||||
* @var array<string, Level>
|
||||
*/
|
||||
private $channelToActionLevel;
|
||||
|
||||
/**
|
||||
* @param int|string $defaultActionLevel The default action level to be used if the record's category doesn't match any
|
||||
* @param array<string, int> $channelToActionLevel An array that maps channel names to action levels.
|
||||
*
|
||||
* @phpstan-param array<string, Level> $channelToActionLevel
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $defaultActionLevel
|
||||
*/
|
||||
public function __construct($defaultActionLevel, array $channelToActionLevel = [])
|
||||
{
|
||||
$this->defaultActionLevel = Logger::toMonologLevel($defaultActionLevel);
|
||||
$this->channelToActionLevel = array_map('Monolog\Logger::toMonologLevel', $channelToActionLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param Record $record
|
||||
*/
|
||||
public function isHandlerActivated(array $record): bool
|
||||
{
|
||||
if (isset($this->channelToActionLevel[$record['channel']])) {
|
||||
return $record['level'] >= $this->channelToActionLevel[$record['channel']];
|
||||
}
|
||||
|
||||
return $record['level'] >= $this->defaultActionLevel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?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\FingersCrossed;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
* Error level based activation strategy.
|
||||
*
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
*
|
||||
* @phpstan-import-type Level from \Monolog\Logger
|
||||
* @phpstan-import-type LevelName from \Monolog\Logger
|
||||
*/
|
||||
class ErrorLevelActivationStrategy implements ActivationStrategyInterface
|
||||
{
|
||||
/**
|
||||
* @var Level
|
||||
*/
|
||||
private $actionLevel;
|
||||
|
||||
/**
|
||||
* @param int|string $actionLevel Level or name or value
|
||||
*
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $actionLevel
|
||||
*/
|
||||
public function __construct($actionLevel)
|
||||
{
|
||||
$this->actionLevel = Logger::toMonologLevel($actionLevel);
|
||||
}
|
||||
|
||||
public function isHandlerActivated(array $record): bool
|
||||
{
|
||||
return $record['level'] >= $this->actionLevel;
|
||||
}
|
||||
}
|
||||
252
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php
vendored
Normal file
252
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php
vendored
Normal file
@@ -0,0 +1,252 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
|
||||
use Monolog\Handler\FingersCrossed\ActivationStrategyInterface;
|
||||
use Monolog\Logger;
|
||||
use Monolog\ResettableInterface;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
* Buffers all records until a certain level is reached
|
||||
*
|
||||
* The advantage of this approach is that you don't get any clutter in your log files.
|
||||
* Only requests which actually trigger an error (or whatever your actionLevel is) will be
|
||||
* in the logs, but they will contain all records, not only those above the level threshold.
|
||||
*
|
||||
* You can then have a passthruLevel as well which means that at the end of the request,
|
||||
* even if it did not get activated, it will still send through log records of e.g. at least a
|
||||
* warning level.
|
||||
*
|
||||
* You can find the various activation strategies in the
|
||||
* Monolog\Handler\FingersCrossed\ namespace.
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
* @phpstan-import-type Level from \Monolog\Logger
|
||||
* @phpstan-import-type LevelName from \Monolog\Logger
|
||||
*/
|
||||
class FingersCrossedHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface, FormattableHandlerInterface
|
||||
{
|
||||
use ProcessableHandlerTrait;
|
||||
|
||||
/**
|
||||
* @var callable|HandlerInterface
|
||||
* @phpstan-var callable(?Record, HandlerInterface): HandlerInterface|HandlerInterface
|
||||
*/
|
||||
protected $handler;
|
||||
/** @var ActivationStrategyInterface */
|
||||
protected $activationStrategy;
|
||||
/** @var bool */
|
||||
protected $buffering = true;
|
||||
/** @var int */
|
||||
protected $bufferSize;
|
||||
/** @var Record[] */
|
||||
protected $buffer = [];
|
||||
/** @var bool */
|
||||
protected $stopBuffering;
|
||||
/**
|
||||
* @var ?int
|
||||
* @phpstan-var ?Level
|
||||
*/
|
||||
protected $passthruLevel;
|
||||
/** @var bool */
|
||||
protected $bubble;
|
||||
|
||||
/**
|
||||
* @psalm-param HandlerInterface|callable(?Record, HandlerInterface): HandlerInterface $handler
|
||||
*
|
||||
* @param callable|HandlerInterface $handler Handler or factory callable($record|null, $fingersCrossedHandler).
|
||||
* @param int|string|ActivationStrategyInterface $activationStrategy Strategy which determines when this handler takes action, or a level name/value at which the handler is activated
|
||||
* @param int $bufferSize How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
|
||||
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
|
||||
* @param bool $stopBuffering Whether the handler should stop buffering after being triggered (default true)
|
||||
* @param int|string $passthruLevel Minimum level to always flush to handler on close, even if strategy not triggered
|
||||
*
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $passthruLevel
|
||||
* @phpstan-param Level|LevelName|LogLevel::*|ActivationStrategyInterface $activationStrategy
|
||||
*/
|
||||
public function __construct($handler, $activationStrategy = null, int $bufferSize = 0, bool $bubble = true, bool $stopBuffering = true, $passthruLevel = null)
|
||||
{
|
||||
if (null === $activationStrategy) {
|
||||
$activationStrategy = new ErrorLevelActivationStrategy(Logger::WARNING);
|
||||
}
|
||||
|
||||
// convert simple int activationStrategy to an object
|
||||
if (!$activationStrategy instanceof ActivationStrategyInterface) {
|
||||
$activationStrategy = new ErrorLevelActivationStrategy($activationStrategy);
|
||||
}
|
||||
|
||||
$this->handler = $handler;
|
||||
$this->activationStrategy = $activationStrategy;
|
||||
$this->bufferSize = $bufferSize;
|
||||
$this->bubble = $bubble;
|
||||
$this->stopBuffering = $stopBuffering;
|
||||
|
||||
if ($passthruLevel !== null) {
|
||||
$this->passthruLevel = Logger::toMonologLevel($passthruLevel);
|
||||
}
|
||||
|
||||
if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) {
|
||||
throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function isHandling(array $record): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually activate this logger regardless of the activation strategy
|
||||
*/
|
||||
public function activate(): void
|
||||
{
|
||||
if ($this->stopBuffering) {
|
||||
$this->buffering = false;
|
||||
}
|
||||
|
||||
$this->getHandler(end($this->buffer) ?: null)->handleBatch($this->buffer);
|
||||
$this->buffer = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handle(array $record): bool
|
||||
{
|
||||
if ($this->processors) {
|
||||
/** @var Record $record */
|
||||
$record = $this->processRecord($record);
|
||||
}
|
||||
|
||||
if ($this->buffering) {
|
||||
$this->buffer[] = $record;
|
||||
if ($this->bufferSize > 0 && count($this->buffer) > $this->bufferSize) {
|
||||
array_shift($this->buffer);
|
||||
}
|
||||
if ($this->activationStrategy->isHandlerActivated($record)) {
|
||||
$this->activate();
|
||||
}
|
||||
} else {
|
||||
$this->getHandler($record)->handle($record);
|
||||
}
|
||||
|
||||
return false === $this->bubble;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function close(): void
|
||||
{
|
||||
$this->flushBuffer();
|
||||
|
||||
$this->getHandler()->close();
|
||||
}
|
||||
|
||||
public function reset()
|
||||
{
|
||||
$this->flushBuffer();
|
||||
|
||||
$this->resetProcessors();
|
||||
|
||||
if ($this->getHandler() instanceof ResettableInterface) {
|
||||
$this->getHandler()->reset();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the buffer without flushing any messages down to the wrapped handler.
|
||||
*
|
||||
* It also resets the handler to its initial buffering state.
|
||||
*/
|
||||
public function clear(): void
|
||||
{
|
||||
$this->buffer = [];
|
||||
$this->reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the state of the handler. Stops forwarding records to the wrapped handler.
|
||||
*/
|
||||
private function flushBuffer(): void
|
||||
{
|
||||
if (null !== $this->passthruLevel) {
|
||||
$level = $this->passthruLevel;
|
||||
$this->buffer = array_filter($this->buffer, function ($record) use ($level) {
|
||||
return $record['level'] >= $level;
|
||||
});
|
||||
if (count($this->buffer) > 0) {
|
||||
$this->getHandler(end($this->buffer))->handleBatch($this->buffer);
|
||||
}
|
||||
}
|
||||
|
||||
$this->buffer = [];
|
||||
$this->buffering = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the nested handler
|
||||
*
|
||||
* If the handler was provided as a factory callable, this will trigger the handler's instantiation.
|
||||
*
|
||||
* @return HandlerInterface
|
||||
*
|
||||
* @phpstan-param Record $record
|
||||
*/
|
||||
public function getHandler(array $record = null)
|
||||
{
|
||||
if (!$this->handler instanceof HandlerInterface) {
|
||||
$this->handler = ($this->handler)($record, $this);
|
||||
if (!$this->handler instanceof HandlerInterface) {
|
||||
throw new \RuntimeException("The factory callable should return a HandlerInterface");
|
||||
}
|
||||
}
|
||||
|
||||
return $this->handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function setFormatter(FormatterInterface $formatter): HandlerInterface
|
||||
{
|
||||
$handler = $this->getHandler();
|
||||
if ($handler instanceof FormattableHandlerInterface) {
|
||||
$handler->setFormatter($formatter);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
throw new \UnexpectedValueException('The nested handler of type '.get_class($handler).' does not support formatters.');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getFormatter(): FormatterInterface
|
||||
{
|
||||
$handler = $this->getHandler();
|
||||
if ($handler instanceof FormattableHandlerInterface) {
|
||||
return $handler->getFormatter();
|
||||
}
|
||||
|
||||
throw new \UnexpectedValueException('The nested handler of type '.get_class($handler).' does not support formatters.');
|
||||
}
|
||||
}
|
||||
180
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php
vendored
Normal file
180
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Formatter\WildfireFormatter;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
|
||||
/**
|
||||
* Simple FirePHP Handler (http://www.firephp.org/), which uses the Wildfire protocol.
|
||||
*
|
||||
* @author Eric Clemmons (@ericclemmons) <eric@uxdriven.com>
|
||||
*
|
||||
* @phpstan-import-type FormattedRecord from AbstractProcessingHandler
|
||||
*/
|
||||
class FirePHPHandler extends AbstractProcessingHandler
|
||||
{
|
||||
use WebRequestRecognizerTrait;
|
||||
|
||||
/**
|
||||
* WildFire JSON header message format
|
||||
*/
|
||||
protected const PROTOCOL_URI = 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2';
|
||||
|
||||
/**
|
||||
* FirePHP structure for parsing messages & their presentation
|
||||
*/
|
||||
protected const STRUCTURE_URI = 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1';
|
||||
|
||||
/**
|
||||
* Must reference a "known" plugin, otherwise headers won't display in FirePHP
|
||||
*/
|
||||
protected const PLUGIN_URI = 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3';
|
||||
|
||||
/**
|
||||
* Header prefix for Wildfire to recognize & parse headers
|
||||
*/
|
||||
protected const HEADER_PREFIX = 'X-Wf';
|
||||
|
||||
/**
|
||||
* Whether or not Wildfire vendor-specific headers have been generated & sent yet
|
||||
* @var bool
|
||||
*/
|
||||
protected static $initialized = false;
|
||||
|
||||
/**
|
||||
* Shared static message index between potentially multiple handlers
|
||||
* @var int
|
||||
*/
|
||||
protected static $messageIndex = 1;
|
||||
|
||||
/** @var bool */
|
||||
protected static $sendHeaders = true;
|
||||
|
||||
/**
|
||||
* Base header creation function used by init headers & record headers
|
||||
*
|
||||
* @param array<int|string> $meta Wildfire Plugin, Protocol & Structure Indexes
|
||||
* @param string $message Log message
|
||||
*
|
||||
* @return array<string, string> Complete header string ready for the client as key and message as value
|
||||
*
|
||||
* @phpstan-return non-empty-array<string, string>
|
||||
*/
|
||||
protected function createHeader(array $meta, string $message): array
|
||||
{
|
||||
$header = sprintf('%s-%s', static::HEADER_PREFIX, join('-', $meta));
|
||||
|
||||
return [$header => $message];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates message header from record
|
||||
*
|
||||
* @return array<string, string>
|
||||
*
|
||||
* @phpstan-return non-empty-array<string, string>
|
||||
*
|
||||
* @see createHeader()
|
||||
*
|
||||
* @phpstan-param FormattedRecord $record
|
||||
*/
|
||||
protected function createRecordHeader(array $record): array
|
||||
{
|
||||
// Wildfire is extensible to support multiple protocols & plugins in a single request,
|
||||
// but we're not taking advantage of that (yet), so we're using "1" for simplicity's sake.
|
||||
return $this->createHeader(
|
||||
[1, 1, 1, self::$messageIndex++],
|
||||
$record['formatted']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getDefaultFormatter(): FormatterInterface
|
||||
{
|
||||
return new WildfireFormatter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wildfire initialization headers to enable message parsing
|
||||
*
|
||||
* @see createHeader()
|
||||
* @see sendHeader()
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
protected function getInitHeaders(): array
|
||||
{
|
||||
// Initial payload consists of required headers for Wildfire
|
||||
return array_merge(
|
||||
$this->createHeader(['Protocol', 1], static::PROTOCOL_URI),
|
||||
$this->createHeader([1, 'Structure', 1], static::STRUCTURE_URI),
|
||||
$this->createHeader([1, 'Plugin', 1], static::PLUGIN_URI)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send header string to the client
|
||||
*/
|
||||
protected function sendHeader(string $header, string $content): void
|
||||
{
|
||||
if (!headers_sent() && self::$sendHeaders) {
|
||||
header(sprintf('%s: %s', $header, $content));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates & sends header for a record, ensuring init headers have been sent prior
|
||||
*
|
||||
* @see sendHeader()
|
||||
* @see sendInitHeaders()
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
if (!self::$sendHeaders || !$this->isWebRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// WildFire-specific headers must be sent prior to any messages
|
||||
if (!self::$initialized) {
|
||||
self::$initialized = true;
|
||||
|
||||
self::$sendHeaders = $this->headersAccepted();
|
||||
if (!self::$sendHeaders) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($this->getInitHeaders() as $header => $content) {
|
||||
$this->sendHeader($header, $content);
|
||||
}
|
||||
}
|
||||
|
||||
$header = $this->createRecordHeader($record);
|
||||
if (trim(current($header)) !== '') {
|
||||
$this->sendHeader(key($header), current($header));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies if the headers are accepted by the current user agent
|
||||
*/
|
||||
protected function headersAccepted(): bool
|
||||
{
|
||||
if (!empty($_SERVER['HTTP_USER_AGENT']) && preg_match('{\bFirePHP/\d+\.\d+\b}', $_SERVER['HTTP_USER_AGENT'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return isset($_SERVER['HTTP_X_FIREPHP_VERSION']);
|
||||
}
|
||||
}
|
||||
118
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php
vendored
Normal file
118
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* Sends logs to Fleep.io using Webhook integrations
|
||||
*
|
||||
* You'll need a Fleep.io account to use this handler.
|
||||
*
|
||||
* @see https://fleep.io/integrations/webhooks/ Fleep Webhooks Documentation
|
||||
* @author Ando Roots <ando@sqroot.eu>
|
||||
*
|
||||
* @phpstan-import-type FormattedRecord from AbstractProcessingHandler
|
||||
*/
|
||||
class FleepHookHandler extends SocketHandler
|
||||
{
|
||||
protected const FLEEP_HOST = 'fleep.io';
|
||||
|
||||
protected const FLEEP_HOOK_URI = '/hook/';
|
||||
|
||||
/**
|
||||
* @var string Webhook token (specifies the conversation where logs are sent)
|
||||
*/
|
||||
protected $token;
|
||||
|
||||
/**
|
||||
* Construct a new Fleep.io Handler.
|
||||
*
|
||||
* For instructions on how to create a new web hook in your conversations
|
||||
* see https://fleep.io/integrations/webhooks/
|
||||
*
|
||||
* @param string $token Webhook token
|
||||
* @throws MissingExtensionException
|
||||
*/
|
||||
public function __construct(string $token, $level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
if (!extension_loaded('openssl')) {
|
||||
throw new MissingExtensionException('The OpenSSL PHP extension is required to use the FleepHookHandler');
|
||||
}
|
||||
|
||||
$this->token = $token;
|
||||
|
||||
$connectionString = 'ssl://' . static::FLEEP_HOST . ':443';
|
||||
parent::__construct($connectionString, $level, $bubble);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default formatter to use with this handler
|
||||
*
|
||||
* Overloaded to remove empty context and extra arrays from the end of the log message.
|
||||
*
|
||||
* @return LineFormatter
|
||||
*/
|
||||
protected function getDefaultFormatter(): FormatterInterface
|
||||
{
|
||||
return new LineFormatter(null, null, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a log record
|
||||
*/
|
||||
public function write(array $record): void
|
||||
{
|
||||
parent::write($record);
|
||||
$this->closeSocket();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function generateDataStream(array $record): string
|
||||
{
|
||||
$content = $this->buildContent($record);
|
||||
|
||||
return $this->buildHeader($content) . $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the header of the API Call
|
||||
*/
|
||||
private function buildHeader(string $content): string
|
||||
{
|
||||
$header = "POST " . static::FLEEP_HOOK_URI . $this->token . " HTTP/1.1\r\n";
|
||||
$header .= "Host: " . static::FLEEP_HOST . "\r\n";
|
||||
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
|
||||
$header .= "Content-Length: " . strlen($content) . "\r\n";
|
||||
$header .= "\r\n";
|
||||
|
||||
return $header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the body of API call
|
||||
*
|
||||
* @phpstan-param FormattedRecord $record
|
||||
*/
|
||||
private function buildContent(array $record): string
|
||||
{
|
||||
$dataArray = [
|
||||
'message' => $record['formatted'],
|
||||
];
|
||||
|
||||
return http_build_query($dataArray);
|
||||
}
|
||||
}
|
||||
115
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php
vendored
Normal file
115
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\Utils;
|
||||
use Monolog\Formatter\FlowdockFormatter;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
|
||||
/**
|
||||
* Sends notifications through the Flowdock push API
|
||||
*
|
||||
* This must be configured with a FlowdockFormatter instance via setFormatter()
|
||||
*
|
||||
* Notes:
|
||||
* API token - Flowdock API token
|
||||
*
|
||||
* @author Dominik Liebler <liebler.dominik@gmail.com>
|
||||
* @see https://www.flowdock.com/api/push
|
||||
*
|
||||
* @phpstan-import-type FormattedRecord from AbstractProcessingHandler
|
||||
*/
|
||||
class FlowdockHandler extends SocketHandler
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $apiToken;
|
||||
|
||||
/**
|
||||
* @throws MissingExtensionException if OpenSSL is missing
|
||||
*/
|
||||
public function __construct(string $apiToken, $level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
if (!extension_loaded('openssl')) {
|
||||
throw new MissingExtensionException('The OpenSSL PHP extension is required to use the FlowdockHandler');
|
||||
}
|
||||
|
||||
parent::__construct('ssl://api.flowdock.com:443', $level, $bubble);
|
||||
$this->apiToken = $apiToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function setFormatter(FormatterInterface $formatter): HandlerInterface
|
||||
{
|
||||
if (!$formatter instanceof FlowdockFormatter) {
|
||||
throw new \InvalidArgumentException('The FlowdockHandler requires an instance of Monolog\Formatter\FlowdockFormatter to function correctly');
|
||||
}
|
||||
|
||||
return parent::setFormatter($formatter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default formatter.
|
||||
*/
|
||||
protected function getDefaultFormatter(): FormatterInterface
|
||||
{
|
||||
throw new \InvalidArgumentException('The FlowdockHandler must be configured (via setFormatter) with an instance of Monolog\Formatter\FlowdockFormatter to function correctly');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
parent::write($record);
|
||||
|
||||
$this->closeSocket();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function generateDataStream(array $record): string
|
||||
{
|
||||
$content = $this->buildContent($record);
|
||||
|
||||
return $this->buildHeader($content) . $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the body of API call
|
||||
*
|
||||
* @phpstan-param FormattedRecord $record
|
||||
*/
|
||||
private function buildContent(array $record): string
|
||||
{
|
||||
return Utils::jsonEncode($record['formatted']['flowdock']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the header of the API Call
|
||||
*/
|
||||
private function buildHeader(string $content): string
|
||||
{
|
||||
$header = "POST /v1/messages/team_inbox/" . $this->apiToken . " HTTP/1.1\r\n";
|
||||
$header .= "Host: api.flowdock.com\r\n";
|
||||
$header .= "Content-Type: application/json\r\n";
|
||||
$header .= "Content-Length: " . strlen($content) . "\r\n";
|
||||
$header .= "\r\n";
|
||||
|
||||
return $header;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
|
||||
/**
|
||||
* Interface to describe loggers that have a formatter
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
interface FormattableHandlerInterface
|
||||
{
|
||||
/**
|
||||
* Sets the formatter.
|
||||
*
|
||||
* @param FormatterInterface $formatter
|
||||
* @return HandlerInterface self
|
||||
*/
|
||||
public function setFormatter(FormatterInterface $formatter): HandlerInterface;
|
||||
|
||||
/**
|
||||
* Gets the formatter.
|
||||
*
|
||||
* @return FormatterInterface
|
||||
*/
|
||||
public function getFormatter(): FormatterInterface;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
|
||||
/**
|
||||
* Helper trait for implementing FormattableInterface
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
trait FormattableHandlerTrait
|
||||
{
|
||||
/**
|
||||
* @var ?FormatterInterface
|
||||
*/
|
||||
protected $formatter;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function setFormatter(FormatterInterface $formatter): HandlerInterface
|
||||
{
|
||||
$this->formatter = $formatter;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getFormatter(): FormatterInterface
|
||||
{
|
||||
if (!$this->formatter) {
|
||||
$this->formatter = $this->getDefaultFormatter();
|
||||
}
|
||||
|
||||
return $this->formatter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default formatter.
|
||||
*
|
||||
* Overwrite this if the LineFormatter is not a good default for your handler.
|
||||
*/
|
||||
protected function getDefaultFormatter(): FormatterInterface
|
||||
{
|
||||
return new LineFormatter();
|
||||
}
|
||||
}
|
||||
57
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php
vendored
Normal file
57
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
<?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;
|
||||
|
||||
use Gelf\PublisherInterface;
|
||||
use Monolog\Logger;
|
||||
use Monolog\Formatter\GelfMessageFormatter;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
|
||||
/**
|
||||
* Handler to send messages to a Graylog2 (http://www.graylog2.org) server
|
||||
*
|
||||
* @author Matt Lehner <mlehner@gmail.com>
|
||||
* @author Benjamin Zikarsky <benjamin@zikarsky.de>
|
||||
*/
|
||||
class GelfHandler extends AbstractProcessingHandler
|
||||
{
|
||||
/**
|
||||
* @var PublisherInterface the publisher object that sends the message to the server
|
||||
*/
|
||||
protected $publisher;
|
||||
|
||||
/**
|
||||
* @param PublisherInterface $publisher a gelf publisher object
|
||||
*/
|
||||
public function __construct(PublisherInterface $publisher, $level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
parent::__construct($level, $bubble);
|
||||
|
||||
$this->publisher = $publisher;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
$this->publisher->publish($record['formatted']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getDefaultFormatter(): FormatterInterface
|
||||
{
|
||||
return new GelfMessageFormatter();
|
||||
}
|
||||
}
|
||||
132
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php
vendored
Normal file
132
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Monolog\ResettableInterface;
|
||||
|
||||
/**
|
||||
* Forwards records to multiple handlers
|
||||
*
|
||||
* @author Lenar Lõhmus <lenar@city.ee>
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
*/
|
||||
class GroupHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface
|
||||
{
|
||||
use ProcessableHandlerTrait;
|
||||
|
||||
/** @var HandlerInterface[] */
|
||||
protected $handlers;
|
||||
/** @var bool */
|
||||
protected $bubble;
|
||||
|
||||
/**
|
||||
* @param HandlerInterface[] $handlers Array of Handlers.
|
||||
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
|
||||
*/
|
||||
public function __construct(array $handlers, bool $bubble = true)
|
||||
{
|
||||
foreach ($handlers as $handler) {
|
||||
if (!$handler instanceof HandlerInterface) {
|
||||
throw new \InvalidArgumentException('The first argument of the GroupHandler must be an array of HandlerInterface instances.');
|
||||
}
|
||||
}
|
||||
|
||||
$this->handlers = $handlers;
|
||||
$this->bubble = $bubble;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function isHandling(array $record): bool
|
||||
{
|
||||
foreach ($this->handlers as $handler) {
|
||||
if ($handler->isHandling($record)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handle(array $record): bool
|
||||
{
|
||||
if ($this->processors) {
|
||||
/** @var Record $record */
|
||||
$record = $this->processRecord($record);
|
||||
}
|
||||
|
||||
foreach ($this->handlers as $handler) {
|
||||
$handler->handle($record);
|
||||
}
|
||||
|
||||
return false === $this->bubble;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handleBatch(array $records): void
|
||||
{
|
||||
if ($this->processors) {
|
||||
$processed = [];
|
||||
foreach ($records as $record) {
|
||||
$processed[] = $this->processRecord($record);
|
||||
}
|
||||
/** @var Record[] $records */
|
||||
$records = $processed;
|
||||
}
|
||||
|
||||
foreach ($this->handlers as $handler) {
|
||||
$handler->handleBatch($records);
|
||||
}
|
||||
}
|
||||
|
||||
public function reset()
|
||||
{
|
||||
$this->resetProcessors();
|
||||
|
||||
foreach ($this->handlers as $handler) {
|
||||
if ($handler instanceof ResettableInterface) {
|
||||
$handler->reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function close(): void
|
||||
{
|
||||
parent::close();
|
||||
|
||||
foreach ($this->handlers as $handler) {
|
||||
$handler->close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function setFormatter(FormatterInterface $formatter): HandlerInterface
|
||||
{
|
||||
foreach ($this->handlers as $handler) {
|
||||
if ($handler instanceof FormattableHandlerInterface) {
|
||||
$handler->setFormatter($formatter);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
53
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/Handler.php
vendored
Normal file
53
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/Handler.php
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Base Handler class providing basic close() support as well as handleBatch
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
abstract class Handler implements HandlerInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handleBatch(array $records): void
|
||||
{
|
||||
foreach ($records as $record) {
|
||||
$this->handle($record);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function close(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
try {
|
||||
$this->close();
|
||||
} catch (\Throwable $e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
public function __sleep()
|
||||
{
|
||||
$this->close();
|
||||
|
||||
return array_keys(get_object_vars($this));
|
||||
}
|
||||
}
|
||||
85
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php
vendored
Normal file
85
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.php
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Interface that all Monolog Handlers must implement
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
* @phpstan-import-type Level from \Monolog\Logger
|
||||
*/
|
||||
interface HandlerInterface
|
||||
{
|
||||
/**
|
||||
* Checks whether the given record will be handled by this handler.
|
||||
*
|
||||
* This is mostly done for performance reasons, to avoid calling processors for nothing.
|
||||
*
|
||||
* Handlers should still check the record levels within handle(), returning false in isHandling()
|
||||
* is no guarantee that handle() will not be called, and isHandling() might not be called
|
||||
* for a given record.
|
||||
*
|
||||
* @param array $record Partial log record containing only a level key
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @phpstan-param array{level: Level} $record
|
||||
*/
|
||||
public function isHandling(array $record): bool;
|
||||
|
||||
/**
|
||||
* Handles a record.
|
||||
*
|
||||
* All records may be passed to this method, and the handler should discard
|
||||
* those that it does not want to handle.
|
||||
*
|
||||
* The return value of this function controls the bubbling process of the handler stack.
|
||||
* Unless the bubbling is interrupted (by returning true), the Logger class will keep on
|
||||
* calling further handlers in the stack with a given log record.
|
||||
*
|
||||
* @param array $record The record to handle
|
||||
* @return bool true means that this handler handled the record, and that bubbling is not permitted.
|
||||
* false means the record was either not processed or that this handler allows bubbling.
|
||||
*
|
||||
* @phpstan-param Record $record
|
||||
*/
|
||||
public function handle(array $record): bool;
|
||||
|
||||
/**
|
||||
* Handles a set of records at once.
|
||||
*
|
||||
* @param array $records The records to handle (an array of record arrays)
|
||||
*
|
||||
* @phpstan-param Record[] $records
|
||||
*/
|
||||
public function handleBatch(array $records): void;
|
||||
|
||||
/**
|
||||
* Closes the handler.
|
||||
*
|
||||
* Ends a log cycle and frees all resources used by the handler.
|
||||
*
|
||||
* Closing a Handler means flushing all buffers and freeing any open resources/handles.
|
||||
*
|
||||
* Implementations have to be idempotent (i.e. it should be possible to call close several times without breakage)
|
||||
* and ideally handlers should be able to reopen themselves on handle() after they have been closed.
|
||||
*
|
||||
* This is useful at the end of a request and will be called automatically when the object
|
||||
* is destroyed if you extend Monolog\Handler\Handler.
|
||||
*
|
||||
* If you are thinking of calling this method yourself, most likely you should be
|
||||
* calling ResettableInterface::reset instead. Have a look.
|
||||
*/
|
||||
public function close(): void;
|
||||
}
|
||||
136
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php
vendored
Normal file
136
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\ResettableInterface;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
|
||||
/**
|
||||
* This simple wrapper class can be used to extend handlers functionality.
|
||||
*
|
||||
* Example: A custom filtering that can be applied to any handler.
|
||||
*
|
||||
* Inherit from this class and override handle() like this:
|
||||
*
|
||||
* public function handle(array $record)
|
||||
* {
|
||||
* if ($record meets certain conditions) {
|
||||
* return false;
|
||||
* }
|
||||
* return $this->handler->handle($record);
|
||||
* }
|
||||
*
|
||||
* @author Alexey Karapetov <alexey@karapetov.com>
|
||||
*/
|
||||
class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, FormattableHandlerInterface, ResettableInterface
|
||||
{
|
||||
/**
|
||||
* @var HandlerInterface
|
||||
*/
|
||||
protected $handler;
|
||||
|
||||
public function __construct(HandlerInterface $handler)
|
||||
{
|
||||
$this->handler = $handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function isHandling(array $record): bool
|
||||
{
|
||||
return $this->handler->isHandling($record);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handle(array $record): bool
|
||||
{
|
||||
return $this->handler->handle($record);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handleBatch(array $records): void
|
||||
{
|
||||
$this->handler->handleBatch($records);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function close(): void
|
||||
{
|
||||
$this->handler->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function pushProcessor(callable $callback): HandlerInterface
|
||||
{
|
||||
if ($this->handler instanceof ProcessableHandlerInterface) {
|
||||
$this->handler->pushProcessor($callback);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
throw new \LogicException('The wrapped handler does not implement ' . ProcessableHandlerInterface::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function popProcessor(): callable
|
||||
{
|
||||
if ($this->handler instanceof ProcessableHandlerInterface) {
|
||||
return $this->handler->popProcessor();
|
||||
}
|
||||
|
||||
throw new \LogicException('The wrapped handler does not implement ' . ProcessableHandlerInterface::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function setFormatter(FormatterInterface $formatter): HandlerInterface
|
||||
{
|
||||
if ($this->handler instanceof FormattableHandlerInterface) {
|
||||
$this->handler->setFormatter($formatter);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
throw new \LogicException('The wrapped handler does not implement ' . FormattableHandlerInterface::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getFormatter(): FormatterInterface
|
||||
{
|
||||
if ($this->handler instanceof FormattableHandlerInterface) {
|
||||
return $this->handler->getFormatter();
|
||||
}
|
||||
|
||||
throw new \LogicException('The wrapped handler does not implement ' . FormattableHandlerInterface::class);
|
||||
}
|
||||
|
||||
public function reset()
|
||||
{
|
||||
if ($this->handler instanceof ResettableInterface) {
|
||||
$this->handler->reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
74
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php
vendored
Normal file
74
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\Utils;
|
||||
|
||||
/**
|
||||
* IFTTTHandler uses cURL to trigger IFTTT Maker actions
|
||||
*
|
||||
* Register a secret key and trigger/event name at https://ifttt.com/maker
|
||||
*
|
||||
* value1 will be the channel from monolog's Logger constructor,
|
||||
* value2 will be the level name (ERROR, WARNING, ..)
|
||||
* value3 will be the log record's message
|
||||
*
|
||||
* @author Nehal Patel <nehal@nehalpatel.me>
|
||||
*/
|
||||
class IFTTTHandler extends AbstractProcessingHandler
|
||||
{
|
||||
/** @var string */
|
||||
private $eventName;
|
||||
/** @var string */
|
||||
private $secretKey;
|
||||
|
||||
/**
|
||||
* @param string $eventName The name of the IFTTT Maker event that should be triggered
|
||||
* @param string $secretKey A valid IFTTT secret key
|
||||
*/
|
||||
public function __construct(string $eventName, string $secretKey, $level = Logger::ERROR, bool $bubble = true)
|
||||
{
|
||||
if (!extension_loaded('curl')) {
|
||||
throw new MissingExtensionException('The curl extension is needed to use the IFTTTHandler');
|
||||
}
|
||||
|
||||
$this->eventName = $eventName;
|
||||
$this->secretKey = $secretKey;
|
||||
|
||||
parent::__construct($level, $bubble);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function write(array $record): void
|
||||
{
|
||||
$postData = [
|
||||
"value1" => $record["channel"],
|
||||
"value2" => $record["level_name"],
|
||||
"value3" => $record["message"],
|
||||
];
|
||||
$postString = Utils::jsonEncode($postData);
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, "https://maker.ifttt.com/trigger/" . $this->eventName . "/with/key/" . $this->secretKey);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $postString);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
"Content-Type: application/json",
|
||||
]);
|
||||
|
||||
Curl\Util::execute($ch);
|
||||
}
|
||||
}
|
||||
57
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php
vendored
Normal file
57
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* Inspired on LogEntriesHandler.
|
||||
*
|
||||
* @author Robert Kaufmann III <rok3@rok3.me>
|
||||
* @author Gabriel Machado <gabriel.ms1@hotmail.com>
|
||||
*/
|
||||
class InsightOpsHandler extends SocketHandler
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $logToken;
|
||||
|
||||
/**
|
||||
* @param string $token Log token supplied by InsightOps
|
||||
* @param string $region Region where InsightOps account is hosted. Could be 'us' or 'eu'.
|
||||
* @param bool $useSSL Whether or not SSL encryption should be used
|
||||
*
|
||||
* @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
|
||||
*/
|
||||
public function __construct(string $token, string $region = 'us', bool $useSSL = true, $level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
if ($useSSL && !extension_loaded('openssl')) {
|
||||
throw new MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for InsightOpsHandler');
|
||||
}
|
||||
|
||||
$endpoint = $useSSL
|
||||
? 'ssl://' . $region . '.data.logs.insight.rapid7.com:443'
|
||||
: $region . '.data.logs.insight.rapid7.com:80';
|
||||
|
||||
parent::__construct($endpoint, $level, $bubble);
|
||||
$this->logToken = $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function generateDataStream(array $record): string
|
||||
{
|
||||
return $this->logToken . ' ' . $record['formatted'];
|
||||
}
|
||||
}
|
||||
51
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php
vendored
Normal file
51
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* @author Robert Kaufmann III <rok3@rok3.me>
|
||||
*/
|
||||
class LogEntriesHandler extends SocketHandler
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $logToken;
|
||||
|
||||
/**
|
||||
* @param string $token Log token supplied by LogEntries
|
||||
* @param bool $useSSL Whether or not SSL encryption should be used.
|
||||
* @param string $host Custom hostname to send the data to if needed
|
||||
*
|
||||
* @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
|
||||
*/
|
||||
public function __construct(string $token, bool $useSSL = true, $level = Logger::DEBUG, bool $bubble = true, string $host = 'data.logentries.com')
|
||||
{
|
||||
if ($useSSL && !extension_loaded('openssl')) {
|
||||
throw new MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for LogEntriesHandler');
|
||||
}
|
||||
|
||||
$endpoint = $useSSL ? 'ssl://' . $host . ':443' : $host . ':80';
|
||||
parent::__construct($endpoint, $level, $bubble);
|
||||
$this->logToken = $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function generateDataStream(array $record): string
|
||||
{
|
||||
return $this->logToken . ' ' . $record['formatted'];
|
||||
}
|
||||
}
|
||||
160
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php
vendored
Normal file
160
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.php
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Monolog\Formatter\LogglyFormatter;
|
||||
use function array_key_exists;
|
||||
use CurlHandle;
|
||||
|
||||
/**
|
||||
* Sends errors to Loggly.
|
||||
*
|
||||
* @author Przemek Sobstel <przemek@sobstel.org>
|
||||
* @author Adam Pancutt <adam@pancutt.com>
|
||||
* @author Gregory Barchard <gregory@barchard.net>
|
||||
*/
|
||||
class LogglyHandler extends AbstractProcessingHandler
|
||||
{
|
||||
protected const HOST = 'logs-01.loggly.com';
|
||||
protected const ENDPOINT_SINGLE = 'inputs';
|
||||
protected const ENDPOINT_BATCH = 'bulk';
|
||||
|
||||
/**
|
||||
* Caches the curl handlers for every given endpoint.
|
||||
*
|
||||
* @var resource[]|CurlHandle[]
|
||||
*/
|
||||
protected $curlHandlers = [];
|
||||
|
||||
/** @var string */
|
||||
protected $token;
|
||||
|
||||
/** @var string[] */
|
||||
protected $tag = [];
|
||||
|
||||
/**
|
||||
* @param string $token API token supplied by Loggly
|
||||
*
|
||||
* @throws MissingExtensionException If the curl extension is missing
|
||||
*/
|
||||
public function __construct(string $token, $level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
if (!extension_loaded('curl')) {
|
||||
throw new MissingExtensionException('The curl extension is needed to use the LogglyHandler');
|
||||
}
|
||||
|
||||
$this->token = $token;
|
||||
|
||||
parent::__construct($level, $bubble);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads and returns the shared curl handler for the given endpoint.
|
||||
*
|
||||
* @param string $endpoint
|
||||
*
|
||||
* @return resource|CurlHandle
|
||||
*/
|
||||
protected function getCurlHandler(string $endpoint)
|
||||
{
|
||||
if (!array_key_exists($endpoint, $this->curlHandlers)) {
|
||||
$this->curlHandlers[$endpoint] = $this->loadCurlHandle($endpoint);
|
||||
}
|
||||
|
||||
return $this->curlHandlers[$endpoint];
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a fresh curl session for the given endpoint and returns its handler.
|
||||
*
|
||||
* @param string $endpoint
|
||||
*
|
||||
* @return resource|CurlHandle
|
||||
*/
|
||||
private function loadCurlHandle(string $endpoint)
|
||||
{
|
||||
$url = sprintf("https://%s/%s/%s/", static::HOST, $endpoint, $this->token);
|
||||
|
||||
$ch = curl_init();
|
||||
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
return $ch;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[]|string $tag
|
||||
*/
|
||||
public function setTag($tag): self
|
||||
{
|
||||
$tag = !empty($tag) ? $tag : [];
|
||||
$this->tag = is_array($tag) ? $tag : [$tag];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[]|string $tag
|
||||
*/
|
||||
public function addTag($tag): self
|
||||
{
|
||||
if (!empty($tag)) {
|
||||
$tag = is_array($tag) ? $tag : [$tag];
|
||||
$this->tag = array_unique(array_merge($this->tag, $tag));
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function write(array $record): void
|
||||
{
|
||||
$this->send($record["formatted"], static::ENDPOINT_SINGLE);
|
||||
}
|
||||
|
||||
public function handleBatch(array $records): void
|
||||
{
|
||||
$level = $this->level;
|
||||
|
||||
$records = array_filter($records, function ($record) use ($level) {
|
||||
return ($record['level'] >= $level);
|
||||
});
|
||||
|
||||
if ($records) {
|
||||
$this->send($this->getFormatter()->formatBatch($records), static::ENDPOINT_BATCH);
|
||||
}
|
||||
}
|
||||
|
||||
protected function send(string $data, string $endpoint): void
|
||||
{
|
||||
$ch = $this->getCurlHandler($endpoint);
|
||||
|
||||
$headers = ['Content-Type: application/json'];
|
||||
|
||||
if (!empty($this->tag)) {
|
||||
$headers[] = 'X-LOGGLY-TAG: '.implode(',', $this->tag);
|
||||
}
|
||||
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
|
||||
Curl\Util::execute($ch, 5, false);
|
||||
}
|
||||
|
||||
protected function getDefaultFormatter(): FormatterInterface
|
||||
{
|
||||
return new LogglyFormatter();
|
||||
}
|
||||
}
|
||||
86
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/LogmaticHandler.php
vendored
Normal file
86
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/LogmaticHandler.php
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Monolog\Formatter\LogmaticFormatter;
|
||||
|
||||
/**
|
||||
* @author Julien Breux <julien.breux@gmail.com>
|
||||
*/
|
||||
class LogmaticHandler extends SocketHandler
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $logToken;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $hostname;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $appname;
|
||||
|
||||
/**
|
||||
* @param string $token Log token supplied by Logmatic.
|
||||
* @param string $hostname Host name supplied by Logmatic.
|
||||
* @param string $appname Application name supplied by Logmatic.
|
||||
* @param bool $useSSL Whether or not SSL encryption should be used.
|
||||
*
|
||||
* @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
|
||||
*/
|
||||
public function __construct(string $token, string $hostname = '', string $appname = '', bool $useSSL = true, $level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
if ($useSSL && !extension_loaded('openssl')) {
|
||||
throw new MissingExtensionException('The OpenSSL PHP extension is required to use SSL encrypted connection for LogmaticHandler');
|
||||
}
|
||||
|
||||
$endpoint = $useSSL ? 'ssl://api.logmatic.io:10515' : 'api.logmatic.io:10514';
|
||||
$endpoint .= '/v1/';
|
||||
|
||||
parent::__construct($endpoint, $level, $bubble);
|
||||
|
||||
$this->logToken = $token;
|
||||
$this->hostname = $hostname;
|
||||
$this->appname = $appname;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function generateDataStream(array $record): string
|
||||
{
|
||||
return $this->logToken . ' ' . $record['formatted'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getDefaultFormatter(): FormatterInterface
|
||||
{
|
||||
$formatter = new LogmaticFormatter();
|
||||
|
||||
if (!empty($this->hostname)) {
|
||||
$formatter->setHostname($this->hostname);
|
||||
}
|
||||
if (!empty($this->appname)) {
|
||||
$formatter->setAppname($this->appname);
|
||||
}
|
||||
|
||||
return $formatter;
|
||||
}
|
||||
}
|
||||
95
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php
vendored
Normal file
95
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Monolog\Formatter\HtmlFormatter;
|
||||
|
||||
/**
|
||||
* Base class for all mail handlers
|
||||
*
|
||||
* @author Gyula Sallai
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
*/
|
||||
abstract class MailHandler extends AbstractProcessingHandler
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handleBatch(array $records): void
|
||||
{
|
||||
$messages = [];
|
||||
|
||||
foreach ($records as $record) {
|
||||
if ($record['level'] < $this->level) {
|
||||
continue;
|
||||
}
|
||||
/** @var Record $message */
|
||||
$message = $this->processRecord($record);
|
||||
$messages[] = $message;
|
||||
}
|
||||
|
||||
if (!empty($messages)) {
|
||||
$this->send((string) $this->getFormatter()->formatBatch($messages), $messages);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a mail with the given content
|
||||
*
|
||||
* @param string $content formatted email body to be sent
|
||||
* @param array $records the array of log records that formed this content
|
||||
*
|
||||
* @phpstan-param Record[] $records
|
||||
*/
|
||||
abstract protected function send(string $content, array $records): void;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
$this->send((string) $record['formatted'], [$record]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param non-empty-array<Record> $records
|
||||
* @phpstan-return Record
|
||||
*/
|
||||
protected function getHighestRecord(array $records): array
|
||||
{
|
||||
$highestRecord = null;
|
||||
foreach ($records as $record) {
|
||||
if ($highestRecord === null || $highestRecord['level'] < $record['level']) {
|
||||
$highestRecord = $record;
|
||||
}
|
||||
}
|
||||
|
||||
return $highestRecord;
|
||||
}
|
||||
|
||||
protected function isHtmlBody(string $body): bool
|
||||
{
|
||||
return ($body[0] ?? null) === '<';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default formatter.
|
||||
*
|
||||
* @return FormatterInterface
|
||||
*/
|
||||
protected function getDefaultFormatter(): FormatterInterface
|
||||
{
|
||||
return new HtmlFormatter();
|
||||
}
|
||||
}
|
||||
83
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php
vendored
Normal file
83
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.php
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Swift;
|
||||
use Swift_Message;
|
||||
|
||||
/**
|
||||
* MandrillHandler uses cURL to send the emails to the Mandrill API
|
||||
*
|
||||
* @author Adam Nicholson <adamnicholson10@gmail.com>
|
||||
*/
|
||||
class MandrillHandler extends MailHandler
|
||||
{
|
||||
/** @var Swift_Message */
|
||||
protected $message;
|
||||
/** @var string */
|
||||
protected $apiKey;
|
||||
|
||||
/**
|
||||
* @psalm-param Swift_Message|callable(): Swift_Message $message
|
||||
*
|
||||
* @param string $apiKey A valid Mandrill API key
|
||||
* @param callable|Swift_Message $message An example message for real messages, only the body will be replaced
|
||||
*/
|
||||
public function __construct(string $apiKey, $message, $level = Logger::ERROR, bool $bubble = true)
|
||||
{
|
||||
parent::__construct($level, $bubble);
|
||||
|
||||
if (!$message instanceof Swift_Message && is_callable($message)) {
|
||||
$message = $message();
|
||||
}
|
||||
if (!$message instanceof Swift_Message) {
|
||||
throw new \InvalidArgumentException('You must provide either a Swift_Message instance or a callable returning it');
|
||||
}
|
||||
$this->message = $message;
|
||||
$this->apiKey = $apiKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function send(string $content, array $records): void
|
||||
{
|
||||
$mime = 'text/plain';
|
||||
if ($this->isHtmlBody($content)) {
|
||||
$mime = 'text/html';
|
||||
}
|
||||
|
||||
$message = clone $this->message;
|
||||
$message->setBody($content, $mime);
|
||||
/** @phpstan-ignore-next-line */
|
||||
if (version_compare(Swift::VERSION, '6.0.0', '>=')) {
|
||||
$message->setDate(new \DateTimeImmutable());
|
||||
} else {
|
||||
/** @phpstan-ignore-next-line */
|
||||
$message->setDate(time());
|
||||
}
|
||||
|
||||
$ch = curl_init();
|
||||
|
||||
curl_setopt($ch, CURLOPT_URL, 'https://mandrillapp.com/api/1.0/messages/send-raw.json');
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
|
||||
'key' => $this->apiKey,
|
||||
'raw_message' => (string) $message,
|
||||
'async' => false,
|
||||
]));
|
||||
|
||||
Curl\Util::execute($ch);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Exception can be thrown if an extension for a handler is missing
|
||||
*
|
||||
* @author Christian Bergau <cbergau86@gmail.com>
|
||||
*/
|
||||
class MissingExtensionException extends \Exception
|
||||
{
|
||||
}
|
||||
86
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php
vendored
Normal file
86
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
<?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;
|
||||
|
||||
use MongoDB\Driver\BulkWrite;
|
||||
use MongoDB\Driver\Manager;
|
||||
use MongoDB\Client;
|
||||
use Monolog\Logger;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Monolog\Formatter\MongoDBFormatter;
|
||||
|
||||
/**
|
||||
* Logs to a MongoDB database.
|
||||
*
|
||||
* Usage example:
|
||||
*
|
||||
* $log = new \Monolog\Logger('application');
|
||||
* $client = new \MongoDB\Client('mongodb://localhost:27017');
|
||||
* $mongodb = new \Monolog\Handler\MongoDBHandler($client, 'logs', 'prod');
|
||||
* $log->pushHandler($mongodb);
|
||||
*
|
||||
* The above examples uses the MongoDB PHP library's client class; however, the
|
||||
* MongoDB\Driver\Manager class from ext-mongodb is also supported.
|
||||
*/
|
||||
class MongoDBHandler extends AbstractProcessingHandler
|
||||
{
|
||||
/** @var \MongoDB\Collection */
|
||||
private $collection;
|
||||
/** @var Client|Manager */
|
||||
private $manager;
|
||||
/** @var string */
|
||||
private $namespace;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Client|Manager $mongodb MongoDB library or driver client
|
||||
* @param string $database Database name
|
||||
* @param string $collection Collection name
|
||||
*/
|
||||
public function __construct($mongodb, string $database, string $collection, $level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
if (!($mongodb instanceof Client || $mongodb instanceof Manager)) {
|
||||
throw new \InvalidArgumentException('MongoDB\Client or MongoDB\Driver\Manager instance required');
|
||||
}
|
||||
|
||||
if ($mongodb instanceof Client) {
|
||||
$this->collection = $mongodb->selectCollection($database, $collection);
|
||||
} else {
|
||||
$this->manager = $mongodb;
|
||||
$this->namespace = $database . '.' . $collection;
|
||||
}
|
||||
|
||||
parent::__construct($level, $bubble);
|
||||
}
|
||||
|
||||
protected function write(array $record): void
|
||||
{
|
||||
if (isset($this->collection)) {
|
||||
$this->collection->insertOne($record['formatted']);
|
||||
}
|
||||
|
||||
if (isset($this->manager, $this->namespace)) {
|
||||
$bulk = new BulkWrite;
|
||||
$bulk->insert($record["formatted"]);
|
||||
$this->manager->executeBulkWrite($this->namespace, $bulk);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getDefaultFormatter(): FormatterInterface
|
||||
{
|
||||
return new MongoDBFormatter;
|
||||
}
|
||||
}
|
||||
174
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php
vendored
Normal file
174
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
|
||||
/**
|
||||
* NativeMailerHandler uses the mail() function to send the emails
|
||||
*
|
||||
* @author Christophe Coevoet <stof@notk.org>
|
||||
* @author Mark Garrett <mark@moderndeveloperllc.com>
|
||||
*/
|
||||
class NativeMailerHandler extends MailHandler
|
||||
{
|
||||
/**
|
||||
* The email addresses to which the message will be sent
|
||||
* @var string[]
|
||||
*/
|
||||
protected $to;
|
||||
|
||||
/**
|
||||
* The subject of the email
|
||||
* @var string
|
||||
*/
|
||||
protected $subject;
|
||||
|
||||
/**
|
||||
* Optional headers for the message
|
||||
* @var string[]
|
||||
*/
|
||||
protected $headers = [];
|
||||
|
||||
/**
|
||||
* Optional parameters for the message
|
||||
* @var string[]
|
||||
*/
|
||||
protected $parameters = [];
|
||||
|
||||
/**
|
||||
* The wordwrap length for the message
|
||||
* @var int
|
||||
*/
|
||||
protected $maxColumnWidth;
|
||||
|
||||
/**
|
||||
* The Content-type for the message
|
||||
* @var string|null
|
||||
*/
|
||||
protected $contentType;
|
||||
|
||||
/**
|
||||
* The encoding for the message
|
||||
* @var string
|
||||
*/
|
||||
protected $encoding = 'utf-8';
|
||||
|
||||
/**
|
||||
* @param string|string[] $to The receiver of the mail
|
||||
* @param string $subject The subject of the mail
|
||||
* @param string $from The sender of the mail
|
||||
* @param int $maxColumnWidth The maximum column width that the message lines will have
|
||||
*/
|
||||
public function __construct($to, string $subject, string $from, $level = Logger::ERROR, bool $bubble = true, int $maxColumnWidth = 70)
|
||||
{
|
||||
parent::__construct($level, $bubble);
|
||||
$this->to = (array) $to;
|
||||
$this->subject = $subject;
|
||||
$this->addHeader(sprintf('From: %s', $from));
|
||||
$this->maxColumnWidth = $maxColumnWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add headers to the message
|
||||
*
|
||||
* @param string|string[] $headers Custom added headers
|
||||
*/
|
||||
public function addHeader($headers): self
|
||||
{
|
||||
foreach ((array) $headers as $header) {
|
||||
if (strpos($header, "\n") !== false || strpos($header, "\r") !== false) {
|
||||
throw new \InvalidArgumentException('Headers can not contain newline characters for security reasons');
|
||||
}
|
||||
$this->headers[] = $header;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add parameters to the message
|
||||
*
|
||||
* @param string|string[] $parameters Custom added parameters
|
||||
*/
|
||||
public function addParameter($parameters): self
|
||||
{
|
||||
$this->parameters = array_merge($this->parameters, (array) $parameters);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function send(string $content, array $records): void
|
||||
{
|
||||
$contentType = $this->getContentType() ?: ($this->isHtmlBody($content) ? 'text/html' : 'text/plain');
|
||||
|
||||
if ($contentType !== 'text/html') {
|
||||
$content = wordwrap($content, $this->maxColumnWidth);
|
||||
}
|
||||
|
||||
$headers = ltrim(implode("\r\n", $this->headers) . "\r\n", "\r\n");
|
||||
$headers .= 'Content-type: ' . $contentType . '; charset=' . $this->getEncoding() . "\r\n";
|
||||
if ($contentType === 'text/html' && false === strpos($headers, 'MIME-Version:')) {
|
||||
$headers .= 'MIME-Version: 1.0' . "\r\n";
|
||||
}
|
||||
|
||||
$subject = $this->subject;
|
||||
if ($records) {
|
||||
$subjectFormatter = new LineFormatter($this->subject);
|
||||
$subject = $subjectFormatter->format($this->getHighestRecord($records));
|
||||
}
|
||||
|
||||
$parameters = implode(' ', $this->parameters);
|
||||
foreach ($this->to as $to) {
|
||||
mail($to, $subject, $content, $headers, $parameters);
|
||||
}
|
||||
}
|
||||
|
||||
public function getContentType(): ?string
|
||||
{
|
||||
return $this->contentType;
|
||||
}
|
||||
|
||||
public function getEncoding(): string
|
||||
{
|
||||
return $this->encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $contentType The content type of the email - Defaults to text/plain. Use text/html for HTML messages.
|
||||
*/
|
||||
public function setContentType(string $contentType): self
|
||||
{
|
||||
if (strpos($contentType, "\n") !== false || strpos($contentType, "\r") !== false) {
|
||||
throw new \InvalidArgumentException('The content type can not contain newline characters to prevent email header injection');
|
||||
}
|
||||
|
||||
$this->contentType = $contentType;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setEncoding(string $encoding): self
|
||||
{
|
||||
if (strpos($encoding, "\n") !== false || strpos($encoding, "\r") !== false) {
|
||||
throw new \InvalidArgumentException('The encoding can not contain newline characters to prevent email header injection');
|
||||
}
|
||||
|
||||
$this->encoding = $encoding;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
199
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php
vendored
Normal file
199
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php
vendored
Normal file
@@ -0,0 +1,199 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
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.
|
||||
*
|
||||
* This handler requires a NormalizerFormatter to function and expects an array in $record['formatted']
|
||||
*
|
||||
* @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
|
||||
{
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public function __construct(
|
||||
$level = Logger::ERROR,
|
||||
bool $bubble = true,
|
||||
?string $appName = null,
|
||||
bool $explodeArrays = false,
|
||||
?string $transactionName = null
|
||||
) {
|
||||
parent::__construct($level, $bubble);
|
||||
|
||||
$this->appName = $appName;
|
||||
$this->explodeArrays = $explodeArrays;
|
||||
$this->transactionName = $transactionName;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
if (!$this->isNewRelicEnabled()) {
|
||||
throw new MissingExtensionException('The newrelic PHP extension is required to use the NewRelicHandler');
|
||||
}
|
||||
|
||||
if ($appName = $this->getAppName($record['context'])) {
|
||||
$this->setNewRelicAppName($appName);
|
||||
}
|
||||
|
||||
if ($transactionName = $this->getTransactionName($record['context'])) {
|
||||
$this->setNewRelicTransactionName($transactionName);
|
||||
unset($record['formatted']['context']['transaction_name']);
|
||||
}
|
||||
|
||||
if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Throwable) {
|
||||
newrelic_notice_error($record['message'], $record['context']['exception']);
|
||||
unset($record['formatted']['context']['exception']);
|
||||
} else {
|
||||
newrelic_notice_error($record['message']);
|
||||
}
|
||||
|
||||
if (isset($record['formatted']['context']) && is_array($record['formatted']['context'])) {
|
||||
foreach ($record['formatted']['context'] as $key => $parameter) {
|
||||
if (is_array($parameter) && $this->explodeArrays) {
|
||||
foreach ($parameter as $paramKey => $paramValue) {
|
||||
$this->setNewRelicParameter('context_' . $key . '_' . $paramKey, $paramValue);
|
||||
}
|
||||
} else {
|
||||
$this->setNewRelicParameter('context_' . $key, $parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($record['formatted']['extra']) && is_array($record['formatted']['extra'])) {
|
||||
foreach ($record['formatted']['extra'] as $key => $parameter) {
|
||||
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.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*/
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getDefaultFormatter(): FormatterInterface
|
||||
{
|
||||
return new NormalizerFormatter();
|
||||
}
|
||||
}
|
||||
40
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/NoopHandler.php
vendored
Normal file
40
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/NoopHandler.php
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* No-op
|
||||
*
|
||||
* This handler handles anything, but does nothing, and does not stop bubbling to the rest of the stack.
|
||||
* This can be used for testing, or to disable a handler when overriding a configuration without
|
||||
* influencing the rest of the stack.
|
||||
*
|
||||
* @author Roel Harbers <roelharbers@gmail.com>
|
||||
*/
|
||||
class NoopHandler extends Handler
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function isHandling(array $record): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handle(array $record): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
60
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php
vendored
Normal file
60
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
* Blackhole
|
||||
*
|
||||
* Any record it can handle will be thrown away. This can be used
|
||||
* to put on top of an existing stack to override it temporarily.
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* @phpstan-import-type Level from \Monolog\Logger
|
||||
* @phpstan-import-type LevelName from \Monolog\Logger
|
||||
*/
|
||||
class NullHandler extends Handler
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $level;
|
||||
|
||||
/**
|
||||
* @param string|int $level The minimum logging level at which this handler will be triggered
|
||||
*
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $level
|
||||
*/
|
||||
public function __construct($level = Logger::DEBUG)
|
||||
{
|
||||
$this->level = Logger::toMonologLevel($level);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function isHandling(array $record): bool
|
||||
{
|
||||
return $record['level'] >= $this->level;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handle(array $record): bool
|
||||
{
|
||||
return $record['level'] >= $this->level;
|
||||
}
|
||||
}
|
||||
149
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/OverflowHandler.php
vendored
Normal file
149
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/OverflowHandler.php
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
|
||||
/**
|
||||
* Handler to only pass log messages when a certain threshold of number of messages is reached.
|
||||
*
|
||||
* This can be useful in cases of processing a batch of data, but you're for example only interested
|
||||
* in case it fails catastrophically instead of a warning for 1 or 2 events. Worse things can happen, right?
|
||||
*
|
||||
* Usage example:
|
||||
*
|
||||
* ```
|
||||
* $log = new Logger('application');
|
||||
* $handler = new SomeHandler(...)
|
||||
*
|
||||
* // Pass all warnings to the handler when more than 10 & all error messages when more then 5
|
||||
* $overflow = new OverflowHandler($handler, [Logger::WARNING => 10, Logger::ERROR => 5]);
|
||||
*
|
||||
* $log->pushHandler($overflow);
|
||||
*```
|
||||
*
|
||||
* @author Kris Buist <krisbuist@gmail.com>
|
||||
*/
|
||||
class OverflowHandler extends AbstractHandler implements FormattableHandlerInterface
|
||||
{
|
||||
/** @var HandlerInterface */
|
||||
private $handler;
|
||||
|
||||
/** @var int[] */
|
||||
private $thresholdMap = [
|
||||
Logger::DEBUG => 0,
|
||||
Logger::INFO => 0,
|
||||
Logger::NOTICE => 0,
|
||||
Logger::WARNING => 0,
|
||||
Logger::ERROR => 0,
|
||||
Logger::CRITICAL => 0,
|
||||
Logger::ALERT => 0,
|
||||
Logger::EMERGENCY => 0,
|
||||
];
|
||||
|
||||
/**
|
||||
* Buffer of all messages passed to the handler before the threshold was reached
|
||||
*
|
||||
* @var mixed[][]
|
||||
*/
|
||||
private $buffer = [];
|
||||
|
||||
/**
|
||||
* @param HandlerInterface $handler
|
||||
* @param int[] $thresholdMap Dictionary of logger level => threshold
|
||||
*/
|
||||
public function __construct(
|
||||
HandlerInterface $handler,
|
||||
array $thresholdMap = [],
|
||||
$level = Logger::DEBUG,
|
||||
bool $bubble = true
|
||||
) {
|
||||
$this->handler = $handler;
|
||||
foreach ($thresholdMap as $thresholdLevel => $threshold) {
|
||||
$this->thresholdMap[$thresholdLevel] = $threshold;
|
||||
}
|
||||
parent::__construct($level, $bubble);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a record.
|
||||
*
|
||||
* All records may be passed to this method, and the handler should discard
|
||||
* those that it does not want to handle.
|
||||
*
|
||||
* The return value of this function controls the bubbling process of the handler stack.
|
||||
* Unless the bubbling is interrupted (by returning true), the Logger class will keep on
|
||||
* calling further handlers in the stack with a given log record.
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handle(array $record): bool
|
||||
{
|
||||
if ($record['level'] < $this->level) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$level = $record['level'];
|
||||
|
||||
if (!isset($this->thresholdMap[$level])) {
|
||||
$this->thresholdMap[$level] = 0;
|
||||
}
|
||||
|
||||
if ($this->thresholdMap[$level] > 0) {
|
||||
// The overflow threshold is not yet reached, so we're buffering the record and lowering the threshold by 1
|
||||
$this->thresholdMap[$level]--;
|
||||
$this->buffer[$level][] = $record;
|
||||
|
||||
return false === $this->bubble;
|
||||
}
|
||||
|
||||
if ($this->thresholdMap[$level] == 0) {
|
||||
// This current message is breaking the threshold. Flush the buffer and continue handling the current record
|
||||
foreach ($this->buffer[$level] ?? [] as $buffered) {
|
||||
$this->handler->handle($buffered);
|
||||
}
|
||||
$this->thresholdMap[$level]--;
|
||||
unset($this->buffer[$level]);
|
||||
}
|
||||
|
||||
$this->handler->handle($record);
|
||||
|
||||
return false === $this->bubble;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function setFormatter(FormatterInterface $formatter): HandlerInterface
|
||||
{
|
||||
if ($this->handler instanceof FormattableHandlerInterface) {
|
||||
$this->handler->setFormatter($formatter);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
throw new \UnexpectedValueException('The nested handler of type '.get_class($this->handler).' does not support formatters.');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getFormatter(): FormatterInterface
|
||||
{
|
||||
if ($this->handler instanceof FormattableHandlerInterface) {
|
||||
return $this->handler->getFormatter();
|
||||
}
|
||||
|
||||
throw new \UnexpectedValueException('The nested handler of type '.get_class($this->handler).' does not support formatters.');
|
||||
}
|
||||
}
|
||||
262
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php
vendored
Normal file
262
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php
vendored
Normal file
@@ -0,0 +1,262 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Monolog\Logger;
|
||||
use Monolog\Utils;
|
||||
use PhpConsole\Connector;
|
||||
use PhpConsole\Handler as VendorPhpConsoleHandler;
|
||||
use PhpConsole\Helper;
|
||||
|
||||
/**
|
||||
* Monolog handler for Google Chrome extension "PHP Console"
|
||||
*
|
||||
* Display PHP error/debug log messages in Google Chrome console and notification popups, executes PHP code remotely
|
||||
*
|
||||
* Usage:
|
||||
* 1. Install Google Chrome extension https://chrome.google.com/webstore/detail/php-console/nfhmhhlpfleoednkpnnnkolmclajemef
|
||||
* 2. See overview https://github.com/barbushin/php-console#overview
|
||||
* 3. Install PHP Console library https://github.com/barbushin/php-console#installation
|
||||
* 4. Example (result will looks like http://i.hizliresim.com/vg3Pz4.png)
|
||||
*
|
||||
* $logger = new \Monolog\Logger('all', array(new \Monolog\Handler\PHPConsoleHandler()));
|
||||
* \Monolog\ErrorHandler::register($logger);
|
||||
* echo $undefinedVar;
|
||||
* $logger->debug('SELECT * FROM users', array('db', 'time' => 0.012));
|
||||
* PC::debug($_SERVER); // PHP Console debugger for any type of vars
|
||||
*
|
||||
* @author Sergey Barbushin https://www.linkedin.com/in/barbushin
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
*/
|
||||
class PHPConsoleHandler extends AbstractProcessingHandler
|
||||
{
|
||||
/** @var array<string, mixed> */
|
||||
private $options = [
|
||||
'enabled' => true, // bool Is PHP Console server enabled
|
||||
'classesPartialsTraceIgnore' => ['Monolog\\'], // array Hide calls of classes started with...
|
||||
'debugTagsKeysInContext' => [0, 'tag'], // bool Is PHP Console server enabled
|
||||
'useOwnErrorsHandler' => false, // bool Enable errors handling
|
||||
'useOwnExceptionsHandler' => false, // bool Enable exceptions handling
|
||||
'sourcesBasePath' => null, // string Base path of all project sources to strip in errors source paths
|
||||
'registerHelper' => true, // bool Register PhpConsole\Helper that allows short debug calls like PC::debug($var, 'ta.g.s')
|
||||
'serverEncoding' => null, // string|null Server internal encoding
|
||||
'headersLimit' => null, // int|null Set headers size limit for your web-server
|
||||
'password' => null, // string|null Protect PHP Console connection by password
|
||||
'enableSslOnlyMode' => false, // bool Force connection by SSL for clients with PHP Console installed
|
||||
'ipMasks' => [], // array Set IP masks of clients that will be allowed to connect to PHP Console: array('192.168.*.*', '127.0.0.1')
|
||||
'enableEvalListener' => false, // bool Enable eval request to be handled by eval dispatcher(if enabled, 'password' option is also required)
|
||||
'dumperDetectCallbacks' => false, // bool Convert callback items in dumper vars to (callback SomeClass::someMethod) strings
|
||||
'dumperLevelLimit' => 5, // int Maximum dumped vars array or object nested dump level
|
||||
'dumperItemsCountLimit' => 100, // int Maximum dumped var same level array items or object properties number
|
||||
'dumperItemSizeLimit' => 5000, // int Maximum length of any string or dumped array item
|
||||
'dumperDumpSizeLimit' => 500000, // int Maximum approximate size of dumped vars result formatted in JSON
|
||||
'detectDumpTraceAndSource' => false, // bool Autodetect and append trace data to debug
|
||||
'dataStorage' => null, // \PhpConsole\Storage|null Fixes problem with custom $_SESSION handler(see http://goo.gl/Ne8juJ)
|
||||
];
|
||||
|
||||
/** @var Connector */
|
||||
private $connector;
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $options See \Monolog\Handler\PHPConsoleHandler::$options for more details
|
||||
* @param Connector|null $connector Instance of \PhpConsole\Connector class (optional)
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function __construct(array $options = [], ?Connector $connector = null, $level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
if (!class_exists('PhpConsole\Connector')) {
|
||||
throw new \RuntimeException('PHP Console library not found. See https://github.com/barbushin/php-console#installation');
|
||||
}
|
||||
parent::__construct($level, $bubble);
|
||||
$this->options = $this->initOptions($options);
|
||||
$this->connector = $this->initConnector($connector);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $options
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function initOptions(array $options): array
|
||||
{
|
||||
$wrongOptions = array_diff(array_keys($options), array_keys($this->options));
|
||||
if ($wrongOptions) {
|
||||
throw new \RuntimeException('Unknown options: ' . implode(', ', $wrongOptions));
|
||||
}
|
||||
|
||||
return array_replace($this->options, $options);
|
||||
}
|
||||
|
||||
private function initConnector(?Connector $connector = null): Connector
|
||||
{
|
||||
if (!$connector) {
|
||||
if ($this->options['dataStorage']) {
|
||||
Connector::setPostponeStorage($this->options['dataStorage']);
|
||||
}
|
||||
$connector = Connector::getInstance();
|
||||
}
|
||||
|
||||
if ($this->options['registerHelper'] && !Helper::isRegistered()) {
|
||||
Helper::register();
|
||||
}
|
||||
|
||||
if ($this->options['enabled'] && $connector->isActiveClient()) {
|
||||
if ($this->options['useOwnErrorsHandler'] || $this->options['useOwnExceptionsHandler']) {
|
||||
$handler = VendorPhpConsoleHandler::getInstance();
|
||||
$handler->setHandleErrors($this->options['useOwnErrorsHandler']);
|
||||
$handler->setHandleExceptions($this->options['useOwnExceptionsHandler']);
|
||||
$handler->start();
|
||||
}
|
||||
if ($this->options['sourcesBasePath']) {
|
||||
$connector->setSourcesBasePath($this->options['sourcesBasePath']);
|
||||
}
|
||||
if ($this->options['serverEncoding']) {
|
||||
$connector->setServerEncoding($this->options['serverEncoding']);
|
||||
}
|
||||
if ($this->options['password']) {
|
||||
$connector->setPassword($this->options['password']);
|
||||
}
|
||||
if ($this->options['enableSslOnlyMode']) {
|
||||
$connector->enableSslOnlyMode();
|
||||
}
|
||||
if ($this->options['ipMasks']) {
|
||||
$connector->setAllowedIpMasks($this->options['ipMasks']);
|
||||
}
|
||||
if ($this->options['headersLimit']) {
|
||||
$connector->setHeadersLimit($this->options['headersLimit']);
|
||||
}
|
||||
if ($this->options['detectDumpTraceAndSource']) {
|
||||
$connector->getDebugDispatcher()->detectTraceAndSource = true;
|
||||
}
|
||||
$dumper = $connector->getDumper();
|
||||
$dumper->levelLimit = $this->options['dumperLevelLimit'];
|
||||
$dumper->itemsCountLimit = $this->options['dumperItemsCountLimit'];
|
||||
$dumper->itemSizeLimit = $this->options['dumperItemSizeLimit'];
|
||||
$dumper->dumpSizeLimit = $this->options['dumperDumpSizeLimit'];
|
||||
$dumper->detectCallbacks = $this->options['dumperDetectCallbacks'];
|
||||
if ($this->options['enableEvalListener']) {
|
||||
$connector->startEvalRequestsListener();
|
||||
}
|
||||
}
|
||||
|
||||
return $connector;
|
||||
}
|
||||
|
||||
public function getConnector(): Connector
|
||||
{
|
||||
return $this->connector;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function getOptions(): array
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
public function handle(array $record): bool
|
||||
{
|
||||
if ($this->options['enabled'] && $this->connector->isActiveClient()) {
|
||||
return parent::handle($record);
|
||||
}
|
||||
|
||||
return !$this->bubble;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the record down to the log of the implementing handler
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
if ($record['level'] < Logger::NOTICE) {
|
||||
$this->handleDebugRecord($record);
|
||||
} elseif (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Throwable) {
|
||||
$this->handleExceptionRecord($record);
|
||||
} else {
|
||||
$this->handleErrorRecord($record);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param Record $record
|
||||
*/
|
||||
private function handleDebugRecord(array $record): void
|
||||
{
|
||||
$tags = $this->getRecordTags($record);
|
||||
$message = $record['message'];
|
||||
if ($record['context']) {
|
||||
$message .= ' ' . Utils::jsonEncode($this->connector->getDumper()->dump(array_filter($record['context'])), null, true);
|
||||
}
|
||||
$this->connector->getDebugDispatcher()->dispatchDebug($message, $tags, $this->options['classesPartialsTraceIgnore']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param Record $record
|
||||
*/
|
||||
private function handleExceptionRecord(array $record): void
|
||||
{
|
||||
$this->connector->getErrorsDispatcher()->dispatchException($record['context']['exception']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param Record $record
|
||||
*/
|
||||
private function handleErrorRecord(array $record): void
|
||||
{
|
||||
$context = $record['context'];
|
||||
|
||||
$this->connector->getErrorsDispatcher()->dispatchError(
|
||||
$context['code'] ?? null,
|
||||
$context['message'] ?? $record['message'],
|
||||
$context['file'] ?? null,
|
||||
$context['line'] ?? null,
|
||||
$this->options['classesPartialsTraceIgnore']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param Record $record
|
||||
* @return string
|
||||
*/
|
||||
private function getRecordTags(array &$record)
|
||||
{
|
||||
$tags = null;
|
||||
if (!empty($record['context'])) {
|
||||
$context = & $record['context'];
|
||||
foreach ($this->options['debugTagsKeysInContext'] as $key) {
|
||||
if (!empty($context[$key])) {
|
||||
$tags = $context[$key];
|
||||
if ($key === 0) {
|
||||
array_shift($context);
|
||||
} else {
|
||||
unset($context[$key]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $tags ?: strtolower($record['level_name']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getDefaultFormatter(): FormatterInterface
|
||||
{
|
||||
return new LineFormatter('%message%');
|
||||
}
|
||||
}
|
||||
191
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/ProcessHandler.php
vendored
Normal file
191
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/ProcessHandler.php
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* Stores to STDIN of any process, specified by a command.
|
||||
*
|
||||
* Usage example:
|
||||
* <pre>
|
||||
* $log = new Logger('myLogger');
|
||||
* $log->pushHandler(new ProcessHandler('/usr/bin/php /var/www/monolog/someScript.php'));
|
||||
* </pre>
|
||||
*
|
||||
* @author Kolja Zuelsdorf <koljaz@web.de>
|
||||
*/
|
||||
class ProcessHandler extends AbstractProcessingHandler
|
||||
{
|
||||
/**
|
||||
* Holds the process to receive data on its STDIN.
|
||||
*
|
||||
* @var resource|bool|null
|
||||
*/
|
||||
private $process;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $command;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $cwd;
|
||||
|
||||
/**
|
||||
* @var resource[]
|
||||
*/
|
||||
private $pipes = [];
|
||||
|
||||
/**
|
||||
* @var array<int, string[]>
|
||||
*/
|
||||
protected const DESCRIPTOR_SPEC = [
|
||||
0 => ['pipe', 'r'], // STDIN is a pipe that the child will read from
|
||||
1 => ['pipe', 'w'], // STDOUT is a pipe that the child will write to
|
||||
2 => ['pipe', 'w'], // STDERR is a pipe to catch the any errors
|
||||
];
|
||||
|
||||
/**
|
||||
* @param string $command Command for the process to start. Absolute paths are recommended,
|
||||
* especially if you do not use the $cwd parameter.
|
||||
* @param string|null $cwd "Current working directory" (CWD) for the process to be executed in.
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function __construct(string $command, $level = Logger::DEBUG, bool $bubble = true, ?string $cwd = null)
|
||||
{
|
||||
if ($command === '') {
|
||||
throw new \InvalidArgumentException('The command argument must be a non-empty string.');
|
||||
}
|
||||
if ($cwd === '') {
|
||||
throw new \InvalidArgumentException('The optional CWD argument must be a non-empty string or null.');
|
||||
}
|
||||
|
||||
parent::__construct($level, $bubble);
|
||||
|
||||
$this->command = $command;
|
||||
$this->cwd = $cwd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the record down to the log of the implementing handler
|
||||
*
|
||||
* @throws \UnexpectedValueException
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
$this->ensureProcessIsStarted();
|
||||
|
||||
$this->writeProcessInput($record['formatted']);
|
||||
|
||||
$errors = $this->readProcessErrors();
|
||||
if (empty($errors) === false) {
|
||||
throw new \UnexpectedValueException(sprintf('Errors while writing to process: %s', $errors));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure that the process is actually started, and if not, starts it,
|
||||
* assigns the stream pipes, and handles startup errors, if any.
|
||||
*/
|
||||
private function ensureProcessIsStarted(): void
|
||||
{
|
||||
if (is_resource($this->process) === false) {
|
||||
$this->startProcess();
|
||||
|
||||
$this->handleStartupErrors();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the actual process and sets all streams to non-blocking.
|
||||
*/
|
||||
private function startProcess(): void
|
||||
{
|
||||
$this->process = proc_open($this->command, static::DESCRIPTOR_SPEC, $this->pipes, $this->cwd);
|
||||
|
||||
foreach ($this->pipes as $pipe) {
|
||||
stream_set_blocking($pipe, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the STDERR stream, handles upcoming startup errors, and throws an exception, if any.
|
||||
*
|
||||
* @throws \UnexpectedValueException
|
||||
*/
|
||||
private function handleStartupErrors(): void
|
||||
{
|
||||
$selected = $this->selectErrorStream();
|
||||
if (false === $selected) {
|
||||
throw new \UnexpectedValueException('Something went wrong while selecting a stream.');
|
||||
}
|
||||
|
||||
$errors = $this->readProcessErrors();
|
||||
|
||||
if (is_resource($this->process) === false || empty($errors) === false) {
|
||||
throw new \UnexpectedValueException(
|
||||
sprintf('The process "%s" could not be opened: ' . $errors, $this->command)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the STDERR stream.
|
||||
*
|
||||
* @return int|bool
|
||||
*/
|
||||
protected function selectErrorStream()
|
||||
{
|
||||
$empty = [];
|
||||
$errorPipes = [$this->pipes[2]];
|
||||
|
||||
return stream_select($errorPipes, $empty, $empty, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the errors of the process, if there are any.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @return string Empty string if there are no errors.
|
||||
*/
|
||||
protected function readProcessErrors(): string
|
||||
{
|
||||
return (string) stream_get_contents($this->pipes[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes to the input stream of the opened process.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected function writeProcessInput(string $string): void
|
||||
{
|
||||
fwrite($this->pipes[0], $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function close(): void
|
||||
{
|
||||
if (is_resource($this->process)) {
|
||||
foreach ($this->pipes as $pipe) {
|
||||
fclose($pipe);
|
||||
}
|
||||
proc_close($this->process);
|
||||
$this->process = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Processor\ProcessorInterface;
|
||||
|
||||
/**
|
||||
* Interface to describe loggers that have processors
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
*/
|
||||
interface ProcessableHandlerInterface
|
||||
{
|
||||
/**
|
||||
* Adds a processor in the stack.
|
||||
*
|
||||
* @psalm-param ProcessorInterface|callable(Record): Record $callback
|
||||
*
|
||||
* @param ProcessorInterface|callable $callback
|
||||
* @return HandlerInterface self
|
||||
*/
|
||||
public function pushProcessor(callable $callback): HandlerInterface;
|
||||
|
||||
/**
|
||||
* Removes the processor on top of the stack and returns it.
|
||||
*
|
||||
* @psalm-return ProcessorInterface|callable(Record): Record $callback
|
||||
*
|
||||
* @throws \LogicException In case the processor stack is empty
|
||||
* @return callable|ProcessorInterface
|
||||
*/
|
||||
public function popProcessor(): callable;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\ResettableInterface;
|
||||
use Monolog\Processor\ProcessorInterface;
|
||||
|
||||
/**
|
||||
* Helper trait for implementing ProcessableInterface
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
*/
|
||||
trait ProcessableHandlerTrait
|
||||
{
|
||||
/**
|
||||
* @var callable[]
|
||||
* @phpstan-var array<ProcessorInterface|callable(Record): Record>
|
||||
*/
|
||||
protected $processors = [];
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function pushProcessor(callable $callback): HandlerInterface
|
||||
{
|
||||
array_unshift($this->processors, $callback);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function popProcessor(): callable
|
||||
{
|
||||
if (!$this->processors) {
|
||||
throw new \LogicException('You tried to pop from an empty processor stack.');
|
||||
}
|
||||
|
||||
return array_shift($this->processors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a record.
|
||||
*
|
||||
* @phpstan-param Record $record
|
||||
* @phpstan-return Record
|
||||
*/
|
||||
protected function processRecord(array $record): array
|
||||
{
|
||||
foreach ($this->processors as $processor) {
|
||||
$record = $processor($record);
|
||||
}
|
||||
|
||||
return $record;
|
||||
}
|
||||
|
||||
protected function resetProcessors(): void
|
||||
{
|
||||
foreach ($this->processors as $processor) {
|
||||
if ($processor instanceof ResettableInterface) {
|
||||
$processor->reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
95
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php
vendored
Normal file
95
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
|
||||
/**
|
||||
* Proxies log messages to an existing PSR-3 compliant logger.
|
||||
*
|
||||
* If a formatter is configured, the formatter's output MUST be a string and the
|
||||
* formatted message will be fed to the wrapped PSR logger instead of the original
|
||||
* log record's message.
|
||||
*
|
||||
* @author Michael Moussa <michael.moussa@gmail.com>
|
||||
*/
|
||||
class PsrHandler extends AbstractHandler implements FormattableHandlerInterface
|
||||
{
|
||||
/**
|
||||
* PSR-3 compliant logger
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* @var FormatterInterface|null
|
||||
*/
|
||||
protected $formatter;
|
||||
|
||||
/**
|
||||
* @param LoggerInterface $logger The underlying PSR-3 compliant logger to which messages will be proxied
|
||||
*/
|
||||
public function __construct(LoggerInterface $logger, $level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
parent::__construct($level, $bubble);
|
||||
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handle(array $record): bool
|
||||
{
|
||||
if (!$this->isHandling($record)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->formatter) {
|
||||
$formatted = $this->formatter->format($record);
|
||||
$this->logger->log(strtolower($record['level_name']), (string) $formatted, $record['context']);
|
||||
} else {
|
||||
$this->logger->log(strtolower($record['level_name']), $record['message'], $record['context']);
|
||||
}
|
||||
|
||||
return false === $this->bubble;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the formatter.
|
||||
*
|
||||
* @param FormatterInterface $formatter
|
||||
*/
|
||||
public function setFormatter(FormatterInterface $formatter): HandlerInterface
|
||||
{
|
||||
$this->formatter = $formatter;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the formatter.
|
||||
*
|
||||
* @return FormatterInterface
|
||||
*/
|
||||
public function getFormatter(): FormatterInterface
|
||||
{
|
||||
if (!$this->formatter) {
|
||||
throw new \LogicException('No formatter has been set and this handler does not have a default formatter');
|
||||
}
|
||||
|
||||
return $this->formatter;
|
||||
}
|
||||
}
|
||||
232
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php
vendored
Normal file
232
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php
vendored
Normal file
@@ -0,0 +1,232 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\Utils;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
* Sends notifications through the pushover api to mobile phones
|
||||
*
|
||||
* @author Sebastian Göttschkes <sebastian.goettschkes@googlemail.com>
|
||||
* @see https://www.pushover.net/api
|
||||
*
|
||||
* @phpstan-import-type FormattedRecord from AbstractProcessingHandler
|
||||
* @phpstan-import-type Level from \Monolog\Logger
|
||||
* @phpstan-import-type LevelName from \Monolog\Logger
|
||||
*/
|
||||
class PushoverHandler extends SocketHandler
|
||||
{
|
||||
/** @var string */
|
||||
private $token;
|
||||
/** @var array<int|string> */
|
||||
private $users;
|
||||
/** @var string */
|
||||
private $title;
|
||||
/** @var string|int|null */
|
||||
private $user = null;
|
||||
/** @var int */
|
||||
private $retry;
|
||||
/** @var int */
|
||||
private $expire;
|
||||
|
||||
/** @var int */
|
||||
private $highPriorityLevel;
|
||||
/** @var int */
|
||||
private $emergencyLevel;
|
||||
/** @var bool */
|
||||
private $useFormattedMessage = false;
|
||||
|
||||
/**
|
||||
* All parameters that can be sent to Pushover
|
||||
* @see https://pushover.net/api
|
||||
* @var array<string, bool>
|
||||
*/
|
||||
private $parameterNames = [
|
||||
'token' => true,
|
||||
'user' => true,
|
||||
'message' => true,
|
||||
'device' => true,
|
||||
'title' => true,
|
||||
'url' => true,
|
||||
'url_title' => true,
|
||||
'priority' => true,
|
||||
'timestamp' => true,
|
||||
'sound' => true,
|
||||
'retry' => true,
|
||||
'expire' => true,
|
||||
'callback' => true,
|
||||
];
|
||||
|
||||
/**
|
||||
* Sounds the api supports by default
|
||||
* @see https://pushover.net/api#sounds
|
||||
* @var string[]
|
||||
*/
|
||||
private $sounds = [
|
||||
'pushover', 'bike', 'bugle', 'cashregister', 'classical', 'cosmic', 'falling', 'gamelan', 'incoming',
|
||||
'intermission', 'magic', 'mechanical', 'pianobar', 'siren', 'spacealarm', 'tugboat', 'alien', 'climb',
|
||||
'persistent', 'echo', 'updown', 'none',
|
||||
];
|
||||
|
||||
/**
|
||||
* @param string $token Pushover api token
|
||||
* @param string|array $users Pushover user id or array of ids the message will be sent to
|
||||
* @param string|null $title Title sent to the Pushover API
|
||||
* @param bool $useSSL Whether to connect via SSL. Required when pushing messages to users that are not
|
||||
* the pushover.net app owner. OpenSSL is required for this option.
|
||||
* @param string|int $highPriorityLevel The minimum logging level at which this handler will start
|
||||
* sending "high priority" requests to the Pushover API
|
||||
* @param string|int $emergencyLevel The minimum logging level at which this handler will start
|
||||
* sending "emergency" requests to the Pushover API
|
||||
* @param int $retry The retry parameter specifies how often (in seconds) the Pushover servers will
|
||||
* send the same notification to the user.
|
||||
* @param int $expire The expire parameter specifies how many seconds your notification will continue
|
||||
* to be retried for (every retry seconds).
|
||||
*
|
||||
* @phpstan-param string|array<int|string> $users
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $highPriorityLevel
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $emergencyLevel
|
||||
*/
|
||||
public function __construct(
|
||||
string $token,
|
||||
$users,
|
||||
?string $title = null,
|
||||
$level = Logger::CRITICAL,
|
||||
bool $bubble = true,
|
||||
bool $useSSL = true,
|
||||
$highPriorityLevel = Logger::CRITICAL,
|
||||
$emergencyLevel = Logger::EMERGENCY,
|
||||
int $retry = 30,
|
||||
int $expire = 25200
|
||||
) {
|
||||
$connectionString = $useSSL ? 'ssl://api.pushover.net:443' : 'api.pushover.net:80';
|
||||
parent::__construct($connectionString, $level, $bubble);
|
||||
|
||||
$this->token = $token;
|
||||
$this->users = (array) $users;
|
||||
$this->title = $title ?: (string) gethostname();
|
||||
$this->highPriorityLevel = Logger::toMonologLevel($highPriorityLevel);
|
||||
$this->emergencyLevel = Logger::toMonologLevel($emergencyLevel);
|
||||
$this->retry = $retry;
|
||||
$this->expire = $expire;
|
||||
}
|
||||
|
||||
protected function generateDataStream(array $record): string
|
||||
{
|
||||
$content = $this->buildContent($record);
|
||||
|
||||
return $this->buildHeader($content) . $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param FormattedRecord $record
|
||||
*/
|
||||
private function buildContent(array $record): string
|
||||
{
|
||||
// Pushover has a limit of 512 characters on title and message combined.
|
||||
$maxMessageLength = 512 - strlen($this->title);
|
||||
|
||||
$message = ($this->useFormattedMessage) ? $record['formatted'] : $record['message'];
|
||||
$message = Utils::substr($message, 0, $maxMessageLength);
|
||||
|
||||
$timestamp = $record['datetime']->getTimestamp();
|
||||
|
||||
$dataArray = [
|
||||
'token' => $this->token,
|
||||
'user' => $this->user,
|
||||
'message' => $message,
|
||||
'title' => $this->title,
|
||||
'timestamp' => $timestamp,
|
||||
];
|
||||
|
||||
if (isset($record['level']) && $record['level'] >= $this->emergencyLevel) {
|
||||
$dataArray['priority'] = 2;
|
||||
$dataArray['retry'] = $this->retry;
|
||||
$dataArray['expire'] = $this->expire;
|
||||
} elseif (isset($record['level']) && $record['level'] >= $this->highPriorityLevel) {
|
||||
$dataArray['priority'] = 1;
|
||||
}
|
||||
|
||||
// First determine the available parameters
|
||||
$context = array_intersect_key($record['context'], $this->parameterNames);
|
||||
$extra = array_intersect_key($record['extra'], $this->parameterNames);
|
||||
|
||||
// Least important info should be merged with subsequent info
|
||||
$dataArray = array_merge($extra, $context, $dataArray);
|
||||
|
||||
// Only pass sounds that are supported by the API
|
||||
if (isset($dataArray['sound']) && !in_array($dataArray['sound'], $this->sounds)) {
|
||||
unset($dataArray['sound']);
|
||||
}
|
||||
|
||||
return http_build_query($dataArray);
|
||||
}
|
||||
|
||||
private function buildHeader(string $content): string
|
||||
{
|
||||
$header = "POST /1/messages.json HTTP/1.1\r\n";
|
||||
$header .= "Host: api.pushover.net\r\n";
|
||||
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
|
||||
$header .= "Content-Length: " . strlen($content) . "\r\n";
|
||||
$header .= "\r\n";
|
||||
|
||||
return $header;
|
||||
}
|
||||
|
||||
protected function write(array $record): void
|
||||
{
|
||||
foreach ($this->users as $user) {
|
||||
$this->user = $user;
|
||||
|
||||
parent::write($record);
|
||||
$this->closeSocket();
|
||||
}
|
||||
|
||||
$this->user = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|string $value
|
||||
*
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $value
|
||||
*/
|
||||
public function setHighPriorityLevel($value): self
|
||||
{
|
||||
$this->highPriorityLevel = Logger::toMonologLevel($value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|string $value
|
||||
*
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $value
|
||||
*/
|
||||
public function setEmergencyLevel($value): self
|
||||
{
|
||||
$this->emergencyLevel = Logger::toMonologLevel($value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the formatted message?
|
||||
*/
|
||||
public function useFormattedMessage(bool $value): self
|
||||
{
|
||||
$this->useFormattedMessage = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
101
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php
vendored
Normal file
101
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* Logs to a Redis key using rpush
|
||||
*
|
||||
* usage example:
|
||||
*
|
||||
* $log = new Logger('application');
|
||||
* $redis = new RedisHandler(new Predis\Client("tcp://localhost:6379"), "logs", "prod");
|
||||
* $log->pushHandler($redis);
|
||||
*
|
||||
* @author Thomas Tourlourat <thomas@tourlourat.com>
|
||||
*
|
||||
* @phpstan-import-type FormattedRecord from AbstractProcessingHandler
|
||||
*/
|
||||
class RedisHandler extends AbstractProcessingHandler
|
||||
{
|
||||
/** @var \Predis\Client|\Redis */
|
||||
private $redisClient;
|
||||
/** @var string */
|
||||
private $redisKey;
|
||||
/** @var int */
|
||||
protected $capSize;
|
||||
|
||||
/**
|
||||
* @param \Predis\Client|\Redis $redis The redis instance
|
||||
* @param string $key The key name to push records to
|
||||
* @param int $capSize Number of entries to limit list size to, 0 = unlimited
|
||||
*/
|
||||
public function __construct($redis, string $key, $level = Logger::DEBUG, bool $bubble = true, int $capSize = 0)
|
||||
{
|
||||
if (!(($redis instanceof \Predis\Client) || ($redis instanceof \Redis))) {
|
||||
throw new \InvalidArgumentException('Predis\Client or Redis instance required');
|
||||
}
|
||||
|
||||
$this->redisClient = $redis;
|
||||
$this->redisKey = $key;
|
||||
$this->capSize = $capSize;
|
||||
|
||||
parent::__construct($level, $bubble);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
if ($this->capSize) {
|
||||
$this->writeCapped($record);
|
||||
} else {
|
||||
$this->redisClient->rpush($this->redisKey, $record["formatted"]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write and cap the collection
|
||||
* Writes the record to the redis list and caps its
|
||||
*
|
||||
* @phpstan-param FormattedRecord $record
|
||||
*/
|
||||
protected function writeCapped(array $record): void
|
||||
{
|
||||
if ($this->redisClient instanceof \Redis) {
|
||||
$mode = defined('\Redis::MULTI') ? \Redis::MULTI : 1;
|
||||
$this->redisClient->multi($mode)
|
||||
->rpush($this->redisKey, $record["formatted"])
|
||||
->ltrim($this->redisKey, -$this->capSize, -1)
|
||||
->exec();
|
||||
} else {
|
||||
$redisKey = $this->redisKey;
|
||||
$capSize = $this->capSize;
|
||||
$this->redisClient->transaction(function ($tx) use ($record, $redisKey, $capSize) {
|
||||
$tx->rpush($redisKey, $record["formatted"]);
|
||||
$tx->ltrim($redisKey, -$capSize, -1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getDefaultFormatter(): FormatterInterface
|
||||
{
|
||||
return new LineFormatter();
|
||||
}
|
||||
}
|
||||
67
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.php
vendored
Normal file
67
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.php
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* Sends the message to a Redis Pub/Sub channel using PUBLISH
|
||||
*
|
||||
* usage example:
|
||||
*
|
||||
* $log = new Logger('application');
|
||||
* $redis = new RedisPubSubHandler(new Predis\Client("tcp://localhost:6379"), "logs", Logger::WARNING);
|
||||
* $log->pushHandler($redis);
|
||||
*
|
||||
* @author Gaëtan Faugère <gaetan@fauge.re>
|
||||
*/
|
||||
class RedisPubSubHandler extends AbstractProcessingHandler
|
||||
{
|
||||
/** @var \Predis\Client|\Redis */
|
||||
private $redisClient;
|
||||
/** @var string */
|
||||
private $channelKey;
|
||||
|
||||
/**
|
||||
* @param \Predis\Client|\Redis $redis The redis instance
|
||||
* @param string $key The channel key to publish records to
|
||||
*/
|
||||
public function __construct($redis, string $key, $level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
if (!(($redis instanceof \Predis\Client) || ($redis instanceof \Redis))) {
|
||||
throw new \InvalidArgumentException('Predis\Client or Redis instance required');
|
||||
}
|
||||
|
||||
$this->redisClient = $redis;
|
||||
$this->channelKey = $key;
|
||||
|
||||
parent::__construct($level, $bubble);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
$this->redisClient->publish($this->channelKey, $record["formatted"]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getDefaultFormatter(): FormatterInterface
|
||||
{
|
||||
return new LineFormatter();
|
||||
}
|
||||
}
|
||||
131
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.php
vendored
Normal file
131
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.php
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
<?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;
|
||||
|
||||
use Rollbar\RollbarLogger;
|
||||
use Throwable;
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* Sends errors to Rollbar
|
||||
*
|
||||
* If the context data contains a `payload` key, that is used as an array
|
||||
* of payload options to RollbarLogger's log method.
|
||||
*
|
||||
* Rollbar's context info will contain the context + extra keys from the log record
|
||||
* merged, and then on top of that a few keys:
|
||||
*
|
||||
* - level (rollbar level name)
|
||||
* - monolog_level (monolog level name, raw level, as rollbar only has 5 but monolog 8)
|
||||
* - channel
|
||||
* - datetime (unix timestamp)
|
||||
*
|
||||
* @author Paul Statezny <paulstatezny@gmail.com>
|
||||
*/
|
||||
class RollbarHandler extends AbstractProcessingHandler
|
||||
{
|
||||
/**
|
||||
* @var RollbarLogger
|
||||
*/
|
||||
protected $rollbarLogger;
|
||||
|
||||
/** @var string[] */
|
||||
protected $levelMap = [
|
||||
Logger::DEBUG => 'debug',
|
||||
Logger::INFO => 'info',
|
||||
Logger::NOTICE => 'info',
|
||||
Logger::WARNING => 'warning',
|
||||
Logger::ERROR => 'error',
|
||||
Logger::CRITICAL => 'critical',
|
||||
Logger::ALERT => 'critical',
|
||||
Logger::EMERGENCY => 'critical',
|
||||
];
|
||||
|
||||
/**
|
||||
* Records whether any log records have been added since the last flush of the rollbar notifier
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $hasRecords = false;
|
||||
|
||||
/** @var bool */
|
||||
protected $initialized = false;
|
||||
|
||||
/**
|
||||
* @param RollbarLogger $rollbarLogger RollbarLogger object constructed with valid token
|
||||
*/
|
||||
public function __construct(RollbarLogger $rollbarLogger, $level = Logger::ERROR, bool $bubble = true)
|
||||
{
|
||||
$this->rollbarLogger = $rollbarLogger;
|
||||
|
||||
parent::__construct($level, $bubble);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
if (!$this->initialized) {
|
||||
// __destructor() doesn't get called on Fatal errors
|
||||
register_shutdown_function(array($this, 'close'));
|
||||
$this->initialized = true;
|
||||
}
|
||||
|
||||
$context = $record['context'];
|
||||
$context = array_merge($context, $record['extra'], [
|
||||
'level' => $this->levelMap[$record['level']],
|
||||
'monolog_level' => $record['level_name'],
|
||||
'channel' => $record['channel'],
|
||||
'datetime' => $record['datetime']->format('U'),
|
||||
]);
|
||||
|
||||
if (isset($context['exception']) && $context['exception'] instanceof Throwable) {
|
||||
$exception = $context['exception'];
|
||||
unset($context['exception']);
|
||||
$toLog = $exception;
|
||||
} else {
|
||||
$toLog = $record['message'];
|
||||
}
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
$this->rollbarLogger->log($context['level'], $toLog, $context);
|
||||
|
||||
$this->hasRecords = true;
|
||||
}
|
||||
|
||||
public function flush(): void
|
||||
{
|
||||
if ($this->hasRecords) {
|
||||
$this->rollbarLogger->flush();
|
||||
$this->hasRecords = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function close(): void
|
||||
{
|
||||
$this->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
$this->flush();
|
||||
|
||||
parent::reset();
|
||||
}
|
||||
}
|
||||
203
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php
vendored
Normal file
203
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php
vendored
Normal file
@@ -0,0 +1,203 @@
|
||||
<?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;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Monolog\Logger;
|
||||
use Monolog\Utils;
|
||||
|
||||
/**
|
||||
* Stores logs to files that are rotated every day and a limited number of files are kept.
|
||||
*
|
||||
* This rotation is only intended to be used as a workaround. Using logrotate to
|
||||
* handle the rotation is strongly encouraged when you can use it.
|
||||
*
|
||||
* @author Christophe Coevoet <stof@notk.org>
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
class RotatingFileHandler extends StreamHandler
|
||||
{
|
||||
public const FILE_PER_DAY = 'Y-m-d';
|
||||
public const FILE_PER_MONTH = 'Y-m';
|
||||
public const FILE_PER_YEAR = 'Y';
|
||||
|
||||
/** @var string */
|
||||
protected $filename;
|
||||
/** @var int */
|
||||
protected $maxFiles;
|
||||
/** @var bool */
|
||||
protected $mustRotate;
|
||||
/** @var \DateTimeImmutable */
|
||||
protected $nextRotation;
|
||||
/** @var string */
|
||||
protected $filenameFormat;
|
||||
/** @var string */
|
||||
protected $dateFormat;
|
||||
|
||||
/**
|
||||
* @param string $filename
|
||||
* @param int $maxFiles The maximal amount of files to keep (0 means unlimited)
|
||||
* @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write)
|
||||
* @param bool $useLocking Try to lock log file before doing any writes
|
||||
*/
|
||||
public function __construct(string $filename, int $maxFiles = 0, $level = Logger::DEBUG, bool $bubble = true, ?int $filePermission = null, bool $useLocking = false)
|
||||
{
|
||||
$this->filename = Utils::canonicalizePath($filename);
|
||||
$this->maxFiles = $maxFiles;
|
||||
$this->nextRotation = new \DateTimeImmutable('tomorrow');
|
||||
$this->filenameFormat = '{filename}-{date}';
|
||||
$this->dateFormat = static::FILE_PER_DAY;
|
||||
|
||||
parent::__construct($this->getTimedFilename(), $level, $bubble, $filePermission, $useLocking);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function close(): void
|
||||
{
|
||||
parent::close();
|
||||
|
||||
if (true === $this->mustRotate) {
|
||||
$this->rotate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
parent::reset();
|
||||
|
||||
if (true === $this->mustRotate) {
|
||||
$this->rotate();
|
||||
}
|
||||
}
|
||||
|
||||
public function setFilenameFormat(string $filenameFormat, string $dateFormat): self
|
||||
{
|
||||
if (!preg_match('{^[Yy](([/_.-]?m)([/_.-]?d)?)?$}', $dateFormat)) {
|
||||
throw new InvalidArgumentException(
|
||||
'Invalid date format - format must be one of '.
|
||||
'RotatingFileHandler::FILE_PER_DAY ("Y-m-d"), RotatingFileHandler::FILE_PER_MONTH ("Y-m") '.
|
||||
'or RotatingFileHandler::FILE_PER_YEAR ("Y"), or you can set one of the '.
|
||||
'date formats using slashes, underscores and/or dots instead of dashes.'
|
||||
);
|
||||
}
|
||||
if (substr_count($filenameFormat, '{date}') === 0) {
|
||||
throw new InvalidArgumentException(
|
||||
'Invalid filename format - format must contain at least `{date}`, because otherwise rotating is impossible.'
|
||||
);
|
||||
}
|
||||
$this->filenameFormat = $filenameFormat;
|
||||
$this->dateFormat = $dateFormat;
|
||||
$this->url = $this->getTimedFilename();
|
||||
$this->close();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
// on the first record written, if the log is new, we should rotate (once per day)
|
||||
if (null === $this->mustRotate) {
|
||||
$this->mustRotate = null === $this->url || !file_exists($this->url);
|
||||
}
|
||||
|
||||
if ($this->nextRotation <= $record['datetime']) {
|
||||
$this->mustRotate = true;
|
||||
$this->close();
|
||||
}
|
||||
|
||||
parent::write($record);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates the files.
|
||||
*/
|
||||
protected function rotate(): void
|
||||
{
|
||||
// update filename
|
||||
$this->url = $this->getTimedFilename();
|
||||
$this->nextRotation = new \DateTimeImmutable('tomorrow');
|
||||
|
||||
// skip GC of old logs if files are unlimited
|
||||
if (0 === $this->maxFiles) {
|
||||
return;
|
||||
}
|
||||
|
||||
$logFiles = glob($this->getGlobPattern());
|
||||
if (false === $logFiles) {
|
||||
// failed to glob
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->maxFiles >= count($logFiles)) {
|
||||
// no files to remove
|
||||
return;
|
||||
}
|
||||
|
||||
// Sorting the files by name to remove the older ones
|
||||
usort($logFiles, function ($a, $b) {
|
||||
return strcmp($b, $a);
|
||||
});
|
||||
|
||||
foreach (array_slice($logFiles, $this->maxFiles) as $file) {
|
||||
if (is_writable($file)) {
|
||||
// suppress errors here as unlink() might fail if two processes
|
||||
// are cleaning up/rotating at the same time
|
||||
set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline): bool {
|
||||
return false;
|
||||
});
|
||||
unlink($file);
|
||||
restore_error_handler();
|
||||
}
|
||||
}
|
||||
|
||||
$this->mustRotate = false;
|
||||
}
|
||||
|
||||
protected function getTimedFilename(): string
|
||||
{
|
||||
$fileInfo = pathinfo($this->filename);
|
||||
$timedFilename = str_replace(
|
||||
['{filename}', '{date}'],
|
||||
[$fileInfo['filename'], date($this->dateFormat)],
|
||||
$fileInfo['dirname'] . '/' . $this->filenameFormat
|
||||
);
|
||||
|
||||
if (isset($fileInfo['extension'])) {
|
||||
$timedFilename .= '.'.$fileInfo['extension'];
|
||||
}
|
||||
|
||||
return $timedFilename;
|
||||
}
|
||||
|
||||
protected function getGlobPattern(): string
|
||||
{
|
||||
$fileInfo = pathinfo($this->filename);
|
||||
$glob = str_replace(
|
||||
['{filename}', '{date}'],
|
||||
[$fileInfo['filename'], '[0-9][0-9][0-9][0-9]*'],
|
||||
$fileInfo['dirname'] . '/' . $this->filenameFormat
|
||||
);
|
||||
if (isset($fileInfo['extension'])) {
|
||||
$glob .= '.'.$fileInfo['extension'];
|
||||
}
|
||||
|
||||
return $glob;
|
||||
}
|
||||
}
|
||||
132
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php
vendored
Normal file
132
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
|
||||
/**
|
||||
* Sampling handler
|
||||
*
|
||||
* A sampled event stream can be useful for logging high frequency events in
|
||||
* a production environment where you only need an idea of what is happening
|
||||
* and are not concerned with capturing every occurrence. Since the decision to
|
||||
* handle or not handle a particular event is determined randomly, the
|
||||
* resulting sampled log is not guaranteed to contain 1/N of the events that
|
||||
* occurred in the application, but based on the Law of large numbers, it will
|
||||
* tend to be close to this ratio with a large number of attempts.
|
||||
*
|
||||
* @author Bryan Davis <bd808@wikimedia.org>
|
||||
* @author Kunal Mehta <legoktm@gmail.com>
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
* @phpstan-import-type Level from \Monolog\Logger
|
||||
*/
|
||||
class SamplingHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface
|
||||
{
|
||||
use ProcessableHandlerTrait;
|
||||
|
||||
/**
|
||||
* @var HandlerInterface|callable
|
||||
* @phpstan-var HandlerInterface|callable(Record|array{level: Level}|null, HandlerInterface): HandlerInterface
|
||||
*/
|
||||
protected $handler;
|
||||
|
||||
/**
|
||||
* @var int $factor
|
||||
*/
|
||||
protected $factor;
|
||||
|
||||
/**
|
||||
* @psalm-param HandlerInterface|callable(Record|array{level: Level}|null, HandlerInterface): HandlerInterface $handler
|
||||
*
|
||||
* @param callable|HandlerInterface $handler Handler or factory callable($record|null, $samplingHandler).
|
||||
* @param int $factor Sample factor (e.g. 10 means every ~10th record is sampled)
|
||||
*/
|
||||
public function __construct($handler, int $factor)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->handler = $handler;
|
||||
$this->factor = $factor;
|
||||
|
||||
if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) {
|
||||
throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object");
|
||||
}
|
||||
}
|
||||
|
||||
public function isHandling(array $record): bool
|
||||
{
|
||||
return $this->getHandler($record)->isHandling($record);
|
||||
}
|
||||
|
||||
public function handle(array $record): bool
|
||||
{
|
||||
if ($this->isHandling($record) && mt_rand(1, $this->factor) === 1) {
|
||||
if ($this->processors) {
|
||||
/** @var Record $record */
|
||||
$record = $this->processRecord($record);
|
||||
}
|
||||
|
||||
$this->getHandler($record)->handle($record);
|
||||
}
|
||||
|
||||
return false === $this->bubble;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the nested handler
|
||||
*
|
||||
* If the handler was provided as a factory callable, this will trigger the handler's instantiation.
|
||||
*
|
||||
* @phpstan-param Record|array{level: Level}|null $record
|
||||
*
|
||||
* @return HandlerInterface
|
||||
*/
|
||||
public function getHandler(array $record = null)
|
||||
{
|
||||
if (!$this->handler instanceof HandlerInterface) {
|
||||
$this->handler = ($this->handler)($record, $this);
|
||||
if (!$this->handler instanceof HandlerInterface) {
|
||||
throw new \RuntimeException("The factory callable should return a HandlerInterface");
|
||||
}
|
||||
}
|
||||
|
||||
return $this->handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function setFormatter(FormatterInterface $formatter): HandlerInterface
|
||||
{
|
||||
$handler = $this->getHandler();
|
||||
if ($handler instanceof FormattableHandlerInterface) {
|
||||
$handler->setFormatter($formatter);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
throw new \UnexpectedValueException('The nested handler of type '.get_class($handler).' does not support formatters.');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getFormatter(): FormatterInterface
|
||||
{
|
||||
$handler = $this->getHandler();
|
||||
if ($handler instanceof FormattableHandlerInterface) {
|
||||
return $handler->getFormatter();
|
||||
}
|
||||
|
||||
throw new \UnexpectedValueException('The nested handler of type '.get_class($handler).' does not support formatters.');
|
||||
}
|
||||
}
|
||||
102
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/SendGridHandler.php
vendored
Normal file
102
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/SendGridHandler.php
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* SendGridrHandler uses the SendGrid API v2 function to send Log emails, more information in https://sendgrid.com/docs/API_Reference/Web_API/mail.html
|
||||
*
|
||||
* @author Ricardo Fontanelli <ricardo.fontanelli@hotmail.com>
|
||||
*/
|
||||
class SendGridHandler extends MailHandler
|
||||
{
|
||||
/**
|
||||
* The SendGrid API User
|
||||
* @var string
|
||||
*/
|
||||
protected $apiUser;
|
||||
|
||||
/**
|
||||
* The SendGrid API Key
|
||||
* @var string
|
||||
*/
|
||||
protected $apiKey;
|
||||
|
||||
/**
|
||||
* The email addresses to which the message will be sent
|
||||
* @var string
|
||||
*/
|
||||
protected $from;
|
||||
|
||||
/**
|
||||
* The email addresses to which the message will be sent
|
||||
* @var string[]
|
||||
*/
|
||||
protected $to;
|
||||
|
||||
/**
|
||||
* The subject of the email
|
||||
* @var string
|
||||
*/
|
||||
protected $subject;
|
||||
|
||||
/**
|
||||
* @param string $apiUser The SendGrid API User
|
||||
* @param string $apiKey The SendGrid API Key
|
||||
* @param string $from The sender of the email
|
||||
* @param string|string[] $to The recipients of the email
|
||||
* @param string $subject The subject of the mail
|
||||
*/
|
||||
public function __construct(string $apiUser, string $apiKey, string $from, $to, string $subject, $level = Logger::ERROR, bool $bubble = true)
|
||||
{
|
||||
if (!extension_loaded('curl')) {
|
||||
throw new MissingExtensionException('The curl extension is needed to use the SendGridHandler');
|
||||
}
|
||||
|
||||
parent::__construct($level, $bubble);
|
||||
$this->apiUser = $apiUser;
|
||||
$this->apiKey = $apiKey;
|
||||
$this->from = $from;
|
||||
$this->to = (array) $to;
|
||||
$this->subject = $subject;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function send(string $content, array $records): void
|
||||
{
|
||||
$message = [];
|
||||
$message['api_user'] = $this->apiUser;
|
||||
$message['api_key'] = $this->apiKey;
|
||||
$message['from'] = $this->from;
|
||||
foreach ($this->to as $recipient) {
|
||||
$message['to[]'] = $recipient;
|
||||
}
|
||||
$message['subject'] = $this->subject;
|
||||
$message['date'] = date('r');
|
||||
|
||||
if ($this->isHtmlBody($content)) {
|
||||
$message['html'] = $content;
|
||||
} else {
|
||||
$message['text'] = $content;
|
||||
}
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, 'https://api.sendgrid.com/api/mail.send.json');
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($message));
|
||||
Curl\Util::execute($ch, 2);
|
||||
}
|
||||
}
|
||||
385
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php
vendored
Normal file
385
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php
vendored
Normal file
@@ -0,0 +1,385 @@
|
||||
<?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\Slack;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\Utils;
|
||||
use Monolog\Formatter\NormalizerFormatter;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
|
||||
/**
|
||||
* Slack record utility helping to log to Slack webhooks or API.
|
||||
*
|
||||
* @author Greg Kedzierski <greg@gregkedzierski.com>
|
||||
* @author Haralan Dobrev <hkdobrev@gmail.com>
|
||||
* @see https://api.slack.com/incoming-webhooks
|
||||
* @see https://api.slack.com/docs/message-attachments
|
||||
*
|
||||
* @phpstan-import-type FormattedRecord from \Monolog\Handler\AbstractProcessingHandler
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
*/
|
||||
class SlackRecord
|
||||
{
|
||||
public const COLOR_DANGER = 'danger';
|
||||
|
||||
public const COLOR_WARNING = 'warning';
|
||||
|
||||
public const COLOR_GOOD = 'good';
|
||||
|
||||
public const COLOR_DEFAULT = '#e3e4e6';
|
||||
|
||||
/**
|
||||
* Slack channel (encoded ID or name)
|
||||
* @var string|null
|
||||
*/
|
||||
private $channel;
|
||||
|
||||
/**
|
||||
* Name of a bot
|
||||
* @var string|null
|
||||
*/
|
||||
private $username;
|
||||
|
||||
/**
|
||||
* User icon e.g. 'ghost', 'http://example.com/user.png'
|
||||
* @var string|null
|
||||
*/
|
||||
private $userIcon;
|
||||
|
||||
/**
|
||||
* Whether the message should be added to Slack as attachment (plain text otherwise)
|
||||
* @var bool
|
||||
*/
|
||||
private $useAttachment;
|
||||
|
||||
/**
|
||||
* Whether the the context/extra messages added to Slack as attachments are in a short style
|
||||
* @var bool
|
||||
*/
|
||||
private $useShortAttachment;
|
||||
|
||||
/**
|
||||
* Whether the attachment should include context and extra data
|
||||
* @var bool
|
||||
*/
|
||||
private $includeContextAndExtra;
|
||||
|
||||
/**
|
||||
* Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2']
|
||||
* @var string[]
|
||||
*/
|
||||
private $excludeFields;
|
||||
|
||||
/**
|
||||
* @var ?FormatterInterface
|
||||
*/
|
||||
private $formatter;
|
||||
|
||||
/**
|
||||
* @var NormalizerFormatter
|
||||
*/
|
||||
private $normalizerFormatter;
|
||||
|
||||
/**
|
||||
* @param string[] $excludeFields
|
||||
*/
|
||||
public function __construct(
|
||||
?string $channel = null,
|
||||
?string $username = null,
|
||||
bool $useAttachment = true,
|
||||
?string $userIcon = null,
|
||||
bool $useShortAttachment = false,
|
||||
bool $includeContextAndExtra = false,
|
||||
array $excludeFields = array(),
|
||||
FormatterInterface $formatter = null
|
||||
) {
|
||||
$this
|
||||
->setChannel($channel)
|
||||
->setUsername($username)
|
||||
->useAttachment($useAttachment)
|
||||
->setUserIcon($userIcon)
|
||||
->useShortAttachment($useShortAttachment)
|
||||
->includeContextAndExtra($includeContextAndExtra)
|
||||
->excludeFields($excludeFields)
|
||||
->setFormatter($formatter);
|
||||
|
||||
if ($this->includeContextAndExtra) {
|
||||
$this->normalizerFormatter = new NormalizerFormatter();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns required data in format that Slack
|
||||
* is expecting.
|
||||
*
|
||||
* @phpstan-param FormattedRecord $record
|
||||
* @phpstan-return mixed[]
|
||||
*/
|
||||
public function getSlackData(array $record): array
|
||||
{
|
||||
$dataArray = array();
|
||||
$record = $this->removeExcludedFields($record);
|
||||
|
||||
if ($this->username) {
|
||||
$dataArray['username'] = $this->username;
|
||||
}
|
||||
|
||||
if ($this->channel) {
|
||||
$dataArray['channel'] = $this->channel;
|
||||
}
|
||||
|
||||
if ($this->formatter && !$this->useAttachment) {
|
||||
/** @phpstan-ignore-next-line */
|
||||
$message = $this->formatter->format($record);
|
||||
} else {
|
||||
$message = $record['message'];
|
||||
}
|
||||
|
||||
if ($this->useAttachment) {
|
||||
$attachment = array(
|
||||
'fallback' => $message,
|
||||
'text' => $message,
|
||||
'color' => $this->getAttachmentColor($record['level']),
|
||||
'fields' => array(),
|
||||
'mrkdwn_in' => array('fields'),
|
||||
'ts' => $record['datetime']->getTimestamp(),
|
||||
);
|
||||
|
||||
if ($this->useShortAttachment) {
|
||||
$attachment['title'] = $record['level_name'];
|
||||
} else {
|
||||
$attachment['title'] = 'Message';
|
||||
$attachment['fields'][] = $this->generateAttachmentField('Level', $record['level_name']);
|
||||
}
|
||||
|
||||
if ($this->includeContextAndExtra) {
|
||||
foreach (array('extra', 'context') as $key) {
|
||||
if (empty($record[$key])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->useShortAttachment) {
|
||||
$attachment['fields'][] = $this->generateAttachmentField(
|
||||
(string) $key,
|
||||
$record[$key]
|
||||
);
|
||||
} else {
|
||||
// Add all extra fields as individual fields in attachment
|
||||
$attachment['fields'] = array_merge(
|
||||
$attachment['fields'],
|
||||
$this->generateAttachmentFields($record[$key])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$dataArray['attachments'] = array($attachment);
|
||||
} else {
|
||||
$dataArray['text'] = $message;
|
||||
}
|
||||
|
||||
if ($this->userIcon) {
|
||||
if (filter_var($this->userIcon, FILTER_VALIDATE_URL)) {
|
||||
$dataArray['icon_url'] = $this->userIcon;
|
||||
} else {
|
||||
$dataArray['icon_emoji'] = ":{$this->userIcon}:";
|
||||
}
|
||||
}
|
||||
|
||||
return $dataArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Slack message attachment color associated with
|
||||
* provided level.
|
||||
*/
|
||||
public function getAttachmentColor(int $level): string
|
||||
{
|
||||
switch (true) {
|
||||
case $level >= Logger::ERROR:
|
||||
return static::COLOR_DANGER;
|
||||
case $level >= Logger::WARNING:
|
||||
return static::COLOR_WARNING;
|
||||
case $level >= Logger::INFO:
|
||||
return static::COLOR_GOOD;
|
||||
default:
|
||||
return static::COLOR_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stringifies an array of key/value pairs to be used in attachment fields
|
||||
*
|
||||
* @param mixed[] $fields
|
||||
*/
|
||||
public function stringify(array $fields): string
|
||||
{
|
||||
/** @var Record $fields */
|
||||
$normalized = $this->normalizerFormatter->format($fields);
|
||||
|
||||
$hasSecondDimension = count(array_filter($normalized, 'is_array'));
|
||||
$hasNonNumericKeys = !count(array_filter(array_keys($normalized), 'is_numeric'));
|
||||
|
||||
return $hasSecondDimension || $hasNonNumericKeys
|
||||
? Utils::jsonEncode($normalized, JSON_PRETTY_PRINT|Utils::DEFAULT_JSON_FLAGS)
|
||||
: Utils::jsonEncode($normalized, Utils::DEFAULT_JSON_FLAGS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel used by the bot when posting
|
||||
*
|
||||
* @param ?string $channel
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function setChannel(?string $channel = null): self
|
||||
{
|
||||
$this->channel = $channel;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Username used by the bot when posting
|
||||
*
|
||||
* @param ?string $username
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function setUsername(?string $username = null): self
|
||||
{
|
||||
$this->username = $username;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function useAttachment(bool $useAttachment = true): self
|
||||
{
|
||||
$this->useAttachment = $useAttachment;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setUserIcon(?string $userIcon = null): self
|
||||
{
|
||||
$this->userIcon = $userIcon;
|
||||
|
||||
if (\is_string($userIcon)) {
|
||||
$this->userIcon = trim($userIcon, ':');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function useShortAttachment(bool $useShortAttachment = false): self
|
||||
{
|
||||
$this->useShortAttachment = $useShortAttachment;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function includeContextAndExtra(bool $includeContextAndExtra = false): self
|
||||
{
|
||||
$this->includeContextAndExtra = $includeContextAndExtra;
|
||||
|
||||
if ($this->includeContextAndExtra) {
|
||||
$this->normalizerFormatter = new NormalizerFormatter();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $excludeFields
|
||||
*/
|
||||
public function excludeFields(array $excludeFields = []): self
|
||||
{
|
||||
$this->excludeFields = $excludeFields;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setFormatter(?FormatterInterface $formatter = null): self
|
||||
{
|
||||
$this->formatter = $formatter;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates attachment field
|
||||
*
|
||||
* @param string|mixed[] $value
|
||||
*
|
||||
* @return array{title: string, value: string, short: false}
|
||||
*/
|
||||
private function generateAttachmentField(string $title, $value): array
|
||||
{
|
||||
$value = is_array($value)
|
||||
? sprintf('```%s```', substr($this->stringify($value), 0, 1990))
|
||||
: $value;
|
||||
|
||||
return array(
|
||||
'title' => ucfirst($title),
|
||||
'value' => $value,
|
||||
'short' => false,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a collection of attachment fields from array
|
||||
*
|
||||
* @param mixed[] $data
|
||||
*
|
||||
* @return array<array{title: string, value: string, short: false}>
|
||||
*/
|
||||
private function generateAttachmentFields(array $data): array
|
||||
{
|
||||
/** @var Record $data */
|
||||
$normalized = $this->normalizerFormatter->format($data);
|
||||
|
||||
$fields = array();
|
||||
foreach ($normalized as $key => $value) {
|
||||
$fields[] = $this->generateAttachmentField((string) $key, $value);
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a copy of record with fields excluded according to $this->excludeFields
|
||||
*
|
||||
* @phpstan-param FormattedRecord $record
|
||||
*
|
||||
* @return mixed[]
|
||||
*/
|
||||
private function removeExcludedFields(array $record): array
|
||||
{
|
||||
foreach ($this->excludeFields as $field) {
|
||||
$keys = explode('.', $field);
|
||||
$node = &$record;
|
||||
$lastKey = end($keys);
|
||||
foreach ($keys as $key) {
|
||||
if (!isset($node[$key])) {
|
||||
break;
|
||||
}
|
||||
if ($lastKey === $key) {
|
||||
unset($node[$key]);
|
||||
break;
|
||||
}
|
||||
$node = &$node[$key];
|
||||
}
|
||||
}
|
||||
|
||||
return $record;
|
||||
}
|
||||
}
|
||||
242
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php
vendored
Normal file
242
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php
vendored
Normal file
@@ -0,0 +1,242 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Monolog\Logger;
|
||||
use Monolog\Utils;
|
||||
use Monolog\Handler\Slack\SlackRecord;
|
||||
|
||||
/**
|
||||
* Sends notifications through Slack API
|
||||
*
|
||||
* @author Greg Kedzierski <greg@gregkedzierski.com>
|
||||
* @see https://api.slack.com/
|
||||
*
|
||||
* @phpstan-import-type FormattedRecord from AbstractProcessingHandler
|
||||
*/
|
||||
class SlackHandler extends SocketHandler
|
||||
{
|
||||
/**
|
||||
* Slack API token
|
||||
* @var string
|
||||
*/
|
||||
private $token;
|
||||
|
||||
/**
|
||||
* Instance of the SlackRecord util class preparing data for Slack API.
|
||||
* @var SlackRecord
|
||||
*/
|
||||
private $slackRecord;
|
||||
|
||||
/**
|
||||
* @param string $token Slack API token
|
||||
* @param string $channel Slack channel (encoded ID or name)
|
||||
* @param string|null $username Name of a bot
|
||||
* @param bool $useAttachment Whether the message should be added to Slack as attachment (plain text otherwise)
|
||||
* @param string|null $iconEmoji The emoji name to use (or null)
|
||||
* @param bool $useShortAttachment Whether the context/extra messages added to Slack as attachments are in a short style
|
||||
* @param bool $includeContextAndExtra Whether the attachment should include context and extra data
|
||||
* @param string[] $excludeFields Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2']
|
||||
* @throws MissingExtensionException If no OpenSSL PHP extension configured
|
||||
*/
|
||||
public function __construct(
|
||||
string $token,
|
||||
string $channel,
|
||||
?string $username = null,
|
||||
bool $useAttachment = true,
|
||||
?string $iconEmoji = null,
|
||||
$level = Logger::CRITICAL,
|
||||
bool $bubble = true,
|
||||
bool $useShortAttachment = false,
|
||||
bool $includeContextAndExtra = false,
|
||||
array $excludeFields = array()
|
||||
) {
|
||||
if (!extension_loaded('openssl')) {
|
||||
throw new MissingExtensionException('The OpenSSL PHP extension is required to use the SlackHandler');
|
||||
}
|
||||
|
||||
parent::__construct('ssl://slack.com:443', $level, $bubble);
|
||||
|
||||
$this->slackRecord = new SlackRecord(
|
||||
$channel,
|
||||
$username,
|
||||
$useAttachment,
|
||||
$iconEmoji,
|
||||
$useShortAttachment,
|
||||
$includeContextAndExtra,
|
||||
$excludeFields
|
||||
);
|
||||
|
||||
$this->token = $token;
|
||||
}
|
||||
|
||||
public function getSlackRecord(): SlackRecord
|
||||
{
|
||||
return $this->slackRecord;
|
||||
}
|
||||
|
||||
public function getToken(): string
|
||||
{
|
||||
return $this->token;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function generateDataStream(array $record): string
|
||||
{
|
||||
$content = $this->buildContent($record);
|
||||
|
||||
return $this->buildHeader($content) . $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the body of API call
|
||||
*
|
||||
* @phpstan-param FormattedRecord $record
|
||||
*/
|
||||
private function buildContent(array $record): string
|
||||
{
|
||||
$dataArray = $this->prepareContentData($record);
|
||||
|
||||
return http_build_query($dataArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param FormattedRecord $record
|
||||
* @return string[]
|
||||
*/
|
||||
protected function prepareContentData(array $record): array
|
||||
{
|
||||
$dataArray = $this->slackRecord->getSlackData($record);
|
||||
$dataArray['token'] = $this->token;
|
||||
|
||||
if (!empty($dataArray['attachments'])) {
|
||||
$dataArray['attachments'] = Utils::jsonEncode($dataArray['attachments']);
|
||||
}
|
||||
|
||||
return $dataArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the header of the API Call
|
||||
*/
|
||||
private function buildHeader(string $content): string
|
||||
{
|
||||
$header = "POST /api/chat.postMessage HTTP/1.1\r\n";
|
||||
$header .= "Host: slack.com\r\n";
|
||||
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
|
||||
$header .= "Content-Length: " . strlen($content) . "\r\n";
|
||||
$header .= "\r\n";
|
||||
|
||||
return $header;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
parent::write($record);
|
||||
$this->finalizeWrite();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalizes the request by reading some bytes and then closing the socket
|
||||
*
|
||||
* If we do not read some but close the socket too early, slack sometimes
|
||||
* drops the request entirely.
|
||||
*/
|
||||
protected function finalizeWrite(): void
|
||||
{
|
||||
$res = $this->getResource();
|
||||
if (is_resource($res)) {
|
||||
@fread($res, 2048);
|
||||
}
|
||||
$this->closeSocket();
|
||||
}
|
||||
|
||||
public function setFormatter(FormatterInterface $formatter): HandlerInterface
|
||||
{
|
||||
parent::setFormatter($formatter);
|
||||
$this->slackRecord->setFormatter($formatter);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFormatter(): FormatterInterface
|
||||
{
|
||||
$formatter = parent::getFormatter();
|
||||
$this->slackRecord->setFormatter($formatter);
|
||||
|
||||
return $formatter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel used by the bot when posting
|
||||
*/
|
||||
public function setChannel(string $channel): self
|
||||
{
|
||||
$this->slackRecord->setChannel($channel);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Username used by the bot when posting
|
||||
*/
|
||||
public function setUsername(string $username): self
|
||||
{
|
||||
$this->slackRecord->setUsername($username);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function useAttachment(bool $useAttachment): self
|
||||
{
|
||||
$this->slackRecord->useAttachment($useAttachment);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setIconEmoji(string $iconEmoji): self
|
||||
{
|
||||
$this->slackRecord->setUserIcon($iconEmoji);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function useShortAttachment(bool $useShortAttachment): self
|
||||
{
|
||||
$this->slackRecord->useShortAttachment($useShortAttachment);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function includeContextAndExtra(bool $includeContextAndExtra): self
|
||||
{
|
||||
$this->slackRecord->includeContextAndExtra($includeContextAndExtra);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $excludeFields
|
||||
*/
|
||||
public function excludeFields(array $excludeFields): self
|
||||
{
|
||||
$this->slackRecord->excludeFields($excludeFields);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
130
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php
vendored
Normal file
130
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Monolog\Logger;
|
||||
use Monolog\Utils;
|
||||
use Monolog\Handler\Slack\SlackRecord;
|
||||
|
||||
/**
|
||||
* Sends notifications through Slack Webhooks
|
||||
*
|
||||
* @author Haralan Dobrev <hkdobrev@gmail.com>
|
||||
* @see https://api.slack.com/incoming-webhooks
|
||||
*/
|
||||
class SlackWebhookHandler extends AbstractProcessingHandler
|
||||
{
|
||||
/**
|
||||
* Slack Webhook token
|
||||
* @var string
|
||||
*/
|
||||
private $webhookUrl;
|
||||
|
||||
/**
|
||||
* Instance of the SlackRecord util class preparing data for Slack API.
|
||||
* @var SlackRecord
|
||||
*/
|
||||
private $slackRecord;
|
||||
|
||||
/**
|
||||
* @param string $webhookUrl Slack Webhook URL
|
||||
* @param string|null $channel Slack channel (encoded ID or name)
|
||||
* @param string|null $username Name of a bot
|
||||
* @param bool $useAttachment Whether the message should be added to Slack as attachment (plain text otherwise)
|
||||
* @param string|null $iconEmoji The emoji name to use (or null)
|
||||
* @param bool $useShortAttachment Whether the the context/extra messages added to Slack as attachments are in a short style
|
||||
* @param bool $includeContextAndExtra Whether the attachment should include context and extra data
|
||||
* @param string[] $excludeFields Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2']
|
||||
*/
|
||||
public function __construct(
|
||||
string $webhookUrl,
|
||||
?string $channel = null,
|
||||
?string $username = null,
|
||||
bool $useAttachment = true,
|
||||
?string $iconEmoji = null,
|
||||
bool $useShortAttachment = false,
|
||||
bool $includeContextAndExtra = false,
|
||||
$level = Logger::CRITICAL,
|
||||
bool $bubble = true,
|
||||
array $excludeFields = array()
|
||||
) {
|
||||
if (!extension_loaded('curl')) {
|
||||
throw new MissingExtensionException('The curl extension is needed to use the SlackWebhookHandler');
|
||||
}
|
||||
|
||||
parent::__construct($level, $bubble);
|
||||
|
||||
$this->webhookUrl = $webhookUrl;
|
||||
|
||||
$this->slackRecord = new SlackRecord(
|
||||
$channel,
|
||||
$username,
|
||||
$useAttachment,
|
||||
$iconEmoji,
|
||||
$useShortAttachment,
|
||||
$includeContextAndExtra,
|
||||
$excludeFields
|
||||
);
|
||||
}
|
||||
|
||||
public function getSlackRecord(): SlackRecord
|
||||
{
|
||||
return $this->slackRecord;
|
||||
}
|
||||
|
||||
public function getWebhookUrl(): string
|
||||
{
|
||||
return $this->webhookUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
$postData = $this->slackRecord->getSlackData($record);
|
||||
$postString = Utils::jsonEncode($postData);
|
||||
|
||||
$ch = curl_init();
|
||||
$options = array(
|
||||
CURLOPT_URL => $this->webhookUrl,
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => array('Content-type: application/json'),
|
||||
CURLOPT_POSTFIELDS => $postString,
|
||||
);
|
||||
if (defined('CURLOPT_SAFE_UPLOAD')) {
|
||||
$options[CURLOPT_SAFE_UPLOAD] = true;
|
||||
}
|
||||
|
||||
curl_setopt_array($ch, $options);
|
||||
|
||||
Curl\Util::execute($ch);
|
||||
}
|
||||
|
||||
public function setFormatter(FormatterInterface $formatter): HandlerInterface
|
||||
{
|
||||
parent::setFormatter($formatter);
|
||||
$this->slackRecord->setFormatter($formatter);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFormatter(): FormatterInterface
|
||||
{
|
||||
$formatter = parent::getFormatter();
|
||||
$this->slackRecord->setFormatter($formatter);
|
||||
|
||||
return $formatter;
|
||||
}
|
||||
}
|
||||
421
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php
vendored
Normal file
421
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php
vendored
Normal file
@@ -0,0 +1,421 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* Stores to any socket - uses fsockopen() or pfsockopen().
|
||||
*
|
||||
* @author Pablo de Leon Belloc <pablolb@gmail.com>
|
||||
* @see http://php.net/manual/en/function.fsockopen.php
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
* @phpstan-import-type FormattedRecord from AbstractProcessingHandler
|
||||
*/
|
||||
class SocketHandler extends AbstractProcessingHandler
|
||||
{
|
||||
/** @var string */
|
||||
private $connectionString;
|
||||
/** @var float */
|
||||
private $connectionTimeout;
|
||||
/** @var resource|null */
|
||||
private $resource;
|
||||
/** @var float */
|
||||
private $timeout = 0.0;
|
||||
/** @var float */
|
||||
private $writingTimeout = 10.0;
|
||||
/** @var ?int */
|
||||
private $lastSentBytes = null;
|
||||
/** @var ?int */
|
||||
private $chunkSize = null;
|
||||
/** @var bool */
|
||||
private $persistent = false;
|
||||
/** @var ?int */
|
||||
private $errno = null;
|
||||
/** @var ?string */
|
||||
private $errstr = null;
|
||||
/** @var ?float */
|
||||
private $lastWritingAt = null;
|
||||
|
||||
/**
|
||||
* @param string $connectionString Socket connection string
|
||||
*/
|
||||
public function __construct(string $connectionString, $level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
parent::__construct($level, $bubble);
|
||||
$this->connectionString = $connectionString;
|
||||
$this->connectionTimeout = (float) ini_get('default_socket_timeout');
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect (if necessary) and write to the socket
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @throws \UnexpectedValueException
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
$this->connectIfNotConnected();
|
||||
$data = $this->generateDataStream($record);
|
||||
$this->writeToSocket($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* We will not close a PersistentSocket instance so it can be reused in other requests.
|
||||
*/
|
||||
public function close(): void
|
||||
{
|
||||
if (!$this->isPersistent()) {
|
||||
$this->closeSocket();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close socket, if open
|
||||
*/
|
||||
public function closeSocket(): void
|
||||
{
|
||||
if (is_resource($this->resource)) {
|
||||
fclose($this->resource);
|
||||
$this->resource = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set socket connection to be persistent. It only has effect before the connection is initiated.
|
||||
*/
|
||||
public function setPersistent(bool $persistent): self
|
||||
{
|
||||
$this->persistent = $persistent;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set connection timeout. Only has effect before we connect.
|
||||
*
|
||||
* @see http://php.net/manual/en/function.fsockopen.php
|
||||
*/
|
||||
public function setConnectionTimeout(float $seconds): self
|
||||
{
|
||||
$this->validateTimeout($seconds);
|
||||
$this->connectionTimeout = $seconds;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set write timeout. Only has effect before we connect.
|
||||
*
|
||||
* @see http://php.net/manual/en/function.stream-set-timeout.php
|
||||
*/
|
||||
public function setTimeout(float $seconds): self
|
||||
{
|
||||
$this->validateTimeout($seconds);
|
||||
$this->timeout = $seconds;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set writing timeout. Only has effect during connection in the writing cycle.
|
||||
*
|
||||
* @param float $seconds 0 for no timeout
|
||||
*/
|
||||
public function setWritingTimeout(float $seconds): self
|
||||
{
|
||||
$this->validateTimeout($seconds);
|
||||
$this->writingTimeout = $seconds;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set chunk size. Only has effect during connection in the writing cycle.
|
||||
*/
|
||||
public function setChunkSize(int $bytes): self
|
||||
{
|
||||
$this->chunkSize = $bytes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current connection string
|
||||
*/
|
||||
public function getConnectionString(): string
|
||||
{
|
||||
return $this->connectionString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get persistent setting
|
||||
*/
|
||||
public function isPersistent(): bool
|
||||
{
|
||||
return $this->persistent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current connection timeout setting
|
||||
*/
|
||||
public function getConnectionTimeout(): float
|
||||
{
|
||||
return $this->connectionTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current in-transfer timeout
|
||||
*/
|
||||
public function getTimeout(): float
|
||||
{
|
||||
return $this->timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current local writing timeout
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getWritingTimeout(): float
|
||||
{
|
||||
return $this->writingTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current chunk size
|
||||
*/
|
||||
public function getChunkSize(): ?int
|
||||
{
|
||||
return $this->chunkSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the socket is currently available.
|
||||
*
|
||||
* UDP might appear to be connected but might fail when writing. See http://php.net/fsockopen for details.
|
||||
*/
|
||||
public function isConnected(): bool
|
||||
{
|
||||
return is_resource($this->resource)
|
||||
&& !feof($this->resource); // on TCP - other party can close connection.
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper to allow mocking
|
||||
*
|
||||
* @return resource|false
|
||||
*/
|
||||
protected function pfsockopen()
|
||||
{
|
||||
return @pfsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper to allow mocking
|
||||
*
|
||||
* @return resource|false
|
||||
*/
|
||||
protected function fsockopen()
|
||||
{
|
||||
return @fsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper to allow mocking
|
||||
*
|
||||
* @see http://php.net/manual/en/function.stream-set-timeout.php
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function streamSetTimeout()
|
||||
{
|
||||
$seconds = floor($this->timeout);
|
||||
$microseconds = round(($this->timeout - $seconds) * 1e6);
|
||||
|
||||
if (!is_resource($this->resource)) {
|
||||
throw new \LogicException('streamSetTimeout called but $this->resource is not a resource');
|
||||
}
|
||||
|
||||
return stream_set_timeout($this->resource, (int) $seconds, (int) $microseconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper to allow mocking
|
||||
*
|
||||
* @see http://php.net/manual/en/function.stream-set-chunk-size.php
|
||||
*
|
||||
* @return int|bool
|
||||
*/
|
||||
protected function streamSetChunkSize()
|
||||
{
|
||||
if (!is_resource($this->resource)) {
|
||||
throw new \LogicException('streamSetChunkSize called but $this->resource is not a resource');
|
||||
}
|
||||
|
||||
if (null === $this->chunkSize) {
|
||||
throw new \LogicException('streamSetChunkSize called but $this->chunkSize is not set');
|
||||
}
|
||||
|
||||
return stream_set_chunk_size($this->resource, $this->chunkSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper to allow mocking
|
||||
*
|
||||
* @return int|bool
|
||||
*/
|
||||
protected function fwrite(string $data)
|
||||
{
|
||||
if (!is_resource($this->resource)) {
|
||||
throw new \LogicException('fwrite called but $this->resource is not a resource');
|
||||
}
|
||||
|
||||
return @fwrite($this->resource, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper to allow mocking
|
||||
*
|
||||
* @return mixed[]|bool
|
||||
*/
|
||||
protected function streamGetMetadata()
|
||||
{
|
||||
if (!is_resource($this->resource)) {
|
||||
throw new \LogicException('streamGetMetadata called but $this->resource is not a resource');
|
||||
}
|
||||
|
||||
return stream_get_meta_data($this->resource);
|
||||
}
|
||||
|
||||
private function validateTimeout(float $value): void
|
||||
{
|
||||
if ($value < 0) {
|
||||
throw new \InvalidArgumentException("Timeout must be 0 or a positive float (got $value)");
|
||||
}
|
||||
}
|
||||
|
||||
private function connectIfNotConnected(): void
|
||||
{
|
||||
if ($this->isConnected()) {
|
||||
return;
|
||||
}
|
||||
$this->connect();
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param FormattedRecord $record
|
||||
*/
|
||||
protected function generateDataStream(array $record): string
|
||||
{
|
||||
return (string) $record['formatted'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return resource|null
|
||||
*/
|
||||
protected function getResource()
|
||||
{
|
||||
return $this->resource;
|
||||
}
|
||||
|
||||
private function connect(): void
|
||||
{
|
||||
$this->createSocketResource();
|
||||
$this->setSocketTimeout();
|
||||
$this->setStreamChunkSize();
|
||||
}
|
||||
|
||||
private function createSocketResource(): void
|
||||
{
|
||||
if ($this->isPersistent()) {
|
||||
$resource = $this->pfsockopen();
|
||||
} else {
|
||||
$resource = $this->fsockopen();
|
||||
}
|
||||
if (is_bool($resource)) {
|
||||
throw new \UnexpectedValueException("Failed connecting to $this->connectionString ($this->errno: $this->errstr)");
|
||||
}
|
||||
$this->resource = $resource;
|
||||
}
|
||||
|
||||
private function setSocketTimeout(): void
|
||||
{
|
||||
if (!$this->streamSetTimeout()) {
|
||||
throw new \UnexpectedValueException("Failed setting timeout with stream_set_timeout()");
|
||||
}
|
||||
}
|
||||
|
||||
private function setStreamChunkSize(): void
|
||||
{
|
||||
if ($this->chunkSize && !$this->streamSetChunkSize()) {
|
||||
throw new \UnexpectedValueException("Failed setting chunk size with stream_set_chunk_size()");
|
||||
}
|
||||
}
|
||||
|
||||
private function writeToSocket(string $data): void
|
||||
{
|
||||
$length = strlen($data);
|
||||
$sent = 0;
|
||||
$this->lastSentBytes = $sent;
|
||||
while ($this->isConnected() && $sent < $length) {
|
||||
if (0 == $sent) {
|
||||
$chunk = $this->fwrite($data);
|
||||
} else {
|
||||
$chunk = $this->fwrite(substr($data, $sent));
|
||||
}
|
||||
if ($chunk === false) {
|
||||
throw new \RuntimeException("Could not write to socket");
|
||||
}
|
||||
$sent += $chunk;
|
||||
$socketInfo = $this->streamGetMetadata();
|
||||
if (is_array($socketInfo) && $socketInfo['timed_out']) {
|
||||
throw new \RuntimeException("Write timed-out");
|
||||
}
|
||||
|
||||
if ($this->writingIsTimedOut($sent)) {
|
||||
throw new \RuntimeException("Write timed-out, no data sent for `{$this->writingTimeout}` seconds, probably we got disconnected (sent $sent of $length)");
|
||||
}
|
||||
}
|
||||
if (!$this->isConnected() && $sent < $length) {
|
||||
throw new \RuntimeException("End-of-file reached, probably we got disconnected (sent $sent of $length)");
|
||||
}
|
||||
}
|
||||
|
||||
private function writingIsTimedOut(int $sent): bool
|
||||
{
|
||||
// convert to ms
|
||||
if (0.0 == $this->writingTimeout) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($sent !== $this->lastSentBytes) {
|
||||
$this->lastWritingAt = microtime(true);
|
||||
$this->lastSentBytes = $sent;
|
||||
|
||||
return false;
|
||||
} else {
|
||||
usleep(100);
|
||||
}
|
||||
|
||||
if ((microtime(true) - $this->lastWritingAt) >= $this->writingTimeout) {
|
||||
$this->closeSocket();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
62
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/SqsHandler.php
vendored
Normal file
62
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/SqsHandler.php
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
<?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;
|
||||
|
||||
use Aws\Sqs\SqsClient;
|
||||
use Monolog\Logger;
|
||||
use Monolog\Utils;
|
||||
|
||||
/**
|
||||
* Writes to any sqs queue.
|
||||
*
|
||||
* @author Martijn van Calker <git@amvc.nl>
|
||||
*/
|
||||
class SqsHandler extends AbstractProcessingHandler
|
||||
{
|
||||
/** 256 KB in bytes - maximum message size in SQS */
|
||||
protected const MAX_MESSAGE_SIZE = 262144;
|
||||
/** 100 KB in bytes - head message size for new error log */
|
||||
protected const HEAD_MESSAGE_SIZE = 102400;
|
||||
|
||||
/** @var SqsClient */
|
||||
private $client;
|
||||
/** @var string */
|
||||
private $queueUrl;
|
||||
|
||||
public function __construct(SqsClient $sqsClient, string $queueUrl, $level = Logger::DEBUG, bool $bubble = true)
|
||||
{
|
||||
parent::__construct($level, $bubble);
|
||||
|
||||
$this->client = $sqsClient;
|
||||
$this->queueUrl = $queueUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
if (!isset($record['formatted']) || 'string' !== gettype($record['formatted'])) {
|
||||
throw new \InvalidArgumentException('SqsHandler accepts only formatted records as a string');
|
||||
}
|
||||
|
||||
$messageBody = $record['formatted'];
|
||||
if (strlen($messageBody) >= static::MAX_MESSAGE_SIZE) {
|
||||
$messageBody = Utils::substr($messageBody, 0, static::HEAD_MESSAGE_SIZE);
|
||||
}
|
||||
|
||||
$this->client->sendMessage([
|
||||
'QueueUrl' => $this->queueUrl,
|
||||
'MessageBody' => $messageBody,
|
||||
]);
|
||||
}
|
||||
}
|
||||
221
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php
vendored
Normal file
221
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php
vendored
Normal file
@@ -0,0 +1,221 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\Utils;
|
||||
|
||||
/**
|
||||
* Stores to any stream resource
|
||||
*
|
||||
* Can be used to store into php://stderr, remote and local files, etc.
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* @phpstan-import-type FormattedRecord from AbstractProcessingHandler
|
||||
*/
|
||||
class StreamHandler extends AbstractProcessingHandler
|
||||
{
|
||||
/** @const int */
|
||||
protected const MAX_CHUNK_SIZE = 2147483647;
|
||||
/** @const int 10MB */
|
||||
protected const DEFAULT_CHUNK_SIZE = 10 * 1024 * 1024;
|
||||
/** @var int */
|
||||
protected $streamChunkSize;
|
||||
/** @var resource|null */
|
||||
protected $stream;
|
||||
/** @var ?string */
|
||||
protected $url = null;
|
||||
/** @var ?string */
|
||||
private $errorMessage = null;
|
||||
/** @var ?int */
|
||||
protected $filePermission;
|
||||
/** @var bool */
|
||||
protected $useLocking;
|
||||
/** @var true|null */
|
||||
private $dirCreated = null;
|
||||
|
||||
/**
|
||||
* @param resource|string $stream If a missing path can't be created, an UnexpectedValueException will be thrown on first write
|
||||
* @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write)
|
||||
* @param bool $useLocking Try to lock log file before doing any writes
|
||||
*
|
||||
* @throws \InvalidArgumentException If stream is not a resource or string
|
||||
*/
|
||||
public function __construct($stream, $level = Logger::DEBUG, bool $bubble = true, ?int $filePermission = null, bool $useLocking = false)
|
||||
{
|
||||
parent::__construct($level, $bubble);
|
||||
|
||||
if (($phpMemoryLimit = Utils::expandIniShorthandBytes(ini_get('memory_limit'))) !== false) {
|
||||
if ($phpMemoryLimit > 0) {
|
||||
// use max 10% of allowed memory for the chunk size, and at least 100KB
|
||||
$this->streamChunkSize = min(static::MAX_CHUNK_SIZE, max((int) ($phpMemoryLimit / 10), 100 * 1024));
|
||||
} else {
|
||||
// memory is unlimited, set to the default 10MB
|
||||
$this->streamChunkSize = static::DEFAULT_CHUNK_SIZE;
|
||||
}
|
||||
} else {
|
||||
// no memory limit information, set to the default 10MB
|
||||
$this->streamChunkSize = static::DEFAULT_CHUNK_SIZE;
|
||||
}
|
||||
|
||||
if (is_resource($stream)) {
|
||||
$this->stream = $stream;
|
||||
|
||||
stream_set_chunk_size($this->stream, $this->streamChunkSize);
|
||||
} elseif (is_string($stream)) {
|
||||
$this->url = Utils::canonicalizePath($stream);
|
||||
} else {
|
||||
throw new \InvalidArgumentException('A stream must either be a resource or a string.');
|
||||
}
|
||||
|
||||
$this->filePermission = $filePermission;
|
||||
$this->useLocking = $useLocking;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function close(): void
|
||||
{
|
||||
if ($this->url && is_resource($this->stream)) {
|
||||
fclose($this->stream);
|
||||
}
|
||||
$this->stream = null;
|
||||
$this->dirCreated = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the currently active stream if it is open
|
||||
*
|
||||
* @return resource|null
|
||||
*/
|
||||
public function getStream()
|
||||
{
|
||||
return $this->stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the stream URL if it was configured with a URL and not an active resource
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getUrl(): ?string
|
||||
{
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getStreamChunkSize(): int
|
||||
{
|
||||
return $this->streamChunkSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
if (!is_resource($this->stream)) {
|
||||
$url = $this->url;
|
||||
if (null === $url || '' === $url) {
|
||||
throw new \LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().');
|
||||
}
|
||||
$this->createDir($url);
|
||||
$this->errorMessage = null;
|
||||
set_error_handler([$this, 'customErrorHandler']);
|
||||
$stream = fopen($url, 'a');
|
||||
if ($this->filePermission !== null) {
|
||||
@chmod($url, $this->filePermission);
|
||||
}
|
||||
restore_error_handler();
|
||||
if (!is_resource($stream)) {
|
||||
$this->stream = null;
|
||||
|
||||
throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened in append mode: '.$this->errorMessage, $url));
|
||||
}
|
||||
stream_set_chunk_size($stream, $this->streamChunkSize);
|
||||
$this->stream = $stream;
|
||||
}
|
||||
|
||||
$stream = $this->stream;
|
||||
if (!is_resource($stream)) {
|
||||
throw new \LogicException('No stream was opened yet');
|
||||
}
|
||||
|
||||
if ($this->useLocking) {
|
||||
// ignoring errors here, there's not much we can do about them
|
||||
flock($stream, LOCK_EX);
|
||||
}
|
||||
|
||||
$this->streamWrite($stream, $record);
|
||||
|
||||
if ($this->useLocking) {
|
||||
flock($stream, LOCK_UN);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write to stream
|
||||
* @param resource $stream
|
||||
* @param array $record
|
||||
*
|
||||
* @phpstan-param FormattedRecord $record
|
||||
*/
|
||||
protected function streamWrite($stream, array $record): void
|
||||
{
|
||||
fwrite($stream, (string) $record['formatted']);
|
||||
}
|
||||
|
||||
private function customErrorHandler(int $code, string $msg): bool
|
||||
{
|
||||
$this->errorMessage = preg_replace('{^(fopen|mkdir)\(.*?\): }', '', $msg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function getDirFromStream(string $stream): ?string
|
||||
{
|
||||
$pos = strpos($stream, '://');
|
||||
if ($pos === false) {
|
||||
return dirname($stream);
|
||||
}
|
||||
|
||||
if ('file://' === substr($stream, 0, 7)) {
|
||||
return dirname(substr($stream, 7));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function createDir(string $url): void
|
||||
{
|
||||
// Do not try to create dir if it has already been tried.
|
||||
if ($this->dirCreated) {
|
||||
return;
|
||||
}
|
||||
|
||||
$dir = $this->getDirFromStream($url);
|
||||
if (null !== $dir && !is_dir($dir)) {
|
||||
$this->errorMessage = null;
|
||||
set_error_handler([$this, 'customErrorHandler']);
|
||||
$status = mkdir($dir, 0777, true);
|
||||
restore_error_handler();
|
||||
if (false === $status && !is_dir($dir)) {
|
||||
throw new \UnexpectedValueException(sprintf('There is no existing directory at "%s" and it could not be created: '.$this->errorMessage, $dir));
|
||||
}
|
||||
}
|
||||
$this->dirCreated = true;
|
||||
}
|
||||
}
|
||||
110
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php
vendored
Normal file
110
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
use Swift_Message;
|
||||
use Swift;
|
||||
|
||||
/**
|
||||
* SwiftMailerHandler uses Swift_Mailer to send the emails
|
||||
*
|
||||
* @author Gyula Sallai
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
*/
|
||||
class SwiftMailerHandler extends MailHandler
|
||||
{
|
||||
/** @var \Swift_Mailer */
|
||||
protected $mailer;
|
||||
/** @var Swift_Message|callable(string, Record[]): Swift_Message */
|
||||
private $messageTemplate;
|
||||
|
||||
/**
|
||||
* @psalm-param Swift_Message|callable(string, Record[]): Swift_Message $message
|
||||
*
|
||||
* @param \Swift_Mailer $mailer The mailer to use
|
||||
* @param callable|Swift_Message $message An example message for real messages, only the body will be replaced
|
||||
*/
|
||||
public function __construct(\Swift_Mailer $mailer, $message, $level = Logger::ERROR, bool $bubble = true)
|
||||
{
|
||||
parent::__construct($level, $bubble);
|
||||
|
||||
$this->mailer = $mailer;
|
||||
$this->messageTemplate = $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function send(string $content, array $records): void
|
||||
{
|
||||
$this->mailer->send($this->buildMessage($content, $records));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the formatter for the Swift_Message subject.
|
||||
*
|
||||
* @param string|null $format The format of the subject
|
||||
*/
|
||||
protected function getSubjectFormatter(?string $format): FormatterInterface
|
||||
{
|
||||
return new LineFormatter($format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates instance of Swift_Message to be sent
|
||||
*
|
||||
* @param string $content formatted email body to be sent
|
||||
* @param array $records Log records that formed the content
|
||||
* @return Swift_Message
|
||||
*
|
||||
* @phpstan-param Record[] $records
|
||||
*/
|
||||
protected function buildMessage(string $content, array $records): Swift_Message
|
||||
{
|
||||
$message = null;
|
||||
if ($this->messageTemplate instanceof Swift_Message) {
|
||||
$message = clone $this->messageTemplate;
|
||||
$message->generateId();
|
||||
} elseif (is_callable($this->messageTemplate)) {
|
||||
$message = ($this->messageTemplate)($content, $records);
|
||||
}
|
||||
|
||||
if (!$message instanceof Swift_Message) {
|
||||
throw new \InvalidArgumentException('Could not resolve message as instance of Swift_Message or a callable returning it');
|
||||
}
|
||||
|
||||
if ($records) {
|
||||
$subjectFormatter = $this->getSubjectFormatter($message->getSubject());
|
||||
$message->setSubject($subjectFormatter->format($this->getHighestRecord($records)));
|
||||
}
|
||||
|
||||
$mime = 'text/plain';
|
||||
if ($this->isHtmlBody($content)) {
|
||||
$mime = 'text/html';
|
||||
}
|
||||
|
||||
$message->setBody($content, $mime);
|
||||
/** @phpstan-ignore-next-line */
|
||||
if (version_compare(Swift::VERSION, '6.0.0', '>=')) {
|
||||
$message->setDate(new \DateTimeImmutable());
|
||||
} else {
|
||||
/** @phpstan-ignore-next-line */
|
||||
$message->setDate(time());
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
}
|
||||
67
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php
vendored
Normal file
67
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* Logs to syslog service.
|
||||
*
|
||||
* usage example:
|
||||
*
|
||||
* $log = new Logger('application');
|
||||
* $syslog = new SyslogHandler('myfacility', 'local6');
|
||||
* $formatter = new LineFormatter("%channel%.%level_name%: %message% %extra%");
|
||||
* $syslog->setFormatter($formatter);
|
||||
* $log->pushHandler($syslog);
|
||||
*
|
||||
* @author Sven Paulus <sven@karlsruhe.org>
|
||||
*/
|
||||
class SyslogHandler extends AbstractSyslogHandler
|
||||
{
|
||||
/** @var string */
|
||||
protected $ident;
|
||||
/** @var int */
|
||||
protected $logopts;
|
||||
|
||||
/**
|
||||
* @param string $ident
|
||||
* @param string|int $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant
|
||||
* @param int $logopts Option flags for the openlog() call, defaults to LOG_PID
|
||||
*/
|
||||
public function __construct(string $ident, $facility = LOG_USER, $level = Logger::DEBUG, bool $bubble = true, int $logopts = LOG_PID)
|
||||
{
|
||||
parent::__construct($facility, $level, $bubble);
|
||||
|
||||
$this->ident = $ident;
|
||||
$this->logopts = $logopts;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function close(): void
|
||||
{
|
||||
closelog();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
if (!openlog($this->ident, $this->logopts, $this->facility)) {
|
||||
throw new \LogicException('Can\'t open syslog for ident "'.$this->ident.'" and facility "'.$this->facility.'"');
|
||||
}
|
||||
syslog($this->logLevels[$record['level']], (string) $record['formatted']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?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\SyslogUdp;
|
||||
|
||||
use Monolog\Utils;
|
||||
use Socket;
|
||||
|
||||
class UdpSocket
|
||||
{
|
||||
protected const DATAGRAM_MAX_LENGTH = 65023;
|
||||
|
||||
/** @var string */
|
||||
protected $ip;
|
||||
/** @var int */
|
||||
protected $port;
|
||||
/** @var resource|Socket|null */
|
||||
protected $socket;
|
||||
|
||||
public function __construct(string $ip, int $port = 514)
|
||||
{
|
||||
$this->ip = $ip;
|
||||
$this->port = $port;
|
||||
$domain = AF_INET;
|
||||
$protocol = SOL_UDP;
|
||||
// Check if we are using unix sockets.
|
||||
if ($port === 0) {
|
||||
$domain = AF_UNIX;
|
||||
$protocol = IPPROTO_IP;
|
||||
}
|
||||
$this->socket = socket_create($domain, SOCK_DGRAM, $protocol) ?: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $line
|
||||
* @param string $header
|
||||
* @return void
|
||||
*/
|
||||
public function write($line, $header = "")
|
||||
{
|
||||
$this->send($this->assembleMessage($line, $header));
|
||||
}
|
||||
|
||||
public function close(): void
|
||||
{
|
||||
if (is_resource($this->socket) || $this->socket instanceof Socket) {
|
||||
socket_close($this->socket);
|
||||
$this->socket = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected function send(string $chunk): void
|
||||
{
|
||||
if (!is_resource($this->socket) && !$this->socket instanceof Socket) {
|
||||
throw new \RuntimeException('The UdpSocket to '.$this->ip.':'.$this->port.' has been closed and can not be written to anymore');
|
||||
}
|
||||
socket_sendto($this->socket, $chunk, strlen($chunk), $flags = 0, $this->ip, $this->port);
|
||||
}
|
||||
|
||||
protected function assembleMessage(string $line, string $header): string
|
||||
{
|
||||
$chunkSize = static::DATAGRAM_MAX_LENGTH - strlen($header);
|
||||
|
||||
return $header . Utils::substr($line, 0, $chunkSize);
|
||||
}
|
||||
}
|
||||
150
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php
vendored
Normal file
150
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
<?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;
|
||||
|
||||
use DateTimeInterface;
|
||||
use Monolog\Logger;
|
||||
use Monolog\Handler\SyslogUdp\UdpSocket;
|
||||
use Monolog\Utils;
|
||||
|
||||
/**
|
||||
* A Handler for logging to a remote syslogd server.
|
||||
*
|
||||
* @author Jesper Skovgaard Nielsen <nulpunkt@gmail.com>
|
||||
* @author Dominik Kukacka <dominik.kukacka@gmail.com>
|
||||
*/
|
||||
class SyslogUdpHandler extends AbstractSyslogHandler
|
||||
{
|
||||
const RFC3164 = 0;
|
||||
const RFC5424 = 1;
|
||||
const RFC5424e = 2;
|
||||
|
||||
/** @var array<self::RFC*, string> */
|
||||
private $dateFormats = array(
|
||||
self::RFC3164 => 'M d H:i:s',
|
||||
self::RFC5424 => \DateTime::RFC3339,
|
||||
self::RFC5424e => \DateTime::RFC3339_EXTENDED,
|
||||
);
|
||||
|
||||
/** @var UdpSocket */
|
||||
protected $socket;
|
||||
/** @var string */
|
||||
protected $ident;
|
||||
/** @var self::RFC* */
|
||||
protected $rfc;
|
||||
|
||||
/**
|
||||
* @param string $host Either IP/hostname or a path to a unix socket (port must be 0 then)
|
||||
* @param int $port Port number, or 0 if $host is a unix socket
|
||||
* @param string|int $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant
|
||||
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
|
||||
* @param string $ident Program name or tag for each log message.
|
||||
* @param int $rfc RFC to format the message for.
|
||||
* @throws MissingExtensionException
|
||||
*
|
||||
* @phpstan-param self::RFC* $rfc
|
||||
*/
|
||||
public function __construct(string $host, int $port = 514, $facility = LOG_USER, $level = Logger::DEBUG, bool $bubble = true, string $ident = 'php', int $rfc = self::RFC5424)
|
||||
{
|
||||
if (!extension_loaded('sockets')) {
|
||||
throw new MissingExtensionException('The sockets extension is required to use the SyslogUdpHandler');
|
||||
}
|
||||
|
||||
parent::__construct($facility, $level, $bubble);
|
||||
|
||||
$this->ident = $ident;
|
||||
$this->rfc = $rfc;
|
||||
|
||||
$this->socket = new UdpSocket($host, $port);
|
||||
}
|
||||
|
||||
protected function write(array $record): void
|
||||
{
|
||||
$lines = $this->splitMessageIntoLines($record['formatted']);
|
||||
|
||||
$header = $this->makeCommonSyslogHeader($this->logLevels[$record['level']], $record['datetime']);
|
||||
|
||||
foreach ($lines as $line) {
|
||||
$this->socket->write($line, $header);
|
||||
}
|
||||
}
|
||||
|
||||
public function close(): void
|
||||
{
|
||||
$this->socket->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|string[] $message
|
||||
* @return string[]
|
||||
*/
|
||||
private function splitMessageIntoLines($message): array
|
||||
{
|
||||
if (is_array($message)) {
|
||||
$message = implode("\n", $message);
|
||||
}
|
||||
|
||||
$lines = preg_split('/$\R?^/m', (string) $message, -1, PREG_SPLIT_NO_EMPTY);
|
||||
if (false === $lines) {
|
||||
$pcreErrorCode = preg_last_error();
|
||||
throw new \RuntimeException('Could not preg_split: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode));
|
||||
}
|
||||
|
||||
return $lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make common syslog header (see rfc5424 or rfc3164)
|
||||
*/
|
||||
protected function makeCommonSyslogHeader(int $severity, DateTimeInterface $datetime): string
|
||||
{
|
||||
$priority = $severity + $this->facility;
|
||||
|
||||
if (!$pid = getmypid()) {
|
||||
$pid = '-';
|
||||
}
|
||||
|
||||
if (!$hostname = gethostname()) {
|
||||
$hostname = '-';
|
||||
}
|
||||
|
||||
if ($this->rfc === self::RFC3164) {
|
||||
// see https://github.com/phpstan/phpstan/issues/5348
|
||||
// @phpstan-ignore-next-line
|
||||
$dateNew = $datetime->setTimezone(new \DateTimeZone('UTC'));
|
||||
$date = $dateNew->format($this->dateFormats[$this->rfc]);
|
||||
|
||||
return "<$priority>" .
|
||||
$date . " " .
|
||||
$hostname . " " .
|
||||
$this->ident . "[" . $pid . "]: ";
|
||||
}
|
||||
|
||||
$date = $datetime->format($this->dateFormats[$this->rfc]);
|
||||
|
||||
return "<$priority>1 " .
|
||||
$date . " " .
|
||||
$hostname . " " .
|
||||
$this->ident . " " .
|
||||
$pid . " - - ";
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject your own socket, mainly used for testing
|
||||
*/
|
||||
public function setSocket(UdpSocket $socket): self
|
||||
{
|
||||
$this->socket = $socket;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
194
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php
vendored
Normal file
194
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php
vendored
Normal file
@@ -0,0 +1,194 @@
|
||||
<?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;
|
||||
|
||||
use RuntimeException;
|
||||
use Monolog\Logger;
|
||||
|
||||
/**
|
||||
* Handler send logs to Telegram using Telegram Bot API.
|
||||
*
|
||||
* How to use:
|
||||
* 1) Create telegram bot with https://telegram.me/BotFather
|
||||
* 2) Create a telegram channel where logs will be recorded.
|
||||
* 3) Add created bot from step 1 to the created channel from step 2.
|
||||
*
|
||||
* Use telegram bot API key from step 1 and channel name with '@' prefix from step 2 to create instance of TelegramBotHandler
|
||||
*
|
||||
* @link https://core.telegram.org/bots/api
|
||||
*
|
||||
* @author Mazur Alexandr <alexandrmazur96@gmail.com>
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
*/
|
||||
class TelegramBotHandler extends AbstractProcessingHandler
|
||||
{
|
||||
private const BOT_API = 'https://api.telegram.org/bot';
|
||||
|
||||
/**
|
||||
* The available values of parseMode according to the Telegram api documentation
|
||||
*/
|
||||
private const AVAILABLE_PARSE_MODES = [
|
||||
'HTML',
|
||||
'MarkdownV2',
|
||||
'Markdown', // legacy mode without underline and strikethrough, use MarkdownV2 instead
|
||||
];
|
||||
|
||||
/**
|
||||
* Telegram bot access token provided by BotFather.
|
||||
* Create telegram bot with https://telegram.me/BotFather and use access token from it.
|
||||
* @var string
|
||||
*/
|
||||
private $apiKey;
|
||||
|
||||
/**
|
||||
* Telegram channel name.
|
||||
* Since to start with '@' symbol as prefix.
|
||||
* @var string
|
||||
*/
|
||||
private $channel;
|
||||
|
||||
/**
|
||||
* The kind of formatting that is used for the message.
|
||||
* See available options at https://core.telegram.org/bots/api#formatting-options
|
||||
* or in AVAILABLE_PARSE_MODES
|
||||
* @var ?string
|
||||
*/
|
||||
private $parseMode;
|
||||
|
||||
/**
|
||||
* Disables link previews for links in the message.
|
||||
* @var ?bool
|
||||
*/
|
||||
private $disableWebPagePreview;
|
||||
|
||||
/**
|
||||
* Sends the message silently. Users will receive a notification with no sound.
|
||||
* @var ?bool
|
||||
*/
|
||||
private $disableNotification;
|
||||
|
||||
/**
|
||||
* @param string $apiKey Telegram bot access token provided by BotFather
|
||||
* @param string $channel Telegram channel name
|
||||
*/
|
||||
public function __construct(
|
||||
string $apiKey,
|
||||
string $channel,
|
||||
$level = Logger::DEBUG,
|
||||
bool $bubble = true,
|
||||
string $parseMode = null,
|
||||
bool $disableWebPagePreview = null,
|
||||
bool $disableNotification = null
|
||||
) {
|
||||
if (!extension_loaded('curl')) {
|
||||
throw new MissingExtensionException('The curl extension is needed to use the TelegramBotHandler');
|
||||
}
|
||||
|
||||
parent::__construct($level, $bubble);
|
||||
|
||||
$this->apiKey = $apiKey;
|
||||
$this->channel = $channel;
|
||||
$this->setParseMode($parseMode);
|
||||
$this->disableWebPagePreview($disableWebPagePreview);
|
||||
$this->disableNotification($disableNotification);
|
||||
}
|
||||
|
||||
public function setParseMode(string $parseMode = null): self
|
||||
{
|
||||
if ($parseMode !== null && !in_array($parseMode, self::AVAILABLE_PARSE_MODES)) {
|
||||
throw new \InvalidArgumentException('Unknown parseMode, use one of these: ' . implode(', ', self::AVAILABLE_PARSE_MODES) . '.');
|
||||
}
|
||||
|
||||
$this->parseMode = $parseMode;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function disableWebPagePreview(bool $disableWebPagePreview = null): self
|
||||
{
|
||||
$this->disableWebPagePreview = $disableWebPagePreview;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function disableNotification(bool $disableNotification = null): self
|
||||
{
|
||||
$this->disableNotification = $disableNotification;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handleBatch(array $records): void
|
||||
{
|
||||
/** @var Record[] $messages */
|
||||
$messages = [];
|
||||
|
||||
foreach ($records as $record) {
|
||||
if (!$this->isHandling($record)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->processors) {
|
||||
/** @var Record $record */
|
||||
$record = $this->processRecord($record);
|
||||
}
|
||||
|
||||
$messages[] = $record;
|
||||
}
|
||||
|
||||
if (!empty($messages)) {
|
||||
$this->send((string) $this->getFormatter()->formatBatch($messages));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
$this->send($record['formatted']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send request to @link https://api.telegram.org/bot on SendMessage action.
|
||||
* @param string $message
|
||||
*/
|
||||
protected function send(string $message): void
|
||||
{
|
||||
$ch = curl_init();
|
||||
$url = self::BOT_API . $this->apiKey . '/SendMessage';
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
|
||||
'text' => $message,
|
||||
'chat_id' => $this->channel,
|
||||
'parse_mode' => $this->parseMode,
|
||||
'disable_web_page_preview' => $this->disableWebPagePreview,
|
||||
'disable_notification' => $this->disableNotification,
|
||||
]));
|
||||
|
||||
$result = Curl\Util::execute($ch);
|
||||
if (!is_string($result)) {
|
||||
throw new RuntimeException('Telegram API error. Description: No response');
|
||||
}
|
||||
$result = json_decode($result, true);
|
||||
|
||||
if ($result['ok'] === false) {
|
||||
throw new RuntimeException('Telegram API error. Description: ' . $result['description']);
|
||||
}
|
||||
}
|
||||
}
|
||||
231
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php
vendored
Normal file
231
wp-content/plugins/wp-optimize/vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php
vendored
Normal file
@@ -0,0 +1,231 @@
|
||||
<?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;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
* Used for testing purposes.
|
||||
*
|
||||
* It records all records and gives you access to them for verification.
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* @method bool hasEmergency($record)
|
||||
* @method bool hasAlert($record)
|
||||
* @method bool hasCritical($record)
|
||||
* @method bool hasError($record)
|
||||
* @method bool hasWarning($record)
|
||||
* @method bool hasNotice($record)
|
||||
* @method bool hasInfo($record)
|
||||
* @method bool hasDebug($record)
|
||||
*
|
||||
* @method bool hasEmergencyRecords()
|
||||
* @method bool hasAlertRecords()
|
||||
* @method bool hasCriticalRecords()
|
||||
* @method bool hasErrorRecords()
|
||||
* @method bool hasWarningRecords()
|
||||
* @method bool hasNoticeRecords()
|
||||
* @method bool hasInfoRecords()
|
||||
* @method bool hasDebugRecords()
|
||||
*
|
||||
* @method bool hasEmergencyThatContains($message)
|
||||
* @method bool hasAlertThatContains($message)
|
||||
* @method bool hasCriticalThatContains($message)
|
||||
* @method bool hasErrorThatContains($message)
|
||||
* @method bool hasWarningThatContains($message)
|
||||
* @method bool hasNoticeThatContains($message)
|
||||
* @method bool hasInfoThatContains($message)
|
||||
* @method bool hasDebugThatContains($message)
|
||||
*
|
||||
* @method bool hasEmergencyThatMatches($message)
|
||||
* @method bool hasAlertThatMatches($message)
|
||||
* @method bool hasCriticalThatMatches($message)
|
||||
* @method bool hasErrorThatMatches($message)
|
||||
* @method bool hasWarningThatMatches($message)
|
||||
* @method bool hasNoticeThatMatches($message)
|
||||
* @method bool hasInfoThatMatches($message)
|
||||
* @method bool hasDebugThatMatches($message)
|
||||
*
|
||||
* @method bool hasEmergencyThatPasses($message)
|
||||
* @method bool hasAlertThatPasses($message)
|
||||
* @method bool hasCriticalThatPasses($message)
|
||||
* @method bool hasErrorThatPasses($message)
|
||||
* @method bool hasWarningThatPasses($message)
|
||||
* @method bool hasNoticeThatPasses($message)
|
||||
* @method bool hasInfoThatPasses($message)
|
||||
* @method bool hasDebugThatPasses($message)
|
||||
*
|
||||
* @phpstan-import-type Record from \Monolog\Logger
|
||||
* @phpstan-import-type Level from \Monolog\Logger
|
||||
* @phpstan-import-type LevelName from \Monolog\Logger
|
||||
*/
|
||||
class TestHandler extends AbstractProcessingHandler
|
||||
{
|
||||
/** @var Record[] */
|
||||
protected $records = [];
|
||||
/** @var array<Level, Record[]> */
|
||||
protected $recordsByLevel = [];
|
||||
/** @var bool */
|
||||
private $skipReset = false;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*
|
||||
* @phpstan-return Record[]
|
||||
*/
|
||||
public function getRecords()
|
||||
{
|
||||
return $this->records;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->records = [];
|
||||
$this->recordsByLevel = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
if (!$this->skipReset) {
|
||||
$this->clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function setSkipReset(bool $skipReset)
|
||||
{
|
||||
$this->skipReset = $skipReset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|int $level Logging level value or name
|
||||
*
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $level
|
||||
*/
|
||||
public function hasRecords($level): bool
|
||||
{
|
||||
return isset($this->recordsByLevel[Logger::toMonologLevel($level)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|array $record Either a message string or an array containing message and optionally context keys that will be checked against all records
|
||||
* @param string|int $level Logging level value or name
|
||||
*
|
||||
* @phpstan-param array{message: string, context?: mixed[]}|string $record
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $level
|
||||
*/
|
||||
public function hasRecord($record, $level): bool
|
||||
{
|
||||
if (is_string($record)) {
|
||||
$record = array('message' => $record);
|
||||
}
|
||||
|
||||
return $this->hasRecordThatPasses(function ($rec) use ($record) {
|
||||
if ($rec['message'] !== $record['message']) {
|
||||
return false;
|
||||
}
|
||||
if (isset($record['context']) && $rec['context'] !== $record['context']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}, $level);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|int $level Logging level value or name
|
||||
*
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $level
|
||||
*/
|
||||
public function hasRecordThatContains(string $message, $level): bool
|
||||
{
|
||||
return $this->hasRecordThatPasses(function ($rec) use ($message) {
|
||||
return strpos($rec['message'], $message) !== false;
|
||||
}, $level);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|int $level Logging level value or name
|
||||
*
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $level
|
||||
*/
|
||||
public function hasRecordThatMatches(string $regex, $level): bool
|
||||
{
|
||||
return $this->hasRecordThatPasses(function (array $rec) use ($regex): bool {
|
||||
return preg_match($regex, $rec['message']) > 0;
|
||||
}, $level);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|int $level Logging level value or name
|
||||
* @return bool
|
||||
*
|
||||
* @psalm-param callable(Record, int): mixed $predicate
|
||||
* @phpstan-param Level|LevelName|LogLevel::* $level
|
||||
*/
|
||||
public function hasRecordThatPasses(callable $predicate, $level)
|
||||
{
|
||||
$level = Logger::toMonologLevel($level);
|
||||
|
||||
if (!isset($this->recordsByLevel[$level])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($this->recordsByLevel[$level] as $i => $rec) {
|
||||
if ($predicate($rec, $i)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function write(array $record): void
|
||||
{
|
||||
$this->recordsByLevel[$record['level']][] = $record;
|
||||
$this->records[] = $record;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $method
|
||||
* @param mixed[] $args
|
||||
* @return bool
|
||||
*/
|
||||
public function __call($method, $args)
|
||||
{
|
||||
if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) {
|
||||
$genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3];
|
||||
$level = constant('Monolog\Logger::' . strtoupper($matches[2]));
|
||||
$callback = [$this, $genericMethod];
|
||||
if (is_callable($callback)) {
|
||||
$args[] = $level;
|
||||
|
||||
return call_user_func_array($callback, $args);
|
||||
}
|
||||
}
|
||||
|
||||
throw new \BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?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;
|
||||
|
||||
trait WebRequestRecognizerTrait
|
||||
{
|
||||
/**
|
||||
* Checks if PHP's serving a web request
|
||||
* @return bool
|
||||
*/
|
||||
protected function isWebRequest(): bool
|
||||
{
|
||||
return 'cli' !== \PHP_SAPI && 'phpdbg' !== \PHP_SAPI;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user