A modern, web-based log viewer built with Next.js for analyzing and filtering structured application logs. Perfect for development, debugging, and monitoring applications that generate structured log files.
- π Multi-file Support - Automatically reads and combines multiple log files
- π Advanced Filtering - Filter by log level (INFO, ERROR, WARNING, etc.) and source file
- π Full-text Search - Search across messages, modules, and timestamps
- π Clean Interface - View logs in an organized table with syntax highlighting
- π Real-time Refresh - Reload logs on demand to see latest entries
- π Multi-line Log Support - Properly handles stack traces and multi-line entries
- β‘ Fast & Responsive - Built with performance in mind using Next.js App Router
- π¨ Modern UI - Beautiful, responsive design with Tailwind CSS
- Node.js 18+
- npm or yarn
- Clone the repository:
git clone https://github.com/shozibabbas/structured-logs-viewer.git
cd structured-logs-viewer- Install dependencies:
npm install- Start the development server:
npm run dev- Open http://localhost:3000 in your browser
Place your .log files in the logs/ directory at the project root:
structured-logs-viewer/
βββ logs/
β βββ application.log
β βββ errors.log
β βββ debug.log
β βββ access.log
βββ app/
βββ lib/
βββ ...
The viewer expects logs in the following pipe-delimited format:
YYYY-MM-DD HH:MM:SS,mmm | LEVEL | module_name | message
Example:
2026-01-30 14:32:15,123 | INFO | auth.service | User authentication successful
2026-01-30 14:32:16,456 | ERROR | db.connection | Connection timeout after 30s
2026-01-30 14:32:17,789 | WARNING | cache.redis | Cache miss for key: user_session_abc123
Supported Log Levels:
INFOWARNING/WARNERRORDEBUGCRITICAL/FATAL
Configure Python's logging module to output in the expected format:
import logging
import os
# Set log level from environment or default to INFO
LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO").upper()
# Configure logging format to match the viewer's expected format
logging.basicConfig(
level=LOG_LEVEL,
format="%(asctime)s | %(levelname)s | %(name)s | %(message)s"
)
# Create logger for your module
log = logging.getLogger("your_module_name")
# Use it in your code
log.info("Application started successfully")
log.warning("Cache miss for key: %s", cache_key)
log.error("Database connection failed: %s", error_message)Using popular logging libraries like Winston or Pino:
const winston = require('winston');
const logger = winston.createLogger({
format: winston.format.combine(
winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss,SSS' }),
winston.format.printf(({ timestamp, level, message }) => {
return `${timestamp} | ${level.toUpperCase()} | ${process.env.MODULE_NAME || 'app'} | ${message}`;
})
),
transports: [
new winston.transports.File({ filename: 'logs/application.log' })
]
});
logger.info('User authentication successful');
logger.error('Connection timeout after 30s');The key is to use a format string that outputs:
- Timestamp in
YYYY-MM-DD HH:MM:SS,mmmformat - Pipe separator (
|) - Log level (INFO, ERROR, etc.)
- Pipe separator (
|) - Module/logger name
- Pipe separator (
|) - Message
The parser automatically handles multi-line log entries, such as stack traces:
2026-01-30 14:35:42,123 | ERROR | api.handler | Request failed with exception
Traceback (most recent call last):
File "/app/api/handler.py", line 42, in process_request
result = process_data(request.body)
ValueError: Invalid input format
- Navigate to http://localhost:3000
- Click "View Logs"
- Use the filters and search bar to find specific entries
- Click "Refresh" to reload logs from disk
Retrieves all parsed log entries from the logs/ directory.
Response:
{
"logs": [
{
"timestamp": "2026-01-30 14:32:15,123",
"level": "INFO",
"module": "auth.service",
"message": "User authentication successful",
"fileName": "application.log",
"rawLine": "2026-01-30 14:32:15,123 | INFO | auth.service | User authentication successful",
"lineNumber": 42,
"packetId": "packet_1_2026-01-30 14:32:10,000",
"isPacketStart": false,
"isPacketEnd": false
}
],
"totalEntries": 1523,
"files": ["application.log", "errors.log"],
"packets": ["packet_1_2026-01-30 14:32:10,000", "packet_2_2026-01-30 14:45:22,100"],
"settings": {
"enablePackets": true,
"packetStartPattern": "Received message on",
"packetEndPattern": "Processed OK"
}
}Retrieves current log parsing settings.
Response:
{
"settings": {
"id": 1,
"enablePackets": true,
"packetStartPattern": "Received message on",
"packetEndPattern": "Processed OK",
"createdAt": "2026-01-30 12:00:00",
"updatedAt": "2026-01-30 12:30:00"
}
}Updates log parsing settings.
Request Body:
{
"enablePackets": true,
"packetStartPattern": "Received message on",
"packetEndPattern": "Processed OK"
}Response:
{
"settings": {
"id": 1,
"enablePackets": true,
"packetStartPattern": "Received message on",
"packetEndPattern": "Processed OK",
"createdAt": "2026-01-30 12:00:00",
"updatedAt": "2026-01-30 12:35:00"
},
"message": "Settings updated successfully"
}Error Responses:
404- Logs directory not found500- Failed to read log files
structured-logs-viewer/
βββ app/
β βββ api/
β β βββ logs/
β β β βββ route.ts # API endpoint for reading logs
β β βββ settings/
β β βββ route.ts # API endpoint for settings
β βββ logs/
β β βββ page.tsx # Main logs viewer interface
β βββ settings/
β β βββ page.tsx # Settings configuration page
β βββ layout.tsx # Root layout
β βββ page.tsx # Landing page
β βββ globals.css # Global styles
βββ lib/
β βββ logParser.ts # Log parsing utilities
β βββ database.ts # SQLite database management
βββ logs/ # Place your .log files here
β βββ sample.log # Example log file
βββ data/ # SQLite database (auto-generated)
β βββ settings.db
βββ public/ # Static assets
βββ package.json
βββ tsconfig.json
βββ next.config.ts
βββ README.md
npm run build
npm startnpm run lintnpx tsc --noEmitBy default, logs are read from the logs/ directory. To use a different location, modify the path in app/api/logs/route.ts:
const logsDir = path.join(process.cwd(), 'your-logs-directory');To support a different log format, update the regex pattern in lib/logParser.ts:
const logPattern = /your-custom-pattern/;Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- Built with Next.js
- Styled with Tailwind CSS
- Icons from Heroicons
Project Link: https://github.com/shozibabbas/structured-logs-viewer
Made with β€οΈ for developers who love clean logs