Skip to content

Commit

Permalink
feature(backend): updating metadata fields to match semantic conventi…
Browse files Browse the repository at this point in the history
…ons (#2717)

* feature(backend): updating metadata fields to match semantic conventions

* feature(backend): PR improvements and aliases for attributes

* feature(backend): fixing unit tests

* feature(backend): PR improvements

* feature(backend): fixing error message
  • Loading branch information
xoscar committed Jun 13, 2023
1 parent da41f03 commit 84f4e11
Show file tree
Hide file tree
Showing 19 changed files with 74 additions and 43 deletions.
20 changes: 10 additions & 10 deletions server/executor/poller_executor_test.go
Expand Up @@ -148,8 +148,8 @@ func Test_PollerExecutor_ExecuteRequest_NoRootSpan_TwoSpansCase(t *testing.T) {
StartTime: firstSpan.EndTime,
EndTime: firstSpan.EndTime.Add(retryDelay),
Attributes: map[string]string{
"testSpan": "true",
"parent_id": firstSpan.ID.String(),
"testSpan": "true",
model.TracetestMetadataFieldParentID: firstSpan.ID.String(),
},
Children: []*model.Span{},
}
Expand Down Expand Up @@ -264,8 +264,8 @@ func Test_PollerExecutor_ExecuteRequest_WithRootSpan_OneSpanCase(t *testing.T) {
StartTime: time.Now(),
EndTime: time.Now().Add(retryDelay),
Attributes: map[string]string{
"testSpan": "true",
"parent_id": rootSpanID.String(),
"testSpan": "true",
model.TracetestMetadataFieldParentID: rootSpanID.String(),
},
Children: []*model.Span{},
},
Expand Down Expand Up @@ -325,8 +325,8 @@ func Test_PollerExecutor_ExecuteRequest_WithRootSpan_OneDelayedSpanCase(t *testi
StartTime: time.Now(),
EndTime: time.Now().Add(retryDelay),
Attributes: map[string]string{
"testSpan": "true",
"parent_id": rootSpan.ID.String(),
"testSpan": "true",
model.TracetestMetadataFieldParentID: rootSpan.ID.String(),
},
Children: []*model.Span{},
}
Expand Down Expand Up @@ -394,8 +394,8 @@ func Test_PollerExecutor_ExecuteRequest_WithRootSpan_TwoSpansCase(t *testing.T)
StartTime: time.Now(),
EndTime: time.Now().Add(retryDelay),
Attributes: map[string]string{
"testSpan": "true",
"parent_id": rootSpan.ID.String(),
"testSpan": "true",
model.TracetestMetadataFieldParentID: rootSpan.ID.String(),
},
Children: []*model.Span{},
}
Expand All @@ -406,8 +406,8 @@ func Test_PollerExecutor_ExecuteRequest_WithRootSpan_TwoSpansCase(t *testing.T)
StartTime: firstSpan.EndTime,
EndTime: firstSpan.EndTime.Add(retryDelay),
Attributes: map[string]string{
"testSpan": "true",
"parent_id": firstSpan.ID.String(),
"testSpan": "true",
model.TracetestMetadataFieldParentID: firstSpan.ID.String(),
},
Children: []*model.Span{},
}
Expand Down
2 changes: 1 addition & 1 deletion server/executor/selector_based_poller_executor_test.go
Expand Up @@ -131,7 +131,7 @@ func TestSelectorBasedPollerExecutor(t *testing.T) {
rootSpan := model.Span{ID: randomIDGenerator.SpanID(), Name: "Tracetest trigger", Attributes: make(model.Attributes)}
trace := model.NewTrace(randomIDGenerator.TraceID().String(), []model.Span{
rootSpan,
{ID: randomIDGenerator.SpanID(), Name: "GET /api/tests", Attributes: model.Attributes{"parent_id": rootSpan.ID.String()}},
{ID: randomIDGenerator.SpanID(), Name: "GET /api/tests", Attributes: model.Attributes{model.TracetestMetadataFieldParentID: rootSpan.ID.String()}},
})
run := model.Run{Trace: &trace}

Expand Down
21 changes: 20 additions & 1 deletion server/expression/data_store.go
Expand Up @@ -13,6 +13,10 @@ type DataStore interface {
Get(name string) (string, error)
}

var attributeAlias = map[string]string{
"name": "tracetest.span.name",
}

type AttributeDataStore struct {
Span model.Span
}
Expand All @@ -21,10 +25,25 @@ func (ds AttributeDataStore) Source() string {
return "attr"
}

func (ds AttributeDataStore) getFromAlias(name string) (string, error) {
alias, found := attributeAlias[name]

if !found {
return "", fmt.Errorf(`attribute "%s" not found`, name)
}

value := ds.Span.Attributes.Get(alias)
if value == "" {
return "", fmt.Errorf(`attribute "%s" not found`, name)
}

return value, nil
}

func (ds AttributeDataStore) Get(name string) (string, error) {
value := ds.Span.Attributes.Get(name)
if value == "" {
return "", fmt.Errorf(`attribute "%s" not found`, name)
return ds.getFromAlias(name)
}

return value, nil
Expand Down
1 change: 1 addition & 0 deletions server/http/mappings/traces.go
Expand Up @@ -57,6 +57,7 @@ func (m OpenAPI) Span(in model.Span) openapi.Span {
EndTime: in.EndTime.UnixMilli(),
Attributes: attributes,
Children: m.Spans(in.Children),
Name: in.Name,
}
}

Expand Down
20 changes: 15 additions & 5 deletions server/model/spans.go
Expand Up @@ -9,6 +9,16 @@ import (
"go.opentelemetry.io/otel/trace"
)

const (
TracetestMetadataFieldStartTime string = "tracetest.span.start_time"
TracetestMetadataFieldEndTime string = "tracetest.span.end_time"
TracetestMetadataFieldDuration string = "tracetest.span.duration"
TracetestMetadataFieldType string = "tracetest.span.type"
TracetestMetadataFieldName string = "tracetest.span.name"
TracetestMetadataFieldParentID string = "tracetest.span.parent_id"
TracetestMetadataFieldKind string = "tracetest.span.kind"
)

type Attributes map[string]string

func (a Attributes) Get(key string) string {
Expand Down Expand Up @@ -184,11 +194,11 @@ func decodeChildren(parent *Span, children []encodedSpan) ([]*Span, error) {
}

func (span Span) setMetadataAttributes() Span {
span.Attributes["name"] = span.Name
span.Attributes["tracetest.span.type"] = spanType(span.Attributes)
span.Attributes["tracetest.span.duration"] = spanDuration(span)
span.Attributes["tracetest.span.startTime"] = fmt.Sprintf("%d", span.StartTime.UnixNano())
span.Attributes["tracetest.span.endTime"] = fmt.Sprintf("%d", span.EndTime.UnixNano())
span.Attributes[TracetestMetadataFieldName] = span.Name
span.Attributes[TracetestMetadataFieldType] = spanType(span.Attributes)
span.Attributes[TracetestMetadataFieldDuration] = spanDuration(span)
span.Attributes[TracetestMetadataFieldStartTime] = fmt.Sprintf("%d", span.StartTime.UnixNano())
span.Attributes[TracetestMetadataFieldEndTime] = fmt.Sprintf("%d", span.EndTime.UnixNano())

return span
}
Expand Down
4 changes: 2 additions & 2 deletions server/model/traces.go
Expand Up @@ -25,7 +25,7 @@ func NewTrace(traceID string, spans []Span) Trace {

rootSpans := make([]*Span, 0)
for _, span := range spanMap {
parentID := span.Attributes["parent_id"]
parentID := span.Attributes[TracetestMetadataFieldParentID]
parentSpan, found := spanMap[parentID]
if !found {
rootSpans = append(rootSpans, span)
Expand Down Expand Up @@ -159,7 +159,7 @@ func replaceRoot(oldRoot, newRoot Span) Span {
oldRoot.Attributes = make(Attributes)
}
oldRoot.Parent = &newRoot
oldRoot.Attributes["parent_id"] = newRoot.ID.String()
oldRoot.Attributes[TracetestMetadataFieldParentID] = newRoot.ID.String()

newRoot.Children = append(newRoot.Children, &oldRoot)

Expand Down
2 changes: 1 addition & 1 deletion server/model/traces_test.go
Expand Up @@ -187,7 +187,7 @@ func newSpan(name string, parent *model.Span) model.Span {
}

if parent != nil {
span.Attributes["parent_id"] = parent.ID.String()
span.Attributes[model.TracetestMetadataFieldParentID] = parent.ID.String()
}

return span
Expand Down
4 changes: 2 additions & 2 deletions server/tracedb/awsxray.go
Expand Up @@ -205,9 +205,9 @@ func generateSpan(seg *segment, parent *model.Span) (model.Span, error) {
return span, err
}

attributes["parent_id"] = parentID.String()
attributes[model.TracetestMetadataFieldParentID] = parentID.String()
} else if parent != nil {
attributes["parent_id"] = parent.ID.String()
attributes[model.TracetestMetadataFieldParentID] = parent.ID.String()
}

// decode span id
Expand Down
4 changes: 2 additions & 2 deletions server/tracedb/azureappinsights.go
Expand Up @@ -231,9 +231,9 @@ func parseParentId(span *model.Span, row azquery.Row, index int) error {

rawParentId, ok := row[index].(string)
if ok {
span.Attributes["parent_id"] = rawParentId
span.Attributes[model.TracetestMetadataFieldParentID] = rawParentId
} else {
span.Attributes["parent_id"] = ""
span.Attributes[model.TracetestMetadataFieldParentID] = ""
}
return nil
}
Expand Down
2 changes: 1 addition & 1 deletion server/tracedb/elasticsearchdb.go
Expand Up @@ -216,7 +216,7 @@ func convertElasticSearchSpanIntoSpan(input map[string]interface{}) model.Span {
// ParentId
parentId := flatInput["parent.id"]
if parentId != nil {
attributes["parent_id"] = flatInput["parent.id"].(string)
attributes[model.TracetestMetadataFieldParentID] = flatInput["parent.id"].(string)
}

return model.Span{
Expand Down
4 changes: 2 additions & 2 deletions server/tracedb/opensearchdb.go
Expand Up @@ -160,8 +160,8 @@ func convertOpensearchSpanIntoSpan(input map[string]interface{}) model.Span {
attributes[name] = fmt.Sprintf("%v", attrValue)
}

attributes["kind"] = input["kind"].(string)
attributes["parent_id"] = input["parentSpanId"].(string)
attributes[model.TracetestMetadataFieldKind] = input["kind"].(string)
attributes[model.TracetestMetadataFieldKind] = input["parentSpanId"].(string)

return model.Span{
ID: spanId,
Expand Down
4 changes: 2 additions & 2 deletions server/tracedb/signalfxdb.go
Expand Up @@ -177,8 +177,8 @@ func convertSignalFXSpan(in signalFXSpan) model.Span {
attributes[name] = value
}

attributes["parent_id"] = in.ParentID
attributes["kind"] = attributes["span.kind"]
attributes[model.TracetestMetadataFieldParentID] = in.ParentID
attributes[model.TracetestMetadataFieldKind] = attributes["span.kind"]
delete(attributes, "span.kind")

spanID, _ := trace.SpanIDFromHex(in.SpanID)
Expand Down
2 changes: 1 addition & 1 deletion server/traces/otel_converter.go
Expand Up @@ -52,7 +52,7 @@ func ConvertOtelSpanIntoSpan(span *v1.Span) *model.Span {
}

spanID := createSpanID(span.SpanId)
attributes["parent_id"] = createSpanID(span.ParentSpanId).String()
attributes[model.TracetestMetadataFieldParentID] = createSpanID(span.ParentSpanId).String()
return &model.Span{
ID: spanID,
Name: span.Name,
Expand Down
2 changes: 1 addition & 1 deletion server/traces/otel_http_converter.go
Expand Up @@ -80,7 +80,7 @@ func convertHttpOtelSpanIntoSpan(span *httpSpan) *model.Span {
}

spanID := createSpanID([]byte(span.SpanId))
attributes["parent_id"] = createSpanID([]byte(span.ParentSpanId)).String()
attributes[model.TracetestMetadataFieldParentID] = createSpanID([]byte(span.ParentSpanId)).String()

return &model.Span{
ID: spanID,
Expand Down
Expand Up @@ -18,8 +18,8 @@ spec:
- attr:tracetest.selected_spans.count = 1
- attr:tracetest.response.status = 200
# Ensure startTime and endTime are present in span
- attr:tracetest.span.startTime > 0
- attr:tracetest.span.endTime > 0
- attr:tracetest.span.start_time > 0
- attr:tracetest.span.end_time > 0
- selector: span[name = "POST /api/tests/{testId}/run" tracetest.span.type = "http"]
assertions:
- attr:tracetest.selected_spans.count = 1
Expand Down
2 changes: 1 addition & 1 deletion web/src/constants/SpanAttribute.constants.ts
Expand Up @@ -2,7 +2,7 @@ import {SemanticAttributes, SemanticResourceAttributes} from '@opentelemetry/sem

export const TraceTestAttributes = {
NAME: 'name',
KIND: 'kind',
KIND: 'tracetest.span.kind',
TRACETEST_SPAN_TYPE: 'tracetest.span.type',
TRACETEST_SPAN_DURATION: 'tracetest.span.duration',
TRACETEST_RESPONSE_STATUS: 'tracetest.response.status',
Expand Down
16 changes: 9 additions & 7 deletions web/src/models/Span.model.ts
Expand Up @@ -48,19 +48,21 @@ const getSpanSignature = (
}, []);
};

const Span = ({id = '', attributes = {}, startTime = 0, endTime = 0, parentId = ''}: TRawSpan): Span => {
const attributeList = Object.entries(attributes).map<TSpanFlatAttribute>(([key, value]) => ({
value: String(value),
key,
}));
const Span = ({id = '', attributes = {}, startTime = 0, endTime = 0, parentId = '', name = ''}: TRawSpan): Span => {
const mappedAttributeList: TSpanFlatAttribute[] = [{key: 'name', value: name}];
const attributeList = Object.entries(attributes)
.map<TSpanFlatAttribute>(([key, value]) => ({
value: String(value),
key,
}))
.concat(mappedAttributeList);

const attributesMap = attributeList.reduce<Record<string, SpanAttribute>>((map, rawSpanAttribute) => {
const attributesMap = attributeList.reduce((map, rawSpanAttribute) => {
const spanAttribute = SpanAttribute(rawSpanAttribute);

return {...map, [spanAttribute.name]: SpanAttribute(rawSpanAttribute)};
}, {});

const name = attributes[Attributes.NAME] || '';
const kind = SpanKindList.find(spanKind => spanKind === attributes[Attributes.KIND]) || SpanKind.INTERNAL;
const duration = attributes[Attributes.TRACETEST_SPAN_DURATION] || '0ns';
const type =
Expand Down
1 change: 0 additions & 1 deletion web/src/models/__mocks__/Span.mock.ts
Expand Up @@ -12,7 +12,6 @@ const SpanMock: IMockFactory<Span, TRawSpan> = () => ({
endTime: faker.date.recent().getMilliseconds(),
attributes: {
'service.name': 'mock',
name: 'span-mock',
'tracetest.span.duration': '10',
},
children: [],
Expand Down
2 changes: 1 addition & 1 deletion web/src/models/__tests__/Span.model.test.ts
Expand Up @@ -11,7 +11,7 @@ describe('Span', () => {
expect(Array.isArray(span.attributeList)).toBe(true);
const value = rawSpan.attributes!['service.name'];
expect(span.attributes['service.name'].value).toEqual(value);
expect(span.name).toEqual(rawSpan.attributes?.name);
expect(span.name).toEqual(rawSpan.name);
expect(span.duration).toEqual(rawSpan.attributes!['tracetest.span.duration']);
});
});

0 comments on commit 84f4e11

Please sign in to comment.