...

Source file src/github.com/prometheus/procfs/proc_stat.go

Documentation: github.com/prometheus/procfs

     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  	"os"
    20  
    21  	"github.com/prometheus/procfs/internal/util"
    22  )
    23  
    24  // Originally, this USER_HZ value was dynamically retrieved via a sysconf call
    25  // which required cgo. However, that caused a lot of problems regarding
    26  // cross-compilation. Alternatives such as running a binary to determine the
    27  // value, or trying to derive it in some other way were all problematic.  After
    28  // much research it was determined that USER_HZ is actually hardcoded to 100 on
    29  // all Go-supported platforms as of the time of this writing. This is why we
    30  // decided to hardcode it here as well. It is not impossible that there could
    31  // be systems with exceptions, but they should be very exotic edge cases, and
    32  // in that case, the worst outcome will be two misreported metrics.
    33  //
    34  // See also the following discussions:
    35  //
    36  // - https://github.com/prometheus/node_exporter/issues/52
    37  // - https://github.com/prometheus/procfs/pull/2
    38  // - http://stackoverflow.com/questions/17410841/how-does-user-hz-solve-the-jiffy-scaling-issue
    39  const userHZ = 100
    40  
    41  // ProcStat provides status information about the process,
    42  // read from /proc/[pid]/stat.
    43  type ProcStat struct {
    44  	// The process ID.
    45  	PID int
    46  	// The filename of the executable.
    47  	Comm string
    48  	// The process state.
    49  	State string
    50  	// The PID of the parent of this process.
    51  	PPID int
    52  	// The process group ID of the process.
    53  	PGRP int
    54  	// The session ID of the process.
    55  	Session int
    56  	// The controlling terminal of the process.
    57  	TTY int
    58  	// The ID of the foreground process group of the controlling terminal of
    59  	// the process.
    60  	TPGID int
    61  	// The kernel flags word of the process.
    62  	Flags uint
    63  	// The number of minor faults the process has made which have not required
    64  	// loading a memory page from disk.
    65  	MinFlt uint
    66  	// The number of minor faults that the process's waited-for children have
    67  	// made.
    68  	CMinFlt uint
    69  	// The number of major faults the process has made which have required
    70  	// loading a memory page from disk.
    71  	MajFlt uint
    72  	// The number of major faults that the process's waited-for children have
    73  	// made.
    74  	CMajFlt uint
    75  	// Amount of time that this process has been scheduled in user mode,
    76  	// measured in clock ticks.
    77  	UTime uint
    78  	// Amount of time that this process has been scheduled in kernel mode,
    79  	// measured in clock ticks.
    80  	STime uint
    81  	// Amount of time that this process's waited-for children have been
    82  	// scheduled in user mode, measured in clock ticks.
    83  	CUTime int
    84  	// Amount of time that this process's waited-for children have been
    85  	// scheduled in kernel mode, measured in clock ticks.
    86  	CSTime int
    87  	// For processes running a real-time scheduling policy, this is the negated
    88  	// scheduling priority, minus one.
    89  	Priority int
    90  	// The nice value, a value in the range 19 (low priority) to -20 (high
    91  	// priority).
    92  	Nice int
    93  	// Number of threads in this process.
    94  	NumThreads int
    95  	// The time the process started after system boot, the value is expressed
    96  	// in clock ticks.
    97  	Starttime uint64
    98  	// Virtual memory size in bytes.
    99  	VSize uint
   100  	// Resident set size in pages.
   101  	RSS int
   102  	// Soft limit in bytes on the rss of the process.
   103  	RSSLimit uint64
   104  	// CPU number last executed on.
   105  	Processor uint
   106  	// Real-time scheduling priority, a number in the range 1 to 99 for processes
   107  	// scheduled under a real-time policy, or 0, for non-real-time processes.
   108  	RTPriority uint
   109  	// Scheduling policy.
   110  	Policy uint
   111  	// Aggregated block I/O delays, measured in clock ticks (centiseconds).
   112  	DelayAcctBlkIOTicks uint64
   113  	// Guest time of the process (time spent running a virtual CPU for a guest
   114  	// operating system), measured in clock ticks.
   115  	GuestTime int
   116  	// Guest time of the process's children, measured in clock ticks.
   117  	CGuestTime int
   118  
   119  	proc FS
   120  }
   121  
   122  // NewStat returns the current status information of the process.
   123  //
   124  // Deprecated: Use p.Stat() instead.
   125  func (p Proc) NewStat() (ProcStat, error) {
   126  	return p.Stat()
   127  }
   128  
   129  // Stat returns the current status information of the process.
   130  func (p Proc) Stat() (ProcStat, error) {
   131  	data, err := util.ReadFileNoStat(p.path("stat"))
   132  	if err != nil {
   133  		return ProcStat{}, err
   134  	}
   135  
   136  	var (
   137  		ignoreInt64  int64
   138  		ignoreUint64 uint64
   139  
   140  		s = ProcStat{PID: p.PID, proc: p.fs}
   141  		l = bytes.Index(data, []byte("("))
   142  		r = bytes.LastIndex(data, []byte(")"))
   143  	)
   144  
   145  	if l < 0 || r < 0 {
   146  		return ProcStat{}, fmt.Errorf("%w: unexpected format, couldn't extract comm %q", ErrFileParse, data)
   147  	}
   148  
   149  	s.Comm = string(data[l+1 : r])
   150  
   151  	// Check the following resources for the details about the particular stat
   152  	// fields and their data types:
   153  	// * https://man7.org/linux/man-pages/man5/proc.5.html
   154  	// * https://man7.org/linux/man-pages/man3/scanf.3.html
   155  	_, err = fmt.Fscan(
   156  		bytes.NewBuffer(data[r+2:]),
   157  		&s.State,
   158  		&s.PPID,
   159  		&s.PGRP,
   160  		&s.Session,
   161  		&s.TTY,
   162  		&s.TPGID,
   163  		&s.Flags,
   164  		&s.MinFlt,
   165  		&s.CMinFlt,
   166  		&s.MajFlt,
   167  		&s.CMajFlt,
   168  		&s.UTime,
   169  		&s.STime,
   170  		&s.CUTime,
   171  		&s.CSTime,
   172  		&s.Priority,
   173  		&s.Nice,
   174  		&s.NumThreads,
   175  		&ignoreInt64,
   176  		&s.Starttime,
   177  		&s.VSize,
   178  		&s.RSS,
   179  		&s.RSSLimit,
   180  		&ignoreUint64,
   181  		&ignoreUint64,
   182  		&ignoreUint64,
   183  		&ignoreUint64,
   184  		&ignoreUint64,
   185  		&ignoreUint64,
   186  		&ignoreUint64,
   187  		&ignoreUint64,
   188  		&ignoreUint64,
   189  		&ignoreUint64,
   190  		&ignoreUint64,
   191  		&ignoreUint64,
   192  		&ignoreInt64,
   193  		&s.Processor,
   194  		&s.RTPriority,
   195  		&s.Policy,
   196  		&s.DelayAcctBlkIOTicks,
   197  		&s.GuestTime,
   198  		&s.CGuestTime,
   199  	)
   200  	if err != nil {
   201  		return ProcStat{}, err
   202  	}
   203  
   204  	return s, nil
   205  }
   206  
   207  // VirtualMemory returns the virtual memory size in bytes.
   208  func (s ProcStat) VirtualMemory() uint {
   209  	return s.VSize
   210  }
   211  
   212  // ResidentMemory returns the resident memory size in bytes.
   213  func (s ProcStat) ResidentMemory() int {
   214  	return s.RSS * os.Getpagesize()
   215  }
   216  
   217  // StartTime returns the unix timestamp of the process in seconds.
   218  func (s ProcStat) StartTime() (float64, error) {
   219  	stat, err := s.proc.Stat()
   220  	if err != nil {
   221  		return 0, err
   222  	}
   223  	return float64(stat.BootTime) + (float64(s.Starttime) / userHZ), nil
   224  }
   225  
   226  // CPUTime returns the total CPU user and system time in seconds.
   227  func (s ProcStat) CPUTime() float64 {
   228  	return float64(s.UTime+s.STime) / userHZ
   229  }
   230  

View as plain text