Skip to content

Commit 1488496

Browse files
authored
Extend profile schema to support spans (#2508)
1 parent ebd6fd1 commit 1488496

File tree

21 files changed

+608
-48
lines changed

21 files changed

+608
-48
lines changed

‎cmd/pyroscope/help-all.txt.tmpl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,8 @@ Usage of ./pyroscope:
881881
Comma-separated list of Pyroscope modules to load. The alias 'all' can be used in the list to load a number of core modules and will enable single-binary mode. (default all)
882882
-tracing.enabled
883883
Set to false to disable tracing. (default true)
884+
-tracing.profiling-enabled
885+
[experimental] Set to true to enable profiling integration.
884886
-usage-stats.enabled
885887
Enable anonymous usage reporting. (default true)
886888
-validation.max-label-names-per-series int

‎docs/sources/configure-server/reference-configuration-parameters/index.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ limits:
110110
# CLI flag: -validation.max-label-names-per-series
111111
[max_label_names_per_series: <int> | default = 30]
112112

113+
# Maximum number of sessions per series. 0 to disable.
114+
# CLI flag: -validation.max-sessions-per-series
115+
[max_sessions_per_series: <int> | default = 0]
116+
113117
# Maximum size of a profile in bytes. This is based off the uncompressed size.
114118
# 0 to disable.
115119
# CLI flag: -validation.max-profile-size-bytes
@@ -714,7 +718,8 @@ grpc_tls_config:
714718
# CLI flag: -server.grpc-max-send-msg-size-bytes
715719
[grpc_server_max_send_msg_size: <int> | default = 4194304]
716720
717-
# Limit on the number of concurrent streams for gRPC calls (0 = unlimited)
721+
# Limit on the number of concurrent streams for gRPC calls per client connection
722+
# (0 = unlimited)
718723
# CLI flag: -server.grpc-max-concurrent-streams
719724
[grpc_server_max_concurrent_streams: <int> | default = 100]
720725

‎examples/golang-push/rideshare/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ go 1.17
55
require (
66
github.com/agoda-com/opentelemetry-logs-go v0.4.1-0.20231002083708-3defe69e69e4
77
github.com/grafana/pyroscope-go v1.0.4
8-
github.com/pyroscope-io/otel-profiling-go v0.4.1-0.20220827003940-ddd28219c77e
8+
github.com/grafana/pyroscope-go/otelpyroscope v0.0.0-20231017042744-3f66066f8d6c
99
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0
1010
go.opentelemetry.io/otel v1.19.0
1111
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0

‎examples/golang-push/rideshare/go.sum

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -844,7 +844,6 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2
844844
github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U=
845845
github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk=
846846
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
847-
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
848847
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
849848
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
850849
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
@@ -962,6 +961,8 @@ github.com/grafana/pyroscope-go v1.0.4 h1:oyQX0BOkL+iARXzHuCdIF5TQ7/sRSel1YFViMH
962961
github.com/grafana/pyroscope-go v1.0.4/go.mod h1:0d7ftwSMBV/Awm7CCiYmHQEG8Y44Ma3YSjt+nWcWztY=
963962
github.com/grafana/pyroscope-go/godeltaprof v0.1.4 h1:mDsJ3ngul7UfrHibGQpV66PbZ3q1T8glz/tK3bQKKEk=
964963
github.com/grafana/pyroscope-go/godeltaprof v0.1.4/go.mod h1:1HSPtjU8vLG0jE9JrTdzjgFqdJ/VgN7fvxBNq3luJko=
964+
github.com/grafana/pyroscope-go/otelpyroscope v0.0.0-20231017042744-3f66066f8d6c h1:5FS9csedLnPXy11nCpr7LfIyhok+cVxUYNqSTDq1bzM=
965+
github.com/grafana/pyroscope-go/otelpyroscope v0.0.0-20231017042744-3f66066f8d6c/go.mod h1:OhQkRYO2Iepoi2sRGUhyMp0tq1w57idp1/sz6OZGAA4=
965966
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
966967
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
967968
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks=
@@ -1017,8 +1018,6 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
10171018
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
10181019
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
10191020
github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
1020-
github.com/pyroscope-io/otel-profiling-go v0.4.1-0.20220827003940-ddd28219c77e h1:gUdiXKQ2a6NehosBbAIZUHxBjEvzRDxjV4xn0QKcSrs=
1021-
github.com/pyroscope-io/otel-profiling-go v0.4.1-0.20220827003940-ddd28219c77e/go.mod h1:y3pdNLRjeZi34yk7Fc1ema4SWtBEpE7Zd/rMdSfQTa8=
10221021
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
10231022
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
10241023
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
@@ -1067,7 +1066,6 @@ go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
10671066
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
10681067
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0 h1:pginetY7+onl4qN1vl0xW/V/v6OBZ0vVdH+esuJgvmM=
10691068
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0/go.mod h1:XiYsayHc36K3EByOO6nbAXnAWbrUxdjUROCEeeROOH8=
1070-
go.opentelemetry.io/otel v1.9.0/go.mod h1:np4EoPGzoPs3O67xUVNoPPcmSvsfOxNlNA4F4AC+0Eo=
10711069
go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4=
10721070
go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs=
10731071
go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY=
@@ -1082,7 +1080,6 @@ go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPi
10821080
go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8=
10831081
go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o=
10841082
go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A=
1085-
go.opentelemetry.io/otel/trace v1.9.0/go.mod h1:2737Q0MuG8q1uILYm2YYVkAyLtOofiTNGg6VODnOiPo=
10861083
go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0=
10871084
go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg=
10881085
go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo=

‎examples/golang-push/rideshare/loadgen.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@ import (
1010
"strconv"
1111
"time"
1212

13-
"rideshare/rideshare"
14-
13+
"github.com/grafana/pyroscope-go/otelpyroscope"
1514
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
1615
"go.opentelemetry.io/otel"
1716
"go.opentelemetry.io/otel/attribute"
1817
"go.opentelemetry.io/otel/propagation"
18+
19+
"rideshare/rideshare"
1920
)
2021

2122
var hosts = []string{}
@@ -67,7 +68,7 @@ func main() {
6768
// Set the Tracer Provider and the W3C Trace Context propagator as globals.
6869
// We wrap the tracer provider to also annotate goroutines with Span ID so
6970
// that pprof would add corresponding labels to profiling samples.
70-
otel.SetTracerProvider(tp)
71+
otel.SetTracerProvider(otelpyroscope.NewTracerProvider(tp))
7172

7273
// Register the trace c ontext and baggage propagators so data is propagated across services/processes.
7374
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(

‎examples/golang-push/rideshare/main.go

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
1515

1616
otellogs "github.com/agoda-com/opentelemetry-logs-go"
17-
otelpyroscope "github.com/pyroscope-io/otel-profiling-go"
17+
"github.com/grafana/pyroscope-go/otelpyroscope"
1818
"go.opentelemetry.io/otel"
1919
"go.opentelemetry.io/otel/propagation"
2020
sdktrace "go.opentelemetry.io/otel/sdk/trace"
@@ -92,12 +92,7 @@ func setupOTEL(c rideshare.Config) (tp *sdktrace.TracerProvider, err error) {
9292
// Set the Tracer Provider and the W3C Trace Context propagator as globals.
9393
// We wrap the tracer provider to also annotate goroutines with Span ID so
9494
// that pprof would add corresponding labels to profiling samples.
95-
otel.SetTracerProvider(otelpyroscope.NewTracerProvider(tp,
96-
otelpyroscope.WithPyroscopeURL(c.PyroscopeServerAddress),
97-
otelpyroscope.WithAppName(c.AppName),
98-
otelpyroscope.WithRootSpanOnly(true),
99-
otelpyroscope.WithAddSpanName(true),
100-
))
95+
otel.SetTracerProvider(otelpyroscope.NewTracerProvider(tp))
10196

10297
// Register the trace context and baggage propagators so data is propagated across services/processes.
10398
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(

‎examples/tracing/tempo/README.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,8 @@ Pyroscope and the demo application will be built from the current branch. After
3030
4. Specify proper `start` and `end` timestamps (milliseconds).
3131

3232
Please note that the pyroscope SDK is configured to only record root spans, therefore stack trace samples
33-
of child spans are included into the root span profile. This is controlled by [`WithRootSpanOnly`](../../golang-push/rideshare/main.go#L98) option.
34-
35-
In the example we use our old SDK which also adds the `pyroscope.profile.id` attribute – although it
36-
might be convenient in some cases, we have no intent to maintain it. At the moment there is no reliable
37-
way to determine if any profiling data has been collected for a specific span, therefore this
38-
label may mislead.
33+
of child spans are included into the root span profile. These spans are marked with `pyroscope.profiling.enabled`
34+
attribute set to `true`.
3935

4036
#### cURL
4137

‎examples/tracing/tempo/docker-compose.yml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ services:
5151

5252
tempo:
5353
image: grafana/tempo:latest
54-
command: [ "-config.file=/etc/tempo.yaml" ]
54+
command: [ "-config.file=/etc/tempo.yml" ]
5555
volumes:
56-
- ./tempo/tempo.yaml:/etc/tempo.yaml
56+
- ./tempo/tempo.yml:/etc/tempo.yml
5757
ports:
5858
- "14268:14268" # jaeger ingest
5959
- "3200:3200" # tempo
@@ -65,6 +65,13 @@ services:
6565
pyroscope:
6666
ports:
6767
- '4040:4040'
68+
environment:
69+
JAEGER_AGENT_HOST: tempo
70+
JAEGER_SAMPLER_TYPE: const
71+
JAEGER_SAMPLER_PARAM: 1
72+
volumes:
73+
- ./pyroscope/pyroscope.yml:/etc/pyroscope.yml
74+
command: [ "-config.file=/etc/pyroscope.yml" ]
6875
build:
6976
context: '../../../'
7077
dockerfile: cmd/pyroscope/Dockerfile
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
tracing:
2+
enabled: true
3+
profiling_enabled: true
4+
5+
pyroscopedb:
6+
max_block_duration: 5m

‎pkg/phlare/phlare.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
wwtracing "github.com/grafana/dskit/tracing"
3131
"github.com/grafana/pyroscope-go"
3232
grpcgw "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
33+
"github.com/opentracing/opentracing-go"
3334
"github.com/prometheus/client_golang/prometheus"
3435
"github.com/prometheus/common/version"
3536
"github.com/samber/lo"
@@ -53,6 +54,7 @@ import (
5354
"github.com/grafana/pyroscope/pkg/usagestats"
5455
"github.com/grafana/pyroscope/pkg/util"
5556
"github.com/grafana/pyroscope/pkg/util/cli"
57+
"github.com/grafana/pyroscope/pkg/util/spanprofiler"
5658
"github.com/grafana/pyroscope/pkg/validation"
5759
"github.com/grafana/pyroscope/pkg/validation/exporter"
5860
)
@@ -250,6 +252,9 @@ func New(cfg Config) (*Phlare, error) {
250252
if err != nil {
251253
level.Error(logger).Log("msg", "error in initializing tracing. tracing will not be enabled", "err", err)
252254
}
255+
if cfg.Tracing.ProfilingEnabled {
256+
opentracing.SetGlobalTracer(spanprofiler.NewTracer(opentracing.GlobalTracer()))
257+
}
253258
phlare.tracer = trace
254259
}
255260

‎pkg/phlaredb/block_querier_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
ingestv1 "github.com/grafana/pyroscope/api/gen/proto/go/ingester/v1"
1717
typesv1 "github.com/grafana/pyroscope/api/gen/proto/go/types/v1"
1818
"github.com/grafana/pyroscope/pkg/iter"
19+
"github.com/grafana/pyroscope/pkg/model"
1920
"github.com/grafana/pyroscope/pkg/objstore/providers/filesystem"
2021
"github.com/grafana/pyroscope/pkg/phlaredb/block"
2122
"github.com/grafana/pyroscope/pkg/phlaredb/tsdb/index"
@@ -147,6 +148,59 @@ func TestBlockCompatability(t *testing.T) {
147148
}
148149
}
149150

151+
func TestBlockCompatability_SelectMergeSpans(t *testing.T) {
152+
path := "./block/testdata/"
153+
bucket, err := filesystem.NewBucket(path)
154+
require.NoError(t, err)
155+
156+
ctx := context.Background()
157+
metas, err := NewBlockQuerier(ctx, bucket).BlockMetas(ctx)
158+
require.NoError(t, err)
159+
160+
for _, meta := range metas {
161+
t.Run(fmt.Sprintf("block-v%d-%s", meta.Version, meta.ULID.String()), func(t *testing.T) {
162+
q := NewSingleBlockQuerierFromMeta(ctx, bucket, meta)
163+
require.NoError(t, q.Open(ctx))
164+
165+
profilesTypes, err := q.index.LabelValues("__profile_type__")
166+
require.NoError(t, err)
167+
168+
profileCount := 0
169+
170+
for _, profileType := range profilesTypes {
171+
t.Log(profileType)
172+
profileTypeParts := strings.Split(profileType, ":")
173+
174+
it, err := q.SelectMatchingProfiles(ctx, &ingestv1.SelectProfilesRequest{
175+
LabelSelector: "{}",
176+
Start: 0,
177+
End: time.Now().UnixMilli(),
178+
Type: &typesv1.ProfileType{
179+
Name: profileTypeParts[0],
180+
SampleType: profileTypeParts[1],
181+
SampleUnit: profileTypeParts[2],
182+
PeriodType: profileTypeParts[3],
183+
PeriodUnit: profileTypeParts[4],
184+
},
185+
})
186+
require.NoError(t, err)
187+
188+
pcIt := &profileCounter{Iterator: it}
189+
190+
spanSelector, err := model.NewSpanSelector([]string{})
191+
require.NoError(t, err)
192+
resp, err := q.MergeBySpans(ctx, pcIt, spanSelector)
193+
require.NoError(t, err)
194+
195+
require.Zero(t, resp.Total())
196+
profileCount += pcIt.count
197+
}
198+
199+
require.Zero(t, profileCount)
200+
})
201+
}
202+
}
203+
150204
type fakeQuerier struct {
151205
Querier
152206
doErr bool

‎pkg/phlaredb/head_queriers.go

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -160,16 +160,15 @@ func (q *headOnDiskQuerier) Series(ctx context.Context, params *ingestv1.SeriesR
160160
return []*typesv1.Labels{}, nil
161161
}
162162

163-
func (q *headOnDiskQuerier) MergeBySpans(_ context.Context, _ iter.Iterator[Profile], _ phlaremodel.SpanSelector) (*phlaremodel.Tree, error) {
164-
// sp, ctx := opentracing.StartSpanFromContext(ctx, "MergeBySpans")
165-
// defer sp.Finish()
166-
// r := symdb.NewResolver(ctx, q.head.symdb)
167-
// defer r.Release()
168-
// if err := mergeBySpans(ctx, q.rowGroup(), rows, r, spanSelector); err != nil {
169-
// return nil, err
170-
// }
171-
// return r.Tree()
172-
return new(phlaremodel.Tree), nil
163+
func (q *headOnDiskQuerier) MergeBySpans(ctx context.Context, rows iter.Iterator[Profile], spanSelector phlaremodel.SpanSelector) (*phlaremodel.Tree, error) {
164+
sp, ctx := opentracing.StartSpanFromContext(ctx, "MergeBySpans")
165+
defer sp.Finish()
166+
r := symdb.NewResolver(ctx, q.head.symdb)
167+
defer r.Release()
168+
if err := mergeBySpans(ctx, q.rowGroup(), rows, r, spanSelector); err != nil {
169+
return nil, err
170+
}
171+
return r.Tree()
173172
}
174173

175174
func (q *headOnDiskQuerier) Sort(in []Profile) []Profile {

‎pkg/phlaredb/sample_merge.go

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package phlaredb
33
import (
44
"context"
55
"sort"
6+
"strings"
67

78
"github.com/google/pprof/profile"
89
"github.com/opentracing/opentracing-go"
@@ -54,16 +55,15 @@ func (b *singleBlockQuerier) MergeByLabels(ctx context.Context, rows iter.Iterat
5455
return m.normalize(), nil
5556
}
5657

57-
func (b *singleBlockQuerier) MergeBySpans(_ context.Context, _ iter.Iterator[Profile], _ phlaremodel.SpanSelector) (*phlaremodel.Tree, error) {
58-
// sp, _ := opentracing.StartSpanFromContext(ctx, "MergeBySpans - Block")
59-
// defer sp.Finish()
60-
// r := symdb.NewResolver(ctx, b.symbols)
61-
// defer r.Release()
62-
// if err := mergeBySpans(ctx, b.profiles.file, rows, r, spanSelector); err != nil {
63-
// return nil, err
64-
// }
65-
// return r.Tree()
66-
return new(phlaremodel.Tree), nil
58+
func (b *singleBlockQuerier) MergeBySpans(ctx context.Context, rows iter.Iterator[Profile], spanSelector phlaremodel.SpanSelector) (*phlaremodel.Tree, error) {
59+
sp, _ := opentracing.StartSpanFromContext(ctx, "MergeBySpans - Block")
60+
defer sp.Finish()
61+
r := symdb.NewResolver(ctx, b.symbols)
62+
defer r.Release()
63+
if err := mergeBySpans(ctx, b.profiles.file, rows, r, spanSelector); err != nil {
64+
return nil, err
65+
}
66+
return r.Tree()
6767
}
6868

6969
type Source interface {
@@ -94,6 +94,42 @@ func mergeByStacktraces(ctx context.Context, profileSource Source, rows iter.Ite
9494
return it.Err()
9595
}
9696

97+
func mergeBySpans(ctx context.Context, profileSource Source, rows iter.Iterator[Profile], r *symdb.Resolver, spanSelector phlaremodel.SpanSelector) error {
98+
sp, ctx := opentracing.StartSpanFromContext(ctx, "mergeBySpans")
99+
defer sp.Finish()
100+
if _, found := profileSource.Schema().Lookup(strings.Split("Samples.list.element.SpanID", ".")...); !found {
101+
return nil
102+
}
103+
// clone the rows to be able to iterate over them twice
104+
multiRows, err := iter.CloneN(rows, 3)
105+
if err != nil {
106+
return err
107+
}
108+
it := query.NewMultiRepeatedPageIterator(
109+
repeatedColumnIter(ctx, profileSource, "Samples.list.element.StacktraceID", multiRows[0]),
110+
repeatedColumnIter(ctx, profileSource, "Samples.list.element.Value", multiRows[1]),
111+
repeatedColumnIter(ctx, profileSource, "Samples.list.element.SpanID", multiRows[2]),
112+
)
113+
defer it.Close()
114+
for it.Next() {
115+
values := it.At().Values
116+
p := r.Partition(it.At().Row.StacktracePartition())
117+
stacktraces := values[0]
118+
sampleValues := values[1]
119+
spans := values[2]
120+
for i := 0; i < len(stacktraces); i++ {
121+
spanID := spans[i].Uint64()
122+
if spanID == 0 {
123+
continue
124+
}
125+
if _, ok := spanSelector[spanID]; ok {
126+
p[uint32(stacktraces[i].Int64())] += sampleValues[i].Int64()
127+
}
128+
}
129+
}
130+
return it.Err()
131+
}
132+
97133
type seriesByLabels map[string]*typesv1.Series
98134

99135
func (m seriesByLabels) normalize() []*typesv1.Series {

0 commit comments

Comments
 (0)