func (elk *ELK) Cleanup(b *beat.Beat) error {
	return nil
}
Cleanup is a callback to cleanup any allocated resources
package main
import (
	"encoding/json"
	"net"
	"sync/atomic"
	log "github.com/Sirupsen/logrus"
	"github.com/elastic/beats/libbeat/beat"
	"github.com/elastic/beats/libbeat/common"
	"github.com/gravitational/trace"
	"github.com/jonboulle/clockwork"
)
const (
	ELKType = "type"
	ELKTimestamp = "@timestamp"
	ELKEntry = "entry"
	ELKMessage = "message"
	ELKTrace = "trace"
	ELKBeatName = "trace"
	ELKBeatVersion = "0.0.1"
)
type ELKOptionSetter func(f *ELK)
func NewELK(opts ...ELKOptionSetter) *ELK {
	f := &ELK{
		closeC: make(chan bool),
		SetupC: make(chan bool),
	}
	for _, o := range opts {
		o(f)
	}
	if f.Clock == nil {
		f.Clock = clockwork.NewRealClock()
	}
	return f
}
type ELK struct {
	Clock  clockwork.Clock
	beat   *beat.Beat
	closed uint32
	setup  uint32
	closeC chan bool
	SetupC chan bool
}
func (elk *ELK) Config(b *beat.Beat) error {
	return nil
}
func (elk *ELK) Setup(b *beat.Beat) error {
	elk.beat = b
	if atomic.CompareAndSwapUint32(&elk.setup, 0, 1) {
		close(elk.SetupC)
	}
	return nil
}
func (elk *ELK) Run(b *beat.Beat) error {
	addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:5000")
	l, err := net.ListenUDP(addr.Network(), addr)
	if err != nil {
		return trace.Wrap(err)
	}
	buf := make([]byte, 1024)
	var f trace.Frame
	for {
		count, _, err := l.ReadFrom(buf)
		if err != nil {
			e, ok := err.(net.Error)
			if ok && e.Timeout() {
				continue
			}
			return trace.Wrap(err)
		}
		err = json.Unmarshal(buf[:count], &f)
		if err != nil {
			log.Infof("failed to decode frame: %v", err)
		} else {
			elk.beat.Events.PublishEvent(common.MapStr{
				ELKTimestamp: common.Time(f.Time),
				ELKType:      f.Type,
				ELKEntry:     f.Entry,
				ELKMessage: map[string]string{
					ELKMessage:       f.Message,
					trace.LevelField: f.Level,
				},
			})
		}
		select {
		case <-elk.closeC:
			return nil
		default:
		}
	}
}