Skip to content

Commit fa80cb5

Browse files
Ian Cottrellianthehat
Ian Cottrell
authored andcommitted
internal/telemetry: pass the http.Client to the ocagent
This will allow us to configure the connection at need. It will also allow us to intercept the content for tests. Change-Id: Id7d34f2d56f233eae112bea97cccab1f2a88de55 Reviewed-on: https://go-review.googlesource.com/c/tools/+/190798 Run-TryBot: Ian Cottrell <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Rebecca Stambler <[email protected]> Reviewed-by: Emmanuel Odeke <[email protected]>
1 parent 547ecf7 commit fa80cb5

File tree

2 files changed

+67
-32
lines changed

2 files changed

+67
-32
lines changed

internal/lsp/cmd/cmd.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,10 @@ gopls flags are:
113113
// If no arguments are passed it will invoke the server sub command, as a
114114
// temporary measure for compatibility.
115115
func (app *Application) Run(ctx context.Context, args ...string) error {
116-
export.AddExporters(ocagent.Connect(app.name, app.OCAgent))
116+
ocConfig := ocagent.Discover()
117+
//TODO: we should not need to adjust the discovered configuration
118+
ocConfig.Address = app.OCAgent
119+
export.AddExporters(ocagent.Connect(ocConfig))
117120
app.Serve.app = app
118121
if len(args) == 0 {
119122
tool.Main(ctx, &app.Serve, args)

internal/telemetry/export/ocagent/ocagent.go

Lines changed: 63 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"fmt"
1515
"net/http"
1616
"os"
17+
"path/filepath"
1718
"sync"
1819
"time"
1920

@@ -23,12 +24,28 @@ import (
2324
"golang.org/x/tools/internal/telemetry/tag"
2425
)
2526

26-
const DefaultAddress = "http://localhost:55678"
27-
const exportRate = 2 * time.Second
27+
type Config struct {
28+
Start time.Time
29+
Host string
30+
Process uint32
31+
Client *http.Client
32+
Service string
33+
Address string
34+
Rate time.Duration
35+
}
36+
37+
// Discover finds the local agent to export to, it will return nil if there
38+
// is not one running.
39+
// TODO: Actually implement a discovery protocol rather than a hard coded address
40+
func Discover() *Config {
41+
return &Config{
42+
Address: "http://localhost:55678",
43+
}
44+
}
2845

2946
type exporter struct {
3047
mu sync.Mutex
31-
address string
48+
config Config
3249
node *wire.Node
3350
spans []*wire.Span
3451
metrics []*wire.Metric
@@ -37,35 +54,48 @@ type exporter struct {
3754
// Connect creates a process specific exporter with the specified
3855
// serviceName and the address of the ocagent to which it will upload
3956
// its telemetry.
40-
func Connect(service, address string) export.Exporter {
41-
if address == "off" {
57+
func Connect(config *Config) export.Exporter {
58+
if config == nil || config.Address == "off" {
4259
return nil
4360
}
44-
hostname, _ := os.Hostname()
45-
exporter := &exporter{
46-
address: address,
47-
node: &wire.Node{
48-
Identifier: &wire.ProcessIdentifier{
49-
HostName: hostname,
50-
Pid: uint32(os.Getpid()),
51-
StartTimestamp: convertTimestamp(time.Now()),
52-
},
53-
LibraryInfo: &wire.LibraryInfo{
54-
Language: wire.LanguageGo,
55-
ExporterVersion: "0.0.1",
56-
CoreLibraryVersion: "x/tools",
57-
},
58-
ServiceInfo: &wire.ServiceInfo{
59-
Name: service,
60-
},
61-
},
61+
exporter := &exporter{config: *config}
62+
if exporter.config.Start.IsZero() {
63+
exporter.config.Start = time.Now()
64+
}
65+
if exporter.config.Host == "" {
66+
hostname, _ := os.Hostname()
67+
exporter.config.Host = hostname
68+
}
69+
if exporter.config.Process == 0 {
70+
exporter.config.Process = uint32(os.Getpid())
6271
}
63-
if exporter.address == "" {
64-
exporter.address = DefaultAddress
72+
if exporter.config.Client == nil {
73+
exporter.config.Client = http.DefaultClient
74+
}
75+
if exporter.config.Service == "" {
76+
exporter.config.Service = filepath.Base(os.Args[0])
77+
}
78+
if exporter.config.Rate == 0 {
79+
exporter.config.Rate = 2 * time.Second
80+
}
81+
exporter.node = &wire.Node{
82+
Identifier: &wire.ProcessIdentifier{
83+
HostName: exporter.config.Host,
84+
Pid: exporter.config.Process,
85+
StartTimestamp: convertTimestamp(exporter.config.Start),
86+
},
87+
LibraryInfo: &wire.LibraryInfo{
88+
Language: wire.LanguageGo,
89+
ExporterVersion: "0.0.1",
90+
CoreLibraryVersion: "x/tools",
91+
},
92+
ServiceInfo: &wire.ServiceInfo{
93+
Name: exporter.config.Service,
94+
},
6595
}
6696
go func() {
67-
for _ = range time.Tick(exportRate) {
68-
exporter.flush()
97+
for _ = range time.Tick(exporter.config.Rate) {
98+
exporter.Flush()
6999
}
70100
}()
71101
return exporter
@@ -87,7 +117,7 @@ func (e *exporter) Metric(ctx context.Context, data telemetry.MetricData) {
87117
e.metrics = append(e.metrics, convertMetric(data))
88118
}
89119

90-
func (e *exporter) flush() {
120+
func (e *exporter) Flush() {
91121
e.mu.Lock()
92122
defer e.mu.Unlock()
93123
spans := e.spans
@@ -117,19 +147,21 @@ func (e *exporter) send(endpoint string, message interface{}) {
117147
errorInExport("ocagent failed to marshal message for %v: %v", endpoint, err)
118148
return
119149
}
120-
uri := e.address + endpoint
150+
uri := e.config.Address + endpoint
121151
req, err := http.NewRequest("POST", uri, bytes.NewReader(blob))
122152
if err != nil {
123153
errorInExport("ocagent failed to build request for %v: %v", uri, err)
124154
return
125155
}
126156
req.Header.Set("Content-Type", "application/json")
127-
res, err := http.DefaultClient.Do(req)
157+
res, err := e.config.Client.Do(req)
128158
if err != nil {
129159
errorInExport("ocagent failed to send message: %v \n", err)
130160
return
131161
}
132-
res.Body.Close()
162+
if res.Body != nil {
163+
res.Body.Close()
164+
}
133165
return
134166
}
135167

0 commit comments

Comments
 (0)