Skip to content

Commit 0dc2da2

Browse files
authored
Merge branch 'main' into feat/read-config-file
2 parents 4761bb3 + e8e7e96 commit 0dc2da2

18 files changed

+290
-146
lines changed

.github/workflows/ci.yaml

+3-3
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
with:
2828
fetch-depth: 0
2929
- name: TruffleHog OSS
30-
uses: trufflesecurity/trufflehog@v3.63.8
30+
uses: trufflesecurity/trufflehog@v3.67.6
3131
with:
3232
path: ./
3333
base: ${{ github.event.repository.default_branch }}
@@ -46,10 +46,10 @@ jobs:
4646
cache: false
4747
- run: go install golang.org/x/tools/cmd/goimports@latest
4848
- name: golangci-lint
49-
uses: golangci/golangci-lint-action@v3
49+
uses: golangci/golangci-lint-action@v4
5050
with:
5151
version: latest
52-
- uses: pre-commit/[email protected].0
52+
- uses: pre-commit/[email protected].1
5353

5454
test-vroom:
5555
runs-on: ubuntu-latest

CHANGELOG.md

+26
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,42 @@
11
# Changelog
22

3+
## Unreleased
4+
35
**Features**:
46

57
- Add support for speedscope rendering of Android reactnative profiles ([#386](https://github.com/getsentry/vroom/pull/386))
8+
- Add callTree generation for reactnative (android+js) profiles ([#390](https://github.com/getsentry/vroom/pull/390))
9+
- Use profiles that were not dynamically sampled to enhance slowest functions aggregation ([#300](https://github.com/getsentry/vroom/pull/300))
610

711
**Bug Fixes**:
812

13+
- Label all node frames as system ([#392](https://github.com/getsentry/vroom/pull/392))
14+
- Fix react-native (android) rendering issue ([#397](https://github.com/getsentry/vroom/pull/397))
15+
916
**Internal**:
1017

1118
- Bump trufflesecurity/trufflehog from 3.63.4 to 3.63.5 ([#381](https://github.com/getsentry/vroom/pull/381))
1219
- Bump trufflesecurity/trufflehog from 3.63.5 to 3.63.7 ([#385](https://github.com/getsentry/vroom/pull/385))
1320
- Bump number of workers for flamegraph dynamically ([#388](https://github.com/getsentry/vroom/pull/388))
21+
- Bump trufflesecurity/trufflehog from 3.63.8 to 3.63.9 ([#389](https://github.com/getsentry/vroom/pull/389))
22+
- Bump trufflesecurity/trufflehog from 3.63.9 to 3.63.10 ([#391](https://github.com/getsentry/vroom/pull/391))
23+
- Bump trufflesecurity/trufflehog from 3.63.10 to 3.63.11 ([#393](https://github.com/getsentry/vroom/pull/393))
24+
- Ref(functions): Clean up Kafka message ([#394](https://github.com/getsentry/vroom/pull/394))
25+
- Bump trufflesecurity/trufflehog from 3.63.11 to 3.64.0 ([#395](https://github.com/getsentry/vroom/pull/395))
26+
- Bump trufflesecurity/trufflehog from 3.64.0 to 3.65.0 ([#396](https://github.com/getsentry/vroom/pull/396))
27+
- Bump trufflesecurity/trufflehog from 3.65.0 to 3.66.1 ([#398](https://github.com/getsentry/vroom/pull/398))
28+
- Bump trufflesecurity/trufflehog from 3.66.1 to 3.66.2 ([#399](https://github.com/getsentry/vroom/pull/399))
29+
- Bump trufflesecurity/trufflehog from 3.66.2 to 3.66.3 ([#400](https://github.com/getsentry/vroom/pull/400))
30+
- Bump trufflesecurity/trufflehog from 3.66.3 to 3.67.0 ([#401](https://github.com/getsentry/vroom/pull/401))
31+
- Bump trufflesecurity/trufflehog from 3.67.0 to 3.67.1 ([#402](https://github.com/getsentry/vroom/pull/402))
32+
- Refactor flamegraph workers sping-off logic ([#403](https://github.com/getsentry/vroom/pull/403))
33+
- Bump trufflesecurity/trufflehog from 3.67.1 to 3.67.3 ([#404](https://github.com/getsentry/vroom/pull/404))
34+
- Bump pre-commit/action from 3.0.0 to 3.0.1 ([#405](https://github.com/getsentry/vroom/pull/405))
35+
- Bump trufflesecurity/trufflehog from 3.67.3 to 3.67.4 ([#406](https://github.com/getsentry/vroom/pull/406))
36+
- Bump trufflesecurity/trufflehog from 3.67.4 to 3.67.5 ([#407](https://github.com/getsentry/vroom/pull/407))
37+
- Bump golangci/golangci-lint-action from 3 to 4 ([#408](https://github.com/getsentry/vroom/pull/408))
38+
- Remove experimental function regression issue ([#409](https://github.com/getsentry/vroom/pull/409))
39+
- Bump trufflesecurity/trufflehog from 3.67.5 to 3.67.6 ([#411](https://github.com/getsentry/vroom/pull/411))
1440

1541
## 23.12.0
1642

cmd/vroom/flamegraph.go

+2-7
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package main
33
import (
44
"encoding/json"
55
"errors"
6-
"math"
76
"net/http"
87
"strconv"
98
"time"
@@ -139,12 +138,8 @@ func (env *environment) postFlamegraphFromProfileIDs(w http.ResponseWriter, r *h
139138
return
140139
}
141140

142-
var numWorkers int
143-
if len(profiles.ProfileIDs) < minNumWorkers {
144-
numWorkers = len(profiles.ProfileIDs)
145-
} else {
146-
numWorkers = int(math.Ceil((float64(len(profiles.ProfileIDs)) / 100) * float64(minNumWorkers)))
147-
}
141+
numWorkers := getFlamegraphNumWorkers(len(profiles.ProfileIDs), minNumWorkers)
142+
148143
s = sentry.StartSpan(ctx, "processing")
149144
speedscope, err := flamegraph.GetFlamegraphFromProfiles(ctx, env.storage, organizationID, projectID, profiles.ProfileIDs, profiles.Spans, numWorkers, timeout)
150145
if err != nil {

cmd/vroom/kafka.go

+20-42
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package main
22

33
import (
4-
"strconv"
5-
64
"github.com/getsentry/vroom/internal/nodetree"
75
"github.com/getsentry/vroom/internal/platform"
86
"github.com/getsentry/vroom/internal/profile"
@@ -11,22 +9,16 @@ import (
119
type (
1210
// FunctionsKafkaMessage is representing the struct we send to Kafka to insert functions in ClickHouse.
1311
FunctionsKafkaMessage struct {
14-
Functions []nodetree.CallTreeFunction `json:"functions"`
15-
Environment string `json:"environment,omitempty"`
16-
ID string `json:"profile_id"`
17-
Platform platform.Platform `json:"platform"`
18-
ProjectID uint64 `json:"project_id"`
19-
Received int64 `json:"received"`
20-
Release string `json:"release,omitempty"`
21-
Dist string `json:"dist,omitempty"`
22-
RetentionDays int `json:"retention_days"`
23-
Timestamp int64 `json:"timestamp"`
24-
TransactionName string `json:"transaction_name"`
25-
TransactionOp string `json:"transaction_op"`
26-
TransactionStatus string `json:"transaction_status"`
27-
HTTPMethod string `json:"http_method,omitempty"`
28-
BrowserName string `json:"browser_name,omitempty"`
29-
DeviceClass uint64 `json:"device_class,omitempty"`
12+
Environment string `json:"environment,omitempty"`
13+
Functions []nodetree.CallTreeFunction `json:"functions"`
14+
ID string `json:"profile_id"`
15+
Platform platform.Platform `json:"platform"`
16+
ProjectID uint64 `json:"project_id"`
17+
Received int64 `json:"received"`
18+
Release string `json:"release,omitempty"`
19+
RetentionDays int `json:"retention_days"`
20+
Timestamp int64 `json:"timestamp"`
21+
TransactionName string `json:"transaction_name"`
3022
}
3123

3224
// ProfileKafkaMessage is representing the struct we send to Kafka to insert a profile in ClickHouse.
@@ -57,31 +49,17 @@ type (
5749
)
5850

5951
func buildFunctionsKafkaMessage(p profile.Profile, functions []nodetree.CallTreeFunction) FunctionsKafkaMessage {
60-
tm := p.TransactionMetadata()
61-
tt := p.TransactionTags()
62-
63-
deviceClass, err := strconv.ParseUint(tt["device.class"], 10, 8)
64-
if err != nil {
65-
deviceClass = 0
66-
}
67-
6852
return FunctionsKafkaMessage{
69-
Functions: functions,
70-
Environment: p.Environment(),
71-
ID: p.ID(),
72-
Platform: p.Platform(),
73-
ProjectID: p.ProjectID(),
74-
Received: p.Received().Unix(),
75-
Release: p.Release(),
76-
Dist: tm.Dist,
77-
RetentionDays: p.RetentionDays(),
78-
Timestamp: p.Timestamp().Unix(),
79-
TransactionName: p.Transaction().Name,
80-
TransactionOp: tm.TransactionOp,
81-
TransactionStatus: tm.TransactionStatus,
82-
HTTPMethod: tm.HTTPMethod,
83-
BrowserName: tt["browser.name"],
84-
DeviceClass: deviceClass,
53+
Environment: p.Environment(),
54+
Functions: functions,
55+
ID: p.ID(),
56+
Platform: p.Platform(),
57+
ProjectID: p.ProjectID(),
58+
Received: p.Received().Unix(),
59+
Release: p.Release(),
60+
RetentionDays: p.RetentionDays(),
61+
Timestamp: p.Timestamp().Unix(),
62+
TransactionName: p.Transaction().Name,
8563
}
8664
}
8765

cmd/vroom/profile.go

+82-62
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ import (
2323
"github.com/getsentry/vroom/internal/storageutil"
2424
)
2525

26-
const maxUniqueFunctionsPerProfile = 100
26+
const (
27+
maxUniqueFunctionsPerProfile = 100
28+
unsampledProfileID = "00000000000000000000000000000000"
29+
)
2730

2831
func (env *environment) postProfile(w http.ResponseWriter, r *http.Request) {
2932
ctx := r.Context()
@@ -71,24 +74,34 @@ func (env *environment) postProfile(w http.ResponseWriter, r *http.Request) {
7174
p.Normalize()
7275
s.Finish()
7376

74-
s = sentry.StartSpan(ctx, "gcs.write")
75-
s.Description = "Write profile to GCS"
76-
err = storageutil.CompressedWrite(ctx, env.storage, p.StoragePath(), p)
77-
s.Finish()
78-
if err != nil {
79-
if errors.Is(err, context.DeadlineExceeded) {
80-
// This is a transient error, we'll retry
81-
w.WriteHeader(http.StatusTooManyRequests)
82-
} else {
83-
// These errors won't be retried
84-
hub.CaptureException(err)
85-
if code := gcerrors.Code(err); code == gcerrors.FailedPrecondition {
86-
w.WriteHeader(http.StatusPreconditionFailed)
77+
if !p.IsSampled() {
78+
// if we're dealing with an unsampled profile
79+
// we'll assign the special "000....00" profile ID
80+
// so that we can handle it accordingly either in
81+
// either of snuba/sentry/front-end
82+
p.SetProfileID(unsampledProfileID)
83+
}
84+
85+
if p.IsSampled() {
86+
s = sentry.StartSpan(ctx, "gcs.write")
87+
s.Description = "Write profile to GCS"
88+
err = storageutil.CompressedWrite(ctx, env.storage, p.StoragePath(), p)
89+
s.Finish()
90+
if err != nil {
91+
if errors.Is(err, context.DeadlineExceeded) {
92+
// This is a transient error, we'll retry
93+
w.WriteHeader(http.StatusTooManyRequests)
8794
} else {
88-
w.WriteHeader(http.StatusInternalServerError)
95+
// These errors won't be retried
96+
hub.CaptureException(err)
97+
if code := gcerrors.Code(err); code == gcerrors.FailedPrecondition {
98+
w.WriteHeader(http.StatusPreconditionFailed)
99+
} else {
100+
w.WriteHeader(http.StatusInternalServerError)
101+
}
89102
}
103+
return
90104
}
91-
return
92105
}
93106

94107
s = sentry.StartSpan(ctx, "processing")
@@ -102,35 +115,40 @@ func (env *environment) postProfile(w http.ResponseWriter, r *http.Request) {
102115
}
103116

104117
if len(callTrees) > 0 {
105-
s = sentry.StartSpan(ctx, "processing")
106-
s.Description = "Find occurrences"
107-
occurrences := occurrence.Find(p, callTrees)
108-
s.Finish()
118+
// if the profile was not sampled we skip find_occurrences since we're only
119+
// interested in extracting data to improve functions aggregations not in
120+
// using it for finding occurrences of an issue
121+
if p.IsSampled() {
122+
s = sentry.StartSpan(ctx, "processing")
123+
s.Description = "Find occurrences"
124+
occurrences := occurrence.Find(p, callTrees)
125+
s.Finish()
109126

110-
// Filter in-place occurrences without a type.
111-
var i int
112-
for _, o := range occurrences {
113-
if o.Type != occurrence.NoneType {
114-
occurrences[i] = o
115-
i++
127+
// Filter in-place occurrences without a type.
128+
var i int
129+
for _, o := range occurrences {
130+
if o.Type != occurrence.NoneType {
131+
occurrences[i] = o
132+
i++
133+
}
116134
}
117-
}
118-
occurrences = occurrences[:i]
119-
s = sentry.StartSpan(ctx, "processing")
120-
s.Description = "Build Kafka message batch"
121-
occurrenceMessages, err := occurrence.GenerateKafkaMessageBatch(occurrences)
122-
s.Finish()
123-
if err != nil {
124-
// Report the error but don't fail profile insertion
125-
hub.CaptureException(err)
126-
} else {
135+
occurrences = occurrences[:i]
127136
s = sentry.StartSpan(ctx, "processing")
128-
s.Description = "Send occurrences to Kafka"
129-
err = env.occurrencesWriter.WriteMessages(ctx, occurrenceMessages...)
137+
s.Description = "Build Kafka message batch"
138+
occurrenceMessages, err := occurrence.GenerateKafkaMessageBatch(occurrences)
130139
s.Finish()
131140
if err != nil {
132141
// Report the error but don't fail profile insertion
133142
hub.CaptureException(err)
143+
} else {
144+
s = sentry.StartSpan(ctx, "processing")
145+
s.Description = "Send occurrences to Kafka"
146+
err = env.occurrencesWriter.WriteMessages(ctx, occurrenceMessages...)
147+
s.Finish()
148+
if err != nil {
149+
// Report the error but don't fail profile insertion
150+
hub.CaptureException(err)
151+
}
134152
}
135153
}
136154

@@ -164,31 +182,33 @@ func (env *environment) postProfile(w http.ResponseWriter, r *http.Request) {
164182
}
165183
}
166184

167-
// Prepare profile Kafka message
168-
s = sentry.StartSpan(ctx, "processing")
169-
s.Description = "Marshal profile metadata Kafka message"
170-
b, err := json.Marshal(buildProfileKafkaMessage(p))
171-
s.Finish()
172-
if err != nil {
173-
hub.CaptureException(err)
174-
w.WriteHeader(http.StatusInternalServerError)
175-
return
176-
}
185+
if p.IsSampled() {
186+
// Prepare profile Kafka message
187+
s = sentry.StartSpan(ctx, "processing")
188+
s.Description = "Marshal profile metadata Kafka message"
189+
b, err := json.Marshal(buildProfileKafkaMessage(p))
190+
s.Finish()
191+
if err != nil {
192+
hub.CaptureException(err)
193+
w.WriteHeader(http.StatusInternalServerError)
194+
return
195+
}
177196

178-
s = sentry.StartSpan(ctx, "processing")
179-
s.Description = "Send profile metadata to Kafka"
180-
err = env.profilingWriter.WriteMessages(ctx, kafka.Message{
181-
Topic: env.config.Profiling.ProfilesKafkaTopic,
182-
Value: b,
183-
})
184-
s.Finish()
185-
hub.Scope().SetContext("Profile metadata Kafka payload", map[string]interface{}{
186-
"Size": len(b),
187-
})
188-
if err != nil {
189-
hub.CaptureException(err)
190-
w.WriteHeader(http.StatusInternalServerError)
191-
return
197+
s = sentry.StartSpan(ctx, "processing")
198+
s.Description = "Send profile metadata to Kafka"
199+
err = env.profilingWriter.WriteMessages(ctx, kafka.Message{
200+
Topic: env.config.Profiling.ProfilesKafkaTopic,
201+
Value: b,
202+
})
203+
s.Finish()
204+
hub.Scope().SetContext("Profile metadata Kafka payload", map[string]interface{}{
205+
"Size": len(b),
206+
})
207+
if err != nil {
208+
hub.CaptureException(err)
209+
w.WriteHeader(http.StatusInternalServerError)
210+
return
211+
}
192212
}
193213

194214
w.WriteHeader(http.StatusNoContent)

cmd/vroom/utils.go

+9
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

33
import (
44
"context"
5+
"math"
56
"net/url"
67
"strconv"
78

@@ -144,3 +145,11 @@ func (e *environment) functionsQueryBuilderFromRequest(
144145

145146
return sqb, nil
146147
}
148+
149+
func getFlamegraphNumWorkers(numProfiles, minNumWorkers int) int {
150+
if numProfiles < minNumWorkers {
151+
return numProfiles
152+
}
153+
v := int(math.Ceil((float64(numProfiles) / 100) * float64(minNumWorkers)))
154+
return max(v, minNumWorkers)
155+
}

0 commit comments

Comments
 (0)