func (instance *Instance) publishLineAs(pub *zmqpubsub.Publisher, source string, logname string, line *tail.Line) { if line == nil { panic("line is nil") } msg := &message.Message{ LogFilename: logname, Source: source, InstanceIndex: instance.Index, AppGUID: instance.AppGUID, AppName: instance.AppName, AppSpace: instance.AppSpace, MessageCommon: common.NewMessageCommon(line.Text, line.Time, util.LocalNodeId()), } if line.Err != nil { // Mark this as a special error record, as it is // coming from tail, not the app. msg.Source = fmt.Sprintf("%v[apptail]", util.GetBrandName()) msg.LogFilename = "" log.Warnf("[%s] %s", instance.AppName, line.Text) } err := msg.Publish(pub, false) if err != nil { common.Fatal("Unable to publish: %v", err) } }
func SendToLogyard(pub *zmqpubsub.Publisher, event *docker_events.Event) { text := fmt.Sprintf("%v action for container %v (image: %v)", event.Status, event.Id, event.From) (&sieve.Event{ Type: event.Status, Process: "docker_events", Severity: "INFO", Desc: text, MessageCommon: common.NewMessageCommon(text, time.Unix(event.Time, 0), NodeID), }).MustPublish(pub) }
func (instance *Instance) SendTimelineEvent(format string, v ...interface{}) { line := fmt.Sprintf(format, v...) tEvent := event.TimelineEvent{event.App{instance.AppGUID, instance.AppSpace, instance.AppName}, instance.Index} evt := sieve.Event{ Type: "timeline", Desc: line, Severity: "INFO", Info: map[string]interface{}{ "app": tEvent.App, "instance_index": tEvent.InstanceIndex, }, Process: "apptail", MessageCommon: common.NewMessageCommon(line, time.Now(), util.LocalNodeId()), } instance.pubch.Ch <- evt }
func tailLogFile( name string, filepath string, nodeid string) (*tail.Tail, error) { if filepath == "" { filepath = fmt.Sprintf("/s/logs/%s.log", name) } log.Info("Tailing... ", filepath) t, err := tail.TailFile(filepath, tail.Config{ MaxLineSize: systail.GetConfig().MaxRecordSize, MustExist: false, Follow: true, // ignore existing content, to support subsequent re-runs of systail Location: &tail.SeekInfo{0, os.SEEK_END}, ReOpen: true, Poll: false}) if err != nil { return nil, err } go func(name string, tail *tail.Tail) { pub := logyard.Broker.NewPublisherMust() defer pub.Stop() for line := range tail.Lines { // JSON must be a valid UTF-8 string if !utf8.ValidString(line.Text) { line.Text = string([]rune(line.Text)) } data, err := json.Marshal(systail.Message{ name, common.NewMessageCommon(line.Text, line.Time, nodeid), }) if err != nil { tail.Killf("Failed to encode to JSON: %v", err) break } pub.MustPublish("systail."+name+"."+nodeid, string(data)) } }(name, t) return t, nil }
func PublishAppLog( pub *zmqpubsub.Publisher, t TimelineEvent, source string, event *sieve.Event) { err := (&message.Message{ LogFilename: "", Source: source, InstanceIndex: t.InstanceIndex, AppGUID: t.App.GUID, AppName: t.App.Name, AppSpace: t.App.Space, MessageCommon: common.NewMessageCommon(event.Desc, time.Unix(event.UnixTime, 0), util.LocalNodeId()), }).Publish(pub, true) if err != nil { common.Fatal("%v", err) } }
func main() { major, minor, patch := gozmq.Version() log.Infof("Starting logyard_sieve (zeromq %d.%d.%d)", major, minor, patch) LoadConfig() parser := sieve.NewStackatoParser(getConfig().Events) parser.DeleteSamples() pub := logyard.Broker.NewPublisherMust() defer pub.Stop() sub := logyard.Broker.Subscribe("systail") defer sub.Stop() server.MarkRunning("logyard_sieve") log.Info("Watching the systail stream on this node") for message := range sub.Ch { var record systail.Message err := json.Unmarshal([]byte(message.Value), &record) if err != nil { log.Warnf("failed to parse json: %s; ignoring record: %s", err, message.Value) continue } event, err := parser.Parse(record.Name, record.Text) if err != nil { log.Warnf( "failed to parse event from %s: %s -- source: %s", record.Name, err, record.Text) continue } if event != nil { event.MessageCommon = common.NewMessageCommon( event.Desc, time.Unix(record.UnixTime, 0), record.NodeID) event.MustPublish(pub) } } }