Commit 52316952 authored by Matthew Holt's avatar Matthew Holt

Refactor diagnostics -> telemetry

parent 7c868afd
...@@ -44,7 +44,7 @@ import ( ...@@ -44,7 +44,7 @@ import (
"time" "time"
"github.com/mholt/caddy/caddyfile" "github.com/mholt/caddy/caddyfile"
"github.com/mholt/caddy/diagnostics" "github.com/mholt/caddy/telemetry"
) )
// Configurable application parameters // Configurable application parameters
...@@ -617,7 +617,7 @@ func ValidateAndExecuteDirectives(cdyfile Input, inst *Instance, justValidate bo ...@@ -617,7 +617,7 @@ func ValidateAndExecuteDirectives(cdyfile Input, inst *Instance, justValidate bo
return fmt.Errorf("error inspecting server blocks: %v", err) return fmt.Errorf("error inspecting server blocks: %v", err)
} }
diagnostics.Set("http_num_server_blocks", len(sblocks)) telemetry.Set("http_num_server_blocks", len(sblocks))
return executeDirectives(inst, cdyfile.Path(), stype.Directives(), sblocks, justValidate) return executeDirectives(inst, cdyfile.Path(), stype.Directives(), sblocks, justValidate)
} }
......
...@@ -30,7 +30,7 @@ import ( ...@@ -30,7 +30,7 @@ import (
"github.com/klauspost/cpuid" "github.com/klauspost/cpuid"
"github.com/mholt/caddy" "github.com/mholt/caddy"
"github.com/mholt/caddy/caddytls" "github.com/mholt/caddy/caddytls"
"github.com/mholt/caddy/diagnostics" "github.com/mholt/caddy/telemetry"
"github.com/xenolf/lego/acme" "github.com/xenolf/lego/acme"
"gopkg.in/natefinch/lumberjack.v2" "gopkg.in/natefinch/lumberjack.v2"
...@@ -52,7 +52,6 @@ func init() { ...@@ -52,7 +52,6 @@ func init() {
flag.StringVar(&caddytls.DefaultEmail, "email", "", "Default ACME CA account email address") flag.StringVar(&caddytls.DefaultEmail, "email", "", "Default ACME CA account email address")
flag.DurationVar(&acme.HTTPClient.Timeout, "catimeout", acme.HTTPClient.Timeout, "Default ACME CA HTTP timeout") flag.DurationVar(&acme.HTTPClient.Timeout, "catimeout", acme.HTTPClient.Timeout, "Default ACME CA HTTP timeout")
flag.StringVar(&logfile, "log", "", "Process log file") flag.StringVar(&logfile, "log", "", "Process log file")
flag.BoolVar(&noDiag, "no-diagnostics", false, "Disable diagnostic reporting")
flag.StringVar(&caddy.PidFile, "pidfile", "", "Path to write pid file") flag.StringVar(&caddy.PidFile, "pidfile", "", "Path to write pid file")
flag.BoolVar(&caddy.Quiet, "quiet", false, "Quiet mode (no initialization output)") flag.BoolVar(&caddy.Quiet, "quiet", false, "Quiet mode (no initialization output)")
flag.StringVar(&revoke, "revoke", "", "Hostname for which to revoke the certificate") flag.StringVar(&revoke, "revoke", "", "Hostname for which to revoke the certificate")
...@@ -89,9 +88,9 @@ func Run() { ...@@ -89,9 +88,9 @@ func Run() {
}) })
} }
// initialize diagnostics client // initialize telemetry client
if !noDiag { if enableTelemetry {
initDiagnostics() initTelemetry()
} }
// Check for one-time actions // Check for one-time actions
...@@ -150,13 +149,13 @@ func Run() { ...@@ -150,13 +149,13 @@ func Run() {
// Execute instantiation events // Execute instantiation events
caddy.EmitEvent(caddy.InstanceStartupEvent, instance) caddy.EmitEvent(caddy.InstanceStartupEvent, instance)
// Begin diagnostics (these are no-ops if diagnostics disabled) // Begin telemetry (these are no-ops if telemetry disabled)
diagnostics.Set("caddy_version", appVersion) telemetry.Set("caddy_version", appVersion)
diagnostics.Set("num_listeners", len(instance.Servers())) telemetry.Set("num_listeners", len(instance.Servers()))
diagnostics.Set("server_type", serverType) telemetry.Set("server_type", serverType)
diagnostics.Set("os", runtime.GOOS) telemetry.Set("os", runtime.GOOS)
diagnostics.Set("arch", runtime.GOARCH) telemetry.Set("arch", runtime.GOARCH)
diagnostics.Set("cpu", struct { telemetry.Set("cpu", struct {
BrandName string `json:"brand_name,omitempty"` BrandName string `json:"brand_name,omitempty"`
NumLogical int `json:"num_logical,omitempty"` NumLogical int `json:"num_logical,omitempty"`
AESNI bool `json:"aes_ni,omitempty"` AESNI bool `json:"aes_ni,omitempty"`
...@@ -165,7 +164,7 @@ func Run() { ...@@ -165,7 +164,7 @@ func Run() {
NumLogical: runtime.NumCPU(), NumLogical: runtime.NumCPU(),
AESNI: cpuid.CPU.AesNi(), AESNI: cpuid.CPU.AesNi(),
}) })
diagnostics.StartEmitting() telemetry.StartEmitting()
// Twiddle your thumbs // Twiddle your thumbs
instance.Wait() instance.Wait()
...@@ -290,8 +289,8 @@ func setCPU(cpu string) error { ...@@ -290,8 +289,8 @@ func setCPU(cpu string) error {
return nil return nil
} }
// initDiagnostics initializes the diagnostics engine. // initTelemetry initializes the telemetry engine.
func initDiagnostics() { func initTelemetry() {
uuidFilename := filepath.Join(caddy.AssetsPath(), "uuid") uuidFilename := filepath.Join(caddy.AssetsPath(), "uuid")
newUUID := func() uuid.UUID { newUUID := func() uuid.UUID {
...@@ -327,7 +326,7 @@ func initDiagnostics() { ...@@ -327,7 +326,7 @@ func initDiagnostics() {
} }
} }
diagnostics.Init(id) telemetry.Init(id)
} }
const appName = "Caddy" const appName = "Caddy"
...@@ -342,7 +341,6 @@ var ( ...@@ -342,7 +341,6 @@ var (
version bool version bool
plugins bool plugins bool
validate bool validate bool
noDiag bool
) )
// Build information obtained with the help of -ldflags // Build information obtained with the help of -ldflags
...@@ -356,4 +354,6 @@ var ( ...@@ -356,4 +354,6 @@ var (
gitCommit string // git rev-parse HEAD gitCommit string // git rev-parse HEAD
gitShortStat string // git diff-index --shortstat gitShortStat string // git diff-index --shortstat
gitFilesModified string // git diff-index --name-only HEAD gitFilesModified string // git diff-index --name-only HEAD
enableTelemetry = true
) )
...@@ -21,7 +21,7 @@ import ( ...@@ -21,7 +21,7 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/mholt/caddy/diagnostics" "github.com/mholt/caddy/telemetry"
) )
// Parse parses the input just enough to group tokens, in // Parse parses the input just enough to group tokens, in
...@@ -371,7 +371,7 @@ func (p *parser) directive() error { ...@@ -371,7 +371,7 @@ func (p *parser) directive() error {
// The directive itself is appended as a relevant token // The directive itself is appended as a relevant token
p.block.Tokens[dir] = append(p.block.Tokens[dir], p.tokens[p.cursor]) p.block.Tokens[dir] = append(p.block.Tokens[dir], p.tokens[p.cursor])
diagnostics.AppendUnique("directives", dir) telemetry.AppendUnique("directives", dir)
for p.Next() { for p.Next() {
if p.Val() == "{" { if p.Val() == "{" {
......
...@@ -25,7 +25,7 @@ import ( ...@@ -25,7 +25,7 @@ import (
"strings" "strings"
"sync" "sync"
"github.com/mholt/caddy/diagnostics" "github.com/mholt/caddy/telemetry"
) )
// tlsHandler is a http.Handler that will inject a value // tlsHandler is a http.Handler that will inject a value
...@@ -103,12 +103,12 @@ func (h *tlsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { ...@@ -103,12 +103,12 @@ func (h *tlsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if checked { if checked {
r = r.WithContext(context.WithValue(r.Context(), MitmCtxKey, mitm)) r = r.WithContext(context.WithValue(r.Context(), MitmCtxKey, mitm))
if mitm { if mitm {
go diagnostics.AppendUnique("http_mitm", "likely") go telemetry.AppendUnique("http_mitm", "likely")
} else { } else {
go diagnostics.AppendUnique("http_mitm", "unlikely") go telemetry.AppendUnique("http_mitm", "unlikely")
} }
} else { } else {
go diagnostics.AppendUnique("http_mitm", "unknown") go telemetry.AppendUnique("http_mitm", "unknown")
} }
if mitm && h.closeOnMITM { if mitm && h.closeOnMITM {
......
...@@ -29,7 +29,7 @@ import ( ...@@ -29,7 +29,7 @@ import (
"github.com/mholt/caddy/caddyfile" "github.com/mholt/caddy/caddyfile"
"github.com/mholt/caddy/caddyhttp/staticfiles" "github.com/mholt/caddy/caddyhttp/staticfiles"
"github.com/mholt/caddy/caddytls" "github.com/mholt/caddy/caddytls"
"github.com/mholt/caddy/diagnostics" "github.com/mholt/caddy/telemetry"
) )
const serverType = "http" const serverType = "http"
...@@ -220,9 +220,9 @@ func (h *httpContext) MakeServers() ([]caddy.Server, error) { ...@@ -220,9 +220,9 @@ func (h *httpContext) MakeServers() ([]caddy.Server, error) {
var atLeastOneSiteLooksLikeProduction bool var atLeastOneSiteLooksLikeProduction bool
for _, cfg := range h.siteConfigs { for _, cfg := range h.siteConfigs {
// if we aren't sure yet whether it's a "production" server, // see if all the addresses (both sites and
// continue to see if all the addresses (both sites and // listeners) are loopback to help us determine
// listeners) are loopback // if this is a "production" instance or not
if !atLeastOneSiteLooksLikeProduction { if !atLeastOneSiteLooksLikeProduction {
if !caddy.IsLoopback(cfg.Addr.Host) && if !caddy.IsLoopback(cfg.Addr.Host) &&
!caddy.IsLoopback(cfg.ListenHost) && !caddy.IsLoopback(cfg.ListenHost) &&
...@@ -272,17 +272,17 @@ func (h *httpContext) MakeServers() ([]caddy.Server, error) { ...@@ -272,17 +272,17 @@ func (h *httpContext) MakeServers() ([]caddy.Server, error) {
servers = append(servers, s) servers = append(servers, s)
} }
// NOTE: This value is only a "good" guess. Quite often, development // NOTE: This value is only a "good guess". Quite often, development
// environments will use internal DNS or a local hosts file to serve // environments will use internal DNS or a local hosts file to serve
// real-looking domains in local development. We can't easily tell // real-looking domains in local development. We can't easily tell
// which without doing a DNS lookup, so this guess is definitely naive, // which without doing a DNS lookup, so this guess is definitely naive,
// and if we ever want a better guess, we will have to do DNS lookups. // and if we ever want a better guess, we will have to do DNS lookups.
deploymentGuess := "dev" deploymentGuess := "dev"
if looksLikeProductionCA && atLeastOneSiteLooksLikeProduction { if looksLikeProductionCA && atLeastOneSiteLooksLikeProduction {
deploymentGuess = "production" deploymentGuess = "prod"
} }
diagnostics.Set("http_deployment_guess", deploymentGuess) telemetry.Set("http_deployment_guess", deploymentGuess)
diagnostics.Set("http_num_sites", len(h.siteConfigs)) telemetry.Set("http_num_sites", len(h.siteConfigs))
return servers, nil return servers, nil
} }
......
...@@ -36,7 +36,7 @@ import ( ...@@ -36,7 +36,7 @@ import (
"github.com/mholt/caddy" "github.com/mholt/caddy"
"github.com/mholt/caddy/caddyhttp/staticfiles" "github.com/mholt/caddy/caddyhttp/staticfiles"
"github.com/mholt/caddy/caddytls" "github.com/mholt/caddy/caddytls"
"github.com/mholt/caddy/diagnostics" "github.com/mholt/caddy/telemetry"
) )
// Server is the HTTP server implementation. // Server is the HTTP server implementation.
...@@ -347,8 +347,8 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { ...@@ -347,8 +347,8 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}() }()
// TODO: Somehow report UA string in conjunction with TLS handshake, if any (and just once per connection) // TODO: Somehow report UA string in conjunction with TLS handshake, if any (and just once per connection)
go diagnostics.AppendUnique("http_user_agent", r.Header.Get("User-Agent")) go telemetry.AppendUnique("http_user_agent", r.Header.Get("User-Agent"))
go diagnostics.Increment("http_request_count") go telemetry.Increment("http_request_count")
// copy the original, unchanged URL into the context // copy the original, unchanged URL into the context
// so it can be referenced by middlewares // so it can be referenced by middlewares
......
...@@ -26,7 +26,7 @@ import ( ...@@ -26,7 +26,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/mholt/caddy/diagnostics" "github.com/mholt/caddy/telemetry"
"golang.org/x/crypto/ocsp" "golang.org/x/crypto/ocsp"
) )
...@@ -166,7 +166,7 @@ func (cfg *Config) CacheManagedCertificate(domain string) (Certificate, error) { ...@@ -166,7 +166,7 @@ func (cfg *Config) CacheManagedCertificate(domain string) (Certificate, error) {
if err != nil { if err != nil {
return cert, err return cert, err
} }
diagnostics.Increment("tls_managed_cert_count") telemetry.Increment("tls_managed_cert_count")
return cfg.cacheCertificate(cert), nil return cfg.cacheCertificate(cert), nil
} }
...@@ -181,7 +181,7 @@ func (cfg *Config) cacheUnmanagedCertificatePEMFile(certFile, keyFile string) er ...@@ -181,7 +181,7 @@ func (cfg *Config) cacheUnmanagedCertificatePEMFile(certFile, keyFile string) er
return err return err
} }
cfg.cacheCertificate(cert) cfg.cacheCertificate(cert)
diagnostics.Increment("tls_manual_cert_count") telemetry.Increment("tls_manual_cert_count")
return nil return nil
} }
...@@ -195,7 +195,7 @@ func (cfg *Config) cacheUnmanagedCertificatePEMBytes(certBytes, keyBytes []byte) ...@@ -195,7 +195,7 @@ func (cfg *Config) cacheUnmanagedCertificatePEMBytes(certBytes, keyBytes []byte)
return err return err
} }
cfg.cacheCertificate(cert) cfg.cacheCertificate(cert)
diagnostics.Increment("tls_manual_cert_count") telemetry.Increment("tls_manual_cert_count")
return nil return nil
} }
......
...@@ -26,7 +26,7 @@ import ( ...@@ -26,7 +26,7 @@ import (
"time" "time"
"github.com/mholt/caddy" "github.com/mholt/caddy"
"github.com/mholt/caddy/diagnostics" "github.com/mholt/caddy/telemetry"
"github.com/xenolf/lego/acme" "github.com/xenolf/lego/acme"
) )
...@@ -268,7 +268,7 @@ Attempts: ...@@ -268,7 +268,7 @@ Attempts:
break break
} }
go diagnostics.Increment("tls_acme_certs_obtained") go telemetry.Increment("tls_acme_certs_obtained")
return nil return nil
} }
...@@ -340,7 +340,7 @@ func (c *ACMEClient) Renew(name string) error { ...@@ -340,7 +340,7 @@ func (c *ACMEClient) Renew(name string) error {
} }
caddy.EmitEvent(caddy.CertRenewEvent, name) caddy.EmitEvent(caddy.CertRenewEvent, name)
go diagnostics.Increment("tls_acme_certs_renewed") go telemetry.Increment("tls_acme_certs_renewed")
return saveCertResource(c.storage, newCertMeta) return saveCertResource(c.storage, newCertMeta)
} }
...@@ -367,7 +367,7 @@ func (c *ACMEClient) Revoke(name string) error { ...@@ -367,7 +367,7 @@ func (c *ACMEClient) Revoke(name string) error {
return err return err
} }
go diagnostics.Increment("tls_acme_certs_revoked") go telemetry.Increment("tls_acme_certs_revoked")
err = c.storage.DeleteSite(name) err = c.storage.DeleteSite(name)
if err != nil { if err != nil {
......
...@@ -26,7 +26,7 @@ import ( ...@@ -26,7 +26,7 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/mholt/caddy/diagnostics" "github.com/mholt/caddy/telemetry"
) )
// configGroup is a type that keys configs by their hostname // configGroup is a type that keys configs by their hostname
...@@ -102,7 +102,7 @@ func (cg configGroup) GetConfigForClient(clientHello *tls.ClientHelloInfo) (*tls ...@@ -102,7 +102,7 @@ func (cg configGroup) GetConfigForClient(clientHello *tls.ClientHelloInfo) (*tls
func (cfg *Config) GetCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) { func (cfg *Config) GetCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
// TODO: We need to collect this in a heavily de-duplicating way // TODO: We need to collect this in a heavily de-duplicating way
// It would also be nice to associate a handshake with the UA string (but that is only for HTTP server type) // It would also be nice to associate a handshake with the UA string (but that is only for HTTP server type)
// go diagnostics.Append("tls_client_hello", struct { // go telemetry.Append("tls_client_hello", struct {
// NoSNI bool `json:"no_sni,omitempty"` // NoSNI bool `json:"no_sni,omitempty"`
// CipherSuites []uint16 `json:"cipher_suites,omitempty"` // CipherSuites []uint16 `json:"cipher_suites,omitempty"`
// SupportedCurves []tls.CurveID `json:"curves,omitempty"` // SupportedCurves []tls.CurveID `json:"curves,omitempty"`
...@@ -121,9 +121,9 @@ func (cfg *Config) GetCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certif ...@@ -121,9 +121,9 @@ func (cfg *Config) GetCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certif
// }) // })
cert, err := cfg.getCertDuringHandshake(strings.ToLower(clientHello.ServerName), true, true) cert, err := cfg.getCertDuringHandshake(strings.ToLower(clientHello.ServerName), true, true)
if err == nil { if err == nil {
go diagnostics.Increment("tls_handshake_count") go telemetry.Increment("tls_handshake_count")
} else { } else {
go diagnostics.Append("tls_handshake_error", err.Error()) go telemetry.Append("tls_handshake_error", err.Error())
} }
return &cert.Certificate, err return &cert.Certificate, err
} }
......
...@@ -28,7 +28,7 @@ import ( ...@@ -28,7 +28,7 @@ import (
"strings" "strings"
"github.com/mholt/caddy" "github.com/mholt/caddy"
"github.com/mholt/caddy/diagnostics" "github.com/mholt/caddy/telemetry"
) )
func init() { func init() {
...@@ -175,11 +175,11 @@ func setupTLS(c *caddy.Controller) error { ...@@ -175,11 +175,11 @@ func setupTLS(c *caddy.Controller) error {
case "max_certs": case "max_certs":
c.Args(&maxCerts) c.Args(&maxCerts)
config.OnDemand = true config.OnDemand = true
diagnostics.Increment("tls_on_demand_count") telemetry.Increment("tls_on_demand_count")
case "ask": case "ask":
c.Args(&askURL) c.Args(&askURL)
config.OnDemand = true config.OnDemand = true
diagnostics.Increment("tls_on_demand_count") telemetry.Increment("tls_on_demand_count")
case "dns": case "dns":
args := c.RemainingArgs() args := c.RemainingArgs()
if len(args) != 1 { if len(args) != 1 {
...@@ -254,7 +254,7 @@ func setupTLS(c *caddy.Controller) error { ...@@ -254,7 +254,7 @@ func setupTLS(c *caddy.Controller) error {
return c.Errf("Unable to load certificate and key files for '%s': %v", c.Key, err) return c.Errf("Unable to load certificate and key files for '%s': %v", c.Key, err)
} }
log.Printf("[INFO] Successfully loaded TLS assets from %s and %s", certificateFile, keyFile) log.Printf("[INFO] Successfully loaded TLS assets from %s and %s", certificateFile, keyFile)
diagnostics.Increment("tls_manual_cert_count") telemetry.Increment("tls_manual_cert_count")
} }
// load a directory of certificates, if specified // load a directory of certificates, if specified
...@@ -274,7 +274,7 @@ func setupTLS(c *caddy.Controller) error { ...@@ -274,7 +274,7 @@ func setupTLS(c *caddy.Controller) error {
if err != nil { if err != nil {
return fmt.Errorf("self-signed: %v", err) return fmt.Errorf("self-signed: %v", err)
} }
diagnostics.Increment("tls_self_signed_count") telemetry.Increment("tls_self_signed_count")
} }
return nil return nil
...@@ -355,7 +355,7 @@ func loadCertsInDir(cfg *Config, c *caddy.Controller, dir string) error { ...@@ -355,7 +355,7 @@ func loadCertsInDir(cfg *Config, c *caddy.Controller, dir string) error {
return c.Errf("%s: failed to load cert and key for '%s': %v", path, c.Key, err) return c.Errf("%s: failed to load cert and key for '%s': %v", path, c.Key, err)
} }
log.Printf("[INFO] Successfully loaded TLS assets from %s", path) log.Printf("[INFO] Successfully loaded TLS assets from %s", path)
diagnostics.Increment("tls_manual_cert_count") telemetry.Increment("tls_manual_cert_count")
} }
return nil return nil
}) })
......
...@@ -20,7 +20,7 @@ import ( ...@@ -20,7 +20,7 @@ import (
"os/signal" "os/signal"
"sync" "sync"
"github.com/mholt/caddy/diagnostics" "github.com/mholt/caddy/telemetry"
) )
// TrapSignals create signal handlers for all applicable signals for this // TrapSignals create signal handlers for all applicable signals for this
...@@ -54,8 +54,8 @@ func trapSignalsCrossPlatform() { ...@@ -54,8 +54,8 @@ func trapSignalsCrossPlatform() {
log.Println("[INFO] SIGINT: Shutting down") log.Println("[INFO] SIGINT: Shutting down")
diagnostics.AppendUnique("sigtrap", "SIGINT") telemetry.AppendUnique("sigtrap", "SIGINT")
go diagnostics.StopEmitting() // not guaranteed to finish in time; that's OK (just don't block!) go telemetry.StopEmitting() // not guaranteed to finish in time; that's OK (just don't block!)
// important cleanup actions before shutdown callbacks // important cleanup actions before shutdown callbacks
for _, f := range OnProcessExit { for _, f := range OnProcessExit {
......
...@@ -22,7 +22,7 @@ import ( ...@@ -22,7 +22,7 @@ import (
"os/signal" "os/signal"
"syscall" "syscall"
"github.com/mholt/caddy/diagnostics" "github.com/mholt/caddy/telemetry"
) )
// trapSignalsPosix captures POSIX-only signals. // trapSignalsPosix captures POSIX-only signals.
...@@ -52,14 +52,14 @@ func trapSignalsPosix() { ...@@ -52,14 +52,14 @@ func trapSignalsPosix() {
exitCode = 3 exitCode = 3
} }
diagnostics.AppendUnique("sigtrap", "SIGTERM") telemetry.AppendUnique("sigtrap", "SIGTERM")
go diagnostics.StopEmitting() // won't finish in time, but that's OK - just don't block go telemetry.StopEmitting() // won't finish in time, but that's OK - just don't block
os.Exit(exitCode) os.Exit(exitCode)
case syscall.SIGUSR1: case syscall.SIGUSR1:
log.Println("[INFO] SIGUSR1: Reloading") log.Println("[INFO] SIGUSR1: Reloading")
go diagnostics.AppendUnique("sigtrap", "SIGUSR1") go telemetry.AppendUnique("sigtrap", "SIGUSR1")
// Start with the existing Caddyfile // Start with the existing Caddyfile
caddyfileToUse, inst, err := getCurrentCaddyfile() caddyfileToUse, inst, err := getCurrentCaddyfile()
...@@ -91,14 +91,14 @@ func trapSignalsPosix() { ...@@ -91,14 +91,14 @@ func trapSignalsPosix() {
case syscall.SIGUSR2: case syscall.SIGUSR2:
log.Println("[INFO] SIGUSR2: Upgrading") log.Println("[INFO] SIGUSR2: Upgrading")
go diagnostics.AppendUnique("sigtrap", "SIGUSR2") go telemetry.AppendUnique("sigtrap", "SIGUSR2")
if err := Upgrade(); err != nil { if err := Upgrade(); err != nil {
log.Printf("[ERROR] SIGUSR2: upgrading: %v", err) log.Printf("[ERROR] SIGUSR2: upgrading: %v", err)
} }
case syscall.SIGHUP: case syscall.SIGHUP:
// ignore; this signal is sometimes sent outside of the user's control // ignore; this signal is sometimes sent outside of the user's control
go diagnostics.AppendUnique("sigtrap", "SIGHUP") go telemetry.AppendUnique("sigtrap", "SIGHUP")
} }
} }
}() }()
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package diagnostics package telemetry
import ( import (
"log" "log"
...@@ -139,7 +139,7 @@ func Append(key string, value interface{}) { ...@@ -139,7 +139,7 @@ func Append(key string, value interface{}) {
sliceVal, sliceOk := bufVal.([]interface{}) sliceVal, sliceOk := bufVal.([]interface{})
if inBuffer && !sliceOk { if inBuffer && !sliceOk {
bufferMu.Unlock() bufferMu.Unlock()
log.Printf("[PANIC] Diagnostics: key %s already used for non-slice value", key) log.Printf("[PANIC] Telemetry: key %s already used for non-slice value", key)
return return
} }
if sliceVal == nil { if sliceVal == nil {
...@@ -169,7 +169,7 @@ func AppendUnique(key string, value interface{}) { ...@@ -169,7 +169,7 @@ func AppendUnique(key string, value interface{}) {
setVal, setOk := bufVal.(countingSet) setVal, setOk := bufVal.(countingSet)
if inBuffer && !setOk { if inBuffer && !setOk {
bufferMu.Unlock() bufferMu.Unlock()
log.Printf("[PANIC] Diagnostics: key %s already used for non-counting-set value", key) log.Printf("[PANIC] Telemetry: key %s already used for non-counting-set value", key)
return return
} }
if setVal == nil { if setVal == nil {
...@@ -212,7 +212,7 @@ func atomicAdd(key string, amount int) { ...@@ -212,7 +212,7 @@ func atomicAdd(key string, amount int) {
intVal, intOk := bufVal.(int) intVal, intOk := bufVal.(int)
if inBuffer && !intOk { if inBuffer && !intOk {
bufferMu.Unlock() bufferMu.Unlock()
log.Printf("[PANIC] Diagnostics: key %s already used for non-integer value", key) log.Printf("[PANIC] Telemetry: key %s already used for non-integer value", key)
return return
} }
if !inBuffer { if !inBuffer {
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package diagnostics package telemetry
import ( import (
"fmt" "fmt"
......
...@@ -12,26 +12,25 @@ ...@@ -12,26 +12,25 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// Package diagnostics implements the client for server-side diagnostics // Package telemetry implements the client for server-side telemetry
// of the network. Functions in this package are synchronous and blocking // of the network. Functions in this package are synchronous and blocking
// unless otherwise specified. For convenience, most functions here do // unless otherwise specified. For convenience, most functions here do
// not return errors, but errors are logged to the standard logger. // not return errors, but errors are logged to the standard logger.
// //
// To use this package, first call Init(). You can then call any of the // To use this package, first call Init(). You can then call any of the
// collection/aggregation functions. Call StartEmitting() when you are // collection/aggregation functions. Call StartEmitting() when you are
// ready to begin sending diagnostic updates. // ready to begin sending telemetry updates.
// //
// When collecting metrics (functions like Set, AppendUnique, or Increment), // When collecting metrics (functions like Set, AppendUnique, or Increment),
// it may be desirable and even recommended to invoke them in a new // it may be desirable and even recommended to invoke them in a new
// goroutine (use the go keyword) in case there is lock contention; // goroutine in case there is lock contention; they are thread-safe (unless
// they are thread-safe (unless noted), and you may not want them to // noted), and you may not want them to block the main thread of execution.
// block the main thread of execution. However, sometimes blocking // However, sometimes blocking may be necessary too; for example, adding
// may be necessary too; for example, adding startup metrics to the // startup metrics to the buffer before the call to StartEmitting().
// buffer before the call to StartEmitting().
// //
// This package is designed to be as fast and space-efficient as reasonably // This package is designed to be as fast and space-efficient as reasonably
// possible, so that it does not disrupt the flow of execution. // possible, so that it does not disrupt the flow of execution.
package diagnostics package telemetry
import ( import (
"bytes" "bytes"
...@@ -53,17 +52,17 @@ import ( ...@@ -53,17 +52,17 @@ import (
func logEmit(final bool) { func logEmit(final bool) {
err := emit(final) err := emit(final)
if err != nil { if err != nil {
log.Printf("[ERROR] Sending diagnostics: %v", err) log.Printf("[ERROR] Sending telemetry: %v", err)
} }
} }
// emit sends an update to the diagnostics server. // emit sends an update to the telemetry server.
// Set final to true if this is the last call to emit. // Set final to true if this is the last call to emit.
// If final is true, no future updates will be scheduled. // If final is true, no future updates will be scheduled.
// Otherwise, the next update will be scheduled. // Otherwise, the next update will be scheduled.
func emit(final bool) error { func emit(final bool) error {
if !enabled { if !enabled {
return fmt.Errorf("diagnostics not enabled") return fmt.Errorf("telemetry not enabled")
} }
// ensure only one update happens at a time; // ensure only one update happens at a time;
...@@ -71,7 +70,7 @@ func emit(final bool) error { ...@@ -71,7 +70,7 @@ func emit(final bool) error {
updateMu.Lock() updateMu.Lock()
if updating { if updating {
updateMu.Unlock() updateMu.Unlock()
log.Println("[NOTICE] Skipping this diagnostics update because previous one is still working") log.Println("[NOTICE] Skipping this telemetry update because previous one is still working")
return nil return nil
} }
updating = true updating = true
...@@ -100,7 +99,7 @@ func emit(final bool) error { ...@@ -100,7 +99,7 @@ func emit(final bool) error {
if i > 0 && err != nil { if i > 0 && err != nil {
// don't hammer the server; first failure might have been // don't hammer the server; first failure might have been
// a fluke, but back off more after that // a fluke, but back off more after that
log.Printf("[WARNING] Sending diagnostics (attempt %d): %v - backing off and retrying", i, err) log.Printf("[WARNING] Sending telemetry (attempt %d): %v - backing off and retrying", i, err)
time.Sleep(time.Duration((i+1)*(i+1)*(i+1)) * time.Second) time.Sleep(time.Duration((i+1)*(i+1)*(i+1)) * time.Second)
} }
...@@ -114,7 +113,7 @@ func emit(final bool) error { ...@@ -114,7 +113,7 @@ func emit(final bool) error {
// check for any special-case response codes // check for any special-case response codes
if resp.StatusCode == http.StatusGone { if resp.StatusCode == http.StatusGone {
// the endpoint has been deprecated and is no longer servicing clients // the endpoint has been deprecated and is no longer servicing clients
err = fmt.Errorf("diagnostics server replied with HTTP %d; upgrade required", resp.StatusCode) err = fmt.Errorf("telemetry server replied with HTTP %d; upgrade required", resp.StatusCode)
if clen := resp.Header.Get("Content-Length"); clen != "0" && clen != "" { if clen := resp.Header.Get("Content-Length"); clen != "0" && clen != "" {
bodyBytes, readErr := ioutil.ReadAll(resp.Body) bodyBytes, readErr := ioutil.ReadAll(resp.Body)
if readErr != nil { if readErr != nil {
...@@ -128,7 +127,7 @@ func emit(final bool) error { ...@@ -128,7 +127,7 @@ func emit(final bool) error {
} }
if resp.StatusCode == http.StatusUnavailableForLegalReasons { if resp.StatusCode == http.StatusUnavailableForLegalReasons {
// the endpoint is unavailable, at least to this client, for legal reasons (!) // the endpoint is unavailable, at least to this client, for legal reasons (!)
err = fmt.Errorf("diagnostics server replied with HTTP %d %s: please consult the project website and developers for guidance", resp.StatusCode, resp.Status) err = fmt.Errorf("telemetry server replied with HTTP %d %s: please consult the project website and developers for guidance", resp.StatusCode, resp.Status)
if clen := resp.Header.Get("Content-Length"); clen != "0" && clen != "" { if clen := resp.Header.Get("Content-Length"); clen != "0" && clen != "" {
bodyBytes, readErr := ioutil.ReadAll(resp.Body) bodyBytes, readErr := ioutil.ReadAll(resp.Body)
if readErr != nil { if readErr != nil {
...@@ -144,7 +143,7 @@ func emit(final bool) error { ...@@ -144,7 +143,7 @@ func emit(final bool) error {
// okay, ensure we can interpret the response // okay, ensure we can interpret the response
if ct := resp.Header.Get("Content-Type"); (resp.StatusCode < 300 || resp.StatusCode >= 400) && if ct := resp.Header.Get("Content-Type"); (resp.StatusCode < 300 || resp.StatusCode >= 400) &&
!strings.Contains(ct, "json") { !strings.Contains(ct, "json") {
err = fmt.Errorf("diagnostics server replied with unknown content-type: '%s' and HTTP %s", ct, resp.Status) err = fmt.Errorf("telemetry server replied with unknown content-type: '%s' and HTTP %s", ct, resp.Status)
resp.Body.Close() resp.Body.Close()
continue continue
} }
...@@ -167,12 +166,12 @@ func emit(final bool) error { ...@@ -167,12 +166,12 @@ func emit(final bool) error {
} }
} }
if !final { if !final {
log.Printf("[NOTICE] Sending diagnostics: we were too early; waiting %s before trying again", reply.NextUpdate) log.Printf("[NOTICE] Sending telemetry: we were too early; waiting %s before trying again", reply.NextUpdate)
time.Sleep(reply.NextUpdate) time.Sleep(reply.NextUpdate)
continue continue
} }
} else if resp.StatusCode >= 400 { } else if resp.StatusCode >= 400 {
err = fmt.Errorf("diagnostics server returned status code %d", resp.StatusCode) err = fmt.Errorf("telemetry server returned status code %d", resp.StatusCode)
continue continue
} }
...@@ -181,14 +180,14 @@ func emit(final bool) error { ...@@ -181,14 +180,14 @@ func emit(final bool) error {
if err == nil && !final { if err == nil && !final {
// (remember, if there was an error, we return it // (remember, if there was an error, we return it
// below, so it WILL get logged if it's supposed to) // below, so it WILL get logged if it's supposed to)
log.Println("[INFO] Sending diagnostics: success") log.Println("[INFO] Sending telemetry: success")
} }
// even if there was an error after all retries, we should // even if there was an error after all retries, we should
// schedule the next update using our default update // schedule the next update using our default update
// interval because the server might be healthy later // interval because the server might be healthy later
// ensure we won't slam the diagnostics server // ensure we won't slam the telemetry server
if reply.NextUpdate < 1*time.Second { if reply.NextUpdate < 1*time.Second {
reply.NextUpdate = defaultUpdateInterval reply.NextUpdate = defaultUpdateInterval
} }
...@@ -247,13 +246,13 @@ func resetBuffer() map[string]interface{} { ...@@ -247,13 +246,13 @@ func resetBuffer() map[string]interface{} {
} }
// Response contains the body of a response from the // Response contains the body of a response from the
// diagnostics server. // telemetry server.
type Response struct { type Response struct {
// NextUpdate is how long to wait before the next update. // NextUpdate is how long to wait before the next update.
NextUpdate time.Duration `json:"next_update"` NextUpdate time.Duration `json:"next_update"`
// Stop instructs the diagnostics server to stop sending // Stop instructs the telemetry server to stop sending
// diagnostics. This would only be done under extenuating // telemetry. This would only be done under extenuating
// circumstances, but we are prepared for it nonetheless. // circumstances, but we are prepared for it nonetheless.
Stop bool `json:"stop,omitempty"` Stop bool `json:"stop,omitempty"`
...@@ -262,7 +261,7 @@ type Response struct { ...@@ -262,7 +261,7 @@ type Response struct {
Error string `json:"error,omitempty"` Error string `json:"error,omitempty"`
} }
// Payload is the data that gets sent to the diagnostics server. // Payload is the data that gets sent to the telemetry server.
type Payload struct { type Payload struct {
// The universally unique ID of the instance // The universally unique ID of the instance
InstanceID string `json:"instance_id"` InstanceID string `json:"instance_id"`
...@@ -337,7 +336,7 @@ var ( ...@@ -337,7 +336,7 @@ var (
updateTimerMu sync.Mutex updateTimerMu sync.Mutex
// instanceUUID is the ID of the current instance. // instanceUUID is the ID of the current instance.
// This MUST be set to emit diagnostics. // This MUST be set to emit telemetry.
// This MUST NOT be openly exposed to clients, for privacy. // This MUST NOT be openly exposed to clients, for privacy.
instanceUUID uuid.UUID instanceUUID uuid.UUID
...@@ -352,12 +351,12 @@ var ( ...@@ -352,12 +351,12 @@ var (
) )
const ( const (
// endpoint is the base URL to remote diagnostics server; // endpoint is the base URL to remote telemetry server;
// the instance ID will be appended to it. // the instance ID will be appended to it.
endpoint = "https://diagnostics-staging.caddyserver.com/update/" // TODO: make configurable, "http://localhost:8085/update/" endpoint = "https://telemetry-staging.caddyserver.com/v1/update/"
// defaultUpdateInterval is how long to wait before emitting // defaultUpdateInterval is how long to wait before emitting
// more diagnostic data if all retires fail. This value is // more telemetry data if all retires fail. This value is
// only used if the client receives a nonsensical value, or // only used if the client receives a nonsensical value, or
// doesn't send one at all, or if a connection can't be made, // doesn't send one at all, or if a connection can't be made,
// likely indicating a problem with the server. Thus, this // likely indicating a problem with the server. Thus, this
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package diagnostics package telemetry
import ( import (
"encoding/json" "encoding/json"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment