diff --git a/prometheus/helper.go b/prometheus/helper.go new file mode 100644 index 000000000..ada967b3d --- /dev/null +++ b/prometheus/helper.go @@ -0,0 +1,38 @@ +// Copyright 2020 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package prometheus + +import ( + "fmt" + "io/ioutil" + "strconv" + "strings" +) + +// NewPidFileFn returns a function that retrieves a pid from the specified file. +// It is meant to be used for the PidFn field in ProcessCollectorOpts. +func NewPidFileFn(pidFilePath string) func() (int, error) { + return func() (int, error) { + content, err := ioutil.ReadFile(pidFilePath) + if err != nil { + return 0, fmt.Errorf("can't read pid file %q: %+v", pidFilePath, err) + } + pid, err := strconv.Atoi(strings.TrimSpace(string(content))) + if err != nil { + return 0, fmt.Errorf("can't parse pid file %q: %+v", pidFilePath, err) + } + + return pid, nil + } +} diff --git a/prometheus/helper_test.go b/prometheus/helper_test.go new file mode 100644 index 000000000..9107ab537 --- /dev/null +++ b/prometheus/helper_test.go @@ -0,0 +1,84 @@ +// Copyright 2020 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package prometheus + +import ( + "fmt" + "os" + "path/filepath" + "strings" + "testing" +) + +// TestNewPidFileFn ... +func TestNewPidFileFn(t *testing.T) { + folderPath, err := os.Getwd() + if err != nil { + t.Error("failed to get current path") + } + mockPidFilePath := filepath.Join(folderPath, "mockPidFile") + defer os.Remove(mockPidFilePath) + + testCases := []struct { + mockPidFile func() + expectedErrPrefix string + expectedPid int + desc string + }{ + { + mockPidFile: func() { + os.Remove(mockPidFilePath) + }, + expectedErrPrefix: "can't read pid file", + expectedPid: 0, + desc: "no existed pid file", + }, + { + mockPidFile: func() { + os.Remove(mockPidFilePath) + f, _ := os.Create(mockPidFilePath) + f.Write([]byte("abc")) + f.Close() + }, + expectedErrPrefix: "can't parse pid file", + expectedPid: 0, + desc: "existed pid file, error pid number", + }, + { + mockPidFile: func() { + os.Remove(mockPidFilePath) + f, _ := os.Create(mockPidFilePath) + f.Write([]byte("123")) + f.Close() + }, + expectedErrPrefix: "", + expectedPid: 123, + desc: "existed pid file, correct pid number", + }, + } + + for _, tc := range testCases { + fn := NewPidFileFn(mockPidFilePath) + if fn == nil { + t.Error("Should not get nil PidFileFn") + } + + tc.mockPidFile() + + if pid, err := fn(); pid != tc.expectedPid || (err != nil && !strings.HasPrefix(err.Error(), tc.expectedErrPrefix)) { + fmt.Println(err.Error()) + t.Error(tc.desc) + } + } +}