Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/sentry/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ return [
// ...
'sentry' => [
'handler' => [
'class' => \Sentry\Monolog\LogsHandler::class,
'class' => \FriendsOfHyperf\Sentry\Monolog\LogsHandler::class,
'constructor' => [
'group' => 'sentry',
'level' => \Sentry\Logs\LogLevel::debug(),
'bubble' => true,
],
],
'formatter' => [
Expand Down
59 changes: 59 additions & 0 deletions src/sentry/src/Monolog/LogsHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

declare(strict_types=1);
/**
* This file is part of friendsofhyperf/components.
*
* @link https://github.com/friendsofhyperf/components
* @document https://github.com/friendsofhyperf/components/blob/main/README.md
* @contact huangdijia@gmail.com
*/

namespace FriendsOfHyperf\Sentry\Monolog;

use Monolog\LogRecord;
use Sentry\Logs\LogLevel;
use Sentry\Logs\Logs;
use Sentry\Monolog\CompatibilityLogLevelTrait;
use Throwable;

class LogsHandler extends \Sentry\Monolog\LogsHandler
{
use CompatibilityLogLevelTrait;

public function __construct(
protected string $group = 'default',
?LogLevel $logLevel = null,
protected bool $bubble = true
) {
parent::__construct($logLevel, $bubble);
}
Comment on lines +24 to +30
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

避免属性遮蔽父类 $bubble;参数名与 README 键对齐

  • 本类重复声明了 protected bool $bubble,会遮蔽父类(Monolog AbstractHandler)同名属性,易造成后续维护歧义。
  • 将参数名 $logLevel 改为 $level(类型不变),与 README 示例键名一致,降低注入踩坑概率。
-    public function __construct(
-        protected string $group = 'default',
-        ?LogLevel $logLevel = null,
-        protected bool $bubble = true
-    ) {
-        parent::__construct($logLevel, $bubble);
-    }
+    public function __construct(
+        protected string $group = 'default',
+        ?LogLevel $level = null,
+        bool $bubble = true
+    ) {
+        parent::__construct($level, $bubble);
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public function __construct(
protected string $group = 'default',
?LogLevel $logLevel = null,
protected bool $bubble = true
) {
parent::__construct($logLevel, $bubble);
}
public function __construct(
protected string $group = 'default',
?LogLevel $level = null,
bool $bubble = true
) {
parent::__construct($level, $bubble);
}
🤖 Prompt for AI Agents
In src/sentry/src/Monolog/LogsHandler.php around lines 24-30, the constructor
currently shadows the parent AbstractHandler's $bubble property and uses
parameter name $logLevel that differs from README; change the constructor to
accept ?LogLevel $level instead of $logLevel and remove the protected
declaration from $bubble so it is a plain parameter (not a class property) to
avoid shadowing the parent property; call parent::__construct($level, $bubble)
unchanged and keep the protected string $group property as-is.


/**
* @param array<string, mixed>|LogRecord $record
*/
public function handle($record): bool
{
if (! $this->isHandling($record)) {
return false;
}
// Do not collect logs for exceptions, they should be handled seperately by the `Handler` or `captureException`
if (isset($record['context']['exception']) && $record['context']['exception'] instanceof Throwable) {
return false;
}

Logs::getInstance()->aggregator()->add(
self::getSentryLogLevelFromMonologLevel($record['level']),
$record['message'],
[],
array_merge(
['log_context' => $record['context']],
['log_extra' => $record['extra']],
['logger' => $record['channel'] ?? ''],
['group' => $this->group]
)
);

return $this->bubble === false;
}
Comment on lines +35 to +58
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

兼容 Monolog v3:对 LogRecord 使用数组下标会导致致命错误

handle() 中大量使用 $record['...'],在 Monolog v3(LogRecord 对象)下会报错。建议规范化记录,兼容 v2 数组与 v3 LogRecord。

-    public function handle($record): bool
+    public function handle($record): bool
     {
         if (! $this->isHandling($record)) {
             return false;
         }
-        // Do not collect logs for exceptions, they should be handled seperately by the `Handler` or `captureException`
-        if (isset($record['context']['exception']) && $record['context']['exception'] instanceof Throwable) {
-            return false;
-        }
-
-        Logs::getInstance()->aggregator()->add(
-            self::getSentryLogLevelFromMonologLevel($record['level']),
-            $record['message'],
-            [],
-            array_merge(
-                ['log_context' => $record['context']],
-                ['log_extra' => $record['extra']],
-                ['logger' => $record['channel'] ?? ''],
-                ['group' => $this->group]
-            )
-        );
-
-        return $this->bubble === false;
+        // Do not collect logs for exceptions, they should be handled separately by the `Handler` or `captureException`
+        $isArray = is_array($record);
+        $level   = $isArray ? ($record['level'] ?? null)   : $record->level;
+        $message = $isArray ? ($record['message'] ?? '')   : $record->message;
+        $context = (array)($isArray ? ($record['context'] ?? []) : $record->context);
+        $extra   = (array)($isArray ? ($record['extra'] ?? [])   : $record->extra);
+        $channel = $isArray ? ($record['channel'] ?? '')         : ($record->channel ?? '');
+
+        $exception = $context['exception'] ?? null;
+        if ($exception instanceof Throwable) {
+            return false;
+        }
+
+        Logs::getInstance()->aggregator()->add(
+            self::getSentryLogLevelFromMonologLevel($level),
+            $message,
+            [],
+            array_merge(
+                ['log_context' => $context],
+                ['log_extra' => $extra],
+                ['logger' => $channel],
+                ['group' => $this->group]
+            )
+        );
+
+        // 返回 true 表示“阻止冒泡”,与 Monolog 语义一致
+        return $this->bubble === false;
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public function handle($record): bool
{
if (! $this->isHandling($record)) {
return false;
}
// Do not collect logs for exceptions, they should be handled seperately by the `Handler` or `captureException`
if (isset($record['context']['exception']) && $record['context']['exception'] instanceof Throwable) {
return false;
}
Logs::getInstance()->aggregator()->add(
self::getSentryLogLevelFromMonologLevel($record['level']),
$record['message'],
[],
array_merge(
['log_context' => $record['context']],
['log_extra' => $record['extra']],
['logger' => $record['channel'] ?? ''],
['group' => $this->group]
)
);
return $this->bubble === false;
}
public function handle($record): bool
{
if (! $this->isHandling($record)) {
return false;
}
// Do not collect logs for exceptions, they should be handled separately by the `Handler` or `captureException`
$isArray = is_array($record);
$level = $isArray ? ($record['level'] ?? null) : $record->level;
$message = $isArray ? ($record['message'] ?? '') : $record->message;
$context = (array)($isArray ? ($record['context'] ?? []) : $record->context);
$extra = (array)($isArray ? ($record['extra'] ?? []) : $record->extra);
$channel = $isArray ? ($record['channel'] ?? '') : ($record->channel ?? '');
$exception = $context['exception'] ?? null;
if ($exception instanceof Throwable) {
return false;
}
Logs::getInstance()->aggregator()->add(
self::getSentryLogLevelFromMonologLevel($level),
$message,
[],
array_merge(
['log_context' => $context],
['log_extra' => $extra],
['logger' => $channel],
['group' => $this->group]
)
);
// 返回 true 表示“阻止冒泡”,与 Monolog 语义一致
return $this->bubble === false;
}

}
2 changes: 1 addition & 1 deletion src/sentry/src/SentryHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
use Throwable;

/**
* @deprecated since v3.1, use `Sentry\Monolog\LogsHandler` instead, will remove in v3.2
* @deprecated since v3.1, use `FriendsOfHyperf\Sentry\Monolog\LogsHandler` instead, will remove in v3.2
*/
class SentryHandler extends AbstractProcessingHandler
{
Expand Down