github.com/verrazzano/verrazzano@v1.7.1/tests/e2e/pkg/test/framework/metrics/search_writer.go (about) 1 // Copyright (c) 2021, 2022, Oracle and/or its affiliates. 2 // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 4 package metrics 5 6 import ( 7 "bytes" 8 "encoding/base64" 9 "fmt" 10 "github.com/hashicorp/go-retryablehttp" 11 "io" 12 "net/http" 13 "os" 14 "time" 15 ) 16 17 // SearchWriter writes to a search endpoint, as an io.Writer and zapcore.WriteSyncer S 18 type SearchWriter struct { 19 hc *retryablehttp.Client 20 url string 21 index string 22 auth string 23 } 24 25 // SearchWriterFromEnv creates a SearchWriter using environment variables 26 func SearchWriterFromEnv(index string) (SearchWriter, error) { 27 uri := os.Getenv(searchURL) 28 if uri == "" { 29 return SearchWriter{}, fmt.Errorf("%s is empty", searchURL) 30 } 31 auth := "" 32 user := os.Getenv(searchUser) 33 pw := os.Getenv(searchPW) 34 if user != "" && pw != "" { 35 auth = base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", user, pw))) 36 } 37 38 return SearchWriter{ 39 hc: retryablehttp.NewClient(), 40 url: uri, 41 index: index, 42 auth: auth, 43 }, nil 44 } 45 46 // Close implement as needed 47 func (s SearchWriter) Close() error { 48 return nil 49 } 50 51 // Sync implement as needed 52 func (s SearchWriter) Sync() error { 53 return nil 54 } 55 56 // postRecord sends the reader record to the search data store via HTTP Post 57 // Basic Authorization is used, if encoded auth is provided for basicAuth 58 func postRecord(hc *retryablehttp.Client, basicAuth, uri string, reader io.Reader) error { 59 req, err := retryablehttp.NewRequest("POST", uri, reader) 60 if err != nil { 61 return err 62 } 63 req.Header.Set("Content-Type", "application/json") 64 65 if basicAuth != "" { // Basic Auth is used if provided 66 req.Header.Set("Authorization", fmt.Sprintf("basic %s", basicAuth)) 67 } 68 resp, err := hc.Do(req) 69 if err != nil { 70 return err 71 } 72 if resp != nil && resp.StatusCode != http.StatusCreated { 73 logger.Errorf("error when posting record[%d: %s]", resp.StatusCode, resp.Status) 74 } 75 return nil 76 } 77 78 // Write out the record to the search data store 79 func (s SearchWriter) Write(data []byte) (int, error) { 80 index := s.timeStampIndex() 81 uri := fmt.Sprintf("%s/%s/_doc", s.url, index) 82 reader := bytes.NewReader(data) 83 if err := postRecord(s.hc, s.auth, uri, reader); err != nil { 84 return 0, err 85 } 86 87 return len(data), nil 88 } 89 90 // timeStampIndex formats the current index in %s-YYYY.mm.dd format 91 func (s SearchWriter) timeStampIndex() string { 92 return fmt.Sprintf("%s-%s", s.index, time.Now().Format(timeFormatString)) 93 }