github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/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 }