Skip to content

Commit 0004520

Browse files
author
Roberto Sora
committed
Refactor the telemetry module
1 parent 013afa2 commit 0004520

File tree

5 files changed

+84
-27
lines changed

5 files changed

+84
-27
lines changed

cli/daemon/daemon.go

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ import (
3434
srv_debug "github.com/arduino/arduino-cli/rpc/debug"
3535
srv_monitor "github.com/arduino/arduino-cli/rpc/monitor"
3636
srv_settings "github.com/arduino/arduino-cli/rpc/settings"
37-
stats "github.com/segmentio/stats/v4"
38-
"github.com/segmentio/stats/v4/prometheus"
37+
"github.com/arduino/arduino-cli/telemetry"
3938
"github.com/sirupsen/logrus"
4039
"github.com/spf13/cobra"
4140
"github.com/spf13/viper"
@@ -62,22 +61,8 @@ var daemonize bool
6261

6362
func runDaemonCommand(cmd *cobra.Command, args []string) {
6463

65-
// Configure telemetry engine
66-
// Create a Prometheus default handler
67-
ph := prometheus.DefaultHandler
68-
// Replace the default stats engine with an engine that prepends the "daemon" prefix to all metrics
69-
stats.DefaultEngine = stats.WithPrefix("daemon")
70-
// Register the handler so it receives metrics from the default engine.
71-
stats.Register(ph)
72-
// Flush the default stats engine on return to ensure all buffered
73-
// metrics are sent to the server.
74-
defer stats.Flush()
75-
// move everything inside commands and search for setting up a common prefix for all metrics sent!
76-
logrus.Infof("Setting up Prometheus telemetry on /metrics, TCP port 2112")
77-
go func() {
78-
http.Handle("/metrics", ph)
79-
logrus.Error(http.ListenAndServe(":2112", nil))
80-
}()
64+
telemetry.Activate("daemon")
65+
defer telemetry.Engine.Flush()
8166

8267
port := viper.GetString("daemon.port")
8368
s := grpc.NewServer()
@@ -114,6 +99,7 @@ func runDaemonCommand(cmd *cobra.Command, args []string) {
11499
go func() {
115100
// Stdin is closed when the controlling parent process ends
116101
_, _ = io.Copy(ioutil.Discard, os.Stdin)
102+
telemetry.Engine.Flush()
117103
os.Exit(0)
118104
}()
119105
}
@@ -147,5 +133,4 @@ func runDaemonCommand(cmd *cobra.Command, args []string) {
147133
if err := s.Serve(lis); err != nil {
148134
logrus.Fatalf("Failed to serve: %v", err)
149135
}
150-
151136
}

commands/board/attach.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,12 @@ import (
2828
"github.com/arduino/arduino-cli/arduino/sketches"
2929
"github.com/arduino/arduino-cli/commands"
3030
rpc "github.com/arduino/arduino-cli/rpc/commands"
31-
discovery "github.com/arduino/board-discovery"
32-
paths "github.com/arduino/go-paths-helper"
31+
"github.com/arduino/board-discovery"
32+
"github.com/arduino/go-paths-helper"
3333
)
3434

3535
// Attach FIXMEDOC
3636
func Attach(ctx context.Context, req *rpc.BoardAttachReq, taskCB commands.TaskProgressCB) (*rpc.BoardAttachResp, error) {
37-
3837
pm := commands.GetPackageManager(req.GetInstance().GetId())
3938
if pm == nil {
4039
return nil, errors.New("invalid instance")

commands/board/list.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package board
1818
import (
1919
"encoding/json"
2020
"fmt"
21+
"github.com/arduino/arduino-cli/telemetry"
2122
"github.com/segmentio/stats/v4"
2223
"io/ioutil"
2324
"net/http"
@@ -107,13 +108,13 @@ func List(instanceID int32) ([]*rpc.DetectedPort, error) {
107108

108109
pm := commands.GetPackageManager(instanceID)
109110
if pm == nil {
110-
stats.Incr("board.list", stats.Tag{"success", "false"})
111+
telemetry.Engine.Incr("board.list", stats.T("success", "false"))
111112
return nil, errors.New("invalid instance")
112113
}
113114

114115
ports, err := commands.ListBoards(pm)
115116
if err != nil {
116-
stats.Incr("board.list", stats.Tag{"success", "false"})
117+
telemetry.Engine.Incr("board.list", stats.T("success", "false"))
117118
return nil, errors.Wrap(err, "error getting port list from serial-discovery")
118119
}
119120

@@ -139,7 +140,7 @@ func List(instanceID int32) ([]*rpc.DetectedPort, error) {
139140
logrus.Debug("Board not recognized")
140141
} else if err != nil {
141142
// this is bad, bail out
142-
stats.Incr("board.list", stats.Tag{"success", "false"})
143+
telemetry.Engine.Incr("board.list", stats.T("success", "false"))
143144
return nil, errors.Wrap(err, "error getting board info from Arduino Cloud")
144145
}
145146

@@ -160,6 +161,6 @@ func List(instanceID int32) ([]*rpc.DetectedPort, error) {
160161
retVal = append(retVal, p)
161162
}
162163

163-
stats.Incr("board.list", stats.Tag{"success", "true"})
164+
telemetry.Engine.Incr("board.list", stats.T("success", "true"))
164165
return retVal, nil
165166
}

commands/compile/compile.go

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"io"
2323
"path/filepath"
2424
"sort"
25+
"strconv"
2526
"strings"
2627

2728
"github.com/arduino/arduino-cli/arduino/cores"
@@ -33,26 +34,48 @@ import (
3334
"github.com/arduino/arduino-cli/legacy/builder/i18n"
3435
"github.com/arduino/arduino-cli/legacy/builder/types"
3536
rpc "github.com/arduino/arduino-cli/rpc/commands"
37+
"github.com/arduino/arduino-cli/telemetry"
3638
paths "github.com/arduino/go-paths-helper"
3739
properties "github.com/arduino/go-properties-orderedmap"
40+
"github.com/segmentio/stats/v4"
3841
"github.com/sirupsen/logrus"
3942
"github.com/spf13/viper"
4043
)
4144

4245
// Compile FIXMEDOC
4346
func Compile(ctx context.Context, req *rpc.CompileReq, outStream, errStream io.Writer, debug bool) (*rpc.CompileResp, error) {
47+
48+
tags := map[string]string{
49+
"fqbn": req.Fqbn,
50+
"sketchPath": req.SketchPath,
51+
"showProperties": strconv.FormatBool(req.ShowProperties),
52+
"preprocess": strconv.FormatBool(req.Preprocess),
53+
"buildProperties": strings.Join(req.BuildProperties, ","),
54+
"warnings": req.Warnings,
55+
"verbose": strconv.FormatBool(req.Verbose),
56+
"quiet": strconv.FormatBool(req.Quiet),
57+
"vidPid": req.VidPid,
58+
"exportFile": req.ExportFile,
59+
"jobs": strconv.FormatInt(int64(req.Jobs), 10),
60+
"libraries": strings.Join(req.Libraries, ","),
61+
"success": "false",
62+
}
63+
4464
pm := commands.GetPackageManager(req.GetInstance().GetId())
4565
if pm == nil {
66+
telemetry.Engine.Incr("compile", stats.M(tags)...)
4667
return nil, errors.New("invalid instance")
4768
}
4869

4970
logrus.Tracef("Compile %s for %s started", req.GetSketchPath(), req.GetFqbn())
5071
if req.GetSketchPath() == "" {
72+
telemetry.Engine.Incr("compile", stats.M(tags)...)
5173
return nil, fmt.Errorf("missing sketchPath")
5274
}
5375
sketchPath := paths.New(req.GetSketchPath())
5476
sketch, err := sketches.NewSketchFromPath(sketchPath)
5577
if err != nil {
78+
telemetry.Engine.Incr("compile", stats.M(tags)...)
5679
return nil, fmt.Errorf("opening sketch: %s", err)
5780
}
5881

@@ -61,10 +84,12 @@ func Compile(ctx context.Context, req *rpc.CompileReq, outStream, errStream io.W
6184
fqbnIn = sketch.Metadata.CPU.Fqbn
6285
}
6386
if fqbnIn == "" {
87+
telemetry.Engine.Incr("compile", stats.M(tags)...)
6488
return nil, fmt.Errorf("no FQBN provided")
6589
}
6690
fqbn, err := cores.ParseFQBN(fqbnIn)
6791
if err != nil {
92+
telemetry.Engine.Incr("compile", stats.M(tags)...)
6893
return nil, fmt.Errorf("incorrect FQBN: %s", err)
6994
}
7095

@@ -78,6 +103,7 @@ func Compile(ctx context.Context, req *rpc.CompileReq, outStream, errStream io.W
78103
// "\"%[1]s:%[2]s\" platform is not installed, please install it by running \""+
79104
// version.GetAppName()+" core install %[1]s:%[2]s\".", fqbn.Package, fqbn.PlatformArch)
80105
// feedback.Error(errorMessage)
106+
telemetry.Engine.Incr("compile", stats.M(tags)...)
81107
return nil, fmt.Errorf("platform not installed")
82108
}
83109

@@ -97,6 +123,7 @@ func Compile(ctx context.Context, req *rpc.CompileReq, outStream, errStream io.W
97123
builderCtx.BuildPath = paths.New(req.GetBuildPath())
98124
err = builderCtx.BuildPath.MkdirAll()
99125
if err != nil {
126+
telemetry.Engine.Incr("compile", stats.M(tags)...)
100127
return nil, fmt.Errorf("cannot create build directory: %s", err)
101128
}
102129
}
@@ -125,6 +152,7 @@ func Compile(ctx context.Context, req *rpc.CompileReq, outStream, errStream io.W
125152
builderCtx.BuildCachePath = paths.New(req.GetBuildCachePath())
126153
err = builderCtx.BuildCachePath.MkdirAll()
127154
if err != nil {
155+
telemetry.Engine.Incr("compile", stats.M(tags)...)
128156
return nil, fmt.Errorf("cannot create build cache directory: %s", err)
129157
}
130158
}
@@ -157,13 +185,18 @@ func Compile(ctx context.Context, req *rpc.CompileReq, outStream, errStream io.W
157185

158186
// if --preprocess or --show-properties were passed, we can stop here
159187
if req.GetShowProperties() {
188+
tags["success"] = "true"
189+
telemetry.Engine.Incr("compile", stats.M(tags)...)
160190
return &rpc.CompileResp{}, builder.RunParseHardwareAndDumpBuildProperties(builderCtx)
161191
} else if req.GetPreprocess() {
192+
tags["success"] = "true"
193+
telemetry.Engine.Incr("compile", stats.M(tags)...)
162194
return &rpc.CompileResp{}, builder.RunPreprocess(builderCtx)
163195
}
164196

165197
// if it's a regular build, go on...
166198
if err := builder.RunBuilder(builderCtx); err != nil {
199+
telemetry.Engine.Incr("compile", stats.M(tags)...)
167200
return nil, err
168201
}
169202

@@ -199,6 +232,7 @@ func Compile(ctx context.Context, req *rpc.CompileReq, outStream, errStream io.W
199232
// Copy "sketch.ino.*.hex" / "sketch.ino.*.bin" artifacts to sketch directory
200233
srcDir, err := outputPath.Parent().ReadDir() // read "/build/path/*"
201234
if err != nil {
235+
telemetry.Engine.Incr("compile", stats.M(tags)...)
202236
return nil, fmt.Errorf("reading build directory: %s", err)
203237
}
204238
srcDir.FilterPrefix(base + ".")
@@ -209,6 +243,7 @@ func Compile(ctx context.Context, req *rpc.CompileReq, outStream, errStream io.W
209243
dstOutput := exportPath.Join(exportFile + srcFilename)
210244
logrus.WithField("from", srcOutput).WithField("to", dstOutput).Debug("copying sketch build output")
211245
if err = srcOutput.CopyTo(dstOutput); err != nil {
246+
telemetry.Engine.Incr("compile", stats.M(tags)...)
212247
return nil, fmt.Errorf("copying output file: %s", err)
213248
}
214249
}
@@ -219,11 +254,13 @@ func Compile(ctx context.Context, req *rpc.CompileReq, outStream, errStream io.W
219254
dstElf := exportPath.Join(exportFile + ".elf")
220255
logrus.WithField("from", srcElf).WithField("to", dstElf).Debug("copying sketch build output")
221256
if err = srcElf.CopyTo(dstElf); err != nil {
257+
telemetry.Engine.Incr("compile", stats.M(tags)...)
222258
return nil, fmt.Errorf("copying elf file: %s", err)
223259
}
224260
}
225261

226262
logrus.Tracef("Compile %s for %s successful", sketch.Name, fqbnIn)
227-
263+
tags["success"] = "true"
264+
telemetry.Engine.Incr("compile", stats.M(tags)...)
228265
return &rpc.CompileResp{}, nil
229266
}

telemetry/telemetry.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,36 @@
11
package telemetry
2+
3+
import (
4+
"net/http"
5+
6+
"github.com/segmentio/stats/v4"
7+
"github.com/segmentio/stats/v4/prometheus"
8+
"github.com/sirupsen/logrus"
9+
)
10+
11+
// Engine is the engine used by global helper functions for this module.
12+
var Engine = stats.DefaultEngine
13+
14+
var serverAddr = ":2112"
15+
var serverPattern = "/metrics"
16+
17+
//Activate configure and starts the telemetry server exposing a Prometheus resource
18+
func Activate(metricPrefix string) {
19+
// Configure telemetry engine
20+
// Create a Prometheus default handler
21+
ph := prometheus.DefaultHandler
22+
// Replace the default stats engine with an engine that prepends the "daemon" prefix to all metrics
23+
Engine = stats.WithPrefix(metricPrefix)
24+
// Register the handler so it receives metrics from the default engine.
25+
Engine.Register(ph)
26+
// Flush the default stats engine on return to ensure all buffered
27+
// metrics are sent to the server.
28+
defer Engine.Flush()
29+
// move everything inside commands and search for setting up a common prefix for all metrics sent!
30+
logrus.Infof("Setting up Prometheus telemetry on %s%s", serverAddr, serverPattern)
31+
go func() {
32+
http.Handle(serverPattern, ph)
33+
logrus.Error(http.ListenAndServe(serverAddr, nil))
34+
}()
35+
36+
}

0 commit comments

Comments
 (0)