// NewEncoder returns a new encoder based on content type negotiation. func NewEncoder(w io.Writer, format Format) Encoder { switch format { case FmtProtoDelim: return encoder(func(v *dto.MetricFamily) error { _, err := pbutil.WriteDelimited(w, v) return err }) case FmtProtoCompact: return encoder(func(v *dto.MetricFamily) error { _, err := fmt.Fprintln(w, v.String()) return err }) case FmtProtoText: return encoder(func(v *dto.MetricFamily) error { _, err := fmt.Fprintln(w, proto.MarshalTextString(v)) return err }) case FmtText: return encoder(func(v *dto.MetricFamily) error { _, err := MetricFamilyToText(w, v) return err }) } panic("expfmt.NewEncoder: unknown format") }
// Encode implements the mesh.GossipData interface. func (gd gossipData) Encode() [][]byte { // Split into sub-messages of ~1MB. const maxSize = 1024 * 1024 var ( buf bytes.Buffer res [][]byte n int ) for _, s := range gd { m, err := pbutil.WriteDelimited(&buf, s) n += m if err != nil { // TODO(fabxc): log error and skip entry. Or can this really not happen with a bytes.Buffer? panic(err) } if n > maxSize { res = append(res, buf.Bytes()) buf = bytes.Buffer{} } } if buf.Len() > 0 { res = append(res, buf.Bytes()) } return res }
func (m *marshaller) Marshal(entry *Entry) ([]byte, error) { buffer := bytes.NewBuffer(nil) if _, err := pbutil.WriteDelimited(buffer, entry); err != nil { return nil, err } return buffer.Bytes(), nil }
func (m *delimitedMarshaller) Marshal(entry *Entry) ([]byte, error) { pbEntry, err := entryToPBEntry(entry) if err != nil { return nil, err } buffer := bytes.NewBuffer(nil) if _, err := pbutil.WriteDelimited(buffer, pbEntry); err != nil { return nil, err } return buffer.Bytes(), nil }
// Snapshot writes the full internal state into the writer and returns the number of bytes // written. func (s *Silences) Snapshot(w io.Writer) (int, error) { s.mtx.RLock() defer s.mtx.RUnlock() var n int for _, s := range s.st { m, err := pbutil.WriteDelimited(w, s) if err != nil { return n + m, err } n += m } return n, nil }
// Snapshot implements the Log interface. func (l *nlog) Snapshot(w io.Writer) (int, error) { l.mtx.RLock() defer l.mtx.RUnlock() var n int for _, e := range l.st { m, err := pbutil.WriteDelimited(w, e) if err != nil { return n + m, err } n += m } return n, nil }
// Snapshot writes the full internal state into the writer and returns the number of bytes // written. func (s *Silences) Snapshot(w io.Writer) (int, error) { start := time.Now() defer func() { s.metrics.snapshotDuration.Observe(time.Since(start).Seconds()) }() s.mtx.Lock() defer s.mtx.Unlock() var n int for _, s := range s.st { m, err := pbutil.WriteDelimited(w, s) if err != nil { return n + m, err } n += m } return n, nil }
// Snapshot implements the Log interface. func (l *nlog) Snapshot(w io.Writer) (int, error) { start := time.Now() defer func() { l.metrics.snapshotDuration.Observe(time.Since(start).Seconds()) }() l.mtx.RLock() defer l.mtx.RUnlock() var n int for _, e := range l.st { m, err := pbutil.WriteDelimited(w, e) if err != nil { return n + m, err } n += m } return n, nil }
// WriteProtoDelimited writes the MetricFamily to the writer in delimited // protobuf format and returns the number of bytes written and any error // encountered. func WriteProtoDelimited(w io.Writer, p *dto.MetricFamily) (int, error) { return pbutil.WriteDelimited(w, p) }
func TestPush(t *testing.T) { mms := MockMetricStore{} handler := Push(&mms, false, map[string]struct{}{"required_label": struct{}{}}) legacyHandler := LegacyPush(&mms, false, map[string]struct{}{"required_label": struct{}{}}) req, err := http.NewRequest("POST", "http://example.org/", &bytes.Buffer{}) if err != nil { t.Fatal(err) } // No job name. w := httptest.NewRecorder() handler(w, req, httprouter.Params{}) if expected, got := http.StatusBadRequest, w.Code; expected != got { t.Errorf("Wanted status code %v, got %v.", expected, got) } if !mms.lastWriteRequest.Timestamp.IsZero() { t.Errorf("Write request timestamp unexpectedly set: %#v", mms.lastWriteRequest) } // With job name, but no instance name and no content. mms.lastWriteRequest = storage.WriteRequest{} w = httptest.NewRecorder() handler(w, req, httprouter.Params{httprouter.Param{Key: "job", Value: "testjob"}}) if expected, got := http.StatusAccepted, w.Code; expected != got { t.Errorf("Wanted status code %v, got %v.", expected, got) } if mms.lastWriteRequest.Timestamp.IsZero() { t.Errorf("Write request timestamp not set: %#v", mms.lastWriteRequest) } if expected, got := "testjob", mms.lastWriteRequest.Labels["job"]; expected != got { t.Errorf("Wanted job %v, got %v.", expected, got) } if expected, got := "", mms.lastWriteRequest.Labels["instance"]; expected != got { t.Errorf("Wanted instance %v, got %v.", expected, got) } // With job name, but no instance name and no content, legacy handler. mms.lastWriteRequest = storage.WriteRequest{} w = httptest.NewRecorder() legacyHandler(w, req, httprouter.Params{httprouter.Param{Key: "job", Value: "testjob"}}) if expected, got := http.StatusAccepted, w.Code; expected != got { t.Errorf("Wanted status code %v, got %v.", expected, got) } if mms.lastWriteRequest.Timestamp.IsZero() { t.Errorf("Write request timestamp not set: %#v", mms.lastWriteRequest) } if expected, got := "testjob", mms.lastWriteRequest.Labels["job"]; expected != got { t.Errorf("Wanted job %v, got %v.", expected, got) } if expected, got := "localhost", mms.lastWriteRequest.Labels["instance"]; expected != got { t.Errorf("Wanted instance %v, got %v.", expected, got) } // With job name and instance name and invalid text content. mms.lastWriteRequest = storage.WriteRequest{} req, err = http.NewRequest( "POST", "http://example.org/", bytes.NewBufferString("blablabla\n"), ) if err != nil { t.Fatal(err) } w = httptest.NewRecorder() handler( w, req, httprouter.Params{ httprouter.Param{Key: "job", Value: "testjob"}, httprouter.Param{Key: "instance", Value: "testinstance"}, }, ) if expected, got := http.StatusInternalServerError, w.Code; expected != got { t.Errorf("Wanted status code %v, got %v.", expected, got) } if !mms.lastWriteRequest.Timestamp.IsZero() { t.Errorf("Write request timestamp unexpectedly set: %#v", mms.lastWriteRequest) } // With job name and instance name and text content. mms.lastWriteRequest = storage.WriteRequest{} req, err = http.NewRequest( "POST", "http://example.org/", bytes.NewBufferString("some_metric 3.14\nanother_metric 42\n"), ) if err != nil { t.Fatal(err) } w = httptest.NewRecorder() handler( w, req, httprouter.Params{ httprouter.Param{Key: "job", Value: "testjob"}, httprouter.Param{Key: "labels", Value: "/instance/testinstance"}, }, ) if expected, got := http.StatusAccepted, w.Code; expected != got { t.Errorf("Wanted status code %v, got %v.", expected, got) } if mms.lastWriteRequest.Timestamp.IsZero() { t.Errorf("Write request timestamp not set: %#v", mms.lastWriteRequest) } if expected, got := "testjob", mms.lastWriteRequest.Labels["job"]; expected != got { t.Errorf("Wanted job %v, got %v.", expected, got) } if expected, got := "testinstance", mms.lastWriteRequest.Labels["instance"]; expected != got { t.Errorf("Wanted instance %v, got %v.", expected, got) } if expected, got := `name:"some_metric" type:UNTYPED metric:<label:<name:"instance" value:"testinstance" > label:<name:"job" value:"testjob" > label:<name:"required_label" value:"" > untyped:<value:3.14 > > `, mms.lastWriteRequest.MetricFamilies["some_metric"].String(); expected != got { t.Errorf("Wanted metric family %v, got %v.", expected, got) } if expected, got := `name:"another_metric" type:UNTYPED metric:<label:<name:"instance" value:"testinstance" > label:<name:"job" value:"testjob" > label:<name:"required_label" value:"" > untyped:<value:42 > > `, mms.lastWriteRequest.MetricFamilies["another_metric"].String(); expected != got { t.Errorf("Wanted metric family %v, got %v.", expected, got) } // With job name and instance name and text content, legacy handler. mms.lastWriteRequest = storage.WriteRequest{} req, err = http.NewRequest( "POST", "http://example.org/", bytes.NewBufferString("some_metric 3.14\nanother_metric 42\n"), ) if err != nil { t.Fatal(err) } w = httptest.NewRecorder() legacyHandler( w, req, httprouter.Params{ httprouter.Param{Key: "job", Value: "testjob"}, httprouter.Param{Key: "instance", Value: "testinstance"}, }, ) if expected, got := http.StatusAccepted, w.Code; expected != got { t.Errorf("Wanted status code %v, got %v.", expected, got) } if mms.lastWriteRequest.Timestamp.IsZero() { t.Errorf("Write request timestamp not set: %#v", mms.lastWriteRequest) } if expected, got := "testjob", mms.lastWriteRequest.Labels["job"]; expected != got { t.Errorf("Wanted job %v, got %v.", expected, got) } if expected, got := "testinstance", mms.lastWriteRequest.Labels["instance"]; expected != got { t.Errorf("Wanted instance %v, got %v.", expected, got) } if expected, got := `name:"some_metric" type:UNTYPED metric:<label:<name:"instance" value:"testinstance" > label:<name:"job" value:"testjob" > label:<name:"required_label" value:"" > untyped:<value:3.14 > > `, mms.lastWriteRequest.MetricFamilies["some_metric"].String(); expected != got { t.Errorf("Wanted metric family %v, got %v.", expected, got) } if expected, got := `name:"another_metric" type:UNTYPED metric:<label:<name:"instance" value:"testinstance" > label:<name:"job" value:"testjob" > label:<name:"required_label" value:"" > untyped:<value:42 > > `, mms.lastWriteRequest.MetricFamilies["another_metric"].String(); expected != got { t.Errorf("Wanted metric family %v, got %v.", expected, got) } // With job name and instance name and text content and job and instance labels. mms.lastWriteRequest = storage.WriteRequest{} req, err = http.NewRequest( "POST", "http://example.org", bytes.NewBufferString(` some_metric{job="foo",instance="bar"} 3.14 another_metric{instance="baz"} 42 `), ) if err != nil { t.Fatal(err) } w = httptest.NewRecorder() handler( w, req, httprouter.Params{ httprouter.Param{Key: "job", Value: "testjob"}, httprouter.Param{Key: "labels", Value: "/instance/testinstance"}, }, ) if expected, got := http.StatusAccepted, w.Code; expected != got { t.Errorf("Wanted status code %v, got %v.", expected, got) } if mms.lastWriteRequest.Timestamp.IsZero() { t.Errorf("Write request timestamp not set: %#v", mms.lastWriteRequest) } if expected, got := "testjob", mms.lastWriteRequest.Labels["job"]; expected != got { t.Errorf("Wanted job %v, got %v.", expected, got) } if expected, got := "testinstance", mms.lastWriteRequest.Labels["instance"]; expected != got { t.Errorf("Wanted instance %v, got %v.", expected, got) } if expected, got := `name:"some_metric" type:UNTYPED metric:<label:<name:"instance" value:"testinstance" > label:<name:"job" value:"testjob" > label:<name:"required_label" value:"" > untyped:<value:3.14 > > `, mms.lastWriteRequest.MetricFamilies["some_metric"].String(); expected != got { t.Errorf("Wanted metric family %v, got %v.", expected, got) } if expected, got := `name:"another_metric" type:UNTYPED metric:<label:<name:"instance" value:"testinstance" > label:<name:"job" value:"testjob" > label:<name:"required_label" value:"" > untyped:<value:42 > > `, mms.lastWriteRequest.MetricFamilies["another_metric"].String(); expected != got { t.Errorf("Wanted metric family %v, got %v.", expected, got) } // With job name and instance name and protobuf content. mms.lastWriteRequest = storage.WriteRequest{} buf := &bytes.Buffer{} _, err = pbutil.WriteDelimited(buf, &dto.MetricFamily{ Name: proto.String("some_metric"), Type: dto.MetricType_UNTYPED.Enum(), Metric: []*dto.Metric{ &dto.Metric{ Untyped: &dto.Untyped{ Value: proto.Float64(1.234), }, }, }, }) if err != nil { t.Fatal(err) } _, err = pbutil.WriteDelimited(buf, &dto.MetricFamily{ Name: proto.String("another_metric"), Type: dto.MetricType_UNTYPED.Enum(), Metric: []*dto.Metric{ &dto.Metric{ Untyped: &dto.Untyped{ Value: proto.Float64(3.14), }, }, }, }) if err != nil { t.Fatal(err) } req, err = http.NewRequest( "POST", "http://example.org/", buf, ) if err != nil { t.Fatal(err) } req.Header.Set("Content-Type", "application/vnd.google.protobuf; encoding=delimited; proto=io.prometheus.client.MetricFamily") w = httptest.NewRecorder() handler( w, req, httprouter.Params{ httprouter.Param{Key: "job", Value: "testjob"}, httprouter.Param{Key: "labels", Value: "/instance/testinstance"}, }, ) if expected, got := http.StatusAccepted, w.Code; expected != got { t.Errorf("Wanted status code %v, got %v.", expected, got) } if mms.lastWriteRequest.Timestamp.IsZero() { t.Errorf("Write request timestamp not set: %#v", mms.lastWriteRequest) } if expected, got := "testjob", mms.lastWriteRequest.Labels["job"]; expected != got { t.Errorf("Wanted job %v, got %v.", expected, got) } if expected, got := "testinstance", mms.lastWriteRequest.Labels["instance"]; expected != got { t.Errorf("Wanted instance %v, got %v.", expected, got) } if expected, got := `name:"some_metric" type:UNTYPED metric:<label:<name:"instance" value:"testinstance" > label:<name:"job" value:"testjob" > label:<name:"required_label" value:"" > untyped:<value:1.234 > > `, mms.lastWriteRequest.MetricFamilies["some_metric"].String(); expected != got { t.Errorf("Wanted metric family %v, got %v.", expected, got) } if expected, got := `name:"another_metric" type:UNTYPED metric:<label:<name:"instance" value:"testinstance" > label:<name:"job" value:"testjob" > label:<name:"required_label" value:"" > untyped:<value:3.14 > > `, mms.lastWriteRequest.MetricFamilies["another_metric"].String(); expected != got { t.Errorf("Wanted metric family %v, got %v.", expected, got) } }