temp
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
node_modules
|
||||||
50
docker/compose.yml
Normal file
50
docker/compose.yml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
services:
|
||||||
|
loki:
|
||||||
|
image: grafana/loki:latest
|
||||||
|
container_name: loki
|
||||||
|
ports:
|
||||||
|
- "3100:3100"
|
||||||
|
volumes:
|
||||||
|
- ./loki/loki-config.yaml:/etc/loki/local-config.yaml
|
||||||
|
- ./loki/data:/loki
|
||||||
|
command: -config.file=/etc/loki/local-config.yaml
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- monitoring
|
||||||
|
|
||||||
|
promtail:
|
||||||
|
image: grafana/promtail:latest
|
||||||
|
container_name: promtail
|
||||||
|
volumes:
|
||||||
|
- ./promtail/promtail-config.yaml:/etc/promtail/config.yml
|
||||||
|
- ./logs:/var/log/ai-api # 挂载你的 AI API 日志目录
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock # 可选:用于 Docker 日志采集
|
||||||
|
command: -config.file=/etc/promtail/config.yml
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
- loki
|
||||||
|
networks:
|
||||||
|
- monitoring
|
||||||
|
|
||||||
|
grafana:
|
||||||
|
image: grafana/grafana:latest
|
||||||
|
container_name: grafana
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
volumes:
|
||||||
|
- ./grafana/grafana.ini:/etc/grafana/grafana.ini
|
||||||
|
- ./grafana/provisioning/datasources:/etc/grafana/provisioning/datasources
|
||||||
|
- ./grafana/provisioning/dashboards:/etc/grafana/provisioning/dashboards
|
||||||
|
- ./grafana/data:/var/lib/grafana
|
||||||
|
environment:
|
||||||
|
- GF_SECURITY_ADMIN_USER=admin
|
||||||
|
- GF_SECURITY_ADMIN_PASSWORD=admin
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
- loki
|
||||||
|
networks:
|
||||||
|
- monitoring
|
||||||
|
|
||||||
|
networks:
|
||||||
|
monitoring:
|
||||||
|
driver: bridge
|
||||||
74
docker/grafana/dashboards/ai-api-token-analysis.json
Normal file
74
docker/grafana/dashboards/ai-api-token-analysis.json
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
{
|
||||||
|
"title": "AI API Token Analysis",
|
||||||
|
"panels": [
|
||||||
|
{
|
||||||
|
"title": "Top 10 Most Used Tokens (last 5m)",
|
||||||
|
"type": "barchart",
|
||||||
|
"datasource": "Loki",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "{job=\"ai-api\"} | logfmt | topk(10, count_over_time(5m)) by (token)",
|
||||||
|
"legendFormat": "{{token}}",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"gridPos": { "x": 0, "y": 0, "w": 12, "h": 8 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Requests per Second by Token (last 1m)",
|
||||||
|
"type": "graph",
|
||||||
|
"datasource": "Loki",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "sum by (token) (rate({job=\"ai-api\"}[1m]))",
|
||||||
|
"legendFormat": "{{token}}",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"gridPos": { "x": 12, "y": 0, "w": 12, "h": 8 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Error Rate (HTTP 4xx/5xx)",
|
||||||
|
"type": "stat",
|
||||||
|
"datasource": "Loki",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "sum by (job) (rate({job=\"ai-api\", response_code=~\"[45]..\"}[5m]))",
|
||||||
|
"legendFormat": "Error Rate",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"options": {
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": ["lastNotNull"],
|
||||||
|
"values": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gridPos": { "x": 0, "y": 8, "w": 6, "h": 4 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Avg Latency by Token",
|
||||||
|
"type": "timeseries",
|
||||||
|
"datasource": "Loki",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "{job=\"ai-api\"} | logfmt | avg(latency_ms) by (token)",
|
||||||
|
"legendFormat": "{{token}}",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"gridPos": { "x": 6, "y": 8, "w": 18, "h": 8 }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"refresh": "5s",
|
||||||
|
"time": {
|
||||||
|
"from": "now-1h",
|
||||||
|
"to": "now"
|
||||||
|
},
|
||||||
|
"timezone": "browser",
|
||||||
|
"panels": [],
|
||||||
|
"schemaVersion": 26,
|
||||||
|
"version": 1,
|
||||||
|
"editable": true,
|
||||||
|
"uid": "ai-api-token-analysis"
|
||||||
|
}
|
||||||
11
docker/grafana/provisioning/datasources/dashboard.yml
Normal file
11
docker/grafana/provisioning/datasources/dashboard.yml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: 1
|
||||||
|
|
||||||
|
providers:
|
||||||
|
- name: 'default'
|
||||||
|
orgId: 1
|
||||||
|
folder: ''
|
||||||
|
type: file
|
||||||
|
disableDeletion: false
|
||||||
|
editable: true
|
||||||
|
options:
|
||||||
|
path: /etc/grafana/provisioning/dashboards
|
||||||
10
docker/grafana/provisioning/datasources/datasource.yml
Normal file
10
docker/grafana/provisioning/datasources/datasource.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: 1
|
||||||
|
|
||||||
|
datasources:
|
||||||
|
- name: Loki
|
||||||
|
type: loki
|
||||||
|
url: http://loki:3100
|
||||||
|
access: proxy
|
||||||
|
isDefault: true
|
||||||
|
version: 1
|
||||||
|
editable: false
|
||||||
3
docker/log.sh
Normal file
3
docker/log.sh
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
echo '{"timestamp":"2024-06-01T10:00:01Z","method":"POST","endpoint":"/v1/ai/chat","token":"sk-abc123xyz","ip":"192.168.1.100","user_id":"user_789","response_code":200,"latency_ms":450,"model":"gpt-4"}' > logs/ai-api.json
|
||||||
|
echo '{"timestamp":"2024-06-01T10:00:02Z","method":"POST","endpoint":"/v1/ai/chat","token":"sk-def456uvw","ip":"192.168.1.101","user_id":"user_123","response_code":401,"latency_ms":120,"model":"gpt-4"}' >> logs/ai-api.json
|
||||||
|
echo '{"timestamp":"2024-06-01T10:00:03Z","method":"POST","endpoint":"/v1/ai/chat","token":"sk-abc123xyz","ip":"192.168.1.102","user_id":"user_789","response_code":200,"latency_ms":380,"model":"gpt-4"}' >> logs/ai-api.json
|
||||||
50
docker/loki/loki-config.yaml
Normal file
50
docker/loki/loki-config.yaml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
auth_enabled: false
|
||||||
|
|
||||||
|
server:
|
||||||
|
http_listen_port: 3100
|
||||||
|
|
||||||
|
common:
|
||||||
|
path_prefix: /loki
|
||||||
|
storage:
|
||||||
|
filesystem:
|
||||||
|
chunks_directory: /loki/chunks
|
||||||
|
rules_directory: /loki/rules
|
||||||
|
replication_factor: 1
|
||||||
|
ring:
|
||||||
|
kvstore:
|
||||||
|
store: inmemory
|
||||||
|
|
||||||
|
schema_config:
|
||||||
|
config:
|
||||||
|
from: 2020-10-24
|
||||||
|
|
||||||
|
config_targets:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
limits_config:
|
||||||
|
# 保留30天日志
|
||||||
|
retention_period: 720h # 30天 = 720小时
|
||||||
|
max_line_length: 1048576 # 支持长日志
|
||||||
|
|
||||||
|
# 启用压缩和合并
|
||||||
|
compactor:
|
||||||
|
working_directory: /loki/compactor
|
||||||
|
retention_period: 720h
|
||||||
|
compaction_interval: 1h
|
||||||
|
|
||||||
|
distributor:
|
||||||
|
receivers:
|
||||||
|
otlp:
|
||||||
|
protocols:
|
||||||
|
grpc:
|
||||||
|
http:
|
||||||
|
|
||||||
|
ingester:
|
||||||
|
lifecycler:
|
||||||
|
address: 127.0.0.1
|
||||||
|
final_sleep: 0s
|
||||||
|
num_tokens: 512
|
||||||
|
ring:
|
||||||
|
kvstore:
|
||||||
|
store: inmemory
|
||||||
|
replication_factor: 1
|
||||||
64
docker/promtail/promtail-config.yaml
Normal file
64
docker/promtail/promtail-config.yaml
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
server:
|
||||||
|
http_listen_port: 9080
|
||||||
|
grpc_listen_port: 0
|
||||||
|
|
||||||
|
positions:
|
||||||
|
filename: /tmp/positions.yaml
|
||||||
|
|
||||||
|
clients:
|
||||||
|
- url: http://loki:3100/loki/api/v1/push
|
||||||
|
|
||||||
|
scrape_configs:
|
||||||
|
# 采集你的 AI API JSON 日志文件
|
||||||
|
- job_name: ai-api-json
|
||||||
|
static_configs:
|
||||||
|
- targets:
|
||||||
|
- localhost
|
||||||
|
labels:
|
||||||
|
job: ai-api
|
||||||
|
__path__: /var/log/ai-api/*.json # 指向挂载的日志目录
|
||||||
|
|
||||||
|
pipeline_stages:
|
||||||
|
- json:
|
||||||
|
expressions:
|
||||||
|
token: token
|
||||||
|
endpoint: endpoint
|
||||||
|
user_id: user_id
|
||||||
|
response_code: response_code
|
||||||
|
latency_ms: latency_ms
|
||||||
|
model: model
|
||||||
|
- labels:
|
||||||
|
token:
|
||||||
|
endpoint:
|
||||||
|
user_id:
|
||||||
|
response_code:
|
||||||
|
model:
|
||||||
|
|
||||||
|
# 可选:过滤错误日志(只保留 response_code >= 400)
|
||||||
|
# - drop:
|
||||||
|
# expression: "response_code < 400"
|
||||||
|
|
||||||
|
# 可选:添加时间戳(如果日志没有 timestamp 字段)
|
||||||
|
# - timestamp:
|
||||||
|
# source: timestamp
|
||||||
|
# format: RFC3339
|
||||||
|
|
||||||
|
# 可选:如果你用 Docker 容器输出日志,也可以采集容器日志
|
||||||
|
# - job_name: docker-containers
|
||||||
|
# docker_sd_configs:
|
||||||
|
# - host: unix:///var/run/docker.sock
|
||||||
|
# refresh_interval: 5s
|
||||||
|
# relabel_configs:
|
||||||
|
# - source_labels: [__meta_docker_container_name]
|
||||||
|
# regex: /(.+)
|
||||||
|
# target_label: container_name
|
||||||
|
# - source_labels: [__meta_docker_container_label_com_docker_compose_service]
|
||||||
|
# target_label: service
|
||||||
|
# pipeline_stages:
|
||||||
|
# - json:
|
||||||
|
# expressions:
|
||||||
|
# level: level
|
||||||
|
# msg: msg
|
||||||
|
# - labels:
|
||||||
|
# level:
|
||||||
|
# service:
|
||||||
Reference in New Issue
Block a user