Source file src/cmd/vendor/golang.org/x/telemetry/internal/config/config.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 config provides methods for loading and querying a
     6  // telemetry upload config file.
     7  package config
     8  
     9  import (
    10  	"encoding/json"
    11  	"os"
    12  	"strings"
    13  
    14  	"golang.org/x/telemetry/internal/telemetry"
    15  )
    16  
    17  // Config is a wrapper around telemetry.UploadConfig that provides some
    18  // convenience methods for checking the contents of a report.
    19  type Config struct {
    20  	*telemetry.UploadConfig
    21  	program         map[string]bool
    22  	goos            map[string]bool
    23  	goarch          map[string]bool
    24  	goversion       map[string]bool
    25  	pgversion       map[pgkey]bool
    26  	pgcounter       map[pgkey]bool
    27  	pgcounterprefix map[pgkey]bool
    28  	pgstack         map[pgkey]bool
    29  	rate            map[pgkey]float64
    30  }
    31  
    32  type pgkey struct {
    33  	program, key string
    34  }
    35  
    36  func ReadConfig(file string) (*Config, error) {
    37  	data, err := os.ReadFile(file)
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  	var cfg telemetry.UploadConfig
    42  	if err := json.Unmarshal(data, &cfg); err != nil {
    43  		return nil, err
    44  	}
    45  	return NewConfig(&cfg), nil
    46  }
    47  
    48  func NewConfig(cfg *telemetry.UploadConfig) *Config {
    49  	ucfg := Config{UploadConfig: cfg}
    50  	ucfg.goos = set(ucfg.GOOS)
    51  	ucfg.goarch = set(ucfg.GOARCH)
    52  	ucfg.goversion = set(ucfg.GoVersion)
    53  	ucfg.program = make(map[string]bool, len(ucfg.Programs))
    54  	ucfg.pgversion = make(map[pgkey]bool, len(ucfg.Programs))
    55  	ucfg.pgcounter = make(map[pgkey]bool, len(ucfg.Programs))
    56  	ucfg.pgcounterprefix = make(map[pgkey]bool, len(ucfg.Programs))
    57  	ucfg.pgstack = make(map[pgkey]bool, len(ucfg.Programs))
    58  	ucfg.rate = make(map[pgkey]float64)
    59  	for _, p := range ucfg.Programs {
    60  		ucfg.program[p.Name] = true
    61  		for _, v := range p.Versions {
    62  			ucfg.pgversion[pgkey{p.Name, v}] = true
    63  		}
    64  		for _, c := range p.Counters {
    65  			for _, e := range Expand(c.Name) {
    66  				ucfg.pgcounter[pgkey{p.Name, e}] = true
    67  				ucfg.rate[pgkey{p.Name, e}] = c.Rate
    68  			}
    69  			prefix, _, found := strings.Cut(c.Name, ":")
    70  			if found {
    71  				ucfg.pgcounterprefix[pgkey{p.Name, prefix}] = true
    72  			}
    73  		}
    74  		for _, s := range p.Stacks {
    75  			ucfg.pgstack[pgkey{p.Name, s.Name}] = true
    76  			ucfg.rate[pgkey{p.Name, s.Name}] = s.Rate
    77  		}
    78  	}
    79  	return &ucfg
    80  }
    81  
    82  func (r *Config) HasProgram(s string) bool {
    83  	return r.program[s]
    84  }
    85  
    86  func (r *Config) HasGOOS(s string) bool {
    87  	return r.goos[s]
    88  }
    89  
    90  func (r *Config) HasGOARCH(s string) bool {
    91  	return r.goarch[s]
    92  }
    93  
    94  func (r *Config) HasGoVersion(s string) bool {
    95  	return r.goversion[s]
    96  }
    97  
    98  func (r *Config) HasVersion(program, version string) bool {
    99  	return r.pgversion[pgkey{program, version}]
   100  }
   101  
   102  func (r *Config) HasCounter(program, counter string) bool {
   103  	return r.pgcounter[pgkey{program, counter}]
   104  }
   105  
   106  func (r *Config) HasCounterPrefix(program, prefix string) bool {
   107  	return r.pgcounterprefix[pgkey{program, prefix}]
   108  }
   109  
   110  func (r *Config) HasStack(program, stack string) bool {
   111  	return r.pgstack[pgkey{program, stack}]
   112  }
   113  
   114  func (r *Config) Rate(program, name string) float64 {
   115  	return r.rate[pgkey{program, name}]
   116  }
   117  
   118  func set(slice []string) map[string]bool {
   119  	s := make(map[string]bool, len(slice))
   120  	for _, v := range slice {
   121  		s[v] = true
   122  	}
   123  	return s
   124  }
   125  
   126  // Expand takes a counter defined with buckets and expands it into distinct
   127  // strings for each bucket
   128  func Expand(counter string) []string {
   129  	prefix, rest, hasBuckets := strings.Cut(counter, "{")
   130  	var counters []string
   131  	if hasBuckets {
   132  		buckets := strings.Split(strings.TrimSuffix(rest, "}"), ",")
   133  		for _, b := range buckets {
   134  			counters = append(counters, prefix+b)
   135  		}
   136  	} else {
   137  		counters = append(counters, prefix)
   138  	}
   139  	return counters
   140  }
   141  

View as plain text