Skip to content

Commit 0f54a3d

Browse files
authored
Merge pull request #7 from bufferapp/task/psr3
Use Monolog in a more standard way
2 parents 03d8815 + c0c6160 commit 0f54a3d

4 files changed

Lines changed: 80 additions & 108 deletions

File tree

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
"version": "0.1.0",
55
"require": {
66
"php": "^7.1",
7-
"monolog/monolog": "1.25.*"
7+
"monolog/monolog": "1.25.*",
8+
"psr/log": "^1.1"
89
},
910
"require-dev": {
1011
"datadog/dd-trace": "0.34.*"

composer.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

example.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
Bufflog::error("I am an error");
1717
Bufflog::error("I am an error", ["mean" => "70"]);
1818

19-
Bufflog::critical("I am critical information!");
19+
Bufflog::criticals("I am criticals information with a typo and you shouldn't see me!");
2020
Bufflog::critical("I am critical information!", ["user" => "betrand"]);
2121

2222
Bufflog::critical("I'm critical log, here some extra fancy informations",
@@ -27,5 +27,4 @@
2727
"Facebook",
2828
"Instagram"
2929
]
30-
]
31-
);
30+
]);

src/php-bufflog/BuffLog.php

Lines changed: 75 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -2,123 +2,105 @@
22
namespace Buffer;
33
require_once('vendor/autoload.php');
44

5-
use Monolog\Logger;
6-
use Monolog\Handler\StreamHandler as MonologStreamHandler;
7-
8-
/*
9-
Level of logs we use:
10-
11-
This level require manual action to appear in Datadog Logs
12-
Logger::DEBUG
13-
Logger::INFO
14-
15-
Everything at this level appears by default in Datadog Logs
16-
Logger::WARNING
17-
Logger::ERROR
18-
Logger::CRITICAL
19-
*/
5+
use Monolog\Logger as Logger;
6+
use Monolog\Handler\StreamHandler;
207

218
class BuffLog {
229

23-
private static $logger = null;
24-
private static $currentVerbosity = Logger::WARNING;
25-
private static $verbosityList = [
10+
protected static $instance;
11+
private static $logger = null;
12+
private static $currentVerbosity = Logger::WARNING;
13+
private static $verbosityList = [
2614
"DEBUG" => Logger::DEBUG,
2715
"INFO" => Logger::INFO,
2816
"WARNING" => Logger::WARNING,
2917
"ERROR" => Logger::ERROR,
3018
"CRITICAL" => Logger::CRITICAL
3119
];
3220

33-
public static function debug($message, $context = [])
34-
{
35-
self::setVerbosity();
36-
if (self::$currentVerbosity > Logger::DEBUG) {
37-
return;
38-
}
21+
private static $logOutputMethods = ['debug', 'info', 'notice', 'warning', 'error', 'critical'];
22+
private static $extraAllowedMethods = ['getName', 'pushHandler', 'setHandlers', 'getHandlers', 'pushProcessor', 'getProcessors'];
3923

40-
$logOutput = self::formatLog($message, Logger::DEBUG, $context);
41-
self::getLogger()->debug($logOutput);
42-
}
24+
/**
25+
* Method to return the Monolog instance
26+
*
27+
* @return \Monolog\Logger
28+
*/
29+
static public function getLogger()
30+
{
31+
if (! self::$instance) {
32+
self::configureInstance();
4333

44-
public static function info($message, $context = [])
45-
{
46-
self::setVerbosity();
47-
if (self::$currentVerbosity > Logger::INFO) {
48-
return;
4934
}
35+
return self::$instance;
36+
}
5037

51-
$logOutput = self::formatLog($message, Logger::INFO, $context);
52-
self::getLogger()->info($logOutput);
53-
}
54-
55-
public static function warning($message, $context = [])
38+
protected static function configureInstance()
39+
{
40+
// @TODO: We could potentially use the Kubernetes downward API to
41+
// define the logger name. This will make it easier for developers
42+
// to read and friendlier to identify where come the logs at a glance
43+
$logger = new Logger('php-bufflog');
44+
$handler = new StreamHandler('php://stdout');
45+
$handler->setFormatter( new \Monolog\Formatter\JsonFormatter() );
46+
$logger->pushHandler($handler);
47+
self::$instance = $logger;
48+
}
49+
50+
// This will be called when a static method in the class doesn't exists
51+
public static function __callStatic($methodName, $args)
5652
{
57-
self::setVerbosity();
58-
if (self::$currentVerbosity > Logger::WARNING) {
59-
return;
60-
}
53+
if (method_exists(self::getLogger(), $methodName)) {
6154

62-
$logOutput = self::formatLog($message, Logger::WARNING, $context);
63-
self::getLogger()->warn($logOutput);
64-
}
55+
if (in_array($methodName, array_merge(self::$logOutputMethods, self::$extraAllowedMethods))) {
6556

66-
public static function error($message, $context = [])
67-
{
68-
self::setVerbosity();
69-
if (self::$currentVerbosity > Logger::ERROR) {
70-
return;
71-
}
57+
if (in_array($methodName, self::$logOutputMethods)) {
7258

73-
$logOutput = self::formatLog($message, Logger::ERROR, $context);
74-
self::getLogger()->error($logOutput);
75-
}
59+
// @TODO: need to make sure we "output" only the correct level of log
60+
// old version looked like:
61+
// self::setVerbosity();
62+
// if (self::$currentVerbosity > Logger::WARNING) {
63+
// return;
64+
// }
7665

77-
// @TODO: That one might could also create an alert in Datadog?
78-
public static function critical($message, $context = [])
79-
{
80-
self::setVerbosity();
81-
$logOutput = self::formatLog($message, Logger::CRITICAL, $context);
82-
self::getLogger()->critical($logOutput);
83-
}
66+
self::enrichLog();
67+
}
68+
// Where the magic happen. We "proxy" functions name with arguments to the Monolog instance
69+
return call_user_func_array(array(self::getLogger(), $methodName), $args);
8470

85-
private function formatLog($message, $level, $context = [])
86-
{
87-
// Add traces information to logs to be able correlate with APM
88-
$ddTraceSpan = \DDTrace\GlobalTracer::get()->getActiveSpan();
89-
$context['dd'] = [
90-
"trace_id" => $ddTraceSpan->getTraceId(),
91-
"span_id" => $ddTraceSpan->getSpanId()
92-
];
93-
94-
$output = [
95-
"message" => $message,
96-
"level" => $level,
97-
"datetime" => date(\DateTime::ATOM),
98-
// we could use timestamp if we need ms precision (but it isn't readable) https://docs.datadoghq.com/logs/processing/#reserved-attributes
99-
// 'timestamp' => round(microtime(true) * 1000),
100-
"context" => $context
101-
];
102-
103-
try {
104-
$output = json_encode($output, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
105-
} catch (Exception $e) {
106-
error_log("can't json_encode your message");
107-
}
71+
} else {
10872

109-
return $output;
73+
error_log("BuffLog::$methodName() is not supported yet. Add it to the BuffLog whitelist to allow it");
74+
}
75+
} else {
76+
error_log("BuffLog::$methodName() does not exist");
77+
}
11078
}
11179

112-
private static function createLogger()
80+
private function enrichLog()
11381
{
114-
// @TODO: We could potentially use the Kubernetes downward API to
115-
// define the logger name. This will make it easier for developers
116-
// to read and friendlier to identify where come the logs at a glance
117-
self::$logger = new Logger('php-bufflog');
118-
$handler = new MonologStreamHandler('php://stdout');
119-
120-
self::$logger->pushHandler($handler);
121-
return self::$logger;
82+
// This should probably implemented as a Monolog Processor
83+
// https://github.com/Seldaek/monolog/tree/master/src/Monolog/Processor
84+
self::getLogger()->pushProcessor(function ($record) {
85+
86+
// We should grab any Buffer information useful when available
87+
// Need to check with the Core team: accountID / userID / profileID
88+
// $user = Buffer/Core::getCurrentUser();
89+
// That should look like:
90+
// $record['context']['user'] = array(
91+
// 'accountID' => $user->getAccountID(),
92+
// 'userID' => $user->getUserID(),
93+
// 'profileID' => $user->getProfileID()
94+
// );
95+
96+
// Add traces information to logs to be able correlate with APM
97+
$ddTraceSpan = \DDTrace\GlobalTracer::get()->getActiveSpan();
98+
$record['context']['dd'] = [
99+
"trace_id" => $ddTraceSpan->getTraceId(),
100+
"span_id" => $ddTraceSpan->getSpanId()
101+
];
102+
return $record;
103+
});
122104
}
123105

124106
private static function setVerbosity()
@@ -129,14 +111,4 @@ private static function setVerbosity()
129111
}
130112
}
131113

132-
public static function getLogger()
133-
{
134-
if (!isset(self::$logger)) {
135-
echo "Initializing logger\n";
136-
self::createLogger();
137-
}
138-
139-
return self::$logger;
140-
}
141-
142114
}

0 commit comments

Comments
 (0)