visitlog

package module
v0.0.0-...-3b06e81 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 24, 2026 License: GPL-3.0 Imports: 24 Imported by: 0

README

caddy_visitlog

Ein Caddy-HTTP-Handler-Modul für Visitor-Analytics mit eingebettetem SQLite (modernc.org/sqlite).

Features

  • loggt IP, URL-Pfad, Query, Status, User-Agent, Referer, Response-Größe, Dauer
  • schreibt asynchron über Channel + Batch-Writer
  • nutzt SQLite im WAL-Modus
  • Retention-Cleanup im Hintergrund
  • exclude-Patterns für Healthchecks, Assets usw.
  • pure Go SQLite-Treiber, kein CGO

Caddyfile

{
    order visitor_analytics before reverse_proxy
    order visitor_analytics_admin before file_server
}

example.com {
    route {
        visitor_analytics {
            db /var/lib/caddy-visitor/analytics.sqlite
            retention 7d
            exclude /health /favicon.ico /assets/* /caddy_visitlog*
            batch_size 500
            flush_interval 1s
            queue_size 10000
        }

        reverse_proxy localhost:8080
    }

    handle /caddy_visitlog* {
        visitor_analytics_admin {
            db /var/lib/caddy-visitor/analytics.sqlite
            default_range 7d
            page_size 100
        }
    }
}

Empfehlung: Das Admin-Frontend selbst über exclude /caddy_visitlog* aus dem Tracking ausnehmen, damit die Auswertungsoberfläche nicht ihre eigenen Requests mitschreibt.

Konfiguration und Defaults

visitor_analytics
  • dbPflichtfeld, kein Default
  • retention — Default: 7d
  • exclude — Default: leer
  • batch_size — Default: 500
  • flush_interval — Default: 1s
  • queue_size — Default: 10000
visitor_analytics_admin
  • dbPflichtfeld, kein Default
  • default_range — Default: 7d
  • page_size — Default: 100
Laufzeitverhalten
  • wenn noch kein Status geschrieben wurde und der Upstream/Handler einen Fehler zurückgibt, wird 500 geloggt
  • wenn noch kein Status geschrieben wurde und kein Fehler vorliegt, wird 200 geloggt
  • bei voller Event-Queue werden Requests nicht blockiert; stattdessen wird das Event verworfen und eine Warnung geloggt
  • site wird aktuell aus dem Request-Host befüllt
  • query wird normal als r.URL.RawQuery gespeichert; ohne Querystring ist der Wert leer
  • Client-IP wird bevorzugt aus Caddys Context-Variable client_ip gelesen, sonst aus RemoteAddr
  • beim Aufruf ohne abschließenden Slash, z. B. /caddy_visitlog, leitet das Admin-Modul auf /caddy_visitlog/ um
  • das Dashboard lädt Chart.js aktuell per CDN von jsdelivr

Gespeichertes Schema

CREATE TABLE hits (
  id INTEGER PRIMARY KEY,
  ts INTEGER NOT NULL,
  site TEXT NOT NULL,
  method TEXT NOT NULL,
  host TEXT NOT NULL,
  path TEXT NOT NULL,
  query TEXT,
  status INTEGER,
  ip TEXT,
  user_agent TEXT,
  referer TEXT,
  duration_ms INTEGER,
  bytes INTEGER
);

Admin UI und API

Aufrufbeispiele:

  • Dashboard: /caddy_visitlog/
  • Summary API: /caddy_visitlog/api/summary
  • Timeseries API: /caddy_visitlog/api/timeseries?bucket=hour
  • Top Paths: /caddy_visitlog/api/top-paths
  • Recent Requests: /caddy_visitlog/api/recent?limit=50
  • CSV Export: /caddy_visitlog/api/export.csv?from=2026-05-01T00:00:00Z&to=2026-05-24T23:59:59Z

Verfügbare Query-Filter für fast alle API-Endpunkte:

  • from
  • to
  • host
  • site
  • method
  • status
  • path_prefix
  • ip
  • limit
  • offset
  • bucket (minute, hour, day)

Basic Auth Komplettbeispiel

Zuerst einen Passwort-Hash erzeugen:

caddy hash-password --plaintext 'mein-sicheres-passwort'

Dann die Admin-Oberfläche absichern:

{
    order visitor_analytics before reverse_proxy
    order visitor_analytics_admin before file_server
}

example.com {
    route {
        visitor_analytics {
            db /var/lib/caddy-visitor/analytics.sqlite
            retention 7d
            exclude /health /favicon.ico /assets/* /caddy_visitlog*
            batch_size 500
            flush_interval 1s
            queue_size 10000
        }

        reverse_proxy localhost:8080
    }

    handle /caddy_visitlog* {
        basic_auth {
            admin HASH_HIER_EINFUEGEN
        }

        visitor_analytics_admin {
            db /var/lib/caddy-visitor/analytics.sqlite
            default_range 7d
            page_size 100
        }
    }
}

HASH_HIER_EINFUEGEN ersetzt du durch den von caddy hash-password erzeugten Wert.

Build mit xcaddy

xcaddy build \
  --with github.com/RobinGru/caddy_visitlog

Hinweise

  • Empfehlung: für produktive Nutzung die Admin-Route zusätzlich über Netzwerk-/IP-Restriktionen oder VPN absichern, nicht nur über basic_auth.
  • CSV-Export unterstützt offset und limit; serverseitig wird das Export-Limit auf maximal 10000 Einträge pro Request begrenzt.
  • Die JSON-Toplisten-Endpunkte begrenzen limit serverseitig auf maximal 1000.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type VisitorAnalytics

type VisitorAnalytics struct {
	DBPath        string        `json:"db,omitempty"`
	Retention     time.Duration `json:"retention,omitempty"`
	Exclude       []string      `json:"exclude,omitempty"`
	BatchSize     int           `json:"batch_size,omitempty"`
	FlushInterval time.Duration `json:"flush_interval,omitempty"`
	QueueSize     int           `json:"queue_size,omitempty"`
	// contains filtered or unexported fields
}

VisitorAnalytics logs HTTP request/response metadata into SQLite.

func (*VisitorAnalytics) CaddyModule

func (*VisitorAnalytics) CaddyModule() caddy.ModuleInfo

func (*VisitorAnalytics) Cleanup

func (v *VisitorAnalytics) Cleanup() error

func (*VisitorAnalytics) Provision

func (v *VisitorAnalytics) Provision(ctx caddy.Context) error

func (*VisitorAnalytics) ServeHTTP

func (*VisitorAnalytics) UnmarshalCaddyfile

func (v *VisitorAnalytics) UnmarshalCaddyfile(d *caddyfile.Dispenser) error

func (*VisitorAnalytics) Validate

func (v *VisitorAnalytics) Validate() error

type VisitorAnalyticsAdmin

type VisitorAnalyticsAdmin struct {
	DBPath       string        `json:"db,omitempty"`
	DefaultRange time.Duration `json:"default_range,omitempty"`
	PageSize     int           `json:"page_size,omitempty"`
	// contains filtered or unexported fields
}

func (*VisitorAnalyticsAdmin) CaddyModule

func (*VisitorAnalyticsAdmin) CaddyModule() caddy.ModuleInfo

func (*VisitorAnalyticsAdmin) Cleanup

func (a *VisitorAnalyticsAdmin) Cleanup() error

func (*VisitorAnalyticsAdmin) Provision

func (a *VisitorAnalyticsAdmin) Provision(ctx caddy.Context) error

func (*VisitorAnalyticsAdmin) ServeHTTP

func (*VisitorAnalyticsAdmin) UnmarshalCaddyfile

func (a *VisitorAnalyticsAdmin) UnmarshalCaddyfile(d *caddyfile.Dispenser) error

func (*VisitorAnalyticsAdmin) Validate

func (a *VisitorAnalyticsAdmin) Validate() error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL