Skip to content

Commit d961a5f

Browse files
author
Andrea Spacca
authored
Add seed flag (#98)
* add --seed flag to cmds * add randSeed to internal * move randSeed and timeNow to init function in pkg * add randSeed to internal * fix aws.ec2_logs not deterministc reproducible schema-b template * refactor deprecated rand.Seed call * TestMain for init customRand
1 parent 3fae152 commit d961a5f

14 files changed

+86
-72
lines changed

assets/templates/aws.ec2_logs/schema-b/fields.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
- name: timestamp
1+
- name: ts
22
type: date
33
- name: process.name
44
type: keyword
@@ -12,8 +12,6 @@
1212
type: keyword
1313
- name: host.name
1414
type: keyword
15-
- name: aws.cloudwatch.ingestion_time
16-
type: date
1715
- name: agent.id
1816
type: keyword
1917
- name: event.id

assets/templates/aws.ec2_logs/schema-b/gotext.tpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{{- $ts := now }}
1+
{{- $ts := generate "ts" }}
22
{{- $ip := generate "aws.ec2.ip_address" }}
33
{{- $pname := generate "process.name" }}
44
{{- $logstream := generate "aws.cloudwatch.log_stream" }}

cmd/generate.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
var integrationPackage string
1919
var dataStream string
2020
var packageVersion string
21-
var timeNowAsString string
2221

2322
func GenerateCmd() *cobra.Command {
2423
generateCmd := &cobra.Command{
@@ -75,7 +74,7 @@ func GenerateCmd() *cobra.Command {
7574
return err
7675
}
7776

78-
payloadFilename, err := fc.Generate(packageRegistryBaseURL, integrationPackage, dataStream, packageVersion, totEvents, timeNow)
77+
payloadFilename, err := fc.Generate(packageRegistryBaseURL, integrationPackage, dataStream, packageVersion, totEvents, timeNow, randSeed)
7978
if err != nil {
8079
return err
8180
}
@@ -90,5 +89,7 @@ func GenerateCmd() *cobra.Command {
9089
generateCmd.Flags().StringVarP(&configFile, "config-file", "c", "", "path to config file for generator settings")
9190
generateCmd.Flags().Uint64VarP(&totEvents, "tot-events", "t", 1, "total events of the corpus to generate")
9291
generateCmd.Flags().StringVarP(&timeNowAsString, "now", "n", "", "time to use for generation based on now (`date` type)")
92+
generateCmd.Flags().Int64VarP(&randSeed, "seed", "s", 1, "seed to set as source of rand")
93+
9394
return generateCmd
9495
}

cmd/generate_common.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010
var packageRegistryBaseURL string
1111
var configFile string
1212
var totEvents uint64
13+
var timeNowAsString string
14+
var randSeed int64
1315

1416
func getTimeNowFromFlag(timeNowAsString string) (time.Time, error) {
1517
if len(timeNowAsString) > 0 {

cmd/generate_with_template.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ func GenerateWithTemplateCmd() *cobra.Command {
6666
return err
6767
}
6868

69-
payloadFilename, err := fc.GenerateWithTemplate(templatePath, fieldsDefinitionPath, totEvents, timeNow)
69+
payloadFilename, err := fc.GenerateWithTemplate(templatePath, fieldsDefinitionPath, totEvents, timeNow, randSeed)
7070
if err != nil {
7171
return err
7272
}
@@ -81,5 +81,7 @@ func GenerateWithTemplateCmd() *cobra.Command {
8181
generateWithTemplateCmd.Flags().StringVarP(&templateType, "template-type", "y", "placeholder", "either 'placeholder' or 'gotext'")
8282
generateWithTemplateCmd.Flags().Uint64VarP(&totEvents, "tot-events", "t", 1, "total events of the corpus to generate")
8383
generateWithTemplateCmd.Flags().StringVarP(&timeNowAsString, "now", "n", "", "time to use for generation based on now (`date` type)")
84+
generateWithTemplateCmd.Flags().Int64VarP(&randSeed, "seed", "s", 1, "seed to set as source of rand")
85+
8486
return generateWithTemplateCmd
8587
}

cmd/local-template.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ func TemplateCmd() *cobra.Command {
8585
return err
8686
}
8787

88-
payloadFilename, err := fc.GenerateWithTemplate(templatePath, fieldsDefinitionPath, totEvents, timeNow)
88+
payloadFilename, err := fc.GenerateWithTemplate(templatePath, fieldsDefinitionPath, totEvents, timeNow, randSeed)
8989
if err != nil {
9090
return err
9191
}
@@ -101,5 +101,7 @@ func TemplateCmd() *cobra.Command {
101101
command.Flags().Uint64VarP(&totEvents, "tot-events", "t", 1, "total events of the corpus to generate")
102102
command.Flags().StringVarP(&flagSchema, "schema", "", "b", "schema to generate data for; valid values: a, b")
103103
command.Flags().StringVarP(&timeNowAsString, "now", "n", "", "time to use for generation based on now (`date` type)")
104+
105+
command.Flags().Int64VarP(&randSeed, "seed", "s", 1, "seed to set as source of rand")
104106
return command
105107
}

internal/corpus/generator.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -106,17 +106,19 @@ func (gc GeneratorCorpus) bulkPayloadFilenameWithTemplate(templatePath string) s
106106
var corpusLocPerm = os.FileMode(0770)
107107
var corpusPerm = os.FileMode(0660)
108108

109-
func (gc GeneratorCorpus) eventsPayloadFromFields(template []byte, fields Fields, totEvents uint64, timeNow time.Time, createPayload []byte, f afero.File) error {
109+
func (gc GeneratorCorpus) eventsPayloadFromFields(template []byte, fields Fields, totEvents uint64, timeNow time.Time, randSeed int64, createPayload []byte, f afero.File) error {
110+
genlib.InitGeneratorTimeNow(timeNow)
111+
genlib.InitGeneratorRandSeed(randSeed)
110112

111113
var evgen genlib.Generator
112114
var err error
113115
if len(template) == 0 {
114-
evgen, err = genlib.NewGenerator(gc.config, fields, totEvents, timeNow)
116+
evgen, err = genlib.NewGenerator(gc.config, fields, totEvents)
115117
} else {
116118
if gc.templateType == templateTypeCustom {
117-
evgen, err = genlib.NewGeneratorWithCustomTemplate(template, gc.config, fields, totEvents, timeNow)
119+
evgen, err = genlib.NewGeneratorWithCustomTemplate(template, gc.config, fields, totEvents)
118120
} else if gc.templateType == templateTypeGoText {
119-
evgen, err = genlib.NewGeneratorWithTextTemplate(template, gc.config, fields, totEvents, timeNow)
121+
evgen, err = genlib.NewGeneratorWithTextTemplate(template, gc.config, fields, totEvents)
120122
} else {
121123
return ErrNotValidTemplate
122124
}
@@ -162,7 +164,7 @@ func (gc GeneratorCorpus) eventsPayloadFromFields(template []byte, fields Fields
162164
}
163165

164166
// Generate generates a bulk request corpus and persist it to file.
165-
func (gc GeneratorCorpus) Generate(packageRegistryBaseURL, integrationPackage, dataStream, packageVersion string, totEvents uint64, timeNow time.Time) (string, error) {
167+
func (gc GeneratorCorpus) Generate(packageRegistryBaseURL, integrationPackage, dataStream, packageVersion string, totEvents uint64, timeNow time.Time, randSeed int64) (string, error) {
166168
if err := gc.fs.MkdirAll(gc.location, corpusLocPerm); err != nil {
167169
return "", fmt.Errorf("cannot generate corpus location folder: %v", err)
168170
}
@@ -181,7 +183,7 @@ func (gc GeneratorCorpus) Generate(packageRegistryBaseURL, integrationPackage, d
181183

182184
createPayload := []byte(`{ "create" : { "_index": "` + dataStreamType + `-` + integrationPackage + `.` + dataStream + `-default" } }` + "\n")
183185

184-
err = gc.eventsPayloadFromFields(nil, flds, totEvents, timeNow, createPayload, f)
186+
err = gc.eventsPayloadFromFields(nil, flds, totEvents, timeNow, randSeed, createPayload, f)
185187
if err != nil {
186188
return "", err
187189
}
@@ -194,7 +196,7 @@ func (gc GeneratorCorpus) Generate(packageRegistryBaseURL, integrationPackage, d
194196
}
195197

196198
// GenerateWithTemplate generates a template based corpus and persist it to file.
197-
func (gc GeneratorCorpus) GenerateWithTemplate(templatePath, fieldsDefinitionPath string, totEvents uint64, timeNow time.Time) (string, error) {
199+
func (gc GeneratorCorpus) GenerateWithTemplate(templatePath, fieldsDefinitionPath string, totEvents uint64, timeNow time.Time, randSeed int64) (string, error) {
198200
if err := gc.fs.MkdirAll(gc.location, corpusLocPerm); err != nil {
199201
return "", fmt.Errorf("cannot generate corpus location folder: %v", err)
200202
}
@@ -220,7 +222,7 @@ func (gc GeneratorCorpus) GenerateWithTemplate(templatePath, fieldsDefinitionPat
220222
return "", err
221223
}
222224

223-
err = gc.eventsPayloadFromFields(template, flds, totEvents, timeNow, nil, f)
225+
err = gc.eventsPayloadFromFields(template, flds, totEvents, timeNow, randSeed, nil, f)
224226
if err != nil {
225227
return "", err
226228
}

pkg/genlib/generator.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import (
1414
"time"
1515
)
1616

17+
var customRand *rand.Rand
18+
1719
const (
1820
textTemplateEngine = iota
1921
customTemplateEngine
@@ -163,9 +165,22 @@ func generateTemplateFromField(cfg Config, fields Fields, templateEngine int) ([
163165
return templateBuffer.Bytes(), objectKeysField
164166
}
165167

166-
func NewGenerator(cfg Config, flds Fields, totEvents uint64, timeNow time.Time) (Generator, error) {
168+
func NewGenerator(cfg Config, flds Fields, totEvents uint64) (Generator, error) {
167169
template, objectKeysField := generateCustomTemplateFromField(cfg, flds)
168170
flds = append(flds, objectKeysField...)
169171

170-
return NewGeneratorWithCustomTemplate(template, cfg, flds, totEvents, timeNow)
172+
return NewGeneratorWithCustomTemplate(template, cfg, flds, totEvents)
173+
}
174+
175+
// InitGeneratorTimeNow sets base timeNow for `date` field
176+
func InitGeneratorTimeNow(timeNow time.Time) {
177+
// set timeNowToBind to --now flag (already parsed or now)
178+
timeNowToBind = timeNow
179+
}
180+
181+
// InitGeneratorRandSeed sets rand seed
182+
func InitGeneratorRandSeed(randSeed int64) {
183+
// set rand and randomdata seed to --seed flag (custom or 1)
184+
customRand = rand.New(rand.NewSource(randSeed))
185+
randomdata.CustomRand(customRand)
171186
}

pkg/genlib/generator_interface.go

Lines changed: 32 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313
"github.com/elastic/elastic-integration-corpus-generator-tool/pkg/genlib/config"
1414
"github.com/elastic/elastic-integration-corpus-generator-tool/pkg/genlib/fields"
1515
"math"
16-
"math/rand"
1716
"regexp"
1817
"strconv"
1918
"strings"
@@ -235,14 +234,14 @@ func makeFloatFunc(fieldCfg ConfigField, field Field) func() float64 {
235234

236235
switch {
237236
case maxValue > 0:
238-
dummyFunc = func() float64 { return minValue + rand.Float64()*(maxValue-minValue) }
237+
dummyFunc = func() float64 { return minValue + customRand.Float64()*(maxValue-minValue) }
239238
case len(field.Example) == 0:
240-
dummyFunc = func() float64 { return rand.Float64() * 10 }
239+
dummyFunc = func() float64 { return customRand.Float64() * 10 }
241240
default:
242241
totDigit := len(field.Example)
243242
max := math.Pow10(totDigit)
244243
dummyFunc = func() float64 {
245-
return rand.Float64() * max
244+
return customRand.Float64() * max
246245
}
247246
}
248247

@@ -261,14 +260,14 @@ func makeIntFunc(fieldCfg ConfigField, field Field) func() int64 {
261260

262261
switch {
263262
case maxValue > 0:
264-
dummyFunc = func() int64 { return rand.Int63n(maxValue-minValue) + minValue }
263+
dummyFunc = func() int64 { return customRand.Int63n(maxValue-minValue) + minValue }
265264
case len(field.Example) == 0:
266-
dummyFunc = func() int64 { return rand.Int63n(10) }
265+
dummyFunc = func() int64 { return customRand.Int63n(10) }
267266
default:
268267
totDigit := len(field.Example)
269268
max := int64(math.Pow10(totDigit))
270269
dummyFunc = func() int64 {
271-
return rand.Int63n(max)
270+
return customRand.Int63n(max)
272271
}
273272
}
274273

@@ -340,30 +339,30 @@ func genNounsNWithReturn(n int) string {
340339
}
341340

342341
func randGeoPoint(buf *bytes.Buffer) error {
343-
lat := rand.Intn(181) - 90
342+
lat := customRand.Intn(181) - 90
344343
var latD int
345344
if lat != -90 && lat != 90 {
346-
latD = rand.Intn(100)
345+
latD = customRand.Intn(100)
347346
}
348347
var longD int
349-
long := rand.Intn(361) - 180
348+
long := customRand.Intn(361) - 180
350349
if long != -180 && long != 180 {
351-
longD = rand.Intn(100)
350+
longD = customRand.Intn(100)
352351
}
353352
_, err := fmt.Fprintf(buf, "%d.%d,%d.%d", lat, latD, long, longD)
354353
return err
355354
}
356355

357356
func randGeoPointWithReturn() string {
358-
lat := rand.Intn(181) - 90
357+
lat := customRand.Intn(181) - 90
359358
var latD int
360359
if lat != -90 && lat != 90 {
361-
latD = rand.Intn(100)
360+
latD = customRand.Intn(100)
362361
}
363362
var longD int
364-
long := rand.Intn(361) - 180
363+
long := customRand.Intn(361) - 180
365364
if long != -180 && long != 180 {
366-
longD = rand.Intn(100)
365+
longD = customRand.Intn(100)
367366
}
368367

369368
return fmt.Sprintf("%d.%d,%d.%d", lat, latD, long, longD)
@@ -390,7 +389,7 @@ func bindKeyword(fieldCfg ConfigField, field Field, fieldMap map[string]any) err
390389
if len(fieldCfg.Enum) > 0 {
391390
var emitFNotReturn emitFNotReturn
392391
emitFNotReturn = func(state *GenState, buf *bytes.Buffer) error {
393-
idx := rand.Intn(len(fieldCfg.Enum))
392+
idx := customRand.Intn(len(fieldCfg.Enum))
394393
buf.WriteString(fieldCfg.Enum[idx])
395394
return nil
396395
}
@@ -462,7 +461,7 @@ func bindStatic(field Field, v any, fieldMap map[string]any) error {
462461
func bindBool(field Field, fieldMap map[string]any) error {
463462
var emitFNotReturn emitFNotReturn
464463
emitFNotReturn = func(state *GenState, buf *bytes.Buffer) error {
465-
switch rand.Int() % 2 {
464+
switch customRand.Int() % 2 {
466465
case 0:
467466
buf.WriteString("false")
468467
case 1:
@@ -488,7 +487,7 @@ func bindGeoPoint(field Field, fieldMap map[string]any) error {
488487
func bindWordN(field Field, n int, fieldMap map[string]any) error {
489488
var emitFNotReturn emitFNotReturn
490489
emitFNotReturn = func(state *GenState, buf *bytes.Buffer) error {
491-
genNounsN(rand.Intn(n), buf)
490+
genNounsN(customRand.Intn(n), buf)
492491
return nil
493492
}
494493

@@ -503,7 +502,7 @@ func bindNearTime(fieldCfg ConfigField, field Field, fieldMap map[string]any) er
503502
if fieldCfg.Period > 0 && state.totEvents > 0 {
504503
offset = time.Duration((fieldCfg.Period.Nanoseconds() / int64(state.totEvents)) * int64(state.counter))
505504
} else {
506-
offset = time.Duration(rand.Intn(FieldTypeTimeRange)*-1) * time.Second
505+
offset = time.Duration(customRand.Intn(FieldTypeTimeRange)*-1) * time.Second
507506
}
508507

509508
newTime := timeNowToBind.Add(offset)
@@ -518,10 +517,10 @@ func bindNearTime(fieldCfg ConfigField, field Field, fieldMap map[string]any) er
518517
func bindIP(field Field, fieldMap map[string]any) error {
519518
var emitFNotReturn emitFNotReturn
520519
emitFNotReturn = func(state *GenState, buf *bytes.Buffer) error {
521-
i0 := rand.Intn(255)
522-
i1 := rand.Intn(255)
523-
i2 := rand.Intn(255)
524-
i3 := rand.Intn(255)
520+
i0 := customRand.Intn(255)
521+
i1 := customRand.Intn(255)
522+
i2 := customRand.Intn(255)
523+
i3 := customRand.Intn(255)
525524

526525
_, err := fmt.Fprintf(buf, "%d.%d.%d.%d", i0, i1, i2, i3)
527526
return err
@@ -537,7 +536,7 @@ func fuzzyInt(previous int64, fuzziness, min, max float64) int64 {
537536
higherBound := float64(previous) * (1 + fuzziness)
538537
lowerBound = math.Max(lowerBound, min)
539538
higherBound = math.Min(higherBound, max)
540-
return rand.Int63n(int64(math.Ceil(higherBound-lowerBound))) + int64(lowerBound)
539+
return customRand.Int63n(int64(math.Ceil(higherBound-lowerBound))) + int64(lowerBound)
541540
}
542541

543542
func bindLong(fieldCfg ConfigField, field Field, fieldMap map[string]any) error {
@@ -587,7 +586,7 @@ func fuzzyFloat(previous, fuzziness, min, max float64) float64 {
587586
higherBound := previous * (1 + fuzziness)
588587
lowerBound = math.Max(lowerBound, min)
589588
higherBound = math.Min(higherBound, max)
590-
return lowerBound + rand.Float64()*(higherBound-lowerBound)
589+
return lowerBound + customRand.Float64()*(higherBound-lowerBound)
591590
}
592591

593592
func bindDouble(fieldCfg ConfigField, field Field, fieldMap map[string]any) error {
@@ -739,7 +738,7 @@ func bindKeywordWithReturn(fieldCfg ConfigField, field Field, fieldMap map[strin
739738
if len(fieldCfg.Enum) > 0 {
740739
var emitF EmitF
741740
emitF = func(state *GenState) any {
742-
idx := rand.Intn(len(fieldCfg.Enum))
741+
idx := customRand.Intn(len(fieldCfg.Enum))
743742
return fieldCfg.Enum[idx]
744743
}
745744

@@ -804,7 +803,7 @@ func bindStaticWithReturn(field Field, v any, fieldMap map[string]any) error {
804803
func bindBoolWithReturn(field Field, fieldMap map[string]any) error {
805804
var emitF EmitF
806805
emitF = func(state *GenState) any {
807-
switch rand.Int() % 2 {
806+
switch customRand.Int() % 2 {
808807
case 0:
809808
return false
810809
default:
@@ -830,7 +829,7 @@ func bindGeoPointWithReturn(field Field, fieldMap map[string]any) error {
830829
func bindWordNWithReturn(field Field, n int, fieldMap map[string]any) error {
831830
var emitF EmitF
832831
emitF = func(state *GenState) any {
833-
return genNounsNWithReturn(rand.Intn(n))
832+
return genNounsNWithReturn(customRand.Intn(n))
834833
}
835834
fieldMap[field.Name] = emitF
836835
return nil
@@ -843,7 +842,7 @@ func bindNearTimeWithReturn(fieldCfg ConfigField, field Field, fieldMap map[stri
843842
if fieldCfg.Period > 0 {
844843
offset = time.Duration((fieldCfg.Period.Nanoseconds() / int64(state.totEvents)) * int64(state.counter))
845844
} else {
846-
offset = time.Duration(rand.Intn(FieldTypeTimeRange)*-1) * time.Second
845+
offset = time.Duration(customRand.Intn(FieldTypeTimeRange)*-1) * time.Second
847846
}
848847

849848
newTime := timeNowToBind.Add(offset)
@@ -857,10 +856,10 @@ func bindNearTimeWithReturn(fieldCfg ConfigField, field Field, fieldMap map[stri
857856
func bindIPWithReturn(field Field, fieldMap map[string]any) error {
858857
var emitF EmitF
859858
emitF = func(state *GenState) any {
860-
i0 := rand.Intn(255)
861-
i1 := rand.Intn(255)
862-
i2 := rand.Intn(255)
863-
i3 := rand.Intn(255)
859+
i0 := customRand.Intn(255)
860+
i1 := customRand.Intn(255)
861+
i2 := customRand.Intn(255)
862+
i3 := customRand.Intn(255)
864863

865864
return fmt.Sprintf("%d.%d.%d.%d", i0, i1, i2, i3)
866865
}

0 commit comments

Comments
 (0)