github.com/m3db/m3@v1.5.0/src/x/instrument/prom_process_collector_test.go (about)

     1  // Copyright (c) 2019 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package instrument
    22  
    23  import (
    24  	"bytes"
    25  	"errors"
    26  	"os"
    27  	"regexp"
    28  	"testing"
    29  
    30  	"github.com/m3db/prometheus_client_golang/prometheus"
    31  	dto "github.com/m3db/prometheus_client_model/go"
    32  	"github.com/m3db/prometheus_common/expfmt"
    33  	procfs "github.com/m3db/prometheus_procfs"
    34  )
    35  
    36  func TestProcessCollector(t *testing.T) {
    37  	if _, err := procfs.Self(); err != nil {
    38  		t.Skipf("skipping TestProcessCollector, procfs not available: %s", err)
    39  	}
    40  
    41  	registry := prometheus.NewRegistry()
    42  	if err := registry.Register(NewPrometheusProcessCollector(ProcessCollectorOpts{})); err != nil {
    43  		t.Fatal(err)
    44  	}
    45  	if err := registry.Register(NewPrometheusProcessCollector(ProcessCollectorOpts{
    46  		PidFn:        func() (int, error) { return os.Getpid(), nil },
    47  		Namespace:    "foobar",
    48  		ReportErrors: true, // No errors expected, just to see if none are reported.
    49  	})); err != nil {
    50  		t.Fatal(err)
    51  	}
    52  
    53  	mfs, err := registry.Gather()
    54  	if err != nil {
    55  		t.Fatal(err)
    56  	}
    57  
    58  	var buf bytes.Buffer
    59  	for _, mf := range mfs {
    60  		if _, err := expfmt.MetricFamilyToText(&buf, mf); err != nil {
    61  			t.Fatal(err)
    62  		}
    63  	}
    64  
    65  	for _, re := range []*regexp.Regexp{
    66  		regexp.MustCompile("\nprocess_cpu_seconds_total [0-9]"),
    67  		regexp.MustCompile("\nprocess_max_fds [1-9]"),
    68  		regexp.MustCompile("\nprocess_open_fds [1-9]"),
    69  		regexp.MustCompile("\nprocess_virtual_memory_max_bytes (-1|[1-9])"),
    70  		regexp.MustCompile("\nprocess_virtual_memory_bytes [1-9]"),
    71  		regexp.MustCompile("\nprocess_resident_memory_bytes [1-9]"),
    72  		regexp.MustCompile("\nprocess_start_time_seconds [0-9.]{10,}"),
    73  		regexp.MustCompile("\nfoobar_process_cpu_seconds_total [0-9]"),
    74  		regexp.MustCompile("\nfoobar_process_max_fds [1-9]"),
    75  		regexp.MustCompile("\nfoobar_process_open_fds [1-9]"),
    76  		regexp.MustCompile("\nfoobar_process_virtual_memory_max_bytes (-1|[1-9])"),
    77  		regexp.MustCompile("\nfoobar_process_virtual_memory_bytes [1-9]"),
    78  		regexp.MustCompile("\nfoobar_process_resident_memory_bytes [1-9]"),
    79  		regexp.MustCompile("\nfoobar_process_start_time_seconds [0-9.]{10,}"),
    80  	} {
    81  		if !re.Match(buf.Bytes()) {
    82  			t.Errorf("want body to match %s\n%s", re, buf.String())
    83  		}
    84  	}
    85  
    86  	brokenProcessCollector := NewPrometheusProcessCollector(ProcessCollectorOpts{
    87  		PidFn:        func() (int, error) { return 0, errors.New("boo") },
    88  		ReportErrors: true,
    89  	})
    90  
    91  	ch := make(chan prometheus.Metric)
    92  	go func() {
    93  		brokenProcessCollector.Collect(ch)
    94  		close(ch)
    95  	}()
    96  	n := 0
    97  	for m := range ch {
    98  		n++
    99  		pb := &dto.Metric{}
   100  		err := m.Write(pb)
   101  		if err == nil {
   102  			t.Error("metric collected from broken process collector is unexpectedly valid")
   103  		}
   104  	}
   105  	if n != 1 {
   106  		t.Errorf("%d metrics collected, want 1", n)
   107  	}
   108  }