Subversion-Projekte lars-tiefland.laravel_shop

Revision

Zur aktuellen Revision | Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
/*
4
 * This file is part of the Symfony package.
5
 *
6
 * (c) Fabien Potencier <fabien@symfony.com>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
 
12
namespace Symfony\Component\HttpKernel\Profiler;
13
 
14
use Psr\Log\LoggerInterface;
15
use Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException;
16
use Symfony\Component\HttpFoundation\Request;
17
use Symfony\Component\HttpFoundation\Response;
18
use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface;
19
use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
20
use Symfony\Contracts\Service\ResetInterface;
21
 
22
/**
23
 * Profiler.
24
 *
25
 * @author Fabien Potencier <fabien@symfony.com>
26
 */
27
class Profiler implements ResetInterface
28
{
29
    private ProfilerStorageInterface $storage;
30
 
31
    /**
32
     * @var DataCollectorInterface[]
33
     */
34
    private array $collectors = [];
35
 
36
    private ?LoggerInterface $logger;
37
    private bool $initiallyEnabled = true;
38
    private bool $enabled = true;
39
 
40
    public function __construct(ProfilerStorageInterface $storage, LoggerInterface $logger = null, bool $enable = true)
41
    {
42
        $this->storage = $storage;
43
        $this->logger = $logger;
44
        $this->initiallyEnabled = $this->enabled = $enable;
45
    }
46
 
47
    /**
48
     * Disables the profiler.
49
     */
50
    public function disable()
51
    {
52
        $this->enabled = false;
53
    }
54
 
55
    /**
56
     * Enables the profiler.
57
     */
58
    public function enable()
59
    {
60
        $this->enabled = true;
61
    }
62
 
63
    public function isEnabled(): bool
64
    {
65
        return $this->enabled;
66
    }
67
 
68
    /**
69
     * Loads the Profile for the given Response.
70
     */
71
    public function loadProfileFromResponse(Response $response): ?Profile
72
    {
73
        if (!$token = $response->headers->get('X-Debug-Token')) {
74
            return null;
75
        }
76
 
77
        return $this->loadProfile($token);
78
    }
79
 
80
    /**
81
     * Loads the Profile for the given token.
82
     */
83
    public function loadProfile(string $token): ?Profile
84
    {
85
        return $this->storage->read($token);
86
    }
87
 
88
    /**
89
     * Saves a Profile.
90
     */
91
    public function saveProfile(Profile $profile): bool
92
    {
93
        // late collect
94
        foreach ($profile->getCollectors() as $collector) {
95
            if ($collector instanceof LateDataCollectorInterface) {
96
                $collector->lateCollect();
97
            }
98
        }
99
 
100
        if (!($ret = $this->storage->write($profile)) && null !== $this->logger) {
101
            $this->logger->warning('Unable to store the profiler information.', ['configured_storage' => \get_class($this->storage)]);
102
        }
103
 
104
        return $ret;
105
    }
106
 
107
    /**
108
     * Purges all data from the storage.
109
     */
110
    public function purge()
111
    {
112
        $this->storage->purge();
113
    }
114
 
115
    /**
116
     * Finds profiler tokens for the given criteria.
117
     *
118
     * @param string|null $limit The maximum number of tokens to return
119
     * @param string|null $start The start date to search from
120
     * @param string|null $end   The end date to search to
121
     *
122
     * @see https://php.net/datetime.formats for the supported date/time formats
123
     */
124
    public function find(?string $ip, ?string $url, ?string $limit, ?string $method, ?string $start, ?string $end, string $statusCode = null): array
125
    {
126
        return $this->storage->find($ip, $url, $limit, $method, $this->getTimestamp($start), $this->getTimestamp($end), $statusCode);
127
    }
128
 
129
    /**
130
     * Collects data for the given Response.
131
     */
132
    public function collect(Request $request, Response $response, \Throwable $exception = null): ?Profile
133
    {
134
        if (false === $this->enabled) {
135
            return null;
136
        }
137
 
138
        $profile = new Profile(substr(hash('sha256', uniqid(mt_rand(), true)), 0, 6));
139
        $profile->setTime(time());
140
        $profile->setUrl($request->getUri());
141
        $profile->setMethod($request->getMethod());
142
        $profile->setStatusCode($response->getStatusCode());
143
        try {
144
            $profile->setIp($request->getClientIp());
145
        } catch (ConflictingHeadersException) {
146
            $profile->setIp('Unknown');
147
        }
148
 
149
        if ($prevToken = $response->headers->get('X-Debug-Token')) {
150
            $response->headers->set('X-Previous-Debug-Token', $prevToken);
151
        }
152
 
153
        $response->headers->set('X-Debug-Token', $profile->getToken());
154
 
155
        foreach ($this->collectors as $collector) {
156
            $collector->collect($request, $response, $exception);
157
 
158
            // we need to clone for sub-requests
159
            $profile->addCollector(clone $collector);
160
        }
161
 
162
        return $profile;
163
    }
164
 
165
    public function reset()
166
    {
167
        foreach ($this->collectors as $collector) {
168
            $collector->reset();
169
        }
170
        $this->enabled = $this->initiallyEnabled;
171
    }
172
 
173
    /**
174
     * Gets the Collectors associated with this profiler.
175
     */
176
    public function all(): array
177
    {
178
        return $this->collectors;
179
    }
180
 
181
    /**
182
     * Sets the Collectors associated with this profiler.
183
     *
184
     * @param DataCollectorInterface[] $collectors An array of collectors
185
     */
186
    public function set(array $collectors = [])
187
    {
188
        $this->collectors = [];
189
        foreach ($collectors as $collector) {
190
            $this->add($collector);
191
        }
192
    }
193
 
194
    /**
195
     * Adds a Collector.
196
     */
197
    public function add(DataCollectorInterface $collector)
198
    {
199
        $this->collectors[$collector->getName()] = $collector;
200
    }
201
 
202
    /**
203
     * Returns true if a Collector for the given name exists.
204
     *
205
     * @param string $name A collector name
206
     */
207
    public function has(string $name): bool
208
    {
209
        return isset($this->collectors[$name]);
210
    }
211
 
212
    /**
213
     * Gets a Collector by name.
214
     *
215
     * @param string $name A collector name
216
     *
217
     * @throws \InvalidArgumentException if the collector does not exist
218
     */
219
    public function get(string $name): DataCollectorInterface
220
    {
221
        if (!isset($this->collectors[$name])) {
222
            throw new \InvalidArgumentException(sprintf('Collector "%s" does not exist.', $name));
223
        }
224
 
225
        return $this->collectors[$name];
226
    }
227
 
228
    private function getTimestamp(?string $value): ?int
229
    {
230
        if (null === $value || '' === $value) {
231
            return null;
232
        }
233
 
234
        try {
235
            $value = new \DateTimeImmutable(is_numeric($value) ? '@'.$value : $value);
236
        } catch (\Exception) {
237
            return null;
238
        }
239
 
240
        return $value->getTimestamp();
241
    }
242
}