66 "os"
77 "path/filepath"
88
9+ "github.com/oklog/ulid"
910 "github.com/pkg/errors"
1011 "github.com/prometheus/common/model"
1112 "github.com/prometheus/prometheus/storage"
@@ -23,20 +24,17 @@ import (
2324)
2425
2526type BlockReader interface {
27+ Meta () block.Meta
2628 Profiles () []parquet.RowGroup
2729 Index () IndexReader
28- // Symbols() SymbolReader
29- }
30-
31- type SymbolReader interface {
32- // todo
30+ // todo symbdb
3331}
3432
3533func Compact (ctx context.Context , src []BlockReader , dst string ) (block.Meta , error ) {
3634 if len (src ) <= 1 {
3735 return block.Meta {}, errors .New ("not enough blocks to compact" )
3836 }
39- meta := block . NewMeta ( )
37+ meta := compactedMeta ( src )
4038 blockPath := filepath .Join (dst , meta .ULID .String ())
4139 if err := os .MkdirAll (blockPath , 0o777 ); err != nil {
4240 return block.Meta {}, err
@@ -59,9 +57,9 @@ func Compact(ctx context.Context, src []BlockReader, dst string) (block.Meta, er
5957 if err != nil {
6058 return block.Meta {}, err
6159 }
62- rowsIt = newSeriesRewriter (rowsIt , indexw )
63- rowsIt = newSymbolsRewriter (rowsIt )
64- reader := phlareparquet .NewIteratorRowReader (newRowsIterator (rowsIt ))
60+ seriesRewriter : = newSeriesRewriter (rowsIt , indexw )
61+ symbolsRewriter : = newSymbolsRewriter (seriesRewriter )
62+ reader := phlareparquet .NewIteratorRowReader (newRowsIterator (symbolsRewriter ))
6563
6664 total , _ , err := phlareparquet .CopyAsRowGroups (profileWriter , reader , defaultParquetConfig .MaxBufferRowCount )
6765 if err != nil {
@@ -78,12 +76,61 @@ func Compact(ctx context.Context, src []BlockReader, dst string) (block.Meta, er
7876 }
7977 // todo: block meta
8078 meta .Stats .NumProfiles = total
79+ meta .Stats .NumSeries = seriesRewriter .NumSeries ()
80+ meta .Stats .NumSamples = symbolsRewriter .NumSamples ()
81+
8182 if _ , err := meta .WriteToFile (util .Logger , blockPath ); err != nil {
8283 return block.Meta {}, err
8384 }
8485 return * meta , nil
8586}
8687
88+ func compactedMeta (src []BlockReader ) * block.Meta {
89+ meta := block .NewMeta ()
90+ highestCompactionLevel := 0
91+ ulids := make ([]ulid.ULID , len (src ))
92+ parents := make ([]tsdb.BlockDesc , len (src ))
93+ minTime , maxTime := model .Latest , model .Earliest
94+ labels := make (map [string ]string )
95+ for _ , b := range src {
96+ if b .Meta ().Compaction .Level > highestCompactionLevel {
97+ highestCompactionLevel = b .Meta ().Compaction .Level
98+ }
99+ ulids = append (ulids , b .Meta ().ULID )
100+ parents = append (parents , tsdb.BlockDesc {
101+ ULID : b .Meta ().ULID ,
102+ MinTime : int64 (b .Meta ().MinTime ),
103+ MaxTime : int64 (b .Meta ().MaxTime ),
104+ })
105+ if b .Meta ().MinTime < minTime {
106+ minTime = b .Meta ().MinTime
107+ }
108+ if b .Meta ().MaxTime > maxTime {
109+ maxTime = b .Meta ().MaxTime
110+ }
111+ for k , v := range b .Meta ().Labels {
112+ if k == block .HostnameLabel {
113+ continue
114+ }
115+ labels [k ] = v
116+ }
117+ }
118+ if hostname , err := os .Hostname (); err == nil {
119+ labels [block .HostnameLabel ] = hostname
120+ }
121+ meta .Source = block .CompactorSource
122+ meta .Compaction = tsdb.BlockMetaCompaction {
123+ Deletable : meta .Stats .NumSamples == 0 ,
124+ Level : highestCompactionLevel + 1 ,
125+ Sources : ulids ,
126+ Parents : parents ,
127+ }
128+ meta .MaxTime = maxTime
129+ meta .MinTime = minTime
130+ meta .Labels = labels
131+ return meta
132+ }
133+
87134type profileRow struct {
88135 timeNanos int64
89136
@@ -205,14 +252,77 @@ func newMergeRowProfileIterator(src []BlockReader) (iter.Iterator[profileRow], e
205252 }, nil
206253}
207254
255+ type noopStacktraceRewriter struct {}
256+
257+ func (noopStacktraceRewriter ) RewriteStacktraces (src , dst []uint32 ) error {
258+ copy (dst , src )
259+ return nil
260+ }
261+
262+ type StacktraceRewriter interface {
263+ RewriteStacktraces (src , dst []uint32 ) error
264+ }
265+
208266type symbolsRewriter struct {
209267 iter.Iterator [profileRow ]
268+ err error
269+
270+ rewriter StacktraceRewriter
271+ src , dst []uint32
272+ numSamples uint64
210273}
211274
212275// todo remap symbols & ingest symbols
213276func newSymbolsRewriter (it iter.Iterator [profileRow ]) * symbolsRewriter {
214277 return & symbolsRewriter {
215278 Iterator : it ,
279+ rewriter : noopStacktraceRewriter {},
280+ }
281+ }
282+
283+ func (s * symbolsRewriter ) NumSamples () uint64 {
284+ return s .numSamples
285+ }
286+
287+ func (s * symbolsRewriter ) Next () bool {
288+ if ! s .Iterator .Next () {
289+ return false
290+ }
291+ var err error
292+ s .Iterator .At ().row .ForStacktraceIDsValues (func (values []parquet.Value ) {
293+ s .numSamples += uint64 (len (values ))
294+ s .loadStacktracesID (values )
295+ err = s .rewriter .RewriteStacktraces (s .src , s .dst )
296+ if err != nil {
297+ return
298+ }
299+ for i , v := range values {
300+ values [i ] = parquet .Int64Value (int64 (s .dst [i ])).Level (v .RepetitionLevel (), v .DefinitionLevel (), v .Column ())
301+ }
302+ })
303+ if err != nil {
304+ s .err = err
305+ return false
306+ }
307+ return true
308+ }
309+
310+ func (s * symbolsRewriter ) Err () error {
311+ if s .err != nil {
312+ return s .err
313+ }
314+ return s .Iterator .Err ()
315+ }
316+
317+ func (s * symbolsRewriter ) loadStacktracesID (values []parquet.Value ) {
318+ if cap (s .src ) < len (values ) {
319+ s .src = make ([]uint32 , len (values )* 2 )
320+ s .dst = make ([]uint32 , len (values )* 2 )
321+ }
322+ s .src = s .src [:len (values )]
323+ s .dst = s .dst [:len (values )]
324+ for i := range values {
325+ s .src [i ] = values [i ].Uint32 ()
216326 }
217327}
218328
@@ -226,6 +336,8 @@ type seriesRewriter struct {
226336 previousFp model.Fingerprint
227337 currentChunkMeta index.ChunkMeta
228338 err error
339+
340+ numSeries uint64
229341}
230342
231343func newSeriesRewriter (it iter.Iterator [profileRow ], indexw * index.Writer ) * seriesRewriter {
@@ -235,13 +347,18 @@ func newSeriesRewriter(it iter.Iterator[profileRow], indexw *index.Writer) *seri
235347 }
236348}
237349
350+ func (s * seriesRewriter ) NumSeries () uint64 {
351+ return s .numSeries
352+ }
353+
238354func (s * seriesRewriter ) Next () bool {
239355 if ! s .Iterator .Next () {
240356 if s .previousFp != 0 {
241357 if err := s .indexw .AddSeries (s .seriesRef , s .labels , s .previousFp , s .currentChunkMeta ); err != nil {
242358 s .err = err
243359 return false
244360 }
361+ s .numSeries ++
245362 }
246363 return false
247364 }
@@ -253,6 +370,7 @@ func (s *seriesRewriter) Next() bool {
253370 s .err = err
254371 return false
255372 }
373+ s .numSeries ++
256374 }
257375 s .seriesRef ++
258376 s .labels = currentProfile .labels .Clone ()
0 commit comments