Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/ints/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/splunk/stef/examples/ints

go 1.23.2
go 1.24.0

require (
github.com/splunk/stef/go/pkg v0.0.8
Expand Down
7 changes: 4 additions & 3 deletions examples/ints/internal/ints/record.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions examples/jsonl/internal/jsonstef/jsonobject.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions examples/profile/internal/profile/labels.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions go/otel/oteltef/attributes.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions go/otel/oteltef/envelopeattributes.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions go/otel/oteltef/keyvaluelist.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

125 changes: 125 additions & 0 deletions go/pkg/schema/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"sort"
"strings"
)

// Schema is a STEF schema description, serializable in JSON format.
Expand Down Expand Up @@ -606,6 +607,130 @@ func (d *Schema) markReachableFromFieldType(
}
}

// PrettyPrint outputs the schema in SDL format.
func (d *Schema) PrettyPrint() string {
var out []string

// Print package declaration
out = append(out, fmt.Sprintf("package %s", strings.Join(d.PackageName, ".")))

// Print enums
for _, enum := range sortedList(d.Enums) {
out = append(out, prettyPrintEnum(enum))
}

// Print multimaps
for _, mm := range sortedList(d.Multimaps) {
out = append(out, prettyPrintMultimap(mm))
}

// Print structs and oneofs
for _, s := range sortedList(d.Structs) {
out = append(out, prettyPrintStruct(s))
}

return strings.Join(out, "\n\n")
}

func sortedList[T any](m map[string]*T) []*T {
var names []string
for k := range m {
names = append(names, k)
}
sort.Strings(names)
var out []*T
for _, n := range names {
out = append(out, m[n])
}
return out
}

func prettyPrintEnum(e *Enum) string {
out := fmt.Sprintf("enum %s {", e.Name)
for _, f := range e.Fields {
out += fmt.Sprintf("\n %s = %d", f.Name, f.Value)
}
out += "\n}"
return out
}

func prettyPrintMultimap(m *Multimap) string {
out := fmt.Sprintf("multimap %s {\n", m.Name)
out += " key " + prettyPrintFieldType(&m.Key.Type)
if dict := m.Key.Type.DictName; dict != "" {
out += fmt.Sprintf(" dict(%s)", dict)
}
out += "\n"
out += " value " + prettyPrintFieldType(&m.Value.Type)
if dict := m.Value.Type.DictName; dict != "" {
out += fmt.Sprintf(" dict(%s)", dict)
}
out += "\n}"
return out
}

func prettyPrintStruct(s *Struct) string {
var out string
if s.OneOf {
out = fmt.Sprintf("oneof %s {", s.Name)
} else {
out = fmt.Sprintf("struct %s", s.Name)
if s.DictName != "" {
out += fmt.Sprintf(" dict(%s)", s.DictName)
}
if s.IsRoot {
out += " root"
}
out += " {"
}
for _, f := range s.Fields {
out += "\n " + prettyPrintStructField(f)
}
out += "\n}"
return out
}

func prettyPrintStructField(f *StructField) string {
ft := prettyPrintFieldType(&f.FieldType)
out := fmt.Sprintf("%s %s", f.Name, ft)
if f.DictName != "" {
out += fmt.Sprintf(" dict(%s)", f.DictName)
}
if f.Optional {
out += " optional"
}
return out
}

func prettyPrintFieldType(ft *FieldType) string {
switch {
case ft.Primitive != nil:
switch ft.Primitive.Type {
case PrimitiveTypeInt64:
return "int64"
case PrimitiveTypeUint64:
return "uint64"
case PrimitiveTypeFloat64:
return "float64"
case PrimitiveTypeBool:
return "bool"
case PrimitiveTypeString:
return "string"
case PrimitiveTypeBytes:
return "bytes"
}
case ft.Array != nil:
return "[]" + prettyPrintFieldType(&ft.Array.ElemType)
case ft.Struct != "":
return ft.Struct
case ft.MultiMap != "":
return ft.MultiMap
case ft.Enum != "":
return ft.Enum
}
return "unknown"
}

type Struct struct {
Name string `json:"name,omitempty"`
OneOf bool `json:"oneof,omitempty"`
Expand Down
129 changes: 129 additions & 0 deletions go/pkg/schema/schema_prettyprint_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package schema

import (
"strings"
"testing"

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

func TestPrettyPrint_SimpleStruct(t *testing.T) {
schema := &Schema{
PackageName: []string{"com", "example", "test"},
Structs: map[string]*Struct{
"Person": {
Name: "Person",
Fields: []*StructField{
{Name: "Name", FieldType: FieldType{Primitive: &PrimitiveType{Type: PrimitiveTypeString}}},
{Name: "Age", FieldType: FieldType{Primitive: &PrimitiveType{Type: PrimitiveTypeUint64}}},
},
},
},
}

expected := `package com.example.test

struct Person {
Name string
Age uint64
}`
actual := strings.TrimSpace(schema.PrettyPrint())
require.Equal(t, expected, actual)
}

func TestPrettyPrint_EnumAndMultimap(t *testing.T) {
schema := &Schema{
PackageName: []string{"com", "example", "test"},
Enums: map[string]*Enum{
"MetricType": {
Name: "MetricType",
Fields: []EnumField{
{Name: "Gauge", Value: 0},
{Name: "Counter", Value: 1},
},
},
},
Multimaps: map[string]*Multimap{
"Labels": {
Name: "Labels",
Key: MultimapField{
Type: FieldType{
Primitive: &PrimitiveType{Type: PrimitiveTypeString}, DictName: "LabelKeys",
},
},
Value: MultimapField{
Type: FieldType{
Primitive: &PrimitiveType{Type: PrimitiveTypeString}, DictName: "LabelValues",
},
},
},
},
}

expected := `package com.example.test

enum MetricType {
Gauge = 0
Counter = 1
}

multimap Labels {
key string dict(LabelKeys)
value string dict(LabelValues)
}`
actual := strings.TrimSpace(schema.PrettyPrint())
require.Equal(t, expected, actual)
}

func TestPrettyPrint_OneofAndArray(t *testing.T) {
schema := &Schema{
PackageName: []string{"example"},
Structs: map[string]*Struct{
"JsonValue": {
Name: "JsonValue",
OneOf: true,
Fields: []*StructField{
{Name: "String", FieldType: FieldType{Primitive: &PrimitiveType{Type: PrimitiveTypeString}}},
{Name: "Number", FieldType: FieldType{Primitive: &PrimitiveType{Type: PrimitiveTypeFloat64}}},
{Name: "Array", FieldType: FieldType{Array: &ArrayType{ElemType: FieldType{Struct: "JsonValue"}}}},
},
},
},
}
expected := `package example

oneof JsonValue {
String string
Number float64
Array []JsonValue
}`
actual := strings.TrimSpace(schema.PrettyPrint())
require.Equal(t, expected, actual)
}

func TestPrettyPrint_OptionalAndDict(t *testing.T) {
schema := &Schema{
PackageName: []string{"example"},
Structs: map[string]*Struct{
"User": {
Name: "User",
Fields: []*StructField{
{Name: "Name", FieldType: FieldType{Primitive: &PrimitiveType{Type: PrimitiveTypeString}}},
{
Name: "Email",
FieldType: FieldType{Primitive: &PrimitiveType{Type: PrimitiveTypeString}, DictName: "Emails"},
Optional: true,
},
},
},
},
}
expected := `package example

struct User {
Name string
Email string dict(Emails) optional
}`
actual := strings.TrimSpace(schema.PrettyPrint())
require.Equal(t, expected, actual)
}
11 changes: 3 additions & 8 deletions java/src/main/java/com/example/oteltef/Attributes.java
Original file line number Diff line number Diff line change
Expand Up @@ -135,21 +135,16 @@ public void append(StringValue k, AnyValue v) {
elems[elemsLen-1] = elem;
}


// setKey sets the key of the element at index i.
public void setKey(int i, StringValue k) {
if (!Types.StringEqual(elems[i].key, k)) {
elems[i].key = k;
modifiedElems.markKeyModified(i);
}
}

// setValue sets the value of the element at index i.
public void setValue(int i, AnyValue v) {
if (!elems[i].value.equals(v)) {
elems[i].value = v;
modifiedElems.markValModified(i);
}
}



// byteSize returns approximate memory usage in bytes. Used to calculate
// memory used by dictionaries.
Expand Down
Loading
Loading