github.com/caesarxuchao/heapster@v1.1.0/events/sinks/elasticsearch/driver.go (about) 1 // Copyright 2015 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package elasticsearch 16 17 import ( 18 "net/url" 19 "sync" 20 "time" 21 22 "encoding/json" 23 "github.com/golang/glog" 24 "github.com/olivere/elastic" 25 esCommon "k8s.io/heapster/common/elasticsearch" 26 event_core "k8s.io/heapster/events/core" 27 "k8s.io/heapster/metrics/core" 28 kube_api "k8s.io/kubernetes/pkg/api" 29 ) 30 31 const ( 32 typeName = "events" 33 ) 34 35 // LimitFunc is a pluggable function to enforce limits on the object 36 type SaveDataFunc func(esClient *elastic.Client, indexName string, typeName string, sinkData interface{}) error 37 38 type elasticSearchSink struct { 39 esClient *elastic.Client 40 saveDataFunc SaveDataFunc 41 esConfig esCommon.ElasticSearchConfig 42 sync.RWMutex 43 } 44 45 type EsSinkPoint struct { 46 EventValue interface{} 47 EventTimestamp time.Time 48 EventTags map[string]string 49 } 50 51 // Generate point value for event 52 func getEventValue(event *kube_api.Event) (string, error) { 53 // TODO: check whether indenting is required. 54 bytes, err := json.MarshalIndent(event, "", " ") 55 if err != nil { 56 return "", err 57 } 58 return string(bytes), nil 59 } 60 61 func eventToPoint(event *kube_api.Event) (*EsSinkPoint, error) { 62 value, err := getEventValue(event) 63 if err != nil { 64 return nil, err 65 } 66 point := EsSinkPoint{ 67 EventTimestamp: event.LastTimestamp.Time.UTC(), 68 EventValue: value, 69 EventTags: map[string]string{ 70 "eventID": string(event.UID), 71 }, 72 } 73 if event.InvolvedObject.Kind == "Pod" { 74 point.EventTags[core.LabelPodId.Key] = string(event.InvolvedObject.UID) 75 point.EventTags[core.LabelPodName.Key] = event.InvolvedObject.Name 76 } 77 point.EventTags[core.LabelHostname.Key] = event.Source.Host 78 return &point, nil 79 } 80 81 func (sink *elasticSearchSink) ExportEvents(eventBatch *event_core.EventBatch) { 82 sink.Lock() 83 defer sink.Unlock() 84 for _, event := range eventBatch.Events { 85 point, err := eventToPoint(event) 86 if err != nil { 87 glog.Warningf("Failed to convert event to point: %v", err) 88 } 89 sink.saveDataFunc(sink.esClient, sink.esConfig.Index, typeName, point) 90 } 91 } 92 93 func (sink *elasticSearchSink) Name() string { 94 return "ElasticSearch Sink" 95 } 96 97 func (sink *elasticSearchSink) Stop() { 98 // nothing needs to be done. 99 } 100 101 func NewElasticSearchSink(uri *url.URL) (event_core.EventSink, error) { 102 var esSink elasticSearchSink 103 elasticsearchConfig, err := esCommon.CreateElasticSearchConfig(uri) 104 if err != nil { 105 glog.V(2).Infof("failed to config elasticsearch") 106 return nil, err 107 108 } 109 esSink.esConfig = *elasticsearchConfig 110 esSink.saveDataFunc = esCommon.SaveDataIntoES 111 glog.V(2).Infof("elasticsearch sink setup successfully") 112 return &esSink, nil 113 }