vitess.io/vitess@v0.16.2/go/vt/vttablet/sysloglogger/sysloglogger.go (about) 1 /* 2 Copyright 2019 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 // Package sysloglogger implements an optional plugin that logs all queries to syslog. 18 package sysloglogger 19 20 import ( 21 "bytes" 22 "log/syslog" 23 24 "github.com/spf13/pflag" 25 26 "vitess.io/vitess/go/vt/log" 27 "vitess.io/vitess/go/vt/servenv" 28 "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" 29 ) 30 31 // syslogWriter is an interface that wraps syslog.Writer, so it can be mocked in unit tests. 32 type syslogWriter interface { 33 Info(string) error 34 Close() error 35 } 36 37 // writer holds a persistent connection to the syslog daemon (or a mock when under test). 38 var writer syslogWriter 39 40 // ch holds the tabletserver.StatsLogger channel to which this plugin subscribes (or a mock when under test). 41 var ch chan any 42 43 var logQueries bool 44 45 func registerFlags(fs *pflag.FlagSet) { 46 // logQueries is the vttablet startup flag that must be set for this plugin to be active. 47 fs.BoolVar(&logQueries, "log_queries", logQueries, "Enable query logging to syslog.") 48 } 49 50 func init() { 51 servenv.OnParseFor("vtcombo", registerFlags) 52 servenv.OnParseFor("vttablet", registerFlags) 53 54 servenv.OnRun(func() { 55 if logQueries { 56 var err error 57 writer, err = syslog.New(syslog.LOG_INFO, "vtquerylogger") 58 if err != nil { 59 log.Errorf("Query logger is unable to connect to syslog: %v", err) 60 return 61 } 62 go run() 63 } 64 }) 65 } 66 67 // Run logs queries to syslog, if the "log_queries" flag is set to true when starting vttablet. 68 func run() { 69 log.Info("Logging queries to syslog") 70 defer writer.Close() 71 72 // ch will only be non-nil in a unit test context, when a mock has been populated 73 if ch == nil { 74 ch = tabletenv.StatsLogger.Subscribe("gwslog") 75 defer tabletenv.StatsLogger.Unsubscribe(ch) 76 } 77 78 formatParams := map[string][]string{"full": {}} 79 for out := range ch { 80 stats, ok := out.(*tabletenv.LogStats) 81 if !ok { 82 log.Errorf("Unexpected value in query logs: %#v (expecting value of type %T)", out, &tabletenv.LogStats{}) 83 continue 84 } 85 var b bytes.Buffer 86 if err := stats.Logf(&b, formatParams); err != nil { 87 log.Errorf("Error formatting logStats: %v", err) 88 continue 89 } 90 if err := writer.Info(b.String()); err != nil { 91 log.Errorf("Error writing to syslog: %v", err) 92 continue 93 } 94 } 95 }