Skip to content

Commit

Permalink
use random factor for rates & merge defaults+random
Browse files Browse the repository at this point in the history
  • Loading branch information
ie-pham committed Jan 15, 2024
1 parent 58a4aa5 commit 39a488a
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 62 deletions.
4 changes: 2 additions & 2 deletions examples/template/template.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ const traceTemplates = [
{service: "shop-backend", attributes: {"http.status_code": 403}},
{service: "shop-backend", name: "authenticate", attributes: {"http.request.header.accept": ["application/json"]}},
{service: "auth-service", name: "authenticate", attributes: {"http.status_code": 403}},
{service: "test-random", name: "events", randomEvents: {exceptionCount: 1, count: 2, randomAttributes: {count: 5, cardinality: 2}}},
{service: "test-random", name: "links", randomLinks: {linkToPreviousSpanIndex: true, count: 2, randomAttributes: {count: 3, cardinality: 2}}}
{service: "cart-service", name: "checkout", randomEvents: {exceptionCount: 1, count: 2, randomAttributes: {count: 5, cardinality: 2}}},
{service: "billing-service", name: "payment", randomLinks: {linkToPreviousSpanIndex: true, count: 2, randomAttributes: {count: 3, cardinality: 2}}}
]
},
]
Expand Down
88 changes: 49 additions & 39 deletions pkg/tracegen/templated.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package tracegen

import (
"fmt"
"math/rand"
"net/http"
"net/url"
"strings"
Expand Down Expand Up @@ -51,9 +52,9 @@ type SpanDefaults struct {
// RandomAttributes random attributes generated for each span.
RandomAttributes *AttributeParams `js:"randomAttributes"`
// Random events generated for each span
EventDefaults EventDefaults `js:"eventDefaults"`
EventDefaults EventParams `js:"eventDefaults"`
// Random links generated for each span
LinkDefaults LinkDefaults `js:"linkDefaults"`
LinkDefaults LinkParams `js:"linkDefaults"`
}

// SpanTemplate parameters that define how a span is created.
Expand Down Expand Up @@ -81,9 +82,9 @@ type SpanTemplate struct {
// List of links for the span with specific parameters
Links []Link `js:"links"`
// Generate random events for the span
RandomEvents RandomEvents `js:"randomEvents"`
RandomEvents EventParams `js:"randomEvents"`
// Generate random links for the span
RandomLinks RandomLinks `js:"randomLinks"`
RandomLinks LinkParams `js:"randomLinks"`
}

// TraceTemplate describes how all a trace and it's spans are generated.
Expand Down Expand Up @@ -112,7 +113,7 @@ type Event struct {
RandomAttributes *AttributeParams `js:"randomAttributes"`
}

type LinkDefaults struct {
type LinkParams struct {
// LinkToPreviousSpanIndex true will set TraceID and SpanID the same as the previous span
// Unless it is the first span then a random TraceID and a random SpanID will be used
LinkToPreviousSpanIndex bool `js:"linkToPreviousSpanIndex"`
Expand All @@ -122,41 +123,26 @@ type LinkDefaults struct {
RandomAttributes *AttributeParams `js:"randomAttributes"`
}

type EventDefaults struct {
type EventParams struct {
// Generate exception event if status code of the span is >= 400
GenerateExceptionOnError bool `js:"generateExceptionOnError"`
// Rate of exception events per each span
ExceptionRate float32 `js:"exceptionRate"`
// Rate of random events per each span
Rate float32 `js:"rate"`
// Generate random attributes for this event
RandomAttributes *AttributeParams `js:"randomAttributes"`
}

type RandomEvents struct {
// Number of random exception events to generate for the span
ExceptionCount int `js:"exceptionCount"`
// Number of non-exception events to generate for the span
Count int `js:"count"`
// Generate random attributes for these events
RandomAttributes *AttributeParams `js:"randomAttributes"`
}

type RandomLinks struct {
// LinkToPreviousSpanIndex true will set TraceID and SpanID the same as the previous span
LinkToPreviousSpanIndex bool `js:"linkToPreviousSpanIndex"`
// Number of links to generate for the span
Count int `js:"count"`
// Generate random attributes for these links
RandomAttributes *AttributeParams `js:"randomAttributes"`
}

type internalLinkDefaults struct {
type internalLinkParams struct {
LinkToPreviousSpanIndex bool
Count int
RandomAttributes *AttributeParams
}

type internalEventDefaults struct {
type internalEventParams struct {
GenerateExceptionOnError bool
ExceptionCount int
Count int
RandomAttributes *AttributeParams
}
Expand Down Expand Up @@ -542,47 +528,71 @@ func (g *TemplatedGenerator) initializeSpan(idx int, parent *internalSpanTemplat
span.attributes = util.MergeMaps(defaults.Attributes, tmpl.Attributes)

eventDefaultsRate := defaults.EventDefaults.Rate
var eventDefaults internalEventDefaults
var eventDefaults internalEventParams
// if rate is more than 1, use whole integers
if eventDefaultsRate > 1 {
eventDefaults = internalEventDefaults{
eventDefaults = internalEventParams{
GenerateExceptionOnError: defaults.EventDefaults.GenerateExceptionOnError,
RandomAttributes: defaults.EventDefaults.RandomAttributes,
Count: int(eventDefaultsRate),
ExceptionCount: int(defaults.EventDefaults.ExceptionRate),
}
} else if idx%int(1/eventDefaultsRate) == 0 {
} else {
var count, exeptionCount int
if rand.Float32() < eventDefaultsRate {
count = 1
}

if rand.Float32() < eventDefaultsRate {
exeptionCount = 1
}

// if rate is less than one
eventDefaults = internalEventDefaults{
eventDefaults = internalEventParams{
GenerateExceptionOnError: defaults.EventDefaults.GenerateExceptionOnError,
RandomAttributes: defaults.EventDefaults.RandomAttributes,
Count: 1,
Count: count,
ExceptionCount: exeptionCount,
}
}

randomEvents := internalEventParams{
GenerateExceptionOnError: tmpl.RandomEvents.GenerateExceptionOnError,
RandomAttributes: tmpl.RandomEvents.RandomAttributes,
Count: int(tmpl.RandomEvents.Rate),
ExceptionCount: int(tmpl.RandomEvents.ExceptionRate),
}

// generate all non-exception events
span.events = g.initializeEvents(tmpl.Events, tmpl.RandomEvents, eventDefaults)
span.events = g.initializeEvents(tmpl.Events, randomEvents, eventDefaults)

// need span status to determine if an exception event should occur
span.generateExceptionEvents = defaults.EventDefaults.GenerateExceptionOnError

linkDefaultsRate := defaults.LinkDefaults.Rate
var linkDefaults internalLinkDefaults
var linkDefaults internalLinkParams
if linkDefaultsRate > 1 {
linkDefaults = internalLinkDefaults{
linkDefaults = internalLinkParams{
LinkToPreviousSpanIndex: defaults.LinkDefaults.LinkToPreviousSpanIndex,
RandomAttributes: defaults.LinkDefaults.RandomAttributes,
Count: int(linkDefaultsRate),
}
} else if idx%int(1/linkDefaultsRate) == 0 {
linkDefaults = internalLinkDefaults{
} else if rand.Float32() < linkDefaultsRate {
linkDefaults = internalLinkParams{
LinkToPreviousSpanIndex: defaults.LinkDefaults.LinkToPreviousSpanIndex,
RandomAttributes: defaults.LinkDefaults.RandomAttributes,
Count: 1,
}
}

randomLinks := internalLinkParams{
LinkToPreviousSpanIndex: tmpl.RandomLinks.LinkToPreviousSpanIndex,
Count: int(tmpl.RandomLinks.Rate),
RandomAttributes: tmpl.RandomEvents.RandomAttributes,
}

// initialize all links but need
span.links = g.initializeLinks(tmpl.Links, tmpl.RandomLinks, linkDefaults)
span.links = g.initializeLinks(tmpl.Links, randomLinks, linkDefaults)

// set span name
if tmpl.Name != nil {
Expand Down Expand Up @@ -679,7 +689,7 @@ func initializeRandomAttributes(attributeParams *AttributeParams) map[string][]i
return attributes
}

func (g *TemplatedGenerator) initializeEvents(tmplEvents []Event, randomEvents RandomEvents, eventDefaults internalEventDefaults) []Event {
func (g *TemplatedGenerator) initializeEvents(tmplEvents []Event, randomEvents internalEventParams, eventDefaults internalEventParams) []Event {
count := len(tmplEvents) + randomEvents.Count + eventDefaults.Count

if count == 0 {
Expand Down Expand Up @@ -757,7 +767,7 @@ func generateRandomExceptionStackTrace() string {
return "panic: " + random.SelectElement(panics) + "\n" + random.SelectElement(functions)
}

func (g *TemplatedGenerator) initializeLinks(tmplLinks []Link, randomLinks RandomLinks, linkDefaults internalLinkDefaults) []Link {
func (g *TemplatedGenerator) initializeLinks(tmplLinks []Link, randomLinks internalLinkParams, linkDefaults internalLinkParams) []Link {
count := len(tmplLinks) + randomLinks.Count + linkDefaults.Count

if count == 0 {
Expand Down
34 changes: 13 additions & 21 deletions pkg/tracegen/templated_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,15 @@ func TestTemplatedGenerator_EventsLinks(t *testing.T) {
Defaults: SpanDefaults{
Attributes: map[string]interface{}{"fixed.attr": "some-value"},
RandomAttributes: &AttributeParams{Count: 3},
LinkDefaults: LinkDefaults{LinkToPreviousSpanIndex: true, Rate: 0.5, RandomAttributes: &AttributeParams{Count: 3}},
EventDefaults: EventDefaults{GenerateExceptionOnError: true, Rate: 0.5, RandomAttributes: &AttributeParams{Count: 3}},
LinkDefaults: LinkParams{LinkToPreviousSpanIndex: true, Rate: 0.5, RandomAttributes: &AttributeParams{Count: 3}},
EventDefaults: EventParams{GenerateExceptionOnError: true, Rate: 0.5, RandomAttributes: &AttributeParams{Count: 3}},
},
Spans: []SpanTemplate{
// do not change order of the first one
{Service: "test-service", Name: ptr("only_default")},
{Service: "test-service", Name: ptr("default_and_template"), Events: []Event{{Name: "event-name", RandomAttributes: &AttributeParams{Count: 2}}}, Links: []Link{{LinkToPreviousSpanIndex: true, Attributes: map[string]interface{}{"link-attr-key": "link-attr-value"}}}},
{Service: "test-service", Name: ptr("default_and_random"), RandomEvents: RandomEvents{Count: 2, RandomAttributes: &AttributeParams{Count: 1}}, RandomLinks: RandomLinks{LinkToPreviousSpanIndex: false, Count: 2, RandomAttributes: &AttributeParams{Count: 1}}},
{Service: "test-service", Name: ptr("default_template_random"), Events: []Event{{Name: "event-name", RandomAttributes: &AttributeParams{Count: 2}}}, Links: []Link{{LinkToPreviousSpanIndex: true, Attributes: map[string]interface{}{"link-attr-key": "link-attr-value"}}}, RandomEvents: RandomEvents{Count: 2, RandomAttributes: &AttributeParams{Count: 1}}, RandomLinks: RandomLinks{LinkToPreviousSpanIndex: false, Count: 2, RandomAttributes: &AttributeParams{Count: 1}}},
{Service: "test-service", Name: ptr("default_and_random"), RandomEvents: EventParams{Rate: 2, RandomAttributes: &AttributeParams{Count: 1}}, RandomLinks: LinkParams{LinkToPreviousSpanIndex: false, Rate: 2, RandomAttributes: &AttributeParams{Count: 1}}},
{Service: "test-service", Name: ptr("default_template_random"), Events: []Event{{Name: "event-name", RandomAttributes: &AttributeParams{Count: 2}}}, Links: []Link{{LinkToPreviousSpanIndex: true, Attributes: map[string]interface{}{"link-attr-key": "link-attr-value"}}}, RandomEvents: EventParams{Rate: 2, RandomAttributes: &AttributeParams{Count: 1}}, RandomLinks: LinkParams{LinkToPreviousSpanIndex: false, Rate: 2, RandomAttributes: &AttributeParams{Count: 1}}},
{Service: "test-service", Name: ptr("default_generate_on_error"), Attributes: map[string]interface{}{"http.status_code": 400}},
},
}
Expand All @@ -87,23 +87,21 @@ func TestTemplatedGenerator_EventsLinks(t *testing.T) {
checkEventsLinksLength := func(spanIndex, expectedTemplate, expectedRandom int, spanName string) {
expected := expectedTemplate + expectedRandom
// because default rate is 0.5
if spanIndex%2 == 0 {
assert.Equal(t, expected+1, events.Len(), "test name: %s events", spanName)
assert.Equal(t, expected+1, links.Len(), "test name: %s links", spanName)
} else {
assert.Equal(t, expected, events.Len(), "test name: %s events", spanName)
assert.Equal(t, expected, links.Len(), "test name: %s links", spanName)
}
assert.GreaterOrEqual(t, events.Len(), expected, "test name: %s events", spanName)
assert.GreaterOrEqual(t, links.Len(), expected, "test name: %s links", spanName)
assert.LessOrEqual(t, events.Len(), expected+1, "test name: %s events", spanName)
assert.LessOrEqual(t, links.Len(), expected+1, "test name: %s links", spanName)
}

switch span.Name() {
case "only_default":
checkEventsLinksLength(i, 0, 0, span.Name())
if i%2 == 0 {
if events.Len() > 0 {
// check default event with 3 random attributes
event := events.At(0)
assert.Equal(t, 3, len(event.Attributes().AsRaw()))

}
if links.Len() > 0 {
// check default link with 3 random attributes
// and not matching trace id and parent span id because this is
// the first span, there is no previous span
Expand All @@ -119,14 +117,8 @@ func TestTemplatedGenerator_EventsLinks(t *testing.T) {
case "default_template_random":
checkEventsLinksLength(i, 1, 2, span.Name())
case "default_generate_on_error":
// # events and links should not match in this scenario
if i%2 == 0 {
assert.Equal(t, 2, events.Len())
assert.Equal(t, 1, links.Len())
} else {
assert.Equal(t, 1, events.Len())
assert.Equal(t, 0, links.Len())
}
// there should be at least one event
assert.GreaterOrEqual(t, events.Len(), 0, "test name: %s events", "default generate on error")
found := false
for i := 0; i < events.Len(); i++ {
event := events.At(i)
Expand Down

0 comments on commit 39a488a

Please sign in to comment.