andrebian/laminas-sentry

一个Laminas 3模块,允许您将日志记录到Sentry.io服务。

dev-master 2023-05-17 21:28 UTC

This package is auto-updated.

Last update: 2024-09-18 00:07:58 UTC


README

ZendSentry的作者已经放弃了这个项目,建议直接使用Sentry,但我在Zend Framework中使用了这个工具,它很棒,因为它不需要编写任何代码,只需插入、配置即可。

这是什么?

一个Laminas框架模块,允许您将异常、错误或其他任何内容自动记录到Sentry.io服务。

许可证

LaminasSentry是在MIT许可证下发布的。

最近的变化

LaminasSentry的当前版本为ZF3的3.7.1。它支持Laminas框架。

  • 3.7.1:为Laminas框架中的应用程序重写
  • 3.7.0:添加了配置使用的Ravenjs版本,升级Ravenjs到3.27.0
  • 3.6.0:添加了静态setter以注入CSP nonce(临时解决方案)
  • 3.5.0:添加了对新的Sentry DSN的支持,废弃旧的DSN以供后续删除
  • 3.4.0:添加了关闭使用raven-js CDN的可能性
  • 3.3.0:添加了将配置选项传递给ravenjs的可能性

简介

什么是Sentry?

Sentry是一个在线服务,您可以将任何内容(包括异常和错误)记录到其中。Sentry会实时创建漂亮的报告,并为您聚合已记录的数据。

什么是Laminasentry?

这是一个模块,它构建了您的Laminas框架应用程序和Sentry.io服务之间的桥梁。它非常容易设置,并提供了许多开箱即用的功能。

功能和能力

  • 自动将未捕获的PHP异常记录到Sentry。
  • 自动将PHP错误记录到Sentry。
  • 自动将未捕获的JavaScript错误记录到Sentry。
  • 通过触发事件监听器捕获异常到Sentry。
  • 通过触发事件监听器将您喜欢的内容记录到Sentry。
  • Http以及CLI(自动选择)的ZF异常策略。
  • 日志操作返回Sentry事件_id。
  • Raven已被注册为服务。
  • 覆盖Raven配置默认值。
  • 将配置选项传递给ravenjs。
  • 配置错误消息。
  • 注入内联脚本渲染的Content-Security-Policynonce。这使得您能够在脚本源中不使用unsafe-inline`来创建CSP。

安装

此模块可在Packagist上找到。在您的项目composer.json中使用

{   
    "require": {
        "andrebian/laminas-sentry": "*"
}

运行php composer.phar update将其下载到您的vendor文件夹并设置自动加载。

现在将laminas-sentry.local.php.dist复制到yourapp/config/autoload/laminas-sentry.local.php,并添加您的Sentry API密钥(在您的项目中提供的DSN配置)。然后,将laminas-sentry.global.php.dist复制到同一位置,也删除.dist。如有需要,调整设置。

LaminasSentry添加到您的application.config.php中的模块数组中,最好是作为第一个模块。

这就完成了。您不需要做任何事情,在这个阶段一切都会正常工作,尝试一下。祝您记录愉快!

基本自动使用

再次强调,您无需编写任何代码即可使此功能生效。默认设置将确保Sentry同时作为错误和异常处理器注册,尝试一下,通过触发错误或抛出一些异常。您应该会立即在Sentry仪表板上看到它们。LaminasSentry还打包了自己的异常策略,以确保ZF可能拦截的异常被记录。

手动使用

此外,该模块在应用级别注册了一个日志事件监听器。因此,您可以从应用的任何地方触发自定义日志事件。

在控制器中,您可能这样做

$this->getEventManager()->trigger('log', $this, array(
    'priority' => \Laminas\Log\Logger::INFO, 
    'message' => 'I am a message and I have been logged'
));

或者,您可以将返回的Sentry event_id存储起来以进行处理

$eventID = $this->getEventManager()->trigger('log', $this, array(
    'priority' => \Laminas\Log\Logger::INFO,
    'message' => 'I am a message and I have been logged'
));

现在,您可以告诉您的用户或API消费者此ID,以便他们可以引用它,例如在寻求支持时。

请确保将"log"作为第一个参数传递,并将$this 一个自定义上下文字符串作为第二个参数传递。保持一致性,因为Sentry将使用此参数对您的日志条目进行分组。作为第三个参数,您想传递一个包含优先级键和消息键的数组。最好使用Laminas框架提供的优先级。它们将被映射到Sentry自己的优先级。

除了未捕获的异常和错误会自动记录之外,您还可以通过直接使用相应的监听器手动记录捕获的或未捕获的异常。

try {
    throw new Exception('throw and catch');
} catch (Exception $exception) {
    $result = $this->getEventManager()->trigger('logException', $this, array('exception' => $exception));

    //get Sentry event_id by retrieving it from the EventManager ResultCollection
    $eventID = $result->last();
}

使用标签

您还可以将自定义标签传递给Sentry。该服务将自动为这些标签创建过滤和排序。当使用log事件时,您可以可选地传递标签,如下所示

$this->getEventManager()->trigger('log', $this, array(
    'priority' => \Laminas\Log\Logger::INFO,
    'message' => 'I am a message with a language tag',
    'tags' => array('language' => 'en'),
    'extra' => array('email' => 'test@test.com'),
));

如果手动使用logException事件,您也可以传递标签

try {
    throw new Exception('throw and catch with tags');
} catch (Exception $exception) {
    $this->getEventManager()->trigger('logException', $this, array('exception' => $exception, 'tags' => array('language' => 'fr')));
}

注意!每个标签都需要一个键和一个值。

下面是如何使用标签来自动记录异常的示例。

Raven作为服务

该模块将Raven_Client注册为全局服务。通常,您不希望直接访问它,因为触发事件监听器会使代码更整洁。Raven直接使用的一个例子是添加用户上下文。例如,您可能希望在启动时执行以下操作

if ($authenticationService->hasIdentity()) {
    $ravenClient = $this->serviceManager->get('raven');
    $ravenClient->user_context($authenticationService->getIdentity()->userID);
}

如果您想向上下文中添加一些标签,这些标签将随每个自动条目一起发送,您可以直接使用Raven。例如,您可以在AbstractActionController::preDispatch()中这样做

$serviceManager = $mvcEvent->getApplication()->getServiceManager();
if ($serviceManager->has('raven')) {
    $ravenClient = $serviceManager->get('raven');
    $ravenClient->tags_context(
        [
            'locale'  => $this->translator()->getLocale(),
        ]
    );
}

注入CSP nonce(注意!临时解决方案)

如果您已在应用中实现了内容安全策略,那么您很可能会为动态内联JavaScript使用nonce。如果是这样,现在您可以将nonce注入到LaminasSentry中

LaminasSentry::setCSPNonce(ContentSecurityPolicy::getNonce());

... 其中 ContentSecurityPolicy 是您实现的该HTTP头。

如果您注入了一个nonce,LaminasSentry将把它添加为Raven加载脚本的属性。示例

<script type="text/javascript" nonce="qlQa7LCu2ZLoVZzpn5s9OJNq7QE=">
    //<![CDATA[
    if (typeof Raven !== 'undefined') Raven.config('https://yourpublickey@sentry.io/5374', []).install()
    //]]>
</script>

请注意,我们将其视为临时解决方案。对于LaminasSentry来说,定义它自己的CSP头会更好。目前,Laminas框架没有正确处理多个CSP头(请参阅zend-http中的此问题)。

配置选项

仅作记录,以下是实际的全局配置选项的副本

/**
 * Turn LaminasSentry off or on as a whole package
 */
'use-module' => true,

/**
 * Attach a generic logger event listener so you can log custom messages from anywhere in your app
 */
'attach-log-listener' => true,

/**
 * Register the Sentry logger as PHP error handler
 */
'handle-errors' => true,

/**
 * Should the previously registered error handler be called as well?
 */
'call-existing-error-handler' => true,

/**
 * Register Sentry as shutdown error handler
 */
'handle-shutdown-errors' => true,

/**
 * Register the Sentry logger as PHP exception handler
 */
'handle-exceptions' => true,

/**
 * Should the previously registered exception handler be called as well
 */
'call-existing-exception-handler' => true,

/**
 * Which errors should be reported to sentry (bitmask), e. g. E_ALL ^ E_DEPRECATED
 * Defaults to -1 to report all possible errors (equivalent to E_ALL in >= PHP 5.4)
 */
'error-reporting' => -1,

/**
 * Should exceptions be displayed on the screen?
 */
'display-exceptions' => false,

/**
 * If Exceptions are displayed on screen, this is the default message
 */
'default-exception-message' => 'Oh no. Something went wrong, but we have been notified. If you are testing, tell us your eventID: %s',

/**
 * If Exceptions are displayed on screen, this is the default message in php cli mode
 */
'default-exception-console-message' => "Oh no. Something went wrong, but we have been notified.\n",

/**
 * Should Sentry also log javascript errors?
 */
'handle-javascript-errors' => true,

/**
 * Should LaminasSentry load raven-js via CDN?
 * If you set this to false you'll need to make sure to load raven-js some other way.
 */
'use-ravenjs-cdn' => true,

/**
 * Change the raven-js version loaded via CDN if you need to downgrade or we're lagging behind with updating.
 * No BC breaks, LaminasSentry will set the version if your config is missing the key.
 */
'ravenjs-version' => '3.27.0',

/**
 * Alternatively, if not using CDN, you can specify a path or url to raven-js.
 * Set to empty to disable but make sure to load raven-js some other way.
 */
'ravenjs-source' => '/js/raven.min.js',

/**
 * Set raven config options for the getsentry/sentry-php package here.
 * Raven has sensible defaults set in Raven_Client, if you need to override them, this is where you can do it.
 */
'raven-config' => array(),

/**
 * Set ravenjs config options for the getsentry/raven-js package here.
 * This will be json encoded and passed to raven-js when doing Raven.install().
 */
'ravenjs-config' => array(),

尝试一下

一些从控制器或视图尝试不同功能的想法

// Test logging of PHP errors
// trigger_error('can I trigger an error from a controller');

// Test logging of PHP exceptions
// throw new \Exception('Some exception gets logged.');

// Throw a javascript error and see it logged (add to view or layout)
// $headScript->appendScript("throw new Error('A javascript error should be logged.');");