Example #1
0
func (c *console) PublishEvent(
	s outputs.Signaler,
	ts time.Time,
	event common.MapStr,
) error {
	var jsonEvent []byte
	var err error

	if c.pretty {
		jsonEvent, err = json.MarshalIndent(event, "", "  ")
	} else {
		jsonEvent, err = json.Marshal(event)
	}
	if err != nil {
		logp.Err("Fail to convert the event to JSON: %s", err)
		outputs.SignalCompleted(s)
		return err
	}

	if err = writeBuffer(jsonEvent); err != nil {
		goto fail
	}
	if err = writeBuffer([]byte{'\n'}); err != nil {
		goto fail
	}

	outputs.SignalCompleted(s)
	return nil
fail:
	logp.Err("Fail to write event: %s", err)
	outputs.SignalFailed(s)
	return err
}
Example #2
0
func (mh *testMessageHandler) acknowledgeMessage(m message) {
	if mh.response == CompletedResponse {
		outputs.SignalCompleted(m.context.signal)
	} else {
		outputs.SignalFailed(m.context.signal, nil)
	}
}
Example #3
0
func (o *outputWorker) onBulk(ctx *context, events []common.MapStr) {
	if len(events) == 0 {
		debug("output worker: no events to publish")
		outputs.SignalCompleted(ctx.signal)
		return
	}

	var sync *outputs.SyncSignal
	if ctx.sync {
		sync = outputs.NewSyncSignal()
	}

	if o.maxBulkSize < 0 || len(events) <= o.maxBulkSize {
		o.sendBulk(sync, ctx, events)
		return
	}

	// start splitting bulk request
	splits := (len(events) + (o.maxBulkSize - 1)) / o.maxBulkSize
	ctx.signal = outputs.NewSplitSignaler(ctx.signal, splits)
	for len(events) > 0 {
		sz := o.maxBulkSize
		if sz > len(events) {
			sz = len(events)
		}
		o.sendBulk(sync, ctx, events[:sz])
		events = events[sz:]
	}
}
Example #4
0
func (m *LoadBalancerMode) onMessage(client ProtocolClient, msg eventsMessage) {
	if msg.event != nil {
		if err := client.PublishEvent(msg.event); err != nil {
			m.onFail(msg, err)
			return
		}
	} else {
		published := 0
		events := msg.events
		send := 0
		for published < len(events) {
			n, err := client.PublishEvents(events[published:])
			if err != nil {
				// retry only non-confirmed subset of events in batch
				msg.events = msg.events[published:]

				// reset attempt count if subset of message has been send
				if send > 0 {
					msg.attemptsLeft = m.maxAttempts + 1
				}
				m.onFail(msg, err)
				return
			}
			published += n
			send++
		}
	}
	outputs.SignalCompleted(msg.signaler)
}
Example #5
0
func (s *singleConnectionMode) PublishEvents(
	trans outputs.Signaler,
	events []common.MapStr,
) error {
	published := 0
	fails := 0
	for !s.closed && (s.maxAttempts == 0 || fails < s.maxAttempts) {
		if err := s.Connect(); err != nil {
			fails++
			time.Sleep(s.waitRetry)
			continue
		}

		for published < len(events) {
			n, err := s.conn.PublishEvents(events[published:])
			if err != nil {
				break
			}

			fails = 0
			published += n
		}

		if published == len(events) {
			outputs.SignalCompleted(trans)
			return nil
		}

		time.Sleep(s.waitRetry)
		fails++
	}

	outputs.SignalFailed(trans)
	return nil
}
Example #6
0
// PublishEvent forwards a single event. On failure PublishEvent tries to reconnect.
func (s *SingleConnectionMode) PublishEvent(
	signaler outputs.Signaler,
	event common.MapStr,
) error {
	fails := 0

	var err error

	for !s.closed && (s.maxAttempts == 0 || fails < s.maxAttempts) {
		if err = s.connect(); err != nil {
			logp.Info("Connecting error publishing event (retrying): %s", err)

			fails++
			time.Sleep(s.waitRetry)
			continue
		}
		if err := s.conn.PublishEvent(event); err != nil {
			logp.Info("Error publishing event (retrying): %s", err)

			fails++
			continue
		}

		outputs.SignalCompleted(signaler)
		return nil
	}

	outputs.SignalFailed(signaler, err)
	return nil
}
Example #7
0
// PublishEvent forwards a single event. On failure PublishEvent tries to reconnect.
func (f *FailOverConnectionMode) PublishEvent(
	signaler outputs.Signaler,
	event common.MapStr,
) error {
	fails := 0
	var err error
	for !f.closed && (f.maxAttempts == 0 || fails < f.maxAttempts) {
		if err := f.connect(f.active); err != nil {
			logp.Info("Connecting error publishing events (retrying): %s", err)
			fails++
			time.Sleep(f.waitRetry)
			continue
		}

		if err := f.conns[f.active].PublishEvent(event); err != nil {
			logp.Info("Error publishing events (retrying): %s", err)
			fails++
			continue
		}

		outputs.SignalCompleted(signaler)
		return nil
	}

	outputs.SignalFailed(signaler, err)
	return nil
}
Example #8
0
func (m *LoadBalancerMode) onMessage(client ProtocolClient, msg eventsMessage) {
	if msg.event != nil {
		if err := client.PublishEvent(msg.event); err != nil {
			msg.attemptsLeft--
			m.onFail(msg, err)
			return
		}
	} else {
		events := msg.events
		total := len(events)
		var backoffCount uint

		for len(events) > 0 {
			var err error

			events, err = client.PublishEvents(events)
			if err != nil {
				msg.attemptsLeft--

				// reset attempt count if subset of messages has been processed
				if len(events) < total {
					msg.attemptsLeft = m.maxAttempts
				}

				if err != ErrTempBulkFailure {
					// retry non-published subset of events in batch
					msg.events = events
					m.onFail(msg, err)
					return
				}

				if m.maxAttempts > 0 && msg.attemptsLeft <= 0 {
					// no more attempts left => drop
					outputs.SignalFailed(msg.signaler, err)
					return
				}

				// wait before retry
				backoff := time.Duration(int64(m.waitRetry) * (1 << backoffCount))
				if backoff > m.maxWaitRetry {
					backoff = m.maxWaitRetry
				} else {
					backoffCount++
				}
				select {
				case <-m.done: // shutdown
					outputs.SignalFailed(msg.signaler, err)
					return
				case <-time.After(backoff):
				}

				// reset total count for temporary failure loop
				total = len(events)
			}
		}
	}
	outputs.SignalCompleted(msg.signaler)
}
Example #9
0
func (out *redisOutput) BulkPublish(
	signal outputs.Signaler,
	ts time.Time,
	events []common.MapStr,
) error {
	if !out.connected {
		logp.Debug("output_redis", "Droping pkt ...")
		return errors.New("Not connected")
	}

	command := "RPUSH"
	if out.DataType == RedisChannelType {
		command = "PUBLISH"
	}

	if len(events) == 1 { // single event
		event := events[0]
		jsonEvent, err := json.Marshal(event)
		if err != nil {
			logp.Err("Fail to convert the event to JSON: %s", err)
			outputs.SignalCompleted(signal)
			return err
		}

		_, err = out.Conn.Do(command, out.Index, string(jsonEvent))
		outputs.Signal(signal, err)
		out.onFail(err)
		return err
	}

	for _, event := range events {
		jsonEvent, err := json.Marshal(event)
		if err != nil {
			logp.Err("Fail to convert the event to JSON: %s", err)
			continue
		}
		err = out.Conn.Send(command, out.Index, string(jsonEvent))
		if err != nil {
			outputs.SignalFailed(signal, err)
			out.onFail(err)
			return err
		}
	}
	if err := out.Conn.Flush(); err != nil {
		outputs.Signal(signal, err)
		out.onFail(err)
		return err
	}
	_, err := out.Conn.Receive()
	outputs.Signal(signal, err)
	out.onFail(err)
	return err
}
Example #10
0
// publish is used to publish events using the configured protocol client.
// It provides general error handling and back off support used on failed
// send attempts. To be used by PublishEvent and PublishEvents.
// The send callback will try to progress sending traffic and returns kind of
// progress made in ok or resetFail. If ok is set to true, send finished
// processing events. If ok is false but resetFail is set, send was partially
// successful. If send was partially successful, the fail counter is reset thus up
// to maxAttempts send attempts without any progress might be executed.
func (s *SingleConnectionMode) publish(
	signaler outputs.Signaler,
	send func() (ok bool, resetFail bool),
) error {
	fails := 0
	var backoffCount uint
	var err error

	for !s.closed && (s.maxAttempts == 0 || fails < s.maxAttempts) {
		ok := false
		resetFail := false

		if err := s.connect(); err != nil {
			logp.Info("Connecting error publishing events (retrying): %s", err)
			goto sendFail
		}

		ok, resetFail = send()
		if !ok {
			goto sendFail
		}

		outputs.SignalCompleted(signaler)
		return nil

	sendFail:
		fails++
		if resetFail {
			fails = 0
		}
		if s.maxAttempts > 0 && fails == s.maxAttempts {
			// max number of attempts reached
			break
		}

		logp.Info("send fail")
		backoff := time.Duration(int64(s.waitRetry) * (1 << backoffCount))
		if backoff > s.maxWaitRetry {
			backoff = s.maxWaitRetry
		} else {
			backoffCount++
		}
		logp.Info("backoff retry: %v", backoff)
		time.Sleep(backoff)
	}

	outputs.SignalFailed(signaler, err)
	return nil
}
Example #11
0
// PublishEvents tries to publish the events with retries if connection becomes
// unavailable. On failure PublishEvents tries to reconnect.
func (s *SingleConnectionMode) PublishEvents(
	signaler outputs.Signaler,
	events []common.MapStr,
) error {
	fails := 0
	var backoffCount uint
	var err error

	for !s.closed && (s.maxAttempts == 0 || fails < s.maxAttempts) {
		if err := s.connect(); err != nil {
			logp.Info("Connecting error publishing events (retrying): %s", err)
			goto sendFail
		}

		for len(events) > 0 {
			var err error
			events, err = s.conn.PublishEvents(events)
			if err != nil {
				logp.Info("Error publishing events (retrying): %s", err)
				break
			}

			fails = 0
		}

		if len(events) == 0 {
			outputs.SignalCompleted(signaler)
			return nil
		}

	sendFail:
		logp.Info("send fail")
		backoff := time.Duration(int64(s.waitRetry) * (1 << backoffCount))
		if backoff > s.maxWaitRetry {
			backoff = s.maxWaitRetry
		} else {
			backoffCount++
		}
		logp.Info("backoff retry: %v", backoff)
		time.Sleep(backoff)
		fails++
	}

	outputs.SignalFailed(signaler, err)
	return nil
}
Example #12
0
func (o *outputWorker) onMessage(m message) {

	if m.event != nil {
		debug("output worker: publish single event")
		ts := time.Time(m.event["timestamp"].(common.Time))
		_ = o.out.PublishEvent(m.signal, ts, m.event)
	} else {
		if len(m.events) == 0 {
			debug("output worker: no events to publish")
			outputs.SignalCompleted(m.signal)
			return
		}

		debug("output worker: publish %v events", len(m.events))
		ts := time.Time(m.events[0]["timestamp"].(common.Time))
		_ = o.out.BulkPublish(m.signal, ts, m.events)
	}
}
Example #13
0
func (o *outputWorker) onEvent(ctx *context, event common.MapStr) {
	debug("output worker: publish single event")
	ts := time.Time(event["@timestamp"].(common.Time)).UTC()

	if !ctx.sync {
		_ = o.out.PublishEvent(ctx.signal, ts, event)
		return
	}

	signal := outputs.NewSyncSignal()
	for {
		o.out.PublishEvent(signal, ts, event)
		if signal.Wait() {
			outputs.SignalCompleted(ctx.signal)
			break
		}
	}
}
Example #14
0
func (out *fileOutput) PublishEvent(
	trans outputs.Signaler,
	ts time.Time,
	event common.MapStr,
) error {
	jsonEvent, err := json.Marshal(event)
	if err != nil {
		// mark as success so event is not send again.
		outputs.SignalCompleted(trans)

		logp.Err("Fail to convert the event to JSON: %s", err)
		return err
	}

	err = out.rotator.WriteLine(jsonEvent)
	outputs.Signal(trans, err)
	return err
}
Example #15
0
// PublishEvents tries to publish the events with retries if connection becomes
// unavailable. On failure PublishEvents tries to connect to another configured
// connection by random.
func (f *FailOverConnectionMode) PublishEvents(
	trans outputs.Signaler,
	events []common.MapStr,
) error {
	published := 0
	fails := 0
	var err error

	for !f.closed && (f.maxAttempts == 0 || fails < f.maxAttempts) {
		if err = f.connect(f.active); err != nil {
			logp.Info("Connecting error publishing events (retrying): %s", err)
			fails++
			time.Sleep(f.waitRetry)
			continue
		}

		// loop until all events have been send in case client supports partial sends
		for published < len(events) {
			conn := f.conns[f.active]
			n, err := conn.PublishEvents(events[published:])
			if err != nil {
				logp.Info("Error publishing events (retrying): %s", err)
				break
			}
			published += n
		}

		if published == len(events) {
			outputs.SignalCompleted(trans)
			return nil
		}

		// TODO(sissel): Track how frequently we timeout and reconnect. If we're
		// timing out too frequently, there's really no point in timing out since
		// basically everything is slow or down. We'll want to ratchet up the
		// timeout value slowly until things improve, then ratchet it down once
		// things seem healthy.
		time.Sleep(f.waitRetry)
		fails++
	}

	outputs.SignalFailed(trans, err)
	return nil
}
Example #16
0
// publish is used to publish events using the configured protocol client.
// It provides general error handling and back off support used on failed
// send attempts. To be used by PublishEvent and PublishEvents.
// The send callback will try to progress sending traffic and returns kind of
// progress made in ok or resetFail. If ok is set to true, send finished
// processing events. If ok is false but resetFail is set, send was partially
// successful. If send was partially successful, the fail counter is reset thus up
// to maxAttempts send attempts without any progress might be executed.
func (f *FailOverConnectionMode) publish(
	signaler outputs.Signaler,
	send func() (ok bool, resetFail bool),
) error {
	fails := 0
	var err error

	// TODO: we want back off support here? Fail over normally will try another
	// connection.

	for !f.closed && (f.maxAttempts == 0 || fails < f.maxAttempts) {
		ok := false
		resetFail := false

		if err = f.connect(f.active); err != nil {
			logp.Info("Connecting error publishing events (retrying): %s", err)
			goto sendFail
		}

		ok, resetFail = send()
		if !ok {
			goto sendFail
		}

		outputs.SignalCompleted(signaler)
		return nil

	sendFail:
		fails++
		if resetFail {
			fails = 0
		}
		if f.maxAttempts > 0 && fails == f.maxAttempts {
			// max number of attempts reached
			break
		}

		time.Sleep(f.waitRetry)
	}

	outputs.SignalFailed(signaler, err)
	return nil
}
Example #17
0
func (o *outputWorker) sendBulk(
	sync *outputs.SyncSignal,
	ctx *context,
	events []common.MapStr,
) {
	debug("output worker: publish %v events", len(events))
	ts := time.Time(events[0]["@timestamp"].(common.Time)).UTC()

	if sync == nil {
		err := o.out.BulkPublish(ctx.signal, ts, events)
		if err != nil {
			logp.Info("Error bulk publishing events: %s", err)
		}
		return
	}

	for done := false; !done; done = sync.Wait() {
		o.out.BulkPublish(sync, ts, events)
	}
	outputs.SignalCompleted(ctx.signal)
}
Example #18
0
// PublishEvents tries to publish the events with retries if connection becomes
// unavailable. On failure PublishEvents tries to reconnect.
func (s *SingleConnectionMode) PublishEvents(
	signaler outputs.Signaler,
	events []common.MapStr,
) error {
	published := 0
	fails := 0
	var err error

	for !s.closed && (s.maxAttempts == 0 || fails < s.maxAttempts) {
		if err := s.connect(); err != nil {
			logp.Info("Connecting error publishing events (retrying): %s", err)

			fails++
			time.Sleep(s.waitRetry)
			continue
		}

		for published < len(events) {
			n, err := s.conn.PublishEvents(events[published:])
			if err != nil {
				logp.Info("Error publishing events (retrying): %s", err)
				break
			}

			fails = 0
			published += n
		}

		if published == len(events) {
			outputs.SignalCompleted(signaler)
			return nil
		}

		time.Sleep(s.waitRetry)
		fails++
	}

	outputs.SignalFailed(signaler, err)
	return nil
}
Example #19
0
func (o *outputWorker) onMessage(m message) {

	if m.event != nil {
		debug("output worker: publish single event")
		ts := time.Time(m.event["@timestamp"].(common.Time)).UTC()
		_ = o.out.PublishEvent(m.signal, ts, m.event)
	} else {
		if len(m.events) == 0 {
			debug("output worker: no events to publish")
			outputs.SignalCompleted(m.signal)
			return
		}

		debug("output worker: publish %v events", len(m.events))
		ts := time.Time(m.events[0]["@timestamp"].(common.Time)).UTC()
		err := o.out.BulkPublish(m.signal, ts, m.events)

		if err != nil {
			logp.Info("Error bulk publishing events: %s", err)
		}
	}
}
Example #20
0
func (p *preprocessor) onMessage(m message) {
	publisher := p.pub
	single := false
	events := m.events
	if m.event != nil {
		single = true
		events = []common.MapStr{m.event}
	}

	var ignore []int // indices of events to be removed from events

	debug("preprocessor")

	for i, event := range events {
		// validate some required field
		if err := filterEvent(event); err != nil {
			logp.Err("Publishing event failed: %v", err)
			ignore = append(ignore, i)
			continue
		}

		// update address and geo-ip information. Ignore event
		// if address is invalid or event is found to be a duplicate
		ok := updateEventAddresses(publisher, event)
		if !ok {
			ignore = append(ignore, i)
			continue
		}

		// add additional Beat meta data
		event["beat"] = common.MapStr{
			"name":     publisher.name,
			"hostname": publisher.hostname,
			"version":  publisher.version,
		}
		if len(publisher.tags) > 0 {
			event["tags"] = publisher.tags
		}

		if logp.IsDebug("publish") {
			PrintPublishEvent(event)
		}
	}

	// return if no event is left
	if len(ignore) == len(events) {
		debug("no event left, complete send")
		outputs.SignalCompleted(m.context.signal)
		return
	}

	// remove invalid events.
	// TODO: is order important? Removal can be turned into O(len(ignore)) by
	//       copying last element into idx and doing
	//       events=events[:len(events)-len(ignore)] afterwards
	// Alternatively filtering could be implemented like:
	//   https://github.com/golang/go/wiki/SliceTricks#filtering-without-allocating
	for i := len(ignore) - 1; i >= 0; i-- {
		idx := ignore[i]
		debug("remove event[%v]", idx)
		events = append(events[:idx], events[idx+1:]...)
	}

	if publisher.disabled {
		debug("publisher disabled")
		outputs.SignalCompleted(m.context.signal)
		return
	}

	debug("preprocessor forward")
	if single {
		p.handler.onMessage(message{context: m.context, event: events[0]})
	} else {
		p.handler.onMessage(message{context: m.context, events: events})
	}
}
Example #21
0
// PublishEvent writes events to a channel then calls Completed on trans.
// It always returns nil.
func (t *testOutputer) PublishEvent(trans outputs.Signaler, ts time.Time,
	event common.MapStr) error {
	t.events <- event
	outputs.SignalCompleted(trans)
	return nil
}