fix(server): 修复 Agent 上报访问日志的 bytes_sent 在 Server 入库链路丢失,导致 Zone 概览“已提供的数据总计”长期为 0 的问题。

This commit is contained in:
ryan
2026-07-12 19:02:52 +08:00
parent c624512da6
commit 69467914fc
5 changed files with 48 additions and 9 deletions
+1
View File
@@ -41,6 +41,7 @@ sidebar: false
### 修复
- 修复 Agent 上报访问日志的 `bytes_sent` 在 Server 入库链路丢失,导致 Zone 概览“已提供的数据总计”长期为 0 的问题。
- 修复嵌入式静态前端访问 `/websites/:zoneId` 时回退到首页 HTML,导致 Zone 详情页显示总览并触发 React hydration error 的问题。
- Docker ClickHouse 性能配置改为单文件挂载,避免覆盖镜像内置的 Docker 网络监听配置,导致宿主机无法通过 8123/9000 访问服务。
@@ -19,13 +19,13 @@ import (
)
const (
healthEventStatusActive = "active"
healthEventStatusResolved = "resolved"
healthSeverityInfo = "info"
healthSeverityWarning = "warning"
healthSeverityCritical = "critical"
accessLogPathMaxLength = 100
healthEventMessageMaxLength = 4096
healthEventStatusActive = "active"
healthEventStatusResolved = "resolved"
healthSeverityInfo = "info"
healthSeverityWarning = "warning"
healthSeverityCritical = "critical"
accessLogPathMaxLength = 100
healthEventMessageMaxLength = 4096
)
// PersistHeartbeatObservability stores profile, snapshots, traffic, access logs, and health events.
@@ -221,6 +221,7 @@ func buildNodeAccessLogRecords(nodeID string, direct []NodeAccessLog, buffered [
Host: strings.TrimSpace(item.Host),
Path: truncateForDatabase(strings.TrimSpace(item.Path), accessLogPathMaxLength),
StatusCode: item.StatusCode,
BytesSent: item.BytesSent,
}
if resolver != nil {
record.Region = resolver.Resolve(record.RemoteAddr)
@@ -0,0 +1,33 @@
// Copyright 2026 Arctel.net
// SPDX-License-Identifier: Apache-2.0
package agent
import (
"testing"
"time"
)
func TestBuildNodeAccessLogRecordsPreservesBytesSent(t *testing.T) {
reportedAt := time.Date(2026, 7, 12, 10, 0, 0, 0, time.UTC)
records, err := buildNodeAccessLogRecords("node-a", []NodeAccessLog{
{
LoggedAtUnix: reportedAt.Unix(),
RemoteAddr: "203.0.113.10",
Host: "api.example.com",
Path: "/v1/ping",
StatusCode: 200,
BytesSent: 4096,
},
}, nil, reportedAt)
if err != nil {
t.Fatalf("buildNodeAccessLogRecords() error = %v", err)
}
if len(records) != 1 {
t.Fatalf("expected one access log record, got %d", len(records))
}
if records[0].BytesSent != 4096 {
t.Fatalf("BytesSent = %d, want 4096", records[0].BytesSent)
}
}
@@ -39,6 +39,7 @@ func TestBatchInsertNodeAccessLogs_UsesModelBatchSQL(t *testing.T) {
Host: "example.com",
Path: "/alpha",
StatusCode: 200,
BytesSent: 2048,
CreatedAt: loggedAt,
},
})
@@ -48,4 +49,6 @@ func TestBatchInsertNodeAccessLogs_UsesModelBatchSQL(t *testing.T) {
assert.True(t, mockBatch.sendCalled)
require.Len(t, mockBatch.rows, 1)
assert.Equal(t, "node-a", mockBatch.rows[0][1])
}
require.Len(t, mockBatch.rows[0], 10)
assert.Equal(t, uint64(2048), mockBatch.rows[0][8])
}
@@ -47,6 +47,7 @@ func BatchInsertNodeAccessLogs(ctx context.Context, logs []analyticsmodel.NodeAc
logItem.Host,
logItem.Path,
logItem.StatusCode,
logItem.BytesSent,
createdAt.UTC(),
); err != nil {
return fmt.Errorf("append node access log to batch: %w", err)
@@ -57,4 +58,4 @@ func BatchInsertNodeAccessLogs(ctx context.Context, logs []analyticsmodel.NodeAc
return fmt.Errorf("send clickhouse batch: %w", err)
}
return nil
}
}