Browse Source

Make query logging (globally) configurable

Ask Bjørn Hansen 9 years ago
parent
commit
7b5172f982
7 changed files with 36 additions and 220 deletions
  1. 5 2
      README.md
  2. 5 2
      config.go
  3. 8 0
      dns/geodns.conf.sample
  4. 13 1
      geodns.go
  5. 3 4
      querylog/querylog.go
  6. 0 207
      querylog/querylog_easyjson.go
  7. 2 4
      server.go

+ 5 - 2
README.md

@@ -144,10 +144,13 @@ with `max_hosts` 2 then .4 will be returned about 4 times more often than .1.
 ## Configuration file
 ## Configuration file
 
 
 The geodns.conf file allows you to specify a specific directory for the GeoIP
 The geodns.conf file allows you to specify a specific directory for the GeoIP
-data files and enable posting metrics to StatHat. See the `geodns.conf.sample`
-file for example configuration.
+data files and other options. See the `geodns.conf.sample` file for example
+configuration.
+
+The global configuration file is not reloaded at runtime.
 
 
 Most of the configuration is "per zone" and done in the zone .json files.
 Most of the configuration is "per zone" and done in the zone .json files.
+The zone configuration files are automatically reloaded when they change.
 
 
 ## Zone format
 ## Zone format
 
 

+ 5 - 2
config.go

@@ -25,6 +25,11 @@ type AppConfig struct {
 		User     string
 		User     string
 		Password string
 		Password string
 	}
 	}
+	QueryLog struct {
+		Path    string
+		MaxSize int
+		Keep    int
+	}
 }
 }
 
 
 var Config = new(AppConfig)
 var Config = new(AppConfig)
@@ -50,8 +55,6 @@ func (conf *AppConfig) GeoIPDirectory() string {
 
 
 func configWatcher(fileName string) {
 func configWatcher(fileName string) {
 
 
-	configReader(fileName)
-
 	watcher, err := fsnotify.NewWatcher()
 	watcher, err := fsnotify.NewWatcher()
 	if err != nil {
 	if err != nil {
 		fmt.Println(err)
 		fmt.Println(err)

+ 8 - 0
dns/geodns.conf.sample

@@ -7,6 +7,14 @@
 ;; Directory containing the GeoIP .dat database files
 ;; Directory containing the GeoIP .dat database files
 ;directory=/usr/local/share/GeoIP/
 ;directory=/usr/local/share/GeoIP/
 
 
+[querylog]
+;; directory to save query logs; disabled if not specified
+path = log/queries.log
+;; max size per file in megabytes before rotating (default 200)
+; maxsize = 100
+;; keep up to this many rotated log files (default 1)
+; keep = 2
+
 [stathat]
 [stathat]
 ;; Add an API key to send query counts and other metrics to stathat
 ;; Add an API key to send query counts and other metrics to stathat
 ;apikey=abc123
 ;apikey=abc123

+ 13 - 1
geodns.go

@@ -29,6 +29,7 @@ import (
 	"strings"
 	"strings"
 	"time"
 	"time"
 
 
+	"github.com/abh/geodns/querylog"
 	"github.com/pborman/uuid"
 	"github.com/pborman/uuid"
 )
 )
 
 
@@ -95,7 +96,6 @@ func main() {
 	}
 	}
 
 
 	srv := Server{}
 	srv := Server{}
-	srv.SetQueryLogger("log/queries.log")
 
 
 	if len(*flagLogFile) > 0 {
 	if len(*flagLogFile) > 0 {
 		logToFileOpen(*flagLogFile)
 		logToFileOpen(*flagLogFile)
@@ -155,11 +155,23 @@ func main() {
 		}()
 		}()
 	}
 	}
 
 
+	// load geodns.conf config
+	configReader(configFileName)
+
+	// load (and re-load) zone data
 	go configWatcher(configFileName)
 	go configWatcher(configFileName)
 
 
 	metrics := NewMetrics()
 	metrics := NewMetrics()
 	go metrics.Updater()
 	go metrics.Updater()
 
 
+	if qlc := Config.QueryLog; len(qlc.Path) > 0 {
+		ql, err := querylog.NewFileLogger(qlc.Path, qlc.MaxSize, qlc.Keep)
+		if err != nil {
+			log.Fatalf("Could not start file query logger: %s", err)
+		}
+		srv.SetQueryLogger(ql)
+	}
+
 	if *flaginter == "*" {
 	if *flaginter == "*" {
 		addrs, _ := net.InterfaceAddrs()
 		addrs, _ := net.InterfaceAddrs()
 		ips := make([]string, 0)
 		ips := make([]string, 0)

+ 3 - 4
querylog/querylog.go

@@ -29,13 +29,12 @@ type FileLogger struct {
 	logger lumberjack.Logger
 	logger lumberjack.Logger
 }
 }
 
 
-func NewFileLogger(filename string) (*FileLogger, error) {
+func NewFileLogger(filename string, maxsize int, keep int) (*FileLogger, error) {
 	fl := &FileLogger{}
 	fl := &FileLogger{}
 	fl.logger = lumberjack.Logger{
 	fl.logger = lumberjack.Logger{
 		Filename:   filename,
 		Filename:   filename,
-		MaxSize:    500, // megabytes
-		MaxBackups: 3,
-		MaxAge:     28, //days
+		MaxSize:    maxsize, // megabytes
+		MaxBackups: keep,
 	}
 	}
 	return fl, nil
 	return fl, nil
 }
 }

+ 0 - 207
querylog/querylog_easyjson.go

@@ -1,207 +0,0 @@
-// AUTOGENERATED FILE: easyjson marshaller/unmarshallers.
-
-package querylog
-
-import (
-	json "encoding/json"
-	jlexer "github.com/mailru/easyjson/jlexer"
-	jwriter "github.com/mailru/easyjson/jwriter"
-)
-
-var _ = json.RawMessage{} // suppress unused package warning
-
-func easyjson_320612c2_decode_github_com_abh_geodns_querylog_FileLogger(in *jlexer.Lexer, out *FileLogger) {
-	if in.IsNull() {
-		in.Skip()
-		return
-	}
-	in.Delim('{')
-	for !in.IsDelim('}') {
-		key := in.UnsafeString()
-		in.WantColon()
-		if in.IsNull() {
-			in.Skip()
-			in.WantComma()
-			continue
-		}
-		switch key {
-		default:
-			in.SkipRecursive()
-		}
-		in.WantComma()
-	}
-	in.Delim('}')
-}
-func easyjson_320612c2_encode_github_com_abh_geodns_querylog_FileLogger(out *jwriter.Writer, in FileLogger) {
-	out.RawByte('{')
-	first := true
-	_ = first
-	out.RawByte('}')
-}
-func (v FileLogger) MarshalJSON() ([]byte, error) {
-	w := jwriter.Writer{}
-	easyjson_320612c2_encode_github_com_abh_geodns_querylog_FileLogger(&w, v)
-	return w.Buffer.BuildBytes(), w.Error
-}
-func (v FileLogger) MarshalEasyJSON(w *jwriter.Writer) {
-	easyjson_320612c2_encode_github_com_abh_geodns_querylog_FileLogger(w, v)
-}
-func (v *FileLogger) UnmarshalJSON(data []byte) error {
-	r := jlexer.Lexer{Data: data}
-	easyjson_320612c2_decode_github_com_abh_geodns_querylog_FileLogger(&r, v)
-	return r.Error()
-}
-func (v *FileLogger) UnmarshalEasyJSON(l *jlexer.Lexer) {
-	easyjson_320612c2_decode_github_com_abh_geodns_querylog_FileLogger(l, v)
-}
-func easyjson_320612c2_decode_github_com_abh_geodns_querylog_Entry(in *jlexer.Lexer, out *Entry) {
-	if in.IsNull() {
-		in.Skip()
-		return
-	}
-	in.Delim('{')
-	for !in.IsDelim('}') {
-		key := in.UnsafeString()
-		in.WantColon()
-		if in.IsNull() {
-			in.Skip()
-			in.WantComma()
-			continue
-		}
-		switch key {
-		case "Time":
-			out.Time = int64(in.Int64())
-		case "Origin":
-			out.Origin = string(in.String())
-		case "Name":
-			out.Name = string(in.String())
-		case "Qtype":
-			out.Qtype = uint16(in.Uint16())
-		case "Rcode":
-			out.Rcode = int(in.Int())
-		case "Answers":
-			out.Answers = int(in.Int())
-		case "Targets":
-			in.Delim('[')
-			if !in.IsDelim(']') {
-				out.Targets = make([]string, 0, 4)
-			} else {
-				out.Targets = nil
-			}
-			for !in.IsDelim(']') {
-				var v1 string
-				v1 = string(in.String())
-				out.Targets = append(out.Targets, v1)
-				in.WantComma()
-			}
-			in.Delim(']')
-		case "LabelName":
-			out.LabelName = string(in.String())
-		case "RemoteAddr":
-			out.RemoteAddr = string(in.String())
-		case "ClientAddr":
-			out.ClientAddr = string(in.String())
-		case "HasECS":
-			out.HasECS = bool(in.Bool())
-		default:
-			in.SkipRecursive()
-		}
-		in.WantComma()
-	}
-	in.Delim('}')
-}
-func easyjson_320612c2_encode_github_com_abh_geodns_querylog_Entry(out *jwriter.Writer, in Entry) {
-	out.RawByte('{')
-	first := true
-	_ = first
-	if !first {
-		out.RawByte(',')
-	}
-	first = false
-	out.RawString("\"Time\":")
-	out.Int64(int64(in.Time))
-	if !first {
-		out.RawByte(',')
-	}
-	first = false
-	out.RawString("\"Origin\":")
-	out.String(string(in.Origin))
-	if !first {
-		out.RawByte(',')
-	}
-	first = false
-	out.RawString("\"Name\":")
-	out.String(string(in.Name))
-	if !first {
-		out.RawByte(',')
-	}
-	first = false
-	out.RawString("\"Qtype\":")
-	out.Uint16(uint16(in.Qtype))
-	if !first {
-		out.RawByte(',')
-	}
-	first = false
-	out.RawString("\"Rcode\":")
-	out.Int(int(in.Rcode))
-	if !first {
-		out.RawByte(',')
-	}
-	first = false
-	out.RawString("\"Answers\":")
-	out.Int(int(in.Answers))
-	if !first {
-		out.RawByte(',')
-	}
-	first = false
-	out.RawString("\"Targets\":")
-	out.RawByte('[')
-	for v2, v3 := range in.Targets {
-		if v2 > 0 {
-			out.RawByte(',')
-		}
-		out.String(string(v3))
-	}
-	out.RawByte(']')
-	if !first {
-		out.RawByte(',')
-	}
-	first = false
-	out.RawString("\"LabelName\":")
-	out.String(string(in.LabelName))
-	if !first {
-		out.RawByte(',')
-	}
-	first = false
-	out.RawString("\"RemoteAddr\":")
-	out.String(string(in.RemoteAddr))
-	if !first {
-		out.RawByte(',')
-	}
-	first = false
-	out.RawString("\"ClientAddr\":")
-	out.String(string(in.ClientAddr))
-	if !first {
-		out.RawByte(',')
-	}
-	first = false
-	out.RawString("\"HasECS\":")
-	out.Bool(bool(in.HasECS))
-	out.RawByte('}')
-}
-func (v Entry) MarshalJSON() ([]byte, error) {
-	w := jwriter.Writer{}
-	easyjson_320612c2_encode_github_com_abh_geodns_querylog_Entry(&w, v)
-	return w.Buffer.BuildBytes(), w.Error
-}
-func (v Entry) MarshalEasyJSON(w *jwriter.Writer) {
-	easyjson_320612c2_encode_github_com_abh_geodns_querylog_Entry(w, v)
-}
-func (v *Entry) UnmarshalJSON(data []byte) error {
-	r := jlexer.Lexer{Data: data}
-	easyjson_320612c2_decode_github_com_abh_geodns_querylog_Entry(&r, v)
-	return r.Error()
-}
-func (v *Entry) UnmarshalEasyJSON(l *jlexer.Lexer) {
-	easyjson_320612c2_decode_github_com_abh_geodns_querylog_Entry(l, v)
-}

+ 2 - 4
server.go

@@ -18,10 +18,8 @@ func NewServer() *Server {
 
 
 // Setup the QueryLogger. For now it only supports writing to a file (and all
 // Setup the QueryLogger. For now it only supports writing to a file (and all
 // zones get logged to the same file).
 // zones get logged to the same file).
-func (srv *Server) SetQueryLogger(file string) error {
-	var err error
-	srv.queryLogger, err = querylog.NewFileLogger(file)
-	return err
+func (srv *Server) SetQueryLogger(logger querylog.QueryLogger) {
+	srv.queryLogger = logger
 }
 }
 
 
 func (srv *Server) setupServerFunc(Zone *Zone) func(dns.ResponseWriter, *dns.Msg) {
 func (srv *Server) setupServerFunc(Zone *Zone) func(dns.ResponseWriter, *dns.Msg) {