RELEASE 1.0.1: v2 log format, source_tag-labeled metrics, lint cleanup

Wire-format and metric overhaul. Both file and UDP ingest now share one
versioned ParseLine that dispatches on the v<N>\t prefix; v1 stays
unchanged, v2 adds $bytes_sent (replacing $body_bytes_sent),
$request_length, $upstream_response_time, and $upstream_status. File
ingest gains the same versioning, and the legacy positional file format
is removed (no live deployments).

Prometheus exposition is rewritten:

  - nginx_http_bytes_sent and nginx_http_request_duration_seconds gain
    a source_tag label.
  - nginx_http_requests_by_source_total gains status_class.
  - New v2-only metrics: nginx_http_request_bytes,
    nginx_http_upstream_duration_seconds,
    nginx_http_upstream_requests_total{status_class}.
  - Dropped nginx_http_response_body_bytes_by_source (subsumed by the
    dual-labeled bytes_sent metric).

Adds 'make fixstyle' (gofmt -w) and clears all golangci-lint findings
across the repo (errcheck, S1001, ST1005, unused).

Docs in design.md FR-2/FR-8 and user-guide.md are rewritten to present
v2 as the recommended log format.
This commit is contained in:
2026-05-01 15:40:53 +02:00
parent d1a21a7a62
commit 6647f95be4
28 changed files with 931 additions and 724 deletions
+8 -7
View File
@@ -11,7 +11,8 @@ import (
func writeLine(t *testing.T, f *os.File, website string) {
t.Helper()
_, err := fmt.Fprintf(f, "%s\t1.2.3.4\t0\tGET\t/path\t200\t0\t0.001\n", website)
// v1 layout: 12 payload fields after the v1 prefix.
_, err := fmt.Fprintf(f, "v1\t%s\t1.2.3.4\tGET\t/path\t200\t0\t0.001\t0\t0\tdirect\t10.0.0.1\thttps\n", website)
if err != nil {
t.Fatalf("writeLine: %v", err)
}
@@ -25,7 +26,7 @@ func TestMultiTailerReadsLines(t *testing.T) {
if err != nil {
t.Fatal(err)
}
defer f.Close()
defer func() { _ = f.Close() }()
ch := make(chan LogRecord, 100)
mt := NewMultiTailer([]string{path}, time.Hour, 24, 48, ch)
@@ -62,7 +63,7 @@ func TestMultiTailerMultipleFiles(t *testing.T) {
if err != nil {
t.Fatal(err)
}
defer f.Close()
defer func() { _ = f.Close() }()
files[i] = f
}
@@ -108,7 +109,7 @@ func TestMultiTailerLogRotation(t *testing.T) {
// Simulate logrotate: rename the old file, create a new one
rotated := filepath.Join(dir, "access.log.1")
f.Close()
_ = f.Close()
if err := os.Rename(path, rotated); err != nil {
t.Fatal(err)
}
@@ -121,7 +122,7 @@ func TestMultiTailerLogRotation(t *testing.T) {
if err != nil {
t.Fatal(err)
}
defer newF.Close()
defer func() { _ = newF.Close() }()
// Allow retry goroutine to pick it up
time.Sleep(300 * time.Millisecond)
@@ -137,7 +138,7 @@ func TestExpandGlobs(t *testing.T) {
dir := t.TempDir()
for _, name := range []string{"a.log", "b.log", "other.txt"} {
f, _ := os.Create(filepath.Join(dir, name))
f.Close()
_ = f.Close()
}
pattern := filepath.Join(dir, "*.log")
@@ -151,7 +152,7 @@ func TestExpandGlobsDeduplication(t *testing.T) {
dir := t.TempDir()
p := filepath.Join(dir, "access.log")
f, _ := os.Create(p)
f.Close()
_ = f.Close()
// Same file listed twice via explicit path and glob
paths := expandGlobs([]string{p, filepath.Join(dir, "*.log")})