Source file src/cmd/vendor/golang.org/x/telemetry/counter/counter.go

     1  // Copyright 2023 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package counter
     6  
     7  // The implementation of this package and tests are located in
     8  // internal/counter, which can be shared with the upload package.
     9  // TODO(hyangah): use of type aliases prevents nice documentation
    10  // rendering in go doc or pkgsite. Fix this either by avoiding
    11  // type aliasing or restructuring the internal/counter package.
    12  import (
    13  	"flag"
    14  	"path"
    15  	"runtime/debug"
    16  
    17  	"golang.org/x/telemetry/internal/counter"
    18  	"golang.org/x/telemetry/internal/telemetry"
    19  )
    20  
    21  // Inc increments the counter with the given name.
    22  func Inc(name string) {
    23  	New(name).Inc()
    24  }
    25  
    26  // Add adds n to the counter with the given name.
    27  func Add(name string, n int64) {
    28  	New(name).Add(n)
    29  }
    30  
    31  // New returns a counter with the given name.
    32  // New can be called in global initializers and will be compiled down to
    33  // linker-initialized data. That is, calling New to initialize a global
    34  // has no cost at program startup.
    35  //
    36  // See "Counter Naming" in the package doc for a description of counter naming
    37  // conventions.
    38  func New(name string) *Counter {
    39  	// Note: not calling DefaultFile.New in order to keep this
    40  	// function something the compiler can inline and convert
    41  	// into static data initializations, with no init-time footprint.
    42  	// TODO(hyangah): is it trivial enough for the compiler to inline?
    43  	return counter.New(name)
    44  }
    45  
    46  // A Counter is a single named event counter.
    47  // A Counter is safe for use by multiple goroutines simultaneously.
    48  //
    49  // Counters should typically be created using New
    50  // and stored as global variables, like:
    51  //
    52  //	package mypackage
    53  //	var errorCount = counter.New("mypackage/errors")
    54  //
    55  // (The initialization of errorCount in this example is handled
    56  // entirely by the compiler and linker; this line executes no code
    57  // at program startup.)
    58  //
    59  // Then code can call Add to increment the counter
    60  // each time the corresponding event is observed.
    61  //
    62  // Although it is possible to use New to create
    63  // a Counter each time a particular event needs to be recorded,
    64  // that usage fails to amortize the construction cost over
    65  // multiple calls to Add, so it is more expensive and not recommended.
    66  type Counter = counter.Counter
    67  
    68  // A StackCounter is the in-memory knowledge about a stack counter.
    69  // StackCounters are more expensive to use than regular Counters,
    70  // requiring, at a minimum, a call to runtime.Callers.
    71  type StackCounter = counter.StackCounter
    72  
    73  // NewStack returns a new stack counter with the given name and depth.
    74  //
    75  // See "Counter Naming" in the package doc for a description of counter naming
    76  // conventions.
    77  func NewStack(name string, depth int) *StackCounter {
    78  	return counter.NewStack(name, depth)
    79  }
    80  
    81  // Open prepares telemetry counters for recording to the file system.
    82  //
    83  // If the telemetry mode is "off", Open is a no-op. Otherwise, it opens the
    84  // counter file on disk and starts to mmap telemetry counters to the file.
    85  // Open also persists any counters already created in the current process.
    86  //
    87  // Open should only be called from short-lived processes such as command line
    88  // tools. If your process is long-running, use [OpenAndRotate].
    89  func Open() {
    90  	counter.Open(false)
    91  }
    92  
    93  // OpenAndRotate is like [Open], but also schedules a rotation of the counter
    94  // file when it expires.
    95  //
    96  // See golang/go#68497 for background on why [OpenAndRotate] is a separate API.
    97  //
    98  // TODO(rfindley): refactor Open and OpenAndRotate for Go 1.24.
    99  func OpenAndRotate() {
   100  	counter.Open(true)
   101  }
   102  
   103  // OpenDir prepares telemetry counters for recording to the file system, using
   104  // the specified telemetry directory, if it is not the empty string.
   105  //
   106  // If the telemetry mode is "off", Open is a no-op. Otherwise, it opens the
   107  // counter file on disk and starts to mmap telemetry counters to the file.
   108  // Open also persists any counters already created in the current process.
   109  func OpenDir(telemetryDir string) {
   110  	if telemetryDir != "" {
   111  		telemetry.Default = telemetry.NewDir(telemetryDir)
   112  	}
   113  	counter.Open(false)
   114  }
   115  
   116  // CountFlags creates a counter for every flag that is set
   117  // and increments the counter. The name of the counter is
   118  // the concatenation of prefix and the flag name.
   119  //
   120  //	For instance, CountFlags("gopls/flag:", *flag.CommandLine)
   121  func CountFlags(prefix string, fs flag.FlagSet) {
   122  	fs.Visit(func(f *flag.Flag) {
   123  		New(prefix + f.Name).Inc()
   124  	})
   125  }
   126  
   127  // CountCommandLineFlags creates a counter for every flag
   128  // that is set in the default flag.CommandLine FlagSet using
   129  // the counter name binaryName+"/flag:"+flagName where
   130  // binaryName is the base name of the Path embedded in the
   131  // binary's build info. If the binary does not have embedded build
   132  // info, the "flag:"+flagName counter will be incremented.
   133  //
   134  // CountCommandLineFlags must be called after flags are parsed
   135  // with flag.Parse.
   136  //
   137  // For instance, if the -S flag is passed to cmd/compile and
   138  // CountCommandLineFlags is called after flags are parsed,
   139  // the "compile/flag:S" counter will be incremented.
   140  func CountCommandLineFlags() {
   141  	prefix := "flag:"
   142  	if buildInfo, ok := debug.ReadBuildInfo(); ok && buildInfo.Path != "" {
   143  		prefix = path.Base(buildInfo.Path) + "/" + prefix
   144  	}
   145  	CountFlags(prefix, *flag.CommandLine)
   146  }
   147  

View as plain text