-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
517 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
/.idea | ||
/*.iml | ||
/vendor | ||
/composer.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,59 @@ | ||
# default-psr-logger | ||
A simple PSR-3 compliant logger | ||
|
||
## Installation | ||
|
||
This library is designed to be used with [Composer](https://getcomposer.org) | ||
|
||
Require entry: | ||
|
||
```json | ||
{ | ||
"myena/default-psr-logger": "@stable" | ||
} | ||
``` | ||
|
||
## Basic Usage | ||
|
||
```php | ||
$logger = new \MyENA\DefaultLogger(); | ||
|
||
$logger->debug('hello!'); | ||
``` | ||
|
||
## Defaults | ||
|
||
The default level of this logger is `debug` | ||
|
||
The default stream for this logger is `php://output` | ||
|
||
## Custom Levels | ||
|
||
You may specify custom levels one of two ways: | ||
|
||
**Construction**: | ||
```php | ||
$logger = new \MyENA\DefaultLogger(\Psr\Log\LogLevel::INFO); | ||
``` | ||
|
||
**Post-Construction**: | ||
```php | ||
$logger->setLogLevel(\Psr\Log\LogLevel::INFO); | ||
``` | ||
|
||
If you attempt to specify a level not denoted by | ||
[\Psr\Log\LogLevel](https://github.com/php-fig/log/blob/1.0.2/Psr/Log/LogLevel.php), an exception will be thrown. | ||
|
||
## Custom Stream | ||
|
||
If you wish for the log output to go to a file or some other resource writeable by the | ||
[fwrite](http://php.net/manual/en/function.fwrite.php) function, you may pass it in as the 2nd argument. | ||
|
||
```php | ||
$logger = new \MyENA\DefaultLogger(\Psr\Log\LogLevel::DEBUG, fopen('tmp/test.log', 'ab')); | ||
``` | ||
|
||
If this file becomes un-writeable for some reason, it will attempt to reconstruct the internal resource. If it is | ||
unable, it will revert to using the stream returned by the [defaultStream()](./src/DefaultLogger.php#L133). | ||
|
||
**NOTE**: No write-ability determination is done, if you pass in a read-only stream it will ultimately not work. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
{ | ||
"name": "myena/default-logger", | ||
"type": "library", | ||
"description": "A simple PSR-3 compliant logger", | ||
"license": "MPLv2.0", | ||
"authors": [ | ||
{ | ||
"name": "Daniel Carbone", | ||
"email": "dcarbone@ena.com" | ||
} | ||
], | ||
|
||
"autoload": { | ||
"psr-4": { | ||
"MyENA\\": "src/" | ||
} | ||
}, | ||
|
||
"require": { | ||
"psr/log": "1.*" | ||
}, | ||
|
||
"require-dev": { | ||
"phpunit/phpunit": "5.7.*" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<phpunit | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.5/phpunit.xsd" | ||
bootstrap="./vendor/autoload.php" | ||
backupGlobals="true" | ||
backupStaticAttributes="false" | ||
cacheTokens="false" | ||
colors="false" | ||
convertErrorsToExceptions="false" | ||
convertNoticesToExceptions="false" | ||
convertWarningsToExceptions="false" | ||
forceCoversAnnotation="false" | ||
mapTestClassNameToCoveredClassName="false" | ||
printerClass="PHPUnit_TextUI_ResultPrinter" | ||
processIsolation="false" | ||
stopOnError="false" | ||
stopOnFailure="false" | ||
stopOnIncomplete="false" | ||
stopOnSkipped="false" | ||
stopOnRisky="false" | ||
testSuiteLoaderClass="PHPUnit_Runner_StandardTestSuiteLoader" | ||
timeoutForSmallTests="1" | ||
timeoutForMediumTests="10" | ||
timeoutForLargeTests="60" | ||
verbose="false"> | ||
|
||
<testsuites> | ||
<testsuite name="default"> | ||
<file>./tests/DefaultStateTest.php</file> | ||
</testsuite> | ||
<testsuite name="custom"> | ||
<file>./tests/CustomStateTest.php</file> | ||
</testsuite> | ||
</testsuites> | ||
|
||
<filter> | ||
<whitelist processUncoveredFilesFromWhitelist="true"> | ||
<directory suffix=".php">./src/</directory> | ||
</whitelist> | ||
</filter> | ||
|
||
<logging> | ||
<log type="coverage-html" target="tmp/report" lowUpperBound="35" highLowerBound="70" /> | ||
</logging> | ||
|
||
</phpunit> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<phpunit | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.5/phpunit.xsd" | ||
bootstrap="./vendor/autoload.php" | ||
backupGlobals="true" | ||
backupStaticAttributes="false" | ||
cacheTokens="false" | ||
colors="false" | ||
convertErrorsToExceptions="false" | ||
convertNoticesToExceptions="false" | ||
convertWarningsToExceptions="false" | ||
forceCoversAnnotation="false" | ||
mapTestClassNameToCoveredClassName="false" | ||
printerClass="PHPUnit_TextUI_ResultPrinter" | ||
processIsolation="false" | ||
stopOnError="false" | ||
stopOnFailure="false" | ||
stopOnIncomplete="false" | ||
stopOnSkipped="false" | ||
stopOnRisky="false" | ||
testSuiteLoaderClass="PHPUnit_Runner_StandardTestSuiteLoader" | ||
timeoutForSmallTests="1" | ||
timeoutForMediumTests="10" | ||
timeoutForLargeTests="60" | ||
verbose="false"> | ||
|
||
<testsuites> | ||
<testsuite name="default"> | ||
<file>./tests/DefaultStateTest.php</file> | ||
</testsuite> | ||
<testsuite name="custom"> | ||
<file>./tests/CustomStateTest.php</file> | ||
</testsuite> | ||
</testsuites> | ||
|
||
|
||
|
||
</phpunit> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
<?php namespace MyENA; | ||
|
||
/* | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
*/ | ||
|
||
use Psr\Log\AbstractLogger; | ||
use Psr\Log\LogLevel; | ||
|
||
/** | ||
* Class DefaultLogger | ||
* | ||
* @package MyENA | ||
*/ | ||
class DefaultLogger extends AbstractLogger | ||
{ | ||
/** @var string */ | ||
public static $dateTimeFormat = \DateTime::RFC3339; | ||
|
||
/** @var resource */ | ||
protected $stream; | ||
|
||
/** @var string */ | ||
protected $streamURI; | ||
/** @var string */ | ||
protected $streamMode; | ||
|
||
/** @var string */ | ||
protected $level; | ||
|
||
/** @var array */ | ||
protected $levelMap = [ | ||
LogLevel::DEBUG => 0, | ||
LogLevel::INFO => 1, | ||
LogLevel::NOTICE => 2, | ||
LogLevel::WARNING => 3, | ||
LogLevel::ERROR => 4, | ||
LogLevel::CRITICAL => 5, | ||
LogLevel::ALERT => 6, | ||
LogLevel::EMERGENCY => 7, | ||
]; | ||
|
||
/** | ||
* DefaultLogger constructor. | ||
* | ||
* @param string $level | ||
* @param resource|null $writeableStream | ||
*/ | ||
public function __construct($level = LogLevel::DEBUG, $writeableStream = null) | ||
{ | ||
$this->setLogLevel($level); | ||
|
||
if (null === $writeableStream) | ||
$this->stream = $this->defaultStream(); | ||
else | ||
$this->stream = $writeableStream; | ||
|
||
$m = stream_get_meta_data($this->stream); | ||
$this->streamMode = $m['mode']; | ||
$this->streamURI = $m['uri']; | ||
} | ||
|
||
/** | ||
* @return array | ||
*/ | ||
public function getPossibleLogLevels() | ||
{ | ||
return $this->levelMap; | ||
} | ||
|
||
/** | ||
* @return string | ||
*/ | ||
public function getLogLevel() | ||
{ | ||
return $this->level; | ||
} | ||
|
||
/** | ||
* setLogLevel will limit what is written to a level greater than or equal to value passed in. | ||
* | ||
* @param string $logLevel | ||
*/ | ||
public function setLogLevel($logLevel) | ||
{ | ||
if (!is_string($logLevel) || '' === ($level = strtolower($logLevel)) || !isset($this->levelMap[$level])) | ||
{ | ||
throw new \InvalidArgumentException(sprintf( | ||
'%s - Log level must be one of the following values: ["%s"]. %s seen.', | ||
get_called_class(), | ||
implode('", "', array_keys($this->levelMap)), | ||
is_string($logLevel) ? $logLevel : gettype($logLevel) | ||
)); | ||
} | ||
|
||
$this->level = $level; | ||
} | ||
|
||
/** | ||
* Logs with an arbitrary level. | ||
* | ||
* @param mixed $level | ||
* @param string $message | ||
* @param array $context | ||
* | ||
* @return void | ||
*/ | ||
public function log($level, $message, array $context = array()) | ||
{ | ||
if (!is_string($level) || !isset($this->levelMap[$level])) | ||
throw new \InvalidArgumentException(sprintf('"%s" is an unknown log level', $level)); | ||
|
||
if ($this->levelMap[$this->level] <= $this->levelMap[$level]) | ||
{ | ||
$slug = sprintf('[%s]%s', strtolower($level), str_repeat(' ', 15 - strlen($level))); | ||
if ("\n" !== substr($message, -1)) | ||
$message .= "\n"; | ||
|
||
$msg = sprintf('%s%s %s', $slug, date(static::$dateTimeFormat), $message); | ||
|
||
$this->tryLog($msg); | ||
} | ||
} | ||
|
||
/** | ||
* defaultStream will be used if no alternative is passed in during construction or if specified stream closes | ||
* unexpectedly | ||
* | ||
* @return resource | ||
*/ | ||
protected function defaultStream() | ||
{ | ||
return fopen('php://output', 'a'); | ||
} | ||
|
||
/** | ||
* tryLog will attempt to write output to local stream. If unable, will kick-off re-open attempt | ||
* | ||
* @param string $msg | ||
* @param int $tries | ||
*/ | ||
protected function tryLog($msg, $tries = 0) | ||
{ | ||
if ((bool)@fwrite($this->stream, $msg)) | ||
return; | ||
|
||
if (0 < $tries) | ||
{ | ||
trigger_error(sprintf('%s - Unable to log message: "%s"', get_called_class(), $tries, $msg)); | ||
return; | ||
} | ||
|
||
$this->attemptStreamRecovery(); | ||
|
||
$this->tryLog($msg, ++$tries); | ||
} | ||
|
||
/** | ||
* Will attempt to re-open stream in the event that it was closed unexpectedly. Will use default if unable to | ||
* re-open custom | ||
* | ||
* @see DefaultLogger::defaultStream() | ||
*/ | ||
protected function attemptStreamRecovery() | ||
{ | ||
if ('resource' === gettype($this->stream)) | ||
{ | ||
@fflush($this->stream); | ||
@fclose($this->stream); | ||
} | ||
|
||
$this->stream = fopen($this->streamURI, $this->streamMode); | ||
if (false === $this->stream) | ||
{ | ||
trigger_error(sprintf( | ||
'%s - Unable to write to "%s" and re-open attempt failed, will default to php-output', | ||
get_called_class(), | ||
$this->streamURI)); | ||
|
||
$this->stream = $this->defaultStream(); | ||
} | ||
} | ||
} |
Oops, something went wrong.