Skip to content

Commit 06e6b9d

Browse files
committed
feat: implement comprehensive logging system for Icon Manager
- Add lightweight initialization pattern to prevent log spam during plugin startup - Create dedicated icon-manager-YYYY-MM-DD.log files with proper rotation (30 days) - Implement LoggingTrait with template substitution for readable log messages - Add log level configuration (error/warning/info/trace) with proper filtering - Fix log target configuration to match Translation Manager's clean format - Add comprehensive logging throughout services: * Cache operations (hits/misses/clears) with performance timing * SVG scanning and parsing with error handling * Icon set validation with detailed error messages in readable format * Database operations with performance metrics - Create logs management interface in Control Panel: * View, filter, and search log entries by date/level/content * Download log files for external analysis * Display file sizes and entry counts * Real-time filtering without form submission - Update documentation (README.md, CONFIGURATION.md) with logging features - Add log configuration section to settings with current level display - Enhance log messages to include meaningful context in readable format: * Icon set names instead of just IDs * Icon types and counts * Cache expiration times * Detailed validation errors - Create comprehensive translation file with 200+ logging-related strings
1 parent e3b36a7 commit 06e6b9d

File tree

15 files changed

+648
-287
lines changed

15 files changed

+648
-287
lines changed

README.md

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,14 @@ return [
9898
'dev' => [
9999
// Use source icons in dev
100100
'iconSetsPath' => '@root/src/icons',
101-
101+
102102
// Enable caching in dev for performance
103103
'enableCache' => true,
104104
'cacheDuration' => 3600, // 1 hour
105-
105+
106+
// Detailed logging for development
107+
'logLevel' => 'trace',
108+
106109
// Allow all icon types for testing
107110
'enabledIconTypes' => [
108111
'svg-folder' => true,
@@ -126,16 +129,19 @@ return [
126129
'production' => [
127130
// Production icons path
128131
'iconSetsPath' => '@webroot/dist/assets/icons',
129-
132+
130133
// Optimize for production
131134
'enableCache' => true,
132135
'cacheDuration' => 2592000, // 30 days
133-
136+
137+
// Minimal logging for production
138+
'logLevel' => 'warning',
139+
134140
// Only stable icon types in production
135141
'enabledIconTypes' => [
136142
'svg-folder' => true,
137143
'svg-sprite' => false, // Beta
138-
'font-awesome' => false, // Beta
144+
'font-awesome' => false, // Beta
139145
'material-icons' => false, // Beta
140146
],
141147
],
@@ -153,6 +159,7 @@ See [Configuration Documentation](docs/CONFIGURATION.md) for all available optio
153159
- **enableCache** - Whether to cache icon data for better performance
154160
- **cacheDuration** - How long to cache icon data, in seconds
155161
- **enabledIconTypes** - Enable/disable specific icon set types
162+
- **logLevel** - Logging verbosity: error, warning, info, or trace
156163

157164
### Creating Icon Sets
158165

@@ -433,10 +440,40 @@ return [
433440

434441
## Logging
435442

436-
Icon Manager logs warnings and errors to dedicated date-based log files:
443+
Icon Manager includes comprehensive logging with configurable levels:
444+
445+
### Log Levels
446+
- **Error**: Critical errors only
447+
- **Warning**: Errors and warnings
448+
- **Info**: General information
449+
- **Trace**: Detailed debugging (includes performance metrics)
450+
451+
### Configuration
452+
```php
453+
// config/icon-manager.php
454+
return [
455+
'logLevel' => 'info', // error, warning, info, or trace
456+
];
457+
```
458+
459+
### Log Files
437460
- **Location**: `storage/logs/icon-manager-YYYY-MM-DD.log`
438-
- **What's logged**: Missing icons, errors, warnings
439-
- **Not logged**: Info messages, routine operations
461+
- **Retention**: 30 days (automatic cleanup)
462+
- **Format**: Structured logs with context data
463+
- **Web Interface**: View and filter logs in CP at Icon Manager → Logs
464+
465+
### What's Logged
466+
- **Error**: File system failures, SVG parsing errors, database errors
467+
- **Warning**: Missing icons, empty content, slow operations (>1s)
468+
- **Info**: Icon set operations, cache clears, major actions
469+
- **Trace**: Cache hits/misses, performance timing, API requests
470+
471+
### Log Management
472+
Access logs through the Control Panel:
473+
1. Navigate to Icon Manager → Logs
474+
2. Filter by date, level, or search terms
475+
3. Download log files for external analysis
476+
4. View file sizes and entry counts
440477

441478
## Environment-Specific Paths
442479

docs/CONFIGURATION.md

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,17 @@ You can override plugin settings by creating an `icon-manager.php` file in your
1616
return [
1717
// Plugin settings
1818
'pluginName' => 'Icon Manager',
19-
19+
2020
// Icon sets path
2121
'iconSetsPath' => '@root/src/icons',
22-
22+
2323
// Caching settings
2424
'enableCache' => true,
2525
'cacheDuration' => 86400, // 24 hours in seconds
26-
26+
27+
// Logging settings
28+
'logLevel' => 'info', // error, warning, info, trace
29+
2730
// Icon types to enable
2831
'enabledIconTypes' => [
2932
'svg-folder' => true,
@@ -60,6 +63,7 @@ return [
6063
'iconSetsPath' => '@root/src/icons',
6164
'enableCache' => true,
6265
'cacheDuration' => 3600, // 1 hour
66+
'logLevel' => 'trace', // Detailed logging for development
6367
'enabledIconTypes' => [
6468
'svg-folder' => true,
6569
'svg-sprite' => true,
@@ -80,10 +84,11 @@ return [
8084
'iconSetsPath' => '@webroot/dist/assets/icons',
8185
'enableCache' => true,
8286
'cacheDuration' => 2592000, // 30 days
87+
'logLevel' => 'warning', // Minimal logging for production
8388
'enabledIconTypes' => [
8489
'svg-folder' => true,
8590
'svg-sprite' => false, // Beta
86-
'font-awesome' => false, // Beta
91+
'font-awesome' => false, // Beta
8792
'material-icons' => false, // Beta
8893
],
8994
],
@@ -99,6 +104,7 @@ return [
99104
'enableCache' => getenv('ICON_MANAGER_CACHE') === 'true',
100105
'cacheDuration' => (int)getenv('ICON_CACHE_DURATION') ?: 86400,
101106
'iconSetsPath' => getenv('ICON_SETS_PATH') ?: '@root/icons',
107+
'logLevel' => getenv('ICON_LOG_LEVEL') ?: 'info',
102108
];
103109
```
104110

@@ -117,6 +123,14 @@ return [
117123
- **enableCache**: Enable/disable icon data caching for better performance
118124
- **cacheDuration**: How long to cache icon data in seconds
119125

126+
#### Logging Settings
127+
128+
- **logLevel**: Logging verbosity level
129+
- `error` - Critical errors only
130+
- `warning` - Errors and warnings
131+
- `info` - General information (recommended for production)
132+
- `trace` - Detailed debugging with performance metrics (development only)
133+
120134
#### Icon Type Settings
121135

122136
- **enabledIconTypes**: Enable/disable specific icon set types
@@ -159,6 +173,44 @@ For production environments:
159173
'cacheDuration' => min((int)getenv('CACHE_DURATION') ?: 86400, 604800), // Max 7 days
160174
```
161175

176+
## Logging Configuration
177+
178+
### Log Levels and Performance
179+
180+
Choose the appropriate log level for your environment:
181+
182+
- **Production**: Use `warning` or `error` to minimize log volume
183+
- **Staging**: Use `info` for operational visibility
184+
- **Development**: Use `trace` for debugging and performance analysis
185+
186+
### Log File Management
187+
188+
- **Location**: `storage/logs/icon-manager-YYYY-MM-DD.log`
189+
- **Retention**: 30 days automatic cleanup
190+
- **File Size**: Includes file size display in CP interface
191+
- **Web Interface**: Access via Icon Manager → Logs in Control Panel
192+
193+
### Environment-Specific Logging
194+
195+
```php
196+
'dev' => [
197+
'logLevel' => 'trace', // Full debugging
198+
],
199+
'staging' => [
200+
'logLevel' => 'info', // Operations monitoring
201+
],
202+
'production' => [
203+
'logLevel' => 'warning', // Errors and warnings only
204+
],
205+
```
206+
207+
### Performance Impact
208+
209+
- **trace**: High verbosity, includes cache operations and timing
210+
- **info**: Moderate verbosity, normal operations
211+
- **warning**: Low verbosity, problems only
212+
- **error**: Minimal verbosity, critical issues only
213+
162214
## Icon Metadata Configuration
163215

164216
You can also configure icon metadata files alongside your icon configuration. See the main README for details on `metadata.json` structure and multilingual label support.

src/IconManager.php

Lines changed: 45 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -353,48 +353,54 @@ private function _clearIconCache(): void
353353
*/
354354
private function _registerLogTarget(): void
355355
{
356-
// Prevent duplicate registration across requests
357-
if (self::$_logTargetRegistered) {
356+
// Skip if already configured
357+
if (isset(Craft::$app->getLog()->targets['icon-manager'])) {
358358
return;
359359
}
360360

361-
if (Craft::$app->has('log')) {
362-
// Get base logs path
363-
$logsPath = Craft::$app->getPath()->getLogPath();
364-
365-
// Use date-based log file naming
366-
$date = date('Y-m-d');
367-
$logFile = $logsPath . "/icon-manager-{$date}.log";
368-
369-
// Get log level from settings with fallback
370-
$logLevel = $this->getSettings()->logLevel ?? 'error';
371-
372-
// Map log level to array of levels to include
373-
$levels = match ($logLevel) {
374-
'trace' => ['error', 'warning', 'info', 'trace'],
375-
'info' => ['error', 'warning', 'info'],
376-
'warning' => ['error', 'warning'],
377-
'error' => ['error'],
378-
default => ['error', 'warning', 'info']
379-
};
380-
381-
// Create a new log target instance
382-
$target = new \yii\log\FileTarget([
383-
'logFile' => $logFile,
384-
'categories' => ['icon-manager', 'icon-manager*', 'lindemannrock\iconmanager\*'],
385-
'logVars' => [],
386-
'levels' => $levels,
387-
'maxFileSize' => 10240, // 10MB
388-
'maxLogFiles' => 30, // Keep 30 days
389-
'rotateByCopy' => false
390-
]);
391-
392-
// Add the target to the log dispatcher
393-
Craft::$app->getLog()->targets[] = $target;
394-
395-
// Mark as registered
396-
self::$_logTargetRegistered = true;
397-
}
361+
// Get base logs path
362+
$logsPath = Craft::$app->getPath()->getLogPath();
363+
364+
// Use date-based log file naming
365+
$date = date('Y-m-d');
366+
$logFile = $logsPath . "/icon-manager-{$date}.log";
367+
368+
// Get log level from settings with fallback
369+
$logLevel = $this->getSettings()->logLevel ?? 'error';
370+
371+
// Map log level to array of levels to include
372+
$levels = match ($logLevel) {
373+
'trace' => ['error', 'warning', 'info', 'trace'],
374+
'info' => ['error', 'warning', 'info'],
375+
'warning' => ['error', 'warning'],
376+
'error' => ['error'],
377+
default => ['error', 'warning', 'info']
378+
};
379+
380+
// Create a new log target instance
381+
$target = new \yii\log\FileTarget([
382+
'logFile' => $logFile,
383+
'categories' => ['icon-manager'],
384+
'logVars' => [],
385+
'levels' => $levels,
386+
'maxFileSize' => 10240, // 10MB
387+
'maxLogFiles' => 30, // Keep 30 days
388+
'prefix' => function ($message) {
389+
$user = Craft::$app->has('user', true) ? Craft::$app->getUser() : null;
390+
$userId = $user && !$user->getIsGuest() ? $user->getId() : '-';
391+
return "[user:{$userId}]";
392+
},
393+
'rotateByCopy' => false
394+
]);
395+
396+
// Add the target to the log dispatcher and ensure it's available immediately
397+
Craft::$app->getLog()->targets['icon-manager'] = $target;
398+
399+
// Initialize the target immediately
400+
$target->init();
401+
402+
// Mark as registered
403+
self::$_logTargetRegistered = true;
398404
}
399405

400406
}

src/controllers/IconsController.php

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
namespace lindemannrock\iconmanager\controllers;
1010

1111
use lindemannrock\iconmanager\IconManager;
12+
use lindemannrock\iconmanager\traits\LoggingTrait;
1213

1314
use Craft;
1415
use craft\web\Controller;
@@ -19,6 +20,8 @@
1920
*/
2021
class IconsController extends Controller
2122
{
23+
use LoggingTrait;
24+
2225
/**
2326
* @var array|bool|int Allow anonymous access
2427
*/
@@ -32,17 +35,26 @@ public function actionRender(): Response
3235
$request = Craft::$app->getRequest();
3336
$iconSetHandle = $request->getRequiredParam('iconSet');
3437
$iconName = $request->getRequiredParam('icon');
35-
38+
39+
$this->logTrace("Icon render request: {$iconSetHandle}:{$iconName}", [
40+
'iconSet' => $iconSetHandle,
41+
'icon' => $iconName,
42+
'userAgent' => $request->getUserAgent(),
43+
'ip' => $request->getUserIP()
44+
]);
45+
3646
$iconSet = IconManager::getInstance()->iconSets->getIconSetByHandle($iconSetHandle);
3747
if (!$iconSet || !$iconSet->enabled) {
48+
$this->logWarning("Icon render failed - icon set not found or disabled: {$iconSetHandle}");
3849
throw new \yii\web\NotFoundHttpException('Icon set not found');
3950
}
40-
51+
4152
$icon = IconManager::getInstance()->icons->getIcon($iconSetHandle, $iconName);
4253
if (!$icon) {
54+
$this->logWarning("Icon render failed - icon not found: {$iconSetHandle}:{$iconName}");
4355
throw new \yii\web\NotFoundHttpException('Icon not found');
4456
}
45-
57+
4658
// Return SVG content
4759
return $this->asRaw($icon->getContent())->format(Response::FORMAT_RAW);
4860
}
@@ -53,21 +65,29 @@ public function actionRender(): Response
5365
public function actionGetData(): Response
5466
{
5567
$this->requireAcceptsJson();
56-
68+
5769
$request = Craft::$app->getRequest();
5870
$iconSetHandle = $request->getRequiredParam('iconSet');
5971
$iconName = $request->getRequiredParam('icon');
60-
72+
73+
$this->logTrace("Icon data request (AJAX): {$iconSetHandle}:{$iconName}", [
74+
'iconSet' => $iconSetHandle,
75+
'icon' => $iconName,
76+
'requestType' => 'ajax-data'
77+
]);
78+
6179
$iconSet = IconManager::getInstance()->iconSets->getIconSetByHandle($iconSetHandle);
6280
if (!$iconSet || !$iconSet->enabled) {
81+
$this->logWarning("Icon data request failed - icon set not found: {$iconSetHandle}");
6382
return $this->asJson(['error' => 'Icon set not found']);
6483
}
65-
84+
6685
$icon = IconManager::getInstance()->icons->getIcon($iconSetHandle, $iconName);
6786
if (!$icon) {
87+
$this->logWarning("Icon data request failed - icon not found: {$iconSetHandle}:{$iconName}");
6888
return $this->asJson(['error' => 'Icon not found']);
6989
}
70-
90+
7191
return $this->asJson([
7292
'success' => true,
7393
'icon' => [

0 commit comments

Comments
 (0)