debug-log-server 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,402 @@
1
+ Metadata-Version: 2.4
2
+ Name: debug-log-server
3
+ Version: 0.1.0
4
+ Summary: Debug log collection and query service based on FastAPI
5
+ Author-email: dengshi <dengshi@mercator.cn>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/dengshihub/debuglogger
8
+ Project-URL: Documentation, https://github.com/dengshihub/debuglogger#readme
9
+ Project-URL: Repository, https://github.com/dengshihub/debuglogger.git
10
+ Project-URL: Issues, https://github.com/dengshihub/debuglogger/issues
11
+ Keywords: debug,log,logging,fastapi,monitoring,error-tracking
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Requires-Python: >=3.8
22
+ Description-Content-Type: text/markdown
23
+ Requires-Dist: fastapi>=0.104.0
24
+ Requires-Dist: uvicorn[standard]>=0.24.0
25
+ Requires-Dist: pydantic>=2.0.0
26
+ Requires-Dist: python-jose[cryptography]>=3.3.0
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
29
+ Requires-Dist: httpx>=0.24.0; extra == "dev"
30
+ Requires-Dist: black>=23.0.0; extra == "dev"
31
+ Requires-Dist: flake8>=6.0.0; extra == "dev"
32
+
33
+ # Debug Log Server
34
+
35
+ Debug log collection and query service based on FastAPI.
36
+
37
+ ## 📦 Installation
38
+
39
+ ### From PyPI
40
+
41
+ ```bash
42
+ pip install debug-log-server
43
+ ```
44
+
45
+ ### From Source
46
+
47
+ ```bash
48
+ git clone https://github.com/dengshihub/debuglogger.git
49
+ cd debuglogger/backend
50
+ pip install -e .
51
+ ```
52
+
53
+ ## 🚀 Quick Start
54
+
55
+ ### Start Server
56
+
57
+ ```bash
58
+ # Basic usage
59
+ debug-log-server
60
+
61
+ # With custom log directory
62
+ DEBUG_LOG_DIR=/var/log/debug-logs debug-log-server
63
+
64
+ # With custom port
65
+ debug-log-server --port 9000
66
+
67
+ # With custom host and port
68
+ debug-log-server --host 0.0.0.0 --port 8000
69
+ ```
70
+
71
+ ### Environment Variables
72
+
73
+ - `DEBUG_LOG_DIR`: Log storage directory (default: `./debug-logs`)
74
+ - `DEBUG_AUTH`: Enable authentication debug mode (default: `false`)
75
+
76
+ ## 📖 API Documentation
77
+
78
+ ### POST /api/debug-log
79
+
80
+ Receive debug logs from frontend.
81
+
82
+ **Request Body:**
83
+ ```json
84
+ {
85
+ "logs": [
86
+ {
87
+ "sessionId": "session-123",
88
+ "timestamp": 1717564800000,
89
+ "type": "console",
90
+ "level": "log",
91
+ "message": "Hello World",
92
+ "url": "https://example.com"
93
+ }
94
+ ],
95
+ "source": "frontend"
96
+ }
97
+ ```
98
+
99
+ **Response:**
100
+ ```json
101
+ {
102
+ "status": "ok",
103
+ "received": 1
104
+ }
105
+ ```
106
+
107
+ ### GET /api/debug-log/list
108
+
109
+ List all log files.
110
+
111
+ **Query Parameters:**
112
+ - `source`: Filter by source (optional)
113
+
114
+ **Response:**
115
+ ```json
116
+ {
117
+ "logs": [
118
+ {
119
+ "name": "frontend.log",
120
+ "path": "/var/log/debug-logs/frontend/frontend.log",
121
+ "size": 1024,
122
+ "modified": "2024-06-05T10:30:00"
123
+ }
124
+ ]
125
+ }
126
+ ```
127
+
128
+ ### GET /api/debug-log/{source}
129
+
130
+ Get logs from a specific source.
131
+
132
+ **Query Parameters:**
133
+ - `limit`: Maximum number of entries to return (default: 100)
134
+
135
+ **Response:**
136
+ ```json
137
+ {
138
+ "source": "frontend",
139
+ "entries": [
140
+ {
141
+ "sessionId": "session-123",
142
+ "timestamp": 1717564800000,
143
+ "type": "console",
144
+ "level": "log",
145
+ "message": "Hello World"
146
+ }
147
+ ]
148
+ }
149
+ ```
150
+
151
+ ## 🐳 Docker
152
+
153
+ ### Build Image
154
+
155
+ ```bash
156
+ docker build -t debug-log-server .
157
+ ```
158
+
159
+ ### Run Container
160
+
161
+ ```bash
162
+ docker run -d \
163
+ -p 8000:8000 \
164
+ -v /var/log/debug-logs:/app/debug-logs \
165
+ --name debug-log-server \
166
+ debug-log-server
167
+ ```
168
+
169
+ ### Docker Compose
170
+
171
+ ```yaml
172
+ version: '3.8'
173
+
174
+ services:
175
+ debug-log-server:
176
+ image: debug-log-server:latest
177
+ ports:
178
+ - "8000:8000"
179
+ volumes:
180
+ - ./debug-logs:/app/debug-logs
181
+ environment:
182
+ - DEBUG_LOG_DIR=/app/debug-logs
183
+ restart: unless-stopped
184
+ ```
185
+
186
+ ## 🔧 Configuration
187
+
188
+ ### Basic Configuration
189
+
190
+ ```python
191
+ # config.py
192
+ import os
193
+
194
+ LOG_DIR = os.getenv("DEBUG_LOG_DIR", "./debug-logs")
195
+ HOST = os.getenv("HOST", "0.0.0.0")
196
+ PORT = int(os.getenv("PORT", "8000"))
197
+ ```
198
+
199
+ ### Advanced Configuration
200
+
201
+ ```python
202
+ # config.py
203
+ from pydantic import BaseSettings
204
+
205
+ class Settings(BaseSettings):
206
+ log_dir: str = "./debug-logs"
207
+ host: str = "0.0.0.0"
208
+ port: int = 8000
209
+ debug_auth: bool = False
210
+
211
+ class Config:
212
+ env_prefix = "DEBUG_"
213
+
214
+ settings = Settings()
215
+ ```
216
+
217
+ ## 🔒 Security
218
+
219
+ ### Authentication
220
+
221
+ The server supports JWT authentication for protected routes:
222
+
223
+ ```python
224
+ from fastapi import Depends
225
+ from debug_log_server import debug_auth
226
+
227
+ @app.get("/api/protected")
228
+ async def protected_route(token: str = Depends(debug_auth)):
229
+ return {"message": "This is a protected route"}
230
+ ```
231
+
232
+ ### CORS
233
+
234
+ CORS is enabled by default for all origins. For production, configure it properly:
235
+
236
+ ```python
237
+ from fastapi.middleware.cors import CORSMiddleware
238
+
239
+ app.add_middleware(
240
+ CORSMiddleware,
241
+ allow_origins=["https://your-domain.com"], # Specify allowed origins
242
+ allow_credentials=True,
243
+ allow_methods=["GET", "POST"],
244
+ allow_headers=["*"],
245
+ )
246
+ ```
247
+
248
+ ## 📊 Monitoring
249
+
250
+ ### Health Check
251
+
252
+ ```bash
253
+ curl http://localhost:8000/
254
+ ```
255
+
256
+ ### Log Statistics
257
+
258
+ ```bash
259
+ curl http://localhost:8000/api/debug-log/list
260
+ ```
261
+
262
+ ## 🧪 Testing
263
+
264
+ ### Install Test Dependencies
265
+
266
+ ```bash
267
+ pip install debug-log-server[dev]
268
+ ```
269
+
270
+ ### Run Tests
271
+
272
+ ```bash
273
+ pytest tests/
274
+ ```
275
+
276
+ ### Test with httpx
277
+
278
+ ```python
279
+ from fastapi.testclient import TestClient
280
+ from main import app
281
+
282
+ client = TestClient(app)
283
+
284
+ def test_receive_log():
285
+ response = client.post("/api/debug-log", json={
286
+ "logs": [{
287
+ "sessionId": "test",
288
+ "timestamp": 1717564800000,
289
+ "type": "console",
290
+ "message": "test"
291
+ }],
292
+ "source": "test"
293
+ })
294
+ assert response.status_code == 200
295
+ ```
296
+
297
+ ## 📝 Examples
298
+
299
+ ### Python Client
300
+
301
+ ```python
302
+ import requests
303
+
304
+ # Send logs
305
+ response = requests.post('http://localhost:8000/api/debug-log', json={
306
+ "logs": [{
307
+ "sessionId": "session-123",
308
+ "timestamp": 1717564800000,
309
+ "type": "console",
310
+ "level": "log",
311
+ "message": "Hello from Python"
312
+ }],
313
+ "source": "python-client"
314
+ })
315
+
316
+ print(response.json())
317
+ ```
318
+
319
+ ### JavaScript Client
320
+
321
+ ```javascript
322
+ // Using fetch
323
+ fetch('http://localhost:8000/api/debug-log', {
324
+ method: 'POST',
325
+ headers: { 'Content-Type': 'application/json' },
326
+ body: JSON.stringify({
327
+ logs: [{
328
+ sessionId: 'session-123',
329
+ timestamp: Date.now(),
330
+ type: 'console',
331
+ level: 'log',
332
+ message: 'Hello from JavaScript'
333
+ }],
334
+ source: 'javascript-client'
335
+ })
336
+ })
337
+ .then(response => response.json())
338
+ .then(data => console.log(data));
339
+ ```
340
+
341
+ ## 🚀 Deployment
342
+
343
+ ### Systemd Service
344
+
345
+ ```ini
346
+ # /etc/systemd/system/debug-log-server.service
347
+ [Unit]
348
+ Description=Debug Log Server
349
+ After=network.target
350
+
351
+ [Service]
352
+ Type=simple
353
+ User=www-data
354
+ WorkingDirectory=/opt/debug-log-server
355
+ Environment="DEBUG_LOG_DIR=/var/log/debug-logs"
356
+ ExecStart=/usr/local/bin/debug-log-server
357
+ Restart=always
358
+
359
+ [Install]
360
+ WantedBy=multi-user.target
361
+ ```
362
+
363
+ ```bash
364
+ sudo systemctl enable debug-log-server
365
+ sudo systemctl start debug-log-server
366
+ ```
367
+
368
+ ### Nginx Reverse Proxy
369
+
370
+ ```nginx
371
+ server {
372
+ listen 80;
373
+ server_name logs.your-domain.com;
374
+
375
+ location / {
376
+ proxy_pass http://127.0.0.1:8000;
377
+ proxy_set_header Host $host;
378
+ proxy_set_header X-Real-IP $remote_addr;
379
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
380
+ proxy_set_header X-Forwarded-Proto $scheme;
381
+ }
382
+ }
383
+ ```
384
+
385
+ ## 📚 Related Projects
386
+
387
+ - **@dengshi/debug-logger**: Frontend log collection library (npm)
388
+ - **playwright-collector**: Playwright-based log collector
389
+
390
+ ## 📄 License
391
+
392
+ MIT License - see [LICENSE](LICENSE) file for details.
393
+
394
+ ## 🤝 Contributing
395
+
396
+ Contributions are welcome! Please read our [Contributing Guide](../CONTRIBUTING.md) for details.
397
+
398
+ ## 📞 Support
399
+
400
+ - 📖 [Documentation](https://github.com/dengshihub/debuglogger#readme)
401
+ - 🐛 [Issue Tracker](https://github.com/dengshihub/debuglogger/issues)
402
+ - 💬 [Discussions](https://github.com/dengshihub/debuglogger/discussions)
@@ -0,0 +1,6 @@
1
+ static/index.html,sha256=ThsBvwX4abtz0yoqbQtch3c0AROeMP8gWHGj87TjUAM,13983
2
+ debug_log_server-0.1.0.dist-info/METADATA,sha256=0mwA6JFdYvKSeN2g1d4ddTPu2UzVtJjvCbfOvmG3FiY,8388
3
+ debug_log_server-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
4
+ debug_log_server-0.1.0.dist-info/entry_points.txt,sha256=XdEvilgx2UAIVk-6Tkk3W-K9s0ksVWM-CuVAc_KinKs,47
5
+ debug_log_server-0.1.0.dist-info/top_level.txt,sha256=ZSyr8N5s1w9m9ysX1kCSA7hJCb6YZCYf62FJQ_LmzGI,7
6
+ debug_log_server-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ debug-log-server = main:main
@@ -0,0 +1 @@
1
+ static
static/index.html ADDED
@@ -0,0 +1,371 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>调试系统 - 前端演示</title>
7
+ <style>
8
+ body {
9
+ font-family: Arial, sans-serif;
10
+ max-width: 800px;
11
+ margin: 50px auto;
12
+ padding: 20px;
13
+ background-color: #f5f5f5;
14
+ }
15
+ .container {
16
+ background: white;
17
+ padding: 30px;
18
+ border-radius: 8px;
19
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
20
+ }
21
+ h1 { color: #333; }
22
+ .section {
23
+ margin: 20px 0;
24
+ padding: 15px;
25
+ border: 1px solid #ddd;
26
+ border-radius: 5px;
27
+ }
28
+ button {
29
+ background: #007bff;
30
+ color: white;
31
+ border: none;
32
+ padding: 10px 20px;
33
+ border-radius: 5px;
34
+ cursor: pointer;
35
+ margin: 5px;
36
+ }
37
+ button:hover { background: #0056b3; }
38
+ button.error { background: #dc3545; }
39
+ button.error:hover { background: #c82333; }
40
+ button.success { background: #28a745; }
41
+ button.success:hover { background: #218838; }
42
+ .log-output {
43
+ background: #f8f9fa;
44
+ padding: 15px;
45
+ border-radius: 5px;
46
+ margin-top: 10px;
47
+ max-height: 200px;
48
+ overflow-y: auto;
49
+ font-family: monospace;
50
+ font-size: 12px;
51
+ }
52
+ .status {
53
+ padding: 10px;
54
+ border-radius: 5px;
55
+ margin: 10px 0;
56
+ }
57
+ .status.success { background: #d4edda; color: #155724; }
58
+ .status.error { background: #f8d7da; color: #721c24; }
59
+ .status.info { background: #d1ecf1; color: #0c5460; }
60
+ </style>
61
+ </head>
62
+ <body>
63
+ <div class="container">
64
+ <h1>🔧 调试系统 - 前端演示</h1>
65
+
66
+ <div class="section">
67
+ <h2>📡 服务状态</h2>
68
+ <button onclick="checkService()">检查服务状态</button>
69
+ <div id="serviceStatus" class="status info">等待检查...</div>
70
+ </div>
71
+
72
+ <div class="section">
73
+ <h2>📝 基础日志测试</h2>
74
+ <button onclick="sendInfoLog()">发送 Info 日志</button>
75
+ <button onclick="sendWarnLog()">发送 Warn 日志</button>
76
+ <button class="error" onclick="sendErrorLog()">发送 Error 日志</button>
77
+ <button class="success" onclick="sendSuccessLog()">发送 Success 日志</button>
78
+ </div>
79
+
80
+ <div class="section">
81
+ <h2>🌐 网络请求测试</h2>
82
+ <button onclick="testApiCall()">测试 API 调用</button>
83
+ <button onclick="testFailedApi()">测试失败 API</button>
84
+ </div>
85
+
86
+ <div class="section">
87
+ <h2>🎯 用户行为测试</h2>
88
+ <button onclick="simulateUserClick()">模拟用户点击</button>
89
+ <button onclick="simulateFormSubmit()">模拟表单提交</button>
90
+ <button onclick="simulateNavigation()">模拟页面跳转</button>
91
+ </div>
92
+
93
+ <div class="section">
94
+ <h2>📊 查看日志</h2>
95
+ <button onclick="viewLogs()">查看所有日志</button>
96
+ <button onclick="viewRecentLogs()">查看最近日志</button>
97
+ <div id="logOutput" class="log-output">日志输出区域...</div>
98
+ </div>
99
+
100
+ <div class="section">
101
+ <h2>🔍 性能监控</h2>
102
+ <button onclick="measurePerformance()">测量页面性能</button>
103
+ <button onclick="measureApiPerformance()">测量 API 性能</button>
104
+ </div>
105
+ </div>
106
+
107
+ <script>
108
+ // 配置
109
+ const DEBUG_ENDPOINT = '/api/debug-log';
110
+ const sessionId = 'session-' + Date.now() + '-' + Math.random().toString(36).substr(2, 9);
111
+
112
+ // 基础日志发送函数
113
+ async function sendLog(type, level, message, extra = {}) {
114
+ const logData = {
115
+ sessionId: sessionId,
116
+ timestamp: Date.now(),
117
+ type: type,
118
+ level: level,
119
+ message: message,
120
+ url: window.location.href,
121
+ ...extra
122
+ };
123
+
124
+ try {
125
+ const response = await fetch(DEBUG_ENDPOINT, {
126
+ method: 'POST',
127
+ headers: { 'Content-Type': 'application/json' },
128
+ body: JSON.stringify({ logs: [logData], source: 'example' })
129
+ });
130
+ const result = await response.json();
131
+ console.log('日志发送成功:', result);
132
+ return result;
133
+ } catch (error) {
134
+ console.error('日志发送失败:', error);
135
+ throw error;
136
+ }
137
+ }
138
+
139
+ // 检查服务状态
140
+ async function checkService() {
141
+ const statusDiv = document.getElementById('serviceStatus');
142
+ try {
143
+ const response = await fetch('/api/debug-log/list');
144
+ if (response.ok) {
145
+ statusDiv.className = 'status success';
146
+ statusDiv.textContent = '✅ 调试服务运行正常';
147
+ sendLog('system', 'info', '调试服务检查通过');
148
+ } else {
149
+ throw new Error('服务响应异常');
150
+ }
151
+ } catch (error) {
152
+ statusDiv.className = 'status error';
153
+ statusDiv.textContent = '❌ 调试服务无法连接: ' + error.message;
154
+ }
155
+ }
156
+
157
+ // 发送不同级别的日志
158
+ function sendInfoLog() {
159
+ sendLog('console', 'info', '这是一条信息日志', {
160
+ userId: 'user-123',
161
+ action: 'info_test'
162
+ });
163
+ }
164
+
165
+ function sendWarnLog() {
166
+ sendLog('console', 'warn', '这是一条警告日志', {
167
+ warningType: 'deprecated_api',
168
+ apiVersion: 'v1'
169
+ });
170
+ }
171
+
172
+ function sendErrorLog() {
173
+ sendLog('console', 'error', '这是一条错误日志', {
174
+ errorCode: 'ERR_001',
175
+ errorMessage: '模拟的错误信息'
176
+ });
177
+ }
178
+
179
+ function sendSuccessLog() {
180
+ sendLog('console', 'info', '操作成功完成', {
181
+ action: 'user_action',
182
+ status: 'success'
183
+ });
184
+ }
185
+
186
+ // 测试 API 调用
187
+ async function testApiCall() {
188
+ const startTime = Date.now();
189
+ try {
190
+ const response = await fetch('/api/debug-log/list');
191
+ const duration = Date.now() - startTime;
192
+
193
+ await sendLog('network-request', 'info', 'API 调用成功', {
194
+ url: '/api/debug-log/list',
195
+ method: 'GET',
196
+ status: response.status,
197
+ duration: duration
198
+ });
199
+ } catch (error) {
200
+ const duration = Date.now() - startTime;
201
+ await sendLog('network-request', 'error', 'API 调用失败', {
202
+ url: '/api/debug-log/list',
203
+ method: 'GET',
204
+ error: error.message,
205
+ duration: duration
206
+ });
207
+ }
208
+ }
209
+
210
+ async function testFailedApi() {
211
+ const startTime = Date.now();
212
+ try {
213
+ const response = await fetch('/api/nonexistent');
214
+ const duration = Date.now() - startTime;
215
+
216
+ await sendLog('network-request', 'error', '预期中的 API 失败', {
217
+ url: '/api/nonexistent',
218
+ method: 'GET',
219
+ status: response.status,
220
+ duration: duration
221
+ });
222
+ } catch (error) {
223
+ const duration = Date.now() - startTime;
224
+ await sendLog('network-request', 'error', 'API 调用异常', {
225
+ url: '/api/nonexistent',
226
+ method: 'GET',
227
+ error: error.message,
228
+ duration: duration
229
+ });
230
+ }
231
+ }
232
+
233
+ // 模拟用户行为
234
+ function simulateUserClick() {
235
+ sendLog('user-action', 'info', '用户点击了按钮', {
236
+ elementId: 'test-button',
237
+ elementType: 'button',
238
+ timestamp: Date.now()
239
+ });
240
+ }
241
+
242
+ function simulateFormSubmit() {
243
+ sendLog('user-action', 'info', '用户提交了表单', {
244
+ formId: 'test-form',
245
+ formData: {
246
+ username: 'test_user',
247
+ email: 'test@example.com'
248
+ }
249
+ });
250
+ }
251
+
252
+ function simulateNavigation() {
253
+ sendLog('navigation', 'info', '用户导航到新页面', {
254
+ from: window.location.href,
255
+ to: '/new-page',
256
+ method: 'push'
257
+ });
258
+ }
259
+
260
+ // 查看日志
261
+ async function viewLogs() {
262
+ try {
263
+ const response = await fetch('/api/debug-log/example');
264
+ const data = await response.json();
265
+ const outputDiv = document.getElementById('logOutput');
266
+
267
+ if (data.entries && data.entries.length > 0) {
268
+ outputDiv.innerHTML = data.entries.map(entry =>
269
+ `<div style="margin: 5px 0; padding: 5px; background: #fff; border-left: 3px solid ${getLevelColor(entry.level)};">
270
+ <strong>[${entry.level}]</strong> ${entry.message} <br>
271
+ <small>${new Date(entry.timestamp).toLocaleString()}</small>
272
+ </div>`
273
+ ).join('');
274
+ } else {
275
+ outputDiv.innerHTML = '暂无日志数据';
276
+ }
277
+ } catch (error) {
278
+ document.getElementById('logOutput').innerHTML = '获取日志失败: ' + error.message;
279
+ }
280
+ }
281
+
282
+ async function viewRecentLogs() {
283
+ try {
284
+ const response = await fetch('/api/debug-log/example?limit=5');
285
+ const data = await response.json();
286
+ const outputDiv = document.getElementById('logOutput');
287
+
288
+ if (data.entries && data.entries.length > 0) {
289
+ outputDiv.innerHTML = `<h3>最近 ${data.entries.length} 条日志:</h3>` +
290
+ data.entries.map(entry =>
291
+ `<div style="margin: 5px 0; padding: 5px; background: #fff; border-left: 3px solid ${getLevelColor(entry.level)};">
292
+ <strong>[${entry.level}]</strong> ${entry.message} <br>
293
+ <small>${new Date(entry.timestamp).toLocaleString()}</small>
294
+ </div>`
295
+ ).join('');
296
+ } else {
297
+ outputDiv.innerHTML = '暂无日志数据';
298
+ }
299
+ } catch (error) {
300
+ document.getElementById('logOutput').innerHTML = '获取日志失败: ' + error.message;
301
+ }
302
+ }
303
+
304
+ function getLevelColor(level) {
305
+ const colors = {
306
+ 'error': '#dc3545',
307
+ 'warn': '#ffc107',
308
+ 'info': '#007bff',
309
+ 'success': '#28a745'
310
+ };
311
+ return colors[level] || '#6c757d';
312
+ }
313
+
314
+ // 性能监控
315
+ function measurePerformance() {
316
+ const perfData = performance.getEntriesByType('navigation')[0];
317
+ sendLog('performance', 'info', '页面性能数据', {
318
+ domContentLoaded: perfData.domContentLoadedEventEnd - perfData.domContentLoadedEventStart,
319
+ loadComplete: perfData.loadEventEnd - perfData.loadEventStart,
320
+ totalLoadTime: perfData.loadEventEnd - perfData.fetchStart,
321
+ domInteractive: perfData.domInteractive - perfData.fetchStart
322
+ });
323
+ }
324
+
325
+ async function measureApiPerformance() {
326
+ const startTime = performance.now();
327
+ try {
328
+ await fetch('/api/debug-log/list');
329
+ const duration = performance.now() - startTime;
330
+
331
+ sendLog('performance', 'info', 'API 性能测试', {
332
+ endpoint: '/api/debug-log/list',
333
+ responseTime: duration.toFixed(2) + 'ms',
334
+ status: 'success'
335
+ });
336
+ } catch (error) {
337
+ const duration = performance.now() - startTime;
338
+ sendLog('performance', 'error', 'API 性能测试失败', {
339
+ endpoint: '/api/debug-log/list',
340
+ responseTime: duration.toFixed(2) + 'ms',
341
+ error: error.message
342
+ });
343
+ }
344
+ }
345
+
346
+ // 页面加载时自动发送日志
347
+ window.addEventListener('load', () => {
348
+ sendLog('page', 'info', '页面加载完成', {
349
+ userAgent: navigator.userAgent,
350
+ screen: `${window.screen.width}x${window.screen.height}`,
351
+ language: navigator.language
352
+ });
353
+ });
354
+
355
+ // 页面卸载前发送日志
356
+ window.addEventListener('beforeunload', () => {
357
+ navigator.sendBeacon(DEBUG_ENDPOINT, JSON.stringify({
358
+ logs: [{
359
+ sessionId: sessionId,
360
+ timestamp: Date.now(),
361
+ type: 'page',
362
+ level: 'info',
363
+ message: '页面即将卸载',
364
+ url: window.location.href
365
+ }],
366
+ source: 'example'
367
+ }));
368
+ });
369
+ </script>
370
+ </body>
371
+ </html>