Skip to content
This repository was archived by the owner on Jun 13, 2023. It is now read-only.

Commit 9ee2f15

Browse files
authored
feat(tracer): Add max trace size configuration
1 parent 0fc399d commit 9ee2f15

File tree

5 files changed

+80
-53
lines changed

5 files changed

+80
-53
lines changed

.travis.yml

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ before_install:
1212
install:
1313
- go mod download
1414
- go get golang.org/x/lint/golint
15+
- go install golang.org/x/lint/golint
1516
- go mod tidy
1617

1718
script:

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,7 @@ Advanced options can be configured as a parameter to the `Config` struct to the
475475
|CollectorURL |EPSAGON_COLLECTOR_URL |String |- |The address of the trace collector to send trace to |
476476
|Debug |EPSAGON_DEBUG |Boolean|`False` |Enable debug prints for troubleshooting |
477477
|SendTimeout |EPSAGON_SEND_TIMEOUT_SEC |String |`1s` |The timeout duration to send the traces to the trace collector |
478+
|MaxTraceSize |EPSAGON_MAX_TRACE_SIZE |Integer|`1287936` |The max allowed trace size (in bytes). Defaults to 64KB, max allowed size - 512KB |
478479
|_ |EPSAGON_LAMBDA_TIMEOUT_THRESHOLD_MS |Integer|`200` |The threshold in milliseconds to send the trace before a Lambda timeout occurs |
479480

480481

epsagon/common_utils.go

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ func NewTracerConfig(applicationName, token string) *Config {
6565
MetadataOnly: true,
6666
Debug: false,
6767
SendTimeout: "1s",
68+
MaxTraceSize: tracer.DefaultMaxTraceSize,
6869
},
6970
}
7071
}

tracer/tracer.go

+36-6
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,24 @@ var (
2727
GlobalTracer Tracer
2828
)
2929

30+
// DefaultMaxTraceSizeKB is the default maximum trace size (in KB)
31+
const DefaultMaxTraceSizeKB = 64
32+
33+
// DefaultMaxTraceSize is the default maximum trace size (in bytes)
34+
const DefaultMaxTraceSize = DefaultMaxTraceSizeKB * 1024
35+
36+
// MaxTraceSizeKB is the maximum allowed trace size (in KB)
37+
const MaxTraceSizeKB = 512
38+
3039
// MaxTraceSize is the maximum allowed trace size (in bytes)
31-
const MaxTraceSize = 64 * 1024
40+
const MaxTraceSize = MaxTraceSizeKB * 1024
3241

3342
// MaxLabelsSize is the maximum allowed total labels size (in bytes)
3443
const MaxLabelsSize = 10 * 1024
3544

45+
// MaxTraceSizeEnvVar max trace size environment variable
46+
const MaxTraceSizeEnvVar = "EPSAGON_MAX_TRACE_SIZE"
47+
3648
// LabelsKey is the key for labels in resource metadata
3749
const LabelsKey = "labels"
3850

@@ -103,6 +115,7 @@ type Config struct {
103115
Disable bool // Disable sending traces
104116
TestMode bool // TestMode sending traces
105117
IgnoredKeys []string // IgnoredKeys are keys that will be masked from events metadata
118+
MaxTraceSize int // MaxTraceSize is the maximum allowed trace size (in bytes)
106119
}
107120

108121
type epsagonLabel struct {
@@ -253,10 +266,10 @@ func (tracer *epsagonTracer) stripEvents(traceLength int, marshaler *jsonpb.Mars
253266
}
254267
strippedSize := eventSize - len(eventJSON)
255268
traceLength -= strippedSize
256-
if traceLength <= MaxTraceSize {
269+
if traceLength <= tracer.Config.MaxTraceSize {
257270
if tracer.Config.Debug {
258271
traceLength := traceLength / 1024
259-
log.Printf("EPSAGON DEBUG trimmed trace from %dKB to %dKB (max allowed size: 64KB)", originalTraceLength, traceLength)
272+
log.Printf("EPSAGON DEBUG trimmed trace from %dKB to %dKB (max allowed size: %dKB)", originalTraceLength, traceLength, MaxTraceSizeKB)
260273
}
261274
return true
262275
}
@@ -272,10 +285,10 @@ func (tracer *epsagonTracer) getTraceJSON(trace *protocol.Trace, runnerEvent *pr
272285
return
273286
}
274287
traceLength := len(traceJSON)
275-
if traceLength > MaxTraceSize {
288+
if traceLength > tracer.Config.MaxTraceSize {
276289
ok := tracer.stripEvents(traceLength, &marshaler)
277290
if !ok {
278-
err = errors.New("Trace is too big (max allowed size: 64KB)")
291+
err = errors.New(fmt.Sprintf("Trace is too big (max allowed size: %dKB)", tracer.Config.MaxTraceSize/1024))
279292
return
280293
}
281294
runnerEvent.Resource.Metadata[IsTrimmedKey] = "true"
@@ -343,6 +356,23 @@ func fillConfigDefaults(config *Config) {
343356
log.Println("EPSAGON DEBUG: setting token from environment variable")
344357
}
345358
}
359+
if config.MaxTraceSize > MaxTraceSize || config.MaxTraceSize < 0 {
360+
config.MaxTraceSize = DefaultMaxTraceSize
361+
if config.Debug {
362+
log.Printf("EPSAGON DEBUG: MaxTraceSize is invalid (must be <= %dKB), using default size (%dKB)\n", MaxTraceSizeKB, DefaultMaxTraceSizeKB)
363+
}
364+
} else {
365+
rawTraceSize := os.Getenv(MaxTraceSizeEnvVar)
366+
maxTraceSize, err := strconv.Atoi(rawTraceSize)
367+
if err != nil || maxTraceSize <= 0 || maxTraceSize > MaxTraceSize {
368+
config.MaxTraceSize = DefaultMaxTraceSize
369+
} else {
370+
config.MaxTraceSize = maxTraceSize
371+
if config.Debug {
372+
log.Printf("EPSAGON DEBUG: setting max trace size (%dKB) from environment variable\n", maxTraceSize/1024)
373+
}
374+
}
375+
}
346376
if config.MetadataOnly {
347377
if strings.ToUpper(os.Getenv("EPSAGON_METADATA")) == "FALSE" {
348378
config.MetadataOnly = false
@@ -407,7 +437,7 @@ func CreateGlobalTracer(config *Config) Tracer {
407437
defer mutex.Unlock()
408438
if GlobalTracer != nil && !GlobalTracer.Stopped() {
409439
log.Println("The tracer is already created, Closing and Creating.")
410-
GlobalTracer.Stop()
440+
StopGlobalTracer()
411441
}
412442
GlobalTracer = CreateTracer(config)
413443
return GlobalTracer

tracer/tracer_test.go

+41-47
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import (
55
"encoding/json"
66
"fmt"
77
"io"
8+
"io/ioutil"
89
"log"
9-
"net"
1010
"net/http"
1111
"net/http/httptest"
1212
"os"
@@ -22,42 +22,6 @@ import (
2222
. "github.com/onsi/gomega"
2323
)
2424

25-
// FakeCollector implements a fake trace collector that will
26-
// listen on an endpoint untill a trace is received and then will
27-
// return that parsed trace
28-
type FakeCollector struct {
29-
Endpoint string
30-
}
31-
32-
// Listen on the endpoint for one trace and push it to outChannel
33-
func (fc *FakeCollector) Listen(outChannel chan *protocol.Trace) {
34-
ln, err := net.Listen("tcp", fc.Endpoint)
35-
if err != nil {
36-
outChannel <- nil
37-
return
38-
}
39-
defer ln.Close()
40-
conn, err := ln.Accept()
41-
if err != nil {
42-
outChannel <- nil
43-
return
44-
}
45-
defer conn.Close()
46-
var buf = make([]byte, 0)
47-
_, err = conn.Read(buf)
48-
if err != nil {
49-
outChannel <- nil
50-
return
51-
}
52-
var receivedTrace protocol.Trace
53-
err = json.Unmarshal(buf, &receivedTrace)
54-
if err != nil {
55-
outChannel <- nil
56-
return
57-
}
58-
outChannel <- &receivedTrace
59-
}
60-
6125
func TestEpsagonTracer(t *testing.T) {
6226
RegisterFailHandler(Fail)
6327
RunSpecs(t, "Epsagon Core Suite")
@@ -75,8 +39,10 @@ var _ = Describe("epsagonTracer suite", func() {
7539
})
7640

7741
func runWithTracer(endpoint string, operations func()) {
42+
tracer.GlobalTracer = nil
7843
tracer.CreateGlobalTracer(&tracer.Config{
7944
CollectorURL: endpoint,
45+
Token: "1",
8046
})
8147
tracer.GlobalTracer.Start()
8248
defer tracer.StopGlobalTracer()
@@ -85,20 +51,36 @@ func runWithTracer(endpoint string, operations func()) {
8551

8652
// testWithTracer runs a test with
8753
func testWithTracer(timeout *time.Duration, operations func()) *protocol.Trace {
88-
endpoint := "127.0.0.1:54769"
8954
traceChannel := make(chan *protocol.Trace)
90-
fc := FakeCollector{Endpoint: endpoint}
91-
go fc.Listen(traceChannel)
92-
go runWithTracer("http://"+endpoint, operations)
55+
fakeCollectorServer := httptest.NewServer(http.HandlerFunc(
56+
func(res http.ResponseWriter, req *http.Request) {
57+
buf, err := ioutil.ReadAll(req.Body)
58+
if err != nil {
59+
traceChannel <- nil
60+
return
61+
}
62+
var receivedTrace protocol.Trace
63+
err = json.Unmarshal(buf, &receivedTrace)
64+
if err != nil {
65+
traceChannel <- nil
66+
return
67+
}
68+
traceChannel <- &receivedTrace
69+
res.Write([]byte(""))
70+
},
71+
))
72+
go runWithTracer(fakeCollectorServer.URL, operations)
9373
if timeout == nil {
9474
defaultTimeout := time.Second * 10
9575
timeout = &defaultTimeout
9676
}
9777
timer := time.NewTimer(*timeout)
9878
select {
9979
case <-timer.C:
80+
fakeCollectorServer.Close()
10081
return nil
10182
case trace := <-traceChannel:
83+
fakeCollectorServer.Close()
10284
return trace
10385
}
10486
}
@@ -175,22 +157,34 @@ func Test_handleSendTracesResponse(t *testing.T) {
175157
}
176158

177159
func Test_AddLabel_sanity(t *testing.T) {
178-
defaultTimeout := time.Second * 100
160+
defaultTimeout := time.Second * 5
179161
timeout := &defaultTimeout
180162
trace := testWithTracer(timeout, func() { epsagon.Label("test_key", "test_value") })
181-
println(trace)
163+
Expect(trace).ToNot(BeNil())
182164
}
183165

184166
func Test_AddError_sanity(t *testing.T) {
185-
defaultTimeout := time.Second * 100
167+
defaultTimeout := time.Second * 5
186168
timeout := &defaultTimeout
187169
trace := testWithTracer(timeout, func() { epsagon.Error("some error") })
188-
println(trace)
170+
Expect(trace).ToNot(BeNil())
189171
}
190172

191173
func Test_AddTypeError(t *testing.T) {
192-
defaultTimeout := time.Second * 100
174+
defaultTimeout := time.Second * 5
193175
timeout := &defaultTimeout
194176
trace := testWithTracer(timeout, func() { epsagon.TypeError("some error", "test error type") })
195-
println(trace)
177+
Expect(trace).ToNot(BeNil())
178+
}
179+
180+
func Test_MaxTraceSize_sanity(t *testing.T) {
181+
defer os.Unsetenv(tracer.MaxTraceSizeEnvVar)
182+
os.Setenv(tracer.MaxTraceSizeEnvVar, "2048")
183+
defaultTimeout := time.Second * 5
184+
timeout := &defaultTimeout
185+
trace := testWithTracer(timeout, func() { epsagon.Label("1", "2") })
186+
Expect(trace).ToNot(BeNil())
187+
os.Setenv(tracer.MaxTraceSizeEnvVar, "64")
188+
trace = testWithTracer(timeout, func() { epsagon.Label("1", "2") })
189+
Expect(trace).To(BeNil())
196190
}

0 commit comments

Comments
 (0)