从 IBM Cloud Functions 调用时,PHP SDK 不会向 Sentry 发送错误

vla*_*run 1 php sentry serverless-framework openwhisk ibm-cloud

我正在使用无服务器框架将 PHP 代码部署为 IBM Cloud Function。

以下是操作 PHP 文件中的代码:

function main($args): array {

    Sentry\init(['dsn' => 'SENTRY_DSN' ]);

    try {
        throw new \Exception('Some error')
    } catch (\Throwable $exception) {
        Sentry\captureException($exception);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是 serverless.yml 文件:

service: cloudfunc

provider:
  name: openwhisk
  runtime: php

package:
  individually: true
  exclude:
    - "**"
  include:
    - "vendor/**"

functions:
    test-sentry:
    handler: actions/test-sentry.main
    annotations:
        raw-http: true
    events:
        - http:
            path: /test-sentry
            method: post
            resp: http
    package:
        include:
        - actions/test-sentry.php

plugins:
  - serverless-openwhisk
Run Code Online (Sandbox Code Playgroud)

当我从本地环境(NGINX/PHP Docker 容器)测试操作处理程序时,错误将被发送到 Sentry。

但是,当我尝试从 IBM Cloud 调用该操作时,Sentry 控制台中没有显示任何内容。

编辑:

经过一段时间尝试调查问题的根源后,我发现它与向 Sentry 发送 http 请求的异步性质有关(我有其他库可以与 Loggly、RabbitMQ、MySQL 建立 HTTP/TCP 连接,它们都按预期工作):

vendor/sentry/sentry/src/Transport/HttpTransport.php
Run Code Online (Sandbox Code Playgroud)

在发送实际 http 请求的 send 方法中:

service: cloudfunc

provider:
  name: openwhisk
  runtime: php

package:
  individually: true
  exclude:
    - "**"
  include:
    - "vendor/**"

functions:
    test-sentry:
    handler: actions/test-sentry.main
    annotations:
        raw-http: true
    events:
        - http:
            path: /test-sentry
            method: post
            resp: http
    package:
        include:
        - actions/test-sentry.php

plugins:
  - serverless-openwhisk
Run Code Online (Sandbox Code Playgroud)

Rob*_*len 5

异步注册的请求在HttpTransport实例的析构函数中发送,或者当 PHP 因注册关闭函数而关闭时发送。在 OpenWhisk 中,我们永远不会关闭,因为我们在永无休止的循环中运行,直到 Docker 容器被终止。

更新:您现在可以调用$client-flush(),无需担心反射。

main()现在看起来像这样:

function main($args): array {

    Sentry\init(['dsn' => 'SENTRY_DSN' ]);

    try {
        throw new \Exception('Some error')
    } catch (\Throwable $exception) {
        Sentry\captureException($exception);
    }

    $client = Sentry\State\Hub::getCurrent()->getClient();
    $client->flush();

    return [
        'body' => ['result' => 'ok']
    ];
}
Run Code Online (Sandbox Code Playgroud)

原文解释:

因此,为了使其工作,我们需要调用s$transport属性的析构函数。不幸的是,这是私有的,因此最简单的方法是使用反射使其可见,然后调用它:Hub$client

function main($args): array {

    Sentry\init(['dsn' => 'SENTRY_DSN' ]);

    try {
        throw new \Exception('Some error')
    } catch (\Throwable $exception) {
        Sentry\captureException($exception);
    }

    $client = Sentry\State\Hub::getCurrent()->getClient();
    $client->flush();

    return [
        'body' => ['result' => 'ok']
    ];
}
Run Code Online (Sandbox Code Playgroud)

这将使该$transport属性可见,以便我们可以检索它并调用其析构函数,该析构函数将依次调用cleanupPendingRequests()该析构函数,然后将请求发送到sentry.io。

因此main()看起来像这样:

$client = Sentry\State\Hub::getCurrent()->getClient();
$property = (new ReflectionObject($client))->getProperty('transport');
$property->setAccessible(true);
$transport = $property->getValue($client);
$transport->__destruct();
Run Code Online (Sandbox Code Playgroud)

顺便问一下,这个Sentry SDK可以和Swoole一起使用吗?

  • 我们很快就会在 SDK 中添加对此的支持 https://github.com/getsentry/sentry-php/pull/799 将会有 `flush` / `close` 参考:https://docs.sentry.io/error -报告/配置/排水/?platform=javascript (2认同)