/
mode.go
132 lines (117 loc) · 4.12 KB
/
mode.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package telemetry manages the telemetry mode file.
package telemetry
import (
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
"time"
)
// The followings are the process' default Settings.
// The values are subdirectories and a file under
// os.UserConfigDir()/go/telemetry.
// For convenience, each field is made to global
// and they are not supposed to be changed.
var (
// Default directory containing count files and local reports (not yet uploaded)
LocalDir string
// Default directory containing uploaded reports.
UploadDir string
// Default file path that holds the telemetry mode info.
ModeFile ModeFilePath
)
// ModeFilePath is the telemetry mode file path with methods to manipulate the file contents.
type ModeFilePath string
func init() {
cfgDir, err := os.UserConfigDir()
if err != nil {
return
}
gotelemetrydir := filepath.Join(cfgDir, "cue", "telemetry")
LocalDir = filepath.Join(gotelemetrydir, "local")
UploadDir = filepath.Join(gotelemetrydir, "upload")
ModeFile = ModeFilePath(filepath.Join(gotelemetrydir, "mode"))
}
// SetMode updates the telemetry mode with the given mode.
// Acceptable values for mode are "on", "off", or "local".
//
// SetMode always writes the mode file, and explicitly records the date at
// which the modefile was updated. This means that calling SetMode with "on"
// effectively resets the timeout before the next telemetry report is uploaded.
func SetMode(mode string) error {
return ModeFile.SetMode(mode)
}
func (m ModeFilePath) SetMode(mode string) error {
return m.SetModeAsOf(mode, time.Now())
}
// SetModeAsOf is like SetMode, but accepts an explicit time to use to
// back-date the mode state. This exists only for testing purposes.
func (m ModeFilePath) SetModeAsOf(mode string, asofTime time.Time) error {
mode = strings.TrimSpace(mode)
switch mode {
case "on", "off", "local":
default:
return fmt.Errorf("invalid telemetry mode: %q", mode)
}
fname := string(m)
if fname == "" {
return fmt.Errorf("cannot determine telemetry mode file name")
}
if err := os.MkdirAll(filepath.Dir(fname), 0755); err != nil {
return fmt.Errorf("cannot create a telemetry mode file: %w", err)
}
asof := asofTime.UTC().Format("2006-01-02")
// Defensively guarantee that we can parse the asof time.
if _, err := time.Parse("2006-01-02", asof); err != nil {
return fmt.Errorf("internal error: invalid mode date %q: %v", asof, err)
}
data := []byte(mode + " " + asof)
return os.WriteFile(fname, data, 0666)
}
// Mode returns the current telemetry mode, as well as the time that the mode
// was effective.
//
// If there is no effective time, the second result is the zero time.
func Mode() (string, time.Time) {
return ModeFile.Mode()
}
func (m ModeFilePath) Mode() (string, time.Time) {
fname := string(m)
if fname == "" {
return "off", time.Time{} // it's likely LocalDir/UploadDir are empty too. Turn off telemetry.
}
data, err := os.ReadFile(fname)
if err != nil {
return "local", time.Time{} // default
}
mode := string(data)
mode = strings.TrimSpace(mode)
// Forward compatibility for https://go.dev/issue/63142#issuecomment-1734025130
//
// If the modefile contains a date, return it.
if idx := strings.Index(mode, " "); idx >= 0 {
d, err := time.Parse("2006-01-02", mode[idx+1:])
if err != nil {
d = time.Time{}
}
return mode[:idx], d
}
return mode, time.Time{}
}
// DisabledOnPlatform indicates whether telemetry is disabled
// due to bugs in the current platform.
const DisabledOnPlatform = false ||
// The following platforms could potentially be supported in the future:
runtime.GOOS == "openbsd" || // #60614
runtime.GOOS == "solaris" || // #60968 #60970
runtime.GOOS == "android" || // #60967
// These platforms fundamentally can't be supported:
runtime.GOOS == "js" || // #60971
runtime.GOOS == "wasip1" || // #60971
runtime.GOOS == "plan9" || // https://github.com/golang/go/issues/57540#issuecomment-1470766639
// Work is in progress to support 386:
runtime.GOARCH == "386" // #60615 #60692 #60965 #60967