337 lines
7.5 KiB
Markdown
337 lines
7.5 KiB
Markdown
# @stock-bot/logger
|
|
|
|
Enhanced logging library with Loki integration for the Stock Bot platform (June 2025).
|
|
|
|
## Features
|
|
|
|
- 🎯 **Multiple Log Levels**: debug, info, warn, error, http
|
|
- 🌐 **Loki Integration**: Centralized logging with Grafana visualization
|
|
- 📁 **File Logging**: Daily rotating log files with compression
|
|
- 🎨 **Console Logging**: Colored, formatted console output
|
|
- 📊 **Structured Logging**: JSON-formatted logs with metadata
|
|
- ⚡ **Performance Optimized**: Batching and async logging
|
|
- 🔐 **Security**: Automatic sensitive data masking
|
|
- 🎭 **Express Middleware**: Request/response logging
|
|
- 📈 **Business Events**: Specialized logging for trading operations
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
# Using Bun (current runtime)
|
|
bun install
|
|
```
|
|
|
|
## Basic Usage
|
|
|
|
### Simple Logging
|
|
|
|
```typescript
|
|
import { getLogger } from '@stock-bot/logger';
|
|
|
|
const logger = getLogger('my-service');
|
|
|
|
logger.info('Service started');
|
|
logger.warn('This is a warning');
|
|
logger.error('An error occurred', new Error('Something went wrong'));
|
|
```
|
|
|
|
### With Context
|
|
|
|
```typescript
|
|
import { getLogger } from '@stock-bot/logger';
|
|
|
|
const logger = getLogger('trading-service');
|
|
|
|
logger.info('Trade executed', {
|
|
symbol: 'AAPL',
|
|
quantity: 100,
|
|
price: 150.25,
|
|
userId: '12345',
|
|
sessionId: 'abc-def-ghi'
|
|
});
|
|
```
|
|
|
|
### Performance Logging
|
|
|
|
```typescript
|
|
import { getLogger, createTimer } from '@stock-bot/logger';
|
|
|
|
const logger = getLogger('data-processor');
|
|
const timer = createTimer('data-processing');
|
|
|
|
// ... do some work ...
|
|
|
|
const timing = timer.end();
|
|
logger.performance('Data processing completed', timing);
|
|
```
|
|
|
|
### Business Events
|
|
|
|
```typescript
|
|
import { getLogger, createBusinessEvent } from '@stock-bot/logger';
|
|
|
|
const logger = getLogger('order-service');
|
|
|
|
logger.business('Order placed', createBusinessEvent(
|
|
'order',
|
|
'place',
|
|
{
|
|
entity: 'order-123',
|
|
result: 'success',
|
|
symbol: 'TSLA',
|
|
amount: 50000
|
|
}
|
|
));
|
|
```
|
|
|
|
### Security Events
|
|
|
|
```typescript
|
|
import { getLogger, createSecurityEvent } from '@stock-bot/logger';
|
|
|
|
const logger = getLogger('auth-service');
|
|
|
|
logger.security('Failed login attempt', createSecurityEvent(
|
|
'authentication',
|
|
{
|
|
user: 'john@example.com',
|
|
result: 'failure',
|
|
ip: '192.168.1.100',
|
|
severity: 'medium'
|
|
}
|
|
));
|
|
```
|
|
|
|
## Express Middleware
|
|
|
|
### Basic Request Logging
|
|
|
|
```typescript
|
|
import express from 'express';
|
|
import { loggingMiddleware } from '@stock-bot/logger';
|
|
|
|
const app = express();
|
|
|
|
app.use(loggingMiddleware({
|
|
serviceName: 'api-gateway',
|
|
skipPaths: ['/health', '/metrics']
|
|
}));
|
|
```
|
|
|
|
### Error Logging
|
|
|
|
```typescript
|
|
import { errorLoggingMiddleware, getLogger } from '@stock-bot/logger';
|
|
|
|
const logger = getLogger('api-gateway');
|
|
|
|
// Add after your routes but before error handlers
|
|
app.use(errorLoggingMiddleware(logger));
|
|
```
|
|
|
|
### Request-scoped Logger
|
|
|
|
```typescript
|
|
import { createRequestLogger, getLogger } from '@stock-bot/logger';
|
|
|
|
const baseLogger = getLogger('api-gateway');
|
|
|
|
app.use((req, res, next) => {
|
|
req.logger = createRequestLogger(req, baseLogger);
|
|
next();
|
|
});
|
|
|
|
app.get('/api/data', (req, res) => {
|
|
req.logger.info('Processing data request');
|
|
// ... handle request ...
|
|
});
|
|
```
|
|
|
|
## Configuration
|
|
|
|
The logger uses configuration from `@stock-bot/config`. Key environment variables:
|
|
|
|
```bash
|
|
# Logging
|
|
LOG_LEVEL=info
|
|
LOG_CONSOLE=true
|
|
LOG_FILE=true
|
|
LOG_FILE_PATH=./logs
|
|
|
|
# Loki
|
|
LOKI_HOST=localhost
|
|
LOKI_PORT=3100
|
|
LOKI_BATCH_SIZE=1024
|
|
```
|
|
|
|
## Advanced Usage
|
|
|
|
### Child Loggers
|
|
|
|
```typescript
|
|
import { getLogger } from '@stock-bot/logger';
|
|
|
|
const parentLogger = getLogger('trading-service');
|
|
const orderLogger = parentLogger.child({
|
|
module: 'order-processing',
|
|
orderId: '12345'
|
|
});
|
|
|
|
orderLogger.info('Order validated'); // Will include parent context
|
|
```
|
|
|
|
### Custom Configuration
|
|
|
|
```typescript
|
|
import { getLogger } from '@stock-bot/logger';
|
|
|
|
// Uses standard getLogger with service-specific configuration
|
|
const logger = getLogger('custom-service');
|
|
```
|
|
|
|
### Sensitive Data Masking
|
|
|
|
```typescript
|
|
import { sanitizeMetadata, maskSensitiveData } from '@stock-bot/logger';
|
|
|
|
const unsafeData = {
|
|
username: 'john',
|
|
password: 'secret123',
|
|
apiKey: 'abc123def456'
|
|
};
|
|
|
|
const safeData = sanitizeMetadata(unsafeData);
|
|
// { username: 'john', password: '[REDACTED]', apiKey: '[REDACTED]' }
|
|
|
|
const message = maskSensitiveData('User API key: abc123def456');
|
|
// 'User API key: [API_KEY]'
|
|
```
|
|
|
|
### Log Throttling
|
|
|
|
```typescript
|
|
import { LogThrottle } from '@stock-bot/logger';
|
|
|
|
const throttle = new LogThrottle(10, 60000); // 10 logs per minute
|
|
|
|
if (throttle.shouldLog('error-key')) {
|
|
logger.error('This error will be throttled');
|
|
}
|
|
```
|
|
|
|
## Viewing Logs
|
|
|
|
### Grafana Dashboard
|
|
|
|
1. Start the monitoring stack: `docker-compose up grafana loki`
|
|
2. Open Grafana at http://localhost:3000
|
|
3. Use the "Stock Bot Logs" dashboard
|
|
4. Query logs with LogQL: `{service="your-service"}`
|
|
|
|
### Log Files
|
|
|
|
When file logging is enabled, logs are written to:
|
|
- `./logs/{service-name}-YYYY-MM-DD.log` - All logs
|
|
- `./logs/{service-name}-error-YYYY-MM-DD.log` - Error logs only
|
|
|
|
## Best Practices
|
|
|
|
1. **Use appropriate log levels**:
|
|
- `debug`: Detailed development information
|
|
- `info`: General operational messages
|
|
- `warn`: Potential issues
|
|
- `error`: Actual errors requiring attention
|
|
|
|
2. **Include context**: Always provide relevant metadata
|
|
```typescript
|
|
logger.info('Trade executed', { symbol, quantity, price, orderId });
|
|
```
|
|
|
|
3. **Use structured logging**: Avoid string concatenation
|
|
```typescript
|
|
// Good
|
|
logger.info('User logged in', { userId, ip, userAgent });
|
|
|
|
// Avoid
|
|
logger.info(`User ${userId} logged in from ${ip}`);
|
|
```
|
|
|
|
4. **Handle sensitive data**: Use sanitization utilities
|
|
```typescript
|
|
const safeMetadata = sanitizeMetadata(requestData);
|
|
logger.info('API request', safeMetadata);
|
|
```
|
|
|
|
5. **Use correlation IDs**: Track requests across services
|
|
```typescript
|
|
const logger = getLogger('service').child({
|
|
correlationId: req.headers['x-correlation-id']
|
|
});
|
|
```
|
|
|
|
## Integration with Services
|
|
|
|
To use in your service:
|
|
|
|
1. Add dependency to your service's `package.json`:
|
|
```json
|
|
{
|
|
"dependencies": {
|
|
"@stock-bot/logger": "*"
|
|
}
|
|
}
|
|
```
|
|
|
|
2. Update your service's `tsconfig.json` references:
|
|
```json
|
|
{
|
|
"references": [
|
|
{ "path": "../../../libs/logger" }
|
|
]
|
|
}
|
|
```
|
|
|
|
3. Import and use:
|
|
```typescript
|
|
import { getLogger } from '@stock-bot/logger';
|
|
|
|
const logger = getLogger('my-service');
|
|
```
|
|
|
|
## Performance Considerations
|
|
|
|
- Logs are batched and sent asynchronously to Loki
|
|
- File logging uses daily rotation to prevent large files
|
|
- Console logging can be disabled in production
|
|
- Use log throttling for high-frequency events
|
|
- Sensitive data is automatically masked
|
|
|
|
## Troubleshooting
|
|
|
|
### Logs not appearing in Loki
|
|
|
|
1. Check Loki connection:
|
|
```bash
|
|
curl http://localhost:3100/ready
|
|
```
|
|
|
|
2. Verify environment variables:
|
|
```bash
|
|
echo $LOKI_HOST $LOKI_PORT
|
|
```
|
|
|
|
3. Check container logs:
|
|
```bash
|
|
docker logs stock-bot-loki
|
|
```
|
|
|
|
### High memory usage
|
|
|
|
- Reduce `LOKI_BATCH_SIZE` if batching too many logs
|
|
- Disable file logging if not needed
|
|
|
|
### Missing logs
|
|
|
|
- Check log level configuration
|
|
- Verify service name matches expectations
|
|
- Ensure proper error handling around logger calls
|