Openstatus www.openstatus.dev
at main 86 lines 2.2 kB view raw
1package tinybird 2 3import ( 4 "bytes" 5 "context" 6 "encoding/json" 7 "fmt" 8 "net/http" 9 "net/url" 10 "os" 11 12 "github.com/rs/zerolog/log" 13) 14 15// Datasource names for Tinybird events 16const ( 17 DatasourceHTTP = "ping_response__v8" 18 DatasourceTCP = "tcp_response__v0" 19 DatasourceDNS = "tcp_dns__v0" 20) 21 22func getBaseURL() string { 23 // Use local Tinybird container if available (Docker/self-hosted) 24 // https://www.tinybird.co/docs/api-reference 25 if tinybirdURL := os.Getenv("TINYBIRD_URL"); tinybirdURL != "" { 26 return tinybirdURL + "/v0/events" 27 } 28 return "https://api.tinybird.co/v0/events" 29} 30 31type Client interface { 32 SendEvent(ctx context.Context, event any, dataSourceName string) error 33} 34 35type client struct { 36 httpClient *http.Client 37 apiKey string 38 baseURL string 39} 40 41func NewClient(httpClient *http.Client, apiKey string) Client { 42 return client{ 43 httpClient: httpClient, 44 apiKey: apiKey, 45 baseURL: getBaseURL(), 46 } 47} 48 49func (c client) SendEvent(ctx context.Context, event any, dataSourceName string) error { 50 requestURL, err := url.Parse(c.baseURL) 51 if err != nil { 52 log.Ctx(ctx).Error().Err(err).Msg("unable to parse url") 53 return fmt.Errorf("unable to parse url: %w", err) 54 } 55 56 q := requestURL.Query() 57 q.Add("name", dataSourceName) 58 requestURL.RawQuery = q.Encode() 59 60 var payload bytes.Buffer 61 if err := json.NewEncoder(&payload).Encode(event); err != nil { 62 log.Ctx(ctx).Error().Err(err).Msg("unable to encode payload") 63 return fmt.Errorf("unable to encode payload: %w", err) 64 } 65 66 req, err := http.NewRequestWithContext(ctx, http.MethodPost, requestURL.String(), bytes.NewReader(payload.Bytes())) 67 if err != nil { 68 log.Ctx(ctx).Error().Err(err).Msg("unable to create request") 69 return fmt.Errorf("unable to create request: %w", err) 70 } 71 req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.apiKey)) 72 73 resp, err := c.httpClient.Do(req) 74 if err != nil { 75 log.Ctx(ctx).Error().Err(err).Msg("unable to send request") 76 return fmt.Errorf("unable to send request: %w", err) 77 } 78 defer resp.Body.Close() 79 80 if resp.StatusCode != http.StatusAccepted { 81 log.Ctx(ctx).Error().Str("status", resp.Status).Msg("unexpected status code") 82 return fmt.Errorf("unexpected status code: %d", resp.StatusCode) 83 } 84 85 return nil 86}