]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blobdiff - vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php
MediaWiki 1.30.2
[autoinstallsdev/mediawiki.git] / vendor / monolog / monolog / src / Monolog / Formatter / JsonFormatter.php
diff --git a/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php b/vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php
new file mode 100644 (file)
index 0000000..4b2be77
--- /dev/null
@@ -0,0 +1,206 @@
+<?php
+
+/*
+ * 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 Exception;
+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>
+ */
+class JsonFormatter extends NormalizerFormatter
+{
+    const BATCH_MODE_JSON = 1;
+    const BATCH_MODE_NEWLINES = 2;
+
+    protected $batchMode;
+    protected $appendNewline;
+    /**
+     * @var bool
+     */
+    protected $includeStacktraces = false;
+
+    /**
+     * @param int $batchMode
+     */
+    public function __construct($batchMode = self::BATCH_MODE_JSON, $appendNewline = true)
+    {
+        $this->batchMode = $batchMode;
+        $this->appendNewline = $appendNewline;
+    }
+
+    /**
+     * 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.
+     *
+     * @return int
+     */
+    public function getBatchMode()
+    {
+        return $this->batchMode;
+    }
+
+    /**
+     * True if newlines are appended to every formatted record
+     *
+     * @return bool
+     */
+    public function isAppendingNewlines()
+    {
+        return $this->appendNewline;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function format(array $record)
+    {
+        return $this->toJson($this->normalize($record), true) . ($this->appendNewline ? "\n" : '');
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function formatBatch(array $records)
+    {
+        switch ($this->batchMode) {
+            case static::BATCH_MODE_NEWLINES:
+                return $this->formatBatchNewlines($records);
+
+            case static::BATCH_MODE_JSON:
+            default:
+                return $this->formatBatchJson($records);
+        }
+    }
+
+    /**
+     * @param bool $include
+     */
+    public function includeStacktraces($include = true)
+    {
+        $this->includeStacktraces = $include;
+    }
+
+    /**
+     * Return a JSON-encoded array of records.
+     *
+     * @param  array  $records
+     * @return string
+     */
+    protected function formatBatchJson(array $records)
+    {
+        return $this->toJson($this->normalize($records), true);
+    }
+
+    /**
+     * Use new lines to separate records instead of a
+     * JSON-encoded array.
+     *
+     * @param  array  $records
+     * @return string
+     */
+    protected function formatBatchNewlines(array $records)
+    {
+        $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)
+    {
+        if (is_array($data) || $data instanceof \Traversable) {
+            $normalized = array();
+
+            $count = 1;
+            foreach ($data as $key => $value) {
+                if ($count++ >= 1000) {
+                    $normalized['...'] = 'Over 1000 items, aborting normalization';
+                    break;
+                }
+                $normalized[$key] = $this->normalize($value);
+            }
+
+            return $normalized;
+        }
+
+        if ($data instanceof Exception || $data instanceof Throwable) {
+            return $this->normalizeException($data);
+        }
+
+        return $data;
+    }
+
+    /**
+     * Normalizes given exception with or without its own stack trace based on
+     * `includeStacktraces` property.
+     *
+     * @param Exception|Throwable $e
+     *
+     * @return array
+     */
+    protected function normalizeException($e)
+    {
+        // TODO 2.0 only check for Throwable
+        if (!$e instanceof Exception && !$e instanceof Throwable) {
+            throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.get_class($e));
+        }
+
+        $data = array(
+            'class' => get_class($e),
+            'message' => $e->getMessage(),
+            'code' => $e->getCode(),
+            'file' => $e->getFile().':'.$e->getLine(),
+        );
+
+        if ($this->includeStacktraces) {
+            $trace = $e->getTrace();
+            foreach ($trace as $frame) {
+                if (isset($frame['file'])) {
+                    $data['trace'][] = $frame['file'].':'.$frame['line'];
+                } elseif (isset($frame['function']) && $frame['function'] === '{closure}') {
+                    // We should again normalize the frames, because it might contain invalid items
+                    $data['trace'][] = $frame['function'];
+                } else {
+                    // We should again normalize the frames, because it might contain invalid items
+                    $data['trace'][] = $this->normalize($frame);
+                }
+            }
+        }
+
+        if ($previous = $e->getPrevious()) {
+            $data['previous'] = $this->normalizeException($previous);
+        }
+
+        return $data;
+    }
+}