8

注册登录

GitHub登录
clipboard.png

创建project 选择 laravel
clipboard.png

clipboard.png

安装扩展使用

composer require sentry/sentry-laravel

php artisan vendor:publish --provider="Sentry\SentryLaravel\SentryLaravelServiceProvider"

public function report(Exception $exception)
{
    if (app()->bound('sentry') && $this->shouldReport($exception)) {
        app('sentry')->captureException($exception);
    }

    parent::report($exception);
}

vi config/sentry.php
return array(
    'dsn' => env('DSN'),

    // capture release as git sha
    // 'release' => trim(exec('git log --pretty="%h" -n1 HEAD')),

    // Capture bindings on SQL queries
    'breadcrumbs.sql_bindings' => true,

    // Capture default user context
    'user_context' => false,

    //transport function https://docs.sentry.io/clients/php/config/
    'transport'=>new \App\SentryTransport(),
);

vi /app/SentryTransport.php
namespace App;
//
class SentryTransport
{
    public static function __set_state($array){
        return function($raven_client,$data){
            \Queue::pushOn('sentry_log',new \App\Commands\sentry($raven_client,$data));
        };
    }
}
vi app/commands/sentry.php
class sentry extends Command implements SelfHandling, ShouldBeQueued {

    use InteractsWithQueue, SerializesModels;

    private $raven_client;
    protected $data;
    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct($raven_client, $data)
    {
        $raven_client->setTransport(null);
        $raven_client->close_curl_resource();
        $this->raven_client=$raven_client;
        $this->data=$data;
    }

    /**
     * Execute the command.
     *
     * @return void
     */
    public function handle()
    {
        $this->raven_client->send($this->data);//send方法来自 /vendor/sentry/sentry/lib/Raven/Client.php:1019
    }

}

vi /vendor/sentry/sentry/lib/Raven/Client.php
public function send(&$data)
    {
        if (is_callable($this->send_callback)
            && call_user_func_array($this->send_callback, array(&$data)) === false
        ) {
            // if send_callback returns false, end native send
            return;
        }

        if (!$this->server) {
            return;
        }

        if ($this->transport) {
            call_user_func($this->transport, $this, $data);
            return;
        }

        // should this event be sampled?
        if (rand(1, 100) / 100.0 > $this->sample_rate) {
            return;
        }

        $message = $this->encode($data);

        $headers = array(
            'User-Agent' => static::getUserAgent(),
            'X-Sentry-Auth' => $this->getAuthHeader(),
            'Content-Type' => 'application/octet-stream'
        );

        $this->send_remote($this->server, $message, $headers);
    }

配置dsn

获取 dsn

clipboard.png

测试

少写个分号,查看效果
clipboard.png

clipboard.png

monolog 发送到sentry

composer require monolog/monolog

vi config/app.php

'App\Providers\sentrylog' 

vi App\Providers\sentrylog.php

use Monolog\Handler\RedisHandler;
use Monolog\Formatter\JsonFormatter;
use Monolog\Formatter\LineFormatter;
use Monolog\Processor\MemoryPeakUsageProcessor;
use Monolog\Processor\WebProcessor;
use Monolog\Handler\RavenHandler;

class sentrylog extends ServiceProvider {

    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot() {
        $logger = \Log::getMonolog();
        $handler = new RedisHandler($redis, "sentry:monolog", \Monolog\Logger::DEBUG);
        $handler->setFormatter(new JsonFormatter(JsonFormatter::BATCH_MODE_NEWLINES, true));
        $handler->pushProcessor(new MemoryPeakUsageProcessor(true));
        /*$logger->pushProcessor(function ($record) {
            $record['extra']['dummy'] = 'Hello world!';

            return $record;
        });
        class MemoryPeakUsageProcessor extends MemoryProcessor
{
    /**
     * @param  array $record 对象当方法调用时执行
     * @return array
     */
    public function __invoke(array $record)
    {
        $bytes = memory_get_peak_usage($this->realUsage);
        $formatted = $this->formatBytes($bytes);

        $record['extra']['memory_peak_usage'] = $formatted;

        return $record;
    }
}*/
            $arr = [
                'uri' => 'REQUEST_URI',
                'ip' => 'REMOTE_ADDR',
                'method' => 'REQUEST_METHOD',
                'query_string' => 'QUERY_STRING',
                'cookie' => 'HTTP_COOKIE',
                'host' => 'HTTP_HOST',
            ];
        $handler->pushProcessor(new WebProcessor(null, $arr));
        $logger->pushHandler($handler);
            
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register() {
        //
    }

}
vi app/commands/sentry_monolog.php

use Monolog\Handler\RavenHandler;
        while (true) {
            $data = $redis->lpop("sentry:monolog");
            if (!$data) {
                sleep(5);
                continue;
            }
            $data = json_decode($data, true);
            $raven_client= new \Raven_Client($dsn,['extra' => $data['extra']]);
            $raven_hanlder = new RavenHandler($raven_client);
            $raven_hanlder->handle($data);//https://pagerefresh.co.uk/apigen/monolog/class-Monolog.Handler.RavenHandler.html vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php:handle  vendor/monolog/monolog/src/Monolog/Handler/RavenHandler.php :write
            $raven_client->__destruct();
            }

资源

你也可以本地搭建
Sentry 之部署到生产环境
搭建自己的 sentry 服务
CentOS6 基于 Python 安装 Sentry
Sentry 自动化异常提醒
Laravel学习笔记之Errors Tracking神器——Sentry
sentry使用
利用 entry/onpremise 搭建一个 Sentry 异常汇总工具
高效利用Sentry追踪日志发现问题
sentry monolog
Sentry - 处理异常日志的正确姿势
Sentry监控Django应用并使用email+钉钉通知
搭建私有的前端监控服务: sentry


苏生不惑
18.9k 声望1.9k 粉丝