Skip to content

Commit

Permalink
Fix Sentry Debug Message for split debug messages
Browse files Browse the repository at this point in the history
by buffering a message when the message does not contain both start and end of a debug message.
  • Loading branch information
mpass99 committed Sep 12, 2024
1 parent 758a6aa commit 6982bf0
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 7 deletions.
35 changes: 28 additions & 7 deletions internal/nomad/sentry_debug_writer.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package nomad

import (
"bytes"
"context"
"fmt"
"io"
Expand All @@ -22,8 +23,9 @@ var (

timeDebugMessagePattern = regexp.MustCompile(
`(?P<before>[\S\s]*?)\x1EPoseidon (?P<text>[^\x1E]+?) (?P<time>\d{13})\x1E(?P<after>[\S\s]*)`)
timeDebugMessagePatternStart = regexp.MustCompile(`\x1EPoseidon`)
timeDebugFallbackDescription = "<empty>"
timeDebugMessagePatternStart = regexp.MustCompile(`\x1EPoseidon`)
timeDebugMessagePatternStartEnd = regexp.MustCompile(`\x1EPoseidon.*\x1E`)
timeDebugFallbackDescription = "<empty>"
)

// SentryDebugWriter is scanning the input for the debug message pattern.
Expand All @@ -32,18 +34,20 @@ var (
type SentryDebugWriter struct {
Target io.Writer
//nolint:containedctx // See #630.
Ctx context.Context
lastSpan *sentry.Span
Ctx context.Context
lastSpan *sentry.Span
remaining *bytes.Buffer
}

func NewSentryDebugWriter(ctx context.Context, target io.Writer) *SentryDebugWriter {
ctx = logging.CloneSentryHub(ctx)
span := sentry.StartSpan(ctx, "nomad.execute.connect")
span.Description = "/bin/bash -c"
return &SentryDebugWriter{
Target: target,
Ctx: ctx,
lastSpan: span,
Target: target,
Ctx: ctx,
lastSpan: span,
remaining: &bytes.Buffer{},
}
}

Expand All @@ -59,6 +63,15 @@ func (s *SentryDebugWriter) Write(debugData []byte) (n int, err error) {
}
log.WithContext(s.lastSpan.Context()).WithField("data", fmt.Sprintf("%q", debugData)).Trace("Received data from Nomad container")

if s.remaining.Len() > 0 {
n -= s.remaining.Len()
joinedDebugData := make([]byte, 0, s.remaining.Len()+len(debugData))
joinedDebugData = append(joinedDebugData, s.remaining.Bytes()...)
joinedDebugData = append(joinedDebugData, debugData...)
s.remaining.Reset()
debugData = joinedDebugData
}

if !timeDebugMessagePatternStart.Match(debugData) {
count, err := s.Target.Write(debugData)
if err != nil {
Expand All @@ -67,6 +80,14 @@ func (s *SentryDebugWriter) Write(debugData []byte) (n int, err error) {
return count, err
}

if !timeDebugMessagePatternStartEnd.Match(debugData) {
count, err := s.remaining.Write(debugData)
if err != nil {
err = fmt.Errorf("SentryDebugWriter failed to buffer data: %w", err)

Check warning on line 86 in internal/nomad/sentry_debug_writer.go

View check run for this annotation

Codecov / codecov/patch

internal/nomad/sentry_debug_writer.go#L86

Added line #L86 was not covered by tests
}
return count, err
}

match := matchAndMapTimeDebugMessage(debugData)
if match == nil {
log.WithContext(s.lastSpan.Context()).WithField("data", fmt.Sprintf("%q", debugData)).Warn("Exec debug message could not be read completely")

Check warning on line 93 in internal/nomad/sentry_debug_writer.go

View check run for this annotation

Codecov / codecov/patch

internal/nomad/sentry_debug_writer.go#L93

Added line #L93 was not covered by tests
Expand Down
39 changes: 39 additions & 0 deletions internal/nomad/sentry_debug_writer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,45 @@ func (s *MainTestSuite) TestSentryDebugWriter_regression_593_empty_command() {
s.Equal(timeDebugFallbackDescription, debugWriter.lastSpan.Description)
}

func (s *MainTestSuite) TestSentryDebugWriter_regression_593_split_debug_message() {
buf := &bytes.Buffer{}
debugWriter := NewSentryDebugWriter(s.TestCtx, buf)

s.Run("single debug message", func() {
output := "Output"
payload := output + "\x1ePoseidon exit 0 1"
payload2 := "725462286087\x1E"

count, err := debugWriter.Write([]byte(payload))
s.Require().NoError(err)
s.Equal(len(payload), count)
s.NotEqual("exit 0", debugWriter.lastSpan.Description)

count, err = debugWriter.Write([]byte(payload2))
s.Require().NoError(err)
s.Equal(len(payload2), count)
s.Equal("exit 0", debugWriter.lastSpan.Description)
s.Equal(output, buf.String())
})
buf.Reset()
s.Run("multiple debug messages", func() {
output := "Output"
payload := "\x1ePoseidon env 1725462286085\x1E" + output + "\x1ePoseidon exit 0 1"
payload2 := "725462286087\x1E"

count, err := debugWriter.Write([]byte(payload))
s.Require().NoError(err)
s.Equal(len(payload), count)
s.NotEqual("exit 0", debugWriter.lastSpan.Description)

count, err = debugWriter.Write([]byte(payload2))
s.Require().NoError(err)
s.Equal(len(payload2), count)
s.Equal("exit 0", debugWriter.lastSpan.Description)
s.Equal(output, buf.String())
})
}

func (s *MainTestSuite) TestSentryDebugWriter_regression_issue_678() {
buf := &bytes.Buffer{}
debugWriter := NewSentryDebugWriter(s.TestCtx, buf)
Expand Down

0 comments on commit 6982bf0

Please sign in to comment.