Skip to content

Commit 0dec838

Browse files
committed
Add possibility to add PSR-3 loggers
1 parent 1ca55d1 commit 0dec838

File tree

6 files changed

+338
-1
lines changed

6 files changed

+338
-1
lines changed

examples/server.php

+6
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,19 @@
77
require __DIR__ . '/../src/Timer.php';
88
require __DIR__ . '/../src/TimerCollection.php';
99

10+
require __DIR__ . '/../src/Logger/LoggerInterface.php';
11+
require __DIR__ . '/../src/Logger/AbstractLogger.php';
12+
require __DIR__ . '/../src/Logger/LogLevel.php';
13+
require __DIR__ . '/../src/Logger/StdOutLogger.php';
14+
1015
require __DIR__ . '/../src/Application/ApplicationInterface.php';
1116
require __DIR__ . '/../src/Application/Application.php';
1217
require __DIR__ . '/../src/Application/StatusApplication.php';
1318

1419
require __DIR__ . '/Application/Chat.php';
1520

1621
$server = new \Bloatless\WebSocket\Server('127.0.0.1', 8000, '/tmp/phpwss.sock');
22+
$server->addLogger(new \Bloatless\WebSocket\Application\StdOutLogger());
1723

1824
// server settings:
1925
$server->setMaxClients(100);

src/Logger/AbstractLogger.php

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<?php
2+
3+
namespace Psr\Log;
4+
5+
/**
6+
* This is a simple Logger implementation that other Loggers can inherit from.
7+
*
8+
* It simply delegates all log-level-specific methods to the `log` method to
9+
* reduce boilerplate code that a simple Logger that does the same thing with
10+
* messages regardless of the error level has to implement.
11+
*/
12+
abstract class AbstractLogger implements LoggerInterface
13+
{
14+
/**
15+
* System is unusable.
16+
*
17+
* @param string $message
18+
* @param array $context
19+
*
20+
* @return void
21+
*/
22+
public function emergency($message, array $context = array())
23+
{
24+
$this->log(LogLevel::EMERGENCY, $message, $context);
25+
}
26+
27+
/**
28+
* Action must be taken immediately.
29+
*
30+
* Example: Entire website down, database unavailable, etc. This should
31+
* trigger the SMS alerts and wake you up.
32+
*
33+
* @param string $message
34+
* @param array $context
35+
*
36+
* @return void
37+
*/
38+
public function alert($message, array $context = array())
39+
{
40+
$this->log(LogLevel::ALERT, $message, $context);
41+
}
42+
43+
/**
44+
* Critical conditions.
45+
*
46+
* Example: Application component unavailable, unexpected exception.
47+
*
48+
* @param string $message
49+
* @param array $context
50+
*
51+
* @return void
52+
*/
53+
public function critical($message, array $context = array())
54+
{
55+
$this->log(LogLevel::CRITICAL, $message, $context);
56+
}
57+
58+
/**
59+
* Runtime errors that do not require immediate action but should typically
60+
* be logged and monitored.
61+
*
62+
* @param string $message
63+
* @param array $context
64+
*
65+
* @return void
66+
*/
67+
public function error($message, array $context = array())
68+
{
69+
$this->log(LogLevel::ERROR, $message, $context);
70+
}
71+
72+
/**
73+
* Exceptional occurrences that are not errors.
74+
*
75+
* Example: Use of deprecated APIs, poor use of an API, undesirable things
76+
* that are not necessarily wrong.
77+
*
78+
* @param string $message
79+
* @param array $context
80+
*
81+
* @return void
82+
*/
83+
public function warning($message, array $context = array())
84+
{
85+
$this->log(LogLevel::WARNING, $message, $context);
86+
}
87+
88+
/**
89+
* Normal but significant events.
90+
*
91+
* @param string $message
92+
* @param array $context
93+
*
94+
* @return void
95+
*/
96+
public function notice($message, array $context = array())
97+
{
98+
$this->log(LogLevel::NOTICE, $message, $context);
99+
}
100+
101+
/**
102+
* Interesting events.
103+
*
104+
* Example: User logs in, SQL logs.
105+
*
106+
* @param string $message
107+
* @param array $context
108+
*
109+
* @return void
110+
*/
111+
public function info($message, array $context = array())
112+
{
113+
$this->log(LogLevel::INFO, $message, $context);
114+
}
115+
116+
/**
117+
* Detailed debug information.
118+
*
119+
* @param string $message
120+
* @param array $context
121+
*
122+
* @return void
123+
*/
124+
public function debug($message, array $context = array())
125+
{
126+
$this->log(LogLevel::DEBUG, $message, $context);
127+
}
128+
}

src/Logger/LogLevel.php

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace Psr\Log;
4+
5+
/**
6+
* Describes log levels.
7+
*/
8+
class LogLevel
9+
{
10+
const EMERGENCY = 'emergency';
11+
const ALERT = 'alert';
12+
const CRITICAL = 'critical';
13+
const ERROR = 'error';
14+
const WARNING = 'warning';
15+
const NOTICE = 'notice';
16+
const INFO = 'info';
17+
const DEBUG = 'debug';
18+
}

src/Logger/LoggerInterface.php

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
<?php
2+
3+
namespace Psr\Log;
4+
5+
/**
6+
* Describes a logger instance.
7+
*
8+
* The message MUST be a string or object implementing __toString().
9+
*
10+
* The message MAY contain placeholders in the form: {foo} where foo
11+
* will be replaced by the context data in key "foo".
12+
*
13+
* The context array can contain arbitrary data. The only assumption that
14+
* can be made by implementors is that if an Exception instance is given
15+
* to produce a stack trace, it MUST be in a key named "exception".
16+
*
17+
* See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
18+
* for the full interface specification.
19+
*/
20+
interface LoggerInterface
21+
{
22+
/**
23+
* System is unusable.
24+
*
25+
* @param string $message
26+
* @param mixed[] $context
27+
*
28+
* @return void
29+
*/
30+
public function emergency($message, array $context = array());
31+
32+
/**
33+
* Action must be taken immediately.
34+
*
35+
* Example: Entire website down, database unavailable, etc. This should
36+
* trigger the SMS alerts and wake you up.
37+
*
38+
* @param string $message
39+
* @param mixed[] $context
40+
*
41+
* @return void
42+
*/
43+
public function alert($message, array $context = array());
44+
45+
/**
46+
* Critical conditions.
47+
*
48+
* Example: Application component unavailable, unexpected exception.
49+
*
50+
* @param string $message
51+
* @param mixed[] $context
52+
*
53+
* @return void
54+
*/
55+
public function critical($message, array $context = array());
56+
57+
/**
58+
* Runtime errors that do not require immediate action but should typically
59+
* be logged and monitored.
60+
*
61+
* @param string $message
62+
* @param mixed[] $context
63+
*
64+
* @return void
65+
*/
66+
public function error($message, array $context = array());
67+
68+
/**
69+
* Exceptional occurrences that are not errors.
70+
*
71+
* Example: Use of deprecated APIs, poor use of an API, undesirable things
72+
* that are not necessarily wrong.
73+
*
74+
* @param string $message
75+
* @param mixed[] $context
76+
*
77+
* @return void
78+
*/
79+
public function warning($message, array $context = array());
80+
81+
/**
82+
* Normal but significant events.
83+
*
84+
* @param string $message
85+
* @param mixed[] $context
86+
*
87+
* @return void
88+
*/
89+
public function notice($message, array $context = array());
90+
91+
/**
92+
* Interesting events.
93+
*
94+
* Example: User logs in, SQL logs.
95+
*
96+
* @param string $message
97+
* @param mixed[] $context
98+
*
99+
* @return void
100+
*/
101+
public function info($message, array $context = array());
102+
103+
/**
104+
* Detailed debug information.
105+
*
106+
* @param string $message
107+
* @param mixed[] $context
108+
*
109+
* @return void
110+
*/
111+
public function debug($message, array $context = array());
112+
113+
/**
114+
* Logs with an arbitrary level.
115+
*
116+
* @param mixed $level
117+
* @param string $message
118+
* @param mixed[] $context
119+
*
120+
* @return void
121+
*
122+
* @throws \Psr\Log\InvalidArgumentException
123+
*/
124+
public function log($level, $message, array $context = array());
125+
}

src/Logger/StdOutLogger.php

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Bloatless\WebSocket\Application;
6+
7+
use Psr\Log\AbstractLogger;
8+
use Psr\Log\LogLevel;
9+
10+
class StdOutLogger extends AbstractLogger
11+
{
12+
private const OUTMAP = [
13+
LogLevel::EMERGENCY => STDERR,
14+
LogLevel::ALERT => STDERR,
15+
LogLevel::CRITICAL => STDERR,
16+
LogLevel::ERROR => STDERR,
17+
18+
LogLevel::WARNING => STDOUT,
19+
LogLevel::NOTICE => STDOUT,
20+
LogLevel::INFO => STDOUT,
21+
LogLevel::DEBUG => STDOUT,
22+
];
23+
24+
/**
25+
* Logs a message to stdout/stderr.
26+
*
27+
* @param mixed $level
28+
* @param string $message
29+
* @param array $context
30+
*/
31+
public function log($level, $message, array $context = [])
32+
{
33+
$level = $level ?? LogLevel::ERROR;
34+
$output = isset(self::OUTMAP[$level]) ? self::OUTMAP[$level] : STDERR;
35+
fwrite($output, date('Y-m-d H:i:s') . ' [' . $level . '] ' . $message . PHP_EOL);
36+
}
37+
}

src/Server.php

+24-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Bloatless\WebSocket;
66

77
use Bloatless\WebSocket\Application\ApplicationInterface;
8+
use Psr\Log\LoggerInterface;
89

910
/**
1011
* Simple WebSocket server implementation in PHP.
@@ -105,6 +106,11 @@ class Server
105106
*/
106107
private TimerCollection $timers;
107108

109+
/**
110+
* @var array $loggers Holds all loggers.
111+
*/
112+
private array $loggers = [];
113+
108114
/**
109115
* @param string $host
110116
* @param int $port
@@ -260,7 +266,24 @@ public function registerApplication(string $key, ApplicationInterface $applicati
260266
*/
261267
public function log(string $message, string $type = 'info'): void
262268
{
263-
echo date('Y-m-d H:i:s') . ' [' . ($type ? $type : 'error') . '] ' . $message . PHP_EOL;
269+
if ($this->loggers === []) {
270+
return;
271+
}
272+
273+
/** @var LoggerInterface $logger */
274+
foreach ($this->loggers as $logger) {
275+
$logger->log($type, $message);
276+
}
277+
}
278+
279+
/**
280+
* Adds a logger to the stack.
281+
*
282+
* @param LoggerInterface $logger
283+
*/
284+
public function addLogger(LoggerInterface $logger): void
285+
{
286+
$this->loggers[] = $logger;
264287
}
265288

266289
/**

0 commit comments

Comments
 (0)