84 lines
4.1 KiB
Go
84 lines
4.1 KiB
Go
// Copyright 2020 The gVisor 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 fsmetric defines filesystem metrics that are used by both VFS1 and
|
|
// VFS2.
|
|
//
|
|
// TODO(gvisor.dev/issue/1624): Once VFS1 is deleted, inline these metrics into
|
|
// VFS2.
|
|
package fsmetric
|
|
|
|
import (
|
|
"time"
|
|
|
|
"gvisor.dev/gvisor/pkg/metric"
|
|
)
|
|
|
|
// RecordWaitTime enables the ReadWait, GoferReadWait9P, GoferReadWaitHost, and
|
|
// TmpfsReadWait metrics. Enabling this comes at a CPU cost due to performing
|
|
// three clock reads per read call.
|
|
//
|
|
// Note that this is only performed in the direct read path, and may not be
|
|
// consistently applied for other forms of reads, such as splice.
|
|
var RecordWaitTime = false
|
|
|
|
// Metrics that apply to all filesystems.
|
|
var (
|
|
Opens = metric.MustCreateNewUint64Metric("/fs/opens", false /* sync */, "Number of file opens.")
|
|
Reads = metric.MustCreateNewUint64Metric("/fs/reads", false /* sync */, "Number of file reads.")
|
|
ReadWait = metric.MustCreateNewUint64NanosecondsMetric("/fs/read_wait", false /* sync */, "Time waiting on file reads, in nanoseconds.")
|
|
)
|
|
|
|
// Metrics that only apply to fs/gofer and fsimpl/gofer.
|
|
var (
|
|
GoferOpensWX = metric.MustCreateNewUint64Metric("/gofer/opened_write_execute_file", true /* sync */, "Number of times a executable file was opened writably from a gofer.")
|
|
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.")
|
|
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.")
|
|
GoferReads9P = metric.MustCreateNewUint64Metric("/gofer/reads_9p", false /* sync */, "Number of 9P file reads from a gofer.")
|
|
GoferReadWait9P = metric.MustCreateNewUint64NanosecondsMetric("/gofer/read_wait_9p", false /* sync */, "Time waiting on 9P file reads from a gofer, in nanoseconds.")
|
|
GoferReadsHost = metric.MustCreateNewUint64Metric("/gofer/reads_host", false /* sync */, "Number of host file reads from a gofer.")
|
|
GoferReadWaitHost = metric.MustCreateNewUint64NanosecondsMetric("/gofer/read_wait_host", false /* sync */, "Time waiting on host file reads from a gofer, in nanoseconds.")
|
|
)
|
|
|
|
// Metrics that only apply to fs/tmpfs and fsimpl/tmpfs.
|
|
var (
|
|
TmpfsOpensRO = metric.MustCreateNewUint64Metric("/in_memory_file/opens_ro", false /* sync */, "Number of times an in-memory file was opened in read-only mode.")
|
|
TmpfsOpensW = metric.MustCreateNewUint64Metric("/in_memory_file/opens_w", false /* sync */, "Number of times an in-memory file was opened in write mode.")
|
|
TmpfsReads = metric.MustCreateNewUint64Metric("/in_memory_file/reads", false /* sync */, "Number of in-memory file reads.")
|
|
TmpfsReadWait = metric.MustCreateNewUint64NanosecondsMetric("/in_memory_file/read_wait", false /* sync */, "Time waiting on in-memory file reads, in nanoseconds.")
|
|
)
|
|
|
|
// StartReadWait indicates the beginning of a file read.
|
|
func StartReadWait() time.Time {
|
|
if !RecordWaitTime {
|
|
return time.Time{}
|
|
}
|
|
return time.Now()
|
|
}
|
|
|
|
// FinishReadWait indicates the end of a file read whose time is accounted by
|
|
// m. start must be the value returned by the corresponding call to
|
|
// StartReadWait.
|
|
//
|
|
// FinishReadWait is marked nosplit for performance since it's often called
|
|
// from defer statements, which prevents it from being inlined
|
|
// (https://github.com/golang/go/issues/38471).
|
|
//go:nosplit
|
|
func FinishReadWait(m *metric.Uint64Metric, start time.Time) {
|
|
if !RecordWaitTime {
|
|
return
|
|
}
|
|
m.IncrementBy(uint64(time.Since(start).Nanoseconds()))
|
|
}
|