422 lines
15 KiB
Go
422 lines
15 KiB
Go
// Copyright 2019 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 procfs
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/prometheus/procfs/internal/util"
|
|
)
|
|
|
|
// Fscacheinfo represents fscache statistics.
|
|
type Fscacheinfo struct {
|
|
// Number of index cookies allocated
|
|
IndexCookiesAllocated uint64
|
|
// data storage cookies allocated
|
|
DataStorageCookiesAllocated uint64
|
|
// Number of special cookies allocated
|
|
SpecialCookiesAllocated uint64
|
|
// Number of objects allocated
|
|
ObjectsAllocated uint64
|
|
// Number of object allocation failures
|
|
ObjectAllocationsFailure uint64
|
|
// Number of objects that reached the available state
|
|
ObjectsAvailable uint64
|
|
// Number of objects that reached the dead state
|
|
ObjectsDead uint64
|
|
// Number of objects that didn't have a coherency check
|
|
ObjectsWithoutCoherencyCheck uint64
|
|
// Number of objects that passed a coherency check
|
|
ObjectsWithCoherencyCheck uint64
|
|
// Number of objects that needed a coherency data update
|
|
ObjectsNeedCoherencyCheckUpdate uint64
|
|
// Number of objects that were declared obsolete
|
|
ObjectsDeclaredObsolete uint64
|
|
// Number of pages marked as being cached
|
|
PagesMarkedAsBeingCached uint64
|
|
// Number of uncache page requests seen
|
|
UncachePagesRequestSeen uint64
|
|
// Number of acquire cookie requests seen
|
|
AcquireCookiesRequestSeen uint64
|
|
// Number of acq reqs given a NULL parent
|
|
AcquireRequestsWithNullParent uint64
|
|
// Number of acq reqs rejected due to no cache available
|
|
AcquireRequestsRejectedNoCacheAvailable uint64
|
|
// Number of acq reqs succeeded
|
|
AcquireRequestsSucceeded uint64
|
|
// Number of acq reqs rejected due to error
|
|
AcquireRequestsRejectedDueToError uint64
|
|
// Number of acq reqs failed on ENOMEM
|
|
AcquireRequestsFailedDueToEnomem uint64
|
|
// Number of lookup calls made on cache backends
|
|
LookupsNumber uint64
|
|
// Number of negative lookups made
|
|
LookupsNegative uint64
|
|
// Number of positive lookups made
|
|
LookupsPositive uint64
|
|
// Number of objects created by lookup
|
|
ObjectsCreatedByLookup uint64
|
|
// Number of lookups timed out and requeued
|
|
LookupsTimedOutAndRequed uint64
|
|
InvalidationsNumber uint64
|
|
InvalidationsRunning uint64
|
|
// Number of update cookie requests seen
|
|
UpdateCookieRequestSeen uint64
|
|
// Number of upd reqs given a NULL parent
|
|
UpdateRequestsWithNullParent uint64
|
|
// Number of upd reqs granted CPU time
|
|
UpdateRequestsRunning uint64
|
|
// Number of relinquish cookie requests seen
|
|
RelinquishCookiesRequestSeen uint64
|
|
// Number of rlq reqs given a NULL parent
|
|
RelinquishCookiesWithNullParent uint64
|
|
// Number of rlq reqs waited on completion of creation
|
|
RelinquishRequestsWaitingCompleteCreation uint64
|
|
// Relinqs rtr
|
|
RelinquishRetries uint64
|
|
// Number of attribute changed requests seen
|
|
AttributeChangedRequestsSeen uint64
|
|
// Number of attr changed requests queued
|
|
AttributeChangedRequestsQueued uint64
|
|
// Number of attr changed rejected -ENOBUFS
|
|
AttributeChangedRejectDueToEnobufs uint64
|
|
// Number of attr changed failed -ENOMEM
|
|
AttributeChangedFailedDueToEnomem uint64
|
|
// Number of attr changed ops given CPU time
|
|
AttributeChangedOps uint64
|
|
// Number of allocation requests seen
|
|
AllocationRequestsSeen uint64
|
|
// Number of successful alloc reqs
|
|
AllocationOkRequests uint64
|
|
// Number of alloc reqs that waited on lookup completion
|
|
AllocationWaitingOnLookup uint64
|
|
// Number of alloc reqs rejected -ENOBUFS
|
|
AllocationsRejectedDueToEnobufs uint64
|
|
// Number of alloc reqs aborted -ERESTARTSYS
|
|
AllocationsAbortedDueToErestartsys uint64
|
|
// Number of alloc reqs submitted
|
|
AllocationOperationsSubmitted uint64
|
|
// Number of alloc reqs waited for CPU time
|
|
AllocationsWaitedForCPU uint64
|
|
// Number of alloc reqs aborted due to object death
|
|
AllocationsAbortedDueToObjectDeath uint64
|
|
// Number of retrieval (read) requests seen
|
|
RetrievalsReadRequests uint64
|
|
// Number of successful retr reqs
|
|
RetrievalsOk uint64
|
|
// Number of retr reqs that waited on lookup completion
|
|
RetrievalsWaitingLookupCompletion uint64
|
|
// Number of retr reqs returned -ENODATA
|
|
RetrievalsReturnedEnodata uint64
|
|
// Number of retr reqs rejected -ENOBUFS
|
|
RetrievalsRejectedDueToEnobufs uint64
|
|
// Number of retr reqs aborted -ERESTARTSYS
|
|
RetrievalsAbortedDueToErestartsys uint64
|
|
// Number of retr reqs failed -ENOMEM
|
|
RetrievalsFailedDueToEnomem uint64
|
|
// Number of retr reqs submitted
|
|
RetrievalsRequests uint64
|
|
// Number of retr reqs waited for CPU time
|
|
RetrievalsWaitingCPU uint64
|
|
// Number of retr reqs aborted due to object death
|
|
RetrievalsAbortedDueToObjectDeath uint64
|
|
// Number of storage (write) requests seen
|
|
StoreWriteRequests uint64
|
|
// Number of successful store reqs
|
|
StoreSuccessfulRequests uint64
|
|
// Number of store reqs on a page already pending storage
|
|
StoreRequestsOnPendingStorage uint64
|
|
// Number of store reqs rejected -ENOBUFS
|
|
StoreRequestsRejectedDueToEnobufs uint64
|
|
// Number of store reqs failed -ENOMEM
|
|
StoreRequestsFailedDueToEnomem uint64
|
|
// Number of store reqs submitted
|
|
StoreRequestsSubmitted uint64
|
|
// Number of store reqs granted CPU time
|
|
StoreRequestsRunning uint64
|
|
// Number of pages given store req processing time
|
|
StorePagesWithRequestsProcessing uint64
|
|
// Number of store reqs deleted from tracking tree
|
|
StoreRequestsDeleted uint64
|
|
// Number of store reqs over store limit
|
|
StoreRequestsOverStoreLimit uint64
|
|
// Number of release reqs against pages with no pending store
|
|
ReleaseRequestsAgainstPagesWithNoPendingStorage uint64
|
|
// Number of release reqs against pages stored by time lock granted
|
|
ReleaseRequestsAgainstPagesStoredByTimeLockGranted uint64
|
|
// Number of release reqs ignored due to in-progress store
|
|
ReleaseRequestsIgnoredDueToInProgressStore uint64
|
|
// Number of page stores cancelled due to release req
|
|
PageStoresCancelledByReleaseRequests uint64
|
|
VmscanWaiting uint64
|
|
// Number of times async ops added to pending queues
|
|
OpsPending uint64
|
|
// Number of times async ops given CPU time
|
|
OpsRunning uint64
|
|
// Number of times async ops queued for processing
|
|
OpsEnqueued uint64
|
|
// Number of async ops cancelled
|
|
OpsCancelled uint64
|
|
// Number of async ops rejected due to object lookup/create failure
|
|
OpsRejected uint64
|
|
// Number of async ops initialised
|
|
OpsInitialised uint64
|
|
// Number of async ops queued for deferred release
|
|
OpsDeferred uint64
|
|
// Number of async ops released (should equal ini=N when idle)
|
|
OpsReleased uint64
|
|
// Number of deferred-release async ops garbage collected
|
|
OpsGarbageCollected uint64
|
|
// Number of in-progress alloc_object() cache ops
|
|
CacheopAllocationsinProgress uint64
|
|
// Number of in-progress lookup_object() cache ops
|
|
CacheopLookupObjectInProgress uint64
|
|
// Number of in-progress lookup_complete() cache ops
|
|
CacheopLookupCompleteInPorgress uint64
|
|
// Number of in-progress grab_object() cache ops
|
|
CacheopGrabObjectInProgress uint64
|
|
CacheopInvalidations uint64
|
|
// Number of in-progress update_object() cache ops
|
|
CacheopUpdateObjectInProgress uint64
|
|
// Number of in-progress drop_object() cache ops
|
|
CacheopDropObjectInProgress uint64
|
|
// Number of in-progress put_object() cache ops
|
|
CacheopPutObjectInProgress uint64
|
|
// Number of in-progress attr_changed() cache ops
|
|
CacheopAttributeChangeInProgress uint64
|
|
// Number of in-progress sync_cache() cache ops
|
|
CacheopSyncCacheInProgress uint64
|
|
// Number of in-progress read_or_alloc_page() cache ops
|
|
CacheopReadOrAllocPageInProgress uint64
|
|
// Number of in-progress read_or_alloc_pages() cache ops
|
|
CacheopReadOrAllocPagesInProgress uint64
|
|
// Number of in-progress allocate_page() cache ops
|
|
CacheopAllocatePageInProgress uint64
|
|
// Number of in-progress allocate_pages() cache ops
|
|
CacheopAllocatePagesInProgress uint64
|
|
// Number of in-progress write_page() cache ops
|
|
CacheopWritePagesInProgress uint64
|
|
// Number of in-progress uncache_page() cache ops
|
|
CacheopUncachePagesInProgress uint64
|
|
// Number of in-progress dissociate_pages() cache ops
|
|
CacheopDissociatePagesInProgress uint64
|
|
// Number of object lookups/creations rejected due to lack of space
|
|
CacheevLookupsAndCreationsRejectedLackSpace uint64
|
|
// Number of stale objects deleted
|
|
CacheevStaleObjectsDeleted uint64
|
|
// Number of objects retired when relinquished
|
|
CacheevRetiredWhenReliquished uint64
|
|
// Number of objects culled
|
|
CacheevObjectsCulled uint64
|
|
}
|
|
|
|
// Fscacheinfo returns information about current fscache statistics.
|
|
// See https://www.kernel.org/doc/Documentation/filesystems/caching/fscache.txt
|
|
func (fs FS) Fscacheinfo() (Fscacheinfo, error) {
|
|
b, err := util.ReadFileNoStat(fs.proc.Path("fs/fscache/stats"))
|
|
if err != nil {
|
|
return Fscacheinfo{}, err
|
|
}
|
|
|
|
m, err := parseFscacheinfo(bytes.NewReader(b))
|
|
if err != nil {
|
|
return Fscacheinfo{}, fmt.Errorf("failed to parse Fscacheinfo: %w", err)
|
|
}
|
|
|
|
return *m, nil
|
|
}
|
|
|
|
func setFSCacheFields(fields []string, setFields ...*uint64) error {
|
|
var err error
|
|
if len(fields) < len(setFields) {
|
|
return fmt.Errorf("Insufficient number of fields, expected %v, got %v", len(setFields), len(fields))
|
|
}
|
|
|
|
for i := range setFields {
|
|
*setFields[i], err = strconv.ParseUint(strings.Split(fields[i], "=")[1], 0, 64)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func parseFscacheinfo(r io.Reader) (*Fscacheinfo, error) {
|
|
var m Fscacheinfo
|
|
s := bufio.NewScanner(r)
|
|
for s.Scan() {
|
|
fields := strings.Fields(s.Text())
|
|
if len(fields) < 2 {
|
|
return nil, fmt.Errorf("malformed Fscacheinfo line: %q", s.Text())
|
|
}
|
|
|
|
switch fields[0] {
|
|
case "Cookies:":
|
|
err := setFSCacheFields(fields[1:], &m.IndexCookiesAllocated, &m.DataStorageCookiesAllocated,
|
|
&m.SpecialCookiesAllocated)
|
|
if err != nil {
|
|
return &m, err
|
|
}
|
|
case "Objects:":
|
|
err := setFSCacheFields(fields[1:], &m.ObjectsAllocated, &m.ObjectAllocationsFailure,
|
|
&m.ObjectsAvailable, &m.ObjectsDead)
|
|
if err != nil {
|
|
return &m, err
|
|
}
|
|
case "ChkAux":
|
|
err := setFSCacheFields(fields[2:], &m.ObjectsWithoutCoherencyCheck, &m.ObjectsWithCoherencyCheck,
|
|
&m.ObjectsNeedCoherencyCheckUpdate, &m.ObjectsDeclaredObsolete)
|
|
if err != nil {
|
|
return &m, err
|
|
}
|
|
case "Pages":
|
|
err := setFSCacheFields(fields[2:], &m.PagesMarkedAsBeingCached, &m.UncachePagesRequestSeen)
|
|
if err != nil {
|
|
return &m, err
|
|
}
|
|
case "Acquire:":
|
|
err := setFSCacheFields(fields[1:], &m.AcquireCookiesRequestSeen, &m.AcquireRequestsWithNullParent,
|
|
&m.AcquireRequestsRejectedNoCacheAvailable, &m.AcquireRequestsSucceeded, &m.AcquireRequestsRejectedDueToError,
|
|
&m.AcquireRequestsFailedDueToEnomem)
|
|
if err != nil {
|
|
return &m, err
|
|
}
|
|
case "Lookups:":
|
|
err := setFSCacheFields(fields[1:], &m.LookupsNumber, &m.LookupsNegative, &m.LookupsPositive,
|
|
&m.ObjectsCreatedByLookup, &m.LookupsTimedOutAndRequed)
|
|
if err != nil {
|
|
return &m, err
|
|
}
|
|
case "Invals":
|
|
err := setFSCacheFields(fields[2:], &m.InvalidationsNumber, &m.InvalidationsRunning)
|
|
if err != nil {
|
|
return &m, err
|
|
}
|
|
case "Updates:":
|
|
err := setFSCacheFields(fields[1:], &m.UpdateCookieRequestSeen, &m.UpdateRequestsWithNullParent,
|
|
&m.UpdateRequestsRunning)
|
|
if err != nil {
|
|
return &m, err
|
|
}
|
|
case "Relinqs:":
|
|
err := setFSCacheFields(fields[1:], &m.RelinquishCookiesRequestSeen, &m.RelinquishCookiesWithNullParent,
|
|
&m.RelinquishRequestsWaitingCompleteCreation, &m.RelinquishRetries)
|
|
if err != nil {
|
|
return &m, err
|
|
}
|
|
case "AttrChg:":
|
|
err := setFSCacheFields(fields[1:], &m.AttributeChangedRequestsSeen, &m.AttributeChangedRequestsQueued,
|
|
&m.AttributeChangedRejectDueToEnobufs, &m.AttributeChangedFailedDueToEnomem, &m.AttributeChangedOps)
|
|
if err != nil {
|
|
return &m, err
|
|
}
|
|
case "Allocs":
|
|
if strings.Split(fields[2], "=")[0] == "n" {
|
|
err := setFSCacheFields(fields[2:], &m.AllocationRequestsSeen, &m.AllocationOkRequests,
|
|
&m.AllocationWaitingOnLookup, &m.AllocationsRejectedDueToEnobufs, &m.AllocationsAbortedDueToErestartsys)
|
|
if err != nil {
|
|
return &m, err
|
|
}
|
|
} else {
|
|
err := setFSCacheFields(fields[2:], &m.AllocationOperationsSubmitted, &m.AllocationsWaitedForCPU,
|
|
&m.AllocationsAbortedDueToObjectDeath)
|
|
if err != nil {
|
|
return &m, err
|
|
}
|
|
}
|
|
case "Retrvls:":
|
|
if strings.Split(fields[1], "=")[0] == "n" {
|
|
err := setFSCacheFields(fields[1:], &m.RetrievalsReadRequests, &m.RetrievalsOk, &m.RetrievalsWaitingLookupCompletion,
|
|
&m.RetrievalsReturnedEnodata, &m.RetrievalsRejectedDueToEnobufs, &m.RetrievalsAbortedDueToErestartsys,
|
|
&m.RetrievalsFailedDueToEnomem)
|
|
if err != nil {
|
|
return &m, err
|
|
}
|
|
} else {
|
|
err := setFSCacheFields(fields[1:], &m.RetrievalsRequests, &m.RetrievalsWaitingCPU, &m.RetrievalsAbortedDueToObjectDeath)
|
|
if err != nil {
|
|
return &m, err
|
|
}
|
|
}
|
|
case "Stores":
|
|
if strings.Split(fields[2], "=")[0] == "n" {
|
|
err := setFSCacheFields(fields[2:], &m.StoreWriteRequests, &m.StoreSuccessfulRequests,
|
|
&m.StoreRequestsOnPendingStorage, &m.StoreRequestsRejectedDueToEnobufs, &m.StoreRequestsFailedDueToEnomem)
|
|
if err != nil {
|
|
return &m, err
|
|
}
|
|
} else {
|
|
err := setFSCacheFields(fields[2:], &m.StoreRequestsSubmitted, &m.StoreRequestsRunning,
|
|
&m.StorePagesWithRequestsProcessing, &m.StoreRequestsDeleted, &m.StoreRequestsOverStoreLimit)
|
|
if err != nil {
|
|
return &m, err
|
|
}
|
|
}
|
|
case "VmScan":
|
|
err := setFSCacheFields(fields[2:], &m.ReleaseRequestsAgainstPagesWithNoPendingStorage,
|
|
&m.ReleaseRequestsAgainstPagesStoredByTimeLockGranted, &m.ReleaseRequestsIgnoredDueToInProgressStore,
|
|
&m.PageStoresCancelledByReleaseRequests, &m.VmscanWaiting)
|
|
if err != nil {
|
|
return &m, err
|
|
}
|
|
case "Ops":
|
|
if strings.Split(fields[2], "=")[0] == "pend" {
|
|
err := setFSCacheFields(fields[2:], &m.OpsPending, &m.OpsRunning, &m.OpsEnqueued, &m.OpsCancelled, &m.OpsRejected)
|
|
if err != nil {
|
|
return &m, err
|
|
}
|
|
} else {
|
|
err := setFSCacheFields(fields[2:], &m.OpsInitialised, &m.OpsDeferred, &m.OpsReleased, &m.OpsGarbageCollected)
|
|
if err != nil {
|
|
return &m, err
|
|
}
|
|
}
|
|
case "CacheOp:":
|
|
if strings.Split(fields[1], "=")[0] == "alo" {
|
|
err := setFSCacheFields(fields[1:], &m.CacheopAllocationsinProgress, &m.CacheopLookupObjectInProgress,
|
|
&m.CacheopLookupCompleteInPorgress, &m.CacheopGrabObjectInProgress)
|
|
if err != nil {
|
|
return &m, err
|
|
}
|
|
} else if strings.Split(fields[1], "=")[0] == "inv" {
|
|
err := setFSCacheFields(fields[1:], &m.CacheopInvalidations, &m.CacheopUpdateObjectInProgress,
|
|
&m.CacheopDropObjectInProgress, &m.CacheopPutObjectInProgress, &m.CacheopAttributeChangeInProgress,
|
|
&m.CacheopSyncCacheInProgress)
|
|
if err != nil {
|
|
return &m, err
|
|
}
|
|
} else {
|
|
err := setFSCacheFields(fields[1:], &m.CacheopReadOrAllocPageInProgress, &m.CacheopReadOrAllocPagesInProgress,
|
|
&m.CacheopAllocatePageInProgress, &m.CacheopAllocatePagesInProgress, &m.CacheopWritePagesInProgress,
|
|
&m.CacheopUncachePagesInProgress, &m.CacheopDissociatePagesInProgress)
|
|
if err != nil {
|
|
return &m, err
|
|
}
|
|
}
|
|
case "CacheEv:":
|
|
err := setFSCacheFields(fields[1:], &m.CacheevLookupsAndCreationsRejectedLackSpace, &m.CacheevStaleObjectsDeleted,
|
|
&m.CacheevRetiredWhenReliquished, &m.CacheevObjectsCulled)
|
|
if err != nil {
|
|
return &m, err
|
|
}
|
|
}
|
|
}
|
|
|
|
return &m, nil
|
|
}
|