diff options
author | dyknon <dyknon@r5f.jp> | 2025-07-13 22:42:28 +0900 |
---|---|---|
committer | dyknon <dyknon@r5f.jp> | 2025-07-13 22:42:28 +0900 |
commit | 86fad60ef2b217cb975983d0d08edf1dcf4ec7cf (patch) | |
tree | 6c0c8a51b047c9a1f5fb89e159d00be2a0b1aef8 /source.go |
Initial commit
Diffstat (limited to 'source.go')
-rw-r--r-- | source.go | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/source.go b/source.go new file mode 100644 index 0000000..353a225 --- /dev/null +++ b/source.go @@ -0,0 +1,104 @@ +package main + +import ( + "strings" + "io" + "fmt" + "os" + "context" + "net" + "net/http" +) + +type Source interface{ + Get() (MetricFamilies, error) +} + +type textSource interface{ + textGet() (io.ReadCloser, string, error) +} +func sourceGetHelper(self textSource) (MetricFamilies, error){ + rc, ty, err := self.textGet() + if err != nil{ + return MetricFamilies{}, + fmt.Errorf("while opening: %w", err) + } + text, err := io.ReadAll(rc) + rc.Close() + if err != nil{ + return MetricFamilies{}, + fmt.Errorf("while reading: %w", err) + } + ret, err := ParseMetrics(text, ty) + if err != nil{ + return MetricFamilies{}, + fmt.Errorf("while parsing: %w", err) + } + return ret, nil +} + +type FileSource string +func (self FileSource) Get() (MetricFamilies, error){ + return sourceGetHelper(self) +} +func (self FileSource) textGet() (io.ReadCloser, string, error){ + f, err := os.Open(string(self)) + if err != nil{ + return nil, "", err + } + return f, "application/openmetrics-text", nil +} + +type HttpSource struct{ + vurl string + client *http.Client +} +func NewHttpSource(loc string) (HttpSource, error){ + return HttpSource{ + vurl: loc, + client: &http.Client{}, + }, nil +} +func NewUnixHttpSource(loc string) (HttpSource, error){ + colon := strings.Index(loc, ":") + if colon < 0 { return HttpSource{}, fmt.Errorf("No protocol part") } + if loc[0:colon] != "unix+http"{ + return HttpSource{}, fmt.Errorf("Invalid protocol") + } + loc = loc[colon+1:] + path := loc + domstart := strings.Index(loc, "//") + if 0 < domstart{ + path = loc[0:domstart] + if strings.Index(loc[domstart+2:], "/") < 0{ + loc = "http:" + loc[domstart:] + "/metrics" + }else{ + loc = "http:" + loc[domstart:] + } + }else{ + loc = "http://0.0.0.0/metrics" + } + tp := http.Transport{ + DialContext: func(c context.Context, _, _ string)(net.Conn, error){ + return (&net.Dialer{}).DialContext(c, "unix", path) + }, + } + return HttpSource{ + vurl: loc, + client: &http.Client{Transport: &tp}, + }, nil +} +func (self HttpSource) Get() (MetricFamilies, error){ + return sourceGetHelper(self) +} +func (self HttpSource) textGet() (io.ReadCloser, string, error){ + r, err := self.client.Get(self.vurl) + if err != nil{ + return nil, "", err + } + if r.StatusCode != 200{ + r.Body.Close() + return nil, "", fmt.Errorf("unexpected response: %s", r.Status) + } + return r.Body, r.Header.Get("Content-Type"), nil +} |