func main() { var port uint var etcdAddr, bstalk, logLevel string // Command line flags flag.StringVarP(&bstalk, "beanstalk", "b", "127.0.0.1:11300", "address of beanstalkd server") flag.StringVarP(&logLevel, "log-level", "l", "warn", "log level") flag.StringVarP(&etcdAddr, "etcd", "e", "http://127.0.0.1:4001", "address of etcd server") flag.UintVarP(&port, "http", "p", 7544, "http port to publish metrics. set to 0 to disable") flag.Parse() // Set up logger if err := logx.DefaultSetup(logLevel); err != nil { log.WithFields(log.Fields{ "error": err, "level": logLevel, }).Fatal("unable to to set up logrus") } etcdClient := etcd.NewClient([]string{etcdAddr}) if !etcdClient.SyncCluster() { log.WithFields(log.Fields{ "addr": etcdAddr, }).Fatal("unable to sync etcd cluster") } ctx := lochness.NewContext(etcdClient) log.WithField("address", bstalk).Info("connection to beanstalk") jobQueue, err := jobqueue.NewClient(bstalk, etcdClient) if err != nil { log.WithFields(log.Fields{ "error": err, "address": bstalk, }).Fatal("failed to create jobQueue client") } // Set up metrics m := setupMetrics(port) if m != nil { } agent := ctx.NewMistifyAgent() // Start consuming consume(jobQueue, agent, m) }
func main() { var port uint var etcdAddr, bstalk, logLevel string flag.StringVarP(&bstalk, "beanstalk", "b", "127.0.0.1:11300", "address of beanstalkd server") flag.StringVarP(&logLevel, "log-level", "l", "warn", "log level") flag.StringVarP(&etcdAddr, "etcd", "e", "http://127.0.0.1:4001", "address of etcd server") flag.UintVarP(&port, "http", "p", 7543, "address for http interface. set to 0 to disable") flag.Parse() // Set up logger if err := logx.DefaultSetup(logLevel); err != nil { log.WithFields(log.Fields{ "error": err, "level": logLevel, }).Fatal("failed to set up logging") } etcdClient := etcd.NewClient([]string{etcdAddr}) if !etcdClient.SyncCluster() { log.WithFields(log.Fields{ "addr": etcdAddr, }).Fatal("unable to sync etcd cluster") } log.WithField("address", bstalk).Info("connection to beanstalk") jobQueue, err := jobqueue.NewClient(bstalk, etcdClient) if err != nil { log.WithFields(log.Fields{ "error": err, "address": bstalk, }).Fatal("failed to create jobQueue client") } // setup metrics ms := mapsink.New() conf := metrics.DefaultConfig("cplacerd") conf.EnableHostname = false m, _ := metrics.New(conf, ms) if port != 0 { http.Handle("/metrics", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { w.WriteHeader(http.StatusOK) w.Header().Set("Content-Type", "application/json") if err := json.NewEncoder(w).Encode(ms); err != nil { log.WithField("error", err).Error(err) } })) go func() { if err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil); err != nil { log.WithFields(log.Fields{ "error": err, }).Fatal("error serving") } }() } // XXX: we want to try to keep track of where a job is // in this pipeline? would have to persist in the job funcs := []TaskFunc{ TaskFunc{ name: "check job status", function: checkJobStatus, }, TaskFunc{ name: "check guest status", function: checkGuestStatus, }, TaskFunc{ name: "select hypervisor candidate", function: selectHypervisor, }, TaskFunc{ name: "update job action", function: changeJobAction, }, TaskFunc{ name: "add task to worker", function: addJobToWorker, }, TaskFunc{ name: "make task for deletion", function: deleteTask, }, } for _, f := range funcs { f.label = strings.Split(runtime.FuncForPC(reflect.ValueOf(f.function).Pointer()).Name(), ".")[1] } for { task, err := jobQueue.NextCreateTask() if err != nil { if bCE, ok := err.(beanstalk.ConnError); ok { switch bCE { case beanstalk.ErrTimeout: // Empty queue, continue waiting continue case beanstalk.ErrDeadline: // See docs on beanstalkd deadline // We're just going to sleep to let the deadline'd job expire // and try to get another job m.IncrCounter([]string{"beanstalk", "error", "deadline"}, 1) log.Debug(beanstalk.ErrDeadline) time.Sleep(5 * time.Second) continue default: // You have failed me for the last time log.WithField("error", err).Fatal(err) } } log.WithFields(log.Fields{ "task": task, "error": err, }).Error("invalid task") if err := task.Delete(); err != nil { log.WithFields(log.Fields{ "task": task.ID, "error": err, }).Error("unable to delete") } } for _, f := range funcs { fields := log.Fields{ "task": task, } log.WithFields(fields).Debug("running") start := time.Now() rm, err := f.function(jobQueue, task) m.MeasureSince([]string{f.label, "time"}, start) m.IncrCounter([]string{f.label, "count"}, 1) duration := int(time.Since(start).Seconds() * 1000) log.WithFields(fields).WithField("duration", duration).Info("done") if err != nil { m.IncrCounter([]string{f.label, "error"}, 1) log.WithFields(fields).WithField("error", err).Error("task error") task.Job.Status = jobqueue.JobStatusError task.Job.Error = err.Error() if err := task.Job.Save(24 * time.Hour); err != nil { log.WithFields(log.Fields{ "task": task, "error": err, }).Error("unable to save") } } if rm { if err := task.Delete(); err != nil { log.WithFields(log.Fields{ "task": task.ID, "error": err, }).Error("unable to delete") } break } } } }
func main() { var port uint var etcdAddr, bstalk, logLevel, statsd string flag.UintVarP(&port, "port", "p", 18000, "listen port") flag.StringVarP(&etcdAddr, "etcd", "e", defaultEtcdAddr, "address of etcd machine") flag.StringVarP(&bstalk, "beanstalk", "b", "127.0.0.1:11300", "address of beanstalkd server") flag.StringVarP(&logLevel, "log-level", "l", "warn", "log level") flag.StringVarP(&statsd, "statsd", "s", "", "statsd address") flag.Parse() if err := logx.DefaultSetup(logLevel); err != nil { log.WithFields(log.Fields{ "error": err, "func": "logx.DefaultSetup", "level": logLevel, }).Fatal("unable to set up logrus") } etcdClient := etcd.NewClient([]string{etcdAddr}) if !etcdClient.SyncCluster() { log.WithFields(log.Fields{ "error": nil, "func": "etcd.SyncCluster", "addr": etcdAddr, }).Fatal("unable to sync etcd cluster") } ctx := lochness.NewContext(etcdClient) log.WithField("address", bstalk).Info("connection to beanstalk") jobQueue, err := jobqueue.NewClient(bstalk, etcdClient) if err != nil { log.WithFields(log.Fields{ "error": err, "address": bstalk, }).Fatal("failed to create jobQueue client") } // setup metrics sink := mapsink.New() fanout := metrics.FanoutSink{sink} if statsd != "" { ss, _ := metrics.NewStatsdSink(statsd) fanout = append(fanout, ss) } conf := metrics.DefaultConfig("cguestd") conf.EnableHostname = false m, _ := metrics.New(conf, fanout) mctx := &metricsContext{ sink: sink, metrics: m, mmw: mmw.New(m), } if err := Run(port, ctx, jobQueue, mctx); err != nil { log.WithFields(log.Fields{ "error": err, }).Fatal("failed to run server") } }