*: add structured logging
This commit is contained in:
parent
353ba01e51
commit
cb55019ab8
6 changed files with 81 additions and 11 deletions
|
@ -6,6 +6,8 @@ package bittorrent
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
log "github.com/Sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PeerID represents a peer ID.
|
// PeerID represents a peer ID.
|
||||||
|
@ -24,6 +26,10 @@ func PeerIDFromBytes(b []byte) PeerID {
|
||||||
return PeerID(buf)
|
return PeerID(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p PeerID) String() string {
|
||||||
|
return string(p[:])
|
||||||
|
}
|
||||||
|
|
||||||
// PeerIDFromString creates a PeerID from a string.
|
// PeerIDFromString creates a PeerID from a string.
|
||||||
//
|
//
|
||||||
// It panics if s is not 20 bytes long.
|
// It panics if s is not 20 bytes long.
|
||||||
|
@ -66,6 +72,10 @@ func InfoHashFromString(s string) InfoHash {
|
||||||
return InfoHash(buf)
|
return InfoHash(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i InfoHash) String() string {
|
||||||
|
return string(i[:])
|
||||||
|
}
|
||||||
|
|
||||||
// AnnounceRequest represents the parsed parameters from an announce request.
|
// AnnounceRequest represents the parsed parameters from an announce request.
|
||||||
type AnnounceRequest struct {
|
type AnnounceRequest struct {
|
||||||
Event Event
|
Event Event
|
||||||
|
@ -92,6 +102,18 @@ type AnnounceResponse struct {
|
||||||
IPv6Peers []Peer
|
IPv6Peers []Peer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LogFields renders the current response as a set of Logrus fields.
|
||||||
|
func (ar AnnounceResponse) LogFields() log.Fields {
|
||||||
|
return log.Fields{
|
||||||
|
"compact": ar.Compact,
|
||||||
|
"complete": ar.Complete,
|
||||||
|
"interval": ar.Interval,
|
||||||
|
"minInterval": ar.MinInterval,
|
||||||
|
"ipv4Peers": ar.IPv4Peers,
|
||||||
|
"ipv6Peers": ar.IPv6Peers,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ScrapeRequest represents the parsed parameters from a scrape request.
|
// ScrapeRequest represents the parsed parameters from a scrape request.
|
||||||
type ScrapeRequest struct {
|
type ScrapeRequest struct {
|
||||||
AddressFamily AddressFamily
|
AddressFamily AddressFamily
|
||||||
|
@ -107,6 +129,13 @@ type ScrapeResponse struct {
|
||||||
Files []Scrape
|
Files []Scrape
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LogFields renders the current response as a set of Logrus fields.
|
||||||
|
func (sr ScrapeResponse) LogFields() log.Fields {
|
||||||
|
return log.Fields{
|
||||||
|
"files": sr.Files,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Scrape represents the state of a swarm that is returned in a scrape response.
|
// Scrape represents the state of a swarm that is returned in a scrape response.
|
||||||
type Scrape struct {
|
type Scrape struct {
|
||||||
InfoHash InfoHash
|
InfoHash InfoHash
|
||||||
|
|
|
@ -45,17 +45,15 @@ func (r *Run) Start(ps storage.PeerStore) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("failed to read config: " + err.Error())
|
return errors.New("failed to read config: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg := configFile.Chihaya
|
cfg := configFile.Chihaya
|
||||||
preHooks, postHooks, err := cfg.CreateHooks()
|
|
||||||
if err != nil {
|
|
||||||
return errors.New("failed to validate hook config: " + err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
r.sg = stop.NewGroup()
|
r.sg = stop.NewGroup()
|
||||||
|
|
||||||
|
log.WithFields(log.Fields{"addr": cfg.PrometheusAddr}).Info("starting Prometheus server")
|
||||||
r.sg.Add(prometheus.NewServer(cfg.PrometheusAddr))
|
r.sg.Add(prometheus.NewServer(cfg.PrometheusAddr))
|
||||||
|
|
||||||
if ps == nil {
|
if ps == nil {
|
||||||
|
log.WithFields(cfg.Storage.LogFields()).Info("starting storage")
|
||||||
ps, err = memory.New(cfg.Storage)
|
ps, err = memory.New(cfg.Storage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("failed to create memory storage: " + err.Error())
|
return errors.New("failed to create memory storage: " + err.Error())
|
||||||
|
@ -63,9 +61,18 @@ func (r *Run) Start(ps storage.PeerStore) error {
|
||||||
}
|
}
|
||||||
r.peerStore = ps
|
r.peerStore = ps
|
||||||
|
|
||||||
|
preHooks, postHooks, err := cfg.CreateHooks()
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("failed to validate hook config: " + err.Error())
|
||||||
|
}
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"preHooks": preHooks,
|
||||||
|
"postHooks": postHooks,
|
||||||
|
}).Info("starting middleware")
|
||||||
r.logic = middleware.NewLogic(cfg.Config, r.peerStore, preHooks, postHooks)
|
r.logic = middleware.NewLogic(cfg.Config, r.peerStore, preHooks, postHooks)
|
||||||
|
|
||||||
if cfg.HTTPConfig.Addr != "" {
|
if cfg.HTTPConfig.Addr != "" {
|
||||||
|
log.WithFields(cfg.HTTPConfig.LogFields()).Info("starting HTTP frontend")
|
||||||
httpfe, err := http.NewFrontend(r.logic, cfg.HTTPConfig)
|
httpfe, err := http.NewFrontend(r.logic, cfg.HTTPConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -74,6 +81,7 @@ func (r *Run) Start(ps storage.PeerStore) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.UDPConfig.Addr != "" {
|
if cfg.UDPConfig.Addr != "" {
|
||||||
|
log.WithFields(cfg.UDPConfig.LogFields()).Info("starting UDP frontend")
|
||||||
udpfe, err := udp.NewFrontend(r.logic, cfg.UDPConfig)
|
udpfe, err := udp.NewFrontend(r.logic, cfg.UDPConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -121,7 +129,7 @@ func (r *Run) Stop(keepPeerStore bool) (storage.PeerStore, error) {
|
||||||
func RunCmdFunc(cmd *cobra.Command, args []string) error {
|
func RunCmdFunc(cmd *cobra.Command, args []string) error {
|
||||||
cpuProfilePath, _ := cmd.Flags().GetString("cpuprofile")
|
cpuProfilePath, _ := cmd.Flags().GetString("cpuprofile")
|
||||||
if cpuProfilePath != "" {
|
if cpuProfilePath != "" {
|
||||||
log.Infoln("enabled CPU profiling to", cpuProfilePath)
|
log.WithFields(log.Fields{"path": cpuProfilePath}).Info("enabling CPU profiling")
|
||||||
f, err := os.Create(cpuProfilePath)
|
f, err := os.Create(cpuProfilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -149,7 +157,7 @@ func RunCmdFunc(cmd *cobra.Command, args []string) error {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-reload:
|
case <-reload:
|
||||||
log.Info("received SIGUSR1")
|
log.Info("reloading; received SIGUSR1")
|
||||||
peerStore, err := r.Stop(true)
|
peerStore, err := r.Stop(true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -159,7 +167,7 @@ func RunCmdFunc(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case <-quit:
|
case <-quit:
|
||||||
log.Info("received SIGINT/SIGTERM")
|
log.Info("shutting down; received SIGINT/SIGTERM")
|
||||||
if _, err := r.Stop(false); err != nil {
|
if _, err := r.Stop(false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -177,8 +185,8 @@ func main() {
|
||||||
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
||||||
debugLog, _ := cmd.Flags().GetBool("debug")
|
debugLog, _ := cmd.Flags().GetBool("debug")
|
||||||
if debugLog {
|
if debugLog {
|
||||||
|
log.Info("enabling debug logging")
|
||||||
log.SetLevel(log.DebugLevel)
|
log.SetLevel(log.DebugLevel)
|
||||||
log.Debugln("debug logging enabled")
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
RunE: RunCmdFunc,
|
RunE: RunCmdFunc,
|
||||||
|
|
|
@ -71,6 +71,19 @@ type Config struct {
|
||||||
TLSKeyPath string `yaml:"tls_key_path"`
|
TLSKeyPath string `yaml:"tls_key_path"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LogFields renders the current config as a set of Logrus fields.
|
||||||
|
func (cfg Config) LogFields() log.Fields {
|
||||||
|
return log.Fields{
|
||||||
|
"addr": cfg.Addr,
|
||||||
|
"readTimeout": cfg.ReadTimeout,
|
||||||
|
"writeTimeout": cfg.WriteTimeout,
|
||||||
|
"allowIPSpoofing": cfg.AllowIPSpoofing,
|
||||||
|
"realIPHeader": cfg.RealIPHeader,
|
||||||
|
"tlsCertPath": cfg.TLSCertPath,
|
||||||
|
"tlsKeyPath": cfg.TLSKeyPath,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Frontend represents the state of an HTTP BitTorrent Frontend.
|
// Frontend represents the state of an HTTP BitTorrent Frontend.
|
||||||
type Frontend struct {
|
type Frontend struct {
|
||||||
srv *http.Server
|
srv *http.Server
|
||||||
|
|
|
@ -73,6 +73,16 @@ type Config struct {
|
||||||
AllowIPSpoofing bool `yaml:"allow_ip_spoofing"`
|
AllowIPSpoofing bool `yaml:"allow_ip_spoofing"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LogFields renders the current config as a set of Logrus fields.
|
||||||
|
func (cfg Config) LogFields() log.Fields {
|
||||||
|
return log.Fields{
|
||||||
|
"addr": cfg.Addr,
|
||||||
|
"privateKey": cfg.PrivateKey,
|
||||||
|
"maxClockSkew": cfg.MaxClockSkew,
|
||||||
|
"allowIPSpoofing": cfg.AllowIPSpoofing,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Frontend holds the state of a UDP BitTorrent Frontend.
|
// Frontend holds the state of a UDP BitTorrent Frontend.
|
||||||
type Frontend struct {
|
type Frontend struct {
|
||||||
socket *net.UDPConn
|
socket *net.UDPConn
|
||||||
|
@ -144,7 +154,6 @@ func (t *Frontend) listenAndServe() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("listening on udp socket")
|
|
||||||
t.socket, err = net.ListenUDP("udp", udpAddr)
|
t.socket, err = net.ListenUDP("udp", udpAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -159,7 +168,7 @@ func (t *Frontend) listenAndServe() error {
|
||||||
// Check to see if we need to shutdown.
|
// Check to see if we need to shutdown.
|
||||||
select {
|
select {
|
||||||
case <-t.closing:
|
case <-t.closing:
|
||||||
log.Debugf("returning from udp listen&serve")
|
log.Debug("udp listenAndServe() received shutdown signal")
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,7 @@ func (l *Logic) HandleAnnounce(ctx context.Context, req *bittorrent.AnnounceRequ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.WithFields(resp.LogFields()).Debug("generated announce response")
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +88,7 @@ func (l *Logic) HandleScrape(ctx context.Context, req *bittorrent.ScrapeRequest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.WithFields(resp.LogFields()).Debug("generated scrape response")
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,15 @@ type Config struct {
|
||||||
ShardCount int `yaml:"shard_count"`
|
ShardCount int `yaml:"shard_count"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LogFields renders the current config as a set of Logrus fields.
|
||||||
|
func (cfg Config) LogFields() log.Fields {
|
||||||
|
return log.Fields{
|
||||||
|
"gcInterval": cfg.GarbageCollectionInterval,
|
||||||
|
"peerLifetime": cfg.PeerLifetime,
|
||||||
|
"shardCount": cfg.ShardCount,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// New creates a new PeerStore backed by memory.
|
// New creates a new PeerStore backed by memory.
|
||||||
func New(cfg Config) (storage.PeerStore, error) {
|
func New(cfg Config) (storage.PeerStore, error) {
|
||||||
shardCount := 1
|
shardCount := 1
|
||||||
|
|
Loading…
Add table
Reference in a new issue