vaibhavpandeyvpz/drishti
Composer 安装命令:
composer require vaibhavpandeyvpz/drishti
包简介
A lightweight, flexible PSR-3 compliant logging library with configurable backends and zero dependencies.
README 文档
README
A lightweight, flexible PSR-3 compliant logging library with configurable backends, PSR-20 Clock support, and minimal dependencies.
Drishti (
दृष्टि) - Sanskrit for "Vision" or "Sight", representing the ability to see and record what happens in your application.
Features
- ✅ PSR-3 Compliant - Full implementation of the PSR-3 LoggerInterface specification
- ✅ PSR-20 Clock Support - Uses PSR-20 ClockInterface for time operations (testable and flexible)
- ✅ Minimal Dependencies - Only requires PSR-3 interface (psr/log) and PSR-20 Clock (psr/clock)
- ✅ Configurable Backends - Contract-based backend system for flexible log destinations
- ✅ Multiple Backends - Send logs to multiple destinations simultaneously
- ✅ First-Party Backends - Built-in support for stdout, stderr, files, and daily rotating files
- ✅ First-Party Formatters - Built-in SimpleLogEntryFormatter and JsonLogEntryFormatter
- ✅ Message Interpolation - Automatic placeholder replacement with context data
- ✅ Exception Handling - Automatic exception information in log entries
- ✅ All Log Levels - Supports all 8 PSR-3 log levels
- ✅ Modern PHP - Built for PHP 8.2+ with modern language features
- ✅ 100% Test Coverage - Fully tested with comprehensive test suite
Installation
Install via Composer:
composer require vaibhavpandeyvpz/drishti
Quick Start
<?php use Drishti\Logger; // Create a new logger instance $logger = new Logger(); // Log messages at different levels $logger->info('User logged in'); $logger->warning('Disk space is running low'); $logger->error('Failed to connect to database'); // Use context for message interpolation $logger->info('User {username} logged in from {ip}', [ 'username' => 'john', 'ip' => '192.168.1.1', ]); // For structured logging (JSON format) use Drishti\JsonLogEntryFormatter; $jsonLogger = new Logger(new FileBackend('/var/log/app.json', new JsonLogEntryFormatter())); $jsonLogger->info('User {username} logged in from {ip}', [ 'username' => 'john', 'ip' => '192.168.1.1', ]); // Log exceptions try { // Some code that might throw } catch (\Exception $e) { $logger->error('An error occurred', [ 'exception' => $e, ]); }
Usage
Basic Logging
The Logger class implements the PSR-3 LoggerInterface and provides methods for all standard log levels:
use Drishti\Logger; $logger = new Logger(); // Emergency: System is unusable $logger->emergency('System is down'); // Alert: Action must be taken immediately $logger->alert('Database connection lost'); // Critical: Critical conditions $logger->critical('Application component unavailable'); // Error: Runtime errors $logger->error('Failed to process request'); // Warning: Exceptional occurrences $logger->warning('Deprecated API used'); // Notice: Normal but significant events $logger->notice('User profile updated'); // Info: Interesting events $logger->info('User logged in'); // Debug: Detailed debug information $logger->debug('Processing request with ID: 12345');
Message Interpolation
Drishti supports PSR-3 message interpolation using placeholders in the form {key}:
$logger->info('User {username} performed {action} on {resource}', [ 'username' => 'admin', 'action' => 'delete', 'resource' => 'file.txt', ]); // Output: User admin performed delete on file.txt
Context Data Types
The logger handles various context data types:
// Strings and numbers $logger->info('Processed {count} items', ['count' => 42]); // Booleans $logger->info('Feature enabled: {enabled}', ['enabled' => true]); // Arrays (JSON encoded) $logger->info('User roles: {roles}', ['roles' => ['admin', 'user']]); // Objects (class name or __toString() result) $logger->info('Object: {obj}', ['obj' => $myObject]); // Null values $logger->info('User: {user}', ['user' => null]);
Exception Logging
When an exception is included in the context with the key exception, Drishti automatically appends exception details:
try { // Some code that might throw throw new \RuntimeException('Something went wrong', 500); } catch (\Exception $e) { $logger->error('An error occurred', [ 'exception' => $e, ]); } // Output includes: [Exception: Something went wrong in /path/to/file.php:123]
Using the log() Method
You can also use the generic log() method with any valid PSR-3 log level:
use Psr\Log\LogLevel; $logger->log(LogLevel::INFO, 'Custom log message'); $logger->log(LogLevel::ERROR, 'Error occurred', ['error_code' => 500]);
Stringable Messages
Messages can be strings or objects implementing \Stringable:
$message = new class implements \Stringable { public function __toString(): string { return 'Dynamic message'; } }; $logger->info($message);
Backend System
Drishti uses a contract-based backend system that allows you to configure where logs are written. You can use one or more backends simultaneously.
Default Behavior
If no backends are configured, Drishti uses default behavior:
- Error levels (emergency, alert, critical, error): Written to
STDERR - Informational levels (warning, notice, info, debug): Written to
STDOUT
Using Backends
Configure backends when creating the logger:
use Drishti\Logger; use Drishti\StdioBackend; use Drishti\FileBackend; use Drishti\DailyFileBackend; // Single backend $logger = new Logger(StdioBackend::stdout()); // Multiple backends $logger = new Logger([ StdioBackend::stdout(), new FileBackend('/var/log/app.log'), ]); // Or add backends after creation $logger = new Logger(); $logger->addBackend(StdioBackend::stdout()) ->addBackend(new FileBackend('/var/log/app.log'));
Available Backends
StdioBackend
Writes logs to standard I/O streams (STDOUT or STDERR). Use static factory methods to create instances:
use Drishti\Logger; use Drishti\StdioBackend; // Write to STDOUT (ideal for containerized applications) $logger = new Logger(StdioBackend::stdout()); $logger->info('This goes to STDOUT'); // Write to STDERR (useful for separating logs from application output) $logger = new Logger(StdioBackend::stderr()); $logger->error('This goes to STDERR'); // With custom formatter use Drishti\JsonLogEntryFormatter; $formatter = new JsonLogEntryFormatter(); $logger = new Logger(StdioBackend::stdout($formatter)); // With custom clock (for testing or timezone control) use Psr\Clock\ClockInterface; use Samay\FrozenClock; $clock = new FrozenClock(new \DateTimeImmutable('2024-01-15 10:00:00')); $formatter = new JsonLogEntryFormatter($clock); $logger = new Logger(StdioBackend::stdout($formatter));
FileBackend
Writes logs to a single file. The directory will be created automatically if it doesn't exist:
use Drishti\Logger; use Drishti\FileBackend; $logger = new Logger(new FileBackend('/var/log/app.log')); $logger->info('This is written to the file'); // With custom clock use Psr\Clock\ClockInterface; $clock = new MyCustomClock(); $logger = new Logger(new FileBackend('/var/log/app.log', null, $clock));
DailyFileBackend
Writes logs to daily rotating files (logrotate style). Files are named with the date suffix:
use Drishti\Logger; use Drishti\DailyFileBackend; $logger = new Logger(new DailyFileBackend('/var/log/app')); // Creates files like: /var/log/app-2024-01-15.log // Automatically rotates to new file each day $logger->info('This goes to today\'s log file'); // With custom clock (useful for testing date rotation) use Psr\Clock\ClockInterface; $clock = new MyCustomClock(); $logger = new Logger(new DailyFileBackend('/var/log/app', null, $clock));
Custom Backends
Create your own backend by implementing BackendInterface:
use Drishti\BackendInterface; use Drishti\LogEntryFormatterInterface; class DatabaseBackend implements BackendInterface { public function __construct( private readonly \PDO $database, private readonly ?LogEntryFormatterInterface $formatter = null ) {} public function write(string $level, string $message, array $context): void { // Format the message using formatter (or your own logic) $formatted = $this->formatter?->format($level, $message, $context) ?? "[$level] $message"; // Write to database, external service, etc. $this->database->prepare('INSERT INTO logs (level, message, context, created_at) VALUES (?, ?, ?, ?)') ->execute([ $level, $message, json_encode($context), (new \DateTimeImmutable)->format('Y-m-d H:i:s'), ]); } } $logger = new Logger(new DatabaseBackend($pdo));
Multiple Backends
Send logs to multiple destinations simultaneously:
use Drishti\Logger; use Drishti\StdioBackend; use Drishti\FileBackend; use Drishti\DailyFileBackend; $logger = new Logger([ StdioBackend::stdout(), // Console output new FileBackend('/var/log/app.log'), // Single file new DailyFileBackend('/var/log/daily'), // Daily rotating files ]); $logger->info('This message goes to all three backends');
Formatters
Drishti includes two first-party formatters and supports custom formatters.
SimpleLogEntryFormatter (Default)
The default formatter produces human-readable log entries:
use Drishti\Logger; use Drishti\FileBackend; use Drishti\SimpleLogEntryFormatter; // SimpleLogEntryFormatter is used by default $logger = new Logger(new FileBackend('/var/log/app.log')); // Or explicitly specify it $formatter = new SimpleLogEntryFormatter(); $logger = new Logger(new FileBackend('/var/log/app.log', $formatter));
Output format: [2024-01-15 10:30:45] INFO: User logged in
JsonLogEntryFormatter
For structured logging, use the JSON formatter:
use Drishti\Logger; use Drishti\FileBackend; use Drishti\JsonLogEntryFormatter; $formatter = new JsonLogEntryFormatter(); $logger = new Logger(new FileBackend('/var/log/app.json', $formatter)); $logger->info('User {username} logged in', ['username' => 'john', 'ip' => '192.168.1.1']);
Output format:
{
"timestamp": "2024-01-15T10:30:45+00:00",
"level": "INFO",
"message": "User john logged in",
"context": { "username": "john", "ip": "192.168.1.1" }
}
The JSON formatter includes:
- ISO 8601 timestamp
- Uppercased log level
- Interpolated message
- Exception details (if present)
- Remaining context data
Custom Formatters
You can create custom formatters by implementing LogEntryFormatterInterface:
use Drishti\LogEntryFormatterInterface; use Psr\Clock\ClockInterface; class CustomFormatter implements LogEntryFormatterInterface { public function __construct( private readonly ?ClockInterface $clock = null ) { $this->clock = $clock ?? new class implements ClockInterface { public function now(): \DateTimeImmutable { return new \DateTimeImmutable; } }; } public function format(string $level, string $message, array $context): string { // Your custom formatting logic // Interpolate message, handle exceptions, format output return $formatted; } } // Use custom formatter with any backend $formatter = new CustomFormatter(); $logger = new Logger(new FileBackend('/var/log/app.log', $formatter));
PSR-20 Clock Support
Drishti uses PSR-20 ClockInterface for all time operations, making it testable and flexible. All backends and formatters accept an optional ClockInterface instance.
For testing, you can use a frozen clock like samay:
use Drishti\Logger; use Drishti\FileBackend; use Samay\FrozenClock; // In tests, use a frozen clock for predictable timestamps $fixedTime = new \DateTimeImmutable('2024-01-15 10:30:45'); $clock = new FrozenClock($fixedTime); $logger = new Logger(new FileBackend('/var/log/test.log', null, $clock)); $logger->info('Test message'); // Timestamp will always be 2024-01-15 10:30:45
Output Format
All log entries include a timestamp in the format [YYYY-MM-DD HH:MM:SS].
Example output:
[2024-01-15 10:30:45] INFO: User john logged in from 192.168.1.1
[2024-01-15 10:30:46] ERROR: Database connection failed [Exception: Connection timeout in /app/Database.php:42]
Requirements
- PHP 8.2 or higher
- PSR-3 interface (psr/log)
- PSR-20 Clock interface (psr/clock)
For testing, we recommend samay for frozen clocks:
composer require --dev vaibhavpandeyvpz/samay
License
This project is licensed under the MIT License. See the LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Support
For issues, questions, or contributions, please visit the GitHub repository.
vaibhavpandeyvpz/drishti 适用场景与选型建议
vaibhavpandeyvpz/drishti 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 31 次下载、GitHub Stars 达 2, 最近一次更新时间为 2025 年 12 月 28 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「logging」 「logger」 「psr-3」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 vaibhavpandeyvpz/drishti 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 vaibhavpandeyvpz/drishti 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 vaibhavpandeyvpz/drishti 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
A Zend Framework module that sets up Monolog for logging in applications.
Workflow logger
HTTP request logger middleware for Laravel
PSR-3 compatible logger with dynamic file naming and hourly rotation, powered by Monolog
Chronolog is a tool that allows you to send logs to files, sockets, mailboxes, databases, etc.
Asynchronous Sentry for Symfony - Fire and forget
统计信息
- 总下载量: 31
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 2
- 点击次数: 10
- 依赖项目数: 1
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-12-28