• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

The-oGlow / ezlogging / 27499980323

14 Jun 2026 01:13PM UTC coverage: 80.247% (-15.3%) from 95.506%
27499980323

push

github

web-flow
Merge pull request #20 from The-oGlow/develop

Switch to Monolog 3

83 of 125 new or added lines in 12 files covered. (66.4%)

4 existing lines in 2 files now uncovered.

195 of 243 relevant lines covered (80.25%)

18.58 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.71
/src/Monolog/Processor/PaddingProcessor.php
1
<?php
2

3
declare(strict_types=1);
4

5
/*
6
 * This file is part of ezlogging
7
 *
8
 * (c) 2025 Oliver Glowa, coding.glowa.com
9
 *
10
 * This source file is subject to the Apache-2.0 license that is bundled
11
 * with this source code in the file LICENSE.
12
 */
13

14
namespace Monolog\Processor;
15

16
use Monolog\Level;
17
use Monolog\Logger;
18
use Monolog\LogRecord;
19

20
/**
21
 * Class PaddingProcessor.
22
 *
23
 * Use Introspection from @see IntrospectionProcessor.
24
 *
25
 * @phpstan-type LoggingLevel value-of<\Monolog\Level>|\Monolog\Level|\Psr\Log\LogLevel::*
26
 *
27
 * @see     IntrospectionProcessor
28
 */
29
class PaddingProcessor implements ProcessorInterface
30
{
31
    public const string OFFSET_EXTRA = 'extra';
32

33
    public const string OFFSET_LEVEL_NAME_PAD = 'level_name_pad';
34

35
    public const string OFFSET_LEVEL_NAME = 'level_name';
36

37
    public const string OFFSET_LEVEL = 'level';
38

39
    public const string OFFSET_XDETAILS = 'xdetails';
40

41
    public const int LEVEL_WIDTH = 8;
42

43
    public const string LEVEL_CHAR = ' ';
44

45
    /** @var array<string> */
46
    protected const array SKIP_FUNCTIONS = [
47
        'call_user_func',
48
        'call_user_func_array',
49
    ];
50

51
    /** @var array<string> */
52
    protected const array SKIP_CLASSES = [
53
        'Monolog\\',
54
    ];
55

56
    private Level $level;
57

58
    /** @var array<string> */
59
    private array $skipClassesPartials;
60

61
    private int $skipStackFramesCount;
62

63
    /**
64
     * @param int|\Monolog\Level|\Psr\Log\LogLevel::*|string $level                The minimum logging level at which this handler will be triggered
65
     * @param string[]                                       $skipClassesPartials
66
     * @param int                                            $skipStackFramesCount
67
     *
68
     * @phpstan-param LoggingLevel $level
69
     */
70
    public function __construct(int|string|Level $level = Level::Debug, array $skipClassesPartials = [], int $skipStackFramesCount = 0)
22✔
71
    {
72
        /** @psalm-suppress PossiblyInvalidArgument  */
73
        $this->level = Logger::toMonologLevel($level);
22✔
74
        $this->skipClassesPartials = array_merge(static::SKIP_CLASSES, $skipClassesPartials);
22✔
75
        $this->skipStackFramesCount = $skipStackFramesCount;
22✔
76
    }
77

78
    /**
79
     * @param LogRecord $record A record
80
     *
81
     * @return LogRecord The processed record
82
     */
83
    #[\Override]
84
    public function __invoke(LogRecord $record): LogRecord
3✔
85
    {
86
        // return if the level is not high enough
87
        if ($record->level->isLowerThan($this->level)) {
3✔
NEW
88
            return $record;
×
89
        }
90

91
        /** @var array<mixed,mixed> */
92
        $extra = $record[self::OFFSET_EXTRA];
3✔
93

94
        /** @var string $levelName */
95
        $levelName = $record[self::OFFSET_LEVEL_NAME];
3✔
96
        $extra[self::OFFSET_LEVEL_NAME_PAD] = str_pad($levelName, self::LEVEL_WIDTH, self::LEVEL_CHAR, STR_PAD_RIGHT);
3✔
97
        $record->offsetSet(self::OFFSET_EXTRA, $extra);
3✔
98

99
        return $this->__invokeIntrospection($record);
3✔
100
    }
101

102
    private function __invokeIntrospection(LogRecord $record): LogRecord
3✔
103
    {
104
        // return if the level is not high enough
105
        if ($record->level->isLowerThan($this->level)) {
3✔
UNCOV
106
            return $record;
×
107
        }
108

109
        $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
3✔
110

111
        // skip first since it's always the current method
112
        array_shift($trace);
3✔
113
        // the call_user_func call is also skipped
114
        array_shift($trace);
3✔
115

116
        $index = 0;
3✔
117

118
        while ($this->isTraceClassOrSkippedFunction($trace, $index)) {
3✔
119
            if (isset($trace[$index]['class'])) {
3✔
120
                foreach ($this->skipClassesPartials as $part) {
3✔
121
                    if (str_contains($trace[$index]['class'], $part)) {
3✔
122
                        $index++;
3✔
123

124
                        continue 2;
3✔
125
                    }
126
                }
NEW
127
            } elseif (in_array($trace[$index]['function'], static::SKIP_FUNCTIONS, true)) {
×
UNCOV
128
                $index++;
×
129

130
                continue;
×
131
            } else {
132
                break;
×
133
            }
134
            break;
3✔
135
        }
136

137
        $index += $this->skipStackFramesCount;
3✔
138

139
        // we should have the call source now
140
        if ($index > 0 && $index < count($trace)) {
3✔
141
            $curTrace  = $trace[$index];
3✔
142
            $prevTrace = $trace[$index - 1];
3✔
143

144
            $record->extra = array_merge(
3✔
145
                $record->extra,
3✔
146
                [
3✔
147
                    'xFile'     => $prevTrace['file'] ?? null,
3✔
148
                    'xLine'     => $prevTrace['line'] ?? null,
3✔
149
                    'xClass'    => $curTrace['class'] ?? null,
3✔
150
                    'xCallType' => $curTrace['type'] ?? null,
3✔
151
                    'xFunction' => $curTrace['function'],
3✔
152
                ]
3✔
153
            );
3✔
154
        }
155

156
        return $record;
3✔
157
    }
158

159
    /**
160
     * @param array<mixed,mixed> $trace
161
     * @param int                $index
162
     *
163
     * @return bool
164
     */
165
    private function isTraceClassOrSkippedFunction(array $trace, int $index): bool
3✔
166
    {
167
        if (!isset($trace[$index])) {
3✔
UNCOV
168
            return false;
×
169
        }
170

171
        return isset($trace[$index]['class']) || \in_array($trace[$index]['function'], static::SKIP_FUNCTIONS, true);
3✔
172
    }
173
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc