@@ -10,17 +10,14 @@ import (
10
10
"strings"
11
11
"sync"
12
12
13
- "github.com/cespare/xxhash/v2"
14
13
"github.com/grafana/dskit/multierror"
15
- "github.com/oklog/ulid"
16
14
"github.com/parquet-go/parquet-go"
17
15
"github.com/prometheus/common/model"
18
16
"github.com/prometheus/prometheus/storage"
19
17
"golang.org/x/sync/errgroup"
20
18
21
19
metastorev1 "github.com/grafana/pyroscope/api/gen/proto/go/metastore/v1"
22
20
"github.com/grafana/pyroscope/pkg/experiment/block/metadata"
23
- "github.com/grafana/pyroscope/pkg/experiment/metrics"
24
21
phlaremodel "github.com/grafana/pyroscope/pkg/model"
25
22
"github.com/grafana/pyroscope/pkg/objstore"
26
23
"github.com/grafana/pyroscope/pkg/phlaredb/block"
@@ -54,11 +51,30 @@ func WithCompactionDestination(storage objstore.Bucket) CompactionOption {
54
51
}
55
52
}
56
53
54
+ func WithSampleObserver (observer SampleObserver ) CompactionOption {
55
+ return func (p * compactionConfig ) {
56
+ p .sampleObserver = observer
57
+ }
58
+ }
59
+
57
60
type compactionConfig struct {
58
- objectOptions []ObjectOption
59
- tempdir string
60
- source objstore.BucketReader
61
- destination objstore.Bucket
61
+ objectOptions []ObjectOption
62
+ tempdir string
63
+ source objstore.BucketReader
64
+ destination objstore.Bucket
65
+ sampleObserver SampleObserver
66
+ }
67
+
68
+ type SampleObserver interface {
69
+ // Observe is called before the compactor appends the entry
70
+ // to the output block. This method must not modify the entry.
71
+ Observe (ProfileEntry )
72
+
73
+ // Flush is called before the compactor flushes the output dataset.
74
+ // This call invalidates all references (such as symbols) to the source
75
+ // and output blocks. Any error returned by the call terminates the
76
+ // compaction job: it's caller responsibility to suppress errors.
77
+ Flush () error
62
78
}
63
79
64
80
func Compact (
@@ -91,19 +107,11 @@ func Compact(
91
107
92
108
compacted := make ([]* metastorev1.BlockMeta , 0 , len (plan ))
93
109
for _ , p := range plan {
94
- md , compactionErr := p .Compact (ctx , c .destination , c .tempdir )
110
+ md , compactionErr := p .Compact (ctx , c .destination , c .tempdir , c . sampleObserver )
95
111
if compactionErr != nil {
96
112
return nil , compactionErr
97
113
}
98
114
compacted = append (compacted , md )
99
-
100
- if p .metricsExporter != nil {
101
- go func () {
102
- if sendErr := p .SendRecordedMetrics (); sendErr != nil {
103
- println ("ERROR" , sendErr ) // TODO
104
- }
105
- }()
106
- }
107
115
}
108
116
109
117
return compacted , nil
@@ -160,13 +168,12 @@ func PlanCompaction(objects Objects) ([]*CompactionPlan, error) {
160
168
}
161
169
162
170
type CompactionPlan struct {
163
- tenant string
164
- path string
165
- datasetMap map [int32 ]* datasetCompaction
166
- datasets []* datasetCompaction
167
- meta * metastorev1.BlockMeta
168
- strings * metadata.StringTable
169
- metricsExporter * metrics.Exporter
171
+ tenant string
172
+ path string
173
+ datasetMap map [int32 ]* datasetCompaction
174
+ datasets []* datasetCompaction
175
+ meta * metastorev1.BlockMeta
176
+ strings * metadata.StringTable
170
177
}
171
178
172
179
func newBlockCompaction (
@@ -188,27 +195,30 @@ func newBlockCompaction(
188
195
Shard : shard ,
189
196
CompactionLevel : compactionLevel ,
190
197
}
191
- if compactionLevel == 1 {
192
- p .metricsExporter = metrics .NewExporter (tenant )
193
- }
194
198
return p
195
199
}
196
200
197
- func (b * CompactionPlan ) Compact (ctx context.Context , dst objstore.Bucket , tmpdir string ) (m * metastorev1.BlockMeta , err error ) {
201
+ func (b * CompactionPlan ) Compact (
202
+ ctx context.Context ,
203
+ dst objstore.Bucket ,
204
+ tmpdir string ,
205
+ observer SampleObserver ,
206
+ ) (m * metastorev1.BlockMeta , err error ) {
198
207
w := NewBlockWriter (dst , b .path , tmpdir )
199
208
defer func () {
200
209
err = multierror .New (err , w .Close ()).Err ()
201
210
}()
202
211
// Datasets are compacted in a strict order.
203
212
for _ , s := range b .datasets {
213
+ s .registerSampleObserver (observer )
204
214
if err = s .compact (ctx , w ); err != nil {
205
215
return nil , fmt .Errorf ("compacting block: %w" , err )
206
216
}
207
- if b .metricsExporter != nil {
208
- b .metricsExporter .AppendMetrics (s .metricsRecorder .Recordings )
209
- }
210
217
b .meta .Datasets = append (b .meta .Datasets , s .meta )
211
218
}
219
+ if err = observer .Flush (); err != nil {
220
+ return nil , fmt .Errorf ("flushing sample observer: %w" , err )
221
+ }
212
222
if err = w .Flush (ctx ); err != nil {
213
223
return nil , fmt .Errorf ("flushing block writer: %w" , err )
214
224
}
@@ -235,10 +245,6 @@ func (b *CompactionPlan) addDataset(md *metastorev1.BlockMeta, s *metastorev1.Da
235
245
return sm
236
246
}
237
247
238
- func (c * CompactionPlan ) SendRecordedMetrics () error {
239
- return c .metricsExporter .Send ()
240
- }
241
-
242
248
type datasetCompaction struct {
243
249
// Dataset name.
244
250
name string
@@ -259,7 +265,7 @@ type datasetCompaction struct {
259
265
260
266
flushOnce sync.Once
261
267
262
- metricsRecorder * metrics. Recorder
268
+ observer SampleObserver
263
269
}
264
270
265
271
func (b * CompactionPlan ) newDatasetCompaction (tenant , name int32 ) * datasetCompaction {
@@ -308,6 +314,10 @@ func (m *datasetCompaction) compact(ctx context.Context, w *Writer) (err error)
308
314
return nil
309
315
}
310
316
317
+ func (m * datasetCompaction ) registerSampleObserver (observer SampleObserver ) {
318
+ m .observer = observer
319
+ }
320
+
311
321
func (m * datasetCompaction ) open (ctx context.Context , path string ) (err error ) {
312
322
m .path = path
313
323
defer func () {
@@ -333,13 +343,6 @@ func (m *datasetCompaction) open(ctx context.Context, path string) (err error) {
333
343
m .indexRewriter = newIndexRewriter (m .path )
334
344
m .symbolsRewriter = newSymbolsRewriter (m .path )
335
345
336
- if m .parent .meta .CompactionLevel == 1 {
337
- recordingTime := int64 (ulid .MustParse (m .parent .meta .Id ).Time ())
338
- rules := metrics .RecordingRulesFromTenant (m .parent .tenant )
339
- pyroscopeInstance := pyroscopeInstanceHash (m .parent .meta .Shard , m .parent .meta .CreatedBy )
340
- m .metricsRecorder = metrics .NewRecorder (rules , recordingTime , pyroscopeInstance )
341
- }
342
-
343
346
g , ctx := errgroup .WithContext (ctx )
344
347
for _ , s := range m .datasets {
345
348
s := s
@@ -361,13 +364,6 @@ func (m *datasetCompaction) open(ctx context.Context, path string) (err error) {
361
364
return nil
362
365
}
363
366
364
- func pyroscopeInstanceHash (shard uint32 , createdBy int32 ) string {
365
- buf := make ([]byte , 0 , 8 )
366
- buf = append (buf , byte (shard >> 24 ), byte (shard >> 16 ), byte (shard >> 8 ), byte (shard ))
367
- buf = append (buf , byte (createdBy >> 24 ), byte (createdBy >> 16 ), byte (createdBy >> 8 ), byte (createdBy ))
368
- return fmt .Sprintf ("%x" , xxhash .Sum64 (buf ))
369
- }
370
-
371
367
func (m * datasetCompaction ) mergeAndClose (ctx context.Context ) (err error ) {
372
368
defer func () {
373
369
err = multierror .New (err , m .close ()).Err ()
@@ -404,9 +400,7 @@ func (m *datasetCompaction) writeRow(r ProfileEntry) (err error) {
404
400
if err = m .symbolsRewriter .rewriteRow (r ); err != nil {
405
401
return err
406
402
}
407
- if m .metricsRecorder != nil {
408
- m .metricsRecorder .RecordRow (r .Fingerprint , r .Labels , r .Row .TotalValue ())
409
- }
403
+ m .observer .Observe (r )
410
404
return m .profilesWriter .writeRow (r )
411
405
}
412
406
0 commit comments