Skip to content

Commit 8954546

Browse files
authored
Merge pull request #14 from clebsonsh/feat/logging-system
feat/logging-system
2 parents 3f051ea + 6280c52 commit 8954546

8 files changed

Lines changed: 199 additions & 2 deletions

File tree

app/Dtos/PostRequestDto.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types=1);
4+
35
namespace App\Dtos;
46

57
use Infra\Interfaces\RequestDtoInterface;

composer.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
"name": "clebson/pure-php-oop",
33
"type": "project",
44
"autoload": {
5+
"files": [
6+
"infra/helper.php"
7+
],
58
"psr-4": {
69
"App\\": "app/",
710
"Infra\\": "infra/",

infra/Interfaces/RequestDtoInterface.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types=1);
4+
35
namespace Infra\Interfaces;
46

57
interface RequestDtoInterface

infra/Support/Log.php

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Infra\Support;
6+
7+
use RuntimeException;
8+
9+
class Log
10+
{
11+
const LEVEL_INFO = 'INFO';
12+
13+
const LEVEL_DEBUG = 'DEBUG';
14+
15+
const LEVEL_WARN = 'WARN';
16+
17+
const LEVEL_ERROR = 'ERROR';
18+
19+
private static ?self $instance = null;
20+
21+
private string $filePath;
22+
23+
/** @var resource */
24+
private $fileHandle;
25+
26+
private function __construct()
27+
{
28+
$logsDirectory = storage_path().'/logs';
29+
if (! file_exists($logsDirectory)) {
30+
// @codeCoverageIgnoreStart
31+
mkdir($logsDirectory, 0755, true);
32+
// @codeCoverageIgnoreEnd
33+
}
34+
35+
$today = date('Ymd');
36+
$this->filePath = $logsDirectory."/app-{$today}.log";
37+
38+
/** @todo delete old log files */
39+
$fileHandle = fopen($this->filePath, 'a');
40+
41+
if (! $fileHandle) {
42+
// @codeCoverageIgnoreStart
43+
throw new RuntimeException("Unable to open log file: $this->filePath");
44+
// @codeCoverageIgnoreEnd
45+
}
46+
47+
$this->fileHandle = $fileHandle;
48+
}
49+
50+
public static function getInstance(): self
51+
{
52+
if (self::$instance === null) {
53+
self::$instance = new self;
54+
}
55+
56+
return self::$instance;
57+
}
58+
59+
public function info(string $message): void
60+
{
61+
fwrite($this->fileHandle, $this->buildMessage($message, self::LEVEL_INFO));
62+
}
63+
64+
public function debug(string $message): void
65+
{
66+
fwrite($this->fileHandle, $this->buildMessage($message, self::LEVEL_DEBUG));
67+
}
68+
69+
public function warn(string $message): void
70+
{
71+
fwrite($this->fileHandle, $this->buildMessage($message, self::LEVEL_WARN));
72+
}
73+
74+
public function error(string $message): void
75+
{
76+
fwrite($this->fileHandle, $this->buildMessage($message, self::LEVEL_ERROR));
77+
}
78+
79+
private function buildMessage(string $message, string $level): string
80+
{
81+
/** @todo php timezone is set to UTC, find a way to make it configurable */
82+
$timestamp = '['.date('Y-m-d H:i:s', time())."] $level: ";
83+
84+
return $timestamp.$message.PHP_EOL;
85+
}
86+
87+
public function __destruct()
88+
{
89+
// @codeCoverageIgnoreStart
90+
if ($this->fileHandle !== null) {
91+
fclose($this->fileHandle);
92+
}
93+
// @codeCoverageIgnoreEnd
94+
}
95+
}

infra/helper.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Infra\Support\Log;
6+
7+
function root_path(): string
8+
{
9+
return dirname(__DIR__);
10+
}
11+
12+
function storage_path(): string
13+
{
14+
return root_path().'/storage';
15+
}
16+
17+
function info(string $message): void
18+
{
19+
$logger = Log::getInstance();
20+
21+
$logger->info($message);
22+
}
23+
24+
function debug(string $message): void
25+
{
26+
$logger = Log::getInstance();
27+
28+
$logger->debug($message);
29+
}
30+
function error(string $message): void
31+
{
32+
$logger = Log::getInstance();
33+
34+
$logger->error($message);
35+
}
36+
function warn(string $message): void
37+
{
38+
$logger = Log::getInstance();
39+
40+
$logger->warn($message);
41+
}

public/index.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@
3232
} catch (Throwable $e) {
3333
// Case the application crash
3434
// Log the actual error for the developer
35-
// @todo Create proper Application logger
36-
error_log($e->getMessage());
35+
error((string) $e);
3736

3837
// Show a generic error to the user
3938
http_response_code(500);

storage/logs/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*
2+
!.gitignore
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
describe('Log', function () {
6+
it('put info message in log file', function () {
7+
$message = 'test info message';
8+
9+
info($message);
10+
11+
$today = date('Ymd');
12+
$logFilePath = storage_path()."/logs/app-$today.log";
13+
$logFile = file_get_contents($logFilePath);
14+
15+
expect(str_contains($logFile, $message))->toBeTrue();
16+
});
17+
18+
it('put debug message in log file', function () {
19+
$message = 'test debug message';
20+
21+
debug($message);
22+
23+
$today = date('Ymd');
24+
$logFilePath = storage_path()."/logs/app-$today.log";
25+
$logFile = file_get_contents($logFilePath);
26+
27+
expect(str_contains($logFile, $message))->toBeTrue();
28+
});
29+
30+
it('put warn message in log file', function () {
31+
$message = 'test warn message';
32+
33+
warn($message);
34+
35+
$today = date('Ymd');
36+
$logFilePath = storage_path()."/logs/app-$today.log";
37+
$logFile = file_get_contents($logFilePath);
38+
39+
expect(str_contains($logFile, $message))->toBeTrue();
40+
});
41+
42+
it('put error message in log file', function () {
43+
$message = 'test error message';
44+
45+
error($message);
46+
47+
$today = date('Ymd');
48+
$logFilePath = storage_path()."/logs/app-$today.log";
49+
$logFile = file_get_contents($logFilePath);
50+
51+
expect(str_contains($logFile, $message))->toBeTrue();
52+
});
53+
});

0 commit comments

Comments
 (0)