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

The-oGlow / ezlogging / 35971183203

24 Sep 2026 07:43AM UTC coverage: 80.247%. Remained the same
35971183203

push

github

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

small bugfix

1 of 1 new or added line in 1 file covered. (100.0%)

47 existing lines in 3 files now uncovered.

195 of 243 relevant lines covered (80.25%)

19.89 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
     *                                                                             (Default: {@link Level::Debug})
66
     * @param string[]                                       $skipClassesPartials
67
     * @param int                                            $skipStackFramesCount
68
     *
69
     * @phpstan-param LoggingLevel $level
70
     */
71
    public function __construct(int|string|Level $level = Level::Debug, array $skipClassesPartials = [], int $skipStackFramesCount = 0)
22✔
72
    {
73
        /** @psalm-suppress PossiblyInvalidArgument  */
74
        $this->level = Logger::toMonologLevel($level);
22✔
75
        $this->skipClassesPartials = array_merge(static::SKIP_CLASSES, $skipClassesPartials);
22✔
76
        $this->skipStackFramesCount = $skipStackFramesCount;
22✔
77
    }
78

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

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

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

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

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

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

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

117
        $index = 0;
3✔
118

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

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

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

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

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

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

157
        return $record;
3✔
158
    }
159

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

172
        return isset($trace[$index]['class']) || \in_array($trace[$index]['function'], static::SKIP_FUNCTIONS, true);
3✔
173
    }
174
}
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