-
Notifications
You must be signed in to change notification settings - Fork 224
/
db.go
104 lines (81 loc) · 2.32 KB
/
db.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
package metrics
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"os/exec"
"time"
"github.com/PuerkitoBio/rehttp"
"github.com/superfly/flyctl/agent"
"github.com/superfly/flyctl/internal/buildinfo"
"github.com/superfly/flyctl/internal/config"
"github.com/superfly/flyctl/iostreams"
)
var metrics []metricsMessage = make([]metricsMessage, 0)
func queueMetric(metric metricsMessage) {
metrics = append(metrics, metric)
}
// Spawns a forked `flyctl metrics send` process that sends metrics to the flyctl-metrics server
func FlushMetrics(ctx context.Context) error {
json, err := json.Marshal(metrics)
if err != nil {
return err
}
iostream := iostreams.FromContext(ctx)
// On CI, always block on metrics send. This sucks, but the alternative is not getting metrics from CI at all. There are timeouts in place to prevent this from taking more than 15 seconds
if iostream.IsInteractive() {
flyctl, err := os.Executable()
if err != nil {
return err
}
cmd := exec.Command(flyctl, "metrics", "send")
stdin, err := cmd.StdinPipe()
if err != nil {
return err
}
go func() {
io.WriteString(stdin, string(json))
stdin.Close()
}()
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, "FLY_NO_UPDATE_CHECK=1")
agent.SetSysProcAttributes(cmd)
if err := cmd.Start(); err != nil {
return err
}
if err := cmd.Process.Release(); err != nil {
return err
}
} else {
SendMetrics(ctx, string(json))
}
return nil
}
// / Spens up to 15 seconds sending all metrics collected so far to flyctl-metrics post endpoint
func SendMetrics(ctx context.Context, json string) error {
authToken, err := GetMetricsToken(ctx)
if err != nil {
return err
}
cfg := config.FromContext(ctx)
request, err := http.NewRequest("POST", cfg.MetricsBaseURL+"/metrics_post", bytes.NewBuffer([]byte(json)))
if err != nil {
return err
}
request.Header.Set("Authorization", authToken)
request.Header.Set("User-Agent", fmt.Sprintf("flyctl/%s", buildinfo.Info().Version))
retryTransport := rehttp.NewTransport(http.DefaultTransport, rehttp.RetryAll(rehttp.RetryMaxRetries(3), rehttp.RetryTimeoutErr()), rehttp.ConstDelay(0))
client := http.Client{
Transport: retryTransport,
Timeout: time.Second * 5,
}
resp, err := client.Do(request)
if err != nil {
return err
}
return resp.Body.Close()
}