traffic

package
v0.6.25 Latest Latest
Warning

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

Go to latest
Published: May 14, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package traffic analyses Caddy access logs to produce per-service bot-detection signals used to distinguish genuine human inactivity from automated keepalive pings.

Motivation

Hobby-tier services sleep after 30 minutes of genuine inactivity, but external cron jobs (e.g. cron-job.org, UptimeRobot) are commonly used to prevent sleep by pinging a service on a fixed schedule. A naive last-request timestamp is trivially defeated by a single automated pinger.

Algorithm

Three independent signals are evaluated over a rolling 1-hour window per service. A service is considered genuinely idle only when ALL three signals agree:

  1. Subnet diversity — real sites attract visitors from many networks. Threshold: fewer than 3 unique /24 subnets in the window.

  2. Cadence regularity — human visits are aperiodic; cron jobs are metronomic. Measured as the coefficient of variation (stddev/mean) of inter-request gaps. Threshold: CV < 0.2 (highly regular).

  3. Path diversity — humans browse multiple pages; ping bots hit only / or /health. Threshold: fewer than 2 unique request paths in the window.

If any one signal suggests human-like traffic, the service remains awake.

Data source

Signals are derived from Caddy's per-domain JSON access logs written to ~/.dployr/logs/caddy/{domain}.log. No additional instrumentation is required. The computed signals are included in the v1.1 node update and evaluated on base.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CaddyLogDir

func CaddyLogDir() string

CaddyLogDir returns the canonical path to the Caddy per-domain log directory.

Types

type LogEntry

type LogEntry struct {
	TS      float64    `json:"ts"` // Unix timestamp with fractional seconds
	Request LogRequest `json:"request"`
	Status  int        `json:"status"`
}

LogEntry represents a single line from Caddy's JSON access log. Fields match Caddy's default structured log output.

func ReadLastHour

func ReadLastHour(logPath string) ([]LogEntry, error)

ReadLastHour reads a Caddy JSON access log file and returns all entries whose timestamp falls within the past hour. Lines that cannot be parsed are silently skipped so a single malformed line never blocks analysis.

type LogRequest

type LogRequest struct {
	RemoteIP string `json:"remote_ip"`
	URI      string `json:"uri"`
	Method   string `json:"method"`
}

LogRequest holds the per-request fields we care about for signal computation.

type Signals

type Signals struct {
	// Domain is the Caddy virtual-host domain this log file belongs to.
	Domain string `json:"domain"`

	// WindowHours is the observation window used (always 1).
	WindowHours int `json:"window_hours"`

	// RequestCount is the total number of requests seen in the window.
	RequestCount int `json:"request_count"`

	// UniqueSubnets is the count of distinct /24 networks that sent requests.
	// Fewer than 3 suggests a single automated source.
	UniqueSubnets int `json:"unique_subnets"`

	// CadenceCV is the coefficient of variation (stddev/mean) of inter-request
	// gap durations in seconds. Values below 0.2 indicate metronomic (bot-like)
	// cadence. Set to 1.0 when fewer than 2 requests are present.
	CadenceCV float64 `json:"cadence_cv"`

	// UniquePaths is the count of distinct URI paths (query strings stripped).
	// Fewer than 2 suggests a bot hitting only / or /health.
	UniquePaths int `json:"unique_paths"`

	// LastRequestAt is the Unix millisecond timestamp of the most recent request
	// in the window, or 0 if the window is empty.
	LastRequestAt int64 `json:"last_request_at"`
}

Signals holds the computed bot-detection signals for a single service over a rolling 1-hour observation window.

func Compute

func Compute(domain, logDir string) Signals

Compute derives bot-detection signals for a given domain from its Caddy access log. logDir is the directory where Caddy writes per-domain log files (typically ~/.dployr/logs/caddy/).

Jump to

Keyboard shortcuts

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