From 78b6815767b0c56a9c360277ba5392b23e9b1ac5 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Mon, 21 Jul 2025 21:01:16 -0700 Subject: [PATCH] Generate marshal JSON without gogo proto jsonpb Signed-off-by: Bogdan Drutu --- .chloggen/gen-marshal-json-stream.yaml | 25 ++++ .../cmd/pdatagen/internal/message_field.go | 14 +++ .../cmd/pdatagen/internal/one_of_field.go | 12 ++ .../pdatagen/internal/one_of_message_value.go | 9 ++ .../internal/one_of_primitive_value.go | 9 ++ .../internal/optional_primitive_field.go | 10 ++ .../cmd/pdatagen/internal/primitive_field.go | 10 ++ .../internal/primitive_slice_field.go | 13 +++ internal/cmd/pdatagen/internal/slice_field.go | 15 +++ .../internal/templates/message.go.tmpl | 15 ++- .../templates/message_internal.go.tmpl | 19 ++- .../internal/templates/message_test.go.tmpl | 28 ++++- .../templates/primitive_slice.go.tmpl | 6 +- .../primitive_slice_internal.go.tmpl | 27 ++++- .../templates/primitive_slice_test.go.tmpl | 6 +- .../pdatagen/internal/templates/slice.go.tmpl | 19 ++- .../internal/templates/slice_internal.go.tmpl | 20 +++- .../internal/templates/slice_test.go.tmpl | 6 +- internal/cmd/pdatagen/internal/typed_field.go | 18 +++ .../internal/xpdata_entity_package.go | 3 +- pdata/internal/data/profileid.go | 12 ++ pdata/internal/data/spanid.go | 12 ++ pdata/internal/data/traceid.go | 12 ++ pdata/internal/generated_wrapper_byteslice.go | 11 ++ pdata/internal/generated_wrapper_entityref.go | 23 ++++ .../generated_wrapper_entityrefslice.go | 14 +++ .../generated_wrapper_float64slice.go | 17 +++ .../generated_wrapper_instrumentationscope.go | 23 ++++ .../internal/generated_wrapper_int32slice.go | 17 +++ .../internal/generated_wrapper_int64slice.go | 17 +++ pdata/internal/generated_wrapper_intslice.go | 34 ------ pdata/internal/generated_wrapper_resource.go | 19 +++ .../internal/generated_wrapper_stringslice.go | 17 +++ .../internal/generated_wrapper_uint64slice.go | 17 +++ pdata/internal/json/iterator.go | 15 +++ pdata/internal/json/stream.go | 74 ++++++++++++ pdata/internal/json/stream_test.go | 87 ++++++++++++++ pdata/internal/wrapper_map.go | 25 ++++ pdata/internal/wrapper_map_test.go | 5 +- pdata/internal/wrapper_slice.go | 14 +++ pdata/internal/wrapper_tracestate.go | 9 ++ pdata/internal/wrapper_value.go | 42 +++++++ .../generated_instrumentationscope_test.go | 15 +++ pdata/pcommon/generated_intslice.go | 108 ------------------ pdata/pcommon/generated_intslice_test.go | 83 -------------- pdata/pcommon/generated_resource_test.go | 15 +++ pdata/plog/generated_logrecord.go | 49 ++++++++ pdata/plog/generated_logrecord_test.go | 15 +++ pdata/plog/generated_logrecordslice.go | 14 +++ pdata/plog/generated_resourcelogs.go | 17 +++ pdata/plog/generated_resourcelogs_test.go | 15 +++ pdata/plog/generated_resourcelogsslice.go | 14 +++ pdata/plog/generated_scopelogs.go | 17 +++ pdata/plog/generated_scopelogs_test.go | 15 +++ pdata/plog/generated_scopelogsslice.go | 14 +++ pdata/plog/json.go | 25 +--- pdata/plog/logs.go | 25 ++++ pdata/plog/logs_test.go | 14 +++ .../generated_exportpartialsuccess.go | 15 +++ .../generated_exportpartialsuccess_test.go | 15 +++ pdata/plog/severity_number.go | 6 + pdata/pmetric/aggregation_temporality.go | 6 + pdata/pmetric/generated_exemplar.go | 31 +++++ pdata/pmetric/generated_exemplar_test.go | 15 +++ pdata/pmetric/generated_exemplarslice.go | 14 +++ .../pmetric/generated_exponentialhistogram.go | 15 +++ .../generated_exponentialhistogram_test.go | 15 +++ ...generated_exponentialhistogramdatapoint.go | 59 ++++++++++ ...ated_exponentialhistogramdatapoint_test.go | 15 +++ ...ed_exponentialhistogramdatapointbuckets.go | 13 +++ ...ponentialhistogramdatapointbuckets_test.go | 15 +++ ...ated_exponentialhistogramdatapointslice.go | 14 +++ pdata/pmetric/generated_gauge.go | 11 ++ pdata/pmetric/generated_gauge_test.go | 15 +++ pdata/pmetric/generated_histogram.go | 15 +++ pdata/pmetric/generated_histogram_test.go | 15 +++ pdata/pmetric/generated_histogramdatapoint.go | 47 ++++++++ .../generated_histogramdatapoint_test.go | 15 +++ .../generated_histogramdatapointslice.go | 14 +++ pdata/pmetric/generated_metric.go | 40 +++++++ pdata/pmetric/generated_metric_test.go | 15 +++ pdata/pmetric/generated_metricslice.go | 14 +++ pdata/pmetric/generated_numberdatapoint.go | 35 ++++++ .../pmetric/generated_numberdatapoint_test.go | 15 +++ .../pmetric/generated_numberdatapointslice.go | 14 +++ pdata/pmetric/generated_resourcemetrics.go | 17 +++ .../pmetric/generated_resourcemetrics_test.go | 15 +++ .../pmetric/generated_resourcemetricsslice.go | 14 +++ pdata/pmetric/generated_scopemetrics.go | 17 +++ pdata/pmetric/generated_scopemetrics_test.go | 15 +++ pdata/pmetric/generated_scopemetricsslice.go | 14 +++ pdata/pmetric/generated_sum.go | 19 +++ pdata/pmetric/generated_sum_test.go | 15 +++ pdata/pmetric/generated_summary.go | 11 ++ pdata/pmetric/generated_summary_test.go | 15 +++ pdata/pmetric/generated_summarydatapoint.go | 35 ++++++ .../generated_summarydatapoint_test.go | 15 +++ .../generated_summarydatapointslice.go | 14 +++ ...nerated_summarydatapointvalueatquantile.go | 15 +++ ...ed_summarydatapointvalueatquantile_test.go | 15 +++ ...ed_summarydatapointvalueatquantileslice.go | 14 +++ pdata/pmetric/json.go | 27 ++--- pdata/pmetric/json_test.go | 4 +- pdata/pmetric/metrics.go | 25 ++++ pdata/pmetric/metrics_test.go | 14 +++ .../generated_exportpartialsuccess.go | 15 +++ .../generated_exportpartialsuccess_test.go | 15 +++ pdata/pprofile/aggregation_temporality.go | 6 + pdata/pprofile/generated_attribute.go | 13 +++ pdata/pprofile/generated_attribute_test.go | 15 +++ .../pprofile/generated_attributetableslice.go | 14 +++ pdata/pprofile/generated_attributeunit.go | 15 +++ .../pprofile/generated_attributeunit_test.go | 15 +++ .../pprofile/generated_attributeunitslice.go | 14 +++ pdata/pprofile/generated_function.go | 23 ++++ pdata/pprofile/generated_function_test.go | 15 +++ pdata/pprofile/generated_functionslice.go | 14 +++ pdata/pprofile/generated_line.go | 19 +++ pdata/pprofile/generated_line_test.go | 15 +++ pdata/pprofile/generated_lineslice.go | 14 +++ pdata/pprofile/generated_link.go | 15 +++ pdata/pprofile/generated_link_test.go | 15 +++ pdata/pprofile/generated_linkslice.go | 14 +++ pdata/pprofile/generated_location.go | 27 +++++ pdata/pprofile/generated_location_test.go | 15 +++ pdata/pprofile/generated_locationslice.go | 14 +++ pdata/pprofile/generated_mapping.go | 43 +++++++ pdata/pprofile/generated_mapping_test.go | 15 +++ pdata/pprofile/generated_mappingslice.go | 14 +++ pdata/pprofile/generated_profile.go | 61 ++++++++++ pdata/pprofile/generated_profile_test.go | 15 +++ .../pprofile/generated_profilesdictionary.go | 35 ++++++ .../generated_profilesdictionary_test.go | 15 +++ pdata/pprofile/generated_profilesslice.go | 14 +++ pdata/pprofile/generated_resourceprofiles.go | 17 +++ .../generated_resourceprofiles_test.go | 15 +++ .../generated_resourceprofilesslice.go | 14 +++ pdata/pprofile/generated_sample.go | 31 +++++ pdata/pprofile/generated_sample_test.go | 15 +++ pdata/pprofile/generated_sampleslice.go | 14 +++ pdata/pprofile/generated_scopeprofiles.go | 17 +++ .../pprofile/generated_scopeprofiles_test.go | 15 +++ .../pprofile/generated_scopeprofilesslice.go | 14 +++ pdata/pprofile/generated_valuetype.go | 19 +++ pdata/pprofile/generated_valuetype_test.go | 15 +++ pdata/pprofile/generated_valuetypeslice.go | 14 +++ pdata/pprofile/json.go | 45 ++++---- .../generated_exportpartialsuccess.go | 15 +++ .../generated_exportpartialsuccess_test.go | 15 +++ pdata/pprofile/profileid.go | 5 + pdata/pprofile/profiles.go | 30 +++++ pdata/pprofile/profiles_test.go | 15 +++ pdata/ptrace/generated_resourcespans.go | 17 +++ pdata/ptrace/generated_resourcespans_test.go | 15 +++ pdata/ptrace/generated_resourcespansslice.go | 14 +++ pdata/ptrace/generated_scopespans.go | 17 +++ pdata/ptrace/generated_scopespans_test.go | 15 +++ pdata/ptrace/generated_scopespansslice.go | 14 +++ pdata/ptrace/generated_span.go | 69 +++++++++++ pdata/ptrace/generated_span_test.go | 15 +++ pdata/ptrace/generated_spanevent.go | 23 ++++ pdata/ptrace/generated_spanevent_test.go | 15 +++ pdata/ptrace/generated_spaneventslice.go | 14 +++ pdata/ptrace/generated_spanlink.go | 31 +++++ pdata/ptrace/generated_spanlink_test.go | 15 +++ pdata/ptrace/generated_spanlinkslice.go | 14 +++ pdata/ptrace/generated_spanslice.go | 14 +++ pdata/ptrace/generated_status.go | 15 +++ pdata/ptrace/generated_status_test.go | 15 +++ pdata/ptrace/json.go | 25 +--- pdata/ptrace/json_test.go | 2 +- .../generated_exportpartialsuccess.go | 15 +++ .../generated_exportpartialsuccess_test.go | 15 +++ pdata/ptrace/span_kind.go | 5 + pdata/ptrace/status_code.go | 5 + pdata/ptrace/traces.go | 25 ++++ pdata/ptrace/traces_test.go | 14 +++ .../xpdata/entity/generated_entityref_test.go | 15 +++ 178 files changed, 3062 insertions(+), 348 deletions(-) create mode 100644 .chloggen/gen-marshal-json-stream.yaml delete mode 100644 pdata/internal/generated_wrapper_intslice.go create mode 100644 pdata/internal/json/iterator.go create mode 100644 pdata/internal/json/stream.go create mode 100644 pdata/internal/json/stream_test.go delete mode 100644 pdata/pcommon/generated_intslice.go delete mode 100644 pdata/pcommon/generated_intslice_test.go diff --git a/.chloggen/gen-marshal-json-stream.yaml b/.chloggen/gen-marshal-json-stream.yaml new file mode 100644 index 00000000000..eacf39d95f9 --- /dev/null +++ b/.chloggen/gen-marshal-json-stream.yaml @@ -0,0 +1,25 @@ +# 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. otlpreceiver) +component: pdata + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Use pdatagen to generate marshalJSON without using gogo proto jsonpb. + +# One or more tracking issues or pull requests related to the change +issues: [13450] + +# (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: + +# 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: [user] diff --git a/internal/cmd/pdatagen/internal/message_field.go b/internal/cmd/pdatagen/internal/message_field.go index a16cca54f98..c1d9103573d 100644 --- a/internal/cmd/pdatagen/internal/message_field.go +++ b/internal/cmd/pdatagen/internal/message_field.go @@ -39,6 +39,15 @@ const messageSetTestTemplate = `{{ if .isCommon -}} const messageCopyOrigTemplate = `{{ if .isCommon }}{{ if not .isBaseStructCommon }}internal.{{ end }}CopyOrig{{ else }}copyOrig{{ end }} {{- .returnType }}(&dest.{{ .originFieldName }}, &src.{{ .originFieldName }})` +const messageMarshalJSONTemplate = `{{- if eq .returnType "TraceState" }} if ms.orig.{{ .originFieldName }} != "" { {{ end -}} + dest.WriteObjectField("{{ lowerFirst .originFieldName }}") + {{- if .isCommon }} + {{ if not .isBaseStructCommon }}internal.{{ end }}MarshalJSONStream{{ .returnType }}( + {{- if not .isBaseStructCommon }}internal.{{ end }}New{{ .returnType }}(&ms.orig.{{ .originFieldName }}, ms.state), dest) + {{- else }} + ms.{{ .fieldName }}().marshalJSONStream(dest) + {{- end }}{{ if eq .returnType "TraceState" -}} } {{- end }}` + type MessageField struct { fieldName string returnMessage *messageStruct @@ -64,6 +73,11 @@ func (mf *MessageField) GenerateCopyOrig(ms *messageStruct) string { return executeTemplate(t, mf.templateFields(ms)) } +func (mf *MessageField) GenerateMarshalJSON(ms *messageStruct) string { + t := template.Must(templateNew("messageMarshalJSONTemplate").Parse(messageMarshalJSONTemplate)) + return executeTemplate(t, mf.templateFields(ms)) +} + func (mf *MessageField) templateFields(ms *messageStruct) map[string]any { return map[string]any{ "isCommon": usedByOtherDataTypes(mf.returnMessage.packageName), diff --git a/internal/cmd/pdatagen/internal/one_of_field.go b/internal/cmd/pdatagen/internal/one_of_field.go index 764fe6181df..11269f75424 100644 --- a/internal/cmd/pdatagen/internal/one_of_field.go +++ b/internal/cmd/pdatagen/internal/one_of_field.go @@ -39,6 +39,12 @@ const oneOfCopyOrigTemplate = `switch t := src.{{ .originFieldName }}.(type) { {{- end }} }` +const oneOfMarshalJSONTemplate = `switch ov := ms.{{ .origAccessor }}.{{ .originFieldName }}.(type) { + {{- range .values }} + {{ .GenerateMarshalJSON $.baseStruct $.OneOfField }} + {{- end }} + }` + type OneOfField struct { originFieldName string typeName string @@ -74,6 +80,11 @@ func (of *OneOfField) GenerateCopyOrig(ms *messageStruct) string { return executeTemplate(t, of.templateFields(ms)) } +func (of *OneOfField) GenerateMarshalJSON(ms *messageStruct) string { + t := template.Must(templateNew("oneOfMarshalJSONTemplate").Parse(oneOfMarshalJSONTemplate)) + return executeTemplate(t, of.templateFields(ms)) +} + func (of *OneOfField) templateFields(ms *messageStruct) map[string]any { return map[string]any{ "baseStruct": ms, @@ -99,4 +110,5 @@ type oneOfValue interface { GenerateSetWithTestValue(ms *messageStruct, of *OneOfField) string GenerateCopyOrig(ms *messageStruct, of *OneOfField) string GenerateType(ms *messageStruct, of *OneOfField) string + GenerateMarshalJSON(ms *messageStruct, of *OneOfField) string } diff --git a/internal/cmd/pdatagen/internal/one_of_message_value.go b/internal/cmd/pdatagen/internal/one_of_message_value.go index 622354c6e09..331642c6624 100644 --- a/internal/cmd/pdatagen/internal/one_of_message_value.go +++ b/internal/cmd/pdatagen/internal/one_of_message_value.go @@ -68,6 +68,10 @@ const oneOfMessageCopyOrigTemplate = ` case *{{ .originStructType }}: const oneOfMessageTypeTemplate = `case *{{ .originStructName }}_{{ .originFieldName }}: return {{ .typeName }}` +const oneOfMessageMarshalJSONTemplate = `case *{{ .originStructName }}_{{ .originFieldName }}: + dest.WriteObjectField("{{ lowerFirst .originFieldName }}") + new{{ .returnType }}(ov.{{ .fieldName }}, ms.state).marshalJSONStream(dest)` + type OneOfMessageValue struct { fieldName string originFieldPackageName string @@ -99,6 +103,11 @@ func (omv *OneOfMessageValue) GenerateType(ms *messageStruct, of *OneOfField) st return executeTemplate(t, omv.templateFields(ms, of)) } +func (omv *OneOfMessageValue) GenerateMarshalJSON(ms *messageStruct, of *OneOfField) string { + t := template.Must(templateNew("oneOfMessageMarshalJSONTemplate").Parse(oneOfMessageMarshalJSONTemplate)) + return executeTemplate(t, omv.templateFields(ms, of)) +} + func (omv *OneOfMessageValue) templateFields(ms *messageStruct, of *OneOfField) map[string]any { return map[string]any{ "fieldName": omv.fieldName, diff --git a/internal/cmd/pdatagen/internal/one_of_primitive_value.go b/internal/cmd/pdatagen/internal/one_of_primitive_value.go index ca4442399b6..0798088a263 100644 --- a/internal/cmd/pdatagen/internal/one_of_primitive_value.go +++ b/internal/cmd/pdatagen/internal/one_of_primitive_value.go @@ -54,6 +54,10 @@ const oneOfPrimitiveCopyOrigTemplate = `case *{{ .originStructName }}_{{ .origin const oneOfPrimitiveTypeTemplate = `case *{{ .originStructName }}_{{ .originFieldName }}: return {{ .typeName }}` +const oneOfPrimitiveMarshalJSONTemplate = `case *{{ .originStructName }}_{{ .originFieldName }}: + dest.WriteObjectField("{{ lowerFirst .originFieldName }}") + dest.Write{{ upperFirst .returnType }}(ov.{{ .originFieldName }})` + type OneOfPrimitiveValue struct { fieldName string defaultVal string @@ -87,6 +91,11 @@ func (opv *OneOfPrimitiveValue) GenerateType(ms *messageStruct, of *OneOfField) return executeTemplate(t, opv.templateFields(ms, of)) } +func (opv *OneOfPrimitiveValue) GenerateMarshalJSON(ms *messageStruct, of *OneOfField) string { + t := template.Must(templateNew("oneOfPrimitiveMarshalJSONTemplate").Parse(oneOfPrimitiveMarshalJSONTemplate)) + return executeTemplate(t, opv.templateFields(ms, of)) +} + func (opv *OneOfPrimitiveValue) templateFields(ms *messageStruct, of *OneOfField) map[string]any { return map[string]any{ "structName": ms.getName(), diff --git a/internal/cmd/pdatagen/internal/optional_primitive_field.go b/internal/cmd/pdatagen/internal/optional_primitive_field.go index f66fc160927..d4969934e1b 100644 --- a/internal/cmd/pdatagen/internal/optional_primitive_field.go +++ b/internal/cmd/pdatagen/internal/optional_primitive_field.go @@ -67,6 +67,11 @@ const optionalPrimitiveCopyOrigTemplate = `if src{{ .fieldName }}, ok := src.{{ dest.{{ .fieldName }}_ = nil }` +const optionalPrimitiveMarshalJSONTemplate = `if ms.Has{{ .fieldName }}() { + dest.WriteObjectField("{{ lowerFirst .fieldName }}") + dest.Write{{ upperFirst .returnType }}(ms.{{ .fieldName }}()) + }` + type OptionalPrimitiveField struct { fieldName string defaultVal string @@ -94,6 +99,11 @@ func (opv *OptionalPrimitiveField) GenerateCopyOrig(ms *messageStruct) string { return executeTemplate(t, opv.templateFields(ms)) } +func (opv *OptionalPrimitiveField) GenerateMarshalJSON(ms *messageStruct) string { + t := template.Must(templateNew("optionalPrimitiveMarshalJSONTemplate").Parse(optionalPrimitiveMarshalJSONTemplate)) + return executeTemplate(t, opv.templateFields(ms)) +} + func (opv *OptionalPrimitiveField) templateFields(ms *messageStruct) map[string]any { return map[string]any{ "structName": ms.getName(), diff --git a/internal/cmd/pdatagen/internal/primitive_field.go b/internal/cmd/pdatagen/internal/primitive_field.go index de8a84ca0ce..df7a4605c11 100644 --- a/internal/cmd/pdatagen/internal/primitive_field.go +++ b/internal/cmd/pdatagen/internal/primitive_field.go @@ -48,6 +48,11 @@ const primitiveSetTestTemplate = `tv.orig.{{ .originFieldName }} = {{ .testValue const primitiveCopyOrigTemplate = `dest.{{ .originFieldName }} = src.{{ .originFieldName }}` +const primitiveMarshalJSONTemplate = `if ms.orig.{{ .originFieldName }} != {{ .defaultVal }} { + dest.WriteObjectField("{{ lowerFirst .originFieldName }}") + dest.Write{{ upperFirst .returnType }}(ms.orig.{{ .originFieldName }}) + }` + type PrimitiveField struct { fieldName string originFieldName string @@ -76,6 +81,11 @@ func (pf *PrimitiveField) GenerateCopyOrig(ms *messageStruct) string { return executeTemplate(t, pf.templateFields(ms)) } +func (pf *PrimitiveField) GenerateMarshalJSON(ms *messageStruct) string { + t := template.Must(templateNew("primitiveMarshalJSONTemplate").Parse(primitiveMarshalJSONTemplate)) + return executeTemplate(t, pf.templateFields(ms)) +} + func (pf *PrimitiveField) templateFields(ms *messageStruct) map[string]any { return map[string]any{ "structName": ms.getName(), diff --git a/internal/cmd/pdatagen/internal/primitive_slice_field.go b/internal/cmd/pdatagen/internal/primitive_slice_field.go index 5578aec4323..6c67f695c12 100644 --- a/internal/cmd/pdatagen/internal/primitive_slice_field.go +++ b/internal/cmd/pdatagen/internal/primitive_slice_field.go @@ -26,6 +26,14 @@ const primitiveSliceCopyOrigTemplate = `dest.{{ .originFieldName }} = {{- if .isCommon }}{{ if not .isBaseStructCommon }}internal.{{ end }}CopyOrig{{ else }}copyOrig{{ end }} {{- .returnType }}(dest.{{ .originFieldName }}, src.{{ .originFieldName }})` +const primitiveSliceMarshalJSONTemplate = `dest.WriteObjectField("{{ lowerFirst .originFieldName }}") + {{- if .isCommon }} + {{ if not .isBaseStructCommon }}internal.{{ end }}MarshalJSONStream{{ .returnType }}( + {{- if not .isBaseStructCommon }}internal.{{ end }}New{{ .returnType }}(&ms.orig.{{ .originFieldName }}, ms.state), dest) + {{- else }} + ms.{{ .fieldName }}().marshalJSONStream(dest) + {{- end }}` + // PrimitiveSliceField is used to generate fields for slice of primitive types type PrimitiveSliceField struct { fieldName string @@ -56,6 +64,11 @@ func (psf *PrimitiveSliceField) GenerateCopyOrig(ms *messageStruct) string { return executeTemplate(t, psf.templateFields(ms)) } +func (psf *PrimitiveSliceField) GenerateMarshalJSON(ms *messageStruct) string { + t := template.Must(templateNew("primitiveSliceMarshalJSONTemplate").Parse(primitiveSliceMarshalJSONTemplate)) + return executeTemplate(t, psf.templateFields(ms)) +} + func (psf *PrimitiveSliceField) templateFields(ms *messageStruct) map[string]any { return map[string]any{ "structName": ms.getName(), diff --git a/internal/cmd/pdatagen/internal/slice_field.go b/internal/cmd/pdatagen/internal/slice_field.go index 05f696a9b31..06f67580f76 100644 --- a/internal/cmd/pdatagen/internal/slice_field.go +++ b/internal/cmd/pdatagen/internal/slice_field.go @@ -46,6 +46,16 @@ const sliceCopyOrigTemplate = `dest.{{ .originFieldName }} = {{- if .isCommon }}{{ if not .isBaseStructCommon }}internal.{{ end }}CopyOrig{{ else }}copyOrig{{ end }} {{- .returnType }}(dest.{{ .originFieldName }}, src.{{ .originFieldName }})` +const sliceMarshalJSONTemplate = `if len(ms.orig.{{ .originFieldName }}) > 0 { + dest.WriteObjectField("{{ lowerFirst .originFieldName }}") + {{- if .isCommon }} + {{ if not .isBaseStructCommon }}internal.{{ end }}MarshalJSONStream{{ .returnType }}( + {{- if not .isBaseStructCommon }}internal.{{ end }}New{{ .returnType }}(&ms.orig.{{ .originFieldName }}, ms.state), dest) + {{- else }} + ms.{{ .fieldName }}().marshalJSONStream(dest) + {{- end }} + }` + type SliceField struct { fieldName string originFieldName string @@ -79,6 +89,11 @@ func (sf *SliceField) GenerateCopyOrig(ms *messageStruct) string { return executeTemplate(t, sf.templateFields(ms)) } +func (sf *SliceField) GenerateMarshalJSON(ms *messageStruct) string { + t := template.Must(templateNew("sliceMarshalJSONTemplate").Parse(sliceMarshalJSONTemplate)) + return executeTemplate(t, sf.templateFields(ms)) +} + func (sf *SliceField) templateFields(ms *messageStruct) map[string]any { return map[string]any{ "structName": ms.getName(), diff --git a/internal/cmd/pdatagen/internal/templates/message.go.tmpl b/internal/cmd/pdatagen/internal/templates/message.go.tmpl index 7d5e6118494..f3dffe99e01 100644 --- a/internal/cmd/pdatagen/internal/templates/message.go.tmpl +++ b/internal/cmd/pdatagen/internal/templates/message.go.tmpl @@ -7,9 +7,9 @@ package {{ .packageName }} import ( -{{ range $index, $element := .imports -}} -{{ $element }} -{{ end }} + {{ range $index, $element := .imports -}} + {{ $element }} + {{ end }} ) {{ .description }} @@ -81,6 +81,15 @@ func (ms {{ .structName }}) getState() *internal.State { return internal.Get{{ .structName }}State(internal.{{ .structName }}(ms)) } {{- else }} +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms {{ .structName }}) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + {{ range .fields -}} + {{ .GenerateMarshalJSON $.messageStruct }} + {{ end -}} + dest.WriteObjectEnd() +} + func copyOrig{{ .structName }}(dest, src *{{ .originName }}) { {{- range .fields }} {{ .GenerateCopyOrig $.messageStruct }} diff --git a/internal/cmd/pdatagen/internal/templates/message_internal.go.tmpl b/internal/cmd/pdatagen/internal/templates/message_internal.go.tmpl index 9551f166874..4bbb97b285c 100644 --- a/internal/cmd/pdatagen/internal/templates/message_internal.go.tmpl +++ b/internal/cmd/pdatagen/internal/templates/message_internal.go.tmpl @@ -7,11 +7,11 @@ package internal import ( -{{ range $index, $element := .imports -}} -{{ if ne $element "go.opentelemetry.io/collector/pdata/internal" }} -{{ $element }} -{{ end }} -{{ end }} + {{ range $index, $element := .imports -}} + {{ if ne $element "go.opentelemetry.io/collector/pdata/internal" }} + {{ $element }} + {{- end }} + {{- end }} ) type {{ .structName }} struct { @@ -50,3 +50,12 @@ func FillTest{{ .structName }}(tv {{ .structName }}) { {{ .GenerateSetWithTestValue $.messageStruct }} {{- end }} } + +// MarshalJSONStream marshals all properties from the current struct to the destination stream. +func MarshalJSONStream{{ .structName }}(ms {{ .structName }}, dest *json.Stream) { + dest.WriteObjectStart() + {{ range .fields -}} + {{ .GenerateMarshalJSON $.messageStruct }} + {{ end -}} + dest.WriteObjectEnd() +} diff --git a/internal/cmd/pdatagen/internal/templates/message_test.go.tmpl b/internal/cmd/pdatagen/internal/templates/message_test.go.tmpl index 3fec634bda4..331901dbb1c 100644 --- a/internal/cmd/pdatagen/internal/templates/message_test.go.tmpl +++ b/internal/cmd/pdatagen/internal/templates/message_test.go.tmpl @@ -7,9 +7,9 @@ package {{ .packageName }} import ( -{{ range $index, $element := .testImports -}} -{{ $element }} -{{ end }} + {{ range $index, $element := .testImports -}} + {{ $element }} + {{ end }} ) func Test{{ .structName }}_MoveTo(t *testing.T) { @@ -37,6 +37,28 @@ func Test{{ .structName }}_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(new{{ .structName }}(&{{ .originName }}{}, &sharedState)) }) } +func Test{{ .structName }}_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTest{{ .structName }}() + {{- if .isCommon }} + internal.MarshalJSONStream{{ .structName }}(internal.{{ .structName }}(src), stream) + {{- else }} + src.marshalJSONStream(stream) + {{- end }} + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := New{{ .structName }}() + {{- if .isCommon }} + internal.UnmarshalJSONIter{{ .structName }}(internal.{{ .structName }}(dest), iter) + {{- else }} + dest.unmarshalJsoniter(iter) + {{- end }} + + assert.Equal(t, src, dest) +} + {{ range .fields }} {{ .GenerateAccessorsTest $.messageStruct }} {{ end }} diff --git a/internal/cmd/pdatagen/internal/templates/primitive_slice.go.tmpl b/internal/cmd/pdatagen/internal/templates/primitive_slice.go.tmpl index 8376e79d02b..5bc4fa3f936 100644 --- a/internal/cmd/pdatagen/internal/templates/primitive_slice.go.tmpl +++ b/internal/cmd/pdatagen/internal/templates/primitive_slice.go.tmpl @@ -7,9 +7,9 @@ package {{ .packageName }} import ( -{{ range $index, $element := .imports -}} -{{ $element }} -{{ end }} + {{ range $index, $element := .imports -}} + {{ $element }} + {{ end }} ) // {{ .structName }} represents a []{{ .itemType }} slice. diff --git a/internal/cmd/pdatagen/internal/templates/primitive_slice_internal.go.tmpl b/internal/cmd/pdatagen/internal/templates/primitive_slice_internal.go.tmpl index 893dff5dbb7..e2d67b41fc5 100644 --- a/internal/cmd/pdatagen/internal/templates/primitive_slice_internal.go.tmpl +++ b/internal/cmd/pdatagen/internal/templates/primitive_slice_internal.go.tmpl @@ -7,11 +7,11 @@ package internal import ( -{{ range $index, $element := .imports -}} -{{ if ne $element "go.opentelemetry.io/collector/pdata/internal" }} -{{ $element }} -{{ end }} -{{ end }} + {{ range $index, $element := .imports -}} + {{ if ne $element "go.opentelemetry.io/collector/pdata/internal" }} + {{ $element }} + {{- end }} + {{- end }} ) type {{ .structName }} struct { @@ -47,3 +47,20 @@ func GenerateTest{{ .structName }}() {{ .structName }} { FillTest{{ .structName }}(ms) return ms } + +// MarshalJSONStream marshals all properties from the current struct to the destination stream. +func MarshalJSONStream{{ .structName }}(ms {{ .structName }}, dest *json.Stream) { + {{- if eq .itemType "byte" }} + dest.WriteString(base64.StdEncoding.EncodeToString(*ms.orig)) + {{- else }} + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + dest.Write{{ upperFirst .itemType }}((*ms.orig)[0]) + } + for i := 1; i < len((*ms.orig)); i++ { + dest.WriteMore() + dest.Write{{ upperFirst .itemType }}((*ms.orig)[i]) + } + dest.WriteArrayEnd() + {{- end }} +} diff --git a/internal/cmd/pdatagen/internal/templates/primitive_slice_test.go.tmpl b/internal/cmd/pdatagen/internal/templates/primitive_slice_test.go.tmpl index 389b1484303..9c555df7038 100644 --- a/internal/cmd/pdatagen/internal/templates/primitive_slice_test.go.tmpl +++ b/internal/cmd/pdatagen/internal/templates/primitive_slice_test.go.tmpl @@ -7,9 +7,9 @@ package {{ .packageName }} import ( -{{ range $index, $element := .testImports -}} -{{ $element }} -{{ end }} + {{ range $index, $element := .testImports -}} + {{ $element }} + {{ end }} ) func TestNew{{ .structName }}(t *testing.T) { diff --git a/internal/cmd/pdatagen/internal/templates/slice.go.tmpl b/internal/cmd/pdatagen/internal/templates/slice.go.tmpl index 9c6a02a9f91..674cb252d45 100644 --- a/internal/cmd/pdatagen/internal/templates/slice.go.tmpl +++ b/internal/cmd/pdatagen/internal/templates/slice.go.tmpl @@ -7,9 +7,9 @@ package {{ .packageName }} import ( -{{ range $index, $element := .imports -}} -{{ $element }} -{{ end }} + {{ range $index, $element := .imports -}} + {{ $element }} + {{ end }} ) // {{ .structName }} logically represents a slice of {{ .elementName }}. @@ -176,6 +176,19 @@ func (ms {{ .structName }}) getState() *internal.State { return internal.Get{{ .structName }}State(internal.{{ .structName }}(ms)) } {{- else }} +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms {{ .structName }}) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrig{{ .structName }}(dest, src []{{ .originElementType }}) []{{ .originElementType }} { if cap(dest) < len(src) { dest = make([]{{ .originElementType }}, len(src)) diff --git a/internal/cmd/pdatagen/internal/templates/slice_internal.go.tmpl b/internal/cmd/pdatagen/internal/templates/slice_internal.go.tmpl index 335b192a65d..6e61e630558 100644 --- a/internal/cmd/pdatagen/internal/templates/slice_internal.go.tmpl +++ b/internal/cmd/pdatagen/internal/templates/slice_internal.go.tmpl @@ -8,13 +8,12 @@ package internal import ( {{ range $index, $element := .imports -}} - {{ if ne $element `"go.opentelemetry.io/collector/pdata/internal"` }} + {{ if ne $element "go.opentelemetry.io/collector/pdata/internal" }} {{ $element }} - {{ end }} - {{ end }} + {{- end }} + {{- end }} ) - type {{ .structName }} struct { orig *[]{{ .originElementType }} state *State @@ -64,3 +63,16 @@ func FillTest{{ .structName }}(es {{ .structName }}) { FillTest{{ .elementName }}(New{{ .elementName }}((*es.orig)[i], es.state)) } } + +// MarshalJSONStream marshals all properties from the current struct to the destination stream. +func MarshalJSONStream{{ .structName }}(ms {{ .structName }}, dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + MarshalJSONStream{{ .elementName }}(New{{ .elementName }}((*ms.orig)[0], ms.state), dest) + } + for i := 1; i < len((*ms.orig)); i++ { + dest.WriteMore() + MarshalJSONStream{{ .elementName }}(New{{ .elementName }}((*ms.orig)[i], ms.state), dest) + } + dest.WriteArrayEnd() +} diff --git a/internal/cmd/pdatagen/internal/templates/slice_test.go.tmpl b/internal/cmd/pdatagen/internal/templates/slice_test.go.tmpl index 9de553de706..d2af75e9d22 100644 --- a/internal/cmd/pdatagen/internal/templates/slice_test.go.tmpl +++ b/internal/cmd/pdatagen/internal/templates/slice_test.go.tmpl @@ -7,9 +7,9 @@ package {{ .packageName }} import ( -{{ range $index, $element := .testImports -}} -{{ $element }} -{{ end }} + {{ range $index, $element := .testImports -}} + {{ $element }} + {{ end }} ) func Test{{ .structName }}(t *testing.T) { diff --git a/internal/cmd/pdatagen/internal/typed_field.go b/internal/cmd/pdatagen/internal/typed_field.go index f4be66163b5..7f29c58b656 100644 --- a/internal/cmd/pdatagen/internal/typed_field.go +++ b/internal/cmd/pdatagen/internal/typed_field.go @@ -31,6 +31,19 @@ const typedSetTestTemplate = `tv.orig.{{ .originFieldName }} = {{ .testValue }}` const typedCopyOrigTemplate = `dest.{{ .originFieldName }} = src.{{ .originFieldName }}` +const typedMarshalJSONTemplate = `if ms.orig.{{ .originFieldName }} != {{ .defaultVal }} { + dest.WriteObjectField("{{ lowerFirst .originFieldName }}") + {{- if .isType }} + {{- if .isCommon }} + ms.orig.{{ .originFieldName }}.MarshalJSONStream(dest) + {{- else }} + ms.{{ .fieldName }}().marshalJSONStream(dest) + {{- end }} + {{- else }} + dest.Write{{ upperFirst .rawType }}(ms.orig.{{ .originFieldName }}) + {{- end }} + }` + // TypedField is a field that has defined a custom type (e.g. "type Timestamp uint64") type TypedField struct { fieldName string @@ -67,6 +80,11 @@ func (ptf *TypedField) GenerateCopyOrig(ms *messageStruct) string { return executeTemplate(t, ptf.templateFields(ms)) } +func (ptf *TypedField) GenerateMarshalJSON(ms *messageStruct) string { + t := template.Must(templateNew("typedMarshalJSONTemplate").Parse(typedMarshalJSONTemplate)) + return executeTemplate(t, ptf.templateFields(ms)) +} + func (ptf *TypedField) templateFields(ms *messageStruct) map[string]any { return map[string]any{ "structName": ms.getName(), diff --git a/internal/cmd/pdatagen/internal/xpdata_entity_package.go b/internal/cmd/pdatagen/internal/xpdata_entity_package.go index a2113349f0a..9ead79ea919 100644 --- a/internal/cmd/pdatagen/internal/xpdata_entity_package.go +++ b/internal/cmd/pdatagen/internal/xpdata_entity_package.go @@ -11,10 +11,9 @@ var xpdataEntity = &Package{ path: filepath.Join("xpdata", "entity"), imports: []string{ `"go.opentelemetry.io/collector/pdata/internal"`, + `otlpcommon "go.opentelemetry.io/collector/pdata/internal/data/protogen/common/v1"`, `"go.opentelemetry.io/collector/pdata/internal/json"`, `"go.opentelemetry.io/collector/pdata/pcommon"`, - `otlpcommon "go.opentelemetry.io/collector/pdata/internal/data/protogen/common/v1"`, - `otlpresource "go.opentelemetry.io/collector/pdata/internal/data/protogen/resource/v1"`, }, testImports: []string{ `"testing"`, diff --git a/pdata/internal/data/profileid.go b/pdata/internal/data/profileid.go index 5b4e6f53ceb..6bdc681f70a 100644 --- a/pdata/internal/data/profileid.go +++ b/pdata/internal/data/profileid.go @@ -4,9 +4,12 @@ package data // import "go.opentelemetry.io/collector/pdata/internal/data" import ( + "encoding/hex" "errors" "github.com/gogo/protobuf/proto" + + "go.opentelemetry.io/collector/pdata/internal/json" ) const profileIDSize = 16 @@ -71,6 +74,15 @@ func (tid ProfileID) MarshalJSON() ([]byte, error) { return marshalJSON(tid[:]) } +// MarshalJSONStream converts trace id into a hex string enclosed in quotes. +func (tid ProfileID) MarshalJSONStream(dest *json.Stream) { + if tid.IsEmpty() { + dest.WriteString("") + return + } + dest.WriteString(hex.EncodeToString(tid[:])) +} + // UnmarshalJSON inflates profile id from hex string, possibly enclosed in quotes. // Called by Protobuf JSON deserialization. func (tid *ProfileID) UnmarshalJSON(data []byte) error { diff --git a/pdata/internal/data/spanid.go b/pdata/internal/data/spanid.go index 25110f8b445..2fdd4082dba 100644 --- a/pdata/internal/data/spanid.go +++ b/pdata/internal/data/spanid.go @@ -4,9 +4,12 @@ package data // import "go.opentelemetry.io/collector/pdata/internal/data" import ( + "encoding/hex" "errors" "github.com/gogo/protobuf/proto" + + "go.opentelemetry.io/collector/pdata/internal/json" ) const spanIDSize = 8 @@ -71,6 +74,15 @@ func (sid SpanID) MarshalJSON() ([]byte, error) { return marshalJSON(sid[:]) } +// MarshalJSONStream converts trace id into a hex string enclosed in quotes. +func (sid SpanID) MarshalJSONStream(dest *json.Stream) { + if sid.IsEmpty() { + dest.WriteString("") + return + } + dest.WriteString(hex.EncodeToString(sid[:])) +} + // UnmarshalJSON decodes SpanID from hex string, possibly enclosed in quotes. // Called by Protobuf JSON deserialization. func (sid *SpanID) UnmarshalJSON(data []byte) error { diff --git a/pdata/internal/data/traceid.go b/pdata/internal/data/traceid.go index 4828ee02bd0..de1f10e0e31 100644 --- a/pdata/internal/data/traceid.go +++ b/pdata/internal/data/traceid.go @@ -4,9 +4,12 @@ package data // import "go.opentelemetry.io/collector/pdata/internal/data" import ( + "encoding/hex" "errors" "github.com/gogo/protobuf/proto" + + "go.opentelemetry.io/collector/pdata/internal/json" ) const traceIDSize = 16 @@ -71,6 +74,15 @@ func (tid TraceID) MarshalJSON() ([]byte, error) { return marshalJSON(tid[:]) } +// MarshalJSONStream converts trace id into a hex string enclosed in quotes. +func (tid TraceID) MarshalJSONStream(dest *json.Stream) { + if tid.IsEmpty() { + dest.WriteString("") + return + } + dest.WriteString(hex.EncodeToString(tid[:])) +} + // UnmarshalJSON inflates trace id from hex string, possibly enclosed in quotes. // Called by Protobuf JSON deserialization. func (tid *TraceID) UnmarshalJSON(data []byte) error { diff --git a/pdata/internal/generated_wrapper_byteslice.go b/pdata/internal/generated_wrapper_byteslice.go index a4d54fc0e12..d674f973a5d 100644 --- a/pdata/internal/generated_wrapper_byteslice.go +++ b/pdata/internal/generated_wrapper_byteslice.go @@ -6,6 +6,12 @@ package internal +import ( + "encoding/base64" + + "go.opentelemetry.io/collector/pdata/internal/json" +) + type ByteSlice struct { orig *[]byte state *State @@ -39,3 +45,8 @@ func GenerateTestByteSlice() ByteSlice { FillTestByteSlice(ms) return ms } + +// MarshalJSONStream marshals all properties from the current struct to the destination stream. +func MarshalJSONStreamByteSlice(ms ByteSlice, dest *json.Stream) { + dest.WriteString(base64.StdEncoding.EncodeToString(*ms.orig)) +} diff --git a/pdata/internal/generated_wrapper_entityref.go b/pdata/internal/generated_wrapper_entityref.go index e330c21575c..5ccf61837d5 100644 --- a/pdata/internal/generated_wrapper_entityref.go +++ b/pdata/internal/generated_wrapper_entityref.go @@ -8,6 +8,7 @@ package internal import ( otlpcommon "go.opentelemetry.io/collector/pdata/internal/data/protogen/common/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) type EntityRef struct { @@ -48,3 +49,25 @@ func FillTestEntityRef(tv EntityRef) { FillTestStringSlice(NewStringSlice(&tv.orig.IdKeys, tv.state)) FillTestStringSlice(NewStringSlice(&tv.orig.DescriptionKeys, tv.state)) } + +// MarshalJSONStream marshals all properties from the current struct to the destination stream. +func MarshalJSONStreamEntityRef(ms EntityRef, dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.SchemaUrl != "" { + dest.WriteObjectField("schemaUrl") + dest.WriteString(ms.orig.SchemaUrl) + } + if ms.orig.Type != "" { + dest.WriteObjectField("type") + dest.WriteString(ms.orig.Type) + } + if len(ms.orig.IdKeys) > 0 { + dest.WriteObjectField("idKeys") + MarshalJSONStreamStringSlice(NewStringSlice(&ms.orig.IdKeys, ms.state), dest) + } + if len(ms.orig.DescriptionKeys) > 0 { + dest.WriteObjectField("descriptionKeys") + MarshalJSONStreamStringSlice(NewStringSlice(&ms.orig.DescriptionKeys, ms.state), dest) + } + dest.WriteObjectEnd() +} diff --git a/pdata/internal/generated_wrapper_entityrefslice.go b/pdata/internal/generated_wrapper_entityrefslice.go index 10c4312506e..ac109f41ffa 100644 --- a/pdata/internal/generated_wrapper_entityrefslice.go +++ b/pdata/internal/generated_wrapper_entityrefslice.go @@ -8,6 +8,7 @@ package internal import ( otlpcommon "go.opentelemetry.io/collector/pdata/internal/data/protogen/common/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) type EntityRefSlice struct { @@ -57,3 +58,16 @@ func FillTestEntityRefSlice(es EntityRefSlice) { FillTestEntityRef(NewEntityRef((*es.orig)[i], es.state)) } } + +// MarshalJSONStream marshals all properties from the current struct to the destination stream. +func MarshalJSONStreamEntityRefSlice(ms EntityRefSlice, dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + MarshalJSONStreamEntityRef(NewEntityRef((*ms.orig)[0], ms.state), dest) + } + for i := 1; i < len((*ms.orig)); i++ { + dest.WriteMore() + MarshalJSONStreamEntityRef(NewEntityRef((*ms.orig)[i], ms.state), dest) + } + dest.WriteArrayEnd() +} diff --git a/pdata/internal/generated_wrapper_float64slice.go b/pdata/internal/generated_wrapper_float64slice.go index f84d538d8ac..7adab535dcb 100644 --- a/pdata/internal/generated_wrapper_float64slice.go +++ b/pdata/internal/generated_wrapper_float64slice.go @@ -6,6 +6,10 @@ package internal +import ( + "go.opentelemetry.io/collector/pdata/internal/json" +) + type Float64Slice struct { orig *[]float64 state *State @@ -39,3 +43,16 @@ func GenerateTestFloat64Slice() Float64Slice { FillTestFloat64Slice(ms) return ms } + +// MarshalJSONStream marshals all properties from the current struct to the destination stream. +func MarshalJSONStreamFloat64Slice(ms Float64Slice, dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + dest.WriteFloat64((*ms.orig)[0]) + } + for i := 1; i < len((*ms.orig)); i++ { + dest.WriteMore() + dest.WriteFloat64((*ms.orig)[i]) + } + dest.WriteArrayEnd() +} diff --git a/pdata/internal/generated_wrapper_instrumentationscope.go b/pdata/internal/generated_wrapper_instrumentationscope.go index 6ad4023e955..db6800a2063 100644 --- a/pdata/internal/generated_wrapper_instrumentationscope.go +++ b/pdata/internal/generated_wrapper_instrumentationscope.go @@ -8,6 +8,7 @@ package internal import ( otlpcommon "go.opentelemetry.io/collector/pdata/internal/data/protogen/common/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) type InstrumentationScope struct { @@ -48,3 +49,25 @@ func FillTestInstrumentationScope(tv InstrumentationScope) { FillTestMap(NewMap(&tv.orig.Attributes, tv.state)) tv.orig.DroppedAttributesCount = uint32(17) } + +// MarshalJSONStream marshals all properties from the current struct to the destination stream. +func MarshalJSONStreamInstrumentationScope(ms InstrumentationScope, dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.Name != "" { + dest.WriteObjectField("name") + dest.WriteString(ms.orig.Name) + } + if ms.orig.Version != "" { + dest.WriteObjectField("version") + dest.WriteString(ms.orig.Version) + } + if len(ms.orig.Attributes) > 0 { + dest.WriteObjectField("attributes") + MarshalJSONStreamMap(NewMap(&ms.orig.Attributes, ms.state), dest) + } + if ms.orig.DroppedAttributesCount != uint32(0) { + dest.WriteObjectField("droppedAttributesCount") + dest.WriteUint32(ms.orig.DroppedAttributesCount) + } + dest.WriteObjectEnd() +} diff --git a/pdata/internal/generated_wrapper_int32slice.go b/pdata/internal/generated_wrapper_int32slice.go index 9ed6e874609..17ef3b23408 100644 --- a/pdata/internal/generated_wrapper_int32slice.go +++ b/pdata/internal/generated_wrapper_int32slice.go @@ -6,6 +6,10 @@ package internal +import ( + "go.opentelemetry.io/collector/pdata/internal/json" +) + type Int32Slice struct { orig *[]int32 state *State @@ -39,3 +43,16 @@ func GenerateTestInt32Slice() Int32Slice { FillTestInt32Slice(ms) return ms } + +// MarshalJSONStream marshals all properties from the current struct to the destination stream. +func MarshalJSONStreamInt32Slice(ms Int32Slice, dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + dest.WriteInt32((*ms.orig)[0]) + } + for i := 1; i < len((*ms.orig)); i++ { + dest.WriteMore() + dest.WriteInt32((*ms.orig)[i]) + } + dest.WriteArrayEnd() +} diff --git a/pdata/internal/generated_wrapper_int64slice.go b/pdata/internal/generated_wrapper_int64slice.go index 47a64ef72f0..f6edbb4783b 100644 --- a/pdata/internal/generated_wrapper_int64slice.go +++ b/pdata/internal/generated_wrapper_int64slice.go @@ -6,6 +6,10 @@ package internal +import ( + "go.opentelemetry.io/collector/pdata/internal/json" +) + type Int64Slice struct { orig *[]int64 state *State @@ -39,3 +43,16 @@ func GenerateTestInt64Slice() Int64Slice { FillTestInt64Slice(ms) return ms } + +// MarshalJSONStream marshals all properties from the current struct to the destination stream. +func MarshalJSONStreamInt64Slice(ms Int64Slice, dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + dest.WriteInt64((*ms.orig)[0]) + } + for i := 1; i < len((*ms.orig)); i++ { + dest.WriteMore() + dest.WriteInt64((*ms.orig)[i]) + } + dest.WriteArrayEnd() +} diff --git a/pdata/internal/generated_wrapper_intslice.go b/pdata/internal/generated_wrapper_intslice.go deleted file mode 100644 index 5f3fe569ba5..00000000000 --- a/pdata/internal/generated_wrapper_intslice.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -// Code generated by "pdata/internal/cmd/pdatagen/main.go". DO NOT EDIT. -// To regenerate this file run "make genpdata". - -package internal - -type IntSlice struct { - orig *[]int - state *State -} - -func GetOrigIntSlice(ms IntSlice) *[]int { - return ms.orig -} - -func GetIntSliceState(ms IntSlice) *State { - return ms.state -} - -func NewIntSlice(orig *[]int, state *State) IntSlice { - return IntSlice{orig: orig, state: state} -} - -func FillTestIntSlice(tv IntSlice) { -} - -func GenerateTestIntSlice() IntSlice { - state := StateMutable - var orig []int = nil - - return IntSlice{&orig, &state} -} diff --git a/pdata/internal/generated_wrapper_resource.go b/pdata/internal/generated_wrapper_resource.go index 745cea4fd7c..e84d477662c 100644 --- a/pdata/internal/generated_wrapper_resource.go +++ b/pdata/internal/generated_wrapper_resource.go @@ -8,6 +8,7 @@ package internal import ( otlpresource "go.opentelemetry.io/collector/pdata/internal/data/protogen/resource/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) type Resource struct { @@ -46,3 +47,21 @@ func FillTestResource(tv Resource) { tv.orig.DroppedAttributesCount = uint32(17) FillTestEntityRefSlice(NewEntityRefSlice(&tv.orig.EntityRefs, tv.state)) } + +// MarshalJSONStream marshals all properties from the current struct to the destination stream. +func MarshalJSONStreamResource(ms Resource, dest *json.Stream) { + dest.WriteObjectStart() + if len(ms.orig.Attributes) > 0 { + dest.WriteObjectField("attributes") + MarshalJSONStreamMap(NewMap(&ms.orig.Attributes, ms.state), dest) + } + if ms.orig.DroppedAttributesCount != uint32(0) { + dest.WriteObjectField("droppedAttributesCount") + dest.WriteUint32(ms.orig.DroppedAttributesCount) + } + if len(ms.orig.EntityRefs) > 0 { + dest.WriteObjectField("entityRefs") + MarshalJSONStreamEntityRefSlice(NewEntityRefSlice(&ms.orig.EntityRefs, ms.state), dest) + } + dest.WriteObjectEnd() +} diff --git a/pdata/internal/generated_wrapper_stringslice.go b/pdata/internal/generated_wrapper_stringslice.go index d717b5546e7..2c29d7f79e2 100644 --- a/pdata/internal/generated_wrapper_stringslice.go +++ b/pdata/internal/generated_wrapper_stringslice.go @@ -6,6 +6,10 @@ package internal +import ( + "go.opentelemetry.io/collector/pdata/internal/json" +) + type StringSlice struct { orig *[]string state *State @@ -39,3 +43,16 @@ func GenerateTestStringSlice() StringSlice { FillTestStringSlice(ms) return ms } + +// MarshalJSONStream marshals all properties from the current struct to the destination stream. +func MarshalJSONStreamStringSlice(ms StringSlice, dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + dest.WriteString((*ms.orig)[0]) + } + for i := 1; i < len((*ms.orig)); i++ { + dest.WriteMore() + dest.WriteString((*ms.orig)[i]) + } + dest.WriteArrayEnd() +} diff --git a/pdata/internal/generated_wrapper_uint64slice.go b/pdata/internal/generated_wrapper_uint64slice.go index 7aa29d1dbd2..c04027dcc1d 100644 --- a/pdata/internal/generated_wrapper_uint64slice.go +++ b/pdata/internal/generated_wrapper_uint64slice.go @@ -6,6 +6,10 @@ package internal +import ( + "go.opentelemetry.io/collector/pdata/internal/json" +) + type UInt64Slice struct { orig *[]uint64 state *State @@ -39,3 +43,16 @@ func GenerateTestUInt64Slice() UInt64Slice { FillTestUInt64Slice(ms) return ms } + +// MarshalJSONStream marshals all properties from the current struct to the destination stream. +func MarshalJSONStreamUInt64Slice(ms UInt64Slice, dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + dest.WriteUint64((*ms.orig)[0]) + } + for i := 1; i < len((*ms.orig)); i++ { + dest.WriteMore() + dest.WriteUint64((*ms.orig)[i]) + } + dest.WriteArrayEnd() +} diff --git a/pdata/internal/json/iterator.go b/pdata/internal/json/iterator.go new file mode 100644 index 00000000000..8bfb3f1d34d --- /dev/null +++ b/pdata/internal/json/iterator.go @@ -0,0 +1,15 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package json // import "go.opentelemetry.io/collector/pdata/internal/json" +import ( + jsoniter "github.com/json-iterator/go" +) + +func BorrowIterator(data []byte) *jsoniter.Iterator { + return jsoniter.ConfigFastest.BorrowIterator(data) +} + +func ReturnIterator(s *jsoniter.Iterator) { + jsoniter.ConfigFastest.ReturnIterator(s) +} diff --git a/pdata/internal/json/stream.go b/pdata/internal/json/stream.go new file mode 100644 index 00000000000..c58bfe2a62b --- /dev/null +++ b/pdata/internal/json/stream.go @@ -0,0 +1,74 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package json // import "go.opentelemetry.io/collector/pdata/internal/json" + +import ( + "fmt" + "io" + "math" + "strconv" + + jsoniter "github.com/json-iterator/go" +) + +// Stream avoids the need to explicitly call the `Stream.WriteMore` method while marshaling objects by +// checking if a field was previously written inside the current object and automatically appending a "," +// if so before writing the next field. +type Stream struct { + *jsoniter.Stream + // wmTracker acts like a stack which pushes a new value when an object is started and removes the + // top when it is ended. The value added for every object tracks if there is any written field + // already for that object, and if it is then automatically add a "," before any new field. + wmTracker []bool +} + +func BorrowStream(writer io.Writer) *Stream { + return &Stream{ + Stream: jsoniter.ConfigFastest.BorrowStream(writer), + wmTracker: make([]bool, 32), + } +} + +func ReturnStream(s *Stream) { + jsoniter.ConfigFastest.ReturnStream(s.Stream) +} + +func (ots *Stream) WriteObjectStart() { + ots.Stream.WriteObjectStart() + ots.wmTracker = append(ots.wmTracker, false) +} + +func (ots *Stream) WriteObjectField(field string) { + if ots.wmTracker[len(ots.wmTracker)-1] { + ots.WriteMore() + } + + ots.Stream.WriteObjectField(field) + ots.wmTracker[len(ots.wmTracker)-1] = true +} + +func (ots *Stream) WriteObjectEnd() { + ots.Stream.WriteObjectEnd() + ots.wmTracker = ots.wmTracker[:len(ots.wmTracker)-1] +} + +// WriteInt64 writes the values as a decimal string. This is per the protobuf encoding rules for int64, fixed64, uint64. +func (ots *Stream) WriteInt64(val int64) { + ots.WriteString(strconv.FormatInt(val, 10)) +} + +// WriteUint64 writes the values as a decimal string. This is per the protobuf encoding rules for int64, fixed64, uint64. +func (ots *Stream) WriteUint64(val uint64) { + ots.WriteString(strconv.FormatUint(val, 10)) +} + +// WriteFloat64 gracefully handles infinity & NaN values +func (ots *Stream) WriteFloat64(val float64) { + if math.IsNaN(val) || math.IsInf(val, 0) { + ots.WriteString(fmt.Sprintf("%f", val)) + return + } + + ots.Stream.WriteFloat64(val) +} diff --git a/pdata/internal/json/stream_test.go b/pdata/internal/json/stream_test.go new file mode 100644 index 00000000000..52196f438fc --- /dev/null +++ b/pdata/internal/json/stream_test.go @@ -0,0 +1,87 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package json + +import ( + "math" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestNestedObject(t *testing.T) { + s := BorrowStream(nil) + defer ReturnStream(s) + + s.WriteObjectStart() + s.WriteObjectField("field1") + s.WriteString("val1") + s.WriteObjectField("field2") + s.WriteObjectStart() + s.WriteObjectField("field3") + s.WriteObjectStart() + s.WriteObjectField("field4") + s.WriteString("val4") + s.WriteObjectField("field5") + s.WriteString("val5") + s.WriteObjectEnd() + s.WriteObjectField("field6") + s.WriteString("val6") + s.WriteObjectField("field7") + s.WriteObjectStart() + s.WriteObjectEnd() + s.WriteObjectEnd() + s.WriteObjectEnd() + + expected := `{ + "field1": "val1", + "field2": { + "field3": { + "field4": "val4", + "field5": "val5" + }, + "field6": "val6", + "field7": {} + } + }` + assert.JSONEq(t, expected, string(s.Buffer())) +} + +func TestMarshalFloat(t *testing.T) { + tests := []struct { + name string + inputFloat float64 + expected string + }{ + { + name: "positive infinity", + inputFloat: math.Inf(1), + expected: `"+Inf"`, + }, + { + name: "negative infinity", + inputFloat: math.Inf(-1), + expected: `"-Inf"`, + }, + { + name: "not-a-number", + inputFloat: math.NaN(), + expected: `"NaN"`, + }, + { + name: "regular float", + inputFloat: math.MaxFloat64, + expected: "1.7976931348623157e+308", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := BorrowStream(nil) + s.WriteFloat64(tt.inputFloat) + require.Equal(t, tt.expected, string(s.Buffer())) + ReturnStream(s) + }) + } +} diff --git a/pdata/internal/wrapper_map.go b/pdata/internal/wrapper_map.go index 8a173bceb18..eca385f044f 100644 --- a/pdata/internal/wrapper_map.go +++ b/pdata/internal/wrapper_map.go @@ -7,6 +7,7 @@ import ( jsoniter "github.com/json-iterator/go" otlpcommon "go.opentelemetry.io/collector/pdata/internal/data/protogen/common/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) type Map struct { @@ -62,6 +63,30 @@ func FillTestMap(dest Map) { } } +// MarshalJSONStreamMap marshals all properties from the current struct to the destination stream. +func MarshalJSONStreamMap(ms Map, dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + writeAttribute(&(*ms.orig)[0], ms.state, dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + writeAttribute(&(*ms.orig)[i], ms.state, dest) + } + dest.WriteArrayEnd() +} + +func writeAttribute(attr *otlpcommon.KeyValue, state *State, dest *json.Stream) { + dest.WriteObjectStart() + if attr.Key != "" { + dest.WriteObjectField("key") + dest.WriteString(attr.Key) + } + dest.WriteObjectField("value") + MarshalJSONStreamValue(NewValue(&attr.Value, state), dest) + dest.WriteObjectEnd() +} + func UnmarshalJSONIterMap(ms Map, iter *jsoniter.Iterator) { iter.ReadArrayCB(func(iter *jsoniter.Iterator) bool { *ms.orig = append(*ms.orig, otlpcommon.KeyValue{}) diff --git a/pdata/internal/wrapper_map_test.go b/pdata/internal/wrapper_map_test.go index ccad80395a3..8dbd7554015 100644 --- a/pdata/internal/wrapper_map_test.go +++ b/pdata/internal/wrapper_map_test.go @@ -11,12 +11,13 @@ import ( "github.com/stretchr/testify/require" otlpcommon "go.opentelemetry.io/collector/pdata/internal/data/protogen/common/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) func TestReadAttributeUnknownField(t *testing.T) { jsonStr := `[{"extra":""}]` - iter := jsoniter.ConfigFastest.BorrowIterator([]byte(jsonStr)) - defer jsoniter.ConfigFastest.ReturnIterator(iter) + iter := json.BorrowIterator([]byte(jsonStr)) + defer json.ReturnIterator(iter) var got []otlpcommon.KeyValue UnmarshalJSONIterMap(NewMap(&got, nil), iter) // unknown fields should not be an error diff --git a/pdata/internal/wrapper_slice.go b/pdata/internal/wrapper_slice.go index 3d584dc5ec6..94317dc0103 100644 --- a/pdata/internal/wrapper_slice.go +++ b/pdata/internal/wrapper_slice.go @@ -7,6 +7,7 @@ import ( jsoniter "github.com/json-iterator/go" otlpcommon "go.opentelemetry.io/collector/pdata/internal/data/protogen/common/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) type Slice struct { @@ -53,6 +54,19 @@ func FillTestSlice(tv Slice) { } } +// MarshalJSONStreamSlice marshals all properties from the current struct to the destination stream. +func MarshalJSONStreamSlice(ms Slice, dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + MarshalJSONStreamValue(NewValue(&(*ms.orig)[0], ms.state), dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + MarshalJSONStreamValue(NewValue(&(*ms.orig)[i], ms.state), dest) + } + dest.WriteArrayEnd() +} + func UnmarshalJSONIterSlice(ms Slice, iter *jsoniter.Iterator) { iter.ReadArrayCB(func(iter *jsoniter.Iterator) bool { *ms.orig = append(*ms.orig, otlpcommon.AnyValue{}) diff --git a/pdata/internal/wrapper_tracestate.go b/pdata/internal/wrapper_tracestate.go index d1d5c3cf865..d210b996927 100644 --- a/pdata/internal/wrapper_tracestate.go +++ b/pdata/internal/wrapper_tracestate.go @@ -3,6 +3,10 @@ package internal // import "go.opentelemetry.io/collector/pdata/internal" +import ( + "go.opentelemetry.io/collector/pdata/internal/json" +) + type TraceState struct { orig *string state *State @@ -35,3 +39,8 @@ func GenerateTestTraceState() TraceState { func FillTestTraceState(dest TraceState) { *dest.orig = "rojo=00f067aa0ba902b7" } + +// MarshalJSONStreamTraceState marshals all properties from the current struct to the destination stream. +func MarshalJSONStreamTraceState(ms TraceState, dest *json.Stream) { + dest.WriteString(*ms.orig) +} diff --git a/pdata/internal/wrapper_value.go b/pdata/internal/wrapper_value.go index a7abb7fe250..c579f7b4c37 100644 --- a/pdata/internal/wrapper_value.go +++ b/pdata/internal/wrapper_value.go @@ -4,6 +4,9 @@ package internal // import "go.opentelemetry.io/collector/pdata/internal" import ( + "errors" + "fmt" + jsoniter "github.com/json-iterator/go" otlpcommon "go.opentelemetry.io/collector/pdata/internal/data/protogen/common/v1" @@ -77,6 +80,45 @@ func GenerateTestValue() Value { return ms } +// MarshalJSONStreamValue marshals all properties from the current struct to the destination stream. +func MarshalJSONStreamValue(ms Value, dest *json.Stream) { + dest.WriteObjectStart() + switch v := ms.orig.Value.(type) { + case nil: + // Do nothing, return an empty object. + case *otlpcommon.AnyValue_StringValue: + dest.WriteObjectField("stringValue") + dest.WriteString(v.StringValue) + case *otlpcommon.AnyValue_BoolValue: + dest.WriteObjectField("boolValue") + dest.WriteBool(v.BoolValue) + case *otlpcommon.AnyValue_IntValue: + dest.WriteObjectField("intValue") + dest.WriteInt64(v.IntValue) + case *otlpcommon.AnyValue_DoubleValue: + dest.WriteObjectField("doubleValue") + dest.WriteFloat64(v.DoubleValue) + case *otlpcommon.AnyValue_BytesValue: + dest.WriteObjectField("bytesValue") + MarshalJSONStreamByteSlice(NewByteSlice(&v.BytesValue, ms.state), dest) + case *otlpcommon.AnyValue_ArrayValue: + dest.WriteObjectField("arrayValue") + dest.WriteObjectStart() + dest.WriteObjectField("values") + MarshalJSONStreamSlice(NewSlice(&v.ArrayValue.Values, ms.state), dest) + dest.WriteObjectEnd() + case *otlpcommon.AnyValue_KvlistValue: + dest.WriteObjectField("kvlistValue") + dest.WriteObjectStart() + dest.WriteObjectField("values") + MarshalJSONStreamMap(NewMap(&v.KvlistValue.Values, ms.state), dest) + dest.WriteObjectEnd() + default: + dest.Error = errors.Join(dest.Error, fmt.Errorf("invalid value type in the passed attribute value: %T", ms.orig.Value)) + } + dest.WriteObjectEnd() +} + // UnmarshalJSONIterValue Unmarshal JSON data and return otlpcommon.AnyValue func UnmarshalJSONIterValue(val Value, iter *jsoniter.Iterator) { iter.ReadObjectCB(func(iter *jsoniter.Iterator, f string) bool { diff --git a/pdata/pcommon/generated_instrumentationscope_test.go b/pdata/pcommon/generated_instrumentationscope_test.go index e8913e81c38..a326c2197b9 100644 --- a/pdata/pcommon/generated_instrumentationscope_test.go +++ b/pdata/pcommon/generated_instrumentationscope_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpcommon "go.opentelemetry.io/collector/pdata/internal/data/protogen/common/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) func TestInstrumentationScope_MoveTo(t *testing.T) { @@ -40,6 +41,20 @@ func TestInstrumentationScope_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newInstrumentationScope(&otlpcommon.InstrumentationScope{}, &sharedState)) }) } +func TestInstrumentationScope_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestInstrumentationScope() + internal.MarshalJSONStreamInstrumentationScope(internal.InstrumentationScope(src), stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewInstrumentationScope() + internal.UnmarshalJSONIterInstrumentationScope(internal.InstrumentationScope(dest), iter) + + assert.Equal(t, src, dest) +} + func TestInstrumentationScope_Name(t *testing.T) { ms := NewInstrumentationScope() assert.Empty(t, ms.Name()) diff --git a/pdata/pcommon/generated_intslice.go b/pdata/pcommon/generated_intslice.go deleted file mode 100644 index 1a72889d554..00000000000 --- a/pdata/pcommon/generated_intslice.go +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -// Code generated by "pdata/internal/cmd/pdatagen/main.go". DO NOT EDIT. -// To regenerate this file run "make genpdata". - -package pcommon - -import ( - "go.opentelemetry.io/collector/pdata/internal" -) - -// IntSlice represents a []int slice. -// The instance of IntSlice can be assigned to multiple objects since it's immutable. -// -// Must use NewIntSlice function to create new instances. -// Important: zero-initialized instance is not valid for use. -type IntSlice internal.IntSlice - -func (ms IntSlice) getOrig() *[]int { - return internal.GetOrigIntSlice(internal.IntSlice(ms)) -} - -func (ms IntSlice) getState() *internal.State { - return internal.GetIntSliceState(internal.IntSlice(ms)) -} - -// NewIntSlice creates a new empty IntSlice. -func NewIntSlice() IntSlice { - orig := []int(nil) - state := internal.StateMutable - return IntSlice(internal.NewIntSlice(&orig, &state)) -} - -// AsRaw returns a copy of the []int slice. -func (ms IntSlice) AsRaw() []int { - return copyIntSlice(nil, *ms.getOrig()) -} - -// FromRaw copies raw []int into the slice IntSlice. -func (ms IntSlice) FromRaw(val []int) { - ms.getState().AssertMutable() - *ms.getOrig() = copyIntSlice(*ms.getOrig(), val) -} - -// Len returns length of the []int slice value. -// Equivalent of len(intSlice). -func (ms IntSlice) Len() int { - return len(*ms.getOrig()) -} - -// At returns an item from particular index. -// Equivalent of intSlice[i]. -func (ms IntSlice) At(i int) int { - return (*ms.getOrig())[i] -} - -// SetAt sets int item at particular index. -// Equivalent of intSlice[i] = val -func (ms IntSlice) SetAt(i int, val int) { - ms.getState().AssertMutable() - (*ms.getOrig())[i] = val -} - -// EnsureCapacity ensures IntSlice has at least the specified capacity. -// 1. If the newCap <= cap, then is no change in capacity. -// 2. If the newCap > cap, then the slice capacity will be expanded to the provided value which will be equivalent of: -// buf := make([]int, len(intSlice), newCap) -// copy(buf, intSlice) -// intSlice = buf -func (ms IntSlice) EnsureCapacity(newCap int) { - ms.getState().AssertMutable() - oldCap := cap(*ms.getOrig()) - if newCap <= oldCap { - return - } - - newOrig := make([]int, len(*ms.getOrig()), newCap) - copy(newOrig, *ms.getOrig()) - *ms.getOrig() = newOrig -} - -// Append appends extra elements to IntSlice. -// Equivalent of intSlice = append(intSlice, elms...) -func (ms IntSlice) Append(elms ...int) { - ms.getState().AssertMutable() - *ms.getOrig() = append(*ms.getOrig(), elms...) -} - -// MoveTo moves all elements from the current slice overriding the destination and -// resetting the current instance to its zero value. -func (ms IntSlice) MoveTo(dest IntSlice) { - ms.getState().AssertMutable() - dest.getState().AssertMutable() - *dest.getOrig() = *ms.getOrig() - *ms.getOrig() = nil -} - -// CopyTo copies all elements from the current slice overriding the destination. -func (ms IntSlice) CopyTo(dest IntSlice) { - dest.getState().AssertMutable() - *dest.getOrig() = copyIntSlice(*dest.getOrig(), *ms.getOrig()) -} - -func copyIntSlice(dst, src []int) []int { - dst = dst[:0] - return append(dst, src...) -} diff --git a/pdata/pcommon/generated_intslice_test.go b/pdata/pcommon/generated_intslice_test.go deleted file mode 100644 index ab5051dfcb8..00000000000 --- a/pdata/pcommon/generated_intslice_test.go +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -// Code generated by "pdata/internal/cmd/pdatagen/main.go". DO NOT EDIT. -// To regenerate this file run "make genpdata". - -package pcommon - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "go.opentelemetry.io/collector/pdata/internal" -) - -func TestNewIntSlice(t *testing.T) { - ms := NewIntSlice() - assert.Equal(t, 0, ms.Len()) - ms.FromRaw([]int{1, 2, 3}) - assert.Equal(t, 3, ms.Len()) - assert.Equal(t, []int{1, 2, 3}, ms.AsRaw()) - ms.SetAt(1, int(5)) - assert.Equal(t, []int{1, 5, 3}, ms.AsRaw()) - ms.FromRaw([]int{3}) - assert.Equal(t, 1, ms.Len()) - assert.Equal(t, int(3), ms.At(0)) - - cp := NewIntSlice() - ms.CopyTo(cp) - ms.SetAt(0, int(2)) - assert.Equal(t, int(2), ms.At(0)) - assert.Equal(t, int(3), cp.At(0)) - ms.CopyTo(cp) - assert.Equal(t, int(2), cp.At(0)) - - mv := NewIntSlice() - ms.MoveTo(mv) - assert.Equal(t, 0, ms.Len()) - assert.Equal(t, 1, mv.Len()) - assert.Equal(t, int(2), mv.At(0)) - ms.FromRaw([]int{1, 2, 3}) - ms.MoveTo(mv) - assert.Equal(t, 3, mv.Len()) - assert.Equal(t, int(1), mv.At(0)) -} - -func TestIntSliceReadOnly(t *testing.T) { - raw := []int{1, 2, 3} - state := internal.StateReadOnly - ms := IntSlice(internal.NewIntSlice(&raw, &state)) - - assert.Equal(t, 3, ms.Len()) - assert.Equal(t, int(1), ms.At(0)) - assert.Panics(t, func() { ms.Append(1) }) - assert.Panics(t, func() { ms.EnsureCapacity(2) }) - assert.Equal(t, raw, ms.AsRaw()) - assert.Panics(t, func() { ms.FromRaw(raw) }) - - ms2 := NewIntSlice() - ms.CopyTo(ms2) - assert.Equal(t, ms.AsRaw(), ms2.AsRaw()) - assert.Panics(t, func() { ms2.CopyTo(ms) }) - - assert.Panics(t, func() { ms.MoveTo(ms2) }) - assert.Panics(t, func() { ms2.MoveTo(ms) }) -} - -func TestIntSliceAppend(t *testing.T) { - ms := NewIntSlice() - ms.FromRaw([]int{1, 2, 3}) - ms.Append(5, 5) - assert.Equal(t, 5, ms.Len()) - assert.Equal(t, int(5), ms.At(4)) -} - -func TestIntSliceEnsureCapacity(t *testing.T) { - ms := NewIntSlice() - ms.EnsureCapacity(4) - assert.Equal(t, 4, cap(*ms.getOrig())) - ms.EnsureCapacity(2) - assert.Equal(t, 4, cap(*ms.getOrig())) -} diff --git a/pdata/pcommon/generated_resource_test.go b/pdata/pcommon/generated_resource_test.go index 6f4a55d414d..66691a08f42 100644 --- a/pdata/pcommon/generated_resource_test.go +++ b/pdata/pcommon/generated_resource_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpresource "go.opentelemetry.io/collector/pdata/internal/data/protogen/resource/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) func TestResource_MoveTo(t *testing.T) { @@ -40,6 +41,20 @@ func TestResource_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newResource(&otlpresource.Resource{}, &sharedState)) }) } +func TestResource_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestResource() + internal.MarshalJSONStreamResource(internal.Resource(src), stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewResource() + internal.UnmarshalJSONIterResource(internal.Resource(dest), iter) + + assert.Equal(t, src, dest) +} + func TestResource_Attributes(t *testing.T) { ms := NewResource() assert.Equal(t, NewMap(), ms.Attributes()) diff --git a/pdata/plog/generated_logrecord.go b/pdata/plog/generated_logrecord.go index 14583d349ab..f93ca786697 100644 --- a/pdata/plog/generated_logrecord.go +++ b/pdata/plog/generated_logrecord.go @@ -10,6 +10,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" "go.opentelemetry.io/collector/pdata/internal/data" otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -166,6 +167,54 @@ func (ms LogRecord) CopyTo(dest LogRecord) { copyOrigLogRecord(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms LogRecord) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.ObservedTimeUnixNano != 0 { + dest.WriteObjectField("observedTimeUnixNano") + dest.WriteUint64(ms.orig.ObservedTimeUnixNano) + } + if ms.orig.TimeUnixNano != 0 { + dest.WriteObjectField("timeUnixNano") + dest.WriteUint64(ms.orig.TimeUnixNano) + } + if ms.orig.TraceId != data.TraceID([16]byte{}) { + dest.WriteObjectField("traceId") + ms.orig.TraceId.MarshalJSONStream(dest) + } + if ms.orig.SpanId != data.SpanID([8]byte{}) { + dest.WriteObjectField("spanId") + ms.orig.SpanId.MarshalJSONStream(dest) + } + if ms.orig.Flags != 0 { + dest.WriteObjectField("flags") + dest.WriteUint32(ms.orig.Flags) + } + if ms.orig.EventName != "" { + dest.WriteObjectField("eventName") + dest.WriteString(ms.orig.EventName) + } + if ms.orig.SeverityText != "" { + dest.WriteObjectField("severityText") + dest.WriteString(ms.orig.SeverityText) + } + if ms.orig.SeverityNumber != otlplogs.SeverityNumber(0) { + dest.WriteObjectField("severityNumber") + ms.SeverityNumber().marshalJSONStream(dest) + } + dest.WriteObjectField("body") + internal.MarshalJSONStreamValue(internal.NewValue(&ms.orig.Body, ms.state), dest) + if len(ms.orig.Attributes) > 0 { + dest.WriteObjectField("attributes") + internal.MarshalJSONStreamMap(internal.NewMap(&ms.orig.Attributes, ms.state), dest) + } + if ms.orig.DroppedAttributesCount != uint32(0) { + dest.WriteObjectField("droppedAttributesCount") + dest.WriteUint32(ms.orig.DroppedAttributesCount) + } + dest.WriteObjectEnd() +} + func copyOrigLogRecord(dest, src *otlplogs.LogRecord) { dest.ObservedTimeUnixNano = src.ObservedTimeUnixNano dest.TimeUnixNano = src.TimeUnixNano diff --git a/pdata/plog/generated_logrecord_test.go b/pdata/plog/generated_logrecord_test.go index 090e200d120..6fbcf01038e 100644 --- a/pdata/plog/generated_logrecord_test.go +++ b/pdata/plog/generated_logrecord_test.go @@ -14,6 +14,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" "go.opentelemetry.io/collector/pdata/internal/data" otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -42,6 +43,20 @@ func TestLogRecord_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newLogRecord(&otlplogs.LogRecord{}, &sharedState)) }) } +func TestLogRecord_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestLogRecord() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewLogRecord() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestLogRecord_ObservedTimestamp(t *testing.T) { ms := NewLogRecord() assert.Equal(t, pcommon.Timestamp(0), ms.ObservedTimestamp()) diff --git a/pdata/plog/generated_logrecordslice.go b/pdata/plog/generated_logrecordslice.go index c3b3709b71f..b2f36c3121e 100644 --- a/pdata/plog/generated_logrecordslice.go +++ b/pdata/plog/generated_logrecordslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // LogRecordSlice logically represents a slice of LogRecord. @@ -156,6 +157,19 @@ func (es LogRecordSlice) Sort(less func(a, b LogRecord) bool) { sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms LogRecordSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigLogRecordSlice(dest, src []*otlplogs.LogRecord) []*otlplogs.LogRecord { if cap(dest) < len(src) { dest = make([]*otlplogs.LogRecord, len(src)) diff --git a/pdata/plog/generated_resourcelogs.go b/pdata/plog/generated_resourcelogs.go index c20885393f7..290380b5701 100644 --- a/pdata/plog/generated_resourcelogs.go +++ b/pdata/plog/generated_resourcelogs.go @@ -9,6 +9,7 @@ package plog import ( "go.opentelemetry.io/collector/pdata/internal" otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -77,6 +78,22 @@ func (ms ResourceLogs) CopyTo(dest ResourceLogs) { copyOrigResourceLogs(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ResourceLogs) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + dest.WriteObjectField("resource") + internal.MarshalJSONStreamResource(internal.NewResource(&ms.orig.Resource, ms.state), dest) + if ms.orig.SchemaUrl != "" { + dest.WriteObjectField("schemaUrl") + dest.WriteString(ms.orig.SchemaUrl) + } + if len(ms.orig.ScopeLogs) > 0 { + dest.WriteObjectField("scopeLogs") + ms.ScopeLogs().marshalJSONStream(dest) + } + dest.WriteObjectEnd() +} + func copyOrigResourceLogs(dest, src *otlplogs.ResourceLogs) { internal.CopyOrigResource(&dest.Resource, &src.Resource) dest.SchemaUrl = src.SchemaUrl diff --git a/pdata/plog/generated_resourcelogs_test.go b/pdata/plog/generated_resourcelogs_test.go index e88fe65c3c7..a814312157e 100644 --- a/pdata/plog/generated_resourcelogs_test.go +++ b/pdata/plog/generated_resourcelogs_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -41,6 +42,20 @@ func TestResourceLogs_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newResourceLogs(&otlplogs.ResourceLogs{}, &sharedState)) }) } +func TestResourceLogs_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestResourceLogs() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewResourceLogs() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestResourceLogs_Resource(t *testing.T) { ms := NewResourceLogs() internal.FillTestResource(internal.Resource(ms.Resource())) diff --git a/pdata/plog/generated_resourcelogsslice.go b/pdata/plog/generated_resourcelogsslice.go index 34dc40d9366..a37efa077d4 100644 --- a/pdata/plog/generated_resourcelogsslice.go +++ b/pdata/plog/generated_resourcelogsslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // ResourceLogsSlice logically represents a slice of ResourceLogs. @@ -156,6 +157,19 @@ func (es ResourceLogsSlice) Sort(less func(a, b ResourceLogs) bool) { sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ResourceLogsSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigResourceLogsSlice(dest, src []*otlplogs.ResourceLogs) []*otlplogs.ResourceLogs { if cap(dest) < len(src) { dest = make([]*otlplogs.ResourceLogs, len(src)) diff --git a/pdata/plog/generated_scopelogs.go b/pdata/plog/generated_scopelogs.go index afc50c49613..b4dcee0527b 100644 --- a/pdata/plog/generated_scopelogs.go +++ b/pdata/plog/generated_scopelogs.go @@ -9,6 +9,7 @@ package plog import ( "go.opentelemetry.io/collector/pdata/internal" otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -77,6 +78,22 @@ func (ms ScopeLogs) CopyTo(dest ScopeLogs) { copyOrigScopeLogs(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ScopeLogs) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + dest.WriteObjectField("scope") + internal.MarshalJSONStreamInstrumentationScope(internal.NewInstrumentationScope(&ms.orig.Scope, ms.state), dest) + if ms.orig.SchemaUrl != "" { + dest.WriteObjectField("schemaUrl") + dest.WriteString(ms.orig.SchemaUrl) + } + if len(ms.orig.LogRecords) > 0 { + dest.WriteObjectField("logRecords") + ms.LogRecords().marshalJSONStream(dest) + } + dest.WriteObjectEnd() +} + func copyOrigScopeLogs(dest, src *otlplogs.ScopeLogs) { internal.CopyOrigInstrumentationScope(&dest.Scope, &src.Scope) dest.SchemaUrl = src.SchemaUrl diff --git a/pdata/plog/generated_scopelogs_test.go b/pdata/plog/generated_scopelogs_test.go index 9dd5b0116f8..4541c587dd6 100644 --- a/pdata/plog/generated_scopelogs_test.go +++ b/pdata/plog/generated_scopelogs_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -41,6 +42,20 @@ func TestScopeLogs_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newScopeLogs(&otlplogs.ScopeLogs{}, &sharedState)) }) } +func TestScopeLogs_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestScopeLogs() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewScopeLogs() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestScopeLogs_Scope(t *testing.T) { ms := NewScopeLogs() internal.FillTestInstrumentationScope(internal.InstrumentationScope(ms.Scope())) diff --git a/pdata/plog/generated_scopelogsslice.go b/pdata/plog/generated_scopelogsslice.go index 559a151d0cd..cf70436502f 100644 --- a/pdata/plog/generated_scopelogsslice.go +++ b/pdata/plog/generated_scopelogsslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // ScopeLogsSlice logically represents a slice of ScopeLogs. @@ -156,6 +157,19 @@ func (es ScopeLogsSlice) Sort(less func(a, b ScopeLogs) bool) { sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ScopeLogsSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigScopeLogsSlice(dest, src []*otlplogs.ScopeLogs) []*otlplogs.ScopeLogs { if cap(dest) < len(src) { dest = make([]*otlplogs.ScopeLogs, len(src)) diff --git a/pdata/plog/json.go b/pdata/plog/json.go index 6dd1a6df42d..7914af65487 100644 --- a/pdata/plog/json.go +++ b/pdata/plog/json.go @@ -4,8 +4,8 @@ package plog // import "go.opentelemetry.io/collector/pdata/plog" import ( - "bytes" "fmt" + "slices" jsoniter "github.com/json-iterator/go" @@ -20,10 +20,10 @@ type JSONMarshaler struct{} // MarshalLogs to the OTLP/JSON format. func (*JSONMarshaler) MarshalLogs(ld Logs) ([]byte, error) { - buf := bytes.Buffer{} - pb := internal.LogsToProto(internal.Logs(ld)) - err := json.Marshal(&buf, &pb) - return buf.Bytes(), err + dest := json.BorrowStream(nil) + defer json.ReturnStream(dest) + ld.marshalJSONStream(dest) + return slices.Clone(dest.Buffer()), dest.Error } var _ Unmarshaler = (*JSONUnmarshaler)(nil) @@ -44,21 +44,6 @@ func (*JSONUnmarshaler) UnmarshalLogs(buf []byte) (Logs, error) { return ld, nil } -func (ms Logs) unmarshalJsoniter(iter *jsoniter.Iterator) { - iter.ReadObjectCB(func(iter *jsoniter.Iterator, f string) bool { - switch f { - case "resource_logs", "resourceLogs": - iter.ReadArrayCB(func(*jsoniter.Iterator) bool { - ms.ResourceLogs().AppendEmpty().unmarshalJsoniter(iter) - return true - }) - default: - iter.Skip() - } - return true - }) -} - func (ms ResourceLogs) unmarshalJsoniter(iter *jsoniter.Iterator) { iter.ReadObjectCB(func(iter *jsoniter.Iterator, f string) bool { switch f { diff --git a/pdata/plog/logs.go b/pdata/plog/logs.go index 490526090f8..c9665214674 100644 --- a/pdata/plog/logs.go +++ b/pdata/plog/logs.go @@ -4,8 +4,11 @@ package plog // import "go.opentelemetry.io/collector/pdata/plog" import ( + jsoniter "github.com/json-iterator/go" + "go.opentelemetry.io/collector/pdata/internal" otlpcollectorlog "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/logs/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // Logs is the top-level struct that is propagated through the logs pipeline. @@ -64,3 +67,25 @@ func (ms Logs) ResourceLogs() ResourceLogsSlice { func (ms Logs) MarkReadOnly() { internal.SetLogsState(internal.Logs(ms), internal.StateReadOnly) } + +func (ms Logs) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + dest.WriteObjectField("resourceLogs") + ms.ResourceLogs().marshalJSONStream(dest) + dest.WriteObjectEnd() +} + +func (ms Logs) unmarshalJsoniter(iter *jsoniter.Iterator) { + iter.ReadObjectCB(func(iter *jsoniter.Iterator, f string) bool { + switch f { + case "resource_logs", "resourceLogs": + iter.ReadArrayCB(func(*jsoniter.Iterator) bool { + ms.ResourceLogs().AppendEmpty().unmarshalJsoniter(iter) + return true + }) + default: + iter.Skip() + } + return true + }) +} diff --git a/pdata/plog/logs_test.go b/pdata/plog/logs_test.go index 84030862848..3cc40811520 100644 --- a/pdata/plog/logs_test.go +++ b/pdata/plog/logs_test.go @@ -172,3 +172,17 @@ func BenchmarkLogsUsage(b *testing.B) { } } } + +func BenchmarkLogsMarshalJSON(b *testing.B) { + md := NewLogs() + fillTestResourceLogsSlice(md.ResourceLogs()) + encoder := &JSONMarshaler{} + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + jsonBuf, err := encoder.MarshalLogs(md) + require.NoError(b, err) + require.NotNil(b, jsonBuf) + } +} diff --git a/pdata/plog/plogotlp/generated_exportpartialsuccess.go b/pdata/plog/plogotlp/generated_exportpartialsuccess.go index 411f37beabf..3b107135123 100644 --- a/pdata/plog/plogotlp/generated_exportpartialsuccess.go +++ b/pdata/plog/plogotlp/generated_exportpartialsuccess.go @@ -9,6 +9,7 @@ package plogotlp import ( "go.opentelemetry.io/collector/pdata/internal" otlpcollectorlog "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/logs/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // ExportPartialSuccess represents the details of a partially successful export request. @@ -77,6 +78,20 @@ func (ms ExportPartialSuccess) CopyTo(dest ExportPartialSuccess) { copyOrigExportPartialSuccess(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ExportPartialSuccess) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.RejectedLogRecords != int64(0) { + dest.WriteObjectField("rejectedLogRecords") + dest.WriteInt64(ms.orig.RejectedLogRecords) + } + if ms.orig.ErrorMessage != "" { + dest.WriteObjectField("errorMessage") + dest.WriteString(ms.orig.ErrorMessage) + } + dest.WriteObjectEnd() +} + func copyOrigExportPartialSuccess(dest, src *otlpcollectorlog.ExportLogsPartialSuccess) { dest.RejectedLogRecords = src.RejectedLogRecords dest.ErrorMessage = src.ErrorMessage diff --git a/pdata/plog/plogotlp/generated_exportpartialsuccess_test.go b/pdata/plog/plogotlp/generated_exportpartialsuccess_test.go index 0c63ec7ee9d..ad1da03c514 100644 --- a/pdata/plog/plogotlp/generated_exportpartialsuccess_test.go +++ b/pdata/plog/plogotlp/generated_exportpartialsuccess_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpcollectorlog "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/logs/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) func TestExportPartialSuccess_MoveTo(t *testing.T) { @@ -42,6 +43,20 @@ func TestExportPartialSuccess_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newExportPartialSuccess(&otlpcollectorlog.ExportLogsPartialSuccess{}, &sharedState)) }) } +func TestExportPartialSuccess_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestExportPartialSuccess() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewExportPartialSuccess() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestExportPartialSuccess_RejectedLogRecords(t *testing.T) { ms := NewExportPartialSuccess() assert.Equal(t, int64(0), ms.RejectedLogRecords()) diff --git a/pdata/plog/severity_number.go b/pdata/plog/severity_number.go index 53a9d4179c4..d460ed25118 100644 --- a/pdata/plog/severity_number.go +++ b/pdata/plog/severity_number.go @@ -5,6 +5,7 @@ package plog // import "go.opentelemetry.io/collector/pdata/plog" import ( otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // SeverityNumber represents severity number of a log record. @@ -94,3 +95,8 @@ func (sn SeverityNumber) String() string { } return "" } + +// MarshalJSONStream converts trace id into a hex string enclosed in quotes. +func (sn SeverityNumber) marshalJSONStream(dest *json.Stream) { + dest.WriteInt32(int32(sn)) +} diff --git a/pdata/pmetric/aggregation_temporality.go b/pdata/pmetric/aggregation_temporality.go index 0ba2b28c29b..5028136f4f9 100644 --- a/pdata/pmetric/aggregation_temporality.go +++ b/pdata/pmetric/aggregation_temporality.go @@ -5,6 +5,7 @@ package pmetric // import "go.opentelemetry.io/collector/pdata/pmetric" import ( otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // AggregationTemporality defines how a metric aggregator reports aggregated values. @@ -32,3 +33,8 @@ func (at AggregationTemporality) String() string { } return "" } + +// MarshalJSONStream converts trace id into a hex string enclosed in quotes. +func (at AggregationTemporality) marshalJSONStream(dest *json.Stream) { + dest.WriteInt32(int32(at)) +} diff --git a/pdata/pmetric/generated_exemplar.go b/pdata/pmetric/generated_exemplar.go index 49adf73364d..943d583b26e 100644 --- a/pdata/pmetric/generated_exemplar.go +++ b/pdata/pmetric/generated_exemplar.go @@ -10,6 +10,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" "go.opentelemetry.io/collector/pdata/internal/data" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -136,6 +137,36 @@ func (ms Exemplar) CopyTo(dest Exemplar) { copyOrigExemplar(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms Exemplar) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.TimeUnixNano != 0 { + dest.WriteObjectField("timeUnixNano") + dest.WriteUint64(ms.orig.TimeUnixNano) + } + switch ov := ms.orig.Value.(type) { + case *otlpmetrics.Exemplar_AsDouble: + dest.WriteObjectField("asDouble") + dest.WriteFloat64(ov.AsDouble) + case *otlpmetrics.Exemplar_AsInt: + dest.WriteObjectField("asInt") + dest.WriteInt64(ov.AsInt) + } + if len(ms.orig.FilteredAttributes) > 0 { + dest.WriteObjectField("filteredAttributes") + internal.MarshalJSONStreamMap(internal.NewMap(&ms.orig.FilteredAttributes, ms.state), dest) + } + if ms.orig.TraceId != data.TraceID([16]byte{}) { + dest.WriteObjectField("traceId") + ms.orig.TraceId.MarshalJSONStream(dest) + } + if ms.orig.SpanId != data.SpanID([8]byte{}) { + dest.WriteObjectField("spanId") + ms.orig.SpanId.MarshalJSONStream(dest) + } + dest.WriteObjectEnd() +} + func copyOrigExemplar(dest, src *otlpmetrics.Exemplar) { dest.TimeUnixNano = src.TimeUnixNano switch t := src.Value.(type) { diff --git a/pdata/pmetric/generated_exemplar_test.go b/pdata/pmetric/generated_exemplar_test.go index 95762bef595..d35bd79b775 100644 --- a/pdata/pmetric/generated_exemplar_test.go +++ b/pdata/pmetric/generated_exemplar_test.go @@ -14,6 +14,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" "go.opentelemetry.io/collector/pdata/internal/data" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -42,6 +43,20 @@ func TestExemplar_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newExemplar(&otlpmetrics.Exemplar{}, &sharedState)) }) } +func TestExemplar_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestExemplar() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewExemplar() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestExemplar_Timestamp(t *testing.T) { ms := NewExemplar() assert.Equal(t, pcommon.Timestamp(0), ms.Timestamp()) diff --git a/pdata/pmetric/generated_exemplarslice.go b/pdata/pmetric/generated_exemplarslice.go index 95aa92aa42c..e90e36ae568 100644 --- a/pdata/pmetric/generated_exemplarslice.go +++ b/pdata/pmetric/generated_exemplarslice.go @@ -11,6 +11,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // ExemplarSlice logically represents a slice of Exemplar. @@ -147,6 +148,19 @@ func (es ExemplarSlice) CopyTo(dest ExemplarSlice) { *dest.orig = copyOrigExemplarSlice(*dest.orig, *es.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ExemplarSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigExemplarSlice(dest, src []otlpmetrics.Exemplar) []otlpmetrics.Exemplar { if cap(dest) < len(src) { dest = make([]otlpmetrics.Exemplar, len(src)) diff --git a/pdata/pmetric/generated_exponentialhistogram.go b/pdata/pmetric/generated_exponentialhistogram.go index 2ffec30b7a7..227519bf004 100644 --- a/pdata/pmetric/generated_exponentialhistogram.go +++ b/pdata/pmetric/generated_exponentialhistogram.go @@ -9,6 +9,7 @@ package pmetric import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // ExponentialHistogram represents the type of a metric that is calculated by aggregating @@ -72,6 +73,20 @@ func (ms ExponentialHistogram) CopyTo(dest ExponentialHistogram) { copyOrigExponentialHistogram(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ExponentialHistogram) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.AggregationTemporality != otlpmetrics.AggregationTemporality(0) { + dest.WriteObjectField("aggregationTemporality") + ms.AggregationTemporality().marshalJSONStream(dest) + } + if len(ms.orig.DataPoints) > 0 { + dest.WriteObjectField("dataPoints") + ms.DataPoints().marshalJSONStream(dest) + } + dest.WriteObjectEnd() +} + func copyOrigExponentialHistogram(dest, src *otlpmetrics.ExponentialHistogram) { dest.AggregationTemporality = src.AggregationTemporality dest.DataPoints = copyOrigExponentialHistogramDataPointSlice(dest.DataPoints, src.DataPoints) diff --git a/pdata/pmetric/generated_exponentialhistogram_test.go b/pdata/pmetric/generated_exponentialhistogram_test.go index 09c15e25edc..5d02919ab68 100644 --- a/pdata/pmetric/generated_exponentialhistogram_test.go +++ b/pdata/pmetric/generated_exponentialhistogram_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) func TestExponentialHistogram_MoveTo(t *testing.T) { @@ -40,6 +41,20 @@ func TestExponentialHistogram_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newExponentialHistogram(&otlpmetrics.ExponentialHistogram{}, &sharedState)) }) } +func TestExponentialHistogram_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestExponentialHistogram() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewExponentialHistogram() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestExponentialHistogram_AggregationTemporality(t *testing.T) { ms := NewExponentialHistogram() assert.Equal(t, AggregationTemporality(otlpmetrics.AggregationTemporality(0)), ms.AggregationTemporality()) diff --git a/pdata/pmetric/generated_exponentialhistogramdatapoint.go b/pdata/pmetric/generated_exponentialhistogramdatapoint.go index 8b2ebd92111..69297952085 100644 --- a/pdata/pmetric/generated_exponentialhistogramdatapoint.go +++ b/pdata/pmetric/generated_exponentialhistogramdatapoint.go @@ -9,6 +9,7 @@ package pmetric import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -225,6 +226,64 @@ func (ms ExponentialHistogramDataPoint) CopyTo(dest ExponentialHistogramDataPoin copyOrigExponentialHistogramDataPoint(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ExponentialHistogramDataPoint) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if len(ms.orig.Attributes) > 0 { + dest.WriteObjectField("attributes") + internal.MarshalJSONStreamMap(internal.NewMap(&ms.orig.Attributes, ms.state), dest) + } + if ms.orig.StartTimeUnixNano != 0 { + dest.WriteObjectField("startTimeUnixNano") + dest.WriteUint64(ms.orig.StartTimeUnixNano) + } + if ms.orig.TimeUnixNano != 0 { + dest.WriteObjectField("timeUnixNano") + dest.WriteUint64(ms.orig.TimeUnixNano) + } + if ms.orig.Count != uint64(0) { + dest.WriteObjectField("count") + dest.WriteUint64(ms.orig.Count) + } + if ms.orig.Scale != int32(0) { + dest.WriteObjectField("scale") + dest.WriteInt32(ms.orig.Scale) + } + if ms.orig.ZeroCount != uint64(0) { + dest.WriteObjectField("zeroCount") + dest.WriteUint64(ms.orig.ZeroCount) + } + dest.WriteObjectField("positive") + ms.Positive().marshalJSONStream(dest) + dest.WriteObjectField("negative") + ms.Negative().marshalJSONStream(dest) + if len(ms.orig.Exemplars) > 0 { + dest.WriteObjectField("exemplars") + ms.Exemplars().marshalJSONStream(dest) + } + if ms.orig.Flags != 0 { + dest.WriteObjectField("flags") + dest.WriteUint32(ms.orig.Flags) + } + if ms.HasSum() { + dest.WriteObjectField("sum") + dest.WriteFloat64(ms.Sum()) + } + if ms.HasMin() { + dest.WriteObjectField("min") + dest.WriteFloat64(ms.Min()) + } + if ms.HasMax() { + dest.WriteObjectField("max") + dest.WriteFloat64(ms.Max()) + } + if ms.orig.ZeroThreshold != float64(0.0) { + dest.WriteObjectField("zeroThreshold") + dest.WriteFloat64(ms.orig.ZeroThreshold) + } + dest.WriteObjectEnd() +} + func copyOrigExponentialHistogramDataPoint(dest, src *otlpmetrics.ExponentialHistogramDataPoint) { dest.Attributes = internal.CopyOrigMap(dest.Attributes, src.Attributes) dest.StartTimeUnixNano = src.StartTimeUnixNano diff --git a/pdata/pmetric/generated_exponentialhistogramdatapoint_test.go b/pdata/pmetric/generated_exponentialhistogramdatapoint_test.go index 3001a2c548a..ef539f4e48f 100644 --- a/pdata/pmetric/generated_exponentialhistogramdatapoint_test.go +++ b/pdata/pmetric/generated_exponentialhistogramdatapoint_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -47,6 +48,20 @@ func TestExponentialHistogramDataPoint_CopyTo(t *testing.T) { }) } +func TestExponentialHistogramDataPoint_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestExponentialHistogramDataPoint() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewExponentialHistogramDataPoint() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestExponentialHistogramDataPoint_Attributes(t *testing.T) { ms := NewExponentialHistogramDataPoint() assert.Equal(t, pcommon.NewMap(), ms.Attributes()) diff --git a/pdata/pmetric/generated_exponentialhistogramdatapointbuckets.go b/pdata/pmetric/generated_exponentialhistogramdatapointbuckets.go index ee978970546..eb65664cf67 100644 --- a/pdata/pmetric/generated_exponentialhistogramdatapointbuckets.go +++ b/pdata/pmetric/generated_exponentialhistogramdatapointbuckets.go @@ -9,6 +9,7 @@ package pmetric import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -72,6 +73,18 @@ func (ms ExponentialHistogramDataPointBuckets) CopyTo(dest ExponentialHistogramD copyOrigExponentialHistogramDataPointBuckets(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ExponentialHistogramDataPointBuckets) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.Offset != int32(0) { + dest.WriteObjectField("offset") + dest.WriteInt32(ms.orig.Offset) + } + dest.WriteObjectField("bucketCounts") + internal.MarshalJSONStreamUInt64Slice(internal.NewUInt64Slice(&ms.orig.BucketCounts, ms.state), dest) + dest.WriteObjectEnd() +} + func copyOrigExponentialHistogramDataPointBuckets(dest, src *otlpmetrics.ExponentialHistogramDataPoint_Buckets) { dest.Offset = src.Offset dest.BucketCounts = internal.CopyOrigUInt64Slice(dest.BucketCounts, src.BucketCounts) diff --git a/pdata/pmetric/generated_exponentialhistogramdatapointbuckets_test.go b/pdata/pmetric/generated_exponentialhistogramdatapointbuckets_test.go index 30484b93d48..239de726f6d 100644 --- a/pdata/pmetric/generated_exponentialhistogramdatapointbuckets_test.go +++ b/pdata/pmetric/generated_exponentialhistogramdatapointbuckets_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) func TestExponentialHistogramDataPointBuckets_MoveTo(t *testing.T) { @@ -46,6 +47,20 @@ func TestExponentialHistogramDataPointBuckets_CopyTo(t *testing.T) { }) } +func TestExponentialHistogramDataPointBuckets_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestExponentialHistogramDataPointBuckets() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewExponentialHistogramDataPointBuckets() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestExponentialHistogramDataPointBuckets_Offset(t *testing.T) { ms := NewExponentialHistogramDataPointBuckets() assert.Equal(t, int32(0), ms.Offset()) diff --git a/pdata/pmetric/generated_exponentialhistogramdatapointslice.go b/pdata/pmetric/generated_exponentialhistogramdatapointslice.go index 6bfdd78284b..f5f84149036 100644 --- a/pdata/pmetric/generated_exponentialhistogramdatapointslice.go +++ b/pdata/pmetric/generated_exponentialhistogramdatapointslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // ExponentialHistogramDataPointSlice logically represents a slice of ExponentialHistogramDataPoint. @@ -156,6 +157,19 @@ func (es ExponentialHistogramDataPointSlice) Sort(less func(a, b ExponentialHist sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ExponentialHistogramDataPointSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigExponentialHistogramDataPointSlice(dest, src []*otlpmetrics.ExponentialHistogramDataPoint) []*otlpmetrics.ExponentialHistogramDataPoint { if cap(dest) < len(src) { dest = make([]*otlpmetrics.ExponentialHistogramDataPoint, len(src)) diff --git a/pdata/pmetric/generated_gauge.go b/pdata/pmetric/generated_gauge.go index 39a5da03007..433cb5d8386 100644 --- a/pdata/pmetric/generated_gauge.go +++ b/pdata/pmetric/generated_gauge.go @@ -9,6 +9,7 @@ package pmetric import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // Gauge represents the type of a numeric metric that always exports the "current value" for every data point. @@ -60,6 +61,16 @@ func (ms Gauge) CopyTo(dest Gauge) { copyOrigGauge(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms Gauge) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if len(ms.orig.DataPoints) > 0 { + dest.WriteObjectField("dataPoints") + ms.DataPoints().marshalJSONStream(dest) + } + dest.WriteObjectEnd() +} + func copyOrigGauge(dest, src *otlpmetrics.Gauge) { dest.DataPoints = copyOrigNumberDataPointSlice(dest.DataPoints, src.DataPoints) } diff --git a/pdata/pmetric/generated_gauge_test.go b/pdata/pmetric/generated_gauge_test.go index e6fb594ca63..0384e7a38de 100644 --- a/pdata/pmetric/generated_gauge_test.go +++ b/pdata/pmetric/generated_gauge_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) func TestGauge_MoveTo(t *testing.T) { @@ -40,6 +41,20 @@ func TestGauge_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newGauge(&otlpmetrics.Gauge{}, &sharedState)) }) } +func TestGauge_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestGauge() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewGauge() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestGauge_DataPoints(t *testing.T) { ms := NewGauge() assert.Equal(t, NewNumberDataPointSlice(), ms.DataPoints()) diff --git a/pdata/pmetric/generated_histogram.go b/pdata/pmetric/generated_histogram.go index 33d6626ff01..67b20c7f74f 100644 --- a/pdata/pmetric/generated_histogram.go +++ b/pdata/pmetric/generated_histogram.go @@ -9,6 +9,7 @@ package pmetric import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // Histogram represents the type of a metric that is calculated by aggregating as a Histogram of all reported measurements over a time interval. @@ -71,6 +72,20 @@ func (ms Histogram) CopyTo(dest Histogram) { copyOrigHistogram(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms Histogram) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.AggregationTemporality != otlpmetrics.AggregationTemporality(0) { + dest.WriteObjectField("aggregationTemporality") + ms.AggregationTemporality().marshalJSONStream(dest) + } + if len(ms.orig.DataPoints) > 0 { + dest.WriteObjectField("dataPoints") + ms.DataPoints().marshalJSONStream(dest) + } + dest.WriteObjectEnd() +} + func copyOrigHistogram(dest, src *otlpmetrics.Histogram) { dest.AggregationTemporality = src.AggregationTemporality dest.DataPoints = copyOrigHistogramDataPointSlice(dest.DataPoints, src.DataPoints) diff --git a/pdata/pmetric/generated_histogram_test.go b/pdata/pmetric/generated_histogram_test.go index 3188ee939ce..ab0c8c2f4ac 100644 --- a/pdata/pmetric/generated_histogram_test.go +++ b/pdata/pmetric/generated_histogram_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) func TestHistogram_MoveTo(t *testing.T) { @@ -40,6 +41,20 @@ func TestHistogram_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newHistogram(&otlpmetrics.Histogram{}, &sharedState)) }) } +func TestHistogram_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestHistogram() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewHistogram() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestHistogram_AggregationTemporality(t *testing.T) { ms := NewHistogram() assert.Equal(t, AggregationTemporality(otlpmetrics.AggregationTemporality(0)), ms.AggregationTemporality()) diff --git a/pdata/pmetric/generated_histogramdatapoint.go b/pdata/pmetric/generated_histogramdatapoint.go index c3c0fccbed5..e6d52cc0fae 100644 --- a/pdata/pmetric/generated_histogramdatapoint.go +++ b/pdata/pmetric/generated_histogramdatapoint.go @@ -9,6 +9,7 @@ package pmetric import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -189,6 +190,52 @@ func (ms HistogramDataPoint) CopyTo(dest HistogramDataPoint) { copyOrigHistogramDataPoint(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms HistogramDataPoint) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if len(ms.orig.Attributes) > 0 { + dest.WriteObjectField("attributes") + internal.MarshalJSONStreamMap(internal.NewMap(&ms.orig.Attributes, ms.state), dest) + } + if ms.orig.StartTimeUnixNano != 0 { + dest.WriteObjectField("startTimeUnixNano") + dest.WriteUint64(ms.orig.StartTimeUnixNano) + } + if ms.orig.TimeUnixNano != 0 { + dest.WriteObjectField("timeUnixNano") + dest.WriteUint64(ms.orig.TimeUnixNano) + } + if ms.orig.Count != uint64(0) { + dest.WriteObjectField("count") + dest.WriteUint64(ms.orig.Count) + } + dest.WriteObjectField("bucketCounts") + internal.MarshalJSONStreamUInt64Slice(internal.NewUInt64Slice(&ms.orig.BucketCounts, ms.state), dest) + dest.WriteObjectField("explicitBounds") + internal.MarshalJSONStreamFloat64Slice(internal.NewFloat64Slice(&ms.orig.ExplicitBounds, ms.state), dest) + if len(ms.orig.Exemplars) > 0 { + dest.WriteObjectField("exemplars") + ms.Exemplars().marshalJSONStream(dest) + } + if ms.orig.Flags != 0 { + dest.WriteObjectField("flags") + dest.WriteUint32(ms.orig.Flags) + } + if ms.HasSum() { + dest.WriteObjectField("sum") + dest.WriteFloat64(ms.Sum()) + } + if ms.HasMin() { + dest.WriteObjectField("min") + dest.WriteFloat64(ms.Min()) + } + if ms.HasMax() { + dest.WriteObjectField("max") + dest.WriteFloat64(ms.Max()) + } + dest.WriteObjectEnd() +} + func copyOrigHistogramDataPoint(dest, src *otlpmetrics.HistogramDataPoint) { dest.Attributes = internal.CopyOrigMap(dest.Attributes, src.Attributes) dest.StartTimeUnixNano = src.StartTimeUnixNano diff --git a/pdata/pmetric/generated_histogramdatapoint_test.go b/pdata/pmetric/generated_histogramdatapoint_test.go index c4d12258d5d..019e99bc971 100644 --- a/pdata/pmetric/generated_histogramdatapoint_test.go +++ b/pdata/pmetric/generated_histogramdatapoint_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -41,6 +42,20 @@ func TestHistogramDataPoint_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newHistogramDataPoint(&otlpmetrics.HistogramDataPoint{}, &sharedState)) }) } +func TestHistogramDataPoint_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestHistogramDataPoint() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewHistogramDataPoint() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestHistogramDataPoint_Attributes(t *testing.T) { ms := NewHistogramDataPoint() assert.Equal(t, pcommon.NewMap(), ms.Attributes()) diff --git a/pdata/pmetric/generated_histogramdatapointslice.go b/pdata/pmetric/generated_histogramdatapointslice.go index d89b718a757..0645a020aa2 100644 --- a/pdata/pmetric/generated_histogramdatapointslice.go +++ b/pdata/pmetric/generated_histogramdatapointslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // HistogramDataPointSlice logically represents a slice of HistogramDataPoint. @@ -156,6 +157,19 @@ func (es HistogramDataPointSlice) Sort(less func(a, b HistogramDataPoint) bool) sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms HistogramDataPointSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigHistogramDataPointSlice(dest, src []*otlpmetrics.HistogramDataPoint) []*otlpmetrics.HistogramDataPoint { if cap(dest) < len(src) { dest = make([]*otlpmetrics.HistogramDataPoint, len(src)) diff --git a/pdata/pmetric/generated_metric.go b/pdata/pmetric/generated_metric.go index 6aea2fd4abe..6002a76b9f0 100644 --- a/pdata/pmetric/generated_metric.go +++ b/pdata/pmetric/generated_metric.go @@ -9,6 +9,7 @@ package pmetric import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -243,6 +244,45 @@ func (ms Metric) CopyTo(dest Metric) { copyOrigMetric(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms Metric) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.Name != "" { + dest.WriteObjectField("name") + dest.WriteString(ms.orig.Name) + } + if ms.orig.Description != "" { + dest.WriteObjectField("description") + dest.WriteString(ms.orig.Description) + } + if ms.orig.Unit != "" { + dest.WriteObjectField("unit") + dest.WriteString(ms.orig.Unit) + } + if len(ms.orig.Metadata) > 0 { + dest.WriteObjectField("metadata") + internal.MarshalJSONStreamMap(internal.NewMap(&ms.orig.Metadata, ms.state), dest) + } + switch ov := ms.orig.Data.(type) { + case *otlpmetrics.Metric_Gauge: + dest.WriteObjectField("gauge") + newGauge(ov.Gauge, ms.state).marshalJSONStream(dest) + case *otlpmetrics.Metric_Sum: + dest.WriteObjectField("sum") + newSum(ov.Sum, ms.state).marshalJSONStream(dest) + case *otlpmetrics.Metric_Histogram: + dest.WriteObjectField("histogram") + newHistogram(ov.Histogram, ms.state).marshalJSONStream(dest) + case *otlpmetrics.Metric_ExponentialHistogram: + dest.WriteObjectField("exponentialHistogram") + newExponentialHistogram(ov.ExponentialHistogram, ms.state).marshalJSONStream(dest) + case *otlpmetrics.Metric_Summary: + dest.WriteObjectField("summary") + newSummary(ov.Summary, ms.state).marshalJSONStream(dest) + } + dest.WriteObjectEnd() +} + func copyOrigMetric(dest, src *otlpmetrics.Metric) { dest.Name = src.Name dest.Description = src.Description diff --git a/pdata/pmetric/generated_metric_test.go b/pdata/pmetric/generated_metric_test.go index d0353818b4a..434c291c3fe 100644 --- a/pdata/pmetric/generated_metric_test.go +++ b/pdata/pmetric/generated_metric_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -41,6 +42,20 @@ func TestMetric_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newMetric(&otlpmetrics.Metric{}, &sharedState)) }) } +func TestMetric_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestMetric() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewMetric() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestMetric_Name(t *testing.T) { ms := NewMetric() assert.Empty(t, ms.Name()) diff --git a/pdata/pmetric/generated_metricslice.go b/pdata/pmetric/generated_metricslice.go index 07874f1ab4a..625d81141eb 100644 --- a/pdata/pmetric/generated_metricslice.go +++ b/pdata/pmetric/generated_metricslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // MetricSlice logically represents a slice of Metric. @@ -156,6 +157,19 @@ func (es MetricSlice) Sort(less func(a, b Metric) bool) { sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms MetricSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigMetricSlice(dest, src []*otlpmetrics.Metric) []*otlpmetrics.Metric { if cap(dest) < len(src) { dest = make([]*otlpmetrics.Metric, len(src)) diff --git a/pdata/pmetric/generated_numberdatapoint.go b/pdata/pmetric/generated_numberdatapoint.go index ba179f27921..1e1c12f7482 100644 --- a/pdata/pmetric/generated_numberdatapoint.go +++ b/pdata/pmetric/generated_numberdatapoint.go @@ -9,6 +9,7 @@ package pmetric import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -137,6 +138,40 @@ func (ms NumberDataPoint) CopyTo(dest NumberDataPoint) { copyOrigNumberDataPoint(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms NumberDataPoint) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if len(ms.orig.Attributes) > 0 { + dest.WriteObjectField("attributes") + internal.MarshalJSONStreamMap(internal.NewMap(&ms.orig.Attributes, ms.state), dest) + } + if ms.orig.StartTimeUnixNano != 0 { + dest.WriteObjectField("startTimeUnixNano") + dest.WriteUint64(ms.orig.StartTimeUnixNano) + } + if ms.orig.TimeUnixNano != 0 { + dest.WriteObjectField("timeUnixNano") + dest.WriteUint64(ms.orig.TimeUnixNano) + } + switch ov := ms.orig.Value.(type) { + case *otlpmetrics.NumberDataPoint_AsDouble: + dest.WriteObjectField("asDouble") + dest.WriteFloat64(ov.AsDouble) + case *otlpmetrics.NumberDataPoint_AsInt: + dest.WriteObjectField("asInt") + dest.WriteInt64(ov.AsInt) + } + if len(ms.orig.Exemplars) > 0 { + dest.WriteObjectField("exemplars") + ms.Exemplars().marshalJSONStream(dest) + } + if ms.orig.Flags != 0 { + dest.WriteObjectField("flags") + dest.WriteUint32(ms.orig.Flags) + } + dest.WriteObjectEnd() +} + func copyOrigNumberDataPoint(dest, src *otlpmetrics.NumberDataPoint) { dest.Attributes = internal.CopyOrigMap(dest.Attributes, src.Attributes) dest.StartTimeUnixNano = src.StartTimeUnixNano diff --git a/pdata/pmetric/generated_numberdatapoint_test.go b/pdata/pmetric/generated_numberdatapoint_test.go index 31cac65ab14..b61d0be2489 100644 --- a/pdata/pmetric/generated_numberdatapoint_test.go +++ b/pdata/pmetric/generated_numberdatapoint_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -41,6 +42,20 @@ func TestNumberDataPoint_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newNumberDataPoint(&otlpmetrics.NumberDataPoint{}, &sharedState)) }) } +func TestNumberDataPoint_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestNumberDataPoint() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewNumberDataPoint() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestNumberDataPoint_Attributes(t *testing.T) { ms := NewNumberDataPoint() assert.Equal(t, pcommon.NewMap(), ms.Attributes()) diff --git a/pdata/pmetric/generated_numberdatapointslice.go b/pdata/pmetric/generated_numberdatapointslice.go index fe136608bcf..807f788122b 100644 --- a/pdata/pmetric/generated_numberdatapointslice.go +++ b/pdata/pmetric/generated_numberdatapointslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // NumberDataPointSlice logically represents a slice of NumberDataPoint. @@ -156,6 +157,19 @@ func (es NumberDataPointSlice) Sort(less func(a, b NumberDataPoint) bool) { sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms NumberDataPointSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigNumberDataPointSlice(dest, src []*otlpmetrics.NumberDataPoint) []*otlpmetrics.NumberDataPoint { if cap(dest) < len(src) { dest = make([]*otlpmetrics.NumberDataPoint, len(src)) diff --git a/pdata/pmetric/generated_resourcemetrics.go b/pdata/pmetric/generated_resourcemetrics.go index b08292a518e..eb6ec271774 100644 --- a/pdata/pmetric/generated_resourcemetrics.go +++ b/pdata/pmetric/generated_resourcemetrics.go @@ -9,6 +9,7 @@ package pmetric import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -77,6 +78,22 @@ func (ms ResourceMetrics) CopyTo(dest ResourceMetrics) { copyOrigResourceMetrics(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ResourceMetrics) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + dest.WriteObjectField("resource") + internal.MarshalJSONStreamResource(internal.NewResource(&ms.orig.Resource, ms.state), dest) + if ms.orig.SchemaUrl != "" { + dest.WriteObjectField("schemaUrl") + dest.WriteString(ms.orig.SchemaUrl) + } + if len(ms.orig.ScopeMetrics) > 0 { + dest.WriteObjectField("scopeMetrics") + ms.ScopeMetrics().marshalJSONStream(dest) + } + dest.WriteObjectEnd() +} + func copyOrigResourceMetrics(dest, src *otlpmetrics.ResourceMetrics) { internal.CopyOrigResource(&dest.Resource, &src.Resource) dest.SchemaUrl = src.SchemaUrl diff --git a/pdata/pmetric/generated_resourcemetrics_test.go b/pdata/pmetric/generated_resourcemetrics_test.go index 594a86b1222..1aaf5f825b6 100644 --- a/pdata/pmetric/generated_resourcemetrics_test.go +++ b/pdata/pmetric/generated_resourcemetrics_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -41,6 +42,20 @@ func TestResourceMetrics_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newResourceMetrics(&otlpmetrics.ResourceMetrics{}, &sharedState)) }) } +func TestResourceMetrics_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestResourceMetrics() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewResourceMetrics() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestResourceMetrics_Resource(t *testing.T) { ms := NewResourceMetrics() internal.FillTestResource(internal.Resource(ms.Resource())) diff --git a/pdata/pmetric/generated_resourcemetricsslice.go b/pdata/pmetric/generated_resourcemetricsslice.go index c443a0034a9..0697b2e50c2 100644 --- a/pdata/pmetric/generated_resourcemetricsslice.go +++ b/pdata/pmetric/generated_resourcemetricsslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // ResourceMetricsSlice logically represents a slice of ResourceMetrics. @@ -156,6 +157,19 @@ func (es ResourceMetricsSlice) Sort(less func(a, b ResourceMetrics) bool) { sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ResourceMetricsSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigResourceMetricsSlice(dest, src []*otlpmetrics.ResourceMetrics) []*otlpmetrics.ResourceMetrics { if cap(dest) < len(src) { dest = make([]*otlpmetrics.ResourceMetrics, len(src)) diff --git a/pdata/pmetric/generated_scopemetrics.go b/pdata/pmetric/generated_scopemetrics.go index 46fab01c934..f503fe48dff 100644 --- a/pdata/pmetric/generated_scopemetrics.go +++ b/pdata/pmetric/generated_scopemetrics.go @@ -9,6 +9,7 @@ package pmetric import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -77,6 +78,22 @@ func (ms ScopeMetrics) CopyTo(dest ScopeMetrics) { copyOrigScopeMetrics(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ScopeMetrics) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + dest.WriteObjectField("scope") + internal.MarshalJSONStreamInstrumentationScope(internal.NewInstrumentationScope(&ms.orig.Scope, ms.state), dest) + if ms.orig.SchemaUrl != "" { + dest.WriteObjectField("schemaUrl") + dest.WriteString(ms.orig.SchemaUrl) + } + if len(ms.orig.Metrics) > 0 { + dest.WriteObjectField("metrics") + ms.Metrics().marshalJSONStream(dest) + } + dest.WriteObjectEnd() +} + func copyOrigScopeMetrics(dest, src *otlpmetrics.ScopeMetrics) { internal.CopyOrigInstrumentationScope(&dest.Scope, &src.Scope) dest.SchemaUrl = src.SchemaUrl diff --git a/pdata/pmetric/generated_scopemetrics_test.go b/pdata/pmetric/generated_scopemetrics_test.go index 064fe804c13..532580407a6 100644 --- a/pdata/pmetric/generated_scopemetrics_test.go +++ b/pdata/pmetric/generated_scopemetrics_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -41,6 +42,20 @@ func TestScopeMetrics_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newScopeMetrics(&otlpmetrics.ScopeMetrics{}, &sharedState)) }) } +func TestScopeMetrics_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestScopeMetrics() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewScopeMetrics() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestScopeMetrics_Scope(t *testing.T) { ms := NewScopeMetrics() internal.FillTestInstrumentationScope(internal.InstrumentationScope(ms.Scope())) diff --git a/pdata/pmetric/generated_scopemetricsslice.go b/pdata/pmetric/generated_scopemetricsslice.go index 27bda1484ab..c4a0112a431 100644 --- a/pdata/pmetric/generated_scopemetricsslice.go +++ b/pdata/pmetric/generated_scopemetricsslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // ScopeMetricsSlice logically represents a slice of ScopeMetrics. @@ -156,6 +157,19 @@ func (es ScopeMetricsSlice) Sort(less func(a, b ScopeMetrics) bool) { sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ScopeMetricsSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigScopeMetricsSlice(dest, src []*otlpmetrics.ScopeMetrics) []*otlpmetrics.ScopeMetrics { if cap(dest) < len(src) { dest = make([]*otlpmetrics.ScopeMetrics, len(src)) diff --git a/pdata/pmetric/generated_sum.go b/pdata/pmetric/generated_sum.go index 382ea7a7e51..e8c3155f507 100644 --- a/pdata/pmetric/generated_sum.go +++ b/pdata/pmetric/generated_sum.go @@ -9,6 +9,7 @@ package pmetric import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // Sum represents the type of a numeric metric that is calculated as a sum of all reported measurements over a time interval. @@ -82,6 +83,24 @@ func (ms Sum) CopyTo(dest Sum) { copyOrigSum(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms Sum) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.AggregationTemporality != otlpmetrics.AggregationTemporality(0) { + dest.WriteObjectField("aggregationTemporality") + ms.AggregationTemporality().marshalJSONStream(dest) + } + if ms.orig.IsMonotonic != false { + dest.WriteObjectField("isMonotonic") + dest.WriteBool(ms.orig.IsMonotonic) + } + if len(ms.orig.DataPoints) > 0 { + dest.WriteObjectField("dataPoints") + ms.DataPoints().marshalJSONStream(dest) + } + dest.WriteObjectEnd() +} + func copyOrigSum(dest, src *otlpmetrics.Sum) { dest.AggregationTemporality = src.AggregationTemporality dest.IsMonotonic = src.IsMonotonic diff --git a/pdata/pmetric/generated_sum_test.go b/pdata/pmetric/generated_sum_test.go index 2636f9cc755..3cc421886f0 100644 --- a/pdata/pmetric/generated_sum_test.go +++ b/pdata/pmetric/generated_sum_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) func TestSum_MoveTo(t *testing.T) { @@ -40,6 +41,20 @@ func TestSum_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newSum(&otlpmetrics.Sum{}, &sharedState)) }) } +func TestSum_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestSum() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewSum() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestSum_AggregationTemporality(t *testing.T) { ms := NewSum() assert.Equal(t, AggregationTemporality(otlpmetrics.AggregationTemporality(0)), ms.AggregationTemporality()) diff --git a/pdata/pmetric/generated_summary.go b/pdata/pmetric/generated_summary.go index 10e7fe4022b..01534f2170b 100644 --- a/pdata/pmetric/generated_summary.go +++ b/pdata/pmetric/generated_summary.go @@ -9,6 +9,7 @@ package pmetric import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // Summary represents the type of a metric that is calculated by aggregating as a Summary of all reported double measurements over a time interval. @@ -60,6 +61,16 @@ func (ms Summary) CopyTo(dest Summary) { copyOrigSummary(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms Summary) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if len(ms.orig.DataPoints) > 0 { + dest.WriteObjectField("dataPoints") + ms.DataPoints().marshalJSONStream(dest) + } + dest.WriteObjectEnd() +} + func copyOrigSummary(dest, src *otlpmetrics.Summary) { dest.DataPoints = copyOrigSummaryDataPointSlice(dest.DataPoints, src.DataPoints) } diff --git a/pdata/pmetric/generated_summary_test.go b/pdata/pmetric/generated_summary_test.go index 0b63fdc3362..7a55689ddea 100644 --- a/pdata/pmetric/generated_summary_test.go +++ b/pdata/pmetric/generated_summary_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) func TestSummary_MoveTo(t *testing.T) { @@ -40,6 +41,20 @@ func TestSummary_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newSummary(&otlpmetrics.Summary{}, &sharedState)) }) } +func TestSummary_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestSummary() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewSummary() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestSummary_DataPoints(t *testing.T) { ms := NewSummary() assert.Equal(t, NewSummaryDataPointSlice(), ms.DataPoints()) diff --git a/pdata/pmetric/generated_summarydatapoint.go b/pdata/pmetric/generated_summarydatapoint.go index 30cb8ba2244..968c415065e 100644 --- a/pdata/pmetric/generated_summarydatapoint.go +++ b/pdata/pmetric/generated_summarydatapoint.go @@ -9,6 +9,7 @@ package pmetric import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -121,6 +122,40 @@ func (ms SummaryDataPoint) CopyTo(dest SummaryDataPoint) { copyOrigSummaryDataPoint(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms SummaryDataPoint) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if len(ms.orig.Attributes) > 0 { + dest.WriteObjectField("attributes") + internal.MarshalJSONStreamMap(internal.NewMap(&ms.orig.Attributes, ms.state), dest) + } + if ms.orig.StartTimeUnixNano != 0 { + dest.WriteObjectField("startTimeUnixNano") + dest.WriteUint64(ms.orig.StartTimeUnixNano) + } + if ms.orig.TimeUnixNano != 0 { + dest.WriteObjectField("timeUnixNano") + dest.WriteUint64(ms.orig.TimeUnixNano) + } + if ms.orig.Count != uint64(0) { + dest.WriteObjectField("count") + dest.WriteUint64(ms.orig.Count) + } + if ms.orig.Sum != float64(0.0) { + dest.WriteObjectField("sum") + dest.WriteFloat64(ms.orig.Sum) + } + if len(ms.orig.QuantileValues) > 0 { + dest.WriteObjectField("quantileValues") + ms.QuantileValues().marshalJSONStream(dest) + } + if ms.orig.Flags != 0 { + dest.WriteObjectField("flags") + dest.WriteUint32(ms.orig.Flags) + } + dest.WriteObjectEnd() +} + func copyOrigSummaryDataPoint(dest, src *otlpmetrics.SummaryDataPoint) { dest.Attributes = internal.CopyOrigMap(dest.Attributes, src.Attributes) dest.StartTimeUnixNano = src.StartTimeUnixNano diff --git a/pdata/pmetric/generated_summarydatapoint_test.go b/pdata/pmetric/generated_summarydatapoint_test.go index 36112018149..7d9b6dd09f5 100644 --- a/pdata/pmetric/generated_summarydatapoint_test.go +++ b/pdata/pmetric/generated_summarydatapoint_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -41,6 +42,20 @@ func TestSummaryDataPoint_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newSummaryDataPoint(&otlpmetrics.SummaryDataPoint{}, &sharedState)) }) } +func TestSummaryDataPoint_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestSummaryDataPoint() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewSummaryDataPoint() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestSummaryDataPoint_Attributes(t *testing.T) { ms := NewSummaryDataPoint() assert.Equal(t, pcommon.NewMap(), ms.Attributes()) diff --git a/pdata/pmetric/generated_summarydatapointslice.go b/pdata/pmetric/generated_summarydatapointslice.go index 6afab24159f..64503ee4ae1 100644 --- a/pdata/pmetric/generated_summarydatapointslice.go +++ b/pdata/pmetric/generated_summarydatapointslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // SummaryDataPointSlice logically represents a slice of SummaryDataPoint. @@ -156,6 +157,19 @@ func (es SummaryDataPointSlice) Sort(less func(a, b SummaryDataPoint) bool) { sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms SummaryDataPointSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigSummaryDataPointSlice(dest, src []*otlpmetrics.SummaryDataPoint) []*otlpmetrics.SummaryDataPoint { if cap(dest) < len(src) { dest = make([]*otlpmetrics.SummaryDataPoint, len(src)) diff --git a/pdata/pmetric/generated_summarydatapointvalueatquantile.go b/pdata/pmetric/generated_summarydatapointvalueatquantile.go index 4335da7c771..68b6db52716 100644 --- a/pdata/pmetric/generated_summarydatapointvalueatquantile.go +++ b/pdata/pmetric/generated_summarydatapointvalueatquantile.go @@ -9,6 +9,7 @@ package pmetric import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // SummaryDataPointValueAtQuantile is a quantile value within a Summary data point. @@ -77,6 +78,20 @@ func (ms SummaryDataPointValueAtQuantile) CopyTo(dest SummaryDataPointValueAtQua copyOrigSummaryDataPointValueAtQuantile(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms SummaryDataPointValueAtQuantile) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.Quantile != float64(0.0) { + dest.WriteObjectField("quantile") + dest.WriteFloat64(ms.orig.Quantile) + } + if ms.orig.Value != float64(0.0) { + dest.WriteObjectField("value") + dest.WriteFloat64(ms.orig.Value) + } + dest.WriteObjectEnd() +} + func copyOrigSummaryDataPointValueAtQuantile(dest, src *otlpmetrics.SummaryDataPoint_ValueAtQuantile) { dest.Quantile = src.Quantile dest.Value = src.Value diff --git a/pdata/pmetric/generated_summarydatapointvalueatquantile_test.go b/pdata/pmetric/generated_summarydatapointvalueatquantile_test.go index 364bf96df4d..2f0f377389d 100644 --- a/pdata/pmetric/generated_summarydatapointvalueatquantile_test.go +++ b/pdata/pmetric/generated_summarydatapointvalueatquantile_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) func TestSummaryDataPointValueAtQuantile_MoveTo(t *testing.T) { @@ -46,6 +47,20 @@ func TestSummaryDataPointValueAtQuantile_CopyTo(t *testing.T) { }) } +func TestSummaryDataPointValueAtQuantile_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestSummaryDataPointValueAtQuantile() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewSummaryDataPointValueAtQuantile() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestSummaryDataPointValueAtQuantile_Quantile(t *testing.T) { ms := NewSummaryDataPointValueAtQuantile() assert.InDelta(t, float64(0.0), ms.Quantile(), 0.01) diff --git a/pdata/pmetric/generated_summarydatapointvalueatquantileslice.go b/pdata/pmetric/generated_summarydatapointvalueatquantileslice.go index 0186d78b8dc..b9c2c93c38a 100644 --- a/pdata/pmetric/generated_summarydatapointvalueatquantileslice.go +++ b/pdata/pmetric/generated_summarydatapointvalueatquantileslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // SummaryDataPointValueAtQuantileSlice logically represents a slice of SummaryDataPointValueAtQuantile. @@ -156,6 +157,19 @@ func (es SummaryDataPointValueAtQuantileSlice) Sort(less func(a, b SummaryDataPo sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms SummaryDataPointValueAtQuantileSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigSummaryDataPointValueAtQuantileSlice(dest, src []*otlpmetrics.SummaryDataPoint_ValueAtQuantile) []*otlpmetrics.SummaryDataPoint_ValueAtQuantile { if cap(dest) < len(src) { dest = make([]*otlpmetrics.SummaryDataPoint_ValueAtQuantile, len(src)) diff --git a/pdata/pmetric/json.go b/pdata/pmetric/json.go index a4a667d9c67..6c536c728a1 100644 --- a/pdata/pmetric/json.go +++ b/pdata/pmetric/json.go @@ -4,8 +4,8 @@ package pmetric // import "go.opentelemetry.io/collector/pdata/pmetric" import ( - "bytes" "fmt" + "slices" jsoniter "github.com/json-iterator/go" @@ -22,10 +22,10 @@ type JSONMarshaler struct{} // MarshalMetrics to the OTLP/JSON format. func (*JSONMarshaler) MarshalMetrics(md Metrics) ([]byte, error) { - buf := bytes.Buffer{} - pb := internal.MetricsToProto(internal.Metrics(md)) - err := json.Marshal(&buf, &pb) - return buf.Bytes(), err + dest := json.BorrowStream(nil) + defer json.ReturnStream(dest) + md.marshalJSONStream(dest) + return slices.Clone(dest.Buffer()), dest.Error } // JSONUnmarshaler unmarshals OTLP/JSON formatted-bytes to pdata.Metrics. @@ -44,21 +44,6 @@ func (*JSONUnmarshaler) UnmarshalMetrics(buf []byte) (Metrics, error) { return md, nil } -func (ms Metrics) unmarshalJsoniter(iter *jsoniter.Iterator) { - iter.ReadObjectCB(func(iter *jsoniter.Iterator, f string) bool { - switch f { - case "resource_metrics", "resourceMetrics": - iter.ReadArrayCB(func(*jsoniter.Iterator) bool { - ms.ResourceMetrics().AppendEmpty().unmarshalJsoniter(iter) - return true - }) - default: - iter.Skip() - } - return true - }) -} - func (ms ResourceMetrics) unmarshalJsoniter(iter *jsoniter.Iterator) { iter.ReadObjectCB(func(iter *jsoniter.Iterator, f string) bool { switch f { @@ -322,6 +307,8 @@ func (ms ExponentialHistogramDataPoint) unmarshalJsoniter(iter *jsoniter.Iterato ms.orig.Min_ = &otlpmetrics.ExponentialHistogramDataPoint_Min{ Min: json.ReadFloat64(iter), } + case "zeroThreshold", "zero_threshold": + ms.orig.ZeroThreshold = json.ReadFloat64(iter) default: iter.Skip() } diff --git a/pdata/pmetric/json_test.go b/pdata/pmetric/json_test.go index 4c2f7143e3c..ae56ff8ac21 100644 --- a/pdata/pmetric/json_test.go +++ b/pdata/pmetric/json_test.go @@ -30,7 +30,7 @@ var metricsOTLP = func() Metrics { var metricsJSON = `{"resourceMetrics":[{"resource":{"attributes":[{"key":"host.name","value":{"stringValue":"testHost"}}]},"scopeMetrics":[{"scope":{"name":"name","version":"version"},"metrics":[{"name":"testMetric","metadata":[{"key":"metadatakey","value":{"stringValue":"metadatavalue"}}]}]}]}]}` -func TestMetricsJSON(t *testing.T) { +func TestJSONUnmarshal(t *testing.T) { encoder := &JSONMarshaler{} jsonBuf, err := encoder.MarshalMetrics(metricsOTLP) require.NoError(t, err) @@ -42,7 +42,7 @@ func TestMetricsJSON(t *testing.T) { assert.Equal(t, metricsOTLP, got) } -func TestMetricsJSON_Marshal(t *testing.T) { +func TestJSONMarshal(t *testing.T) { encoder := &JSONMarshaler{} jsonBuf, err := encoder.MarshalMetrics(metricsOTLP) require.NoError(t, err) diff --git a/pdata/pmetric/metrics.go b/pdata/pmetric/metrics.go index 91195ca4dfa..edfe319bd75 100644 --- a/pdata/pmetric/metrics.go +++ b/pdata/pmetric/metrics.go @@ -4,8 +4,11 @@ package pmetric // import "go.opentelemetry.io/collector/pdata/pmetric" import ( + jsoniter "github.com/json-iterator/go" + "go.opentelemetry.io/collector/pdata/internal" otlpcollectormetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // Metrics is the top-level struct that is propagated through the metrics pipeline. @@ -93,3 +96,25 @@ func (ms Metrics) DataPointCount() (dataPointCount int) { func (ms Metrics) MarkReadOnly() { internal.SetMetricsState(internal.Metrics(ms), internal.StateReadOnly) } + +func (ms Metrics) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + dest.WriteObjectField("resourceMetrics") + ms.ResourceMetrics().marshalJSONStream(dest) + dest.WriteObjectEnd() +} + +func (ms Metrics) unmarshalJsoniter(iter *jsoniter.Iterator) { + iter.ReadObjectCB(func(iter *jsoniter.Iterator, f string) bool { + switch f { + case "resource_metrics", "resourceMetrics": + iter.ReadArrayCB(func(*jsoniter.Iterator) bool { + ms.ResourceMetrics().AppendEmpty().unmarshalJsoniter(iter) + return true + }) + default: + iter.Skip() + } + return true + }) +} diff --git a/pdata/pmetric/metrics_test.go b/pdata/pmetric/metrics_test.go index 4db384b9eb8..e23947ec5c1 100644 --- a/pdata/pmetric/metrics_test.go +++ b/pdata/pmetric/metrics_test.go @@ -998,3 +998,17 @@ func BenchmarkMetricsUsage(b *testing.B) { } } } + +func BenchmarkMetricsMarshalJSON(b *testing.B) { + md := NewMetrics() + fillTestResourceMetricsSlice(md.ResourceMetrics()) + encoder := &JSONMarshaler{} + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + jsonBuf, err := encoder.MarshalMetrics(md) + require.NoError(b, err) + require.NotNil(b, jsonBuf) + } +} diff --git a/pdata/pmetric/pmetricotlp/generated_exportpartialsuccess.go b/pdata/pmetric/pmetricotlp/generated_exportpartialsuccess.go index 68e6d7ab36f..d256c379f3d 100644 --- a/pdata/pmetric/pmetricotlp/generated_exportpartialsuccess.go +++ b/pdata/pmetric/pmetricotlp/generated_exportpartialsuccess.go @@ -9,6 +9,7 @@ package pmetricotlp import ( "go.opentelemetry.io/collector/pdata/internal" otlpcollectormetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // ExportPartialSuccess represents the details of a partially successful export request. @@ -77,6 +78,20 @@ func (ms ExportPartialSuccess) CopyTo(dest ExportPartialSuccess) { copyOrigExportPartialSuccess(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ExportPartialSuccess) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.RejectedDataPoints != int64(0) { + dest.WriteObjectField("rejectedDataPoints") + dest.WriteInt64(ms.orig.RejectedDataPoints) + } + if ms.orig.ErrorMessage != "" { + dest.WriteObjectField("errorMessage") + dest.WriteString(ms.orig.ErrorMessage) + } + dest.WriteObjectEnd() +} + func copyOrigExportPartialSuccess(dest, src *otlpcollectormetrics.ExportMetricsPartialSuccess) { dest.RejectedDataPoints = src.RejectedDataPoints dest.ErrorMessage = src.ErrorMessage diff --git a/pdata/pmetric/pmetricotlp/generated_exportpartialsuccess_test.go b/pdata/pmetric/pmetricotlp/generated_exportpartialsuccess_test.go index e219b5754a5..a81587399e0 100644 --- a/pdata/pmetric/pmetricotlp/generated_exportpartialsuccess_test.go +++ b/pdata/pmetric/pmetricotlp/generated_exportpartialsuccess_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpcollectormetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/metrics/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) func TestExportPartialSuccess_MoveTo(t *testing.T) { @@ -46,6 +47,20 @@ func TestExportPartialSuccess_CopyTo(t *testing.T) { }) } +func TestExportPartialSuccess_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestExportPartialSuccess() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewExportPartialSuccess() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestExportPartialSuccess_RejectedDataPoints(t *testing.T) { ms := NewExportPartialSuccess() assert.Equal(t, int64(0), ms.RejectedDataPoints()) diff --git a/pdata/pprofile/aggregation_temporality.go b/pdata/pprofile/aggregation_temporality.go index b79f8b04097..222a8d9b07f 100644 --- a/pdata/pprofile/aggregation_temporality.go +++ b/pdata/pprofile/aggregation_temporality.go @@ -5,6 +5,7 @@ package pprofile // import "go.opentelemetry.io/collector/pdata/pprofile" import ( otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" ) // AggregationTemporality specifies the method of aggregating metric values, @@ -33,3 +34,8 @@ func (at AggregationTemporality) String() string { } return "" } + +// MarshalJSONStream converts trace id into a hex string enclosed in quotes. +func (at AggregationTemporality) marshalJSONStream(dest *json.Stream) { + dest.WriteInt32(int32(at)) +} diff --git a/pdata/pprofile/generated_attribute.go b/pdata/pprofile/generated_attribute.go index 469780738de..d81d0387f2a 100644 --- a/pdata/pprofile/generated_attribute.go +++ b/pdata/pprofile/generated_attribute.go @@ -9,6 +9,7 @@ package pprofile import ( "go.opentelemetry.io/collector/pdata/internal" v1 "go.opentelemetry.io/collector/pdata/internal/data/protogen/common/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -72,6 +73,18 @@ func (ms Attribute) CopyTo(dest Attribute) { copyOrigAttribute(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms Attribute) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.Key != "" { + dest.WriteObjectField("key") + dest.WriteString(ms.orig.Key) + } + dest.WriteObjectField("value") + internal.MarshalJSONStreamValue(internal.NewValue(&ms.orig.Value, ms.state), dest) + dest.WriteObjectEnd() +} + func copyOrigAttribute(dest, src *v1.KeyValue) { dest.Key = src.Key internal.CopyOrigValue(&dest.Value, &src.Value) diff --git a/pdata/pprofile/generated_attribute_test.go b/pdata/pprofile/generated_attribute_test.go index 6bad76182f3..36d620dbcd1 100644 --- a/pdata/pprofile/generated_attribute_test.go +++ b/pdata/pprofile/generated_attribute_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" v1 "go.opentelemetry.io/collector/pdata/internal/data/protogen/common/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -41,6 +42,20 @@ func TestAttribute_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newAttribute(&v1.KeyValue{}, &sharedState)) }) } +func TestAttribute_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestAttribute() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewAttribute() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestAttribute_Key(t *testing.T) { ms := NewAttribute() assert.Empty(t, ms.Key()) diff --git a/pdata/pprofile/generated_attributetableslice.go b/pdata/pprofile/generated_attributetableslice.go index 8d98cb63918..8e62f50223f 100644 --- a/pdata/pprofile/generated_attributetableslice.go +++ b/pdata/pprofile/generated_attributetableslice.go @@ -11,6 +11,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" v1 "go.opentelemetry.io/collector/pdata/internal/data/protogen/common/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // AttributeTableSlice logically represents a slice of Attribute. @@ -147,6 +148,19 @@ func (es AttributeTableSlice) CopyTo(dest AttributeTableSlice) { *dest.orig = copyOrigAttributeTableSlice(*dest.orig, *es.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms AttributeTableSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigAttributeTableSlice(dest, src []v1.KeyValue) []v1.KeyValue { if cap(dest) < len(src) { dest = make([]v1.KeyValue, len(src)) diff --git a/pdata/pprofile/generated_attributeunit.go b/pdata/pprofile/generated_attributeunit.go index b82091232d6..edea9382552 100644 --- a/pdata/pprofile/generated_attributeunit.go +++ b/pdata/pprofile/generated_attributeunit.go @@ -9,6 +9,7 @@ package pprofile import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" ) // AttributeUnit Represents a mapping between Attribute Keys and Units. @@ -77,6 +78,20 @@ func (ms AttributeUnit) CopyTo(dest AttributeUnit) { copyOrigAttributeUnit(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms AttributeUnit) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.AttributeKeyStrindex != int32(0) { + dest.WriteObjectField("attributeKeyStrindex") + dest.WriteInt32(ms.orig.AttributeKeyStrindex) + } + if ms.orig.UnitStrindex != int32(0) { + dest.WriteObjectField("unitStrindex") + dest.WriteInt32(ms.orig.UnitStrindex) + } + dest.WriteObjectEnd() +} + func copyOrigAttributeUnit(dest, src *otlpprofiles.AttributeUnit) { dest.AttributeKeyStrindex = src.AttributeKeyStrindex dest.UnitStrindex = src.UnitStrindex diff --git a/pdata/pprofile/generated_attributeunit_test.go b/pdata/pprofile/generated_attributeunit_test.go index 9e99726847d..98c9eac5776 100644 --- a/pdata/pprofile/generated_attributeunit_test.go +++ b/pdata/pprofile/generated_attributeunit_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" ) func TestAttributeUnit_MoveTo(t *testing.T) { @@ -40,6 +41,20 @@ func TestAttributeUnit_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newAttributeUnit(&otlpprofiles.AttributeUnit{}, &sharedState)) }) } +func TestAttributeUnit_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestAttributeUnit() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewAttributeUnit() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestAttributeUnit_AttributeKeyStrindex(t *testing.T) { ms := NewAttributeUnit() assert.Equal(t, int32(0), ms.AttributeKeyStrindex()) diff --git a/pdata/pprofile/generated_attributeunitslice.go b/pdata/pprofile/generated_attributeunitslice.go index d9fc9f20a23..ae66fa3c207 100644 --- a/pdata/pprofile/generated_attributeunitslice.go +++ b/pdata/pprofile/generated_attributeunitslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" ) // AttributeUnitSlice logically represents a slice of AttributeUnit. @@ -156,6 +157,19 @@ func (es AttributeUnitSlice) Sort(less func(a, b AttributeUnit) bool) { sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms AttributeUnitSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigAttributeUnitSlice(dest, src []*otlpprofiles.AttributeUnit) []*otlpprofiles.AttributeUnit { if cap(dest) < len(src) { dest = make([]*otlpprofiles.AttributeUnit, len(src)) diff --git a/pdata/pprofile/generated_function.go b/pdata/pprofile/generated_function.go index a7da35238c3..01962a614b6 100644 --- a/pdata/pprofile/generated_function.go +++ b/pdata/pprofile/generated_function.go @@ -9,6 +9,7 @@ package pprofile import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" ) // Function describes a function, including its human-readable name, system name, source file, and starting line number in the source. @@ -99,6 +100,28 @@ func (ms Function) CopyTo(dest Function) { copyOrigFunction(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms Function) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.NameStrindex != int32(0) { + dest.WriteObjectField("nameStrindex") + dest.WriteInt32(ms.orig.NameStrindex) + } + if ms.orig.SystemNameStrindex != int32(0) { + dest.WriteObjectField("systemNameStrindex") + dest.WriteInt32(ms.orig.SystemNameStrindex) + } + if ms.orig.FilenameStrindex != int32(0) { + dest.WriteObjectField("filenameStrindex") + dest.WriteInt32(ms.orig.FilenameStrindex) + } + if ms.orig.StartLine != int64(0) { + dest.WriteObjectField("startLine") + dest.WriteInt64(ms.orig.StartLine) + } + dest.WriteObjectEnd() +} + func copyOrigFunction(dest, src *otlpprofiles.Function) { dest.NameStrindex = src.NameStrindex dest.SystemNameStrindex = src.SystemNameStrindex diff --git a/pdata/pprofile/generated_function_test.go b/pdata/pprofile/generated_function_test.go index 7c7460486b6..fdcb66201a9 100644 --- a/pdata/pprofile/generated_function_test.go +++ b/pdata/pprofile/generated_function_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" ) func TestFunction_MoveTo(t *testing.T) { @@ -40,6 +41,20 @@ func TestFunction_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newFunction(&otlpprofiles.Function{}, &sharedState)) }) } +func TestFunction_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestFunction() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewFunction() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestFunction_NameStrindex(t *testing.T) { ms := NewFunction() assert.Equal(t, int32(0), ms.NameStrindex()) diff --git a/pdata/pprofile/generated_functionslice.go b/pdata/pprofile/generated_functionslice.go index c9b0f88f445..bb47fa151d3 100644 --- a/pdata/pprofile/generated_functionslice.go +++ b/pdata/pprofile/generated_functionslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" ) // FunctionSlice logically represents a slice of Function. @@ -156,6 +157,19 @@ func (es FunctionSlice) Sort(less func(a, b Function) bool) { sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms FunctionSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigFunctionSlice(dest, src []*otlpprofiles.Function) []*otlpprofiles.Function { if cap(dest) < len(src) { dest = make([]*otlpprofiles.Function, len(src)) diff --git a/pdata/pprofile/generated_line.go b/pdata/pprofile/generated_line.go index d625a69135e..add53386de2 100644 --- a/pdata/pprofile/generated_line.go +++ b/pdata/pprofile/generated_line.go @@ -9,6 +9,7 @@ package pprofile import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" ) // Line details a specific line in a source code, linked to a function. @@ -88,6 +89,24 @@ func (ms Line) CopyTo(dest Line) { copyOrigLine(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms Line) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.FunctionIndex != int32(0) { + dest.WriteObjectField("functionIndex") + dest.WriteInt32(ms.orig.FunctionIndex) + } + if ms.orig.Line != int64(0) { + dest.WriteObjectField("line") + dest.WriteInt64(ms.orig.Line) + } + if ms.orig.Column != int64(0) { + dest.WriteObjectField("column") + dest.WriteInt64(ms.orig.Column) + } + dest.WriteObjectEnd() +} + func copyOrigLine(dest, src *otlpprofiles.Line) { dest.FunctionIndex = src.FunctionIndex dest.Line = src.Line diff --git a/pdata/pprofile/generated_line_test.go b/pdata/pprofile/generated_line_test.go index 01079926521..b8b0484a940 100644 --- a/pdata/pprofile/generated_line_test.go +++ b/pdata/pprofile/generated_line_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" ) func TestLine_MoveTo(t *testing.T) { @@ -40,6 +41,20 @@ func TestLine_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newLine(&otlpprofiles.Line{}, &sharedState)) }) } +func TestLine_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestLine() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewLine() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestLine_FunctionIndex(t *testing.T) { ms := NewLine() assert.Equal(t, int32(0), ms.FunctionIndex()) diff --git a/pdata/pprofile/generated_lineslice.go b/pdata/pprofile/generated_lineslice.go index eb62f683611..cec74d78105 100644 --- a/pdata/pprofile/generated_lineslice.go +++ b/pdata/pprofile/generated_lineslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" ) // LineSlice logically represents a slice of Line. @@ -156,6 +157,19 @@ func (es LineSlice) Sort(less func(a, b Line) bool) { sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms LineSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigLineSlice(dest, src []*otlpprofiles.Line) []*otlpprofiles.Line { if cap(dest) < len(src) { dest = make([]*otlpprofiles.Line, len(src)) diff --git a/pdata/pprofile/generated_link.go b/pdata/pprofile/generated_link.go index af8449b6ef2..f43fa5385f2 100644 --- a/pdata/pprofile/generated_link.go +++ b/pdata/pprofile/generated_link.go @@ -10,6 +10,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" "go.opentelemetry.io/collector/pdata/internal/data" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -79,6 +80,20 @@ func (ms Link) CopyTo(dest Link) { copyOrigLink(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms Link) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.TraceId != data.TraceID([16]byte{}) { + dest.WriteObjectField("traceId") + ms.orig.TraceId.MarshalJSONStream(dest) + } + if ms.orig.SpanId != data.SpanID([8]byte{}) { + dest.WriteObjectField("spanId") + ms.orig.SpanId.MarshalJSONStream(dest) + } + dest.WriteObjectEnd() +} + func copyOrigLink(dest, src *otlpprofiles.Link) { dest.TraceId = src.TraceId dest.SpanId = src.SpanId diff --git a/pdata/pprofile/generated_link_test.go b/pdata/pprofile/generated_link_test.go index 172b2ab3f3e..a156e12e256 100644 --- a/pdata/pprofile/generated_link_test.go +++ b/pdata/pprofile/generated_link_test.go @@ -14,6 +14,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" "go.opentelemetry.io/collector/pdata/internal/data" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -42,6 +43,20 @@ func TestLink_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newLink(&otlpprofiles.Link{}, &sharedState)) }) } +func TestLink_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestLink() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewLink() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestLink_TraceID(t *testing.T) { ms := NewLink() assert.Equal(t, pcommon.TraceID(data.TraceID([16]byte{})), ms.TraceID()) diff --git a/pdata/pprofile/generated_linkslice.go b/pdata/pprofile/generated_linkslice.go index 0efc976520d..7d557f6aa42 100644 --- a/pdata/pprofile/generated_linkslice.go +++ b/pdata/pprofile/generated_linkslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" ) // LinkSlice logically represents a slice of Link. @@ -156,6 +157,19 @@ func (es LinkSlice) Sort(less func(a, b Link) bool) { sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms LinkSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigLinkSlice(dest, src []*otlpprofiles.Link) []*otlpprofiles.Link { if cap(dest) < len(src) { dest = make([]*otlpprofiles.Link, len(src)) diff --git a/pdata/pprofile/generated_location.go b/pdata/pprofile/generated_location.go index d68bce1aad7..4ec7eafadd3 100644 --- a/pdata/pprofile/generated_location.go +++ b/pdata/pprofile/generated_location.go @@ -9,6 +9,7 @@ package pprofile import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -111,6 +112,32 @@ func (ms Location) CopyTo(dest Location) { copyOrigLocation(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms Location) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if ms.HasMappingIndex() { + dest.WriteObjectField("mappingIndex") + dest.WriteInt32(ms.MappingIndex()) + } + if ms.orig.Address != uint64(0) { + dest.WriteObjectField("address") + dest.WriteUint64(ms.orig.Address) + } + if len(ms.orig.Line) > 0 { + dest.WriteObjectField("line") + ms.Line().marshalJSONStream(dest) + } + if ms.orig.IsFolded != false { + dest.WriteObjectField("isFolded") + dest.WriteBool(ms.orig.IsFolded) + } + if len(ms.orig.AttributeIndices) > 0 { + dest.WriteObjectField("attributeIndices") + internal.MarshalJSONStreamInt32Slice(internal.NewInt32Slice(&ms.orig.AttributeIndices, ms.state), dest) + } + dest.WriteObjectEnd() +} + func copyOrigLocation(dest, src *otlpprofiles.Location) { if srcMappingIndex, ok := src.MappingIndex_.(*otlpprofiles.Location_MappingIndex); ok { destMappingIndex, ok := dest.MappingIndex_.(*otlpprofiles.Location_MappingIndex) diff --git a/pdata/pprofile/generated_location_test.go b/pdata/pprofile/generated_location_test.go index 995e54281d3..210aeb5b565 100644 --- a/pdata/pprofile/generated_location_test.go +++ b/pdata/pprofile/generated_location_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -41,6 +42,20 @@ func TestLocation_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newLocation(&otlpprofiles.Location{}, &sharedState)) }) } +func TestLocation_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestLocation() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewLocation() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestLocation_MappingIndex(t *testing.T) { ms := NewLocation() assert.Equal(t, int32(0), ms.MappingIndex()) diff --git a/pdata/pprofile/generated_locationslice.go b/pdata/pprofile/generated_locationslice.go index cdf69e788eb..1f7a747b6cc 100644 --- a/pdata/pprofile/generated_locationslice.go +++ b/pdata/pprofile/generated_locationslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" ) // LocationSlice logically represents a slice of Location. @@ -156,6 +157,19 @@ func (es LocationSlice) Sort(less func(a, b Location) bool) { sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms LocationSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigLocationSlice(dest, src []*otlpprofiles.Location) []*otlpprofiles.Location { if cap(dest) < len(src) { dest = make([]*otlpprofiles.Location, len(src)) diff --git a/pdata/pprofile/generated_mapping.go b/pdata/pprofile/generated_mapping.go index 3036d91585a..be3d0bb8826 100644 --- a/pdata/pprofile/generated_mapping.go +++ b/pdata/pprofile/generated_mapping.go @@ -9,6 +9,7 @@ package pprofile import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -149,6 +150,48 @@ func (ms Mapping) CopyTo(dest Mapping) { copyOrigMapping(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms Mapping) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.MemoryStart != uint64(0) { + dest.WriteObjectField("memoryStart") + dest.WriteUint64(ms.orig.MemoryStart) + } + if ms.orig.MemoryLimit != uint64(0) { + dest.WriteObjectField("memoryLimit") + dest.WriteUint64(ms.orig.MemoryLimit) + } + if ms.orig.FileOffset != uint64(0) { + dest.WriteObjectField("fileOffset") + dest.WriteUint64(ms.orig.FileOffset) + } + if ms.orig.FilenameStrindex != int32(0) { + dest.WriteObjectField("filenameStrindex") + dest.WriteInt32(ms.orig.FilenameStrindex) + } + if len(ms.orig.AttributeIndices) > 0 { + dest.WriteObjectField("attributeIndices") + internal.MarshalJSONStreamInt32Slice(internal.NewInt32Slice(&ms.orig.AttributeIndices, ms.state), dest) + } + if ms.orig.HasFunctions != false { + dest.WriteObjectField("hasFunctions") + dest.WriteBool(ms.orig.HasFunctions) + } + if ms.orig.HasFilenames != false { + dest.WriteObjectField("hasFilenames") + dest.WriteBool(ms.orig.HasFilenames) + } + if ms.orig.HasLineNumbers != false { + dest.WriteObjectField("hasLineNumbers") + dest.WriteBool(ms.orig.HasLineNumbers) + } + if ms.orig.HasInlineFrames != false { + dest.WriteObjectField("hasInlineFrames") + dest.WriteBool(ms.orig.HasInlineFrames) + } + dest.WriteObjectEnd() +} + func copyOrigMapping(dest, src *otlpprofiles.Mapping) { dest.MemoryStart = src.MemoryStart dest.MemoryLimit = src.MemoryLimit diff --git a/pdata/pprofile/generated_mapping_test.go b/pdata/pprofile/generated_mapping_test.go index c36ecb85f18..e980909ab9d 100644 --- a/pdata/pprofile/generated_mapping_test.go +++ b/pdata/pprofile/generated_mapping_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -41,6 +42,20 @@ func TestMapping_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newMapping(&otlpprofiles.Mapping{}, &sharedState)) }) } +func TestMapping_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestMapping() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewMapping() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestMapping_MemoryStart(t *testing.T) { ms := NewMapping() assert.Equal(t, uint64(0), ms.MemoryStart()) diff --git a/pdata/pprofile/generated_mappingslice.go b/pdata/pprofile/generated_mappingslice.go index 74fe482dc73..032aa63ca0e 100644 --- a/pdata/pprofile/generated_mappingslice.go +++ b/pdata/pprofile/generated_mappingslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" ) // MappingSlice logically represents a slice of Mapping. @@ -156,6 +157,19 @@ func (es MappingSlice) Sort(less func(a, b Mapping) bool) { sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms MappingSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigMappingSlice(dest, src []*otlpprofiles.Mapping) []*otlpprofiles.Mapping { if cap(dest) < len(src) { dest = make([]*otlpprofiles.Mapping, len(src)) diff --git a/pdata/pprofile/generated_profile.go b/pdata/pprofile/generated_profile.go index 70dbd27bf95..319ce4704e4 100644 --- a/pdata/pprofile/generated_profile.go +++ b/pdata/pprofile/generated_profile.go @@ -10,6 +10,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" "go.opentelemetry.io/collector/pdata/internal/data" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -169,6 +170,66 @@ func (ms Profile) CopyTo(dest Profile) { copyOrigProfile(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms Profile) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if len(ms.orig.SampleType) > 0 { + dest.WriteObjectField("sampleType") + ms.SampleType().marshalJSONStream(dest) + } + if len(ms.orig.Sample) > 0 { + dest.WriteObjectField("sample") + ms.Sample().marshalJSONStream(dest) + } + if len(ms.orig.LocationIndices) > 0 { + dest.WriteObjectField("locationIndices") + internal.MarshalJSONStreamInt32Slice(internal.NewInt32Slice(&ms.orig.LocationIndices, ms.state), dest) + } + if ms.orig.TimeNanos != 0 { + dest.WriteObjectField("timeNanos") + dest.WriteInt64(ms.orig.TimeNanos) + } + if ms.orig.DurationNanos != 0 { + dest.WriteObjectField("durationNanos") + dest.WriteInt64(ms.orig.DurationNanos) + } + dest.WriteObjectField("periodType") + ms.PeriodType().marshalJSONStream(dest) + if ms.orig.Period != int64(0) { + dest.WriteObjectField("period") + dest.WriteInt64(ms.orig.Period) + } + if len(ms.orig.CommentStrindices) > 0 { + dest.WriteObjectField("commentStrindices") + internal.MarshalJSONStreamInt32Slice(internal.NewInt32Slice(&ms.orig.CommentStrindices, ms.state), dest) + } + if ms.orig.DefaultSampleTypeIndex != int32(0) { + dest.WriteObjectField("defaultSampleTypeIndex") + dest.WriteInt32(ms.orig.DefaultSampleTypeIndex) + } + if ms.orig.ProfileId != data.ProfileID([16]byte{}) { + dest.WriteObjectField("profileId") + ms.ProfileID().marshalJSONStream(dest) + } + if ms.orig.DroppedAttributesCount != uint32(0) { + dest.WriteObjectField("droppedAttributesCount") + dest.WriteUint32(ms.orig.DroppedAttributesCount) + } + if ms.orig.OriginalPayloadFormat != "" { + dest.WriteObjectField("originalPayloadFormat") + dest.WriteString(ms.orig.OriginalPayloadFormat) + } + if len(ms.orig.OriginalPayload) > 0 { + dest.WriteObjectField("originalPayload") + internal.MarshalJSONStreamByteSlice(internal.NewByteSlice(&ms.orig.OriginalPayload, ms.state), dest) + } + if len(ms.orig.AttributeIndices) > 0 { + dest.WriteObjectField("attributeIndices") + internal.MarshalJSONStreamInt32Slice(internal.NewInt32Slice(&ms.orig.AttributeIndices, ms.state), dest) + } + dest.WriteObjectEnd() +} + func copyOrigProfile(dest, src *otlpprofiles.Profile) { dest.SampleType = copyOrigValueTypeSlice(dest.SampleType, src.SampleType) dest.Sample = copyOrigSampleSlice(dest.Sample, src.Sample) diff --git a/pdata/pprofile/generated_profile_test.go b/pdata/pprofile/generated_profile_test.go index 07f1602b1ac..a8bb55bb528 100644 --- a/pdata/pprofile/generated_profile_test.go +++ b/pdata/pprofile/generated_profile_test.go @@ -14,6 +14,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" "go.opentelemetry.io/collector/pdata/internal/data" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -42,6 +43,20 @@ func TestProfile_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newProfile(&otlpprofiles.Profile{}, &sharedState)) }) } +func TestProfile_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestProfile() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewProfile() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestProfile_SampleType(t *testing.T) { ms := NewProfile() assert.Equal(t, NewValueTypeSlice(), ms.SampleType()) diff --git a/pdata/pprofile/generated_profilesdictionary.go b/pdata/pprofile/generated_profilesdictionary.go index 8293d25065a..520006b07eb 100644 --- a/pdata/pprofile/generated_profilesdictionary.go +++ b/pdata/pprofile/generated_profilesdictionary.go @@ -9,6 +9,7 @@ package pprofile import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -91,6 +92,40 @@ func (ms ProfilesDictionary) CopyTo(dest ProfilesDictionary) { copyOrigProfilesDictionary(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ProfilesDictionary) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if len(ms.orig.MappingTable) > 0 { + dest.WriteObjectField("mappingTable") + ms.MappingTable().marshalJSONStream(dest) + } + if len(ms.orig.LocationTable) > 0 { + dest.WriteObjectField("locationTable") + ms.LocationTable().marshalJSONStream(dest) + } + if len(ms.orig.FunctionTable) > 0 { + dest.WriteObjectField("functionTable") + ms.FunctionTable().marshalJSONStream(dest) + } + if len(ms.orig.LinkTable) > 0 { + dest.WriteObjectField("linkTable") + ms.LinkTable().marshalJSONStream(dest) + } + if len(ms.orig.StringTable) > 0 { + dest.WriteObjectField("stringTable") + internal.MarshalJSONStreamStringSlice(internal.NewStringSlice(&ms.orig.StringTable, ms.state), dest) + } + if len(ms.orig.AttributeTable) > 0 { + dest.WriteObjectField("attributeTable") + ms.AttributeTable().marshalJSONStream(dest) + } + if len(ms.orig.AttributeUnits) > 0 { + dest.WriteObjectField("attributeUnits") + ms.AttributeUnits().marshalJSONStream(dest) + } + dest.WriteObjectEnd() +} + func copyOrigProfilesDictionary(dest, src *otlpprofiles.ProfilesDictionary) { dest.MappingTable = copyOrigMappingSlice(dest.MappingTable, src.MappingTable) dest.LocationTable = copyOrigLocationSlice(dest.LocationTable, src.LocationTable) diff --git a/pdata/pprofile/generated_profilesdictionary_test.go b/pdata/pprofile/generated_profilesdictionary_test.go index 2371c2da6d4..a1f6d3a7f9a 100644 --- a/pdata/pprofile/generated_profilesdictionary_test.go +++ b/pdata/pprofile/generated_profilesdictionary_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -41,6 +42,20 @@ func TestProfilesDictionary_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newProfilesDictionary(&otlpprofiles.ProfilesDictionary{}, &sharedState)) }) } +func TestProfilesDictionary_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestProfilesDictionary() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewProfilesDictionary() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestProfilesDictionary_MappingTable(t *testing.T) { ms := NewProfilesDictionary() assert.Equal(t, NewMappingSlice(), ms.MappingTable()) diff --git a/pdata/pprofile/generated_profilesslice.go b/pdata/pprofile/generated_profilesslice.go index 1182f3a0360..18fe59ad01c 100644 --- a/pdata/pprofile/generated_profilesslice.go +++ b/pdata/pprofile/generated_profilesslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" ) // ProfilesSlice logically represents a slice of Profile. @@ -156,6 +157,19 @@ func (es ProfilesSlice) Sort(less func(a, b Profile) bool) { sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ProfilesSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigProfilesSlice(dest, src []*otlpprofiles.Profile) []*otlpprofiles.Profile { if cap(dest) < len(src) { dest = make([]*otlpprofiles.Profile, len(src)) diff --git a/pdata/pprofile/generated_resourceprofiles.go b/pdata/pprofile/generated_resourceprofiles.go index d696e2c1508..bc24f7c0f4b 100644 --- a/pdata/pprofile/generated_resourceprofiles.go +++ b/pdata/pprofile/generated_resourceprofiles.go @@ -9,6 +9,7 @@ package pprofile import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -77,6 +78,22 @@ func (ms ResourceProfiles) CopyTo(dest ResourceProfiles) { copyOrigResourceProfiles(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ResourceProfiles) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + dest.WriteObjectField("resource") + internal.MarshalJSONStreamResource(internal.NewResource(&ms.orig.Resource, ms.state), dest) + if ms.orig.SchemaUrl != "" { + dest.WriteObjectField("schemaUrl") + dest.WriteString(ms.orig.SchemaUrl) + } + if len(ms.orig.ScopeProfiles) > 0 { + dest.WriteObjectField("scopeProfiles") + ms.ScopeProfiles().marshalJSONStream(dest) + } + dest.WriteObjectEnd() +} + func copyOrigResourceProfiles(dest, src *otlpprofiles.ResourceProfiles) { internal.CopyOrigResource(&dest.Resource, &src.Resource) dest.SchemaUrl = src.SchemaUrl diff --git a/pdata/pprofile/generated_resourceprofiles_test.go b/pdata/pprofile/generated_resourceprofiles_test.go index 475665c05eb..262fee63d27 100644 --- a/pdata/pprofile/generated_resourceprofiles_test.go +++ b/pdata/pprofile/generated_resourceprofiles_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -41,6 +42,20 @@ func TestResourceProfiles_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newResourceProfiles(&otlpprofiles.ResourceProfiles{}, &sharedState)) }) } +func TestResourceProfiles_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestResourceProfiles() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewResourceProfiles() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestResourceProfiles_Resource(t *testing.T) { ms := NewResourceProfiles() internal.FillTestResource(internal.Resource(ms.Resource())) diff --git a/pdata/pprofile/generated_resourceprofilesslice.go b/pdata/pprofile/generated_resourceprofilesslice.go index 39e81ee892c..bd663f52b39 100644 --- a/pdata/pprofile/generated_resourceprofilesslice.go +++ b/pdata/pprofile/generated_resourceprofilesslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" ) // ResourceProfilesSlice logically represents a slice of ResourceProfiles. @@ -156,6 +157,19 @@ func (es ResourceProfilesSlice) Sort(less func(a, b ResourceProfiles) bool) { sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ResourceProfilesSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigResourceProfilesSlice(dest, src []*otlpprofiles.ResourceProfiles) []*otlpprofiles.ResourceProfiles { if cap(dest) < len(src) { dest = make([]*otlpprofiles.ResourceProfiles, len(src)) diff --git a/pdata/pprofile/generated_sample.go b/pdata/pprofile/generated_sample.go index d0056451179..312c3e83167 100644 --- a/pdata/pprofile/generated_sample.go +++ b/pdata/pprofile/generated_sample.go @@ -9,6 +9,7 @@ package pprofile import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -116,6 +117,36 @@ func (ms Sample) CopyTo(dest Sample) { copyOrigSample(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms Sample) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.LocationsStartIndex != int32(0) { + dest.WriteObjectField("locationsStartIndex") + dest.WriteInt32(ms.orig.LocationsStartIndex) + } + if ms.orig.LocationsLength != int32(0) { + dest.WriteObjectField("locationsLength") + dest.WriteInt32(ms.orig.LocationsLength) + } + if len(ms.orig.Value) > 0 { + dest.WriteObjectField("value") + internal.MarshalJSONStreamInt64Slice(internal.NewInt64Slice(&ms.orig.Value, ms.state), dest) + } + if len(ms.orig.AttributeIndices) > 0 { + dest.WriteObjectField("attributeIndices") + internal.MarshalJSONStreamInt32Slice(internal.NewInt32Slice(&ms.orig.AttributeIndices, ms.state), dest) + } + if ms.HasLinkIndex() { + dest.WriteObjectField("linkIndex") + dest.WriteInt32(ms.LinkIndex()) + } + if len(ms.orig.TimestampsUnixNano) > 0 { + dest.WriteObjectField("timestampsUnixNano") + internal.MarshalJSONStreamUInt64Slice(internal.NewUInt64Slice(&ms.orig.TimestampsUnixNano, ms.state), dest) + } + dest.WriteObjectEnd() +} + func copyOrigSample(dest, src *otlpprofiles.Sample) { dest.LocationsStartIndex = src.LocationsStartIndex dest.LocationsLength = src.LocationsLength diff --git a/pdata/pprofile/generated_sample_test.go b/pdata/pprofile/generated_sample_test.go index 4ca9a30287d..56bf6b3a806 100644 --- a/pdata/pprofile/generated_sample_test.go +++ b/pdata/pprofile/generated_sample_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -41,6 +42,20 @@ func TestSample_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newSample(&otlpprofiles.Sample{}, &sharedState)) }) } +func TestSample_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestSample() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewSample() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestSample_LocationsStartIndex(t *testing.T) { ms := NewSample() assert.Equal(t, int32(0), ms.LocationsStartIndex()) diff --git a/pdata/pprofile/generated_sampleslice.go b/pdata/pprofile/generated_sampleslice.go index 0e93ecee53b..1eaf4ed3ec4 100644 --- a/pdata/pprofile/generated_sampleslice.go +++ b/pdata/pprofile/generated_sampleslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" ) // SampleSlice logically represents a slice of Sample. @@ -156,6 +157,19 @@ func (es SampleSlice) Sort(less func(a, b Sample) bool) { sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms SampleSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigSampleSlice(dest, src []*otlpprofiles.Sample) []*otlpprofiles.Sample { if cap(dest) < len(src) { dest = make([]*otlpprofiles.Sample, len(src)) diff --git a/pdata/pprofile/generated_scopeprofiles.go b/pdata/pprofile/generated_scopeprofiles.go index ac7bb8c5f3f..a6de565f14e 100644 --- a/pdata/pprofile/generated_scopeprofiles.go +++ b/pdata/pprofile/generated_scopeprofiles.go @@ -9,6 +9,7 @@ package pprofile import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -77,6 +78,22 @@ func (ms ScopeProfiles) CopyTo(dest ScopeProfiles) { copyOrigScopeProfiles(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ScopeProfiles) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + dest.WriteObjectField("scope") + internal.MarshalJSONStreamInstrumentationScope(internal.NewInstrumentationScope(&ms.orig.Scope, ms.state), dest) + if ms.orig.SchemaUrl != "" { + dest.WriteObjectField("schemaUrl") + dest.WriteString(ms.orig.SchemaUrl) + } + if len(ms.orig.Profiles) > 0 { + dest.WriteObjectField("profiles") + ms.Profiles().marshalJSONStream(dest) + } + dest.WriteObjectEnd() +} + func copyOrigScopeProfiles(dest, src *otlpprofiles.ScopeProfiles) { internal.CopyOrigInstrumentationScope(&dest.Scope, &src.Scope) dest.SchemaUrl = src.SchemaUrl diff --git a/pdata/pprofile/generated_scopeprofiles_test.go b/pdata/pprofile/generated_scopeprofiles_test.go index c9d2a8ed552..cde9e231952 100644 --- a/pdata/pprofile/generated_scopeprofiles_test.go +++ b/pdata/pprofile/generated_scopeprofiles_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -41,6 +42,20 @@ func TestScopeProfiles_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newScopeProfiles(&otlpprofiles.ScopeProfiles{}, &sharedState)) }) } +func TestScopeProfiles_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestScopeProfiles() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewScopeProfiles() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestScopeProfiles_Scope(t *testing.T) { ms := NewScopeProfiles() internal.FillTestInstrumentationScope(internal.InstrumentationScope(ms.Scope())) diff --git a/pdata/pprofile/generated_scopeprofilesslice.go b/pdata/pprofile/generated_scopeprofilesslice.go index 032bf031fad..ad0a558a751 100644 --- a/pdata/pprofile/generated_scopeprofilesslice.go +++ b/pdata/pprofile/generated_scopeprofilesslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" ) // ScopeProfilesSlice logically represents a slice of ScopeProfiles. @@ -156,6 +157,19 @@ func (es ScopeProfilesSlice) Sort(less func(a, b ScopeProfiles) bool) { sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ScopeProfilesSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigScopeProfilesSlice(dest, src []*otlpprofiles.ScopeProfiles) []*otlpprofiles.ScopeProfiles { if cap(dest) < len(src) { dest = make([]*otlpprofiles.ScopeProfiles, len(src)) diff --git a/pdata/pprofile/generated_valuetype.go b/pdata/pprofile/generated_valuetype.go index 8371a56d051..65a26d6c4b1 100644 --- a/pdata/pprofile/generated_valuetype.go +++ b/pdata/pprofile/generated_valuetype.go @@ -9,6 +9,7 @@ package pprofile import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" ) // ValueType describes the type and units of a value, with an optional aggregation temporality. @@ -88,6 +89,24 @@ func (ms ValueType) CopyTo(dest ValueType) { copyOrigValueType(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ValueType) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.TypeStrindex != int32(0) { + dest.WriteObjectField("typeStrindex") + dest.WriteInt32(ms.orig.TypeStrindex) + } + if ms.orig.UnitStrindex != int32(0) { + dest.WriteObjectField("unitStrindex") + dest.WriteInt32(ms.orig.UnitStrindex) + } + if ms.orig.AggregationTemporality != otlpprofiles.AggregationTemporality(0) { + dest.WriteObjectField("aggregationTemporality") + ms.AggregationTemporality().marshalJSONStream(dest) + } + dest.WriteObjectEnd() +} + func copyOrigValueType(dest, src *otlpprofiles.ValueType) { dest.TypeStrindex = src.TypeStrindex dest.UnitStrindex = src.UnitStrindex diff --git a/pdata/pprofile/generated_valuetype_test.go b/pdata/pprofile/generated_valuetype_test.go index dad75163fac..91add4f0d86 100644 --- a/pdata/pprofile/generated_valuetype_test.go +++ b/pdata/pprofile/generated_valuetype_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" ) func TestValueType_MoveTo(t *testing.T) { @@ -40,6 +41,20 @@ func TestValueType_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newValueType(&otlpprofiles.ValueType{}, &sharedState)) }) } +func TestValueType_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestValueType() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewValueType() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestValueType_TypeStrindex(t *testing.T) { ms := NewValueType() assert.Equal(t, int32(0), ms.TypeStrindex()) diff --git a/pdata/pprofile/generated_valuetypeslice.go b/pdata/pprofile/generated_valuetypeslice.go index dae919aae61..b64d029edc8 100644 --- a/pdata/pprofile/generated_valuetypeslice.go +++ b/pdata/pprofile/generated_valuetypeslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpprofiles "go.opentelemetry.io/collector/pdata/internal/data/protogen/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" ) // ValueTypeSlice logically represents a slice of ValueType. @@ -156,6 +157,19 @@ func (es ValueTypeSlice) Sort(less func(a, b ValueType) bool) { sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ValueTypeSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigValueTypeSlice(dest, src []*otlpprofiles.ValueType) []*otlpprofiles.ValueType { if cap(dest) < len(src) { dest = make([]*otlpprofiles.ValueType, len(src)) diff --git a/pdata/pprofile/json.go b/pdata/pprofile/json.go index 072b42c322c..91215db79df 100644 --- a/pdata/pprofile/json.go +++ b/pdata/pprofile/json.go @@ -4,8 +4,8 @@ package pprofile // import "go.opentelemetry.io/collector/pdata/pprofile" import ( - "bytes" "fmt" + "slices" jsoniter "github.com/json-iterator/go" @@ -19,11 +19,11 @@ import ( type JSONMarshaler struct{} // MarshalProfiles to the OTLP/JSON format. -func (*JSONMarshaler) MarshalProfiles(td Profiles) ([]byte, error) { - buf := bytes.Buffer{} - pb := internal.ProfilesToProto(internal.Profiles(td)) - err := json.Marshal(&buf, &pb) - return buf.Bytes(), err +func (*JSONMarshaler) MarshalProfiles(pd Profiles) ([]byte, error) { + dest := json.BorrowStream(nil) + defer json.ReturnStream(dest) + pd.marshalJSONStream(dest) + return slices.Clone(dest.Buffer()), dest.Error } // JSONUnmarshaler unmarshals OTLP/JSON formatted-bytes to pprofile.Profiles. @@ -42,24 +42,6 @@ func (*JSONUnmarshaler) UnmarshalProfiles(buf []byte) (Profiles, error) { return td, nil } -func (ms Profiles) unmarshalJsoniter(iter *jsoniter.Iterator) { - iter.ReadObjectCB(func(iter *jsoniter.Iterator, f string) bool { - switch f { - case "resourceProfiles", "resource_profiles": - iter.ReadArrayCB(func(iter *jsoniter.Iterator) bool { - ms.ResourceProfiles().AppendEmpty().unmarshalJsoniter(iter) - return true - }) - case "dictionary", "profilesDictionary", "profiles_dictionary": - ms.ProfilesDictionary().unmarshalJsoniter(iter) - return true - default: - iter.Skip() - } - return true - }) -} - func (ms ResourceProfiles) unmarshalJsoniter(iter *jsoniter.Iterator) { iter.ReadObjectCB(func(iter *jsoniter.Iterator, f string) bool { switch f { @@ -121,6 +103,21 @@ func (ms ProfilesDictionary) unmarshalJsoniter(iter *jsoniter.Iterator) { }) } +// unmarshalJsoniter is not yet used, only here for tests. +func (ms Attribute) unmarshalJsoniter(iter *jsoniter.Iterator) { + iter.ReadObjectCB(func(iter *jsoniter.Iterator, f string) bool { + switch f { + case "key": + ms.orig.Key = iter.ReadString() + case "value": + internal.UnmarshalJSONIterValue(internal.NewValue(&ms.orig.Value, ms.state), iter) + default: + iter.Skip() + } + return true + }) +} + func (sp ScopeProfiles) unmarshalJsoniter(iter *jsoniter.Iterator) { iter.ReadObjectCB(func(iter *jsoniter.Iterator, f string) bool { switch f { diff --git a/pdata/pprofile/pprofileotlp/generated_exportpartialsuccess.go b/pdata/pprofile/pprofileotlp/generated_exportpartialsuccess.go index 98e8b2e2827..7b38ae15fe5 100644 --- a/pdata/pprofile/pprofileotlp/generated_exportpartialsuccess.go +++ b/pdata/pprofile/pprofileotlp/generated_exportpartialsuccess.go @@ -9,6 +9,7 @@ package pprofileotlp import ( "go.opentelemetry.io/collector/pdata/internal" otlpcollectorprofile "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" ) // ExportPartialSuccess represents the details of a partially successful export request. @@ -77,6 +78,20 @@ func (ms ExportPartialSuccess) CopyTo(dest ExportPartialSuccess) { copyOrigExportPartialSuccess(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ExportPartialSuccess) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.RejectedProfiles != int64(0) { + dest.WriteObjectField("rejectedProfiles") + dest.WriteInt64(ms.orig.RejectedProfiles) + } + if ms.orig.ErrorMessage != "" { + dest.WriteObjectField("errorMessage") + dest.WriteString(ms.orig.ErrorMessage) + } + dest.WriteObjectEnd() +} + func copyOrigExportPartialSuccess(dest, src *otlpcollectorprofile.ExportProfilesPartialSuccess) { dest.RejectedProfiles = src.RejectedProfiles dest.ErrorMessage = src.ErrorMessage diff --git a/pdata/pprofile/pprofileotlp/generated_exportpartialsuccess_test.go b/pdata/pprofile/pprofileotlp/generated_exportpartialsuccess_test.go index b8fa619c290..dfb90e0495a 100644 --- a/pdata/pprofile/pprofileotlp/generated_exportpartialsuccess_test.go +++ b/pdata/pprofile/pprofileotlp/generated_exportpartialsuccess_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpcollectorprofile "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" ) func TestExportPartialSuccess_MoveTo(t *testing.T) { @@ -46,6 +47,20 @@ func TestExportPartialSuccess_CopyTo(t *testing.T) { }) } +func TestExportPartialSuccess_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestExportPartialSuccess() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewExportPartialSuccess() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestExportPartialSuccess_RejectedProfiles(t *testing.T) { ms := NewExportPartialSuccess() assert.Equal(t, int64(0), ms.RejectedProfiles()) diff --git a/pdata/pprofile/profileid.go b/pdata/pprofile/profileid.go index 52ee2e812b6..892e92e6a18 100644 --- a/pdata/pprofile/profileid.go +++ b/pdata/pprofile/profileid.go @@ -7,6 +7,7 @@ import ( "encoding/hex" "go.opentelemetry.io/collector/pdata/internal/data" + "go.opentelemetry.io/collector/pdata/internal/json" ) var emptyProfileID = ProfileID([16]byte{}) @@ -35,3 +36,7 @@ func (ms ProfileID) String() string { func (ms ProfileID) IsEmpty() bool { return data.ProfileID(ms).IsEmpty() } + +func (ms ProfileID) marshalJSONStream(dest *json.Stream) { + data.ProfileID(ms).MarshalJSONStream(dest) +} diff --git a/pdata/pprofile/profiles.go b/pdata/pprofile/profiles.go index 4fcfa74e8c3..65ff8ed712e 100644 --- a/pdata/pprofile/profiles.go +++ b/pdata/pprofile/profiles.go @@ -4,8 +4,11 @@ package pprofile // import "go.opentelemetry.io/collector/pdata/pprofile" import ( + jsoniter "github.com/json-iterator/go" + "go.opentelemetry.io/collector/pdata/internal" otlpcollectorprofile "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/profiles/v1development" + "go.opentelemetry.io/collector/pdata/internal/json" ) // Profiles is the top-level struct that is propagated through the profiles pipeline. @@ -72,3 +75,30 @@ func (ms Profiles) SampleCount() int { } return sampleCount } + +func (ms Profiles) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + dest.WriteObjectField("resourceProfiles") + ms.ResourceProfiles().marshalJSONStream(dest) + dest.WriteObjectField("dictionary") + ms.ProfilesDictionary().marshalJSONStream(dest) + dest.WriteObjectEnd() +} + +func (ms Profiles) unmarshalJsoniter(iter *jsoniter.Iterator) { + iter.ReadObjectCB(func(iter *jsoniter.Iterator, f string) bool { + switch f { + case "resourceProfiles", "resource_profiles": + iter.ReadArrayCB(func(iter *jsoniter.Iterator) bool { + ms.ResourceProfiles().AppendEmpty().unmarshalJsoniter(iter) + return true + }) + case "dictionary": + ms.ProfilesDictionary().unmarshalJsoniter(iter) + return true + default: + iter.Skip() + } + return true + }) +} diff --git a/pdata/pprofile/profiles_test.go b/pdata/pprofile/profiles_test.go index eee3f64f5ae..e92af387089 100644 --- a/pdata/pprofile/profiles_test.go +++ b/pdata/pprofile/profiles_test.go @@ -8,6 +8,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "go.opentelemetry.io/collector/pdata/internal/data" otlpcollectorprofile "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/profiles/v1development" @@ -137,3 +138,17 @@ func BenchmarkProfilesUsage(b *testing.B) { } } } + +func BenchmarkProfilesMarshalJSON(b *testing.B) { + md := NewProfiles() + fillTestResourceProfilesSlice(md.ResourceProfiles()) + encoder := &JSONMarshaler{} + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + jsonBuf, err := encoder.MarshalProfiles(md) + require.NoError(b, err) + require.NotNil(b, jsonBuf) + } +} diff --git a/pdata/ptrace/generated_resourcespans.go b/pdata/ptrace/generated_resourcespans.go index 2c74de48c2a..8cf3b7a37d4 100644 --- a/pdata/ptrace/generated_resourcespans.go +++ b/pdata/ptrace/generated_resourcespans.go @@ -9,6 +9,7 @@ package ptrace import ( "go.opentelemetry.io/collector/pdata/internal" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -77,6 +78,22 @@ func (ms ResourceSpans) CopyTo(dest ResourceSpans) { copyOrigResourceSpans(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ResourceSpans) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + dest.WriteObjectField("resource") + internal.MarshalJSONStreamResource(internal.NewResource(&ms.orig.Resource, ms.state), dest) + if ms.orig.SchemaUrl != "" { + dest.WriteObjectField("schemaUrl") + dest.WriteString(ms.orig.SchemaUrl) + } + if len(ms.orig.ScopeSpans) > 0 { + dest.WriteObjectField("scopeSpans") + ms.ScopeSpans().marshalJSONStream(dest) + } + dest.WriteObjectEnd() +} + func copyOrigResourceSpans(dest, src *otlptrace.ResourceSpans) { internal.CopyOrigResource(&dest.Resource, &src.Resource) dest.SchemaUrl = src.SchemaUrl diff --git a/pdata/ptrace/generated_resourcespans_test.go b/pdata/ptrace/generated_resourcespans_test.go index 4a8cd404da2..6d0dc0dd771 100644 --- a/pdata/ptrace/generated_resourcespans_test.go +++ b/pdata/ptrace/generated_resourcespans_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -41,6 +42,20 @@ func TestResourceSpans_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newResourceSpans(&otlptrace.ResourceSpans{}, &sharedState)) }) } +func TestResourceSpans_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestResourceSpans() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewResourceSpans() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestResourceSpans_Resource(t *testing.T) { ms := NewResourceSpans() internal.FillTestResource(internal.Resource(ms.Resource())) diff --git a/pdata/ptrace/generated_resourcespansslice.go b/pdata/ptrace/generated_resourcespansslice.go index a405f64f6d9..daf3e01b371 100644 --- a/pdata/ptrace/generated_resourcespansslice.go +++ b/pdata/ptrace/generated_resourcespansslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // ResourceSpansSlice logically represents a slice of ResourceSpans. @@ -156,6 +157,19 @@ func (es ResourceSpansSlice) Sort(less func(a, b ResourceSpans) bool) { sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ResourceSpansSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigResourceSpansSlice(dest, src []*otlptrace.ResourceSpans) []*otlptrace.ResourceSpans { if cap(dest) < len(src) { dest = make([]*otlptrace.ResourceSpans, len(src)) diff --git a/pdata/ptrace/generated_scopespans.go b/pdata/ptrace/generated_scopespans.go index 6e553a9836b..bbcdc3d7647 100644 --- a/pdata/ptrace/generated_scopespans.go +++ b/pdata/ptrace/generated_scopespans.go @@ -9,6 +9,7 @@ package ptrace import ( "go.opentelemetry.io/collector/pdata/internal" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -77,6 +78,22 @@ func (ms ScopeSpans) CopyTo(dest ScopeSpans) { copyOrigScopeSpans(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ScopeSpans) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + dest.WriteObjectField("scope") + internal.MarshalJSONStreamInstrumentationScope(internal.NewInstrumentationScope(&ms.orig.Scope, ms.state), dest) + if ms.orig.SchemaUrl != "" { + dest.WriteObjectField("schemaUrl") + dest.WriteString(ms.orig.SchemaUrl) + } + if len(ms.orig.Spans) > 0 { + dest.WriteObjectField("spans") + ms.Spans().marshalJSONStream(dest) + } + dest.WriteObjectEnd() +} + func copyOrigScopeSpans(dest, src *otlptrace.ScopeSpans) { internal.CopyOrigInstrumentationScope(&dest.Scope, &src.Scope) dest.SchemaUrl = src.SchemaUrl diff --git a/pdata/ptrace/generated_scopespans_test.go b/pdata/ptrace/generated_scopespans_test.go index aeafdbe3569..4c7ee6a5bac 100644 --- a/pdata/ptrace/generated_scopespans_test.go +++ b/pdata/ptrace/generated_scopespans_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -41,6 +42,20 @@ func TestScopeSpans_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newScopeSpans(&otlptrace.ScopeSpans{}, &sharedState)) }) } +func TestScopeSpans_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestScopeSpans() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewScopeSpans() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestScopeSpans_Scope(t *testing.T) { ms := NewScopeSpans() internal.FillTestInstrumentationScope(internal.InstrumentationScope(ms.Scope())) diff --git a/pdata/ptrace/generated_scopespansslice.go b/pdata/ptrace/generated_scopespansslice.go index 5f49fd103b3..c8e17c0be89 100644 --- a/pdata/ptrace/generated_scopespansslice.go +++ b/pdata/ptrace/generated_scopespansslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // ScopeSpansSlice logically represents a slice of ScopeSpans. @@ -156,6 +157,19 @@ func (es ScopeSpansSlice) Sort(less func(a, b ScopeSpans) bool) { sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ScopeSpansSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigScopeSpansSlice(dest, src []*otlptrace.ScopeSpans) []*otlptrace.ScopeSpans { if cap(dest) < len(src) { dest = make([]*otlptrace.ScopeSpans, len(src)) diff --git a/pdata/ptrace/generated_span.go b/pdata/ptrace/generated_span.go index 0b7001510ad..416237a4d5d 100644 --- a/pdata/ptrace/generated_span.go +++ b/pdata/ptrace/generated_span.go @@ -10,6 +10,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" "go.opentelemetry.io/collector/pdata/internal/data" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -204,6 +205,74 @@ func (ms Span) CopyTo(dest Span) { copyOrigSpan(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms Span) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.TraceId != data.TraceID([16]byte{}) { + dest.WriteObjectField("traceId") + ms.orig.TraceId.MarshalJSONStream(dest) + } + if ms.orig.SpanId != data.SpanID([8]byte{}) { + dest.WriteObjectField("spanId") + ms.orig.SpanId.MarshalJSONStream(dest) + } + if ms.orig.TraceState != "" { + dest.WriteObjectField("traceState") + internal.MarshalJSONStreamTraceState(internal.NewTraceState(&ms.orig.TraceState, ms.state), dest) + } + if ms.orig.ParentSpanId != data.SpanID([8]byte{}) { + dest.WriteObjectField("parentSpanId") + ms.orig.ParentSpanId.MarshalJSONStream(dest) + } + if ms.orig.Name != "" { + dest.WriteObjectField("name") + dest.WriteString(ms.orig.Name) + } + if ms.orig.Flags != uint32(0) { + dest.WriteObjectField("flags") + dest.WriteUint32(ms.orig.Flags) + } + if ms.orig.Kind != otlptrace.Span_SpanKind(0) { + dest.WriteObjectField("kind") + ms.Kind().marshalJSONStream(dest) + } + if ms.orig.StartTimeUnixNano != 0 { + dest.WriteObjectField("startTimeUnixNano") + dest.WriteUint64(ms.orig.StartTimeUnixNano) + } + if ms.orig.EndTimeUnixNano != 0 { + dest.WriteObjectField("endTimeUnixNano") + dest.WriteUint64(ms.orig.EndTimeUnixNano) + } + if len(ms.orig.Attributes) > 0 { + dest.WriteObjectField("attributes") + internal.MarshalJSONStreamMap(internal.NewMap(&ms.orig.Attributes, ms.state), dest) + } + if ms.orig.DroppedAttributesCount != uint32(0) { + dest.WriteObjectField("droppedAttributesCount") + dest.WriteUint32(ms.orig.DroppedAttributesCount) + } + if len(ms.orig.Events) > 0 { + dest.WriteObjectField("events") + ms.Events().marshalJSONStream(dest) + } + if ms.orig.DroppedEventsCount != uint32(0) { + dest.WriteObjectField("droppedEventsCount") + dest.WriteUint32(ms.orig.DroppedEventsCount) + } + if len(ms.orig.Links) > 0 { + dest.WriteObjectField("links") + ms.Links().marshalJSONStream(dest) + } + if ms.orig.DroppedLinksCount != uint32(0) { + dest.WriteObjectField("droppedLinksCount") + dest.WriteUint32(ms.orig.DroppedLinksCount) + } + dest.WriteObjectField("status") + ms.Status().marshalJSONStream(dest) + dest.WriteObjectEnd() +} + func copyOrigSpan(dest, src *otlptrace.Span) { dest.TraceId = src.TraceId dest.SpanId = src.SpanId diff --git a/pdata/ptrace/generated_span_test.go b/pdata/ptrace/generated_span_test.go index ac18d3b174a..20561c8016d 100644 --- a/pdata/ptrace/generated_span_test.go +++ b/pdata/ptrace/generated_span_test.go @@ -14,6 +14,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" "go.opentelemetry.io/collector/pdata/internal/data" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -42,6 +43,20 @@ func TestSpan_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newSpan(&otlptrace.Span{}, &sharedState)) }) } +func TestSpan_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestSpan() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewSpan() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestSpan_TraceID(t *testing.T) { ms := NewSpan() assert.Equal(t, pcommon.TraceID(data.TraceID([16]byte{})), ms.TraceID()) diff --git a/pdata/ptrace/generated_spanevent.go b/pdata/ptrace/generated_spanevent.go index f2be5facbdb..ff9951b95e0 100644 --- a/pdata/ptrace/generated_spanevent.go +++ b/pdata/ptrace/generated_spanevent.go @@ -9,6 +9,7 @@ package ptrace import ( "go.opentelemetry.io/collector/pdata/internal" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -95,6 +96,28 @@ func (ms SpanEvent) CopyTo(dest SpanEvent) { copyOrigSpanEvent(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms SpanEvent) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.TimeUnixNano != 0 { + dest.WriteObjectField("timeUnixNano") + dest.WriteUint64(ms.orig.TimeUnixNano) + } + if ms.orig.Name != "" { + dest.WriteObjectField("name") + dest.WriteString(ms.orig.Name) + } + if len(ms.orig.Attributes) > 0 { + dest.WriteObjectField("attributes") + internal.MarshalJSONStreamMap(internal.NewMap(&ms.orig.Attributes, ms.state), dest) + } + if ms.orig.DroppedAttributesCount != uint32(0) { + dest.WriteObjectField("droppedAttributesCount") + dest.WriteUint32(ms.orig.DroppedAttributesCount) + } + dest.WriteObjectEnd() +} + func copyOrigSpanEvent(dest, src *otlptrace.Span_Event) { dest.TimeUnixNano = src.TimeUnixNano dest.Name = src.Name diff --git a/pdata/ptrace/generated_spanevent_test.go b/pdata/ptrace/generated_spanevent_test.go index 707dfec8ee4..4bab2abf1f1 100644 --- a/pdata/ptrace/generated_spanevent_test.go +++ b/pdata/ptrace/generated_spanevent_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -41,6 +42,20 @@ func TestSpanEvent_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newSpanEvent(&otlptrace.Span_Event{}, &sharedState)) }) } +func TestSpanEvent_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestSpanEvent() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewSpanEvent() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestSpanEvent_Timestamp(t *testing.T) { ms := NewSpanEvent() assert.Equal(t, pcommon.Timestamp(0), ms.Timestamp()) diff --git a/pdata/ptrace/generated_spaneventslice.go b/pdata/ptrace/generated_spaneventslice.go index 95304b58739..1cef795cb42 100644 --- a/pdata/ptrace/generated_spaneventslice.go +++ b/pdata/ptrace/generated_spaneventslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // SpanEventSlice logically represents a slice of SpanEvent. @@ -156,6 +157,19 @@ func (es SpanEventSlice) Sort(less func(a, b SpanEvent) bool) { sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms SpanEventSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigSpanEventSlice(dest, src []*otlptrace.Span_Event) []*otlptrace.Span_Event { if cap(dest) < len(src) { dest = make([]*otlptrace.Span_Event, len(src)) diff --git a/pdata/ptrace/generated_spanlink.go b/pdata/ptrace/generated_spanlink.go index dfe82ec841f..47635b4c655 100644 --- a/pdata/ptrace/generated_spanlink.go +++ b/pdata/ptrace/generated_spanlink.go @@ -10,6 +10,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" "go.opentelemetry.io/collector/pdata/internal/data" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -113,6 +114,36 @@ func (ms SpanLink) CopyTo(dest SpanLink) { copyOrigSpanLink(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms SpanLink) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.TraceId != data.TraceID([16]byte{}) { + dest.WriteObjectField("traceId") + ms.orig.TraceId.MarshalJSONStream(dest) + } + if ms.orig.SpanId != data.SpanID([8]byte{}) { + dest.WriteObjectField("spanId") + ms.orig.SpanId.MarshalJSONStream(dest) + } + if ms.orig.TraceState != "" { + dest.WriteObjectField("traceState") + internal.MarshalJSONStreamTraceState(internal.NewTraceState(&ms.orig.TraceState, ms.state), dest) + } + if ms.orig.Flags != uint32(0) { + dest.WriteObjectField("flags") + dest.WriteUint32(ms.orig.Flags) + } + if len(ms.orig.Attributes) > 0 { + dest.WriteObjectField("attributes") + internal.MarshalJSONStreamMap(internal.NewMap(&ms.orig.Attributes, ms.state), dest) + } + if ms.orig.DroppedAttributesCount != uint32(0) { + dest.WriteObjectField("droppedAttributesCount") + dest.WriteUint32(ms.orig.DroppedAttributesCount) + } + dest.WriteObjectEnd() +} + func copyOrigSpanLink(dest, src *otlptrace.Span_Link) { dest.TraceId = src.TraceId dest.SpanId = src.SpanId diff --git a/pdata/ptrace/generated_spanlink_test.go b/pdata/ptrace/generated_spanlink_test.go index 3411f66b3f9..0d3f3ae53c2 100644 --- a/pdata/ptrace/generated_spanlink_test.go +++ b/pdata/ptrace/generated_spanlink_test.go @@ -14,6 +14,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" "go.opentelemetry.io/collector/pdata/internal/data" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -42,6 +43,20 @@ func TestSpanLink_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newSpanLink(&otlptrace.Span_Link{}, &sharedState)) }) } +func TestSpanLink_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestSpanLink() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewSpanLink() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestSpanLink_TraceID(t *testing.T) { ms := NewSpanLink() assert.Equal(t, pcommon.TraceID(data.TraceID([16]byte{})), ms.TraceID()) diff --git a/pdata/ptrace/generated_spanlinkslice.go b/pdata/ptrace/generated_spanlinkslice.go index c9b3fedf484..e2797a50064 100644 --- a/pdata/ptrace/generated_spanlinkslice.go +++ b/pdata/ptrace/generated_spanlinkslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // SpanLinkSlice logically represents a slice of SpanLink. @@ -156,6 +157,19 @@ func (es SpanLinkSlice) Sort(less func(a, b SpanLink) bool) { sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms SpanLinkSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigSpanLinkSlice(dest, src []*otlptrace.Span_Link) []*otlptrace.Span_Link { if cap(dest) < len(src) { dest = make([]*otlptrace.Span_Link, len(src)) diff --git a/pdata/ptrace/generated_spanslice.go b/pdata/ptrace/generated_spanslice.go index 4678f00f3a6..01d702f24e1 100644 --- a/pdata/ptrace/generated_spanslice.go +++ b/pdata/ptrace/generated_spanslice.go @@ -12,6 +12,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // SpanSlice logically represents a slice of Span. @@ -156,6 +157,19 @@ func (es SpanSlice) Sort(less func(a, b Span) bool) { sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) }) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms SpanSlice) marshalJSONStream(dest *json.Stream) { + dest.WriteArrayStart() + if len(*ms.orig) > 0 { + ms.At(0).marshalJSONStream(dest) + } + for i := 1; i < len(*ms.orig); i++ { + dest.WriteMore() + ms.At(i).marshalJSONStream(dest) + } + dest.WriteArrayEnd() +} + func copyOrigSpanSlice(dest, src []*otlptrace.Span) []*otlptrace.Span { if cap(dest) < len(src) { dest = make([]*otlptrace.Span, len(src)) diff --git a/pdata/ptrace/generated_status.go b/pdata/ptrace/generated_status.go index e39f91c95db..d21d9015ffb 100644 --- a/pdata/ptrace/generated_status.go +++ b/pdata/ptrace/generated_status.go @@ -9,6 +9,7 @@ package ptrace import ( "go.opentelemetry.io/collector/pdata/internal" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // Status is an optional final status for this span. Semantically, when Status was not @@ -78,6 +79,20 @@ func (ms Status) CopyTo(dest Status) { copyOrigStatus(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms Status) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.Code != 0 { + dest.WriteObjectField("code") + ms.Code().marshalJSONStream(dest) + } + if ms.orig.Message != "" { + dest.WriteObjectField("message") + dest.WriteString(ms.orig.Message) + } + dest.WriteObjectEnd() +} + func copyOrigStatus(dest, src *otlptrace.Status) { dest.Code = src.Code dest.Message = src.Message diff --git a/pdata/ptrace/generated_status_test.go b/pdata/ptrace/generated_status_test.go index fc14b682e62..7eceb3c2bf8 100644 --- a/pdata/ptrace/generated_status_test.go +++ b/pdata/ptrace/generated_status_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) func TestStatus_MoveTo(t *testing.T) { @@ -40,6 +41,20 @@ func TestStatus_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newStatus(&otlptrace.Status{}, &sharedState)) }) } +func TestStatus_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestStatus() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewStatus() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestStatus_Code(t *testing.T) { ms := NewStatus() assert.Equal(t, StatusCode(0), ms.Code()) diff --git a/pdata/ptrace/json.go b/pdata/ptrace/json.go index daa7ea4c9f4..740ab6ec0b7 100644 --- a/pdata/ptrace/json.go +++ b/pdata/ptrace/json.go @@ -4,8 +4,8 @@ package ptrace // import "go.opentelemetry.io/collector/pdata/ptrace" import ( - "bytes" "fmt" + "slices" jsoniter "github.com/json-iterator/go" @@ -20,10 +20,10 @@ type JSONMarshaler struct{} // MarshalTraces to the OTLP/JSON format. func (*JSONMarshaler) MarshalTraces(td Traces) ([]byte, error) { - buf := bytes.Buffer{} - pb := internal.TracesToProto(internal.Traces(td)) - err := json.Marshal(&buf, &pb) - return buf.Bytes(), err + dest := json.BorrowStream(nil) + defer json.ReturnStream(dest) + td.marshalJSONStream(dest) + return slices.Clone(dest.Buffer()), dest.Error } // JSONUnmarshaler unmarshals OTLP/JSON formatted-bytes to pdata.Traces. @@ -42,21 +42,6 @@ func (*JSONUnmarshaler) UnmarshalTraces(buf []byte) (Traces, error) { return td, nil } -func (ms Traces) unmarshalJsoniter(iter *jsoniter.Iterator) { - iter.ReadObjectCB(func(iter *jsoniter.Iterator, f string) bool { - switch f { - case "resourceSpans", "resource_spans": - iter.ReadArrayCB(func(iter *jsoniter.Iterator) bool { - ms.ResourceSpans().AppendEmpty().unmarshalJsoniter(iter) - return true - }) - default: - iter.Skip() - } - return true - }) -} - func (ms ResourceSpans) unmarshalJsoniter(iter *jsoniter.Iterator) { iter.ReadObjectCB(func(iter *jsoniter.Iterator, f string) bool { switch f { diff --git a/pdata/ptrace/json_test.go b/pdata/ptrace/json_test.go index 03bec4f8996..80330fa3661 100644 --- a/pdata/ptrace/json_test.go +++ b/pdata/ptrace/json_test.go @@ -93,7 +93,7 @@ var tracesOTLP = func() Traces { return td }() -var tracesJSON = `{"resourceSpans":[{"resource":{"attributes":[{"key":"host.name","value":{"stringValue":"testHost"}},{"key":"service.name","value":{"stringValue":"testService"}}],"droppedAttributesCount":1},"scopeSpans":[{"scope":{"name":"scope name","version":"scope version"},"spans":[{"traceId":"0102030405060708090a0b0c0d0e0f10","spanId":"1112131415161718","traceState":"state","parentSpanId":"1112131415161718","flags":1,"name":"testSpan","kind":3,"startTimeUnixNano":"1684617382541971000","endTimeUnixNano":"1684623646539558000","attributes":[{"key":"string","value":{"stringValue":"value"}},{"key":"bool","value":{"boolValue":true}},{"key":"int","value":{"intValue":"1"}},{"key":"double","value":{"doubleValue":1.1}},{"key":"bytes","value":{"bytesValue":"Zm9v"}},{"key":"array","value":{"arrayValue":{"values":[{"intValue":"1"},{"stringValue":"str"}]}}},{"key":"kvList","value":{"kvlistValue":{"values":[{"key":"int","value":{"intValue":"1"}},{"key":"string","value":{"stringValue":"string"}}]}}}],"droppedAttributesCount":1,"events":[{"timeUnixNano":"1684620382541971000","name":"eventName","attributes":[{"key":"string","value":{"stringValue":"value"}},{"key":"bool","value":{"boolValue":true}},{"key":"int","value":{"intValue":"1"}},{"key":"double","value":{"doubleValue":1.1}},{"key":"bytes","value":{"bytesValue":"Zm9v"}}],"droppedAttributesCount":1}],"droppedEventsCount":1,"links":[{"traceId":"0102030405060708090a0b0c0d0e0f10","spanId":"1112131415161718","traceState":"state","attributes":[{"key":"string","value":{"stringValue":"value"}},{"key":"bool","value":{"boolValue":true}},{"key":"int","value":{"intValue":"1"}},{"key":"double","value":{"doubleValue":1.1}},{"key":"bytes","value":{"bytesValue":"Zm9v"}}],"droppedAttributesCount":1,"flags":1}],"droppedLinksCount":1,"status":{"message":"message","code":1}},{"traceId":"","spanId":"","parentSpanId":"","name":"testSpan2","status":{}}],"schemaUrl":"schemaURL"}],"schemaUrl":"schemaURL"}]}` +var tracesJSON = `{"resourceSpans":[{"resource":{"attributes":[{"key":"host.name","value":{"stringValue":"testHost"}},{"key":"service.name","value":{"stringValue":"testService"}}],"droppedAttributesCount":1},"scopeSpans":[{"scope":{"name":"scope name","version":"scope version"},"spans":[{"traceId":"0102030405060708090a0b0c0d0e0f10","spanId":"1112131415161718","traceState":"state","parentSpanId":"1112131415161718","flags":1,"name":"testSpan","kind":3,"startTimeUnixNano":"1684617382541971000","endTimeUnixNano":"1684623646539558000","attributes":[{"key":"string","value":{"stringValue":"value"}},{"key":"bool","value":{"boolValue":true}},{"key":"int","value":{"intValue":"1"}},{"key":"double","value":{"doubleValue":1.1}},{"key":"bytes","value":{"bytesValue":"Zm9v"}},{"key":"array","value":{"arrayValue":{"values":[{"intValue":"1"},{"stringValue":"str"}]}}},{"key":"kvList","value":{"kvlistValue":{"values":[{"key":"int","value":{"intValue":"1"}},{"key":"string","value":{"stringValue":"string"}}]}}}],"droppedAttributesCount":1,"events":[{"timeUnixNano":"1684620382541971000","name":"eventName","attributes":[{"key":"string","value":{"stringValue":"value"}},{"key":"bool","value":{"boolValue":true}},{"key":"int","value":{"intValue":"1"}},{"key":"double","value":{"doubleValue":1.1}},{"key":"bytes","value":{"bytesValue":"Zm9v"}}],"droppedAttributesCount":1}],"droppedEventsCount":1,"links":[{"traceId":"0102030405060708090a0b0c0d0e0f10","spanId":"1112131415161718","traceState":"state","attributes":[{"key":"string","value":{"stringValue":"value"}},{"key":"bool","value":{"boolValue":true}},{"key":"int","value":{"intValue":"1"}},{"key":"double","value":{"doubleValue":1.1}},{"key":"bytes","value":{"bytesValue":"Zm9v"}}],"droppedAttributesCount":1,"flags":1}],"droppedLinksCount":1,"status":{"message":"message","code":1}},{"name":"testSpan2","status":{}}],"schemaUrl":"schemaURL"}],"schemaUrl":"schemaURL"}]}` func TestJSONUnmarshal(t *testing.T) { decoder := &JSONUnmarshaler{} diff --git a/pdata/ptrace/ptraceotlp/generated_exportpartialsuccess.go b/pdata/ptrace/ptraceotlp/generated_exportpartialsuccess.go index 29a801d9415..7d6e1cd01ea 100644 --- a/pdata/ptrace/ptraceotlp/generated_exportpartialsuccess.go +++ b/pdata/ptrace/ptraceotlp/generated_exportpartialsuccess.go @@ -9,6 +9,7 @@ package ptraceotlp import ( "go.opentelemetry.io/collector/pdata/internal" otlpcollectortrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/trace/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // ExportPartialSuccess represents the details of a partially successful export request. @@ -77,6 +78,20 @@ func (ms ExportPartialSuccess) CopyTo(dest ExportPartialSuccess) { copyOrigExportPartialSuccess(dest.orig, ms.orig) } +// marshalJSONStream marshals all properties from the current struct to the destination stream. +func (ms ExportPartialSuccess) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + if ms.orig.RejectedSpans != int64(0) { + dest.WriteObjectField("rejectedSpans") + dest.WriteInt64(ms.orig.RejectedSpans) + } + if ms.orig.ErrorMessage != "" { + dest.WriteObjectField("errorMessage") + dest.WriteString(ms.orig.ErrorMessage) + } + dest.WriteObjectEnd() +} + func copyOrigExportPartialSuccess(dest, src *otlpcollectortrace.ExportTracePartialSuccess) { dest.RejectedSpans = src.RejectedSpans dest.ErrorMessage = src.ErrorMessage diff --git a/pdata/ptrace/ptraceotlp/generated_exportpartialsuccess_test.go b/pdata/ptrace/ptraceotlp/generated_exportpartialsuccess_test.go index 335548585c7..075a458d48e 100644 --- a/pdata/ptrace/ptraceotlp/generated_exportpartialsuccess_test.go +++ b/pdata/ptrace/ptraceotlp/generated_exportpartialsuccess_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpcollectortrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/trace/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) func TestExportPartialSuccess_MoveTo(t *testing.T) { @@ -46,6 +47,20 @@ func TestExportPartialSuccess_CopyTo(t *testing.T) { }) } +func TestExportPartialSuccess_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestExportPartialSuccess() + src.marshalJSONStream(stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewExportPartialSuccess() + dest.unmarshalJsoniter(iter) + + assert.Equal(t, src, dest) +} + func TestExportPartialSuccess_RejectedSpans(t *testing.T) { ms := NewExportPartialSuccess() assert.Equal(t, int64(0), ms.RejectedSpans()) diff --git a/pdata/ptrace/span_kind.go b/pdata/ptrace/span_kind.go index 561d82cfffa..202146fa65a 100644 --- a/pdata/ptrace/span_kind.go +++ b/pdata/ptrace/span_kind.go @@ -5,6 +5,7 @@ package ptrace // import "go.opentelemetry.io/collector/pdata/ptrace" import ( otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // SpanKind is the type of span. Can be used to specify additional relationships between spans @@ -52,3 +53,7 @@ func (sk SpanKind) String() string { } return "" } + +func (sk SpanKind) marshalJSONStream(dest *json.Stream) { + dest.WriteInt32(int32(sk)) +} diff --git a/pdata/ptrace/status_code.go b/pdata/ptrace/status_code.go index 18a21f56ba8..65519f52f34 100644 --- a/pdata/ptrace/status_code.go +++ b/pdata/ptrace/status_code.go @@ -5,6 +5,7 @@ package ptrace // import "go.opentelemetry.io/collector/pdata/ptrace" import ( otlptrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // StatusCode mirrors the codes defined at @@ -29,3 +30,7 @@ func (sc StatusCode) String() string { } return "" } + +func (sc StatusCode) marshalJSONStream(dest *json.Stream) { + dest.WriteInt32(int32(sc)) +} diff --git a/pdata/ptrace/traces.go b/pdata/ptrace/traces.go index a4b71e17853..a8c7722a0ee 100644 --- a/pdata/ptrace/traces.go +++ b/pdata/ptrace/traces.go @@ -4,8 +4,11 @@ package ptrace // import "go.opentelemetry.io/collector/pdata/ptrace" import ( + jsoniter "github.com/json-iterator/go" + "go.opentelemetry.io/collector/pdata/internal" otlpcollectortrace "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/trace/v1" + "go.opentelemetry.io/collector/pdata/internal/json" ) // Traces is the top-level struct that is propagated through the traces pipeline. @@ -63,3 +66,25 @@ func (ms Traces) ResourceSpans() ResourceSpansSlice { func (ms Traces) MarkReadOnly() { internal.SetTracesState(internal.Traces(ms), internal.StateReadOnly) } + +func (ms Traces) marshalJSONStream(dest *json.Stream) { + dest.WriteObjectStart() + dest.WriteObjectField("resourceSpans") + ms.ResourceSpans().marshalJSONStream(dest) + dest.WriteObjectEnd() +} + +func (ms Traces) unmarshalJsoniter(iter *jsoniter.Iterator) { + iter.ReadObjectCB(func(iter *jsoniter.Iterator, f string) bool { + switch f { + case "resourceSpans", "resource_spans": + iter.ReadArrayCB(func(iter *jsoniter.Iterator) bool { + ms.ResourceSpans().AppendEmpty().unmarshalJsoniter(iter) + return true + }) + default: + iter.Skip() + } + return true + }) +} diff --git a/pdata/ptrace/traces_test.go b/pdata/ptrace/traces_test.go index e028f64ce0f..f30e5f9ac19 100644 --- a/pdata/ptrace/traces_test.go +++ b/pdata/ptrace/traces_test.go @@ -179,3 +179,17 @@ func BenchmarkTracesUsage(b *testing.B) { } } } + +func BenchmarkTracesMarshalJSON(b *testing.B) { + md := NewTraces() + fillTestResourceSpansSlice(md.ResourceSpans()) + encoder := &JSONMarshaler{} + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + jsonBuf, err := encoder.MarshalTraces(md) + require.NoError(b, err) + require.NotNil(b, jsonBuf) + } +} diff --git a/pdata/xpdata/entity/generated_entityref_test.go b/pdata/xpdata/entity/generated_entityref_test.go index 0c4639ab87e..f5e643faa70 100644 --- a/pdata/xpdata/entity/generated_entityref_test.go +++ b/pdata/xpdata/entity/generated_entityref_test.go @@ -13,6 +13,7 @@ import ( "go.opentelemetry.io/collector/pdata/internal" otlpcommon "go.opentelemetry.io/collector/pdata/internal/data/protogen/common/v1" + "go.opentelemetry.io/collector/pdata/internal/json" "go.opentelemetry.io/collector/pdata/pcommon" ) @@ -41,6 +42,20 @@ func TestEntityRef_CopyTo(t *testing.T) { assert.Panics(t, func() { ms.CopyTo(newEntityRef(&otlpcommon.EntityRef{}, &sharedState)) }) } +func TestEntityRef_MarshalAndUnmarshal(t *testing.T) { + stream := json.BorrowStream(nil) + defer json.ReturnStream(stream) + src := generateTestEntityRef() + internal.MarshalJSONStreamEntityRef(internal.EntityRef(src), stream) + + iter := json.BorrowIterator(stream.Buffer()) + defer json.ReturnIterator(iter) + dest := NewEntityRef() + internal.UnmarshalJSONIterEntityRef(internal.EntityRef(dest), iter) + + assert.Equal(t, src, dest) +} + func TestEntityRef_SchemaUrl(t *testing.T) { ms := NewEntityRef() assert.Empty(t, ms.SchemaUrl())