func main() { flag.Usage = usage flag.Parse() config_file = "/etc/carbon-relay-ng.ini" if 1 == flag.NArg() { config_file = flag.Arg(0) } if _, err := toml.DecodeFile(config_file, &config); err != nil { log.Error("Cannot use config file '%s':\n", config_file) log.Error(err.Error()) usage() return } //runtime.SetBlockProfileRate(1) // to enable block profiling. in my experience, adds 35% overhead. levels := map[string]logging.Level{ "critical": logging.CRITICAL, "error": logging.ERROR, "warning": logging.WARNING, "notice": logging.NOTICE, "info": logging.INFO, "debug": logging.DEBUG, } level, ok := levels[config.Log_level] if !ok { log.Error("unrecognized log level '%s'\n", config.Log_level) return } logging.SetLevel(level, "carbon-relay-ng") if *cpuprofile != "" { f, err := os.Create(*cpuprofile) if err != nil { log.Fatal(err) } pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() } if len(config.Instance) == 0 { log.Error("instance identifier cannot be empty") os.Exit(1) } runtime.GOMAXPROCS(config.max_procs) instance = config.Instance expvar.NewString("instance").Set(instance) expvar.NewString("service").Set(service) log.Notice("===== carbon-relay-ng instance '%s' starting. =====\n", instance) numIn = Counter("unit=Metric.direction=in") numInvalid = Counter("unit=Err.type=invalid") if config.Instrumentation.Graphite_addr != "" { addr, err := net.ResolveTCPAddr("tcp", config.Instrumentation.Graphite_addr) if err != nil { log.Fatal(err) } go metrics.Graphite(metrics.DefaultRegistry, time.Duration(config.Instrumentation.Graphite_interval)*time.Millisecond, "", addr) } log.Notice("creating routing table...") maxAge, err := time.ParseDuration(config.Bad_metrics_max_age) if err != nil { log.Error("could not parse badMetrics max age") log.Error(err.Error()) os.Exit(1) } badMetrics = badmetrics.New(maxAge) table = NewTable(config.Spool_dir) log.Notice("initializing routing table...") for i, cmd := range config.Init { log.Notice("applying: %s", cmd) err = applyCommand(table, cmd) if err != nil { log.Error("could not apply init cmd #%d", i+1) log.Error(err.Error()) os.Exit(1) } } tablePrinted := table.Print() log.Notice("===========================") log.Notice("========== TABLE ==========") log.Notice("===========================") for _, line := range strings.Split(tablePrinted, "\n") { log.Notice(line) } // Follow the goagain protocol, <https://github.com/rcrowley/goagain>. l, ppid, err := goagain.GetEnvs() if nil != err { laddr, err := net.ResolveTCPAddr("tcp", config.Listen_addr) if nil != err { log.Error(err.Error()) os.Exit(1) } l, err = net.ListenTCP("tcp", laddr) if nil != err { log.Error(err.Error()) os.Exit(1) } log.Notice("listening on %v", laddr) go accept(l.(*net.TCPListener), config) } else { log.Notice("resuming listening on %v", l.Addr()) go accept(l.(*net.TCPListener), config) if err := goagain.KillParent(ppid); nil != err { log.Error(err.Error()) os.Exit(1) } for { err := syscall.Kill(ppid, 0) if err != nil { break } time.Sleep(10 * time.Millisecond) } } if config.Admin_addr != "" { go func() { err := adminListener(config.Admin_addr) if err != nil { fmt.Println("Error listening:", err.Error()) os.Exit(1) } }() } if config.Http_addr != "" { go HttpListener(config.Http_addr, table) } if err := goagain.AwaitSignals(l); nil != err { log.Error(err.Error()) os.Exit(1) } }
func main() { flag.Usage = usage flag.Parse() runtime.SetBlockProfileRate(*blockProfileRate) runtime.MemProfileRate = *memProfileRate // validation defaults config.Validation_level_legacy.Level = m20.MediumLegacy config.Validation_level_m20.Level = m20.MediumM20 config_file = "/etc/carbon-relay-ng.ini" if 1 == flag.NArg() { config_file = flag.Arg(0) } if _, err := toml.DecodeFile(config_file, &config); err != nil { log.Error("Cannot use config file '%s':\n", config_file) log.Error(err.Error()) usage() return } //runtime.SetBlockProfileRate(1) // to enable block profiling. in my experience, adds 35% overhead. levels := map[string]logging.Level{ "critical": logging.CRITICAL, "error": logging.ERROR, "warning": logging.WARNING, "notice": logging.NOTICE, "info": logging.INFO, "debug": logging.DEBUG, } level, ok := levels[config.Log_level] if !ok { log.Error("unrecognized log level '%s'\n", config.Log_level) return } logging.SetLevel(level, "carbon-relay-ng") if *cpuprofile != "" { f, err := os.Create(*cpuprofile) if err != nil { log.Fatal(err) } pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() } if len(config.Instance) == 0 { log.Error("instance identifier cannot be empty") os.Exit(1) } runtime.GOMAXPROCS(config.Max_procs) log.Notice("===== carbon-relay-ng instance '%s' starting. =====\n", config.Instance) stats.New(config.Instance) if config.Pid_file != "" { f, err := os.Create(config.Pid_file) if err != nil { fmt.Println("error creating pidfile:", err.Error()) os.Exit(1) } _, err = f.Write([]byte(strconv.Itoa(os.Getpid()))) if err != nil { fmt.Println("error writing to pidfile:", err.Error()) os.Exit(1) } f.Close() } if config.Instrumentation.Graphite_addr != "" { addr, err := net.ResolveTCPAddr("tcp", config.Instrumentation.Graphite_addr) if err != nil { log.Fatal(err) } go metrics.Graphite(metrics.DefaultRegistry, time.Duration(config.Instrumentation.Graphite_interval)*time.Millisecond, "", addr) } log.Notice("creating routing table...") maxAge, err := time.ParseDuration(config.Bad_metrics_max_age) if err != nil { log.Error("could not parse badMetrics max age") log.Error(err.Error()) os.Exit(1) } badMetrics = badmetrics.New(maxAge) table = tbl.New(config.Spool_dir) log.Notice("initializing routing table...") for i, cmd := range config.Init { log.Notice("applying: %s", cmd) err = imperatives.Apply(table, cmd) if err != nil { log.Error("could not apply init cmd #%d", i+1) log.Error(err.Error()) os.Exit(1) } } tablePrinted := table.Print() log.Notice("===========================") log.Notice("========== TABLE ==========") log.Notice("===========================") for _, line := range strings.Split(tablePrinted, "\n") { log.Notice(line) } if config.Listen_addr != "" { _, err = input.NewPlain(config, config.Listen_addr, table, badMetrics) if err != nil { log.Error(err.Error()) os.Exit(1) } } if config.Pickle_addr != "" { _, err = input.NewPickle(config, config.Pickle_addr, table, badMetrics) if err != nil { log.Error(err.Error()) os.Exit(1) } } if config.Admin_addr != "" { go func() { err := telnet.Start(config.Admin_addr, table) if err != nil { fmt.Println("Error listening:", err.Error()) os.Exit(1) } }() } if config.Http_addr != "" { go web.Start(config.Http_addr, config, table, badMetrics) } select {} }