Skip to content

Commit

Permalink
Merge pull request #3 from solo-io/rolds/properties_allow_list
Browse files Browse the repository at this point in the history
Support controlling which properties from the JUnit report are included in metrics and traces
  • Loading branch information
ryanrolds authored Dec 18, 2024
2 parents e824282 + c313144 commit b211433
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 18 deletions.
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. |

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
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.23

require (
github.com/go-git/go-git/v5 v5.4.2
github.com/joshdk/go-junit v0.0.0-20210226021600-6145f504ca0d
github.com/joshdk/go-junit v1.0.0
github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.10.0
github.com/testcontainers/testcontainers-go v0.14.0
Expand All @@ -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
4 changes: 4 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 @@ -600,6 +602,8 @@ github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUB
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/joshdk/go-junit v0.0.0-20210226021600-6145f504ca0d h1:lcSbmPJf3b19MTZtGDLI6Y2Jnk3VBDT8UG/8IVCEMxA=
github.com/joshdk/go-junit v0.0.0-20210226021600-6145f504ca0d/go.mod h1:TiiV0PqkaNfFXjEiyjWM3XXrhVyCa1K4Zfga6W52ung=
github.com/joshdk/go-junit v1.0.0 h1:S86cUKIdwBHWwA6xCmFlf3RTLfVXYQfvanM5Uh+K6GE=
github.com/joshdk/go-junit v1.0.0/go.mod h1:TiiV0PqkaNfFXjEiyjWM3XXrhVyCa1K4Zfga6W52ung=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
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 {
// 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

0 comments on commit b211433

Please sign in to comment.