Skip to content

Commit d9665c9

Browse files
authored
add logging to perf tool (#1542)
1 parent 1374a36 commit d9665c9

File tree

12 files changed

+335
-11
lines changed

12 files changed

+335
-11
lines changed

book/src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
- [Custom Prometheus metrics](./libs/wasp/benchspy/prometheus_custom.md)
8181
- [To Loki or not to Loki?](./libs/wasp/benchspy/loki_dillema.md)
8282
- [Real world example](./libs/wasp/benchspy/real_world.md)
83+
- [Debugging](./libs/wasp/benchspy/debugging.md)
8384
- [Reports](./libs/wasp/benchspy/reports/overview.md)
8485
- [Standard Report](./libs/wasp/benchspy/reports/standard_report.md)
8586
- [Adding new QueryExecutor](./libs/wasp/benchspy/reports/new_executor.md)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# BenchSpy - Debugging
2+
3+
If you run into any issues with `BenchSpy` it might help to lower the default logging level to either `debug` or `trace`. It's controlled by environment variable called `BENCHSPY_LOG_LEVEL`.

book/src/libs/wasp/benchspy/getting_started.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,7 @@ The following examples assume you have access to the following applications:
1111
1212
Since BenchSpy is tightly coupled with WASP, we highly recommend that you [get familiar with it first](../overview.md) if you haven't already.
1313

14-
Ready? [Let's get started!](./first_test.md)
14+
Ready? [Let's get started!](./first_test.md)
15+
16+
> [!NOTE]
17+
> You can `BENCHSPY_LOG_LEVEL` environment variable to control the log level.

wasp/benchspy/TO_DO.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Known things to do:
2-
- [ ] add logger
2+
- [x] add logger
33
- [x] add unit tests for prometheus
44
- [x] add wasp test for prometheus only
55
- [ ] add e2e OCRv2 test with CTFv2

wasp/benchspy/basic.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,12 @@ func MustNewBasicData(commitOrTag string, generators ...*wasp.Generator) BasicDa
3434
}
3535

3636
// NewBasicData creates a new BasicData instance using the provided commit or tag and a list of generators.
37-
// It ensures that at least one generator is provided and that it is associated with a testing.T instance.
37+
// It ensures that at least one generator is provided and that it is associated with a testing.T instance.
3838
// This function is essential for initializing test data configurations in a structured manner.
3939
func NewBasicData(commitOrTag string, generators ...*wasp.Generator) (*BasicData, error) {
40+
L.Debug().
41+
Msg("Creating new basic data instance")
42+
4043
if len(generators) == 0 {
4144
return nil, errors.New("at least one generator is required")
4245
}
@@ -60,12 +63,18 @@ func NewBasicData(commitOrTag string, generators ...*wasp.Generator) (*BasicData
6063
return nil, timeErr
6164
}
6265

66+
L.Debug().
67+
Msg("Basic data instance created successfully")
68+
6369
return b, nil
6470
}
6571

6672
// FillStartEndTimes calculates the earliest start time and latest end time from generator schedules.
6773
// It updates the BasicData instance with these times, ensuring all segments have valid start and end times.
6874
func (b *BasicData) FillStartEndTimes() error {
75+
L.Debug().
76+
Msg("Filling test start and end times for basic data instance based on generator schedules")
77+
6978
earliestTime := time.Now()
7079
var latestTime time.Time
7180

@@ -92,13 +101,19 @@ func (b *BasicData) FillStartEndTimes() error {
92101

93102
b.TestStart = earliestTime
94103
b.TestEnd = latestTime
104+
L.Debug().
105+
Str("Test start time", earliestTime.Format(time.RFC3339)).
106+
Str("Test end time", latestTime.Format(time.RFC3339)).
107+
Msg("Start and end times filled successfully")
95108

96109
return nil
97110
}
98111

99112
// Validate checks the integrity of the BasicData fields, ensuring that the test start and end times are set,
100113
// and that at least one generator configuration is provided. It returns an error if any of these conditions are not met.
101114
func (b *BasicData) Validate() error {
115+
L.Debug().
116+
Msg("Validating basic data instance")
102117
if b.TestStart.IsZero() {
103118
return errors.New("test start time is missing. We cannot query Loki without a time range. Please set it and try again")
104119
}
@@ -110,6 +125,9 @@ func (b *BasicData) Validate() error {
110125
return errors.New("generator configs are missing. At least one is required. Please set them and try again")
111126
}
112127

128+
L.Debug().
129+
Msg("Basic data instance is valid")
130+
113131
return nil
114132
}
115133

@@ -118,7 +136,9 @@ func (b *BasicData) Validate() error {
118136
// returning an error if any discrepancies are found. This function is useful for ensuring
119137
// consistency between data reports before processing or comparison.
120138
func (b *BasicData) IsComparable(otherData BasicData) error {
121-
// are all configs present? do they have the same schedule type? do they have the same segments? is call timeout the same? is rate limit timeout the same?
139+
L.Debug().
140+
Msg("Checking if basic data instances are comparable")
141+
122142
if len(b.GeneratorConfigs) != len(otherData.GeneratorConfigs) {
123143
return fmt.Errorf("generator configs count is different. Expected %d, got %d", len(b.GeneratorConfigs), len(otherData.GeneratorConfigs))
124144
}
@@ -133,6 +153,9 @@ func (b *BasicData) IsComparable(otherData BasicData) error {
133153
}
134154
}
135155

156+
L.Debug().
157+
Msg("Basic data instances are comparable")
158+
136159
return nil
137160
}
138161

wasp/benchspy/direct.go

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,27 @@ func NewStandardDirectQueryExecutor(generator *wasp.Generator) (*DirectQueryExec
3939
// NewDirectQueryExecutor creates a new DirectQueryExecutor with the specified generator and query functions.
4040
// It initializes the executor with a kind name and prepares a map for query results, enabling efficient query execution.
4141
func NewDirectQueryExecutor(generator *wasp.Generator, queries map[string]DirectQueryFn) (*DirectQueryExecutor, error) {
42-
g := &DirectQueryExecutor{
42+
ex := &DirectQueryExecutor{
4343
KindName: string(StandardQueryExecutor_Direct),
4444
Generator: generator,
4545
Queries: queries,
4646
QueryResults: make(map[string]interface{}),
4747
}
4848

49-
return g, nil
49+
L.Debug().
50+
Str("Generator", ex.GeneratorName()).
51+
Int("Queries", len(queries)).
52+
Msg("Creating new Direct query executor")
53+
54+
return ex, nil
5055
}
5156

5257
// GeneratorName returns the name of the generator associated with the query executor.
5358
// It is useful for identifying and categorizing results based on their generator type.
5459
func (g *DirectQueryExecutor) GeneratorName() string {
60+
if g.Generator == nil {
61+
return ""
62+
}
5563
return g.Generator.Cfg.GenName
5664
}
5765

@@ -70,6 +78,10 @@ func (l *DirectQueryExecutor) Kind() string {
7078
// IsComparable checks if the given QueryExecutor is of the same type and has comparable configurations.
7179
// It returns an error if the types do not match or if the configurations are not comparable.
7280
func (g *DirectQueryExecutor) IsComparable(otherQueryExecutor QueryExecutor) error {
81+
L.Debug().
82+
Str("Expected kind", g.KindName).
83+
Msg("Checking if query executors are comparable")
84+
7385
otherType := reflect.TypeOf(otherQueryExecutor)
7486

7587
if otherType != reflect.TypeOf(g) {
@@ -82,7 +94,16 @@ func (g *DirectQueryExecutor) IsComparable(otherQueryExecutor QueryExecutor) err
8294
return errors.New("generators are not comparable")
8395
}
8496

85-
return g.compareQueries(otherGeneratorQueryExecutor.Queries)
97+
queryErr := g.compareQueries(otherGeneratorQueryExecutor.Queries)
98+
if queryErr != nil {
99+
return queryErr
100+
}
101+
102+
L.Debug().
103+
Str("Kind", g.KindName).
104+
Msg("Query executors are comparable")
105+
106+
return nil
86107
}
87108

88109
func (l *DirectQueryExecutor) compareQueries(other map[string]DirectQueryFn) error {
@@ -104,6 +125,9 @@ func (l *DirectQueryExecutor) compareQueries(other map[string]DirectQueryFn) err
104125
// It ensures that a generator is set and at least one query is provided.
105126
// Returns an error if validation fails, helping to prevent execution issues.
106127
func (g *DirectQueryExecutor) Validate() error {
128+
L.Debug().
129+
Msg("Validating Direct query executor")
130+
107131
if g.Generator == nil {
108132
return errors.New("generator is not set")
109133
}
@@ -112,18 +136,31 @@ func (g *DirectQueryExecutor) Validate() error {
112136
return errors.New("at least one query is needed")
113137
}
114138

139+
L.Debug().
140+
Msg("Direct query executor is valid")
141+
115142
return nil
116143
}
117144

118145
// Execute runs the defined queries using the data from the generator.
119146
// It validates the generator's data and aggregates responses before executing each query.
120147
// This function is essential for processing and retrieving results from multiple queries concurrently.
121148
func (g *DirectQueryExecutor) Execute(_ context.Context) error {
149+
L.Info().
150+
Str("Generator", g.Generator.Cfg.GenName).
151+
Int("Queries", len(g.Queries)).
152+
Msg("Executing Direct queries")
153+
122154
if g.Generator == nil {
123155
return errors.New("generator is not set")
124156
}
125157

126158
for queryName, queryFunction := range g.Queries {
159+
L.Debug().
160+
Str("Generator", g.Generator.Cfg.GenName).
161+
Str("Query", queryName).
162+
Msg("Executing Direct query")
163+
127164
if g.Generator.GetData() == nil {
128165
return fmt.Errorf("generator %s has no data", g.Generator.Cfg.GenName)
129166
}
@@ -148,8 +185,18 @@ func (g *DirectQueryExecutor) Execute(_ context.Context) error {
148185
}
149186

150187
g.QueryResults[queryName] = results
188+
189+
L.Debug().
190+
Str("Query", queryName).
191+
Float64("Result", results).
192+
Msg("Direct query executed successfully")
151193
}
152194

195+
L.Info().
196+
Str("Generator", g.Generator.Cfg.GenName).
197+
Int("Queries", len(g.Queries)).
198+
Msg("Direct queries executed successfully")
199+
153200
return nil
154201
}
155202

@@ -160,6 +207,9 @@ func (g *DirectQueryExecutor) TimeRange(_, _ time.Time) {
160207
}
161208

162209
func (g *DirectQueryExecutor) generateStandardQueries() (map[string]DirectQueryFn, error) {
210+
L.Debug().
211+
Msg("Generating standard Direct queries")
212+
163213
standardQueries := make(map[string]DirectQueryFn)
164214

165215
for _, metric := range StandardLoadMetrics {
@@ -170,6 +220,10 @@ func (g *DirectQueryExecutor) generateStandardQueries() (map[string]DirectQueryF
170220
standardQueries[string(metric)] = query
171221
}
172222

223+
L.Debug().
224+
Int("Queries", len(standardQueries)).
225+
Msg("Standard queries Direct generated")
226+
173227
return standardQueries, nil
174228
}
175229

wasp/benchspy/log.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package benchspy
22

33
import (
4+
"fmt"
45
"os"
56

67
"github.com/rs/zerolog"
@@ -28,5 +29,15 @@ func initDefaultLogging() {
2829
if err != nil {
2930
panic(err)
3031
}
31-
L = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).Level(lvl)
32+
33+
output := zerolog.ConsoleWriter{Out: os.Stderr}
34+
output.FormatMessage = func(i interface{}) string {
35+
return fmt.Sprintf("\033[38;5;136m%v \033[0m", i) // Dark gold color for message
36+
}
37+
38+
output.FormatFieldValue = func(i interface{}) string {
39+
return fmt.Sprintf("\033[38;5;136m%v \033[0m", i) // Dark gold color for field value
40+
}
41+
42+
L = log.Output(output).Level(lvl)
3243
}

0 commit comments

Comments
 (0)