Skip to content

Commit bd09259

Browse files
cleptricstayallive
andauthored
Add Sentry logs (#1813)
Co-authored-by: Alex Bouma <[email protected]>
1 parent 18b57e0 commit bd09259

28 files changed

+1429
-42
lines changed

phpstan-baseline.neon

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,7 @@ parameters:
5353
-
5454
message: "#^Parameter \\#2 \\.\\.\\.\\$values of function sprintf expects bool\\|float\\|int\\|string\\|null, mixed given\\.$#"
5555
count: 1
56-
path: src/Logger/DebugFileLogger.php
57-
58-
-
59-
message: "#^Parameter \\#2 \\.\\.\\.\\$values of function sprintf expects bool\\|float\\|int\\|string\\|null, mixed given\\.$#"
60-
count: 1
61-
path: src/Logger/DebugStdOutLogger.php
56+
path: src/Logger/DebugLogger.php
6257

6358
-
6459
message: "#^Parameter \\#1 \\$level of method Monolog\\\\Handler\\\\AbstractHandler\\:\\:__construct\\(\\) expects 100\\|200\\|250\\|300\\|400\\|500\\|550\\|600\\|'ALERT'\\|'alert'\\|'CRITICAL'\\|'critical'\\|'DEBUG'\\|'debug'\\|'EMERGENCY'\\|'emergency'\\|'ERROR'\\|'error'\\|'INFO'\\|'info'\\|'NOTICE'\\|'notice'\\|'WARNING'\\|'warning'\\|Monolog\\\\Level, int\\|Monolog\\\\Level\\|string given\\.$#"
@@ -80,6 +75,11 @@ parameters:
8075
count: 1
8176
path: src/Options.php
8277

78+
-
79+
message: "#^Method Sentry\\\\Options\\:\\:getBeforeSendLogCallback\\(\\) should return callable\\(Sentry\\\\Logs\\\\Log\\)\\: \\(Sentry\\\\Logs\\\\Log\\|null\\) but returns mixed\\.$#"
80+
count: 1
81+
path: src/Options.php
82+
8383
-
8484
message: "#^Method Sentry\\\\Options\\:\\:getBeforeSendMetricsCallback\\(\\) should return callable\\(Sentry\\\\Event, Sentry\\\\EventHint\\|null\\)\\: \\(Sentry\\\\Event\\|null\\) but returns mixed\\.$#"
8585
count: 1
@@ -105,6 +105,11 @@ parameters:
105105
count: 1
106106
path: src/Options.php
107107

108+
-
109+
message: "#^Method Sentry\\\\Options\\:\\:getEnableLogs\\(\\) should return bool but returns mixed\\.$#"
110+
count: 1
111+
path: src/Options.php
112+
108113
-
109114
message: "#^Method Sentry\\\\Options\\:\\:getEnableTracing\\(\\) should return bool\\|null but returns mixed\\.$#"
110115
count: 1

src/Attributes/Attribute.php

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sentry\Attributes;
6+
7+
/**
8+
* @phpstan-type AttributeType 'string'|'boolean'|'integer'|'double'
9+
* @phpstan-type AttributeValue string|bool|int|float
10+
* @phpstan-type AttributeSerialized array{
11+
* type: AttributeType,
12+
* value: AttributeValue
13+
* }
14+
*/
15+
class Attribute implements \JsonSerializable
16+
{
17+
/**
18+
* @var AttributeType
19+
*/
20+
private $type;
21+
22+
/**
23+
* @var AttributeValue
24+
*/
25+
private $value;
26+
27+
/**
28+
* @param AttributeValue $value
29+
* @param AttributeType $type
30+
*/
31+
public function __construct($value, string $type)
32+
{
33+
$this->value = $value;
34+
$this->type = $type;
35+
}
36+
37+
/**
38+
* @return AttributeType
39+
*/
40+
public function getType(): string
41+
{
42+
return $this->type;
43+
}
44+
45+
/**
46+
* @return AttributeValue
47+
*/
48+
public function getValue()
49+
{
50+
return $this->value;
51+
}
52+
53+
/**
54+
* @param mixed $value
55+
*
56+
* @throws \InvalidArgumentException thrown when the value cannot be serialized as an attribute
57+
*/
58+
public static function fromValue($value): self
59+
{
60+
$attribute = self::tryFromValue($value);
61+
62+
if ($attribute === null) {
63+
throw new \InvalidArgumentException(\sprintf('Invalid attribute value, %s cannot be serialized', \gettype($value)));
64+
}
65+
66+
return $attribute;
67+
}
68+
69+
/**
70+
* @param mixed $value
71+
*/
72+
public static function tryFromValue($value): ?self
73+
{
74+
if ($value === null) {
75+
return null;
76+
}
77+
78+
if (\is_bool($value)) {
79+
return new self($value, 'boolean');
80+
}
81+
82+
if (\is_int($value)) {
83+
return new self($value, 'integer');
84+
}
85+
86+
if (\is_float($value)) {
87+
return new self($value, 'double');
88+
}
89+
90+
if (\is_string($value) || (\is_object($value) && method_exists($value, '__toString'))) {
91+
$stringValue = (string) $value;
92+
93+
if (empty($stringValue)) {
94+
return null;
95+
}
96+
97+
return new self($stringValue, 'string');
98+
}
99+
100+
return null;
101+
}
102+
103+
/**
104+
* @return AttributeSerialized
105+
*/
106+
public function toArray(): array
107+
{
108+
return [
109+
'type' => $this->type,
110+
'value' => $this->value,
111+
];
112+
}
113+
114+
/**
115+
* @return AttributeSerialized
116+
*/
117+
public function jsonSerialize(): array
118+
{
119+
return $this->toArray();
120+
}
121+
122+
public function __toString(): string
123+
{
124+
return "{$this->value} ({$this->type})";
125+
}
126+
}

src/Attributes/AttributeBag.php

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sentry\Attributes;
6+
7+
/**
8+
* @phpstan-import-type AttributeValue from Attribute
9+
* @phpstan-import-type AttributeSerialized from Attribute
10+
*/
11+
class AttributeBag implements \JsonSerializable
12+
{
13+
/**
14+
* @var array<string, Attribute>
15+
*/
16+
private $attributes = [];
17+
18+
/**
19+
* @param mixed $value
20+
*/
21+
public function set(string $key, $value): self
22+
{
23+
$attribute = $value instanceof Attribute
24+
? $value
25+
: Attribute::tryFromValue($value);
26+
27+
if ($attribute !== null) {
28+
$this->attributes[$key] = $attribute;
29+
}
30+
31+
return $this;
32+
}
33+
34+
public function get(string $key): ?Attribute
35+
{
36+
return $this->attributes[$key] ?? null;
37+
}
38+
39+
/**
40+
* @return array<string, Attribute>
41+
*/
42+
public function all(): array
43+
{
44+
return $this->attributes;
45+
}
46+
47+
/**
48+
* @return array<string, AttributeSerialized>
49+
*/
50+
public function toArray(): array
51+
{
52+
return array_map(static function (Attribute $attribute) {
53+
return $attribute->jsonSerialize();
54+
}, $this->attributes);
55+
}
56+
57+
/**
58+
* @return array<string, AttributeSerialized>
59+
*/
60+
public function jsonSerialize(): array
61+
{
62+
return $this->toArray();
63+
}
64+
65+
/**
66+
* @return array<string, AttributeValue>
67+
*/
68+
public function toSimpleArray(): array
69+
{
70+
return array_map(static function (Attribute $attribute) {
71+
return $attribute->getValue();
72+
}, $this->attributes);
73+
}
74+
}

src/Client.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,16 @@ public function getTransport(): TransportInterface
255255
return $this->transport;
256256
}
257257

258+
public function getSdkIdentifier(): string
259+
{
260+
return $this->sdkIdentifier;
261+
}
262+
263+
public function getSdkVersion(): string
264+
{
265+
return $this->sdkVersion;
266+
}
267+
258268
/**
259269
* Assembles an event and prepares it to be sent of to Sentry.
260270
*
@@ -280,6 +290,7 @@ private function prepareEvent(Event $event, ?EventHint $hint = null, ?Scope $sco
280290

281291
$event->setSdkIdentifier($this->sdkIdentifier);
282292
$event->setSdkVersion($this->sdkVersion);
293+
283294
$event->setTags(array_merge($this->options->getTags(), $event->getTags()));
284295

285296
if ($event->getServerName() === null) {

src/Event.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Sentry\Context\OsContext;
88
use Sentry\Context\RuntimeContext;
9+
use Sentry\Logs\Log;
910
use Sentry\Profiling\Profile;
1011
use Sentry\Tracing\Span;
1112

@@ -65,6 +66,11 @@ final class Event
6566
*/
6667
private $checkIn;
6768

69+
/**
70+
* @var Log[]
71+
*/
72+
private $logs = [];
73+
6874
/**
6975
* @var string|null The name of the server (e.g. the host name)
7076
*/
@@ -230,6 +236,11 @@ public static function createCheckIn(?EventId $eventId = null): self
230236
return new self($eventId, EventType::checkIn());
231237
}
232238

239+
public static function createLogs(?EventId $eventId = null): self
240+
{
241+
return new self($eventId, EventType::logs());
242+
}
243+
233244
/**
234245
* @deprecated Metrics are no longer supported. Metrics API is a no-op and will be removed in 5.x.
235246
*/
@@ -416,6 +427,24 @@ public function setCheckIn(?CheckIn $checkIn): self
416427
return $this;
417428
}
418429

430+
/**
431+
* @return Log[]
432+
*/
433+
public function getLogs(): array
434+
{
435+
return $this->logs;
436+
}
437+
438+
/**
439+
* @param Log[] $logs
440+
*/
441+
public function setLogs(array $logs): self
442+
{
443+
$this->logs = $logs;
444+
445+
return $this;
446+
}
447+
419448
/**
420449
* @deprecated Metrics are no longer supported. Metrics API is a no-op and will be removed in 5.x.
421450
*/

src/EventType.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ public static function checkIn(): self
4242
return self::getInstance('check_in');
4343
}
4444

45+
public static function logs(): self
46+
{
47+
return self::getInstance('log');
48+
}
49+
4550
/**
4651
* @deprecated Metrics are no longer supported. Metrics API is a no-op and will be removed in 5.x.
4752
*/
@@ -61,6 +66,7 @@ public static function cases(): array
6166
self::event(),
6267
self::transaction(),
6368
self::checkIn(),
69+
self::logs(),
6470
self::metrics(),
6571
];
6672
}

src/Logger/DebugFileLogger.php

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44

55
namespace Sentry\Logger;
66

7-
use Psr\Log\AbstractLogger;
8-
9-
class DebugFileLogger extends AbstractLogger
7+
class DebugFileLogger extends DebugLogger
108
{
119
/**
1210
* @var string
@@ -18,13 +16,8 @@ public function __construct(string $filePath)
1816
$this->filePath = $filePath;
1917
}
2018

21-
/**
22-
* @param mixed $level
23-
* @param string|\Stringable $message
24-
* @param mixed[] $context
25-
*/
26-
public function log($level, $message, array $context = []): void
19+
public function write(string $message): void
2720
{
28-
file_put_contents($this->filePath, \sprintf("sentry/sentry: [%s] %s\n", $level, (string) $message), \FILE_APPEND);
21+
file_put_contents($this->filePath, $message, \FILE_APPEND);
2922
}
3023
}

src/Logger/DebugLogger.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sentry\Logger;
6+
7+
use Psr\Log\AbstractLogger;
8+
9+
abstract class DebugLogger extends AbstractLogger
10+
{
11+
/**
12+
* @param mixed $level
13+
* @param string|\Stringable $message
14+
* @param mixed[] $context
15+
*/
16+
public function log($level, $message, array $context = []): void
17+
{
18+
$formattedMessageAndContext = implode(' ', array_filter([(string) $message, json_encode($context)]));
19+
20+
$this->write(
21+
\sprintf("sentry/sentry: [%s] %s\n", $level, $formattedMessageAndContext)
22+
);
23+
}
24+
25+
abstract public function write(string $message): void;
26+
}

0 commit comments

Comments
 (0)