Tuesday, 1 October 2024

Manage multiple types of logs in Symfony

Here’s the complete implementation that allows you to select a logger dynamically based on the APP_LOGGER_TYPE environment variable. This includes the logger interface, logger implementations, user service, user controller, and the service configuration in services.yaml.

1. Logger Interface

File: src/Service/Logger/LoggerInterface.php

namespace App\Service\Logger; interface LoggerInterface { public function log(string $message): void; }

2. File Logger Implementation

File: src/Service/Logger/FileLogger.php

namespace App\Service\Logger; class FileLogger implements LoggerInterface { private string $logFile; public function __construct(string $logFile = 'app.log') { $this->logFile = $logFile; } public function log(string $message): void { file_put_contents($this->logFile, $message . PHP_EOL, FILE_APPEND); } }

3. Database Logger Implementation

File: src/Service/Logger/DatabaseLogger.php

namespace App\Service\Logger; use Doctrine\ORM\EntityManagerInterface; use App\Entity\LogEntry; class DatabaseLogger implements LoggerInterface { private EntityManagerInterface $entityManager; public function __construct(EntityManagerInterface $entityManager) { $this->entityManager = $entityManager; } public function log(string $message): void { $logEntry = new LogEntry(); $logEntry->setMessage($message); $logEntry->setCreatedAt(new \DateTime()); $this->entityManager->persist($logEntry); $this->entityManager->flush(); } }

4. Email Logger Implementation (Optional)

File: src/Service/Logger/EmailLogger.php

namespace App\Service\Logger; class EmailLogger implements LoggerInterface { public function log(string $message): void { // Implement email logging logic here // e.g., sending an email with the log message mail('admin@example.com', 'Log Entry', $message); } }

5. User Service

File: src/Service/UserService.php

namespace App\Service; use App\Service\Logger\LoggerInterface; class UserService { private LoggerInterface $logger; public function __construct(LoggerInterface $logger) { $this->logger = $logger; } public function createUser(string $username): void { $this->logger->log("User $username created."); } }

6. User Controller

File: src/Controller/UserController.php

namespace App\Controller; use App\Service\UserService; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; class UserController extends AbstractController { private UserService $userService; public function __construct(UserService $userService) { $this->userService = $userService; } public function create(): Response { $this->userService->createUser('JohnDoe'); // Uses the injected logger return new Response('User created and logged.'); } }

7. Entity Class for Log Entry (Optional)

File: src/Entity/LogEntry.php

namespace App\Entity; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity() */ class LogEntry { /** * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") */ private int $id; /** * @ORM\Column(type="string") */ private string $message; /** * @ORM\Column(type="datetime") */ private \DateTime $createdAt; public function setMessage(string $message): void { $this->message = $message; } public function setCreatedAt(\DateTime $createdAt): void { $this->createdAt = $createdAt; } }

8. Configure Services in services.yaml

File: config/services.yaml

parameters: log_file: 'app.log' # Default log file location services: # Conditional service based on APP_LOGGER_TYPE App\Service\Logger\LoggerInterface: '@=service("App\Service\Logger\\" . ucfirst(getenv("APP_LOGGER_TYPE")) . "Logger")' App\Service\Logger\DatabaseLogger: arguments: $entityManager: '@doctrine.orm.entity_manager' App\Service\Logger\FileLogger: arguments: $logFile: '%log_file%' # Use the default log file from parameters App\Service\Logger\EmailLogger: ~ # Add EmailLogger service if necessary App\Service\UserService: arguments: $logger: '@=service("App\Service\Logger\\" . ucfirst(getenv("APP_LOGGER_TYPE")) . "Logger")'

9. Update Your .env File

Set the desired default logger in your .env file:

File: .env

APP_LOGGER_TYPE=file # or database, or email

Summary

With this setup:

  • You can easily switch between different logging mechanisms by simply changing the value of APP_LOGGER_TYPE in your .env file.
  • The services.yaml configuration dynamically selects the appropriate logger implementation based on the environment variable, enabling you to use different logging strategies without modifying the service or application logic.

No comments:

Post a Comment

Golang Advanced Interview Q&A