@@ -14,6 +14,7 @@ import (
14
14
"fmt"
15
15
"net/http"
16
16
"os"
17
+ "path/filepath"
17
18
"sync"
18
19
"time"
19
20
@@ -23,12 +24,28 @@ import (
23
24
"golang.org/x/tools/internal/telemetry/tag"
24
25
)
25
26
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
+ }
28
45
29
46
type exporter struct {
30
47
mu sync.Mutex
31
- address string
48
+ config Config
32
49
node * wire.Node
33
50
spans []* wire.Span
34
51
metrics []* wire.Metric
@@ -37,35 +54,48 @@ type exporter struct {
37
54
// Connect creates a process specific exporter with the specified
38
55
// serviceName and the address of the ocagent to which it will upload
39
56
// 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" {
42
59
return nil
43
60
}
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 ())
62
71
}
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
+ },
65
95
}
66
96
go func () {
67
- for _ = range time .Tick (exportRate ) {
68
- exporter .flush ()
97
+ for _ = range time .Tick (exporter . config . Rate ) {
98
+ exporter .Flush ()
69
99
}
70
100
}()
71
101
return exporter
@@ -87,7 +117,7 @@ func (e *exporter) Metric(ctx context.Context, data telemetry.MetricData) {
87
117
e .metrics = append (e .metrics , convertMetric (data ))
88
118
}
89
119
90
- func (e * exporter ) flush () {
120
+ func (e * exporter ) Flush () {
91
121
e .mu .Lock ()
92
122
defer e .mu .Unlock ()
93
123
spans := e .spans
@@ -117,19 +147,21 @@ func (e *exporter) send(endpoint string, message interface{}) {
117
147
errorInExport ("ocagent failed to marshal message for %v: %v" , endpoint , err )
118
148
return
119
149
}
120
- uri := e .address + endpoint
150
+ uri := e .config . Address + endpoint
121
151
req , err := http .NewRequest ("POST" , uri , bytes .NewReader (blob ))
122
152
if err != nil {
123
153
errorInExport ("ocagent failed to build request for %v: %v" , uri , err )
124
154
return
125
155
}
126
156
req .Header .Set ("Content-Type" , "application/json" )
127
- res , err := http . DefaultClient .Do (req )
157
+ res , err := e . config . Client .Do (req )
128
158
if err != nil {
129
159
errorInExport ("ocagent failed to send message: %v \n " , err )
130
160
return
131
161
}
132
- res .Body .Close ()
162
+ if res .Body != nil {
163
+ res .Body .Close ()
164
+ }
133
165
return
134
166
}
135
167
0 commit comments