forked from elastic/beats
-
Notifications
You must be signed in to change notification settings - Fork 0
/
client.go
162 lines (135 loc) · 4.15 KB
/
client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package publisher
import (
"expvar"
"github.com/elastic/beats/libbeat/common"
"github.com/elastic/beats/libbeat/logp"
"github.com/elastic/beats/libbeat/outputs"
)
// Metrics that can retrieved through the expvar web interface.
var (
publishedEvents = expvar.NewInt("libbeatPublishedEvents")
)
// Client is used by beats to publish new events.
type Client interface {
// PublishEvent publishes one event with given options. If Sync option is set,
// PublishEvent will block until output plugins report success or failure state
// being returned by this method.
PublishEvent(event common.MapStr, opts ...ClientOption) bool
// PublishEvents publishes multiple events with given options. If Guaranteed
// option is set, PublishEvent will block until output plugins report
// success or failure state being returned by this method.
PublishEvents(events []common.MapStr, opts ...ClientOption) bool
}
// ChanClient will forward all published events one by one to the given channel
type ChanClient struct {
Channel chan common.MapStr
}
type ExtChanClient struct {
Channel chan PublishMessage
}
type PublishMessage struct {
Context Context
Events []common.MapStr
}
type client struct {
publisher *PublisherType
beatMeta common.MapStr
tags []string
}
// ClientOption allows API users to set additional options when publishing events.
type ClientOption func(option Context) Context
// Guaranteed option will retry publishing the event, until send attempt have
// been ACKed by output plugin.
func Guaranteed(o Context) Context {
o.Guaranteed = true
return o
}
// Sync option will block the event publisher until an event has been ACKed by
// the output plugin or failed.
func Sync(o Context) Context {
o.Sync = true
return o
}
func Signal(signaler outputs.Signaler) ClientOption {
return func(ctx Context) Context {
if ctx.Signal == nil {
ctx.Signal = signaler
} else {
ctx.Signal = outputs.NewCompositeSignaler(ctx.Signal, signaler)
}
return ctx
}
}
func newClient(pub *PublisherType) *client {
return &client{
publisher: pub,
beatMeta: common.MapStr{
"name": pub.name,
"hostname": pub.hostname,
},
tags: pub.tags,
}
}
func (c *client) PublishEvent(event common.MapStr, opts ...ClientOption) bool {
c.annotateEvent(event)
ctx, client := c.getClient(opts)
publishedEvents.Add(1)
return client.PublishEvent(ctx, event)
}
func (c *client) PublishEvents(events []common.MapStr, opts ...ClientOption) bool {
for _, event := range events {
c.annotateEvent(event)
}
ctx, client := c.getClient(opts)
publishedEvents.Add(int64(len(events)))
return client.PublishEvents(ctx, events)
}
func (c *client) annotateEvent(event common.MapStr) {
event["beat"] = c.beatMeta
if len(c.tags) > 0 {
event["tags"] = c.tags
}
if logp.IsDebug("publish") {
PrintPublishEvent(event)
}
}
func (c *client) getClient(opts []ClientOption) (Context, eventPublisher) {
ctx := makeContext(opts)
if ctx.Sync {
return ctx, c.publisher.syncPublisher.client()
}
return ctx, c.publisher.asyncPublisher.client()
}
// PublishEvent will publish the event on the channel. Options will be ignored.
// Always returns true.
func (c ChanClient) PublishEvent(event common.MapStr, opts ...ClientOption) bool {
c.Channel <- event
return true
}
// PublishEvents publishes all event on the configured channel. Options will be ignored.
// Always returns true.
func (c ChanClient) PublishEvents(events []common.MapStr, opts ...ClientOption) bool {
for _, event := range events {
c.Channel <- event
}
return true
}
// PublishEvent will publish the event on the channel. Options will be ignored.
// Always returns true.
func (c ExtChanClient) PublishEvent(event common.MapStr, opts ...ClientOption) bool {
c.Channel <- PublishMessage{makeContext(opts), []common.MapStr{event}}
return true
}
// PublishEvents publishes all event on the configured channel. Options will be ignored.
// Always returns true.
func (c ExtChanClient) PublishEvents(events []common.MapStr, opts ...ClientOption) bool {
c.Channel <- PublishMessage{makeContext(opts), events}
return true
}
func makeContext(opts []ClientOption) Context {
var ctx Context
for _, opt := range opts {
ctx = opt(ctx)
}
return ctx
}