@@ -12,6 +12,7 @@ import (
12
12
elasticV6 "github.com/olivere/elastic"
13
13
elasticV3 "gopkg.in/olivere/elastic.v3"
14
14
elasticV5 "gopkg.in/olivere/elastic.v5"
15
+ elasticV7 "gopkg.in/olivere/elastic.v7"
15
16
16
17
"github.com/qiniu/log"
17
18
"github.com/qiniu/pandora-go-sdk/base/reqerr"
@@ -31,11 +32,13 @@ type Sender struct {
31
32
host []string
32
33
retention int
33
34
indexName string
35
+ idField string
34
36
eType string
35
37
eVersion string
36
38
elasticV3Client * elasticV3.Client
37
39
elasticV5Client * elasticV5.Client
38
40
elasticV6Client * elasticV6.Client
41
+ elasticV7Client * elasticV7.Client
39
42
40
43
aliasFields map [string ]string
41
44
@@ -73,6 +76,7 @@ func NewSender(conf conf.MapConf) (elasticSender sender.Sender, err error) {
73
76
return
74
77
}
75
78
logkitSendTime , _ := conf .GetBoolOr (KeyLogkitSendTime , true )
79
+ idField , _ := conf .GetStringOr (KeyElasticIDField , "" )
76
80
eType , _ := conf .GetStringOr (KeyElasticType , defaultType )
77
81
name , _ := conf .GetStringOr (KeyName , fmt .Sprintf ("elasticSender:(elasticUrl:%s,index:%s,type:%s)" , host , index , eType ))
78
82
fields , _ := conf .GetAliasMapOr (KeyElasticAlias , make (map [string ]string ))
@@ -93,7 +97,24 @@ func NewSender(conf conf.MapConf) (elasticSender sender.Sender, err error) {
93
97
var elasticV3Client * elasticV3.Client
94
98
var elasticV5Client * elasticV5.Client
95
99
var elasticV6Client * elasticV6.Client
100
+ var elasticV7Client * elasticV7.Client
96
101
switch eVersion {
102
+ case ElasticVersion7 :
103
+ optFns := []elasticV7.ClientOptionFunc {
104
+ elasticV7 .SetSniff (false ),
105
+ elasticV7 .SetHealthcheck (false ),
106
+ elasticV7 .SetURL (host ... ),
107
+ elasticV7 .SetGzip (enableGzip ),
108
+ }
109
+
110
+ if len (authUsername ) > 0 && len (authPassword ) > 0 {
111
+ optFns = append (optFns , elasticV7 .SetBasicAuth (authUsername , authPassword ))
112
+ }
113
+
114
+ elasticV7Client , err = elasticV7 .NewClient (optFns ... )
115
+ if err != nil {
116
+ return nil , err
117
+ }
97
118
case ElasticVersion6 :
98
119
optFns := []elasticV6.ClientOptionFunc {
99
120
elasticV6 .SetSniff (false ),
@@ -152,10 +173,12 @@ func NewSender(conf conf.MapConf) (elasticSender sender.Sender, err error) {
152
173
name : name ,
153
174
host : host ,
154
175
indexName : index ,
176
+ idField : idField ,
155
177
eVersion : eVersion ,
156
178
elasticV3Client : elasticV3Client ,
157
179
elasticV5Client : elasticV5Client ,
158
180
elasticV6Client : elasticV6Client ,
181
+ elasticV7Client : elasticV7Client ,
159
182
eType : eType ,
160
183
aliasFields : fields ,
161
184
intervalIndex : i ,
@@ -184,6 +207,78 @@ func (s *Sender) Name() string {
184
207
// Send ElasticSearchSender
185
208
func (s * Sender ) Send (datas []Data ) error {
186
209
switch s .eVersion {
210
+ case ElasticVersion7 :
211
+ bulkService := s .elasticV7Client .Bulk ()
212
+
213
+ makeDoc := true
214
+ if len (s .aliasFields ) == 0 {
215
+ makeDoc = false
216
+ }
217
+ var indexName string
218
+ for _ , doc := range datas {
219
+ //计算索引
220
+ indexName = buildIndexName (s .indexName , s .timeZone , s .intervalIndex )
221
+ //字段名称替换
222
+ if makeDoc {
223
+ doc = s .wrapDoc (doc )
224
+ }
225
+ //添加发送时间
226
+ if s .logkitSendTime {
227
+ doc [KeySendTime ] = time .Now ().In (s .timeZone ).UnixNano () / 1000000
228
+ }
229
+ doc2 := doc
230
+
231
+ request := elasticV7 .NewBulkIndexRequest ().UseEasyJSON (true ).Index (indexName ).Type (s .eType ).Doc (& doc2 )
232
+ id , ok := doc [s .idField ].(string )
233
+ if ok && id != "" {
234
+ request .Id (id )
235
+ }
236
+ bulkService .Add (request )
237
+ }
238
+
239
+ resp , err := bulkService .Do (context .Background ())
240
+ if err != nil {
241
+ return err
242
+ }
243
+
244
+ var (
245
+ // 查找出失败的操作并回溯对应的数据返回给上层
246
+ lastFailedResult * elasticV7.BulkResponseItem
247
+ failedDatas = make ([]map [string ]interface {}, len (datas ))
248
+ failedDatasIdx = 0
249
+ )
250
+ for i , item := range resp .Items {
251
+ for _ , result := range item {
252
+ if ! (result .Status >= 200 && result .Status <= 299 ) {
253
+ failedDatas [failedDatasIdx ] = datas [i ]
254
+ failedDatasIdx ++
255
+ lastFailedResult = result
256
+ break // 任一情况的失败都算该条数据整体操作失败,没有必要重复检查
257
+ }
258
+ }
259
+ }
260
+ failedDatas = failedDatas [:failedDatasIdx ]
261
+ if len (failedDatas ) == 0 {
262
+ return nil
263
+ }
264
+ lastError , err := jsoniter .MarshalToString (lastFailedResult )
265
+ if err != nil {
266
+ lastError = fmt .Sprintf ("marshal to string failed: %v" , lastFailedResult )
267
+ }
268
+
269
+ return & StatsError {
270
+ StatsInfo : StatsInfo {
271
+ Success : int64 (len (datas ) - len (failedDatas )),
272
+ Errors : int64 (len (failedDatas )),
273
+ LastError : lastError ,
274
+ },
275
+ SendError : reqerr .NewSendError (
276
+ fmt .Sprintf ("bulk failed with last error: %s" , lastError ),
277
+ failedDatas ,
278
+ reqerr .TypeBinaryUnpack ,
279
+ ),
280
+ }
281
+
187
282
case ElasticVersion6 :
188
283
bulkService := s .elasticV6Client .Bulk ()
189
284
@@ -204,7 +299,13 @@ func (s *Sender) Send(datas []Data) error {
204
299
doc [KeySendTime ] = time .Now ().In (s .timeZone ).UnixNano () / 1000000
205
300
}
206
301
doc2 := doc
207
- bulkService .Add (elasticV6 .NewBulkIndexRequest ().UseEasyJSON (true ).Index (indexName ).Type (s .eType ).Doc (& doc2 ))
302
+
303
+ request := elasticV6 .NewBulkIndexRequest ().UseEasyJSON (true ).Index (indexName ).Type (s .eType ).Doc (& doc2 )
304
+ id , ok := doc [s .idField ].(string )
305
+ if ok && id != "" {
306
+ request .Id (id )
307
+ }
308
+ bulkService .Add (request )
208
309
}
209
310
210
311
resp , err := bulkService .Do (context .Background ())
@@ -270,7 +371,12 @@ func (s *Sender) Send(datas []Data) error {
270
371
doc [KeySendTime ] = curTime
271
372
}
272
373
doc2 := doc
273
- bulkService .Add (elasticV5 .NewBulkIndexRequest ().Index (indexName ).Type (s .eType ).Doc (& doc2 ))
374
+ request := elasticV5 .NewBulkIndexRequest ().Index (indexName ).Type (s .eType ).Doc (& doc2 )
375
+ id , ok := doc [s .idField ].(string )
376
+ if ok && id != "" {
377
+ request .Id (id )
378
+ }
379
+ bulkService .Add (request )
274
380
}
275
381
276
382
resp , err := bulkService .Do (context .Background ())
@@ -335,7 +441,12 @@ func (s *Sender) Send(datas []Data) error {
335
441
doc [KeySendTime ] = time .Now ().In (s .timeZone ).UnixNano () / 1000000
336
442
}
337
443
doc2 := doc
338
- bulkService .Add (elasticV3 .NewBulkIndexRequest ().Index (indexName ).Type (s .eType ).Doc (& doc2 ))
444
+ request := elasticV3 .NewBulkIndexRequest ().Index (indexName ).Type (s .eType ).Doc (& doc2 )
445
+ id , ok := doc [s .idField ].(string )
446
+ if ok && id != "" {
447
+ request .Id (id )
448
+ }
449
+ bulkService .Add (request )
339
450
}
340
451
341
452
resp , err := bulkService .Do ()
@@ -409,6 +520,9 @@ func (s *Sender) Close() error {
409
520
if s .elasticV6Client != nil {
410
521
s .elasticV6Client .Stop ()
411
522
}
523
+ if s .elasticV7Client != nil {
524
+ s .elasticV7Client .Stop ()
525
+ }
412
526
return nil
413
527
}
414
528
0 commit comments