fix: Gitea Traefik routing and connection pool optimization
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
- Remove middleware reference from Gitea Traefik labels (caused routing issues) - Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s) - Add explicit service reference in Traefik labels - Fix intermittent 504 timeouts by improving PostgreSQL connection handling Fixes Gitea unreachability via git.michaelschiemer.de
This commit is contained in:
413
docs/modules/error-tracking.md
Normal file
413
docs/modules/error-tracking.md
Normal file
@@ -0,0 +1,413 @@
|
||||
# Error Tracking Module
|
||||
|
||||
**Centralized Error Tracking and Reporting**
|
||||
|
||||
The Error Tracking Module provides comprehensive error tracking, grouping, and reporting capabilities for production applications.
|
||||
|
||||
---
|
||||
|
||||
## Features
|
||||
|
||||
- **Error Collection** - Automatically capture unhandled errors and promise rejections
|
||||
- **Error Grouping** - Group similar errors to reduce noise
|
||||
- **Error Reporting** - Send errors to backend for analysis
|
||||
- **Error Analytics** - Track error frequency and patterns
|
||||
- **Integration with ErrorBoundary** - Works with LiveComponent ErrorBoundary
|
||||
- **Source Map Support** - Map minified errors to source code
|
||||
- **Error Filtering** - Filter out known or irrelevant errors
|
||||
- **Sampling** - Control error reporting volume with sampling
|
||||
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```javascript
|
||||
import { ErrorTracker } from './modules/error-tracking/index.js';
|
||||
|
||||
// Create error tracker
|
||||
const tracker = ErrorTracker.create({
|
||||
endpoint: '/api/errors',
|
||||
enabled: true,
|
||||
sampleRate: 1.0 // Report 100% of errors
|
||||
});
|
||||
|
||||
// Manually capture an error
|
||||
try {
|
||||
// Some code that might throw
|
||||
} catch (error) {
|
||||
tracker.captureException(error, {
|
||||
type: 'user-action',
|
||||
action: 'submit-form'
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### Module System Integration
|
||||
|
||||
```html
|
||||
<!-- Enable global error tracking -->
|
||||
<script type="module">
|
||||
import { init } from './modules/error-tracking/index.js';
|
||||
|
||||
init({
|
||||
endpoint: '/api/errors',
|
||||
enabled: true,
|
||||
sampleRate: 0.1 // Report 10% of errors
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Access globally -->
|
||||
<script>
|
||||
// Errors are automatically captured
|
||||
// Or manually capture:
|
||||
window.ErrorTracker.captureException(new Error('Something went wrong'), {
|
||||
context: { userId: 123 }
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API Reference
|
||||
|
||||
### ErrorTracker.create(config)
|
||||
|
||||
Create a new ErrorTracker instance.
|
||||
|
||||
**Parameters**:
|
||||
- `config.endpoint` - Backend endpoint for error reporting (default: '/api/errors')
|
||||
- `config.enabled` - Enable error tracking (default: true)
|
||||
- `config.sampleRate` - Sampling rate 0.0 to 1.0 (default: 1.0)
|
||||
- `config.maxErrors` - Maximum errors to keep in memory (default: 100)
|
||||
- `config.groupingWindow` - Time window for error grouping in ms (default: 60000)
|
||||
- `config.includeStack` - Include stack traces (default: true)
|
||||
- `config.includeContext` - Include context information (default: true)
|
||||
- `config.includeUserAgent` - Include user agent (default: true)
|
||||
- `config.includeUrl` - Include current URL (default: true)
|
||||
- `config.filters` - Array of filter functions or regex patterns
|
||||
- `config.beforeSend` - Hook to modify errors before sending
|
||||
|
||||
**Example**:
|
||||
```javascript
|
||||
const tracker = ErrorTracker.create({
|
||||
endpoint: '/api/errors',
|
||||
enabled: true,
|
||||
sampleRate: 0.5, // Report 50% of errors
|
||||
filters: [
|
||||
// Filter out specific errors
|
||||
/Script error/i,
|
||||
(error, context) => {
|
||||
// Custom filter logic
|
||||
return error.message.includes('ResizeObserver');
|
||||
}
|
||||
],
|
||||
beforeSend: (errorData) => {
|
||||
// Add additional context
|
||||
errorData.userId = getCurrentUserId();
|
||||
errorData.sessionId = getSessionId();
|
||||
return errorData;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### tracker.captureException(error, context)
|
||||
|
||||
Manually capture an exception.
|
||||
|
||||
**Parameters**:
|
||||
- `error` - Error object or any value
|
||||
- `context` - Additional context information
|
||||
|
||||
**Example**:
|
||||
```javascript
|
||||
try {
|
||||
// Some code
|
||||
} catch (error) {
|
||||
tracker.captureException(error, {
|
||||
type: 'api-call',
|
||||
endpoint: '/api/users',
|
||||
method: 'POST'
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### tracker.report()
|
||||
|
||||
Manually flush error reports to backend.
|
||||
|
||||
**Example**:
|
||||
```javascript
|
||||
// Report errors immediately
|
||||
await tracker.report();
|
||||
```
|
||||
|
||||
### tracker.getErrorGroups()
|
||||
|
||||
Get grouped errors.
|
||||
|
||||
**Returns**: `Array<ErrorGroup>`
|
||||
|
||||
**Example**:
|
||||
```javascript
|
||||
const groups = tracker.getErrorGroups();
|
||||
groups.forEach(group => {
|
||||
console.log(`${group.fingerprint}: ${group.count} occurrences`);
|
||||
});
|
||||
```
|
||||
|
||||
### tracker.getErrors()
|
||||
|
||||
Get all captured errors.
|
||||
|
||||
**Returns**: `Array<ErrorData>`
|
||||
|
||||
### tracker.clearErrors()
|
||||
|
||||
Clear all captured errors.
|
||||
|
||||
---
|
||||
|
||||
## Integration with ErrorBoundary
|
||||
|
||||
```javascript
|
||||
import { ErrorTracker } from './modules/error-tracking/index.js';
|
||||
import { ErrorBoundary } from './modules/livecomponent/ErrorBoundary.js';
|
||||
|
||||
const tracker = ErrorTracker.create({
|
||||
endpoint: '/api/errors'
|
||||
});
|
||||
|
||||
// ErrorBoundary automatically captures errors
|
||||
const errorBoundary = new ErrorBoundary(liveComponentManager);
|
||||
|
||||
// Listen for errors
|
||||
window.addEventListener('error-tracker:error', (event) => {
|
||||
const errorData = event.detail;
|
||||
console.error('Error captured:', errorData);
|
||||
|
||||
// Show user-friendly error message
|
||||
showErrorNotification(errorData.message);
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Error Filtering
|
||||
|
||||
### Filter by Regex
|
||||
|
||||
```javascript
|
||||
const tracker = ErrorTracker.create({
|
||||
filters: [
|
||||
/Script error/i, // Filter out script errors
|
||||
/ResizeObserver/i // Filter out ResizeObserver errors
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
### Filter by Function
|
||||
|
||||
```javascript
|
||||
const tracker = ErrorTracker.create({
|
||||
filters: [
|
||||
(error, context) => {
|
||||
// Filter out errors from specific domains
|
||||
if (context.url && context.url.includes('localhost')) {
|
||||
return false; // Don't track localhost errors
|
||||
}
|
||||
return true; // Track other errors
|
||||
}
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Error Sampling
|
||||
|
||||
Control error reporting volume with sampling:
|
||||
|
||||
```javascript
|
||||
const tracker = ErrorTracker.create({
|
||||
sampleRate: 0.1 // Report only 10% of errors
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## beforeSend Hook
|
||||
|
||||
Modify errors before sending to backend:
|
||||
|
||||
```javascript
|
||||
const tracker = ErrorTracker.create({
|
||||
beforeSend: (errorData) => {
|
||||
// Add user information
|
||||
errorData.user = {
|
||||
id: getCurrentUserId(),
|
||||
email: getCurrentUserEmail()
|
||||
};
|
||||
|
||||
// Add session information
|
||||
errorData.session = {
|
||||
id: getSessionId(),
|
||||
startTime: getSessionStartTime()
|
||||
};
|
||||
|
||||
// Remove sensitive data
|
||||
delete errorData.context.password;
|
||||
|
||||
// Return modified error data
|
||||
return errorData;
|
||||
|
||||
// Or return null/false to prevent sending
|
||||
// return null;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Error Grouping
|
||||
|
||||
Errors are automatically grouped by:
|
||||
- Error name
|
||||
- Error message
|
||||
- Stack trace (first 3 lines)
|
||||
|
||||
Similar errors are grouped together to reduce noise:
|
||||
|
||||
```javascript
|
||||
const groups = tracker.getErrorGroups();
|
||||
groups.forEach(group => {
|
||||
console.log(`Error: ${group.fingerprint}`);
|
||||
console.log(`Count: ${group.count}`);
|
||||
console.log(`First seen: ${new Date(group.firstSeen)}`);
|
||||
console.log(`Last seen: ${new Date(group.lastSeen)}`);
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Backend Integration
|
||||
|
||||
The error tracker sends errors to the backend endpoint:
|
||||
|
||||
```javascript
|
||||
POST /api/errors
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"errors": [
|
||||
{
|
||||
"message": "Cannot read property 'x' of undefined",
|
||||
"name": "TypeError",
|
||||
"stack": "...",
|
||||
"timestamp": 1234567890,
|
||||
"type": "unhandled",
|
||||
"context": {
|
||||
"url": "https://example.com/page",
|
||||
"userAgent": "...",
|
||||
"viewport": { "width": 1920, "height": 1080 }
|
||||
}
|
||||
}
|
||||
],
|
||||
"errorGroups": [
|
||||
{
|
||||
"fingerprint": "TypeError:Cannot read property...",
|
||||
"count": 5,
|
||||
"firstSeen": 1234567890,
|
||||
"lastSeen": 1234567900
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Use Cases
|
||||
|
||||
### Production Error Tracking
|
||||
|
||||
```javascript
|
||||
const tracker = ErrorTracker.create({
|
||||
endpoint: '/api/errors',
|
||||
enabled: true,
|
||||
sampleRate: 0.1, // Sample 10% in production
|
||||
filters: [
|
||||
// Filter out known issues
|
||||
/ResizeObserver/i,
|
||||
/Script error/i
|
||||
],
|
||||
beforeSend: (errorData) => {
|
||||
// Add user context
|
||||
errorData.userId = getCurrentUserId();
|
||||
return errorData;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Development Error Tracking
|
||||
|
||||
```javascript
|
||||
const tracker = ErrorTracker.create({
|
||||
endpoint: '/api/errors',
|
||||
enabled: true,
|
||||
sampleRate: 1.0, // Track all errors in development
|
||||
includeStack: true,
|
||||
includeContext: true
|
||||
});
|
||||
```
|
||||
|
||||
### API Error Tracking
|
||||
|
||||
```javascript
|
||||
async function apiCall(url, options) {
|
||||
try {
|
||||
const response = await fetch(url, options);
|
||||
if (!response.ok) {
|
||||
throw new Error(`API error: ${response.status}`);
|
||||
}
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
tracker.captureException(error, {
|
||||
type: 'api-error',
|
||||
url,
|
||||
method: options.method || 'GET',
|
||||
status: error.status
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Use Sampling in Production** - Set sampleRate to 0.1 or lower to reduce backend load
|
||||
2. **Filter Known Issues** - Filter out errors you can't fix (e.g., browser extensions)
|
||||
3. **Add Context** - Use beforeSend to add user, session, or request context
|
||||
4. **Group Errors** - Let the tracker group similar errors automatically
|
||||
5. **Monitor Error Groups** - Track error frequency and patterns
|
||||
|
||||
---
|
||||
|
||||
## Browser Support
|
||||
|
||||
- **Chrome/Edge**: 90+
|
||||
- **Firefox**: 88+
|
||||
- **Safari**: 14+
|
||||
- **Mobile**: iOS 14+, Android Chrome 90+
|
||||
|
||||
**Required Features**:
|
||||
- ES2020 JavaScript
|
||||
- Fetch API
|
||||
- Promise support
|
||||
|
||||
---
|
||||
|
||||
**Next**: [Event Bus Module](event-bus.md) →
|
||||
|
||||
Reference in New Issue
Block a user