Skip to content

Commit cc7bfe9

Browse files
authored
Merge pull request #4 from OpenForgeProject/feature/log-message-groups
feat: add option to group log entries by message content in workspace configuration
2 parents 0200e7b + 4e87678 commit cc7bfe9

File tree

6 files changed

+70
-24
lines changed

6 files changed

+70
-24
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how
66

77
## [Unreleased]
88

9+
### Added
10+
11+
- Added Feature in Workspace configuration option to group log entries by message content.
12+
- When grouping is enabled, the counter will display "grouped" (e.g., `INFO (128, grouped)`).
13+
914
## [1.2.2] - 2024-11-19
1015

1116
### Fixed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44

55
The Magento Log Viewer extension for Visual Studio Code provides a convenient way to view and manage Magento log files directly in your workspace.
66

7+
![Magento Log Viewer Screenshot](resources/logVideo.gif)
8+
79
## Features
810

911
- Tree view of log files from Magento's `var/log` directory
1012
- Grouped log entries by severity level (ERROR, WARN, DEBUG, INFO)
13+
- Option to group log entries by message content
1114
- Direct file opening with line highlighting
1215
- One-click log file clearing
1316
- Status bar showing total log entries
@@ -30,6 +33,7 @@ Note: Settings are workspace-specific, allowing different configurations for eac
3033
- **Refresh**: Click the refresh icon or wait for auto-update
3134
- **Navigate**: Click on log entries to jump to specific lines
3235
- **Filter**: Expand log files to see entries grouped by severity
36+
- **Group by Message**: Enable or disable grouping of log entries by message content in the settings. When enabled, the counter will display "grouped" (e.g., `INFO (128, grouped)`).
3337

3438
## Requirements
3539

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@
5252
"default": "",
5353
"description": "Path to the Magento root folder",
5454
"scope": "resource"
55+
},
56+
"magentoLogViewer.groupByMessage": {
57+
"type": "boolean",
58+
"default": true,
59+
"description": "Group log entries by message content",
60+
"scope": "resource"
5561
}
5662
}
5763
},

resources/logVideo.gif

172 KB
Loading

resources/screenshot.png

-60.1 KB
Binary file not shown.

src/logViewer.ts

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ export class LogViewerProvider implements vscode.TreeDataProvider<LogFile>, vsco
66
private _onDidChangeTreeData: vscode.EventEmitter<LogFile | undefined | void> = new vscode.EventEmitter<LogFile | undefined | void>();
77
readonly onDidChangeTreeData: vscode.Event<LogFile | undefined | void> = this._onDidChangeTreeData.event;
88
private statusBarItem: vscode.StatusBarItem;
9+
private groupByMessage: boolean;
910

1011
constructor(private workspaceRoot: string) {
1112
this.statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 100);
1213
this.statusBarItem.command = 'magento-log-viewer.refreshLogFiles';
1314
this.statusBarItem.show();
15+
this.groupByMessage = vscode.workspace.getConfiguration('magentoLogViewer').get<boolean>('groupByMessage', true);
1416
this.updateBadge();
1517
}
1618

@@ -91,40 +93,69 @@ export class LogViewerProvider implements vscode.TreeDataProvider<LogFile>, vsco
9193
}
9294

9395
private groupLogEntries(lines: string[], filePath: string): LogFile[] {
94-
const grouped = new Map<string, { line: string, lineNumber: number }[]>();
96+
const groupedByType = new Map<string, { message: string, line: string, lineNumber: number }[]>();
9597

9698
lines.forEach((line, index) => {
9799
const match = line.match(/\.(\w+):/);
98100
if (match) {
99-
const level = match[1].toUpperCase(); // Changed to uppercase
101+
const level = match[1].toUpperCase();
100102
const message = line.replace(/^\[.*?\]\s*\.\w+:\s*/, '');
101-
const entries = grouped.get(level) || [];
102-
entries.push({ line: message, lineNumber: index });
103-
grouped.set(level, entries);
103+
const entries = groupedByType.get(level) || [];
104+
entries.push({ message, line, lineNumber: index });
105+
groupedByType.set(level, entries);
104106
}
105107
});
106108

107-
return Array.from(grouped.entries()).map(([level, entries]) => {
108-
const count = entries.length;
109-
const label = `${level} (${count})`;
110-
const logFile = new LogFile(label, vscode.TreeItemCollapsibleState.Collapsed, undefined,
111-
entries.map(entry => {
112-
const lineNumber = (entry.lineNumber + 1).toString().padStart(2, '0');
113-
return new LogFile(
114-
`Line ${lineNumber}: ${entry.line}`,
115-
vscode.TreeItemCollapsibleState.None,
116-
{
117-
command: 'magento-log-viewer.openFileAtLine',
118-
title: 'Open Log File at Line',
119-
arguments: [filePath, entry.lineNumber]
120-
}
109+
return Array.from(groupedByType.entries()).map(([level, entries]) => {
110+
if (this.groupByMessage) {
111+
const groupedByMessage = new Map<string, { line: string, lineNumber: number }[]>();
112+
113+
entries.forEach(entry => {
114+
const messageGroup = groupedByMessage.get(entry.message) || [];
115+
messageGroup.push({ line: entry.line, lineNumber: entry.lineNumber });
116+
groupedByMessage.set(entry.message, messageGroup);
117+
});
118+
119+
const messageGroups = Array.from(groupedByMessage.entries()).map(([message, messageEntries]) => {
120+
const count = messageEntries.length;
121+
const label = `${message} (${count})`;
122+
return new LogFile(label, vscode.TreeItemCollapsibleState.Collapsed, undefined,
123+
messageEntries.map(entry => {
124+
const lineNumber = (entry.lineNumber + 1).toString().padStart(2, '0');
125+
return new LogFile(
126+
`Line ${lineNumber}: ${entry.line}`,
127+
vscode.TreeItemCollapsibleState.None,
128+
{
129+
command: 'magento-log-viewer.openFileAtLine',
130+
title: 'Open Log File at Line',
131+
arguments: [filePath, entry.lineNumber]
132+
}
133+
);
134+
})
121135
);
122-
})
123-
);
136+
});
124137

125-
// Set icon based on known log levels, use default for others
126-
logFile.iconPath = this.getIconForLogLevel(level);
127-
return logFile;
138+
const logFile = new LogFile(`${level} (${entries.length}, grouped)`, vscode.TreeItemCollapsibleState.Collapsed, undefined, messageGroups);
139+
logFile.iconPath = this.getIconForLogLevel(level);
140+
return logFile;
141+
} else {
142+
const logFile = new LogFile(`${level} (${entries.length})`, vscode.TreeItemCollapsibleState.Collapsed, undefined,
143+
entries.map(entry => {
144+
const lineNumber = (entry.lineNumber + 1).toString().padStart(2, '0');
145+
return new LogFile(
146+
`Line ${lineNumber}: ${entry.line}`,
147+
vscode.TreeItemCollapsibleState.None,
148+
{
149+
command: 'magento-log-viewer.openFileAtLine',
150+
title: 'Open Log File at Line',
151+
arguments: [filePath, entry.lineNumber]
152+
}
153+
);
154+
})
155+
);
156+
logFile.iconPath = this.getIconForLogLevel(level);
157+
return logFile;
158+
}
128159
});
129160
}
130161

0 commit comments

Comments
 (0)