summaryrefslogtreecommitdiff
path: root/source.go
diff options
context:
space:
mode:
authordyknon <dyknon@r5f.jp>2025-07-13 22:42:28 +0900
committerdyknon <dyknon@r5f.jp>2025-07-13 22:42:28 +0900
commit86fad60ef2b217cb975983d0d08edf1dcf4ec7cf (patch)
tree6c0c8a51b047c9a1f5fb89e159d00be2a0b1aef8 /source.go
Initial commit
Diffstat (limited to 'source.go')
-rw-r--r--source.go104
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
+}