ๆฆ่ฆ
PHP ใญใฐใ Datadog ใซ้ไฟกใใๅ ดๅใฏใใใกใคใซใซใญใฐใ่จ้ฒใใDatadog Agent ใไฝฟ็จใใฆใใฎใใกใคใซใใใผใซใใพใใใใฎใใผใธใงใฏใMonologใZend-Log ใใใณ Symfony ใญใฐใฉใคใใฉใชใใปใใใขใใใใไพใ่ฉณใใ่ชฌๆใใพใใ
ใปใใใขใใ
ใคใณในใใผใซ
ใใฎใณใใณใใๅฎ่กใใใจใComposer ใไฝฟ็จใใฆ Monolog ใไพๅญ้ขไฟใจใใฆ่ฟฝๅ ใใใใจใใงใใพใใ
composer require "monolog/monolog"
ใพใใฏใไปฅไธใฎๆนๆณใง Monolog ใๆๅใงใคใณในใใผใซใใพใใ
ใชใใธใใชใใ Monolog ใใใฆใณใญใผใใใใฉใคใใฉใชใซ่ฟฝๅ ใใพใใ
ใขใใชใฑใผใทใงใณใฎใใผใในใใฉใใๅ
ใซไปฅไธใ่ฟฝๅ ใใใคใณในใฟใณในใๅๆๅใใพใใ
<?php
require __DIR__ . '/vendor/autoload.php';
// load Monolog library
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Formatter\JsonFormatter;
Zend-Log ใฏใZend ใใฌใผใ ใฏใผใฏใฎไธ้จใงใใใใฎใณใใณใใๅฎ่กใใใจใComposer ใไฝฟใฃใฆ Zend-Log ใ่ฟฝๅ ใใใใจใใงใใพใใ
composer require "zendframework/zend-log"
ใพใใฏใไปฅไธใฎๆนๆณใง Zend-Log ใๆๅใงใคใณในใใผใซใใพใใ
- ใชใใธใใชใใใฝใผในใใใฆใณใญใผใใใใฉใคใใฉใชใซ่ฟฝๅ ใใพใใ
- ใขใใชใฑใผใทใงใณใฎใใผใในใใฉใใๅ
ใซไปฅไธใ่ฟฝๅ ใใใคใณในใฟใณในใๅๆๅใใพใใ
<?php
require __DIR__ . '/vendor/autoload.php';
use Zend\Log\Logger;
use Zend\Log\Writer\Stream;
use Zend\Log\Formatter\JsonFormatter;
ไปฅไธใ่ฟฝๅ ใใฆใMonolog JSON Formatter ใใตใผใในใจใใฆๅฎฃ่จใใพใใ
services:
monolog.json_formatter:
class: Monolog\Formatter\JsonFormatter
ใญใฌใผใฎๆงๆ
ไปฅไธใฎๆงๆใงใฏใJSON ใใฉใผใใใใๆๅนใซใใใญใฐใจใคใใณใใ application-json.log
ใใกใคใซใซๆธใ่พผใใงใใพใใใณใผใใงใMonolog ใคใณในใฟใณในใฎๅๆๅๅพใซๆฐใใใใณใใฉใผใ่ฟฝๅ ใใพใใ
<?php
require __DIR__ . '/vendor/autoload.php';
// Monolog ใฉใคใใฉใชใใญใผใ
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Formatter\JsonFormatter;
// ใญใฐใใฃใใซใไฝๆ
$log = new Logger('channel_name');
// Json ใใฉใผใใใฟใไฝๆ
$formatter = new JsonFormatter();
// ใใณใใฉใผใไฝๆ
$stream = new StreamHandler(__DIR__.'/application-json.log', Logger::DEBUG);
$stream->setFormatter($formatter);
// ใใคใณใ
$log->pushHandler($stream);
// ไพ
$log->info('Adding a new user', array('username' => 'Seldaek'));```
ไปฅไธใฎๆงๆใงใฏใJSON ใใฉใผใใใใๆๅนใซใใใญใฐใจใคใใณใใ application-json.log
ใใกใคใซใซๆธใ่พผใใงใใพใใใณใผใใงใZend-Log ใคใณในใฟใณในใฎๅๆๅๅพใซๆฐใใใใณใใฉใผใ่ฟฝๅ ใใพใใ
<?php
use Zend\Log\Logger;
use Zend\Log\Writer\Stream;
use Zend\Log\Formatter\JsonFormatter;
// ใญใฌใผใไฝๆ
$logger = new Logger();
// ใฉใคใฟใผใไฝๆ
$writer = new Stream('file://' . __DIR__ . '/application-json.log');
// Json ใใฉใผใใใฟใไฝๆ
$formatter = new JsonFormatter();
$writer->setFormatter($formatter);
// ใใคใณใ
$logger->addWriter($writer); Zend\Log\Logger::registerErrorHandler($logger);```
Monolog ๆงๆใงใใฉใผใใใฟใๆงๆใใใซใฏใไปฅไธใฎใใฉใผใใใฟใใฃใผใซใใๅฎฃ่จใใพใใ
monolog:
handlers:
main:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
formatter: monolog.json_formatter
Datadog Agent ใฎๆงๆ
ใญใฐๅ้ใๆๅนใซใชใฃใใใไปฅไธใ่กใฃใฆใญใฐใใกใคใซใ่ฟฝ่ทกใใฆๆฐใใใญใฐใ Datadog ใซ้ไฟกใใใซในใฟใ ใญใฐๅ้ใ่จญๅฎใใพใใ
php.d/
ใใฉใซใใผใ conf.d/
Agent ๆงๆใใฃใฌใฏใใชใซไฝๆใใพใใphp.d/
ใซไปฅไธใฎๅ
ๅฎนใง conf.yaml
ใใกใคใซใไฝๆใใพใใ
init_config:
instances:
## Log ใปใฏใทใงใณ
logs:
- type: file
path: "<path_to_your_php_application_json>.log"
service: "<service_name>"
source: php
sourcecategory: sourcecode
ใญใฐใจใใฌใผในใซใใใใตใผใในใๆฅ็ถ
ใใฎใขใใชใฑใผใทใงใณใง APM ใๆๅนใซใชใฃใฆใใๅ ดๅใAPM PHP ใญใฎใณใฐใฎๆ็คบใซๅพใฃใฆใญใฐใซใใฌใผใน ID ใจในใใณ ID ใ่ชๅ็ใซ่ฟฝๅ ใใใใจใงใใขใใชใฑใผใทใงใณใญใฐใจใใฌใผใน้ใฎ็ธ้ข้ขไฟใๆนๅใงใใพใใ
ใญใฐใซใณใณใใญในใใ่ฟฝๅ ใใ
ใญใฐใใคใใณใใซ่ฟฝๅ ใฎใณใณใใญในใใ่ฟฝๅ ใใใจไพฟๅฉใชใใจใใใใพใใMonolog ใฏใในใฌใใใญใผใซใซใณใณใใญในใใ่จญๅฎใใใกใฝใใใๆไพใใใในใฆใฎใคใใณใใจๅ
ฑใซ่ชๅ็ใซ้ไฟกใใใพใใไพใใฐใใณใณใใญในใใใผใฟใๅซใใคใใณใใใญใฐใซ่จ้ฒใใใซใฏ
<?php
$logger->info('Adding a new user', array('username' => 'Seldaek'));
Monolog ใฎใใชใใญใปใใตใผใซใฏใๅ็ดใชใณใผใซใใใฏใงใ่จญๅฎใงใใใกใฟใใผใฟ (ไพใใฐใใปใใทใงใณ ID ใใชใฏใจในใ ID ใชใฉ) ใงใคใใณใใใชใใๅใใๆฉ่ฝใใใใพใใ
<?php
$log->pushProcessor(function ($record) {
// ็พๅจใฎใฆใผใถใผใ่จ้ฒ
$user = Acme::getCurrentUser();
$record['context']['user'] = array(
'name' => $user->getName(),
'username' => $user->getUsername(),
'email' => $user->getEmail(),
);
// ใใพใใพใชใฟใฐใ่ฟฝๅ
$record['ddtags'] = array('key' => 'value');
// ใใพใใพใชๆฑ็จใณใณใใญในใใ่ฟฝๅ
$record['extra']['key'] = 'value';
return $record; });```
ใญใฐใใคใใณใใซ่ฟฝๅ ใฎใณใณใใญในใใ่ฟฝๅ ใใใจไพฟๅฉใชใใจใใใใพใใZend-Log ใฏใในใฌใใใญใผใซใซใณใณใใญในใใ่จญๅฎใใใกใฝใใใๆไพใใใในใฆใฎใคใใณใใจๅ
ฑใซ่ชๅ็ใซ้ไฟกใใใพใใไพใใฐใใณใณใใญในใใใผใฟใๅซใใคใใณใใใญใฐใซ่จ้ฒใใใซใฏ
<?php
$logger->info('Adding a new user', array('username' => 'Seldaek'));
ใญใฐใซ่ฟฝๅ ๆ
ๅ ฑใไธใใๆนๆณใซใคใใฆใฏใ Zend ใฎใใญใปใใตใผใฎใใญใฅใกใณใใๅ็
งใใฆใใ ใใใ
ใปใใทใงใณใใญใปใใตใผใไฝฟ็จใใฆใญใฐใซๅคๆฐใณใณใใญในใใ่ฟฝๅ ใใใซใฏใไปฅไธใฎๆ้ ใซๅพใใพใใ
ใปใใทใงใณใใญใปใใตใผใๅฎ่ฃ
ใใพใใ
ๆฌกใฎไพใงใฏใใใญใปใใตใผใฏ็พๅจใฎใปใใทใงใณใ็ฅใฃใฆใใใrequestId
ใsessionId
ใชใฉใฎๆ
ๅ ฑใงใญใฐใฌใณใผใใฎๅ
ๅฎนใใชใใๅใใฆใใพใใ
<?php
namespace Acme\Bundle\MonologBundle\Log;
use Symfony\Component\HttpFoundation\Session\Session;
class SessionRequestProcessor {
private $session;
private $sessionId;
private $requestId;
private $_server;
private $_get;
private $_post;
public function __construct(Session $session) {
$this->session = $session;
}
public function processRecord(array $record) {
if (null === $this->requestId) {
if ('cli' === php_sapi_name()) {
$this->sessionId = getmypid();
} else {
try {
$this->session->start();
$this->sessionId = $this->session->getId();
} catch (\RuntimeException $e) {
$this->sessionId = '????????';
}
}
$this->requestId = substr(uniqid(), -8);
$this->_server = array(
'http.url' => (@$_SERVER['HTTP_HOST']).'/'.(@$_SERVER['REQUEST_URI']),
'http.method' => @$_SERVER['REQUEST_METHOD'],
'http.useragent' => @$_SERVER['HTTP_USER_AGENT'],
'http.referer' => @$_SERVER['HTTP_REFERER'],
'http.x_forwarded_for' => @$_SERVER['HTTP_X_FORWARDED_FOR']
);
$this->_post = $this->clean($_POST);
$this->_get = $this->clean($_GET);
}
$record['http.request_id'] = $this->requestId;
$record['http.session_id'] = $this->sessionId;
$record['http.url'] = $this->_server['http.url'];
$record['http.method'] = $this->_server['http.method'];
$record['http.useragent'] = $this->_server['http.useragent'];
$record['http.referer'] = $this->_server['http.referer'];
$record['http.x_forwarded_for'] = $this->_server['http.x_forwarded_for'];
return $record;
}
protected function clean($array) {
$toReturn = array();
foreach(array_keys($array) as $key) {
if (false !== strpos($key, 'password')) {
// Do not add
} else if (false !== strpos($key, 'csrf_token')) {
// Do not add
} else {
$toReturn[$key] = $array[$key];
}
}
return $toReturn;
}
}
ไปฅไธใ่ฟฝๅ ใใฆใใใญใปใใตใผใ Symfony ใจใคใณใใฐใฌใผใทใงใณใใพใใ
services:
monolog.processor.session_request:
class: Acme\Bundle\MonologBundle\Log\SessionRequestProcessor
arguments: [ @session ]
tags:
- { name: monolog.processor, method: processRecord }
็ๆใใใ JSON ใใกใคใซใ Datadog ใซในใใชใผใใณใฐใใพใใ
Monolog ใใฌใผใ ใฏใผใฏใฎใคใณใใฐใฌใผใทใงใณ
Monolog ใฏใไปฅไธใฎใใฌใผใ ใฏใผใฏใงไฝฟ็จใใใใจใใงใใพใใ
Monolog ใใใฌใผใ ใฏใผใฏใจใคใณใใฐใฌใผใทใงใณใใใใใซใไปฅไธใ่ฟฝๅ ใใพใใ
<?php
// Monolog ใฉใคใใฉใชใฎใญใผใใๆญฃๅธธใ็ขบ่ช
//use Monolog\Logger;
//use Monolog\Handler\StreamHandler;
//use Monolog\Formatter\JsonFormatter;
// monolog ใคใณในใฟใณในใๅซใ
$monolog = ...
///// Log shipper configuration
$formatter = new JsonFormatter();
$stream = new StreamHandler(__DIR__.'/application-json.log', Logger::DEBUG);
$stream->setFormatter($formatter);
$monolog->pushHandler($stream);
return $r;
ๆฌกใซใMonolog ็จใฎใญใฌใผใๆงๆใใพใใ
ๆงๆใใฃใฌใฏใใช /path/to/config/directory/
ใซใใ config_dev.yml
ใจ config_prod.yml
ใซไปฅไธใ่ฟฝๅ ใใฆใใ ใใใ้็บ็ฐๅขใจๆฌ็ช็ฐๅขใซๅใใใๆงๆใซใชใใใใซใใตใณใใซใไฟฎๆญฃใใพใใ
# app/config/config.yml
monolog:
# ใใญใปใใตใผใไฝฟ็จใใๅ ดๅใฏใใฎใปใฏใทใงใณใฎใณใกใณใใ่งฃ้ค
# Processor :
# session_processor:
# class: Acme\Bundle\MonologBundle\Log\SessionRequestProcessor
# arguments: [ @session ]
# tags:
# - { name: monolog.processor, method: processRecord }
json_formatter:
class: Monolog\Formatter\JsonFormatter
handlers:
# ใญใฐใทใใใผใฎใณใณใใฃใฎใฅใฌใผใทใงใณ
to_json_files:
# lvar/logs/(environment).log ใซ่จ้ฒ
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
# ๅ
จใใฃใใซ (ใใฏใใชใณใใจใฉใผใชใฉ) ใๅซใ
channels: ~
# json ใใฉใผใใใฟใไฝฟ็จ
formatter: monolog.json_formatter
# ใญใฐใฌใใซใ่จญๅฎใใพใ (ไพ: debugใerrorใalert)
level: debug
ๆงๆใใฃใฌใฏใใช /path/to/config/directory/
ใซใใ config_dev.yml
ใจ config_prod.yml
ใซไปฅไธใ่ฟฝๅ ใใฆใใ ใใใ้็บ็ฐๅขใจๆฌ็ช็ฐๅขใซๅใใใๆงๆใซใชใใใใซใใตใณใใซใไฟฎๆญฃใใพใใ
monolog:
handlers:
# ใญใฐใทใใใผๆงๆ
to_json_files:
# var/logs/(environment).log ใซใญใฐใ่จ้ฒใใพใ
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
# JSON ใใฉใผใใใฟใไฝฟ็จใใพใ
formatter: monolog.json_formatter
# ใญใฐใฌใใซใ่จญๅฎใใพใ (ไพ: debugใerrorใalert)
level: debug
้ขๆฐ
\DDTrace\current_context()
ใฏใใใผใธใงใณ
0.61.0 ใงๅฐๅ
ฅใใใฆใใพใใ
ไปฅไธใ่ฟฝๅ ใใพใใ
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
// Monolog ใคใณในใฟใณในใๅๅพ
$monolog = logger()->getLogger();
if (!$monolog instanceof \Monolog\Logger) {
return;
}
// ใชใใทใงใณ: JSON ๅฝขๅผใไฝฟ็จ
$useJson = false;
foreach ($monolog->getHandlers() as $handler) {
if (method_exists($handler, 'setFormatter')) {
$handler->setFormatter(new \Monolog\Formatter\JsonFormatter());
$useJson = true;
}
}
// ใใฌใผในใใใณในใใณ ID ใๆฟๅ
ฅใใฆใญใฐใจใณใใชใ APM ใใฌใผในใจๆฅ็ถ
$monolog->pushProcessor(function ($record) use ($useJson) {
$context = \DDTrace\current_context();
if ($useJson === true) {
$record['extra']['dd'] = [
'trace_id' => $context['trace_id'],
'span_id' => $context['span_id'],
];
} else {
$record['message'] .= sprintf(
' [dd.trace_id=%d dd.span_id=%d]',
$context['trace_id'],
$context['span_id']
);
}
return $record;
});
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
//
}
}
ไปฅไธใ่ฟฝๅ ใใพใใ
<?php
// file: bootstrap
$app->extend('monolog', function($monolog, $app) {
$monolog->pushHandler(...);
// ไธ่จใซใญใฌใผใๆงๆ
return $monolog;
});
ไปฅไธใ่ฟฝๅ ใใพใใ
<?php
//file: bootstrap/app.php
$app->configureMonologUsing(function($monolog) {
$monolog->pushHandler(...);
// ไธ่จใซใญใฌใผใๆงๆ
});
return $app;
ใใฎไปใฎๅ่่ณๆ
ใๅฝนใซ็ซใคใใญใฅใกใณใใใชใณใฏใ่จไบ: