/
upload.go
115 lines (96 loc) · 2.89 KB
/
upload.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
package main
import (
"context"
"os"
"connectrpc.com/connect"
"github.com/go-kit/log/level"
"github.com/google/uuid"
pushv1 "github.com/grafana/pyroscope/api/gen/proto/go/push/v1"
"github.com/grafana/pyroscope/api/gen/proto/go/push/v1/pushv1connect"
"github.com/grafana/pyroscope/pkg/model"
"github.com/grafana/pyroscope/pkg/pprof"
)
func (c *phlareClient) pusherClient() pushv1connect.PusherServiceClient {
return pushv1connect.NewPusherServiceClient(
c.httpClient(),
c.URL,
)
}
type uploadParams struct {
*phlareClient
paths []string
extraLabels map[string]string
}
func addUploadParams(cmd commander) *uploadParams {
var (
params = &uploadParams{
extraLabels: map[string]string{},
}
)
params.phlareClient = addPhlareClient(cmd)
cmd.Arg("path", "Path(s) to profile(s) to upload").Required().ExistingFilesVar(¶ms.paths)
cmd.Flag("extra-labels", "Add additional labels to the profile(s)").StringMapVar(¶ms.extraLabels)
return params
}
func upload(ctx context.Context, params *uploadParams) (err error) {
pc := params.phlareClient.pusherClient()
lblStrings := make([]string, 0, len(params.extraLabels)*2)
for key, value := range params.extraLabels {
lblStrings = append(lblStrings, key, value)
}
var (
lbl = model.LabelsFromStrings(lblStrings...)
series = make([]*pushv1.RawProfileSeries, len(params.paths))
lblBuilder = model.NewLabelsBuilder(lbl)
)
for idx, path := range params.paths {
lblBuilder.Reset(lbl)
data, err := os.ReadFile(path)
if err != nil {
return nil
}
profile, err := pprof.RawFromBytes(data)
if err != nil {
return err
}
// detect name if no name has been set
if lbl.Get(model.LabelNameProfileName) == "" {
name := "unknown"
for _, t := range profile.Profile.SampleType {
if sid := int(t.Type); sid < len(profile.StringTable) {
if s := profile.StringTable[sid]; s == "cpu" {
name = "process_cpu"
break
} else if s == "alloc_space" || s == "inuse_space" {
name = "memory"
break
} else {
level.Debug(logger).Log("msg", "unspecific/unknown profile sample type", "profile", s)
}
}
}
lblBuilder.Set(model.LabelNameProfileName, name)
}
// set a default service_name label if one is not provided
if lbl.Get(model.LabelNameServiceName) == "" {
lblBuilder.Set(model.LabelNameServiceName, "profilecli-upload")
}
series[idx] = &pushv1.RawProfileSeries{
Labels: lblBuilder.Labels(),
Samples: []*pushv1.RawSample{{
ID: uuid.New().String(),
RawProfile: data,
}},
}
}
_, err = pc.Push(ctx, connect.NewRequest(&pushv1.PushRequest{
Series: series,
}))
if err != nil {
return err
}
for idx := range series {
level.Info(logger).Log("msg", "successfully uploaded profile", "id", series[idx].Samples[0].ID, "labels", model.Labels(series[idx].Labels).ToPrometheusLabels().String(), "path", params.paths[idx])
}
return nil
}