firstlog
Version:
Modern middleware based logger for Express.js
274 lines (206 loc) • 8.34 kB
Markdown
<p align="center">
<img src="https://res.cloudinary.com/domebtgvk/image/upload/v1751872966/free-wood-log-icon-download-in-svg-png-gif-file-formats--wooden-timber-firewood-autumn-pack-nature-icons-5002823_zdbj46.png" alt="Firstlog Logo" width="180" />
</p>
<h1 align="center"><strong>Firstlog</strong></h1>
<p align="center">
<img src="https://img.shields.io/npm/v/firstlog.svg?style=for-the-badge" alt="NPM version" />
<img src="https://img.shields.io/npm/dm/firstlog.svg?style=for-the-badge" alt="NPM downloads" />
<img src="https://img.shields.io/github/stars/adidecodes/firstlog.svg?style=for-the-badge" alt="GitHub stars" />
<img src="https://img.shields.io/badge/built%20with-TypeScript-blue.svg?style=for-the-badge" alt="Built with TypeScript" />
</p>
<p align="center">
<em>Firstlog is a flexible and powerful Express.js middleware for advanced request logging with comprehensive features like geographic tracking, performance monitoring, and customizable output formats.</em>
</p>
## Features
- 🚀 **Easy Integration** - Simple Express middleware setup
- 📊 **Performance Monitoring** - Track request duration and identify slow requests
- 🌍 **Geographic Tracking** - Optional GeoIP location tracking
- 🔒 **Security** - Mask sensitive fields in logs
- 📝 **Flexible Logging** - Outputs is JSON object format
- 🎯 **Selective Logging** - Filter by paths, errors, or custom conditions
- 📦 **TypeScript Support** - Full TypeScript definitions included
- 🔧 **Highly Configurable** - Extensive customization options
## Installation
```bash
npm install firstlog
```
To use the optional GeoIP feature, you must also install `geoip-lite`:
```bash
npm install geoip-lite
```
## Quick Start
```typescript
import express from "express";
import { logger } from "firstlog";
const app = express();
// Basic usage
app.use(
logger({
logFile: "./logs/access.log",
})
);
// Your routes
app.get("/", (req, res) => {
res.json({ message: "Hello World" });
});
app.listen(3000);
```
## Configuration Options
### Basic Options
| Option | Type | Default | Description |
| ------------- | ---------- | ----------------------- | --------------------------------- |
| `logFile` | `string` | **Required** | Path to the log file |
| `maskFields` | `string[]` | `['password', 'token']` | Fields to mask in logs |
| `captureBody` | `boolean` | `true` | Whether to capture request body |
| `prettyPrint` | `boolean` | `false` | Format JSON logs with indentation |
### Advanced Options
| Option | Type | Default | Description |
| ----------------- | ---------- | ---------------- | -------------------------------------------------- |
| `onlyLogOnError` | `boolean` | `false` | Only log requests that result in errors (4xx, 5xx) |
| `maxBodySize` | `number` | `1024` | Maximum body size to log (in bytes) |
| `slowThresholdMs` | `number` | `1000` | Threshold for marking requests as slow |
| `excludePaths` | `string[]` | `[]` | Paths to exclude from logging |
| `requestIdHeader` | `string` | `'x-request-id'` | Header name for request ID |
### Feature Toggles
| Option | Type | Default | Description |
| ----------------- | --------- | ------- | ------------------------------------- |
| `trackQuery` | `boolean` | `false` | Include query parameters in logs |
| `trackOrigin` | `boolean` | `false` | Track the origin of the request |
| `enableGeoIP` | `boolean` | `false` | Enable geographic IP tracking |
| `logHeaders` | `boolean` | `false` | Include request headers in logs |
| `logParams` | `boolean` | `false` | Include route parameters in logs |
| `logResponseBody` | `boolean` | `false` | Include response body snippet in logs |
### Callbacks
| Option | Type | Description |
| ----------- | -------------------------- | ------------------------------------ |
| `trackUser` | `(req: Request) => string` | Custom function to identify users |
| `onLog` | `(logEntry) => void` | Callback executed for each log entry |
## Usage Examples
### Basic Logging
```typescript
import { logger } from "firstlog";
app.use(
logger({
logFile: "./logs/app.log",
})
);
```
### Advanced Configuration
```typescript
app.use(
logger({
logFile: "./logs/app.log",
maskFields: ["password", "token", "apiKey"],
captureBody: true,
trackQuery: true,
enableGeoIP: true, // Requires geoip-lite to be installed
slowThresholdMs: 500,
prettyPrint: true,
excludePaths: ["/health", "/metrics"],
trackUser: (req) => req.user?.id || "anonymous",
onLog: (logEntry) => {
if (logEntry.slow) {
console.warn(`Slow request detected: ${logEntry.route}`);
}
},
})
);
```
### Error-Only Logging
```typescript
app.use(
logger({
logFile: "./logs/errors.log",
onlyLogOnError: true,
logResponseBody: true,
})
);
```
### External Service Integration
```typescript
app.use(
logger({
logFile: "./logs/app.log",
onLog: (logEntry) => {
// Send to your monitoring service
analytics.track("request", logEntry);
},
})
);
```
## Log Format
Each log entry contains the following information:
```json
{
"requestId": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2024-01-15T10:30:45.123Z",
"method": "POST",
"route": "/api/users",
"status": 201,
"ip": "192.168.1.100",
"durationMs": 234.56,
"slow": false,
"user": "user123",
"body": { "name": "John Doe", "password": "****" },
"query": { "page": "1" },
"headers": { "user-agent": "Mozilla/5.0...", "authorization": "****" },
"params": { "id": "123" },
"responseSnippet": "{\"success\": true, \"id\": \"456\"}",
"location": {
"country": "US",
"region": "CA",
"city": "San Francisco"
}
}
```
## TypeScript Support
Firstlog is built with TypeScript and includes comprehensive type definitions:
```typescript
import { LoggerOptions, logger } from "firstlog";
const options: LoggerOptions = {
logFile: "./logs/app.log",
maskFields: ["password"],
captureBody: true,
};
app.use(logger(options));
```
## Performance Considerations
- **Body Capture**: Disable `captureBody` for high-throughput applications
- **GeoIP**: GeoIP lookups add latency and require the `geoip-lite` peer dependency. Use only when necessary.
- **Memory Usage**: Set appropriate `maxBodySize` to prevent memory issues
## Security
- Sensitive fields are automatically masked using the `maskFields` option
- Request IDs are generated using `nanoid` package
## License
This project is licensed under the Usage-Only License.
## Dependencies
- **express**: Web framework compatibility
- **nanoid**: Secure request ID generation
### Peer Dependencies
- **geoip-lite** (optional): For geographic IP tracking.
## Authors
- [@adidecodes](https://www.github.com/adidecodes)
## Conclusion
#### If you like this package, show your support & love!
[](https://www.buymeacoffee.com/adidecodes)
## Changelog
### v0.0.1
- Initial release
- Basic logging functionality
- TypeScript support
- GeoIP integration
- Performance monitoring
- Security features
### v0.0.2
- Minor Fixes
- Updated Readme
### v0.0.3
- Reduced package size under 100KB
- Replaced uuid with nanoid
- Modularized `geoip-lite` as an optional peer dependency to reduce bundle size for users who do not need the GeoIP feature.
### v0.0.4
- Fixed an issue where `geoip-lite` was getting installed automatically
**Made with ❤️ by Aditya**