github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/sentry/fsmetric/fsmetric.go (about)

     1  // Copyright 2020 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package fsmetric defines filesystem metrics.
    16  package fsmetric
    17  
    18  import (
    19  	"time"
    20  
    21  	"github.com/nicocha30/gvisor-ligolo/pkg/metric"
    22  )
    23  
    24  // RecordWaitTime enables the ReadWait, GoferReadWait9P, GoferReadWaitHost, and
    25  // TmpfsReadWait metrics. Enabling this comes at a CPU cost due to performing
    26  // three clock reads per read call.
    27  //
    28  // Note that this is only performed in the direct read path, and may not be
    29  // consistently applied for other forms of reads, such as splice.
    30  var RecordWaitTime = false
    31  
    32  // Metrics that apply to all filesystems.
    33  var (
    34  	Opens    = metric.MustCreateNewUint64Metric("/fs/opens", false /* sync */, "Number of file opens.")
    35  	Reads    = metric.MustCreateNewUint64Metric("/fs/reads", false /* sync */, "Number of file reads.")
    36  	ReadWait = metric.MustCreateNewUint64NanosecondsMetric("/fs/read_wait", false /* sync */, "Time waiting on file reads, in nanoseconds.")
    37  )
    38  
    39  // Metrics that only apply to fs/gofer and fsimpl/gofer.
    40  var (
    41  	GoferOpens9P      = metric.MustCreateNewUint64Metric("/gofer/opens_9p", false /* sync */, "Number of times a file was opened from a gofer and did not have a host file descriptor.")
    42  	GoferOpensHost    = metric.MustCreateNewUint64Metric("/gofer/opens_host", false /* sync */, "Number of times a file was opened from a gofer and did have a host file descriptor.")
    43  	GoferReads9P      = metric.MustCreateNewUint64Metric("/gofer/reads_9p", false /* sync */, "Number of 9P file reads from a gofer.")
    44  	GoferReadWait9P   = metric.MustCreateNewUint64NanosecondsMetric("/gofer/read_wait_9p", false /* sync */, "Time waiting on 9P file reads from a gofer, in nanoseconds.")
    45  	GoferReadsHost    = metric.MustCreateNewUint64Metric("/gofer/reads_host", false /* sync */, "Number of host file reads from a gofer.")
    46  	GoferReadWaitHost = metric.MustCreateNewUint64NanosecondsMetric("/gofer/read_wait_host", false /* sync */, "Time waiting on host file reads from a gofer, in nanoseconds.")
    47  )
    48  
    49  // Metrics that only apply to fs/tmpfs and fsimpl/tmpfs.
    50  var (
    51  	TmpfsOpensRO  = metric.MustCreateNewUint64Metric("/in_memory_file/opens_ro", false /* sync */, "Number of times an in-memory file was opened in read-only mode.")
    52  	TmpfsOpensW   = metric.MustCreateNewUint64Metric("/in_memory_file/opens_w", false /* sync */, "Number of times an in-memory file was opened in write mode.")
    53  	TmpfsReads    = metric.MustCreateNewUint64Metric("/in_memory_file/reads", false /* sync */, "Number of in-memory file reads.")
    54  	TmpfsReadWait = metric.MustCreateNewUint64NanosecondsMetric("/in_memory_file/read_wait", false /* sync */, "Time waiting on in-memory file reads, in nanoseconds.")
    55  )
    56  
    57  // StartReadWait indicates the beginning of a file read.
    58  func StartReadWait() time.Time {
    59  	if !RecordWaitTime {
    60  		return time.Time{}
    61  	}
    62  	return time.Now()
    63  }
    64  
    65  // FinishReadWait indicates the end of a file read whose time is accounted by
    66  // m. start must be the value returned by the corresponding call to
    67  // StartReadWait.
    68  //
    69  // FinishReadWait is marked nosplit for performance since it's often called
    70  // from defer statements, which prevents it from being inlined
    71  // (https://github.com/golang/go/issues/38471).
    72  //
    73  //go:nosplit
    74  func FinishReadWait(m *metric.Uint64Metric, start time.Time) {
    75  	if !RecordWaitTime {
    76  		return
    77  	}
    78  	m.IncrementBy(uint64(time.Since(start).Nanoseconds()))
    79  }