func TestSyslogFilter(t *testing.T) { if runtime.GOOS == "windows" { t.SkipNow() } l, err := gsyslog.NewLogger(gsyslog.LOG_NOTICE, "LOCAL0", "consul") if err != nil { t.Fatalf("err: %s", err) } filt := LevelFilter() filt.MinLevel = logutils.LogLevel("INFO") s := &SyslogWrapper{l, filt} n, err := s.Write([]byte("[INFO] test")) if err != nil { t.Fatalf("err: %s", err) } if n == 0 { t.Fatalf("should have logged") } n, err = s.Write([]byte("[DEBUG] test")) if err != nil { t.Fatalf("err: %s", err) } if n != 0 { t.Fatalf("should not have logged") } }
func TestRPCLogStream(t *testing.T) { sc := &MockStreamClient{} filter := LevelFilter() filter.MinLevel = logutils.LogLevel("INFO") ls := newLogStream(sc, filter, 42, log.New(os.Stderr, "", log.LstdFlags)) defer ls.Stop() log := "[DEBUG] this is a test log" log2 := "[INFO] This should pass" ls.HandleLog(log) ls.HandleLog(log2) time.Sleep(5 * time.Millisecond) if len(sc.headers) != 1 { t.Fatalf("expected 1 messages!") } for _, h := range sc.headers { if h.Seq != 42 { t.Fatalf("bad seq") } if h.Error != "" { t.Fatalf("bad err") } } obj1 := sc.objs[0].(*logRecord) if obj1.Log != log2 { t.Fatalf("bad event %#v", obj1) } }
func (c *MonitorCommand) Run(args []string) int { var logLevel string cmdFlags := flag.NewFlagSet("monitor", flag.ContinueOnError) cmdFlags.Usage = func() { c.Ui.Output(c.Help()) } cmdFlags.StringVar(&logLevel, "log-level", "INFO", "log level") rpcAddr := RPCAddrFlag(cmdFlags) if err := cmdFlags.Parse(args); err != nil { return 1 } client, err := RPCClient(*rpcAddr) if err != nil { c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err)) return 1 } defer client.Close() logCh := make(chan string, 1024) monHandle, err := client.Monitor(logutils.LogLevel(logLevel), logCh) if err != nil { c.Ui.Error(fmt.Sprintf("Error starting monitor: %s", err)) return 1 } defer client.Stop(monHandle) eventDoneCh := make(chan struct{}) go func() { defer close(eventDoneCh) OUTER: for { select { case log := <-logCh: if log == "" { break OUTER } c.Ui.Info(log) } } c.lock.Lock() defer c.lock.Unlock() if !c.quitting { c.Ui.Info("") c.Ui.Output("Remote side ended the monitor! This usually means that the\n" + "remote side has exited or crashed.") } }() select { case <-eventDoneCh: return 1 case <-c.ShutdownCh: c.lock.Lock() c.quitting = true c.lock.Unlock() } return 0 }
// setupLoggers is used to setup the logGate, logWriter, and our logOutput func (c *Command) setupLoggers(config *Config) (*GatedWriter, *logWriter, io.Writer) { // Setup logging. First create the gated log writer, which will // store logs until we're ready to show them. Then create the level // filter, filtering logs of the specified level. logGate := &GatedWriter{ Writer: &cli.UiWriter{Ui: c.Ui}, } c.logFilter = LevelFilter() c.logFilter.MinLevel = logutils.LogLevel(strings.ToUpper(config.LogLevel)) c.logFilter.Writer = logGate if !ValidateLevelFilter(c.logFilter.MinLevel, c.logFilter) { c.Ui.Error(fmt.Sprintf( "Invalid log level: %s. Valid log levels are: %v", c.logFilter.MinLevel, c.logFilter.Levels)) return nil, nil, nil } // Check if syslog is enabled var syslog io.Writer if config.EnableSyslog { l, err := gsyslog.NewLogger(gsyslog.LOG_NOTICE, config.SyslogFacility, "consul") if err != nil { c.Ui.Error(fmt.Sprintf("Syslog setup failed: %v", err)) return nil, nil, nil } syslog = &SyslogWrapper{l, c.logFilter} } // Create a log writer, and wrap a logOutput around it logWriter := NewLogWriter(512) var logOutput io.Writer if syslog != nil { logOutput = io.MultiWriter(c.logFilter, logWriter, syslog) } else { logOutput = io.MultiWriter(c.logFilter, logWriter) } c.logOutput = logOutput return logGate, logWriter, logOutput }
func (i *AgentRPC) handleMonitor(client *rpcClient, seq uint64) error { var req monitorRequest if err := client.dec.Decode(&req); err != nil { return fmt.Errorf("decode failed: %v", err) } resp := responseHeader{ Seq: seq, Error: "", } // Upper case the log level req.LogLevel = strings.ToUpper(req.LogLevel) // Create a level filter filter := LevelFilter() filter.MinLevel = logutils.LogLevel(req.LogLevel) if !ValidateLevelFilter(filter.MinLevel, filter) { resp.Error = fmt.Sprintf("Unknown log level: %s", filter.MinLevel) goto SEND } // Check if there is an existing monitor if client.logStreamer != nil { resp.Error = monitorExists goto SEND } // Create a log streamer client.logStreamer = newLogStream(client, filter, seq, i.logger) // Register with the log writer. Defer so that we can respond before // registration, avoids any possible race condition defer i.logWriter.RegisterHandler(client.logStreamer) SEND: return client.Send(&resp, nil) }
// handleReload is invoked when we should reload our configs, e.g. SIGHUP func (c *Command) handleReload(config *Config) *Config { c.Ui.Output("Reloading configuration...") newConf := c.readConfig() if newConf == nil { c.Ui.Error(fmt.Sprintf("Failed to reload configs")) return config } // Change the log level minLevel := logutils.LogLevel(strings.ToUpper(newConf.LogLevel)) if ValidateLevelFilter(minLevel, c.logFilter) { c.logFilter.SetMinLevel(minLevel) } else { c.Ui.Error(fmt.Sprintf( "Invalid log level: %s. Valid log levels are: %v", minLevel, c.logFilter.Levels)) // Keep the current log level newConf.LogLevel = config.LogLevel } // Bulk update the services and checks c.agent.PauseSync() defer c.agent.ResumeSync() // First unload all checks and services. This lets us begin the reload // with a clean slate. if err := c.agent.unloadServices(); err != nil { c.Ui.Error(fmt.Sprintf("Failed unloading services: %s", err)) return nil } if err := c.agent.unloadChecks(); err != nil { c.Ui.Error(fmt.Sprintf("Failed unloading checks: %s", err)) return nil } // Reload services and check definitions. if err := c.agent.loadServices(newConf); err != nil { c.Ui.Error(fmt.Sprintf("Failed reloading services: %s", err)) return nil } if err := c.agent.loadChecks(newConf); err != nil { c.Ui.Error(fmt.Sprintf("Failed reloading checks: %s", err)) return nil } // Get the new client listener addr httpAddr, err := newConf.ClientListener(config.Addresses.HTTP, config.Ports.HTTP) if err != nil { c.Ui.Error(fmt.Sprintf("Failed to determine HTTP address: %v", err)) } // Deregister the old watches for _, wp := range config.WatchPlans { wp.Stop() } // Register the new watches for _, wp := range newConf.WatchPlans { go func(wp *watch.WatchPlan) { wp.Handler = makeWatchHandler(c.logOutput, wp.Exempt["handler"]) wp.LogOutput = c.logOutput if err := wp.Run(httpAddr.String()); err != nil { c.Ui.Error(fmt.Sprintf("Error running watch: %v", err)) } }(wp) } return newConf }