Skip to content

Commit abe594c

Browse files
committed
feat(handler): [DatadogHandler] created
1 parent 86fca1b commit abe594c

File tree

1 file changed

+173
-0
lines changed

1 file changed

+173
-0
lines changed

src/Handlers/DatadogHandler.php

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
<?php
2+
3+
namespace Onramplab\LaravelLogEnhancement\Handlers;
4+
5+
use Exception;
6+
use Monolog\Formatter\JsonFormatter;
7+
use Monolog\Handler\AbstractProcessingHandler;
8+
use Monolog\Handler\Curl\Util;
9+
use Monolog\Handler\MissingExtensionException;
10+
use Monolog\Logger;
11+
12+
class DatadogHandler extends AbstractProcessingHandler
13+
{
14+
protected const BASE_HOST = 'datadoghq.com';
15+
16+
/**
17+
* Datadog Api Key access
18+
*/
19+
private string $key;
20+
21+
/**
22+
* Datadog Api Host
23+
*/
24+
private string $apiHost;
25+
26+
/**
27+
* Datadog optionals attributes
28+
*/
29+
private array $attributes;
30+
31+
/**
32+
* @param string $key Datadog Api Key access
33+
* @param string $region Datadog Region
34+
* @param array $attributes Some options fore Datadog Logs
35+
* @param string|int $level The minimum logging level at which this handler will be triggered
36+
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
37+
*/
38+
public function __construct(
39+
string $key,
40+
string $region = null,
41+
array $attributes = [],
42+
$level = Logger::DEBUG,
43+
bool $bubble = true
44+
) {
45+
if (!extension_loaded('curl')) {
46+
throw new MissingExtensionException('The curl extension is needed to use the DatadogHandler');
47+
}
48+
49+
parent::__construct($level, $bubble);
50+
51+
$this->key = $this->getApiKey($key);
52+
$this->apiHost = $this->getApiHost($region);
53+
$this->attributes = $attributes;
54+
}
55+
56+
/**
57+
* Handles a log record
58+
*/
59+
protected function write(array $record): void
60+
{
61+
$this->send($record['formatted']);
62+
}
63+
64+
/**
65+
* Send request to @link https://docs.datadoghq.com/api/latest/logs/?code-lang=curl#send-logs
66+
* @param string $record
67+
*/
68+
protected function send($record): void
69+
{
70+
$parameters = [
71+
'ddsource' => $this->getSource(),
72+
'hostname' => $this->getHostname(),
73+
'service' => $this->getService($record),
74+
'ddtags' => $this->getTags()
75+
];
76+
$queryString = http_build_query($parameters);
77+
$url = sprintf('https://http-intake.logs.%s/api/v2/logs?%s', $this->apiHost, $queryString);
78+
79+
$headers = [
80+
'DD-API-KEY: ' . $this->key,
81+
'Accept: application/json',
82+
'Content-Type: application/json',
83+
];
84+
85+
$ch = curl_init();
86+
87+
curl_setopt($ch, CURLOPT_URL, $url);
88+
curl_setopt($ch, CURLOPT_POST, true);
89+
curl_setopt($ch, CURLOPT_POSTFIELDS, $record);
90+
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
91+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
92+
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
93+
94+
Util::execute($ch);
95+
}
96+
97+
/**
98+
* Get Datadog Api Key.
99+
* @param string $key
100+
*
101+
* @return string
102+
*/
103+
protected function getApiKey($key)
104+
{
105+
if ($key) {
106+
return $key;
107+
} else {
108+
throw new Exception('The Datadog Api Key is required');
109+
}
110+
}
111+
112+
/**
113+
* Get Datadog Region host.
114+
* @param ?string $region
115+
*
116+
* @return string
117+
*/
118+
protected function getApiHost($region)
119+
{
120+
return $region ? sprintf("%s.%s", $region, self::BASE_HOST) : self::BASE_HOST;
121+
}
122+
/**
123+
* Get Datadog Source from $attributes params.
124+
*
125+
* @return string
126+
*/
127+
protected function getSource()
128+
{
129+
return !empty($this->attributes['source']) ? $this->attributes['source'] : 'php';
130+
}
131+
132+
/**
133+
* Get Datadog Service from $attributes params.
134+
*
135+
* @return string
136+
*/
137+
protected function getService($record)
138+
{
139+
$channel = json_decode($record, true);
140+
141+
return !empty($this->attributes['service']) ? $this->attributes['service'] : $channel['channel'];
142+
}
143+
144+
/**
145+
* Get Datadog Hostname from $attributes params.
146+
*
147+
* @return string
148+
*/
149+
protected function getHostname()
150+
{
151+
return !empty($this->attributes['hostname']) ? $this->attributes['hostname'] : $_SERVER['SERVER_NAME'];
152+
}
153+
154+
/**
155+
* Get Datadog Tags from $attributes params.
156+
*
157+
* @return string
158+
*/
159+
protected function getTags()
160+
{
161+
return !empty($this->attributes['tags']) ? $this->attributes['tags'] : '';
162+
}
163+
164+
/**
165+
* Returns the default formatter to use with this handler
166+
*
167+
* @return JsonFormatter
168+
*/
169+
protected function getDefaultFormatter(): JsonFormatter
170+
{
171+
return new JsonFormatter();
172+
}
173+
}

0 commit comments

Comments
 (0)