diff --git a/modules/prometheus/metadata.yaml b/modules/prometheus/metadata.yaml index 536b3bf66..7fa0eb349 100644 --- a/modules/prometheus/metadata.yaml +++ b/modules/prometheus/metadata.yaml @@ -186,6 +186,13 @@ modules: jobs: - name: local url: http://127.0.0.1:9090/metrics + - name: Read metrics from a file + description: An example configuration to read metrics from a file. + config: | + # use "file://" scheme + jobs: + - name: myapp + url: file:///opt/metrics/myapp/metrics.txt - name: HTTP authentication description: | > **Note**: Change the port of the monitored application on which it provides metrics. diff --git a/pkg/prometheus/client.go b/pkg/prometheus/client.go index aa65a144b..7e359a99e 100644 --- a/pkg/prometheus/client.go +++ b/pkg/prometheus/client.go @@ -9,6 +9,9 @@ import ( "fmt" "io" "net/http" + "net/url" + "os" + "path/filepath" "github.com/netdata/go.d.plugin/pkg/prometheus/selector" "github.com/netdata/go.d.plugin/pkg/web" @@ -24,8 +27,9 @@ type ( } prometheus struct { - client *http.Client - request web.Request + client *http.Client + request web.Request + filepath string sr selector.Selector @@ -53,13 +57,19 @@ func New(client *http.Client, request web.Request) Prometheus { // NewWithSelector creates a Prometheus instance with the selector. func NewWithSelector(client *http.Client, request web.Request, sr selector.Selector) Prometheus { - return &prometheus{ + p := &prometheus{ client: client, request: request, sr: sr, buf: bytes.NewBuffer(make([]byte, 0, 16000)), parser: promTextParser{sr: sr}, } + + if v, err := url.Parse(request.URL); err == nil && v.Scheme == "file" { + p.filepath = filepath.Join(v.Host, v.Path) + } + + return p } func (p *prometheus) HTTPClient() *http.Client { @@ -88,6 +98,19 @@ func (p *prometheus) Scrape() (MetricFamilies, error) { } func (p *prometheus) fetch(w io.Writer) error { + // TODO: should be a separate text file prom client + if p.filepath != "" { + f, err := os.Open(p.filepath) + if err != nil { + return err + } + defer f.Close() + + _, err = io.Copy(w, f) + + return err + } + req, err := web.NewHTTPRequest(p.request) if err != nil { return err diff --git a/pkg/prometheus/client_test.go b/pkg/prometheus/client_test.go index 99931808b..45a68dd64 100644 --- a/pkg/prometheus/client_test.go +++ b/pkg/prometheus/client_test.go @@ -111,6 +111,17 @@ func TestPrometheusGzip(t *testing.T) { } } +func TestPrometheusReadFromFile(t *testing.T) { + req := web.Request{URL: "file://testdata/testdata.txt"} + prom := NewWithSelector(http.DefaultClient, req, nil) + + for i := 0; i < 2; i++ { + res, err := prom.ScrapeSeries() + assert.NoError(t, err) + verifyTestData(t, res) + } +} + func verifyTestData(t *testing.T, ms Series) { assert.Equal(t, 410, len(ms)) assert.Equal(t, "go_gc_duration_seconds", ms[0].Labels.Get("__name__"))