src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

config.go (3626B)


      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 }