|
1 | 1 | package analytics |
2 | 2 |
|
3 | 3 | import ( |
4 | | - "context" |
5 | | - "crypto/tls" |
6 | 4 | "encoding/json" |
7 | 5 | "time" |
8 | 6 |
|
9 | 7 | "github.com/golang/glog" |
10 | 8 | "github.com/livepeer/catalyst-api/metrics" |
11 | 9 | "github.com/segmentio/kafka-go" |
12 | | - "github.com/segmentio/kafka-go/sasl/plain" |
13 | 10 | ) |
14 | 11 |
|
15 | 12 | const ( |
16 | | - KafkaBatchInterval = 1 * time.Second |
17 | | - KafkaRequestTimeout = 60 * time.Second |
| 13 | + kafkaBatchInterval = 1 * time.Second |
| 14 | + kafkaRequestTimeout = 60 * time.Second |
18 | 15 | ) |
19 | 16 |
|
20 | 17 | type ILogProcessor interface { |
@@ -95,37 +92,18 @@ type KafkaKey struct { |
95 | 92 | EventType string `json:"event_type"` |
96 | 93 | } |
97 | 94 |
|
98 | | -func NewLogProcessor(bootstrapServers, user, password, topic string) (*LogProcessor, error) { |
99 | | - dialer := &kafka.Dialer{ |
100 | | - Timeout: KafkaRequestTimeout, |
101 | | - SASLMechanism: plain.Mechanism{ |
102 | | - Username: user, |
103 | | - Password: password, |
104 | | - }, |
105 | | - DualStack: true, |
106 | | - TLS: &tls.Config{ |
107 | | - MinVersion: tls.VersionTLS12, |
108 | | - }, |
109 | | - } |
110 | | - |
111 | | - // Create a new Kafka writer |
112 | | - writer := kafka.NewWriter(kafka.WriterConfig{ |
113 | | - Brokers: []string{bootstrapServers}, |
114 | | - Topic: topic, |
115 | | - Balancer: kafka.CRC32Balancer{}, |
116 | | - Dialer: dialer, |
117 | | - }) |
118 | | - |
| 95 | +func NewLogProcessor(bootstrapServers, user, password, topic string) *LogProcessor { |
| 96 | + writer := newWriter(bootstrapServers, user, password, topic) |
119 | 97 | return &LogProcessor{ |
120 | 98 | logs: []LogData{}, |
121 | 99 | writer: writer, |
122 | 100 | topic: topic, |
123 | | - }, nil |
| 101 | + } |
124 | 102 | } |
125 | 103 |
|
126 | 104 | // Start starts LogProcessor which sends events to Kafka in batches. |
127 | 105 | func (lp *LogProcessor) Start(ch chan LogData) { |
128 | | - t := time.NewTicker(KafkaBatchInterval) |
| 106 | + t := time.NewTicker(kafkaBatchInterval) |
129 | 107 | go func() { |
130 | 108 | for { |
131 | 109 | select { |
@@ -156,7 +134,7 @@ func updateMetrics(d LogData) { |
156 | 134 | } |
157 | 135 |
|
158 | 136 | func (p *LogProcessor) sendEvents() { |
159 | | - defer p.logWriteMetrics() |
| 137 | + defer logWriteMetrics(p.writer) |
160 | 138 |
|
161 | 139 | if len(p.logs) > 0 { |
162 | 140 | glog.Infof("sending analytics logs, count=%d", len(p.logs)) |
@@ -184,27 +162,5 @@ func (p *LogProcessor) sendEvents() { |
184 | 162 | } |
185 | 163 | p.logs = []LogData{} |
186 | 164 |
|
187 | | - // We retry sending messages to Kafka in case of a failure |
188 | | - // We don't use any backoff, because the number of events are filling up very quickly, so in case of a failure |
189 | | - // it's better to lose analytics logs than fill up the memory and crash the whole catalyst-api |
190 | | - kafkaWriteRetries := 3 |
191 | | - var err error |
192 | | - for i := 0; i < kafkaWriteRetries; i++ { |
193 | | - err = p.writer.WriteMessages(context.Background(), msgs...) |
194 | | - if err == nil { |
195 | | - return |
196 | | - } else { |
197 | | - glog.Warningf("error while sending analytics log to Kafka, retrying, try=%d, err=%v", i, err) |
198 | | - } |
199 | | - } |
200 | | - metrics.Metrics.AnalyticsMetrics.LogProcessorWriteErrors.Inc() |
201 | | - glog.Errorf("error while sending analytics log to Kafka, the analytics logs are lost, err=%d", err) |
202 | | -} |
203 | | - |
204 | | -func (p *LogProcessor) logWriteMetrics() { |
205 | | - stats := p.writer.Stats() |
206 | | - metrics.Metrics.AnalyticsMetrics.KafkaWriteErrors.Add(float64(stats.Errors)) |
207 | | - metrics.Metrics.AnalyticsMetrics.KafkaWriteMessages.Add(float64(stats.Messages)) |
208 | | - metrics.Metrics.AnalyticsMetrics.KafkaWriteAvgTime.Observe(stats.WriteTime.Avg.Seconds()) |
209 | | - metrics.Metrics.AnalyticsMetrics.KafkaWriteRetries.Add(float64(stats.Retries)) |
| 165 | + sendWithRetries(p.writer, msgs) |
210 | 166 | } |
0 commit comments