func (input *S3OffsetInput) ReportMsg(msg *message.Message) error { message.NewInt64Field(msg, "ProcessMessageCount", atomic.LoadInt64(&input.processMessageCount), "count") message.NewInt64Field(msg, "ProcessMessageFailures", atomic.LoadInt64(&input.processMessageFailures), "count") message.NewInt64Field(msg, "ProcessMessageBytes", atomic.LoadInt64(&input.processMessageBytes), "B") return nil }
func (k *KafkaInput) ReportMsg(msg *message.Message) error { message.NewInt64Field(msg, "ProcessMessageCount", atomic.LoadInt64(&k.processMessageCount), "count") message.NewInt64Field(msg, "ProcessMessageFailures", atomic.LoadInt64(&k.processMessageFailures), "count") return nil }
// Satisfies the `pipeline.ReportingPlugin` interface to provide sandbox state // information to the Heka report and dashboard. func (s *SandboxDecoder) ReportMsg(msg *message.Message) error { if s.sb == nil { return fmt.Errorf("Decoder is not running") } s.reportLock.RLock() defer s.reportLock.RUnlock() message.NewIntField(msg, "Memory", int(s.sb.Usage(TYPE_MEMORY, STAT_CURRENT)), "B") message.NewIntField(msg, "MaxMemory", int(s.sb.Usage(TYPE_MEMORY, STAT_MAXIMUM)), "B") message.NewIntField(msg, "MaxInstructions", int(s.sb.Usage( TYPE_INSTRUCTIONS, STAT_MAXIMUM)), "count") message.NewIntField(msg, "MaxOutput", int(s.sb.Usage(TYPE_OUTPUT, STAT_MAXIMUM)), "B") message.NewInt64Field(msg, "ProcessMessageCount", atomic.LoadInt64(&s.processMessageCount), "count") message.NewInt64Field(msg, "ProcessMessageFailures", atomic.LoadInt64(&s.processMessageFailures), "count") message.NewInt64Field(msg, "ProcessMessageSamples", s.processMessageSamples, "count") var tmp int64 = 0 if s.processMessageSamples > 0 { tmp = s.processMessageDuration / s.processMessageSamples } message.NewInt64Field(msg, "ProcessMessageAvgDuration", tmp, "ns") return nil }
// Satisfies the `pipeline.ReportingPlugin` interface to provide plugin state // information to the Heka report and dashboard. func (t *TcpOutput) ReportMsg(msg *message.Message) error { t.reportLock.Lock() defer t.reportLock.Unlock() message.NewInt64Field(msg, "ProcessMessageCount", atomic.LoadInt64(&t.processMessageCount), "count") message.NewInt64Field(msg, "SentMessageCount", atomic.LoadInt64(&t.sentMessageCount), "count") return nil }
func (r *RedisListOutput) ReportMsg(msg *message.Message) error { message.NewInt64Field(msg, "EncodingErrors", atomic.LoadInt64(&r.encodingErrors), "count") message.NewInt64Field(msg, "ProcessMessageCount", atomic.LoadInt64(&r.processMessageCount), "count") message.NewInt64Field(msg, "ProcessMessageFailures", atomic.LoadInt64(&r.processMessageFailures), "count") return nil }
// Satisfies the `pipeline.ReportingPlugin` interface to provide plugin state // information to the Heka report and dashboard. func (o *ElasticSearchOutput) ReportMsg(msg *message.Message) error { o.reportLock.Lock() defer o.reportLock.Unlock() message.NewInt64Field(msg, "SentMessageCount", atomic.LoadInt64(&o.sentMessageCount), "count") message.NewInt64Field(msg, "DropMessageCount", atomic.LoadInt64(&o.dropMessageCount), "count") return nil }
func (r *RedisListInput) ReportMsg(msg *message.Message) error { message.NewInt64Field(msg, "RedisPollCount", atomic.LoadInt64(&r.redisPollCount), "count") message.NewInt64Field(msg, "RedisPollFailures", atomic.LoadInt64(&r.redisPollFailures), "count") message.NewInt64Field(msg, "RedisPingFailures", atomic.LoadInt64(&r.redisPingFailures), "count") message.NewInt64Field(msg, "ProcessMessageCount", atomic.LoadInt64(&r.processMessageCount), "count") message.NewInt64Field(msg, "ProcessMessageFailures", atomic.LoadInt64(&r.processMessageFailures), "count") return nil }
func (k *KafkaOutput) ReportMsg(msg *message.Message) error { message.NewInt64Field(msg, "ProcessMessageCount", atomic.LoadInt64(&k.processMessageCount), "count") message.NewInt64Field(msg, "ProcessMessageFailures", atomic.LoadInt64(&k.processMessageFailures), "count") message.NewInt64Field(msg, "ProcessMessageDiscards", atomic.LoadInt64(&k.processMessageDiscards), "count") message.NewInt64Field(msg, "KafkaDroppedMessages", atomic.LoadInt64(&k.kafkaDroppedMessages), "count") message.NewInt64Field(msg, "KafkaEncodingErrors", atomic.LoadInt64(&k.kafkaEncodingErrors), "count") return nil }
// Satisfies the `pipeline.ReportingPlugin` interface to provide plugin state // information to the Heka report and dashboard. func (o *ElasticSearchOutput) ReportMsg(msg *message.Message) error { o.reportLock.Lock() defer o.reportLock.Unlock() message.NewInt64Field(msg, "ProcessMessageCount", atomic.LoadInt64(&o.processMessageCount), "count") message.NewInt64Field(msg, "DropMessageCount", atomic.LoadInt64(&o.dropMessageCount), "count") if o.conf.UseBuffering { o.bufferedOut.ReportMsg(msg) } return nil }
func (o *FlumeOutput) ReportMsg(msg *message.Message) error { o.reportLock.Lock() defer o.reportLock.Unlock() message.NewInt64Field(msg, "ProcessMessageCount", atomic.LoadInt64(&o.processMessageCount), "count") message.NewInt64Field(msg, "DropMessageCount", atomic.LoadInt64(&o.dropMessageCount), "count") message.NewInt64Field(msg, "BackMessageCount", atomic.LoadInt64(&o.backMessageCount), "count") o.bufferedOut.ReportMsg(msg) return nil }
// Adds running filters count to the report output. func (this *SandboxManagerFilter) ReportMsg(msg *message.Message) error { message.NewIntField(msg, "RunningFilters", int(atomic.LoadInt32(&this.currentFilters)), "count") message.NewInt64Field(msg, "ProcessMessageCount", atomic.LoadInt64(&this.processMessageCount), "count") return nil }
func (p *ProtobufDecoder) ReportMsg(msg *message.Message) error { p.reportLock.Lock() defer p.reportLock.Unlock() message.NewInt64Field(msg, "ProcessMessageCount", atomic.LoadInt64(&p.processMessageCount), "count") message.NewInt64Field(msg, "ProcessMessageFailures", atomic.LoadInt64(&p.processMessageFailures), "count") message.NewInt64Field(msg, "ProcessMessageSamples", p.processMessageSamples, "count") var tmp int64 = 0 if p.processMessageSamples > 0 { tmp = p.processMessageDuration / p.processMessageSamples } message.NewInt64Field(msg, "ProcessMessageAvgDuration", tmp, "ns") return nil }
func (o *S3SplitFileOutput) ReportMsg(msg *message.Message) error { // If the OpenFileCount is consistently at or near OpenFileLimit, consider // increasing the max_open_files parameter. message.NewInt64Field(msg, "OpenFileCount", int64(o.fopenCache.Len()), "count") message.NewInt64Field(msg, "OpenFileLimit", int64(o.MaxOpenFiles), "count") message.NewInt64Field(msg, "ProcessFileCount", atomic.LoadInt64(&o.processFileCount), "count") message.NewInt64Field(msg, "ProcessFileFailures", atomic.LoadInt64(&o.processFileFailures), "count") message.NewInt64Field(msg, "ProcessFilePartialFailures", atomic.LoadInt64(&o.processFilePartialFailures), "count") message.NewInt64Field(msg, "ProcessFileBytes", atomic.LoadInt64(&o.processFileBytes), "B") message.NewInt64Field(msg, "ProcessMessageCount", atomic.LoadInt64(&o.processMessageCount), "count") message.NewInt64Field(msg, "ProcessMessageFailures", atomic.LoadInt64(&o.processMessageFailures), "count") message.NewInt64Field(msg, "ProcessMessageBytes", atomic.LoadInt64(&o.processMessageBytes), "B") message.NewInt64Field(msg, "EncodeMessageFailures", atomic.LoadInt64(&o.encodeMessageFailures), "count") return nil }
// Given a PluginRunner and a Message struct, this function will populate the // Message struct's field values with the plugin's input channel length and // capacity, plus any additional data that the plugin might provide through // implementation of the `ReportingPlugin` interface defined above. func PopulateReportMsg(pr PluginRunner, msg *message.Message) (err error) { if reporter, ok := pr.Plugin().(ReportingPlugin); ok { if err = reporter.ReportMsg(msg); err != nil { return } } if fRunner, ok := pr.(FilterRunner); ok { message.NewIntField(msg, "InChanCapacity", cap(fRunner.InChan()), "count") message.NewIntField(msg, "InChanLength", len(fRunner.InChan()), "count") message.NewIntField(msg, "MatchChanCapacity", cap(fRunner.MatchRunner().inChan), "count") message.NewIntField(msg, "MatchChanLength", len(fRunner.MatchRunner().inChan), "count") message.NewIntField(msg, "LeakCount", fRunner.LeakCount(), "count") var tmp int64 = 0 fRunner.MatchRunner().reportLock.Lock() if fRunner.MatchRunner().matchSamples > 0 { tmp = fRunner.MatchRunner().matchDuration / fRunner.MatchRunner().matchSamples } fRunner.MatchRunner().reportLock.Unlock() message.NewInt64Field(msg, "MatchAvgDuration", tmp, "ns") } else if dRunner, ok := pr.(DecoderRunner); ok { message.NewIntField(msg, "InChanCapacity", cap(dRunner.InChan()), "count") message.NewIntField(msg, "InChanLength", len(dRunner.InChan()), "count") } msg.SetType("heka.plugin-report") return }
func (re *RiemannEncoder) ReportMsg(msg *message.Message) error { re.reportLock.Lock() defer re.reportLock.Unlock() message.NewInt64Field(msg, "ProcessMessageCount", atomic.LoadInt64(&re.processMessageCount), "count") message.NewInt64Field(msg, "ProcessMessageFailures", atomic.LoadInt64(&re.processMessageFailures), "count") message.NewInt64Field(msg, "ProcessMessageSamples", re.processMessageSamples, "count") var tmp int64 = 0 if re.processMessageSamples > 0 { tmp = re.processMessageDuration / re.processMessageSamples } message.NewInt64Field(msg, "ProcessMessageAvgDuration", tmp, "ns") return nil }
// Satisfies the `pipeline.ReportingPlugin` interface to provide sandbox state // information to the Heka report and dashboard. func (s *SandboxInput) ReportMsg(msg *message.Message) error { s.reportLock.Lock() defer s.reportLock.Unlock() if s.sb == nil { return fmt.Errorf("Input is not running") } message.NewIntField(msg, "Memory", int(s.sb.Usage(TYPE_MEMORY, STAT_CURRENT)), "B") message.NewIntField(msg, "MaxMemory", int(s.sb.Usage(TYPE_MEMORY, STAT_MAXIMUM)), "B") message.NewIntField(msg, "MaxInstructions", int(s.sb.Usage( TYPE_INSTRUCTIONS, STAT_MAXIMUM)), "count") message.NewIntField(msg, "MaxOutput", int(s.sb.Usage(TYPE_OUTPUT, STAT_MAXIMUM)), "B") message.NewInt64Field(msg, "ProcessMessageCount", atomic.LoadInt64(&s.processMessageCount), "count") message.NewInt64Field(msg, "ProcessMessageFailures", atomic.LoadInt64(&s.processMessageFailures), "count") message.NewInt64Field(msg, "ProcessMessageBytes", atomic.LoadInt64(&s.processMessageBytes), "B") return nil }
// ReportMsg provides plugin state to Heka report and dashboard. func (li *LogstreamerInput) ReportMsg(msg *message.Message) error { li.logstreamSetLock.RLock() defer li.logstreamSetLock.RUnlock() for _, name := range li.logstreamSet.GetLogstreamNames() { logstream, ok := li.logstreamSet.GetLogstream(name) if ok { fname, bytes := logstream.ReportPosition() message.NewStringField(msg, fmt.Sprintf("%s-filename", name), fname) message.NewInt64Field(msg, fmt.Sprintf("%s-bytes", name), bytes, "count") } } return nil }
// Satisfies the `pipeline.ReportingPlugin` interface to provide sandbox state // information to the Heka report and dashboard. func (this *SandboxFilter) ReportMsg(msg *message.Message) error { this.reportLock.Lock() defer this.reportLock.Unlock() if this.sb == nil { // Plugin not initialized or running return nil } message.NewIntField(msg, "Memory", int(this.sb.Usage(TYPE_MEMORY, STAT_CURRENT)), "B") message.NewIntField(msg, "MaxMemory", int(this.sb.Usage(TYPE_MEMORY, STAT_MAXIMUM)), "B") message.NewIntField(msg, "MaxInstructions", int(this.sb.Usage( TYPE_INSTRUCTIONS, STAT_MAXIMUM)), "count") message.NewIntField(msg, "MaxOutput", int(this.sb.Usage(TYPE_OUTPUT, STAT_MAXIMUM)), "B") message.NewInt64Field(msg, "ProcessMessageCount", atomic.LoadInt64(&this.processMessageCount), "count") message.NewInt64Field(msg, "ProcessMessageFailures", atomic.LoadInt64(&this.processMessageFailures), "count") message.NewInt64Field(msg, "InjectMessageCount", atomic.LoadInt64(&this.injectMessageCount), "count") message.NewInt64Field(msg, "ProcessMessageSamples", this.processMessageSamples, "count") message.NewInt64Field(msg, "TimerEventSamples", this.timerEventSamples, "count") var tmp int64 = 0 if this.processMessageSamples > 0 { tmp = this.processMessageDuration / this.processMessageSamples } message.NewInt64Field(msg, "ProcessMessageAvgDuration", tmp, "ns") tmp = 0 if this.profileMessageSamples > 0 { message.NewInt64Field(msg, "ProfileMessageSamples", this.profileMessageSamples, "count") tmp = this.profileMessageDuration / this.profileMessageSamples message.NewInt64Field(msg, "ProfileMessageAvgDuration", tmp, "ns") } tmp = 0 if this.timerEventSamples > 0 { tmp = this.timerEventDuration / this.timerEventSamples } message.NewInt64Field(msg, "TimerEventAvgDuration", tmp, "ns") return nil }
func (k *KinesisOutput) ReportMsg(msg *message.Message) error { k.reportLock.Lock() defer k.reportLock.Unlock() message.NewInt64Field(msg, "ProcessMessageCount", atomic.LoadInt64(&k.processMessageCount), "count") message.NewInt64Field(msg, "DropMessageCount", atomic.LoadInt64(&k.dropMessageCount), "count") message.NewInt64Field(msg, "BatchesSent", atomic.LoadInt64(&k.batchesSent), "count") message.NewInt64Field(msg, "BatchesFailed", atomic.LoadInt64(&k.batchesFailed), "count") message.NewInt64Field(msg, "RecordCount", atomic.LoadInt64(&k.recordCount), "count") message.NewInt64Field(msg, "RetryCount", atomic.LoadInt64(&k.retryCount), "count") message.NewInt64Field(msg, "FlushCount", atomic.LoadInt64(&k.flushCount), "count") message.NewInt64Field(msg, "tickerActivations", atomic.LoadInt64(&k.tickerActivations), "count") return nil }
func (md *MultiDecoder) ReportMsg(msg *message.Message) error { md.reportLock.RLock() defer md.reportLock.RUnlock() var tmp int64 for i, sub := range md.Config.Subs { message.NewInt64Field(msg, fmt.Sprintf("ProcessMessageCount-%s", sub), atomic.LoadInt64(&md.processMessageCount[i]), "count") message.NewInt64Field(msg, fmt.Sprintf("ProcessMessageFailures-%s", sub), atomic.LoadInt64(&md.processMessageFailures[i]), "count") message.NewInt64Field(msg, fmt.Sprintf("ProcessMessageSamples-%s", sub), md.processMessageSamples[i], "count") tmp = 0 if md.processMessageSamples[i] > 0 { tmp = md.processMessageDuration[i] / md.processMessageSamples[i] } message.NewInt64Field(msg, fmt.Sprintf("ProcessMessageAvgDuration-%s", sub), tmp, "ns") } message.NewInt64Field(msg, "ProcessMessageCount", atomic.LoadInt64(&md.processMessageCount[0]), "count") message.NewInt64Field(msg, "ProcessMessageFailures", atomic.LoadInt64(&md.totalMessageFailures), "count") message.NewInt64Field(msg, "ProcessMessageSamples", md.totalMessageSamples, "count") tmp = 0 if md.totalMessageSamples > 0 { tmp = md.totalMessageDuration / md.totalMessageSamples } message.NewInt64Field(msg, "ProcessMessageAvgDuration", tmp, "ns") return nil }
func (dei *DockerEventInput) Run(ir pipeline.InputRunner, h pipeline.PluginHelper) error { defer dei.dockerClient.RemoveEventListener(dei.eventStream) defer close(dei.eventStream) var ( ok bool err error pack *pipeline.PipelinePack ) hostname := h.Hostname() // Provides empty PipelinePacks packSupply := ir.InChan() ok = true for ok { select { case event := <-dei.eventStream: pack = <-packSupply pack.Message.SetType("DockerEvent") pack.Message.SetLogger(event.ID) pack.Message.SetHostname(hostname) payload := fmt.Sprintf("id:%s status:%s from:%s time:%d", event.ID, event.Status, event.From, event.Time) pack.Message.SetPayload(payload) pack.Message.SetTimestamp(time.Now().UnixNano()) pack.Message.SetUuid(uuid.NewRandom()) message.NewStringField(pack.Message, "ID", event.ID) message.NewStringField(pack.Message, "Status", event.Status) message.NewStringField(pack.Message, "From", event.From) message.NewInt64Field(pack.Message, "Time", event.Time, "ts") ir.Deliver(pack) case err = <-dei.stopChan: ok = false } } return err }
// Generates a single message with a payload that is a string representation // of the fields data and payload extracted from each running plugin's report // message and hands the message to the router for delivery. func (pc *PipelineConfig) AllReportsMsg() { report_type, msg_payload := pc.allReportsData() pack, e := pc.PipelinePack(0) if e != nil { LogError.Println(e.Error()) return } pack.Message.SetLogger(HEKA_DAEMON) pack.Message.SetType(report_type) pack.Message.SetPayload(msg_payload) if err := pack.EncodeMsgBytes(); err != nil { LogError.Printf("encoding heka.all-report message: %s\n", err.Error()) pack.recycle() } else { pc.router.InChan() <- pack } mempack, e := pc.PipelinePack(0) if e != nil { LogError.Println(e.Error()) return } mempack.Message.SetLogger(HEKA_DAEMON) mempack.Message.SetType("heka.memstat") var m runtime.MemStats runtime.ReadMemStats(&m) message.NewInt64Field(mempack.Message, "HeapSys", int64(m.HeapSys), "B") message.NewInt64Field(mempack.Message, "HeapAlloc", int64(m.HeapAlloc), "B") message.NewInt64Field(mempack.Message, "HeapIdle", int64(m.HeapIdle), "B") message.NewInt64Field(mempack.Message, "HeapInuse", int64(m.HeapInuse), "B") message.NewInt64Field(mempack.Message, "HeapReleased", int64(m.HeapReleased), "B") message.NewInt64Field(mempack.Message, "HeapObjects", int64(m.HeapObjects), "count") if err := mempack.EncodeMsgBytes(); err != nil { LogError.Printf("encoding heka.memstat message: %s\n", err.Error()) mempack.recycle() } else { pc.router.InChan() <- mempack } }
// Generates a single message with a payload that is a string representation // of the fields data and payload extracted from each running plugin's report // message and hands the message to the router for delivery. func (pc *PipelineConfig) AllReportsMsg() { report_type, msg_payload := pc.allReportsData() pack := pc.PipelinePack(0) pack.Message.SetLogger(HEKA_DAEMON) pack.Message.SetType(report_type) pack.Message.SetPayload(msg_payload) pc.router.InChan() <- pack mempack := pc.PipelinePack(0) mempack.Message.SetType("heka.memstat") var m runtime.MemStats runtime.ReadMemStats(&m) message.NewInt64Field(mempack.Message, "HeapSys", int64(m.HeapSys), "B") message.NewInt64Field(mempack.Message, "HeapAlloc", int64(m.HeapAlloc), "B") message.NewInt64Field(mempack.Message, "HeapIdle", int64(m.HeapIdle), "B") message.NewInt64Field(mempack.Message, "HeapInuse", int64(m.HeapInuse), "B") message.NewInt64Field(mempack.Message, "HeapReleased", int64(m.HeapReleased), "B") message.NewInt64Field(mempack.Message, "HeapObjects", int64(m.HeapObjects), "count") pc.router.InChan() <- mempack }
// Generate recycle channel and plugin report messages and put them on the // provided channel as they're ready. func (pc *PipelineConfig) reports(reportChan chan *PipelinePack) { var ( f *message.Field pack *PipelinePack msg *message.Message err, e error ) pack = <-pc.reportRecycleChan msg = pack.Message message.NewIntField(msg, "InChanCapacity", cap(pc.inputRecycleChan), "count") message.NewIntField(msg, "InChanLength", len(pc.inputRecycleChan), "count") msg.SetType("heka.input-report") message.NewStringField(msg, "name", "inputRecycleChan") message.NewStringField(msg, "key", "globals") reportChan <- pack pack = <-pc.reportRecycleChan msg = pack.Message message.NewIntField(msg, "InChanCapacity", cap(pc.injectRecycleChan), "count") message.NewIntField(msg, "InChanLength", len(pc.injectRecycleChan), "count") msg.SetType("heka.inject-report") message.NewStringField(msg, "name", "injectRecycleChan") message.NewStringField(msg, "key", "globals") reportChan <- pack pack = <-pc.reportRecycleChan msg = pack.Message message.NewIntField(msg, "InChanCapacity", cap(pc.router.InChan()), "count") message.NewIntField(msg, "InChanLength", len(pc.router.InChan()), "count") message.NewInt64Field(msg, "ProcessMessageCount", atomic.LoadInt64(&pc.router.processMessageCount), "count") msg.SetType("heka.router-report") message.NewStringField(msg, "name", "Router") message.NewStringField(msg, "key", "globals") reportChan <- pack getReport := func(runner PluginRunner) (pack *PipelinePack) { pack = <-pc.reportRecycleChan if err = PopulateReportMsg(runner, pack.Message); err != nil { msg = pack.Message f, e = message.NewField("Error", err.Error(), "") if e == nil { msg.AddField(f) } msg.SetType("heka.plugin-report") } return } pc.inputsLock.Lock() for name, runner := range pc.InputRunners { if runner.Transient() { continue } pack = getReport(runner) message.NewStringField(pack.Message, "name", name) message.NewStringField(pack.Message, "key", "inputs") reportChan <- pack } pc.inputsLock.Unlock() for _, runner := range pc.allDecoders { pack = getReport(runner) message.NewStringField(pack.Message, "name", runner.Name()) message.NewStringField(pack.Message, "key", "decoders") reportChan <- pack } pc.filtersLock.Lock() for name, runner := range pc.FilterRunners { pack = getReport(runner) message.NewStringField(pack.Message, "name", name) message.NewStringField(pack.Message, "key", "filters") reportChan <- pack } pc.filtersLock.Unlock() for name, runner := range pc.OutputRunners { pack = getReport(runner) message.NewStringField(pack.Message, "name", name) message.NewStringField(pack.Message, "key", "outputs") reportChan <- pack } close(reportChan) }
func (b *BufferedOutput) ReportMsg(msg *message.Message) error { message.NewInt64Field(msg, "SentMessageCount", atomic.LoadInt64(&b.sentMessageCount), "count") return nil }
func (this *SandboxFilter) Run(fr pipeline.FilterRunner, h pipeline.PluginHelper) (err error) { inChan := fr.InChan() ticker := fr.Ticker() var ( ok = true terminated = false sample = true blocking = false backpressure = false pack *pipeline.PipelinePack retval int msgLoopCount uint injectionCount uint startTime time.Time slowDuration int64 = int64(this.pConfig.Globals.MaxMsgProcessDuration) duration int64 capacity = cap(inChan) - 1 ) // We assign to the return value of Run() for errors in the closure so that // the plugin runner can determine what caused the SandboxFilter to return. this.sb.InjectMessage(func(payload, payload_type, payload_name string) int { if injectionCount == 0 { err = pipeline.TerminatedError("exceeded InjectMessage count") return 2 } injectionCount-- pack := h.PipelinePack(msgLoopCount) if pack == nil { err = pipeline.TerminatedError(fmt.Sprintf("exceeded MaxMsgLoops = %d", this.pConfig.Globals.MaxMsgLoops)) return 3 } if len(payload_type) == 0 { // heka protobuf message hostname := pack.Message.GetHostname() err := proto.Unmarshal([]byte(payload), pack.Message) if err == nil { // do not allow filters to override the following pack.Message.SetType("heka.sandbox." + pack.Message.GetType()) pack.Message.SetLogger(fr.Name()) pack.Message.SetHostname(hostname) } else { return 1 } } else { pack.Message.SetType("heka.sandbox-output") pack.Message.SetLogger(fr.Name()) pack.Message.SetPayload(payload) ptype, _ := message.NewField("payload_type", payload_type, "file-extension") pack.Message.AddField(ptype) pname, _ := message.NewField("payload_name", payload_name, "") pack.Message.AddField(pname) } if !fr.Inject(pack) { return 4 } atomic.AddInt64(&this.injectMessageCount, 1) return 0 }) for ok { select { case pack, ok = <-inChan: if !ok { break } atomic.AddInt64(&this.processMessageCount, 1) injectionCount = this.pConfig.Globals.MaxMsgProcessInject msgLoopCount = pack.MsgLoopCount if this.manager != nil { // only check for backpressure on dynamic plugins // reading a channel length is generally fast ~1ns // we need to check the entire chain back to the router backpressure = len(inChan) >= capacity || fr.MatchRunner().InChanLen() >= capacity || len(h.PipelineConfig().Router().InChan()) >= capacity } // performing the timing is expensive ~40ns but if we are // backpressured we need a decent sample set before triggering // termination if sample || (backpressure && this.processMessageSamples < int64(capacity)) || this.sbc.Profile { startTime = time.Now() sample = true } retval = this.sb.ProcessMessage(pack) if sample { duration = time.Since(startTime).Nanoseconds() this.reportLock.Lock() this.processMessageDuration += duration this.processMessageSamples++ if this.sbc.Profile { this.profileMessageDuration = this.processMessageDuration this.profileMessageSamples = this.processMessageSamples if this.profileMessageSamples == int64(capacity)*10 { this.sbc.Profile = false // reset the normal sampling so it isn't heavily skewed by the profile values // i.e. process messages fast during profiling and then switch to malicious code this.processMessageDuration = this.profileMessageDuration / this.profileMessageSamples this.processMessageSamples = 1 } } this.reportLock.Unlock() } if retval <= 0 { if backpressure && this.processMessageSamples >= int64(capacity) { if this.processMessageDuration/this.processMessageSamples > slowDuration || fr.MatchRunner().GetAvgDuration() > slowDuration/5 { terminated = true blocking = true } } if retval < 0 { atomic.AddInt64(&this.processMessageFailures, 1) em := this.sb.LastError() if len(em) > 0 { fr.LogError(errors.New(em)) } } sample = 0 == rand.Intn(this.sampleDenominator) } else { terminated = true } pack.Recycle() case t := <-ticker: injectionCount = this.pConfig.Globals.MaxMsgTimerInject startTime = time.Now() if retval = this.sb.TimerEvent(t.UnixNano()); retval != 0 { terminated = true } duration = time.Since(startTime).Nanoseconds() this.reportLock.Lock() this.timerEventDuration += duration this.timerEventSamples++ this.reportLock.Unlock() } if terminated { pack := h.PipelinePack(0) pack.Message.SetType("heka.sandbox-terminated") pack.Message.SetLogger(pipeline.HEKA_DAEMON) message.NewStringField(pack.Message, "plugin", fr.Name()) if blocking { pack.Message.SetPayload("sandbox is running slowly and blocking the router") // no lock on the ProcessMessage variables here because there are no active writers message.NewInt64Field(pack.Message, "ProcessMessageCount", this.processMessageCount, "count") message.NewInt64Field(pack.Message, "ProcessMessageFailures", this.processMessageFailures, "count") message.NewInt64Field(pack.Message, "ProcessMessageSamples", this.processMessageSamples, "count") message.NewInt64Field(pack.Message, "ProcessMessageAvgDuration", this.processMessageDuration/this.processMessageSamples, "ns") message.NewInt64Field(pack.Message, "MatchAvgDuration", fr.MatchRunner().GetAvgDuration(), "ns") message.NewIntField(pack.Message, "FilterChanLength", len(inChan), "count") message.NewIntField(pack.Message, "MatchChanLength", fr.MatchRunner().InChanLen(), "count") message.NewIntField(pack.Message, "RouterChanLength", len(h.PipelineConfig().Router().InChan()), "count") } else { pack.Message.SetPayload(this.sb.LastError()) } fr.Inject(pack) break } } if this.manager != nil { this.manager.PluginExited() } this.reportLock.Lock() var destroyErr error if this.sbc.PreserveData { destroyErr = this.sb.Destroy(this.preservationFile) } else { destroyErr = this.sb.Destroy("") } if destroyErr != nil { err = destroyErr } this.sb = nil this.reportLock.Unlock() return }