func (manager *DrainManager) StartDrain(name, uri string, retry retry.Retryer) { manager.mux.Lock() defer manager.mux.Unlock() var stateChangeFn state.StateChangedFn _, exists := manager.stmMap[name] if exists { // Stop the running drain first. manager.stopDrain(name, false) } else { stateChangeFn = func(state state.State, rev int64) { manager.stateCache.SetState(name, state, rev) } } process, err := NewDrainProcess(name, uri) if err != nil { log.Error(process.Logf("Couldn't create drain: %v", err)) return } drainStm := state.NewStateMachine("Drain", process, retry, stateChangeFn) manager.stmMap[name] = drainStm if err = drainStm.SendAction(state.START); err != nil { log.Fatalf("Failed to start drain %s; %v", name, err) } }
func createLogyardConfig() { g, err := server.NewConfig("logyard", logyardConfig{}) if err != nil { log.Fatalf("Unable to load logyard config; %v", err) } config = g if config.GetConfig().(*logyardConfig).Drains == nil { log.Fatal("Logyard configuration is missing") } }
// stopDrain should only be called inside a mutex. func (manager *DrainManager) stopDrain(drainName string, clearStateCache bool) { if drainStm, ok := manager.stmMap[drainName]; ok { if err := drainStm.SendAction(state.STOP); err != nil { log.Fatalf("Failed to stop drain %s; %v", drainName, err) } drainStm.Stop() delete(manager.stmMap, drainName) if clearStateCache { manager.stateCache.Clear(drainName) } } // Sending on stopCh could block if DrainManager.Run().select // {...} is blocking on a mutex (via Start/Stop). Ideally, get rid // of mutexes and use channels. go func() { manager.stopCh <- true }() }
func NewDrainManager() *DrainManager { manager := new(DrainManager) manager.stopCh = make(chan bool) manager.stmMap = make(map[string]*state.StateMachine) client, err := server.NewRedisClientRetry( server.GetClusterConfig().MbusIp+":6464", "", 0, -1) if err != nil { log.Fatalf("Unable to connect to applog_redis; %v", err) } manager.stateCache = &statecache.StateCache{ "logyard:drainstatus:", server.LocalIPMust(), client} return manager }
func (manager *DrainManager) Run() { iteration := 0 drains := logyard.GetConfig().Drains log.Infof("Found %d drains to start\n", len(drains)) for name, uri := range drains { manager.StartDrain(name, uri, NewRetryerForDrain(name)) } // Watch for config changes in redis. for { iteration += 1 prefix := fmt.Sprintf("CONFIG.%d", iteration) select { case err := <-logyard.GetConfigChanges(): if err != nil { log.Fatalf("Error re-loading config: %v", err) } log.Infof( "[%s] checking drains after a config change...", prefix) newDrains := logyard.GetConfig().Drains for _, c := range mapdiff.MapDiff(drains, newDrains) { if c.Deleted { log.Infof("[%s] Drain %s was deleted.", prefix, c.Key) manager.StopDrain(c.Key, true) delete(drains, c.Key) } else { log.Infof("[%s] Drain %s was added.", prefix, c.Key) manager.StopDrain(c.Key, false) manager.StartDrain( c.Key, c.NewValue, NewRetryerForDrain(c.Key)) drains[c.Key] = c.NewValue } } log.Infof("[%s] Done checking drains.", prefix) case <-manager.stopCh: break } } }
func Stream(ch chan string, options MessagePrinterOptions) { // XXX: do we need MessagePrinter at all? all it does is // provide abstraction over color formatting; most other things // (formatting, skipping) happen in handler.go. printer := NewMessagePrinter(options) printer.AddFormat("systail", "{{.name}}@{{.node_id}}: {{.text}}") printer.AddFormat("event", "{{.type}}[{{.process}}]@{{.node_id}}: {{.desc}}") printer.AddFormat("apptail", "{{.app_name}}[{{.source}}]@{{.node_id}}: {{.text}}") printer.SetPrePrintHook(streamHandler) // Print incoming records for line := range ch { parts := strings.SplitN(string(line), " ", 2) if len(parts) != 2 { printer.PrintInternalError(fmt.Sprintf( "received invalid message: %v", string(line))) continue } msg := zmqpubsub.Message{parts[0], parts[1]} if !(strings.HasPrefix(msg.Key, "systail") || strings.HasPrefix(msg.Key, "apptail") || strings.HasPrefix(msg.Key, "event")) { printer.PrintInternalError(fmt.Sprintf( "unsupported stream key (%s) for message: %v", msg.Key, msg.Value)) continue } if err := printer.Print(msg); err != nil { log.Fatalf("Error -- %s -- printing message %s:%s", err, msg.Key, msg.Value) } } }