github.com/galamsiva2020/kubernetes-heapster-monitoring@v0.0.0-20210823134957-3c1baa7c1e70/common/honeycomb/honeycomb.go (about) 1 // Copyright 2017 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 honeycomb 16 17 import ( 18 "bytes" 19 "encoding/json" 20 "errors" 21 "io" 22 "io/ioutil" 23 "net/http" 24 "net/url" 25 "os" 26 "path" 27 "strings" 28 "time" 29 30 "github.com/golang/glog" 31 ) 32 33 const maxBatchSize = 100 34 35 type config struct { 36 APIHost string 37 Dataset string 38 WriteKey string 39 } 40 41 func BuildConfig(uri *url.URL) (*config, error) { 42 opts := uri.Query() 43 44 config := &config{ 45 WriteKey: os.Getenv("HONEYCOMB_WRITEKEY"), 46 APIHost: "https://api.honeycomb.io/", 47 Dataset: "heapster", 48 } 49 50 if len(opts["writekey"]) >= 1 { 51 config.WriteKey = opts["writekey"][0] 52 } 53 54 if len(opts["apihost"]) >= 1 { 55 config.APIHost = opts["apihost"][0] 56 } 57 58 if len(opts["dataset"]) >= 1 { 59 config.Dataset = opts["dataset"][0] 60 } 61 62 if config.WriteKey == "" { 63 return nil, errors.New("Failed to find honeycomb API write key") 64 } 65 66 return config, nil 67 } 68 69 type Client interface { 70 SendBatch(batch Batch) error 71 } 72 73 type HoneycombClient struct { 74 config config 75 httpClient http.Client 76 } 77 78 func NewClient(uri *url.URL) (*HoneycombClient, error) { 79 config, err := BuildConfig(uri) 80 if err != nil { 81 return nil, err 82 } 83 return &HoneycombClient{config: *config}, nil 84 } 85 86 type BatchPoint struct { 87 Data interface{} 88 Timestamp time.Time 89 } 90 91 type Batch []*BatchPoint 92 93 func (c *HoneycombClient) sendBatch(batch Batch) error { 94 buf := new(bytes.Buffer) 95 err := json.NewEncoder(buf).Encode(batch) 96 if err != nil { 97 return err 98 } 99 err = c.makeRequest(buf) 100 if err != nil { 101 return err 102 } 103 return nil 104 } 105 106 // SendBatch splits the top-level batch into sub-batches if needed. Otherwise, 107 // requests that are too large will be rejected by the Honeycomb API. 108 func (c *HoneycombClient) SendBatch(batch Batch) error { 109 if len(batch) == 0 { 110 // Nothing to send 111 return nil 112 } 113 114 errs := []string{} 115 for i := 0; i < len(batch); i += maxBatchSize { 116 offset := i + maxBatchSize 117 if offset > len(batch) { 118 offset = len(batch) 119 } 120 if err := c.sendBatch(batch[i:offset]); err != nil { 121 errs = append(errs, err.Error()) 122 } 123 } 124 125 if len(errs) > 0 { 126 return errors.New(strings.Join(errs, "\n")) 127 } 128 129 return nil 130 } 131 132 func (c *HoneycombClient) makeRequest(body io.Reader) error { 133 url, err := url.Parse(c.config.APIHost) 134 if err != nil { 135 return err 136 } 137 url.Path = path.Join(url.Path, "/1/batch", c.config.Dataset) 138 req, err := http.NewRequest("POST", url.String(), body) 139 req.Header.Set("Content-Type", "application/json") 140 req.Header.Add("X-Honeycomb-Team", c.config.WriteKey) 141 142 resp, err := c.httpClient.Do(req) 143 if err != nil { 144 glog.Warningf("Failed to send event: %v", err) 145 return err 146 } 147 defer resp.Body.Close() 148 ioutil.ReadAll(resp.Body) 149 return nil 150 }