// PrintAsText outputs all metrics in text format. func (r *Registry) PrintAsText(w io.Writer) error { var metricFamily prometheusgo.MetricFamily var ret error labels := r.getLabels() for _, metric := range r.tracked { metric.Inspect(func(v interface{}) { if ret != nil { return } if prom, ok := v.(PrometheusExportable); ok { metricFamily.Reset() metricFamily.Name = proto.String(exportedName(metric.GetName())) metricFamily.Help = proto.String(metric.GetHelp()) prom.FillPrometheusMetric(&metricFamily) if len(labels) != 0 { // Set labels from registry. We only set one metric in the slice, but loop anyway. for _, m := range metricFamily.Metric { m.Label = labels } } if l := prom.GetLabels(); len(l) != 0 { // Append per-metric labels. for _, m := range metricFamily.Metric { m.Label = append(m.Label, l...) } } if _, err := expfmt.MetricFamilyToText(w, &metricFamily); err != nil { ret = err } } }) } return ret }
// PrintAsText writes all metrics in the families map to the io.Writer in // prometheus' text format. It removes individual metrics from the families // as it goes, readying the families for another found of registry additions. func (pm *PrometheusExporter) PrintAsText(w io.Writer) error { for _, family := range pm.families { if _, err := expfmt.MetricFamilyToText(w, family); err != nil { return err } // Clear metrics for reuse. family.Metric = []*prometheusgo.Metric{} } return nil }
func TestProcessCollector(t *testing.T) { if _, err := procfs.Self(); err != nil { t.Skipf("skipping TestProcessCollector, procfs not available: %s", err) } registry := NewRegistry() if err := registry.Register(NewProcessCollector(os.Getpid(), "")); err != nil { t.Fatal(err) } if err := registry.Register(NewProcessCollectorPIDFn( func() (int, error) { return os.Getpid(), nil }, "foobar"), ); err != nil { t.Fatal(err) } mfs, err := registry.Gather() if err != nil { t.Fatal(err) } var buf bytes.Buffer for _, mf := range mfs { if _, err := expfmt.MetricFamilyToText(&buf, mf); err != nil { t.Fatal(err) } } for _, re := range []*regexp.Regexp{ regexp.MustCompile("\nprocess_cpu_seconds_total [0-9]"), regexp.MustCompile("\nprocess_max_fds [1-9]"), regexp.MustCompile("\nprocess_open_fds [1-9]"), regexp.MustCompile("\nprocess_virtual_memory_bytes [1-9]"), regexp.MustCompile("\nprocess_resident_memory_bytes [1-9]"), regexp.MustCompile("\nprocess_start_time_seconds [0-9.]{10,}"), regexp.MustCompile("\nfoobar_process_cpu_seconds_total [0-9]"), regexp.MustCompile("\nfoobar_process_max_fds [1-9]"), regexp.MustCompile("\nfoobar_process_open_fds [1-9]"), regexp.MustCompile("\nfoobar_process_virtual_memory_bytes [1-9]"), regexp.MustCompile("\nfoobar_process_resident_memory_bytes [1-9]"), regexp.MustCompile("\nfoobar_process_start_time_seconds [0-9.]{10,}"), } { if !re.Match(buf.Bytes()) { t.Errorf("want body to match %s\n%s", re, buf.String()) } } }
// PrintAsText outputs all metrics in text format. func (r *Registry) PrintAsText(w io.Writer) error { var metricFamily prometheusgo.MetricFamily var ret error r.Each(func(name string, v interface{}) { if ret != nil { return } if metric, ok := v.(PrometheusExportable); ok { metricFamily.Reset() metricFamily.Name = proto.String(exportedName(name)) metric.FillPrometheusMetric(&metricFamily) if _, err := expfmt.MetricFamilyToText(w, &metricFamily); err != nil { ret = err } } }) return ret }
func ExampleGatherers() { reg := prometheus.NewRegistry() temp := prometheus.NewGaugeVec( prometheus.GaugeOpts{ Name: "temperature_kelvin", Help: "Temperature in Kelvin.", }, []string{"location"}, ) reg.MustRegister(temp) temp.WithLabelValues("outside").Set(273.14) temp.WithLabelValues("inside").Set(298.44) var parser expfmt.TextParser text := ` # TYPE humidity_percent gauge # HELP humidity_percent Humidity in %. humidity_percent{location="outside"} 45.4 humidity_percent{location="inside"} 33.2 # TYPE temperature_kelvin gauge # HELP temperature_kelvin Temperature in Kelvin. temperature_kelvin{location="somewhere else"} 4.5 ` parseText := func() ([]*dto.MetricFamily, error) { parsed, err := parser.TextToMetricFamilies(strings.NewReader(text)) if err != nil { return nil, err } var result []*dto.MetricFamily for _, mf := range parsed { result = append(result, mf) } return result, nil } gatherers := prometheus.Gatherers{ reg, prometheus.GathererFunc(parseText), } gathering, err := gatherers.Gather() if err != nil { fmt.Println(err) } out := &bytes.Buffer{} for _, mf := range gathering { if _, err := expfmt.MetricFamilyToText(out, mf); err != nil { panic(err) } } fmt.Print(out.String()) fmt.Println("----------") // Note how the temperature_kelvin metric family has been merged from // different sources. Now try text = ` # TYPE humidity_percent gauge # HELP humidity_percent Humidity in %. humidity_percent{location="outside"} 45.4 humidity_percent{location="inside"} 33.2 # TYPE temperature_kelvin gauge # HELP temperature_kelvin Temperature in Kelvin. # Duplicate metric: temperature_kelvin{location="outside"} 265.3 # Wrong labels: temperature_kelvin 4.5 ` gathering, err = gatherers.Gather() if err != nil { fmt.Println(err) } // Note that still as many metrics as possible are returned: out.Reset() for _, mf := range gathering { if _, err := expfmt.MetricFamilyToText(out, mf); err != nil { panic(err) } } fmt.Print(out.String()) // Output: // # HELP humidity_percent Humidity in %. // # TYPE humidity_percent gauge // humidity_percent{location="inside"} 33.2 // humidity_percent{location="outside"} 45.4 // # HELP temperature_kelvin Temperature in Kelvin. // # TYPE temperature_kelvin gauge // temperature_kelvin{location="inside"} 298.44 // temperature_kelvin{location="outside"} 273.14 // temperature_kelvin{location="somewhere else"} 4.5 // ---------- // 2 error(s) occurred: // * collected metric temperature_kelvin label:<name:"location" value:"outside" > gauge:<value:265.3 > was collected before with the same name and label values // * collected metric temperature_kelvin gauge:<value:4.5 > has label dimensions inconsistent with previously collected metrics in the same metric family // # HELP humidity_percent Humidity in %. // # TYPE humidity_percent gauge // humidity_percent{location="inside"} 33.2 // humidity_percent{location="outside"} 45.4 // # HELP temperature_kelvin Temperature in Kelvin. // # TYPE temperature_kelvin gauge // temperature_kelvin{location="inside"} 298.44 // temperature_kelvin{location="outside"} 273.14 }