github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/prometheus/procfs/proc_stat.go (about)

     1  // Copyright 2018 The Prometheus Authors
     2  // Licensed under the Apache License, Version 2.0 (the "License");
     3  // you may not use this file except in compliance with the License.
     4  // You may obtain a copy of the License at
     5  //
     6  // http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software
     9  // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package procfs
    15  
    16  import (
    17  	"bytes"
    18  	"fmt"
    19  	"io/ioutil"
    20  	"os"
    21  )
    22  
    23  // Originally, this USER_HZ value was dynamically retrieved via a sysconf call
    24  // which required cgo. However, that caused a lot of problems regarding
    25  // cross-compilation. Alternatives such as running a binary to determine the
    26  // value, or trying to derive it in some other way were all problematic.  After
    27  // much research it was determined that USER_HZ is actually hardcoded to 100 on
    28  // all Go-supported platforms as of the time of this writing. This is why we
    29  // decided to hardcode it here as well. It is not impossible that there could
    30  // be systems with exceptions, but they should be very exotic edge cases, and
    31  // in that case, the worst outcome will be two misreported metrics.
    32  //
    33  // See also the following discussions:
    34  //
    35  // - https://github.com/prometheus/node_exporter/issues/52
    36  // - https://github.com/prometheus/procfs/pull/2
    37  // - http://stackoverflow.com/questions/17410841/how-does-user-hz-solve-the-jiffy-scaling-issue
    38  const userHZ = 100
    39  
    40  // ProcStat provides status information about the process,
    41  // read from /proc/[pid]/stat.
    42  type ProcStat struct {
    43  	// The process ID.
    44  	PID int
    45  	// The filename of the executable.
    46  	Comm string
    47  	// The process state.
    48  	State string
    49  	// The PID of the parent of this process.
    50  	PPID int
    51  	// The process group ID of the process.
    52  	PGRP int
    53  	// The session ID of the process.
    54  	Session int
    55  	// The controlling terminal of the process.
    56  	TTY int
    57  	// The ID of the foreground process group of the controlling terminal of
    58  	// the process.
    59  	TPGID int
    60  	// The kernel flags word of the process.
    61  	Flags uint
    62  	// The number of minor faults the process has made which have not required
    63  	// loading a memory page from disk.
    64  	MinFlt uint
    65  	// The number of minor faults that the process's waited-for children have
    66  	// made.
    67  	CMinFlt uint
    68  	// The number of major faults the process has made which have required
    69  	// loading a memory page from disk.
    70  	MajFlt uint
    71  	// The number of major faults that the process's waited-for children have
    72  	// made.
    73  	CMajFlt uint
    74  	// Amount of time that this process has been scheduled in user mode,
    75  	// measured in clock ticks.
    76  	UTime uint
    77  	// Amount of time that this process has been scheduled in kernel mode,
    78  	// measured in clock ticks.
    79  	STime uint
    80  	// Amount of time that this process's waited-for children have been
    81  	// scheduled in user mode, measured in clock ticks.
    82  	CUTime uint
    83  	// Amount of time that this process's waited-for children have been
    84  	// scheduled in kernel mode, measured in clock ticks.
    85  	CSTime uint
    86  	// For processes running a real-time scheduling policy, this is the negated
    87  	// scheduling priority, minus one.
    88  	Priority int
    89  	// The nice value, a value in the range 19 (low priority) to -20 (high
    90  	// priority).
    91  	Nice int
    92  	// Number of threads in this process.
    93  	NumThreads int
    94  	// The time the process started after system boot, the value is expressed
    95  	// in clock ticks.
    96  	Starttime uint64
    97  	// Virtual memory size in bytes.
    98  	VSize int
    99  	// Resident set size in pages.
   100  	RSS int
   101  
   102  	fs FS
   103  }
   104  
   105  // NewStat returns the current status information of the process.
   106  func (p Proc) NewStat() (ProcStat, error) {
   107  	f, err := os.Open(p.path("stat"))
   108  	if err != nil {
   109  		return ProcStat{}, err
   110  	}
   111  	defer f.Close()
   112  
   113  	data, err := ioutil.ReadAll(f)
   114  	if err != nil {
   115  		return ProcStat{}, err
   116  	}
   117  
   118  	var (
   119  		ignore int
   120  
   121  		s = ProcStat{PID: p.PID, fs: p.fs}
   122  		l = bytes.Index(data, []byte("("))
   123  		r = bytes.LastIndex(data, []byte(")"))
   124  	)
   125  
   126  	if l < 0 || r < 0 {
   127  		return ProcStat{}, fmt.Errorf(
   128  			"unexpected format, couldn't extract comm: %s",
   129  			data,
   130  		)
   131  	}
   132  
   133  	s.Comm = string(data[l+1 : r])
   134  	_, err = fmt.Fscan(
   135  		bytes.NewBuffer(data[r+2:]),
   136  		&s.State,
   137  		&s.PPID,
   138  		&s.PGRP,
   139  		&s.Session,
   140  		&s.TTY,
   141  		&s.TPGID,
   142  		&s.Flags,
   143  		&s.MinFlt,
   144  		&s.CMinFlt,
   145  		&s.MajFlt,
   146  		&s.CMajFlt,
   147  		&s.UTime,
   148  		&s.STime,
   149  		&s.CUTime,
   150  		&s.CSTime,
   151  		&s.Priority,
   152  		&s.Nice,
   153  		&s.NumThreads,
   154  		&ignore,
   155  		&s.Starttime,
   156  		&s.VSize,
   157  		&s.RSS,
   158  	)
   159  	if err != nil {
   160  		return ProcStat{}, err
   161  	}
   162  
   163  	return s, nil
   164  }
   165  
   166  // VirtualMemory returns the virtual memory size in bytes.
   167  func (s ProcStat) VirtualMemory() int {
   168  	return s.VSize
   169  }
   170  
   171  // ResidentMemory returns the resident memory size in bytes.
   172  func (s ProcStat) ResidentMemory() int {
   173  	return s.RSS * os.Getpagesize()
   174  }
   175  
   176  // StartTime returns the unix timestamp of the process in seconds.
   177  func (s ProcStat) StartTime() (float64, error) {
   178  	stat, err := s.fs.NewStat()
   179  	if err != nil {
   180  		return 0, err
   181  	}
   182  	return float64(stat.BootTime) + (float64(s.Starttime) / userHZ), nil
   183  }
   184  
   185  // CPUTime returns the total CPU user and system time in seconds.
   186  func (s ProcStat) CPUTime() float64 {
   187  	return float64(s.UTime+s.STime) / userHZ
   188  }