Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added --properties-allowed switch and retries to test. #89

Merged
merged 11 commits into from
Dec 20, 2024
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ This tool is able to override the following attributes:
| Service Name | --service-name | `junit2otlp` | Overrides OpenTelemetry's service name. If the `OTEL_SERVICE_NAME` environment variable is set, it will take precedence over any other value. |
| Service Version | --service-version | Empty | Overrides OpenTelemetry's service version. If the `OTEL_SERVICE_VERSION` environment variable is set, it will take precedence over any other value. |
| Trace Name | --trace-name | `junit2otlp` | Overrides OpenTelemetry's trace name. |
| Properties Allowed | --properties-allowed | All | Comma separated list of properties to be allowed in the jUnit report. |
mdelapenya marked this conversation as resolved.
Show resolved Hide resolved

For using this tool in a distributed tracing scenario, where there is a parent trace in which the test reports traces should be attached, it's important to set the `TRACEPARENT` environment variable, so that the traces and spans generated by this tool are located under the right parent trace. Please read more on this [here](https://github.com/open-telemetry/opentelemetry-specification/issues/740).

Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ require (
github.com/Microsoft/hcsshim v0.9.4 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect
github.com/acomagu/bufpipe v1.0.3 // indirect
github.com/avast/retry-go v3.0.0+incompatible // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/containerd/cgroups v1.0.4 // indirect
github.com/containerd/containerd v1.6.8 // indirect
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0=
github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
Expand Down Expand Up @@ -963,6 +965,7 @@ go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw=
go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I=
go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM=
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4=
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0/go.mod h1:78XhIg8Ht9vR4tbLNUhXsiOnE2HOuSeKAiAcoVQEpOY=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.33.0 h1:7F29RDmnlqk6B5d+sUqemt8TBfDqxryYW5gX6L74RFA=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.33.0/go.mod h1:ZiGDq7xwDMKmWDrN1XsXAj0iC7hns+2DhxBFSncNHSE=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0/go.mod h1:hO1KLR7jcKaDDKDkvI9dP/FIhpmna5lkqPUQdEjFAM8=
Expand Down
28 changes: 27 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"log"
"os"
"runtime"
"slices"
"strings"
"time"

"github.com/joshdk/go-junit"
Expand All @@ -27,20 +29,33 @@ var repositoryPathFlag string
var serviceNameFlag string
var serviceVersionFlag string
var traceNameFlag string
var propertiesAllowedString string

const propertiesAllowAll = "all"

var runtimeAttributes []attribute.KeyValue
var propsAllowed []string

func init() {
flag.StringVar(&repositoryPathFlag, "repository-path", getDefaultwd(), "Path to the SCM repository to be read")
flag.StringVar(&serviceNameFlag, "service-name", "", "OpenTelemetry Service Name to be used when sending traces and metrics for the jUnit report")
flag.StringVar(&serviceVersionFlag, "service-version", "", "OpenTelemetry Service Version to be used when sending traces and metrics for the jUnit report")
flag.StringVar(&traceNameFlag, "trace-name", Junit2otlp, "OpenTelemetry Trace Name to be used when sending traces and metrics for the jUnit report")
flag.StringVar(&propertiesAllowedString, "properties-allowed", propertiesAllowAll, "Comma separated list of properties to be allowed in the jUnit report")

// initialise runtime keys
// initialize runtime keys
runtimeAttributes = []attribute.KeyValue{
semconv.HostArchKey.String(runtime.GOARCH),
semconv.OSNameKey.String(runtime.GOOS),
}

propsAllowed = []string{}
if propertiesAllowedString != "" {
allowed := strings.Split(propertiesAllowedString, ",")
for _, prop := range allowed {
propsAllowed = append(propsAllowed, strings.TrimSpace(prop))
}
}
}

func createIntCounter(meter metric.Meter, name string, description string) metric.Int64Counter {
Expand Down Expand Up @@ -193,6 +208,13 @@ func initTracerProvider(ctx context.Context, res *resource.Resource) (*sdktrace.
func propsToLabels(props map[string]string) []attribute.KeyValue {
attributes := []attribute.KeyValue{}
for k, v := range props {
// if propertiesAllowedString is not "all" (default) and the key is not in the
// allowed list, skip it
if propertiesAllowedString != propertiesAllowAll &&
len(propsAllowed) > 0 && !slices.Contains(propsAllowed, k) {
continue
}

attributes = append(attributes, attribute.Key(k).String(v))
}

Expand All @@ -212,6 +234,10 @@ func (pr *PipeReader) Read() ([]byte, error) {
var buf []byte
scanner := bufio.NewScanner(os.Stdin)

// 64KB initial buffer, 1MB max buffer size
// was seeing large failure messages causing parsing to fail
scanner.Buffer(make([]byte, 0, 64*1024), 1024*1024)

for scanner.Scan() {
buf = append(buf, scanner.Bytes()...)
}
Expand Down
47 changes: 31 additions & 16 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import (
"path"
"strings"
"testing"
"time"

"github.com/avast/retry-go"
"github.com/docker/go-connections/nat"
"github.com/stretchr/testify/assert"
"github.com/testcontainers/testcontainers-go"
)
Expand Down Expand Up @@ -212,9 +213,17 @@ func Test_Main_SampleXML(t *testing.T) {
t.Error(err)
}

collectorPort, err := otelCollector.MappedPort(ctx, "4317/tcp")
var collectorPort nat.Port
err = retry.Do(func() error {
collectorPort, err = otelCollector.MappedPort(ctx, "4317/tcp")
if err != nil {
return err
}

return nil
})
if err != nil {
t.Errorf("could not get mapped port for otel-collector: %v", err)
t.Errorf("could not get the collector port: %s", err)
}

os.Setenv(exporterEndpointKey, "http://localhost:"+collectorPort.Port())
Expand Down Expand Up @@ -251,25 +260,31 @@ func Test_Main_SampleXML(t *testing.T) {
t.Error()
}

// TODO: retry until the file is written by the otel-exporter
time.Sleep(time.Second * 30)

// assert using the generated file
jsonBytes, err := os.ReadFile(reportFilePath)
if err != nil {
t.Error(err)
}

// merge both JSON files
// 1. get the spans and metrics JSONs, they are separated by \n
// 2. remote white spaces
// 3. unmarshal each resource separately
// 4. assign each resource to the test report struct
content := string(jsonBytes)

jsons := strings.Split(strings.TrimSpace(content), "\n")
if len(jsons) != 2 {
t.Errorf("expected 2 JSONs, got %d - %s", len(jsons), jsons)
var jsons []string
err = retry.Do(func() error {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep the wait strategy do its job here.

// assert using the generated file
jsonBytes, err := os.ReadFile(reportFilePath)
if err != nil {
t.Error(err)
}

content := string(jsonBytes)

jsons = strings.Split(strings.TrimSpace(content), "\n")
if len(jsons) != 2 {
return fmt.Errorf("expected 2 JSONs, got %d - %s", len(jsons), jsons)
}

return nil
})
if err != nil {
t.Errorf("error while waiting for collector output: %s", err)
}

jsonSpans := ""
Expand Down
Loading