Skip to content

Commit

Permalink
[cmd/telemetrygen] Add TraceID and SpanID support for logs in tracegen (
Browse files Browse the repository at this point in the history
#33234)

Signed-off-by: Juraci Paixão Kröhling <juraci@kroehling.de>

---------

Signed-off-by: Juraci Paixão Kröhling <juraci@kroehling.de>
  • Loading branch information
jpkrohling authored May 28, 2024
1 parent ea9144e commit 9a0a8fa
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 0 deletions.
27 changes: 27 additions & 0 deletions .chloggen/add-traceid-spanid-telemetrygen.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: cmd/telemetrygen

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Add support for specifying trace ID and span ID in telemetrygen for logs

# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
issues: [33234]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:

# If your change doesn't affect end users or the exported elements of any package,
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: []
32 changes: 32 additions & 0 deletions cmd/telemetrygen/internal/logs/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
package logs

import (
"encoding/hex"

"github.com/spf13/pflag"

"github.com/open-telemetry/opentelemetry-collector-contrib/cmd/telemetrygen/internal/common"
Expand All @@ -16,6 +18,8 @@ type Config struct {
Body string
SeverityText string
SeverityNumber int32
TraceID string
SpanID string
}

// Flags registers config flags.
Expand All @@ -28,4 +32,32 @@ func (c *Config) Flags(fs *pflag.FlagSet) {
fs.StringVar(&c.Body, "body", "the message", "Body of the log")
fs.StringVar(&c.SeverityText, "severity-text", "Info", "Severity text of the log")
fs.Int32Var(&c.SeverityNumber, "severity-number", 9, "Severity number of the log, range from 1 to 24 (inclusive)")
fs.StringVar(&c.TraceID, "trace-id", "", "TraceID of the log")
fs.StringVar(&c.SpanID, "span-id", "", "SpanID of the log")
}

// Validate validates the test scenario parameters.
func (c *Config) Validate() error {
if c.TraceID != "" {
if len(c.TraceID) != 32 {
return errInvalidTraceIDLenght
}

_, err := hex.DecodeString(c.TraceID)
if err != nil {
return errInvalidTraceID
}
}

if c.SpanID != "" {
if len(c.SpanID) != 16 {
return errInvalidSpanIDLenght
}
_, err := hex.DecodeString(c.SpanID)
if err != nil {
return errInvalidSpanID
}
}

return nil
}
66 changes: 66 additions & 0 deletions cmd/telemetrygen/internal/logs/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package logs

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestValidate(t *testing.T) {
tests := []struct {
name string
config *Config
expected error
}{
{
name: "ValidConfig",
config: &Config{
TraceID: "ae87dadd90e9935a4bc9660628efd569",
SpanID: "5828fa4960140870",
},
expected: nil,
},
{
name: "InvalidInvalidTraceIDLenght",
config: &Config{
TraceID: "invalid-length",
SpanID: "5828fa4960140870",
},
expected: errInvalidTraceIDLenght,
},
{
name: "InvalidInvalidSpanIDLenght",
config: &Config{
TraceID: "ae87dadd90e9935a4bc9660628efd569",
SpanID: "invalid-length",
},
expected: errInvalidSpanIDLenght,
},
{
name: "InvalidTraceID",
config: &Config{
TraceID: "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz",
SpanID: "5828fa4960140870",
},
expected: errInvalidTraceID,
},
{
name: "InvalidSpanID",
config: &Config{
TraceID: "ae87dadd90e9935a4bc9660628efd569",
SpanID: "zzzzzzzzzzzzzzzz",
},
expected: errInvalidSpanID,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.config.Validate()
assert.ErrorIs(t, err, tt.expected)
})
}
}
14 changes: 14 additions & 0 deletions cmd/telemetrygen/internal/logs/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ import (
"github.com/open-telemetry/opentelemetry-collector-contrib/cmd/telemetrygen/internal/common"
)

var (
errInvalidTraceIDLenght = fmt.Errorf("TraceID must be a 32 character hex string, like: 'ae87dadd90e9935a4bc9660628efd569'")
errInvalidSpanIDLenght = fmt.Errorf("SpanID must be a 16 character hex string, like: '5828fa4960140870'")
errInvalidTraceID = fmt.Errorf("failed to create traceID byte array from the given traceID, make sure the traceID is a hex representation of a [16]byte, like: 'ae87dadd90e9935a4bc9660628efd569'")
errInvalidSpanID = fmt.Errorf("failed to create SpanID byte array from the given SpanID, make sure the SpanID is a hex representation of a [8]byte, like: '5828fa4960140870'")
)

// Start starts the log telemetry generator
func Start(cfg *Config) error {
logger, err := common.CreateLogger(cfg.SkipSettingGRPCLogger)
Expand All @@ -30,6 +37,11 @@ func Start(cfg *Config) error {
return err
}

if err = cfg.Validate(); err != nil {
logger.Error("failed to validate the parameters for the test scenario.", zap.Error(err))
return err
}

if err = Run(cfg, e, logger); err != nil {
logger.Error("failed to execute the test scenario.", zap.Error(err))
return err
Expand Down Expand Up @@ -78,6 +90,8 @@ func Run(c *Config, exp exporter, logger *zap.Logger) error {
wg: &wg,
logger: logger.With(zap.Int("worker", i)),
index: i,
traceID: c.TraceID,
spanID: c.SpanID,
}

go w.simulateLogs(res, exp, c.GetTelemetryAttributes())
Expand Down
22 changes: 22 additions & 0 deletions cmd/telemetrygen/internal/logs/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package logs

import (
"context"
"encoding/hex"
"sync"
"sync/atomic"
"time"
Expand All @@ -28,6 +29,8 @@ type worker struct {
wg *sync.WaitGroup // notify when done
logger *zap.Logger // logger
index int // worker index
traceID string // traceID string
spanID string // spanID string
}

func (w worker) simulateLogs(res *resource.Resource, exporter exporter, telemetryAttributes []attribute.KeyValue) {
Expand All @@ -41,6 +44,7 @@ func (w worker) simulateLogs(res *resource.Resource, exporter exporter, telemetr
for _, attr := range attrs {
nRes.Attributes().PutStr(string(attr.Key), attr.Value.AsString())
}

log := logs.ResourceLogs().At(0).ScopeLogs().AppendEmpty().LogRecords().AppendEmpty()
log.Body().SetStr(w.body)
log.SetTimestamp(pcommon.NewTimestampFromTime(time.Now()))
Expand All @@ -51,6 +55,24 @@ func (w worker) simulateLogs(res *resource.Resource, exporter exporter, telemetr
lattrs := log.Attributes()
lattrs.PutStr("app", "server")

if w.traceID != "" {
// we checked this for errors in the Validate function
// nolint: errcheck
b, _ := hex.DecodeString(w.traceID)

tid := pcommon.TraceID(b)
log.SetTraceID(tid)
}

if w.spanID != "" {
// we checked this for errors in the Validate function
// nolint: errcheck
b, _ := hex.DecodeString(w.spanID)

sid := pcommon.SpanID(b)
log.SetSpanID(sid)
}

for i, attr := range telemetryAttributes {
lattrs.PutStr(string(attr.Key), telemetryAttributes[i].Value.AsString())
}
Expand Down
24 changes: 24 additions & 0 deletions cmd/telemetrygen/internal/logs/worker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,30 @@ func TestLogsWithMultipleTelemetryAttributes(t *testing.T) {
}
}

func TestLogsWithTraceIDAndSpanID(t *testing.T) {
qty := 1
cfg := configWithOneAttribute(qty, "custom body")
cfg.TraceID = "ae87dadd90e9935a4bc9660628efd569"
cfg.SpanID = "5828fa4960140870"

exp := &mockExporter{}

// test
logger, _ := zap.NewDevelopment()
require.NoError(t, Run(cfg, exp, logger))

// verify
require.Len(t, exp.logs, qty)
for _, log := range exp.logs {
rlogs := log.ResourceLogs()
for i := 0; i < rlogs.Len(); i++ {
log := rlogs.At(i).ScopeLogs().At(0).LogRecords().At(0)
assert.Equal(t, "ae87dadd90e9935a4bc9660628efd569", log.TraceID().String())
assert.Equal(t, "5828fa4960140870", log.SpanID().String())
}
}
}

func configWithNoAttributes(qty int, body string) *Config {
return &Config{
Body: body,
Expand Down

0 comments on commit 9a0a8fa

Please sign in to comment.