[pdata] Introduce runtime safeguards to catch incorrect pdata mutations (#8494)

This change introduces an option to enable runtime assertions to catch
unintentional pdata mutations in components that are claimed as
non-mutating pdata. Without these assertions, runtime errors may still
occur, but thrown by unrelated components, making it very difficult to
troubleshoot.

For now, this doesn't change the default behavior. It just introduces a
new method on `[Metrics/Traces|Logs].Shared()` that returns pdata marked
as shared. The method will be applied to fan-out consumers in the next
PR.

Later, if we want to remove the need of `MutatesData` capability, we can
introduce another method `[Metrics/Traces|Logs].Exclusive()` which
returns a copy of the pdata if it's shared.

This change unblocks the 1.0 release by implementing the original
solution proposed by @bogdandrutu in
https://github.com/open-telemetry/opentelemetry-collector/issues/6794.
Going forward, we may introduce a copy-on-write solution that doesn't
require the runtime assertions. That will likely be part of the 2.0
release.
This commit is contained in:
Dmitrii Anoshin 2023-10-06 08:56:20 -07:00 committed by GitHub
parent b89b8194c1
commit 7ee0b28302
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
138 changed files with 2358 additions and 541 deletions

View File

@ -0,0 +1,19 @@
# 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: Introduce runtime assertions to catch incorrect pdata mutations
# One or more tracking issues or pull requests related to the change
issues: [6794]
# (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: |
This change introduces an option to enable runtime assertions to catch unintentional pdata mutations in components
that are claimed as non-mutating pdata. Without these assertions, runtime errors may still occur, but thrown by
unrelated components, making it very difficult to troubleshoot.

View File

@ -12,9 +12,15 @@ import (
const accessorSliceTemplate = `// {{ .fieldName }} returns the {{ .fieldName }} associated with this {{ .structName }}.
func (ms {{ .structName }}) {{ .fieldName }}() {{ .packageName }}{{ .returnType }} {
{{- if .isCommon }}
return {{ .packageName }}{{ .returnType }}(internal.New{{ .returnType }}(&ms.{{ .origAccessor }}.{{ .fieldName }}))
return {{ .packageName }}{{ .returnType }}(internal.New{{ .returnType }}(&ms.{{ .origAccessor }}.{{ .fieldName }}
{{- if .isBaseStructCommon -}}
, internal.Get{{ .structName }}State(internal.{{ .structName }}(ms))
{{- else -}}
, ms.state
{{- end -}}
))
{{- else }}
return new{{ .returnType }}(&ms.{{ .origAccessor }}.{{ .fieldName }})
return new{{ .returnType }}(&ms.{{ .origAccessor }}.{{ .fieldName }}, ms.state)
{{- end }}
}`
@ -36,14 +42,14 @@ const setTestValueTemplate = `{{ if .isCommon -}}
{{- else -}}
fillTest{{ .returnType }}(new
{{- end -}}
{{ .returnType }}(&tv.orig.{{ .fieldName }}))`
{{ .returnType }}(&tv.orig.{{ .fieldName }}, tv.state))`
const accessorsMessageValueTemplate = `// {{ .fieldName }} returns the {{ .lowerFieldName }} associated with this {{ .structName }}.
func (ms {{ .structName }}) {{ .fieldName }}() {{ .packageName }}{{ .returnType }} {
{{- if .isCommon }}
return {{ .packageName }}{{ .returnType }}(internal.New{{ .returnType }}(&ms.{{ .origAccessor }}.{{ .fieldName }}))
return {{ .packageName }}{{ .returnType }}(internal.New{{ .returnType }}(&ms.{{ .origAccessor }}.{{ .fieldName }}, ms.state))
{{- else }}
return new{{ .returnType }}(&ms.{{ .origAccessor }}.{{ .fieldName }})
return new{{ .returnType }}(&ms.{{ .origAccessor }}.{{ .fieldName }}, ms.state)
{{- end }}
}`
@ -65,12 +71,13 @@ func (ms {{ .structName }}) {{ .fieldName }}() {{ .packageName }}{{ .returnType
// Set{{ .fieldName }} replaces the {{ .lowerFieldName }} associated with this {{ .structName }}.
func (ms {{ .structName }}) Set{{ .fieldName }}(v {{ .returnType }}) {
ms.{{ .stateAccessor }}.AssertMutable()
ms.{{ .origAccessor }}.{{ .fieldName }} = v
}`
const accessorsPrimitiveSliceTemplate = `// {{ .fieldName }} returns the {{ .lowerFieldName }} associated with this {{ .structName }}.
func (ms {{ .structName }}) {{ .fieldName }}() {{ .packageName }}{{ .returnType }} {
return {{ .packageName }}{{ .returnType }}(internal.New{{ .returnType }}(&ms.{{ .origAccessor }}.{{ .fieldName }}))
return {{ .packageName }}{{ .returnType }}(internal.New{{ .returnType }}(&ms.{{ .origAccessor }}.{{ .fieldName }}, ms.state))
}`
const oneOfTypeAccessorTemplate = `// {{ .typeFuncName }} returns the type of the {{ .lowerOriginFieldName }} for this {{ .structName }}.
@ -108,7 +115,7 @@ func (ms {{ .structName }}) {{ .fieldName }}() {{ .returnType }} {
if !ok {
return {{ .returnType }}{}
}
return new{{ .returnType }}(v.{{ .fieldName }})
return new{{ .returnType }}(v.{{ .fieldName }}, ms.state)
}
// SetEmpty{{ .fieldName }} sets an empty {{ .lowerFieldName }} to this {{ .structName }}.
@ -117,9 +124,10 @@ func (ms {{ .structName }}) {{ .fieldName }}() {{ .returnType }} {
//
// Calling this function on zero-initialized {{ .structName }} will cause a panic.
func (ms {{ .structName }}) SetEmpty{{ .fieldName }}() {{ .returnType }} {
ms.state.AssertMutable()
val := &{{ .originFieldPackageName }}.{{ .fieldName }}{}
ms.orig.{{ .originOneOfFieldName }} = &{{ .originStructType }}{{ "{" }}{{ .fieldName }}: val}
return new{{ .returnType }}(val)
return new{{ .returnType }}(val, ms.state)
}`
const accessorsOneOfMessageTestTemplate = `func Test{{ .structName }}_{{ .fieldName }}(t *testing.T) {
@ -127,6 +135,8 @@ const accessorsOneOfMessageTestTemplate = `func Test{{ .structName }}_{{ .fieldN
fillTest{{ .returnType }}(ms.SetEmpty{{ .fieldName }}())
assert.Equal(t, {{ .typeName }}, ms.{{ .originOneOfTypeFuncName }}())
assert.Equal(t, generateTest{{ .returnType }}(), ms.{{ .fieldName }}())
sharedState := internal.StateReadOnly
assert.Panics(t, func() { new{{ .structName }}(&{{ .originStructName }}{}, &sharedState).SetEmpty{{ .fieldName }}() })
}
func Test{{ .structName }}_CopyTo_{{ .fieldName }}(t *testing.T) {
@ -135,6 +145,8 @@ func Test{{ .structName }}_CopyTo_{{ .fieldName }}(t *testing.T) {
dest := New{{ .structName }}()
ms.CopyTo(dest)
assert.Equal(t, ms, dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.CopyTo(new{{ .structName }}(&{{ .originStructName }}{}, &sharedState)) })
}`
const copyToValueOneOfMessageTemplate = ` case {{ .typeName }}:
@ -147,6 +159,7 @@ func (ms {{ .structName }}) {{ .accessorFieldName }}() {{ .returnType }} {
// Set{{ .accessorFieldName }} replaces the {{ .lowerFieldName }} associated with this {{ .structName }}.
func (ms {{ .structName }}) Set{{ .accessorFieldName }}(v {{ .returnType }}) {
ms.state.AssertMutable()
ms.orig.{{ .originOneOfFieldName }} = &{{ .originStructType }}{
{{ .originFieldName }}: v,
}
@ -158,6 +171,8 @@ const accessorsOneOfPrimitiveTestTemplate = `func Test{{ .structName }}_{{ .acce
ms.Set{{ .accessorFieldName }}({{ .testValue }})
assert.Equal(t, {{ .testValue }}, ms.{{ .accessorFieldName }}())
assert.Equal(t, {{ .typeName }}, ms.{{ .originOneOfTypeFuncName }}())
sharedState := internal.StateReadOnly
assert.Panics(t, func() { new{{ .structName }}(&{{ .originStructName }}{}, &sharedState).Set{{ .accessorFieldName }}({{ .testValue }}) })
}`
const accessorsPrimitiveTestTemplate = `func Test{{ .structName }}_{{ .fieldName }}(t *testing.T) {
@ -165,6 +180,8 @@ const accessorsPrimitiveTestTemplate = `func Test{{ .structName }}_{{ .fieldName
assert.Equal(t, {{ .defaultVal }}, ms.{{ .fieldName }}())
ms.Set{{ .fieldName }}({{ .testValue }})
assert.Equal(t, {{ .testValue }}, ms.{{ .fieldName }}())
sharedState := internal.StateReadOnly
assert.Panics(t, func() { new{{ .structName }}(&{{ .originStructName }}{}, &sharedState).Set{{ .fieldName }}({{ .testValue }}) })
}`
const accessorsPrimitiveTypedTemplate = `// {{ .fieldName }} returns the {{ .lowerFieldName }} associated with this {{ .structName }}.
@ -174,6 +191,7 @@ func (ms {{ .structName }}) {{ .fieldName }}() {{ .packageName }}{{ .returnType
// Set{{ .fieldName }} replaces the {{ .lowerFieldName }} associated with this {{ .structName }}.
func (ms {{ .structName }}) Set{{ .fieldName }}(v {{ .packageName }}{{ .returnType }}) {
ms.state.AssertMutable()
ms.orig.{{ .originFieldName }} = {{ .rawType }}(v)
}`
@ -205,11 +223,13 @@ func (ms {{ .structName }}) Has{{ .fieldName }}() bool {
// Set{{ .fieldName }} replaces the {{ .lowerFieldName }} associated with this {{ .structName }}.
func (ms {{ .structName }}) Set{{ .fieldName }}(v {{ .returnType }}) {
ms.state.AssertMutable()
ms.orig.{{ .fieldName }}_ = &{{ .originStructType }}{{ "{" }}{{ .fieldName }}: v}
}
// Remove{{ .fieldName }} removes the {{ .lowerFieldName }} associated with this {{ .structName }}.
func (ms {{ .structName }}) Remove{{ .fieldName }}() {
ms.state.AssertMutable()
ms.orig.{{ .fieldName }}_ = nil
}`
@ -281,6 +301,7 @@ func (sf *sliceField) templateFields(ms *messageValueStruct) map[string]any {
}(),
"returnType": sf.returnSlice.getName(),
"origAccessor": origAccessor(ms),
"stateAccessor": stateAccessor(ms),
"isCommon": usedByOtherDataTypes(sf.returnSlice.getPackageName()),
"isBaseStructCommon": usedByOtherDataTypes(ms.packageName),
}
@ -337,7 +358,8 @@ func (mf *messageValueField) templateFields(ms *messageValueStruct) map[string]a
}
return ""
}(),
"origAccessor": origAccessor(ms),
"origAccessor": origAccessor(ms),
"stateAccessor": stateAccessor(ms),
}
}
@ -378,14 +400,16 @@ func (pf *primitiveField) GenerateCopyToValue(_ *messageValueStruct) string {
func (pf *primitiveField) templateFields(ms *messageValueStruct) map[string]any {
return map[string]any{
"structName": ms.getName(),
"packageName": "",
"defaultVal": pf.defaultVal,
"fieldName": pf.fieldName,
"lowerFieldName": strings.ToLower(pf.fieldName),
"testValue": pf.testVal,
"returnType": pf.returnType,
"origAccessor": origAccessor(ms),
"structName": ms.getName(),
"packageName": "",
"defaultVal": pf.defaultVal,
"fieldName": pf.fieldName,
"lowerFieldName": strings.ToLower(pf.fieldName),
"testValue": pf.testVal,
"returnType": pf.returnType,
"origAccessor": origAccessor(ms),
"stateAccessor": stateAccessor(ms),
"originStructName": ms.originFullName,
}
}
@ -513,6 +537,7 @@ func (psf *primitiveSliceField) templateFields(ms *messageValueStruct) map[strin
"lowerFieldName": strings.ToLower(psf.fieldName),
"testValue": psf.testVal,
"origAccessor": origAccessor(ms),
"stateAccessor": stateAccessor(ms),
}
}
@ -576,6 +601,7 @@ func (of *oneOfField) templateFields(ms *messageValueStruct) map[string]any {
"originFieldName": of.originFieldName,
"lowerOriginFieldName": strings.ToLower(of.originFieldName),
"origAccessor": origAccessor(ms),
"stateAccessor": stateAccessor(ms),
"values": of.values,
"originTypePrefix": ms.originFullName + "_",
}
@ -653,6 +679,7 @@ func (opv *oneOfPrimitiveValue) templateFields(ms *messageValueStruct, of *oneOf
"returnType": opv.returnType,
"originFieldName": opv.originFieldName,
"originOneOfFieldName": of.originFieldName,
"originStructName": ms.originFullName,
"originStructType": ms.originFullName + "_" + opv.originFieldName,
}
}
@ -687,7 +714,7 @@ func (omv *oneOfMessageValue) GenerateTests(ms *messageValueStruct, of *oneOfFie
func (omv *oneOfMessageValue) GenerateSetWithTestValue(ms *messageValueStruct, of *oneOfField) string {
return "\ttv.orig." + of.originFieldName + " = &" + ms.originFullName + "_" + omv.fieldName + "{" + omv.
fieldName + ": &" + omv.originFieldPackageName + "." + omv.fieldName + "{}}\n" +
"\tfillTest" + omv.returnMessage.structName + "(new" + omv.fieldName + "(tv.orig.Get" + omv.fieldName + "()))"
"\tfillTest" + omv.returnMessage.structName + "(new" + omv.fieldName + "(tv.orig.Get" + omv.fieldName + "(), tv.state))"
}
func (omv *oneOfMessageValue) GenerateCopyToValue(ms *messageValueStruct, of *oneOfField, sb *bytes.Buffer) {
@ -713,6 +740,7 @@ func (omv *oneOfMessageValue) templateFields(ms *messageValueStruct, of *oneOfFi
"originOneOfTypeFuncName": of.typeFuncName(),
"lowerFieldName": strings.ToLower(omv.fieldName),
"originFieldPackageName": omv.originFieldPackageName,
"originStructName": ms.originFullName,
"originStructType": ms.originFullName + "_" + omv.fieldName,
}
}
@ -764,6 +792,7 @@ func (opv *optionalPrimitiveValue) templateFields(ms *messageValueStruct) map[st
"lowerFieldName": strings.ToLower(opv.fieldName),
"testValue": opv.testVal,
"returnType": opv.returnType,
"originStructName": ms.originFullName,
"originStructType": ms.originFullName + "_" + opv.fieldName,
}
}
@ -776,3 +805,10 @@ func origAccessor(bs *messageValueStruct) string {
}
return "orig"
}
func stateAccessor(bs *messageValueStruct) string {
if usedByOtherDataTypes(bs.packageName) {
return "getState()"
}
return "state"
}

View File

@ -17,17 +17,19 @@ const sliceTemplate = `// {{ .structName }} logically represents a slice of {{ .
// Important: zero-initialized instance is not valid for use.
type {{ .structName }} struct {
orig *[]{{ .originElementType }}
state *internal.State
}
func new{{ .structName }}(orig *[]{{ .originElementType }}) {{ .structName }} {
return {{ .structName }}{orig}
func new{{ .structName }}(orig *[]{{ .originElementType }}, state *internal.State) {{ .structName }} {
return {{ .structName }}{orig: orig, state: state}
}
// New{{ .structName }} creates a {{ .structName }} with 0 elements.
// Can use "EnsureCapacity" to initialize with a given capacity.
func New{{ .structName }}() {{ .structName }} {
orig := []{{ .originElementType }}(nil)
return new{{ .structName }}(&orig)
state := internal.StateMutable
return new{{ .structName }}(&orig, &state)
}
// Len returns the number of elements in the slice.
@ -60,6 +62,7 @@ func (es {{ .structName }}) At(i int) {{ .elementName }} {
// // Here should set all the values for e.
// }
func (es {{ .structName }}) EnsureCapacity(newCap int) {
es.state.AssertMutable()
oldCap := cap(*es.orig)
if newCap <= oldCap {
return
@ -73,6 +76,7 @@ func (es {{ .structName }}) EnsureCapacity(newCap int) {
// AppendEmpty will append to the end of the slice an empty {{ .elementName }}.
// It returns the newly added {{ .elementName }}.
func (es {{ .structName }}) AppendEmpty() {{ .elementName }} {
es.state.AssertMutable()
*es.orig = append(*es.orig, {{ .emptyOriginElement }})
return es.At(es.Len() - 1)
}
@ -80,6 +84,8 @@ func (es {{ .structName }}) AppendEmpty() {{ .elementName }} {
// MoveAndAppendTo moves all elements from the current slice and appends them to the dest.
// The current slice will be cleared.
func (es {{ .structName }}) MoveAndAppendTo(dest {{ .structName }}) {
es.state.AssertMutable()
dest.state.AssertMutable()
if *dest.orig == nil {
// We can simply move the entire vector and avoid any allocations.
*dest.orig = *es.orig
@ -92,6 +98,7 @@ func (es {{ .structName }}) MoveAndAppendTo(dest {{ .structName }}) {
// RemoveIf calls f sequentially for each element present in the slice.
// If f returns true, the element is removed from the slice.
func (es {{ .structName }}) RemoveIf(f func({{ .elementName }}) bool) {
es.state.AssertMutable()
newLen := 0
for i := 0; i < len(*es.orig); i++ {
if f(es.At(i)) {
@ -112,6 +119,7 @@ func (es {{ .structName }}) RemoveIf(f func({{ .elementName }}) bool) {
// CopyTo copies all elements from the current slice overriding the destination.
func (es {{ .structName }}) CopyTo(dest {{ .structName }}) {
dest.state.AssertMutable()
srcLen := es.Len()
destCap := cap(*dest.orig)
if srcLen <= destCap {
@ -119,7 +127,7 @@ func (es {{ .structName }}) CopyTo(dest {{ .structName }}) {
{{- if eq .type "sliceOfPtrs" }}
for i := range *es.orig {
new{{ .elementName }}((*es.orig)[i]).CopyTo(new{{ .elementName }}((*dest.orig)[i]))
new{{ .elementName }}((*es.orig)[i], es.state).CopyTo(new{{ .elementName }}((*dest.orig)[i], dest.state))
}
return
}
@ -127,7 +135,7 @@ func (es {{ .structName }}) CopyTo(dest {{ .structName }}) {
wrappers := make([]*{{ .originName }}, srcLen)
for i := range *es.orig {
wrappers[i] = &origs[i]
new{{ .elementName }}((*es.orig)[i]).CopyTo(new{{ .elementName }}(wrappers[i]))
new{{ .elementName }}((*es.orig)[i], es.state).CopyTo(new{{ .elementName }}(wrappers[i], dest.state))
}
*dest.orig = wrappers
@ -136,7 +144,7 @@ func (es {{ .structName }}) CopyTo(dest {{ .structName }}) {
(*dest.orig) = make([]{{ .originElementType }}, srcLen)
}
for i := range *es.orig {
{{ .newElement }}.CopyTo(new{{ .elementName }}(&(*dest.orig)[i]))
{{ .newElement }}.CopyTo(new{{ .elementName }}(&(*dest.orig)[i], dest.state))
}
{{- end }}
}
@ -146,6 +154,7 @@ func (es {{ .structName }}) CopyTo(dest {{ .structName }}) {
// provided less function so that two instances of {{ .structName }}
// can be compared.
func (es {{ .structName }}) Sort(less func(a, b {{ .elementName }}) bool) {
es.state.AssertMutable()
sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) })
}
{{- end }}`
@ -153,7 +162,8 @@ func (es {{ .structName }}) Sort(less func(a, b {{ .elementName }}) bool) {
const sliceTestTemplate = `func Test{{ .structName }}(t *testing.T) {
es := New{{ .structName }}()
assert.Equal(t, 0, es.Len())
es = new{{ .structName }}(&[]{{ .originElementType }}{})
state := internal.StateMutable
es = new{{ .structName }}(&[]{{ .originElementType }}{}, &state)
assert.Equal(t, 0, es.Len())
emptyVal := New{{ .elementName }}()
@ -167,6 +177,19 @@ const sliceTestTemplate = `func Test{{ .structName }}(t *testing.T) {
assert.Equal(t, 7, es.Len())
}
func Test{{ .structName }}ReadOnly(t *testing.T) {
sharedState := internal.StateReadOnly
es := new{{ .structName }}(&[]{{ .originElementType }}{}, &sharedState)
assert.Equal(t, 0, es.Len())
assert.Panics(t, func() { es.AppendEmpty() })
assert.Panics(t, func() { es.EnsureCapacity(2) })
es2 := New{{ .structName }}()
es.CopyTo(es2)
assert.Panics(t, func() { es2.CopyTo(es) })
assert.Panics(t, func() { es.MoveAndAppendTo(es2) })
assert.Panics(t, func() { es2.MoveAndAppendTo(es) })
}
func Test{{ .structName }}_CopyTo(t *testing.T) {
dest := New{{ .structName }}()
// Test CopyTo to empty
@ -324,7 +347,7 @@ func (ss *sliceOfPtrs) templateFields() map[string]any {
"originName": ss.element.originFullName,
"originElementType": "*" + ss.element.originFullName,
"emptyOriginElement": "&" + ss.element.originFullName + "{}",
"newElement": "new" + ss.element.structName + "((*es.orig)[i])",
"newElement": "new" + ss.element.structName + "((*es.orig)[i], es.state)",
}
}
@ -376,7 +399,7 @@ func (ss *sliceOfValues) templateFields() map[string]any {
"originName": ss.element.originFullName,
"originElementType": ss.element.originFullName,
"emptyOriginElement": ss.element.originFullName + "{}",
"newElement": "new" + ss.element.structName + "(&(*es.orig)[i])",
"newElement": "new" + ss.element.structName + "(&(*es.orig)[i], es.state)",
}
}

View File

@ -21,14 +21,15 @@ type {{ .structName }} internal.{{ .structName }}
{{- else }}
type {{ .structName }} struct {
orig *{{ .originName }}
state *internal.State
}
{{- end }}
func new{{ .structName }}(orig *{{ .originName }}) {{ .structName }} {
func new{{ .structName }}(orig *{{ .originName }}, state *internal.State) {{ .structName }} {
{{- if .isCommon }}
return {{ .structName }}(internal.New{{ .structName }}(orig))
return {{ .structName }}(internal.New{{ .structName }}(orig, state))
{{- else }}
return {{ .structName }}{orig}
return {{ .structName }}{orig: orig, state: state}
{{- end }}
}
@ -37,12 +38,15 @@ func new{{ .structName }}(orig *{{ .originName }}) {{ .structName }} {
// This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice,
// OR directly access the member if this is embedded in another struct.
func New{{ .structName }}() {{ .structName }} {
return new{{ .structName }}(&{{ .originName }}{})
state := internal.StateMutable
return new{{ .structName }}(&{{ .originName }}{}, &state)
}
// MoveTo moves all properties from the current struct overriding the destination and
// resetting the current instance to its zero value
func (ms {{ .structName }}) MoveTo(dest {{ .structName }}) {
ms.{{- if .isCommon }}getState(){{ else }}state{{ end }}.AssertMutable()
dest.{{- if .isCommon }}getState(){{ else }}state{{ end }}.AssertMutable()
*dest.{{ .origAccessor }} = *ms.{{ .origAccessor }}
*ms.{{ .origAccessor }} = {{ .originName }}{}
}
@ -51,6 +55,10 @@ func (ms {{ .structName }}) MoveTo(dest {{ .structName }}) {
func (ms {{ .structName }}) getOrig() *{{ .originName }} {
return internal.GetOrig{{ .structName }}(internal.{{ .structName }}(ms))
}
func (ms {{ .structName }}) getState() *internal.State {
return internal.Get{{ .structName }}State(internal.{{ .structName }}(ms))
}
{{- end }}
{{ range .fields -}}
@ -59,9 +67,10 @@ func (ms {{ .structName }}) getOrig() *{{ .originName }} {
// CopyTo copies all properties from the current struct overriding the destination.
func (ms {{ .structName }}) CopyTo(dest {{ .structName }}) {
{{- range .fields }}
{{ .GenerateCopyToValue $.messageStruct }}
{{- end }}
dest.{{- if .isCommon }}getState(){{ else }}state{{ end }}.AssertMutable()
{{- range .fields }}
{{ .GenerateCopyToValue $.messageStruct }}
{{- end }}
}`
const messageValueTestTemplate = `
@ -71,6 +80,9 @@ func Test{{ .structName }}_MoveTo(t *testing.T) {
ms.MoveTo(dest)
assert.Equal(t, New{{ .structName }}(), ms)
assert.Equal(t, {{ .generateTestData }}, dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.MoveTo(new{{ .structName }}(&{{ .originName }}{}, &sharedState)) })
assert.Panics(t, func() { new{{ .structName }}(&{{ .originName }}{}, &sharedState).MoveTo(dest) })
}
func Test{{ .structName }}_CopyTo(t *testing.T) {
@ -81,6 +93,8 @@ func Test{{ .structName }}_CopyTo(t *testing.T) {
orig = {{ .generateTestData }}
orig.CopyTo(ms)
assert.Equal(t, orig, ms)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.CopyTo(new{{ .structName }}(&{{ .originName }}{}, &sharedState)) })
}
{{ range .fields }}
@ -90,8 +104,9 @@ func Test{{ .structName }}_CopyTo(t *testing.T) {
const messageValueGenerateTestTemplate = `func {{ upperIfInternal "g" }}enerateTest{{ .structName }}() {{ .structName }} {
{{- if .isCommon }}
orig := {{ .originName }}{}
state := StateMutable
{{- end }}
tv := New{{ .structName }}({{ if .isCommon }}&orig{{ end }})
tv := New{{ .structName }}({{ if .isCommon }}&orig, &state{{ end }})
{{ upperIfInternal "f" }}illTest{{ .structName }}(tv)
return tv
}
@ -105,14 +120,19 @@ func {{ upperIfInternal "f" }}illTest{{ .structName }}(tv {{ .structName }}) {
const messageValueAliasTemplate = `
type {{ .structName }} struct {
orig *{{ .originName }}
state *State
}
func GetOrig{{ .structName }}(ms {{ .structName }}) *{{ .originName }} {
return ms.orig
}
func New{{ .structName }}(orig *{{ .originName }}) {{ .structName }} {
return {{ .structName }}{orig: orig}
func Get{{ .structName }}State(ms {{ .structName }}) *State {
return ms.state
}
func New{{ .structName }}(orig *{{ .originName }}, state *State) {{ .structName }} {
return {{ .structName }}{orig: orig, state: state}
}`
type baseStruct interface {

View File

@ -20,10 +20,15 @@ func (ms {{ .structName }}) getOrig() *[]{{ .itemType }} {
return internal.GetOrig{{ .structName }}(internal.{{ .structName }}(ms))
}
func (ms {{ .structName }}) getState() *internal.State {
return internal.Get{{ .structName }}State(internal.{{ .structName }}(ms))
}
// New{{ .structName }} creates a new empty {{ .structName }}.
func New{{ .structName }}() {{ .structName }} {
orig := []{{ .itemType }}(nil)
return {{ .structName }}(internal.New{{ .structName }}(&orig))
state := internal.StateMutable
return {{ .structName }}(internal.New{{ .structName }}(&orig, &state))
}
// AsRaw returns a copy of the []{{ .itemType }} slice.
@ -33,6 +38,7 @@ func (ms {{ .structName }}) AsRaw() []{{ .itemType }} {
// FromRaw copies raw []{{ .itemType }} into the slice {{ .structName }}.
func (ms {{ .structName }}) FromRaw(val []{{ .itemType }}) {
ms.getState().AssertMutable()
*ms.getOrig() = copy{{ .structName }}(*ms.getOrig(), val)
}
@ -51,6 +57,7 @@ func (ms {{ .structName }}) At(i int) {{ .itemType }} {
// SetAt sets {{ .itemType }} item at particular index.
// Equivalent of {{ .lowerStructName }}[i] = val
func (ms {{ .structName }}) SetAt(i int, val {{ .itemType }}) {
ms.getState().AssertMutable()
(*ms.getOrig())[i] = val
}
@ -61,6 +68,7 @@ func (ms {{ .structName }}) SetAt(i int, val {{ .itemType }}) {
// copy(buf, {{ .lowerStructName }})
// {{ .lowerStructName }} = buf
func (ms {{ .structName }}) EnsureCapacity(newCap int) {
ms.getState().AssertMutable()
oldCap := cap(*ms.getOrig())
if newCap <= oldCap {
return
@ -74,18 +82,22 @@ func (ms {{ .structName }}) EnsureCapacity(newCap int) {
// Append appends extra elements to {{ .structName }}.
// Equivalent of {{ .lowerStructName }} = append({{ .lowerStructName }}, elms...)
func (ms {{ .structName }}) Append(elms ...{{ .itemType }}) {
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 {{ .structName }}) MoveTo(dest {{ .structName }}) {
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 {{ .structName }}) CopyTo(dest {{ .structName }}) {
dest.getState().AssertMutable()
*dest.getOrig() = copy{{ .structName }}(*dest.getOrig(), *ms.getOrig())
}
@ -125,6 +137,27 @@ const immutableSliceTestTemplate = `func TestNew{{ .structName }}(t *testing.T)
assert.Equal(t, {{ .itemType }}(1), mv.At(0))
}
func Test{{ .structName }}ReadOnly(t *testing.T) {
raw := []{{ .itemType }}{1, 2, 3}
state := internal.StateReadOnly
ms := {{ .structName }}(internal.New{{ .structName }}(&raw, &state))
assert.Equal(t, 3, ms.Len())
assert.Equal(t, {{ .itemType }}(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 := New{{ .structName }}()
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 Test{{ .structName }}Append(t *testing.T) {
ms := New{{ .structName }}()
ms.FromRaw([]{{ .itemType }}{1, 2, 3})
@ -144,14 +177,19 @@ func Test{{ .structName }}EnsureCapacity(t *testing.T) {
const primitiveSliceInternalTemplate = `
type {{ .structName }} struct {
orig *[]{{ .itemType }}
state *State
}
func GetOrig{{ .structName }}(ms {{ .structName }}) *[]{{ .itemType }} {
return ms.orig
}
func New{{ .structName }}(orig *[]{{ .itemType }}) {{ .structName }} {
return {{ .structName }}{orig: orig}
func Get{{ .structName }}State(ms {{ .structName }}) *State {
return ms.state
}
func New{{ .structName }}(orig *[]{{ .itemType }}, state *State) {{ .structName }} {
return {{ .structName }}{orig: orig, state: state}
}`
// primitiveSliceStruct generates a struct for a slice of primitive value elements. The structs are always generated

View File

@ -7,13 +7,18 @@
package internal
type ByteSlice struct {
orig *[]byte
orig *[]byte
state *State
}
func GetOrigByteSlice(ms ByteSlice) *[]byte {
return ms.orig
}
func NewByteSlice(orig *[]byte) ByteSlice {
return ByteSlice{orig: orig}
func GetByteSliceState(ms ByteSlice) *State {
return ms.state
}
func NewByteSlice(orig *[]byte, state *State) ByteSlice {
return ByteSlice{orig: orig, state: state}
}

View File

@ -7,13 +7,18 @@
package internal
type Float64Slice struct {
orig *[]float64
orig *[]float64
state *State
}
func GetOrigFloat64Slice(ms Float64Slice) *[]float64 {
return ms.orig
}
func NewFloat64Slice(orig *[]float64) Float64Slice {
return Float64Slice{orig: orig}
func GetFloat64SliceState(ms Float64Slice) *State {
return ms.state
}
func NewFloat64Slice(orig *[]float64, state *State) Float64Slice {
return Float64Slice{orig: orig, state: state}
}

View File

@ -11,20 +11,26 @@ import (
)
type InstrumentationScope struct {
orig *otlpcommon.InstrumentationScope
orig *otlpcommon.InstrumentationScope
state *State
}
func GetOrigInstrumentationScope(ms InstrumentationScope) *otlpcommon.InstrumentationScope {
return ms.orig
}
func NewInstrumentationScope(orig *otlpcommon.InstrumentationScope) InstrumentationScope {
return InstrumentationScope{orig: orig}
func GetInstrumentationScopeState(ms InstrumentationScope) *State {
return ms.state
}
func NewInstrumentationScope(orig *otlpcommon.InstrumentationScope, state *State) InstrumentationScope {
return InstrumentationScope{orig: orig, state: state}
}
func GenerateTestInstrumentationScope() InstrumentationScope {
orig := otlpcommon.InstrumentationScope{}
tv := NewInstrumentationScope(&orig)
state := StateMutable
tv := NewInstrumentationScope(&orig, &state)
FillTestInstrumentationScope(tv)
return tv
}
@ -32,6 +38,6 @@ func GenerateTestInstrumentationScope() InstrumentationScope {
func FillTestInstrumentationScope(tv InstrumentationScope) {
tv.orig.Name = "test_name"
tv.orig.Version = "test_version"
FillTestMap(NewMap(&tv.orig.Attributes))
FillTestMap(NewMap(&tv.orig.Attributes, tv.state))
tv.orig.DroppedAttributesCount = uint32(17)
}

View File

@ -11,25 +11,31 @@ import (
)
type Resource struct {
orig *otlpresource.Resource
orig *otlpresource.Resource
state *State
}
func GetOrigResource(ms Resource) *otlpresource.Resource {
return ms.orig
}
func NewResource(orig *otlpresource.Resource) Resource {
return Resource{orig: orig}
func GetResourceState(ms Resource) *State {
return ms.state
}
func NewResource(orig *otlpresource.Resource, state *State) Resource {
return Resource{orig: orig, state: state}
}
func GenerateTestResource() Resource {
orig := otlpresource.Resource{}
tv := NewResource(&orig)
state := StateMutable
tv := NewResource(&orig, &state)
FillTestResource(tv)
return tv
}
func FillTestResource(tv Resource) {
FillTestMap(NewMap(&tv.orig.Attributes))
FillTestMap(NewMap(&tv.orig.Attributes, tv.state))
tv.orig.DroppedAttributesCount = uint32(17)
}

View File

@ -7,13 +7,18 @@
package internal
type UInt64Slice struct {
orig *[]uint64
orig *[]uint64
state *State
}
func GetOrigUInt64Slice(ms UInt64Slice) *[]uint64 {
return ms.orig
}
func NewUInt64Slice(orig *[]uint64) UInt64Slice {
return UInt64Slice{orig: orig}
func GetUInt64SliceState(ms UInt64Slice) *State {
return ms.state
}
func NewUInt64Slice(orig *[]uint64, state *State) UInt64Slice {
return UInt64Slice{orig: orig, state: state}
}

22
pdata/internal/state.go Normal file
View File

@ -0,0 +1,22 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package internal // import "go.opentelemetry.io/collector/pdata/internal"
// State defines an ownership state of pmetric.Metrics, plog.Logs or ptrace.Traces.
type State int32
const (
// StateMutable indicates that the data is exclusive to the current consumer.
StateMutable State = iota
// StateReadOnly indicates that the data is shared with other consumers.
StateReadOnly
)
// AssertMutable panics if the state is not StateMutable.
func (state *State) AssertMutable() {
if *state != StateMutable {
panic("invalid access to shared data")
}
}

View File

@ -9,15 +9,24 @@ import (
)
type Logs struct {
orig *otlpcollectorlog.ExportLogsServiceRequest
orig *otlpcollectorlog.ExportLogsServiceRequest
state *State
}
func GetOrigLogs(ms Logs) *otlpcollectorlog.ExportLogsServiceRequest {
return ms.orig
}
func NewLogs(orig *otlpcollectorlog.ExportLogsServiceRequest) Logs {
return Logs{orig: orig}
func GetLogsState(ms Logs) *State {
return ms.state
}
func SetLogsState(ms Logs, state State) {
*ms.state = state
}
func NewLogs(orig *otlpcollectorlog.ExportLogsServiceRequest, state *State) Logs {
return Logs{orig: orig, state: state}
}
// LogsToProto internal helper to convert Logs to protobuf representation.
@ -28,8 +37,10 @@ func LogsToProto(l Logs) otlplogs.LogsData {
}
// LogsFromProto internal helper to convert protobuf representation to Logs.
// This function set exclusive state assuming that it's called only once per Logs.
func LogsFromProto(orig otlplogs.LogsData) Logs {
return Logs{orig: &otlpcollectorlog.ExportLogsServiceRequest{
state := StateMutable
return NewLogs(&otlpcollectorlog.ExportLogsServiceRequest{
ResourceLogs: orig.ResourceLogs,
}}
}, &state)
}

View File

@ -8,20 +8,26 @@ import (
)
type Map struct {
orig *[]otlpcommon.KeyValue
orig *[]otlpcommon.KeyValue
state *State
}
func GetOrigMap(ms Map) *[]otlpcommon.KeyValue {
return ms.orig
}
func NewMap(orig *[]otlpcommon.KeyValue) Map {
return Map{orig: orig}
func GetMapState(ms Map) *State {
return ms.state
}
func NewMap(orig *[]otlpcommon.KeyValue, state *State) Map {
return Map{orig: orig, state: state}
}
func GenerateTestMap() Map {
var orig []otlpcommon.KeyValue
ms := NewMap(&orig)
state := StateMutable
ms := NewMap(&orig, &state)
FillTestMap(ms)
return ms
}

View File

@ -9,15 +9,24 @@ import (
)
type Metrics struct {
orig *otlpcollectormetrics.ExportMetricsServiceRequest
orig *otlpcollectormetrics.ExportMetricsServiceRequest
state *State
}
func GetOrigMetrics(ms Metrics) *otlpcollectormetrics.ExportMetricsServiceRequest {
return ms.orig
}
func NewMetrics(orig *otlpcollectormetrics.ExportMetricsServiceRequest) Metrics {
return Metrics{orig: orig}
func GetMetricsState(ms Metrics) *State {
return ms.state
}
func SetMetricsState(ms Metrics, state State) {
*ms.state = state
}
func NewMetrics(orig *otlpcollectormetrics.ExportMetricsServiceRequest, state *State) Metrics {
return Metrics{orig: orig, state: state}
}
// MetricsToProto internal helper to convert Metrics to protobuf representation.
@ -28,8 +37,10 @@ func MetricsToProto(l Metrics) otlpmetrics.MetricsData {
}
// MetricsFromProto internal helper to convert protobuf representation to Metrics.
// This function set exclusive state assuming that it's called only once per Metrics.
func MetricsFromProto(orig otlpmetrics.MetricsData) Metrics {
return Metrics{orig: &otlpcollectormetrics.ExportMetricsServiceRequest{
state := StateMutable
return NewMetrics(&otlpcollectormetrics.ExportMetricsServiceRequest{
ResourceMetrics: orig.ResourceMetrics,
}}
}, &state)
}

View File

@ -8,20 +8,26 @@ import (
)
type Slice struct {
orig *[]otlpcommon.AnyValue
orig *[]otlpcommon.AnyValue
state *State
}
func GetOrigSlice(ms Slice) *[]otlpcommon.AnyValue {
return ms.orig
}
func NewSlice(orig *[]otlpcommon.AnyValue) Slice {
return Slice{orig: orig}
func GetSliceState(ms Slice) *State {
return ms.state
}
func NewSlice(orig *[]otlpcommon.AnyValue, state *State) Slice {
return Slice{orig: orig, state: state}
}
func GenerateTestSlice() Slice {
orig := []otlpcommon.AnyValue{}
tv := NewSlice(&orig)
state := StateMutable
tv := NewSlice(&orig, &state)
FillTestSlice(tv)
return tv
}
@ -29,6 +35,7 @@ func GenerateTestSlice() Slice {
func FillTestSlice(tv Slice) {
*tv.orig = make([]otlpcommon.AnyValue, 7)
for i := 0; i < 7; i++ {
FillTestValue(NewValue(&(*tv.orig)[i]))
state := StateMutable
FillTestValue(NewValue(&(*tv.orig)[i], &state))
}
}

View File

@ -9,15 +9,24 @@ import (
)
type Traces struct {
orig *otlpcollectortrace.ExportTraceServiceRequest
orig *otlpcollectortrace.ExportTraceServiceRequest
state *State
}
func GetOrigTraces(ms Traces) *otlpcollectortrace.ExportTraceServiceRequest {
return ms.orig
}
func NewTraces(orig *otlpcollectortrace.ExportTraceServiceRequest) Traces {
return Traces{orig: orig}
func GetTracesState(ms Traces) *State {
return ms.state
}
func SetTracesState(ms Traces, state State) {
*ms.state = state
}
func NewTraces(orig *otlpcollectortrace.ExportTraceServiceRequest, state *State) Traces {
return Traces{orig: orig, state: state}
}
// TracesToProto internal helper to convert Traces to protobuf representation.
@ -28,8 +37,10 @@ func TracesToProto(l Traces) otlptrace.TracesData {
}
// TracesFromProto internal helper to convert protobuf representation to Traces.
// This function set exclusive state assuming that it's called only once per Traces.
func TracesFromProto(orig otlptrace.TracesData) Traces {
return Traces{orig: &otlpcollectortrace.ExportTraceServiceRequest{
state := StateMutable
return NewTraces(&otlpcollectortrace.ExportTraceServiceRequest{
ResourceSpans: orig.ResourceSpans,
}}
}, &state)
}

View File

@ -4,20 +4,26 @@
package internal // import "go.opentelemetry.io/collector/pdata/internal"
type TraceState struct {
orig *string
orig *string
state *State
}
func GetOrigTraceState(ms TraceState) *string {
return ms.orig
}
func NewTraceState(orig *string) TraceState {
return TraceState{orig: orig}
func GetTraceStateState(ms TraceState) *State {
return ms.state
}
func NewTraceState(orig *string, state *State) TraceState {
return TraceState{orig: orig, state: state}
}
func GenerateTestTraceState() TraceState {
var orig string
ms := NewTraceState(&orig)
state := StateMutable
ms := NewTraceState(&orig, &state)
FillTestTraceState(ms)
return ms
}

View File

@ -8,15 +8,20 @@ import (
)
type Value struct {
orig *otlpcommon.AnyValue
orig *otlpcommon.AnyValue
state *State
}
func GetOrigValue(ms Value) *otlpcommon.AnyValue {
return ms.orig
}
func NewValue(orig *otlpcommon.AnyValue) Value {
return Value{orig: orig}
func GetValueState(ms Value) *State {
return ms.state
}
func NewValue(orig *otlpcommon.AnyValue, state *State) Value {
return Value{orig: orig, state: state}
}
func FillTestValue(dest Value) {
@ -25,7 +30,8 @@ func FillTestValue(dest Value) {
func GenerateTestValue() Value {
var orig otlpcommon.AnyValue
ms := NewValue(&orig)
state := StateMutable
ms := NewValue(&orig, &state)
FillTestValue(ms)
return ms
}

View File

@ -21,10 +21,15 @@ func (ms ByteSlice) getOrig() *[]byte {
return internal.GetOrigByteSlice(internal.ByteSlice(ms))
}
func (ms ByteSlice) getState() *internal.State {
return internal.GetByteSliceState(internal.ByteSlice(ms))
}
// NewByteSlice creates a new empty ByteSlice.
func NewByteSlice() ByteSlice {
orig := []byte(nil)
return ByteSlice(internal.NewByteSlice(&orig))
state := internal.StateMutable
return ByteSlice(internal.NewByteSlice(&orig, &state))
}
// AsRaw returns a copy of the []byte slice.
@ -34,6 +39,7 @@ func (ms ByteSlice) AsRaw() []byte {
// FromRaw copies raw []byte into the slice ByteSlice.
func (ms ByteSlice) FromRaw(val []byte) {
ms.getState().AssertMutable()
*ms.getOrig() = copyByteSlice(*ms.getOrig(), val)
}
@ -52,6 +58,7 @@ func (ms ByteSlice) At(i int) byte {
// SetAt sets byte item at particular index.
// Equivalent of byteSlice[i] = val
func (ms ByteSlice) SetAt(i int, val byte) {
ms.getState().AssertMutable()
(*ms.getOrig())[i] = val
}
@ -62,6 +69,7 @@ func (ms ByteSlice) SetAt(i int, val byte) {
// copy(buf, byteSlice)
// byteSlice = buf
func (ms ByteSlice) EnsureCapacity(newCap int) {
ms.getState().AssertMutable()
oldCap := cap(*ms.getOrig())
if newCap <= oldCap {
return
@ -75,18 +83,22 @@ func (ms ByteSlice) EnsureCapacity(newCap int) {
// Append appends extra elements to ByteSlice.
// Equivalent of byteSlice = append(byteSlice, elms...)
func (ms ByteSlice) Append(elms ...byte) {
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 ByteSlice) MoveTo(dest ByteSlice) {
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 ByteSlice) CopyTo(dest ByteSlice) {
dest.getState().AssertMutable()
*dest.getOrig() = copyByteSlice(*dest.getOrig(), *ms.getOrig())
}

View File

@ -10,6 +10,8 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
)
func TestNewByteSlice(t *testing.T) {
@ -43,6 +45,27 @@ func TestNewByteSlice(t *testing.T) {
assert.Equal(t, byte(1), mv.At(0))
}
func TestByteSliceReadOnly(t *testing.T) {
raw := []byte{1, 2, 3}
state := internal.StateReadOnly
ms := ByteSlice(internal.NewByteSlice(&raw, &state))
assert.Equal(t, 3, ms.Len())
assert.Equal(t, byte(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 := NewByteSlice()
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 TestByteSliceAppend(t *testing.T) {
ms := NewByteSlice()
ms.FromRaw([]byte{1, 2, 3})

View File

@ -21,10 +21,15 @@ func (ms Float64Slice) getOrig() *[]float64 {
return internal.GetOrigFloat64Slice(internal.Float64Slice(ms))
}
func (ms Float64Slice) getState() *internal.State {
return internal.GetFloat64SliceState(internal.Float64Slice(ms))
}
// NewFloat64Slice creates a new empty Float64Slice.
func NewFloat64Slice() Float64Slice {
orig := []float64(nil)
return Float64Slice(internal.NewFloat64Slice(&orig))
state := internal.StateMutable
return Float64Slice(internal.NewFloat64Slice(&orig, &state))
}
// AsRaw returns a copy of the []float64 slice.
@ -34,6 +39,7 @@ func (ms Float64Slice) AsRaw() []float64 {
// FromRaw copies raw []float64 into the slice Float64Slice.
func (ms Float64Slice) FromRaw(val []float64) {
ms.getState().AssertMutable()
*ms.getOrig() = copyFloat64Slice(*ms.getOrig(), val)
}
@ -52,6 +58,7 @@ func (ms Float64Slice) At(i int) float64 {
// SetAt sets float64 item at particular index.
// Equivalent of float64Slice[i] = val
func (ms Float64Slice) SetAt(i int, val float64) {
ms.getState().AssertMutable()
(*ms.getOrig())[i] = val
}
@ -62,6 +69,7 @@ func (ms Float64Slice) SetAt(i int, val float64) {
// copy(buf, float64Slice)
// float64Slice = buf
func (ms Float64Slice) EnsureCapacity(newCap int) {
ms.getState().AssertMutable()
oldCap := cap(*ms.getOrig())
if newCap <= oldCap {
return
@ -75,18 +83,22 @@ func (ms Float64Slice) EnsureCapacity(newCap int) {
// Append appends extra elements to Float64Slice.
// Equivalent of float64Slice = append(float64Slice, elms...)
func (ms Float64Slice) Append(elms ...float64) {
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 Float64Slice) MoveTo(dest Float64Slice) {
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 Float64Slice) CopyTo(dest Float64Slice) {
dest.getState().AssertMutable()
*dest.getOrig() = copyFloat64Slice(*dest.getOrig(), *ms.getOrig())
}

View File

@ -10,6 +10,8 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
)
func TestNewFloat64Slice(t *testing.T) {
@ -43,6 +45,27 @@ func TestNewFloat64Slice(t *testing.T) {
assert.Equal(t, float64(1), mv.At(0))
}
func TestFloat64SliceReadOnly(t *testing.T) {
raw := []float64{1, 2, 3}
state := internal.StateReadOnly
ms := Float64Slice(internal.NewFloat64Slice(&raw, &state))
assert.Equal(t, 3, ms.Len())
assert.Equal(t, float64(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 := NewFloat64Slice()
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 TestFloat64SliceAppend(t *testing.T) {
ms := NewFloat64Slice()
ms.FromRaw([]float64{1, 2, 3})

View File

@ -20,8 +20,8 @@ import (
// Important: zero-initialized instance is not valid for use.
type InstrumentationScope internal.InstrumentationScope
func newInstrumentationScope(orig *otlpcommon.InstrumentationScope) InstrumentationScope {
return InstrumentationScope(internal.NewInstrumentationScope(orig))
func newInstrumentationScope(orig *otlpcommon.InstrumentationScope, state *internal.State) InstrumentationScope {
return InstrumentationScope(internal.NewInstrumentationScope(orig, state))
}
// NewInstrumentationScope creates a new empty InstrumentationScope.
@ -29,12 +29,15 @@ func newInstrumentationScope(orig *otlpcommon.InstrumentationScope) Instrumentat
// This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice,
// OR directly access the member if this is embedded in another struct.
func NewInstrumentationScope() InstrumentationScope {
return newInstrumentationScope(&otlpcommon.InstrumentationScope{})
state := internal.StateMutable
return newInstrumentationScope(&otlpcommon.InstrumentationScope{}, &state)
}
// MoveTo moves all properties from the current struct overriding the destination and
// resetting the current instance to its zero value
func (ms InstrumentationScope) MoveTo(dest InstrumentationScope) {
ms.getState().AssertMutable()
dest.getState().AssertMutable()
*dest.getOrig() = *ms.getOrig()
*ms.getOrig() = otlpcommon.InstrumentationScope{}
}
@ -43,6 +46,10 @@ func (ms InstrumentationScope) getOrig() *otlpcommon.InstrumentationScope {
return internal.GetOrigInstrumentationScope(internal.InstrumentationScope(ms))
}
func (ms InstrumentationScope) getState() *internal.State {
return internal.GetInstrumentationScopeState(internal.InstrumentationScope(ms))
}
// Name returns the name associated with this InstrumentationScope.
func (ms InstrumentationScope) Name() string {
return ms.getOrig().Name
@ -50,6 +57,7 @@ func (ms InstrumentationScope) Name() string {
// SetName replaces the name associated with this InstrumentationScope.
func (ms InstrumentationScope) SetName(v string) {
ms.getState().AssertMutable()
ms.getOrig().Name = v
}
@ -60,12 +68,13 @@ func (ms InstrumentationScope) Version() string {
// SetVersion replaces the version associated with this InstrumentationScope.
func (ms InstrumentationScope) SetVersion(v string) {
ms.getState().AssertMutable()
ms.getOrig().Version = v
}
// Attributes returns the Attributes associated with this InstrumentationScope.
func (ms InstrumentationScope) Attributes() Map {
return Map(internal.NewMap(&ms.getOrig().Attributes))
return Map(internal.NewMap(&ms.getOrig().Attributes, internal.GetInstrumentationScopeState(internal.InstrumentationScope(ms))))
}
// DroppedAttributesCount returns the droppedattributescount associated with this InstrumentationScope.
@ -75,11 +84,13 @@ func (ms InstrumentationScope) DroppedAttributesCount() uint32 {
// SetDroppedAttributesCount replaces the droppedattributescount associated with this InstrumentationScope.
func (ms InstrumentationScope) SetDroppedAttributesCount(v uint32) {
ms.getState().AssertMutable()
ms.getOrig().DroppedAttributesCount = v
}
// CopyTo copies all properties from the current struct overriding the destination.
func (ms InstrumentationScope) CopyTo(dest InstrumentationScope) {
dest.getState().AssertMutable()
dest.SetName(ms.Name())
dest.SetVersion(ms.Version())
ms.Attributes().CopyTo(dest.Attributes())

View File

@ -12,6 +12,7 @@ import (
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlpcommon "go.opentelemetry.io/collector/pdata/internal/data/protogen/common/v1"
)
func TestInstrumentationScope_MoveTo(t *testing.T) {
@ -20,6 +21,9 @@ func TestInstrumentationScope_MoveTo(t *testing.T) {
ms.MoveTo(dest)
assert.Equal(t, NewInstrumentationScope(), ms)
assert.Equal(t, InstrumentationScope(internal.GenerateTestInstrumentationScope()), dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.MoveTo(newInstrumentationScope(&otlpcommon.InstrumentationScope{}, &sharedState)) })
assert.Panics(t, func() { newInstrumentationScope(&otlpcommon.InstrumentationScope{}, &sharedState).MoveTo(dest) })
}
func TestInstrumentationScope_CopyTo(t *testing.T) {
@ -30,6 +34,8 @@ func TestInstrumentationScope_CopyTo(t *testing.T) {
orig = InstrumentationScope(internal.GenerateTestInstrumentationScope())
orig.CopyTo(ms)
assert.Equal(t, orig, ms)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.CopyTo(newInstrumentationScope(&otlpcommon.InstrumentationScope{}, &sharedState)) })
}
func TestInstrumentationScope_Name(t *testing.T) {
@ -37,6 +43,8 @@ func TestInstrumentationScope_Name(t *testing.T) {
assert.Equal(t, "", ms.Name())
ms.SetName("test_name")
assert.Equal(t, "test_name", ms.Name())
sharedState := internal.StateReadOnly
assert.Panics(t, func() { newInstrumentationScope(&otlpcommon.InstrumentationScope{}, &sharedState).SetName("test_name") })
}
func TestInstrumentationScope_Version(t *testing.T) {
@ -44,6 +52,10 @@ func TestInstrumentationScope_Version(t *testing.T) {
assert.Equal(t, "", ms.Version())
ms.SetVersion("test_version")
assert.Equal(t, "test_version", ms.Version())
sharedState := internal.StateReadOnly
assert.Panics(t, func() {
newInstrumentationScope(&otlpcommon.InstrumentationScope{}, &sharedState).SetVersion("test_version")
})
}
func TestInstrumentationScope_Attributes(t *testing.T) {
@ -58,4 +70,8 @@ func TestInstrumentationScope_DroppedAttributesCount(t *testing.T) {
assert.Equal(t, uint32(0), ms.DroppedAttributesCount())
ms.SetDroppedAttributesCount(uint32(17))
assert.Equal(t, uint32(17), ms.DroppedAttributesCount())
sharedState := internal.StateReadOnly
assert.Panics(t, func() {
newInstrumentationScope(&otlpcommon.InstrumentationScope{}, &sharedState).SetDroppedAttributesCount(uint32(17))
})
}

View File

@ -20,8 +20,8 @@ import (
// Important: zero-initialized instance is not valid for use.
type Resource internal.Resource
func newResource(orig *otlpresource.Resource) Resource {
return Resource(internal.NewResource(orig))
func newResource(orig *otlpresource.Resource, state *internal.State) Resource {
return Resource(internal.NewResource(orig, state))
}
// NewResource creates a new empty Resource.
@ -29,12 +29,15 @@ func newResource(orig *otlpresource.Resource) Resource {
// This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice,
// OR directly access the member if this is embedded in another struct.
func NewResource() Resource {
return newResource(&otlpresource.Resource{})
state := internal.StateMutable
return newResource(&otlpresource.Resource{}, &state)
}
// MoveTo moves all properties from the current struct overriding the destination and
// resetting the current instance to its zero value
func (ms Resource) MoveTo(dest Resource) {
ms.getState().AssertMutable()
dest.getState().AssertMutable()
*dest.getOrig() = *ms.getOrig()
*ms.getOrig() = otlpresource.Resource{}
}
@ -43,9 +46,13 @@ func (ms Resource) getOrig() *otlpresource.Resource {
return internal.GetOrigResource(internal.Resource(ms))
}
func (ms Resource) getState() *internal.State {
return internal.GetResourceState(internal.Resource(ms))
}
// Attributes returns the Attributes associated with this Resource.
func (ms Resource) Attributes() Map {
return Map(internal.NewMap(&ms.getOrig().Attributes))
return Map(internal.NewMap(&ms.getOrig().Attributes, internal.GetResourceState(internal.Resource(ms))))
}
// DroppedAttributesCount returns the droppedattributescount associated with this Resource.
@ -55,11 +62,13 @@ func (ms Resource) DroppedAttributesCount() uint32 {
// SetDroppedAttributesCount replaces the droppedattributescount associated with this Resource.
func (ms Resource) SetDroppedAttributesCount(v uint32) {
ms.getState().AssertMutable()
ms.getOrig().DroppedAttributesCount = v
}
// CopyTo copies all properties from the current struct overriding the destination.
func (ms Resource) CopyTo(dest Resource) {
dest.getState().AssertMutable()
ms.Attributes().CopyTo(dest.Attributes())
dest.SetDroppedAttributesCount(ms.DroppedAttributesCount())
}

View File

@ -12,6 +12,7 @@ import (
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlpresource "go.opentelemetry.io/collector/pdata/internal/data/protogen/resource/v1"
)
func TestResource_MoveTo(t *testing.T) {
@ -20,6 +21,9 @@ func TestResource_MoveTo(t *testing.T) {
ms.MoveTo(dest)
assert.Equal(t, NewResource(), ms)
assert.Equal(t, Resource(internal.GenerateTestResource()), dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.MoveTo(newResource(&otlpresource.Resource{}, &sharedState)) })
assert.Panics(t, func() { newResource(&otlpresource.Resource{}, &sharedState).MoveTo(dest) })
}
func TestResource_CopyTo(t *testing.T) {
@ -30,6 +34,8 @@ func TestResource_CopyTo(t *testing.T) {
orig = Resource(internal.GenerateTestResource())
orig.CopyTo(ms)
assert.Equal(t, orig, ms)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.CopyTo(newResource(&otlpresource.Resource{}, &sharedState)) })
}
func TestResource_Attributes(t *testing.T) {
@ -44,4 +50,6 @@ func TestResource_DroppedAttributesCount(t *testing.T) {
assert.Equal(t, uint32(0), ms.DroppedAttributesCount())
ms.SetDroppedAttributesCount(uint32(17))
assert.Equal(t, uint32(17), ms.DroppedAttributesCount())
sharedState := internal.StateReadOnly
assert.Panics(t, func() { newResource(&otlpresource.Resource{}, &sharedState).SetDroppedAttributesCount(uint32(17)) })
}

View File

@ -21,10 +21,15 @@ func (ms UInt64Slice) getOrig() *[]uint64 {
return internal.GetOrigUInt64Slice(internal.UInt64Slice(ms))
}
func (ms UInt64Slice) getState() *internal.State {
return internal.GetUInt64SliceState(internal.UInt64Slice(ms))
}
// NewUInt64Slice creates a new empty UInt64Slice.
func NewUInt64Slice() UInt64Slice {
orig := []uint64(nil)
return UInt64Slice(internal.NewUInt64Slice(&orig))
state := internal.StateMutable
return UInt64Slice(internal.NewUInt64Slice(&orig, &state))
}
// AsRaw returns a copy of the []uint64 slice.
@ -34,6 +39,7 @@ func (ms UInt64Slice) AsRaw() []uint64 {
// FromRaw copies raw []uint64 into the slice UInt64Slice.
func (ms UInt64Slice) FromRaw(val []uint64) {
ms.getState().AssertMutable()
*ms.getOrig() = copyUInt64Slice(*ms.getOrig(), val)
}
@ -52,6 +58,7 @@ func (ms UInt64Slice) At(i int) uint64 {
// SetAt sets uint64 item at particular index.
// Equivalent of uInt64Slice[i] = val
func (ms UInt64Slice) SetAt(i int, val uint64) {
ms.getState().AssertMutable()
(*ms.getOrig())[i] = val
}
@ -62,6 +69,7 @@ func (ms UInt64Slice) SetAt(i int, val uint64) {
// copy(buf, uInt64Slice)
// uInt64Slice = buf
func (ms UInt64Slice) EnsureCapacity(newCap int) {
ms.getState().AssertMutable()
oldCap := cap(*ms.getOrig())
if newCap <= oldCap {
return
@ -75,18 +83,22 @@ func (ms UInt64Slice) EnsureCapacity(newCap int) {
// Append appends extra elements to UInt64Slice.
// Equivalent of uInt64Slice = append(uInt64Slice, elms...)
func (ms UInt64Slice) Append(elms ...uint64) {
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 UInt64Slice) MoveTo(dest UInt64Slice) {
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 UInt64Slice) CopyTo(dest UInt64Slice) {
dest.getState().AssertMutable()
*dest.getOrig() = copyUInt64Slice(*dest.getOrig(), *ms.getOrig())
}

View File

@ -10,6 +10,8 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
)
func TestNewUInt64Slice(t *testing.T) {
@ -43,6 +45,27 @@ func TestNewUInt64Slice(t *testing.T) {
assert.Equal(t, uint64(1), mv.At(0))
}
func TestUInt64SliceReadOnly(t *testing.T) {
raw := []uint64{1, 2, 3}
state := internal.StateReadOnly
ms := UInt64Slice(internal.NewUInt64Slice(&raw, &state))
assert.Equal(t, 3, ms.Len())
assert.Equal(t, uint64(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 := NewUInt64Slice()
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 TestUInt64SliceAppend(t *testing.T) {
ms := NewUInt64Slice()
ms.FromRaw([]uint64{1, 2, 3})

View File

@ -16,25 +16,32 @@ type Map internal.Map
// NewMap creates a Map with 0 elements.
func NewMap() Map {
orig := []otlpcommon.KeyValue(nil)
return Map(internal.NewMap(&orig))
state := internal.StateMutable
return Map(internal.NewMap(&orig, &state))
}
func (m Map) getOrig() *[]otlpcommon.KeyValue {
return internal.GetOrigMap(internal.Map(m))
}
func newMap(orig *[]otlpcommon.KeyValue) Map {
return Map(internal.NewMap(orig))
func (m Map) getState() *internal.State {
return internal.GetMapState(internal.Map(m))
}
func newMap(orig *[]otlpcommon.KeyValue, state *internal.State) Map {
return Map(internal.NewMap(orig, state))
}
// Clear erases any existing entries in this Map instance.
func (m Map) Clear() {
m.getState().AssertMutable()
*m.getOrig() = nil
}
// EnsureCapacity increases the capacity of this Map instance, if necessary,
// to ensure that it can hold at least the number of elements specified by the capacity argument.
func (m Map) EnsureCapacity(capacity int) {
m.getState().AssertMutable()
oldOrig := *m.getOrig()
if capacity <= cap(oldOrig) {
return
@ -54,15 +61,16 @@ func (m Map) Get(key string) (Value, bool) {
for i := range *m.getOrig() {
akv := &(*m.getOrig())[i]
if akv.Key == key {
return newValue(&akv.Value), true
return newValue(&akv.Value, m.getState()), true
}
}
return newValue(nil), false
return newValue(nil, m.getState()), false
}
// Remove removes the entry associated with the key and returns true if the key
// was present in the map, otherwise returns false.
func (m Map) Remove(key string) bool {
m.getState().AssertMutable()
for i := range *m.getOrig() {
akv := &(*m.getOrig())[i]
if akv.Key == key {
@ -76,10 +84,11 @@ func (m Map) Remove(key string) bool {
// RemoveIf removes the entries for which the function in question returns true
func (m Map) RemoveIf(f func(string, Value) bool) {
m.getState().AssertMutable()
newLen := 0
for i := 0; i < len(*m.getOrig()); i++ {
akv := &(*m.getOrig())[i]
if f(akv.Key, newValue(&akv.Value)) {
if f(akv.Key, newValue(&akv.Value, m.getState())) {
continue
}
if newLen == i {
@ -96,18 +105,20 @@ func (m Map) RemoveIf(f func(string, Value) bool) {
// PutEmpty inserts or updates an empty value to the map under given key
// and return the updated/inserted value.
func (m Map) PutEmpty(k string) Value {
m.getState().AssertMutable()
if av, existing := m.Get(k); existing {
av.getOrig().Value = nil
return newValue(av.getOrig())
return newValue(av.getOrig(), m.getState())
}
*m.getOrig() = append(*m.getOrig(), otlpcommon.KeyValue{Key: k})
return newValue(&(*m.getOrig())[len(*m.getOrig())-1].Value)
return newValue(&(*m.getOrig())[len(*m.getOrig())-1].Value, m.getState())
}
// PutStr performs the Insert or Update action. The Value is
// inserted to the map that did not originally have the key. The key/value is
// updated to the map where the key already existed.
func (m Map) PutStr(k string, v string) {
m.getState().AssertMutable()
if av, existing := m.Get(k); existing {
av.SetStr(v)
} else {
@ -119,6 +130,7 @@ func (m Map) PutStr(k string, v string) {
// inserted to the map that did not originally have the key. The key/value is
// updated to the map where the key already existed.
func (m Map) PutInt(k string, v int64) {
m.getState().AssertMutable()
if av, existing := m.Get(k); existing {
av.SetInt(v)
} else {
@ -130,6 +142,7 @@ func (m Map) PutInt(k string, v int64) {
// inserted to the map that did not originally have the key. The key/value is
// updated to the map where the key already existed.
func (m Map) PutDouble(k string, v float64) {
m.getState().AssertMutable()
if av, existing := m.Get(k); existing {
av.SetDouble(v)
} else {
@ -141,6 +154,7 @@ func (m Map) PutDouble(k string, v float64) {
// inserted to the map that did not originally have the key. The key/value is
// updated to the map where the key already existed.
func (m Map) PutBool(k string, v bool) {
m.getState().AssertMutable()
if av, existing := m.Get(k); existing {
av.SetBool(v)
} else {
@ -150,35 +164,38 @@ func (m Map) PutBool(k string, v bool) {
// PutEmptyBytes inserts or updates an empty byte slice under given key and returns it.
func (m Map) PutEmptyBytes(k string) ByteSlice {
m.getState().AssertMutable()
bv := otlpcommon.AnyValue_BytesValue{}
if av, existing := m.Get(k); existing {
av.getOrig().Value = &bv
} else {
*m.getOrig() = append(*m.getOrig(), otlpcommon.KeyValue{Key: k, Value: otlpcommon.AnyValue{Value: &bv}})
}
return ByteSlice(internal.NewByteSlice(&bv.BytesValue))
return ByteSlice(internal.NewByteSlice(&bv.BytesValue, m.getState()))
}
// PutEmptyMap inserts or updates an empty map under given key and returns it.
func (m Map) PutEmptyMap(k string) Map {
m.getState().AssertMutable()
kvl := otlpcommon.AnyValue_KvlistValue{KvlistValue: &otlpcommon.KeyValueList{Values: []otlpcommon.KeyValue(nil)}}
if av, existing := m.Get(k); existing {
av.getOrig().Value = &kvl
} else {
*m.getOrig() = append(*m.getOrig(), otlpcommon.KeyValue{Key: k, Value: otlpcommon.AnyValue{Value: &kvl}})
}
return Map(internal.NewMap(&kvl.KvlistValue.Values))
return Map(internal.NewMap(&kvl.KvlistValue.Values, m.getState()))
}
// PutEmptySlice inserts or updates an empty slice under given key and returns it.
func (m Map) PutEmptySlice(k string) Slice {
m.getState().AssertMutable()
vl := otlpcommon.AnyValue_ArrayValue{ArrayValue: &otlpcommon.ArrayValue{Values: []otlpcommon.AnyValue(nil)}}
if av, existing := m.Get(k); existing {
av.getOrig().Value = &vl
} else {
*m.getOrig() = append(*m.getOrig(), otlpcommon.KeyValue{Key: k, Value: otlpcommon.AnyValue{Value: &vl}})
}
return Slice(internal.NewSlice(&vl.ArrayValue.Values))
return Slice(internal.NewSlice(&vl.ArrayValue.Values, m.getState()))
}
// Len returns the length of this map.
@ -199,7 +216,7 @@ func (m Map) Len() int {
func (m Map) Range(f func(k string, v Value) bool) {
for i := range *m.getOrig() {
kv := &(*m.getOrig())[i]
if !f(kv.Key, Value(internal.NewValue(&kv.Value))) {
if !f(kv.Key, Value(internal.NewValue(&kv.Value, m.getState()))) {
break
}
}
@ -207,6 +224,7 @@ func (m Map) Range(f func(k string, v Value) bool) {
// CopyTo copies all elements from the current map overriding the destination.
func (m Map) CopyTo(dest Map) {
dest.getState().AssertMutable()
newLen := len(*m.getOrig())
oldCap := cap(*dest.getOrig())
if newLen <= oldCap {
@ -216,7 +234,7 @@ func (m Map) CopyTo(dest Map) {
akv := &(*m.getOrig())[i]
destAkv := &(*dest.getOrig())[i]
destAkv.Key = akv.Key
newValue(&akv.Value).CopyTo(newValue(&destAkv.Value))
newValue(&akv.Value, m.getState()).CopyTo(newValue(&destAkv.Value, dest.getState()))
}
return
}
@ -226,7 +244,7 @@ func (m Map) CopyTo(dest Map) {
for i := range *m.getOrig() {
akv := &(*m.getOrig())[i]
origs[i].Key = akv.Key
newValue(&akv.Value).CopyTo(newValue(&origs[i].Value))
newValue(&akv.Value, m.getState()).CopyTo(newValue(&origs[i].Value, dest.getState()))
}
*dest.getOrig() = origs
}
@ -243,6 +261,7 @@ func (m Map) AsRaw() map[string]any {
// FromRaw overrides this Map instance from a standard go map.
func (m Map) FromRaw(rawMap map[string]any) error {
m.getState().AssertMutable()
if len(rawMap) == 0 {
*m.getOrig() = nil
return nil
@ -253,7 +272,7 @@ func (m Map) FromRaw(rawMap map[string]any) error {
ix := 0
for k, iv := range rawMap {
origs[ix].Key = k
errs = multierr.Append(errs, newValue(&origs[ix].Value).FromRaw(iv))
errs = multierr.Append(errs, newValue(&origs[ix].Value, m.getState()).FromRaw(iv))
ix++
}
*m.getOrig() = origs

View File

@ -17,7 +17,8 @@ func TestMap(t *testing.T) {
val, exist := NewMap().Get("test_key")
assert.False(t, exist)
assert.EqualValues(t, newValue(nil), val)
state := internal.StateMutable
assert.EqualValues(t, newValue(nil, &state), val)
putString := NewMap()
putString.PutStr("k", "v")
@ -52,6 +53,44 @@ func TestMap(t *testing.T) {
assert.EqualValues(t, NewMap(), removeMap)
}
func TestMapReadOnly(t *testing.T) {
state := internal.StateReadOnly
m := newMap(&[]otlpcommon.KeyValue{
{Key: "k1", Value: otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_StringValue{StringValue: "v1"}}},
}, &state)
assert.Equal(t, 1, m.Len())
v, ok := m.Get("k1")
assert.True(t, ok)
assert.EqualValues(t, "v1", v.Str())
m.Range(func(k string, v Value) bool {
assert.Equal(t, "k1", k)
assert.Equal(t, "v1", v.Str())
return true
})
assert.Panics(t, func() { m.PutStr("k2", "v2") })
assert.Panics(t, func() { m.PutInt("k2", 123) })
assert.Panics(t, func() { m.PutDouble("k2", 1.23) })
assert.Panics(t, func() { m.PutBool("k2", true) })
assert.Panics(t, func() { m.PutEmptyBytes("k2") })
assert.Panics(t, func() { m.PutEmptyMap("k2") })
assert.Panics(t, func() { m.PutEmptySlice("k2") })
assert.Panics(t, func() { m.Remove("k1") })
assert.Panics(t, func() { m.RemoveIf(func(k string, v Value) bool { return true }) })
assert.Panics(t, func() { m.EnsureCapacity(2) })
m2 := NewMap()
m.CopyTo(m2)
assert.Equal(t, m2.AsRaw(), m.AsRaw())
assert.Panics(t, func() { NewMap().CopyTo(m) })
assert.Equal(t, map[string]any{"k1": "v1"}, m.AsRaw())
assert.Panics(t, func() { _ = m.FromRaw(map[string]any{"k1": "v1"}) })
}
func TestMapPutEmpty(t *testing.T) {
m := NewMap()
v := m.PutEmpty("k1")
@ -148,7 +187,8 @@ func TestMapWithEmpty(t *testing.T) {
Value: otlpcommon.AnyValue{Value: nil},
},
}
sm := newMap(&origWithNil)
state := internal.StateMutable
sm := newMap(&origWithNil, &state)
val, exist := sm.Get("test_key")
assert.True(t, exist)
assert.EqualValues(t, ValueTypeStr, val.Type())

View File

@ -19,19 +19,24 @@ import (
// Important: zero-initialized instance is not valid for use.
type Slice internal.Slice
func newSlice(orig *[]otlpcommon.AnyValue) Slice {
return Slice(internal.NewSlice(orig))
func newSlice(orig *[]otlpcommon.AnyValue, state *internal.State) Slice {
return Slice(internal.NewSlice(orig, state))
}
func (es Slice) getOrig() *[]otlpcommon.AnyValue {
return internal.GetOrigSlice(internal.Slice(es))
}
func (es Slice) getState() *internal.State {
return internal.GetSliceState(internal.Slice(es))
}
// NewSlice creates a Slice with 0 elements.
// Can use "EnsureCapacity" to initialize with a given capacity.
func NewSlice() Slice {
orig := []otlpcommon.AnyValue(nil)
return Slice(internal.NewSlice(&orig))
state := internal.StateMutable
return Slice(internal.NewSlice(&orig, &state))
}
// Len returns the number of elements in the slice.
@ -50,11 +55,12 @@ func (es Slice) Len() int {
// ... // Do something with the element
// }
func (es Slice) At(ix int) Value {
return newValue(&(*es.getOrig())[ix])
return newValue(&(*es.getOrig())[ix], es.getState())
}
// CopyTo copies all elements from the current slice overriding the destination.
func (es Slice) CopyTo(dest Slice) {
dest.getState().AssertMutable()
srcLen := es.Len()
destCap := cap(*dest.getOrig())
if srcLen <= destCap {
@ -64,7 +70,7 @@ func (es Slice) CopyTo(dest Slice) {
}
for i := range *es.getOrig() {
newValue(&(*es.getOrig())[i]).CopyTo(newValue(&(*dest.getOrig())[i]))
newValue(&(*es.getOrig())[i], es.getState()).CopyTo(newValue(&(*dest.getOrig())[i], dest.getState()))
}
}
@ -81,6 +87,7 @@ func (es Slice) CopyTo(dest Slice) {
// // Here should set all the values for e.
// }
func (es Slice) EnsureCapacity(newCap int) {
es.getState().AssertMutable()
oldCap := cap(*es.getOrig())
if newCap <= oldCap {
return
@ -94,6 +101,7 @@ func (es Slice) EnsureCapacity(newCap int) {
// AppendEmpty will append to the end of the slice an empty Value.
// It returns the newly added Value.
func (es Slice) AppendEmpty() Value {
es.getState().AssertMutable()
*es.getOrig() = append(*es.getOrig(), otlpcommon.AnyValue{})
return es.At(es.Len() - 1)
}
@ -101,6 +109,8 @@ func (es Slice) AppendEmpty() Value {
// MoveAndAppendTo moves all elements from the current slice and appends them to the dest.
// The current slice will be cleared.
func (es Slice) MoveAndAppendTo(dest Slice) {
es.getState().AssertMutable()
dest.getState().AssertMutable()
if *dest.getOrig() == nil {
// We can simply move the entire vector and avoid any allocations.
*dest.getOrig() = *es.getOrig()
@ -113,6 +123,7 @@ func (es Slice) MoveAndAppendTo(dest Slice) {
// RemoveIf calls f sequentially for each element present in the slice.
// If f returns true, the element is removed from the slice.
func (es Slice) RemoveIf(f func(Value) bool) {
es.getState().AssertMutable()
newLen := 0
for i := 0; i < len(*es.getOrig()); i++ {
if f(es.At(i)) {
@ -141,6 +152,7 @@ func (es Slice) AsRaw() []any {
// FromRaw copies []any into the Slice.
func (es Slice) FromRaw(rawSlice []any) error {
es.getState().AssertMutable()
if len(rawSlice) == 0 {
*es.getOrig() = nil
return nil
@ -148,7 +160,7 @@ func (es Slice) FromRaw(rawSlice []any) error {
var errs error
origs := make([]otlpcommon.AnyValue, len(rawSlice))
for ix, iv := range rawSlice {
errs = multierr.Append(errs, newValue(&origs[ix]).FromRaw(iv))
errs = multierr.Append(errs, newValue(&origs[ix], es.getState()).FromRaw(iv))
}
*es.getOrig() = origs
return errs

View File

@ -15,11 +15,12 @@ import (
func TestSlice(t *testing.T) {
es := NewSlice()
assert.Equal(t, 0, es.Len())
es = newSlice(&[]otlpcommon.AnyValue{})
state := internal.StateMutable
es = newSlice(&[]otlpcommon.AnyValue{}, &state)
assert.Equal(t, 0, es.Len())
es.EnsureCapacity(7)
emptyVal := newValue(&otlpcommon.AnyValue{})
emptyVal := newValue(&otlpcommon.AnyValue{}, &state)
testVal := Value(internal.GenerateTestValue())
assert.Equal(t, 7, cap(*es.getOrig()))
for i := 0; i < es.Len(); i++ {
@ -30,6 +31,29 @@ func TestSlice(t *testing.T) {
}
}
func TestSliceReadOnly(t *testing.T) {
state := internal.StateReadOnly
es := newSlice(&[]otlpcommon.AnyValue{{Value: &otlpcommon.AnyValue_IntValue{IntValue: 3}}}, &state)
assert.Equal(t, 1, es.Len())
assert.Equal(t, int64(3), es.At(0).Int())
assert.Panics(t, func() { es.AppendEmpty() })
assert.Panics(t, func() { es.EnsureCapacity(2) })
es2 := NewSlice()
es.CopyTo(es2)
assert.Equal(t, es.AsRaw(), es2.AsRaw())
assert.Panics(t, func() { es2.CopyTo(es) })
assert.Panics(t, func() { es.MoveAndAppendTo(es2) })
assert.Panics(t, func() { es2.MoveAndAppendTo(es) })
assert.Panics(t, func() { es.RemoveIf(func(el Value) bool { return false }) })
assert.Equal(t, []any{int64(3)}, es.AsRaw())
assert.Panics(t, func() { _ = es.FromRaw([]any{3}) })
}
func TestSlice_CopyTo(t *testing.T) {
dest := NewSlice()
// Test CopyTo to empty

View File

@ -11,13 +11,18 @@ import (
type TraceState internal.TraceState
func NewTraceState() TraceState {
return TraceState(internal.NewTraceState(new(string)))
state := internal.StateMutable
return TraceState(internal.NewTraceState(new(string), &state))
}
func (ms TraceState) getOrig() *string {
return internal.GetOrigTraceState(internal.TraceState(ms))
}
func (ms TraceState) getState() *internal.State {
return internal.GetTraceStateState(internal.TraceState(ms))
}
// AsRaw returns the string representation of the tracestate in w3c-trace-context format: https://www.w3.org/TR/trace-context/#tracestate-header
func (ms TraceState) AsRaw() string {
return *ms.getOrig()
@ -25,17 +30,21 @@ func (ms TraceState) AsRaw() string {
// FromRaw copies the string representation in w3c-trace-context format of the tracestate into this TraceState.
func (ms TraceState) FromRaw(v string) {
ms.getState().AssertMutable()
*ms.getOrig() = v
}
// MoveTo moves the TraceState instance overriding the destination
// and resetting the current instance to its zero value.
func (ms TraceState) MoveTo(dest TraceState) {
ms.getState().AssertMutable()
dest.getState().AssertMutable()
*dest.getOrig() = *ms.getOrig()
*ms.getOrig() = ""
}
// CopyTo copies the TraceState instance overriding the destination.
func (ms TraceState) CopyTo(dest TraceState) {
dest.getState().AssertMutable()
*dest.getOrig() = *ms.getOrig()
}

View File

@ -71,52 +71,64 @@ type Value internal.Value
// NewValueEmpty creates a new Value with an empty value.
func NewValueEmpty() Value {
return newValue(&otlpcommon.AnyValue{})
state := internal.StateMutable
return newValue(&otlpcommon.AnyValue{}, &state)
}
// NewValueStr creates a new Value with the given string value.
func NewValueStr(v string) Value {
return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_StringValue{StringValue: v}})
state := internal.StateMutable
return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_StringValue{StringValue: v}}, &state)
}
// NewValueInt creates a new Value with the given int64 value.
func NewValueInt(v int64) Value {
return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_IntValue{IntValue: v}})
state := internal.StateMutable
return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_IntValue{IntValue: v}}, &state)
}
// NewValueDouble creates a new Value with the given float64 value.
func NewValueDouble(v float64) Value {
return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_DoubleValue{DoubleValue: v}})
state := internal.StateMutable
return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_DoubleValue{DoubleValue: v}}, &state)
}
// NewValueBool creates a new Value with the given bool value.
func NewValueBool(v bool) Value {
return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_BoolValue{BoolValue: v}})
state := internal.StateMutable
return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_BoolValue{BoolValue: v}}, &state)
}
// NewValueMap creates a new Value of map type.
func NewValueMap() Value {
return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_KvlistValue{KvlistValue: &otlpcommon.KeyValueList{}}})
state := internal.StateMutable
return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_KvlistValue{KvlistValue: &otlpcommon.KeyValueList{}}}, &state)
}
// NewValueSlice creates a new Value of array type.
func NewValueSlice() Value {
return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_ArrayValue{ArrayValue: &otlpcommon.ArrayValue{}}})
state := internal.StateMutable
return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_ArrayValue{ArrayValue: &otlpcommon.ArrayValue{}}}, &state)
}
// NewValueBytes creates a new empty Value of byte type.
func NewValueBytes() Value {
return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_BytesValue{BytesValue: nil}})
state := internal.StateMutable
return newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_BytesValue{BytesValue: nil}}, &state)
}
func newValue(orig *otlpcommon.AnyValue) Value {
return Value(internal.NewValue(orig))
func newValue(orig *otlpcommon.AnyValue, state *internal.State) Value {
return Value(internal.NewValue(orig, state))
}
func (v Value) getOrig() *otlpcommon.AnyValue {
return internal.GetOrigValue(internal.Value(v))
}
func (v Value) getState() *internal.State {
return internal.GetValueState(internal.Value(v))
}
func (v Value) FromRaw(iv any) error {
switch tv := iv.(type) {
case nil:
@ -222,7 +234,7 @@ func (v Value) Map() Map {
if kvlist == nil {
return Map{}
}
return newMap(&kvlist.Values)
return newMap(&kvlist.Values, internal.GetValueState(internal.Value(v)))
}
// Slice returns the slice value associated with this Value.
@ -235,7 +247,7 @@ func (v Value) Slice() Slice {
if arr == nil {
return Slice{}
}
return newSlice(&arr.Values)
return newSlice(&arr.Values, internal.GetValueState(internal.Value(v)))
}
// Bytes returns the ByteSlice value associated with this Value.
@ -248,7 +260,7 @@ func (v Value) Bytes() ByteSlice {
if !ok {
return ByteSlice{}
}
return ByteSlice(internal.NewByteSlice(&bv.BytesValue))
return ByteSlice(internal.NewByteSlice(&bv.BytesValue, internal.GetValueState(internal.Value(v))))
}
// SetStr replaces the string value associated with this Value,
@ -257,6 +269,7 @@ func (v Value) Bytes() ByteSlice {
// fmt.Stringer interface by the corresponding getter method.
// Calling this function on zero-initialized Value will cause a panic.
func (v Value) SetStr(sv string) {
v.getState().AssertMutable()
v.getOrig().Value = &otlpcommon.AnyValue_StringValue{StringValue: sv}
}
@ -264,6 +277,7 @@ func (v Value) SetStr(sv string) {
// it also changes the type to be ValueTypeInt.
// Calling this function on zero-initialized Value will cause a panic.
func (v Value) SetInt(iv int64) {
v.getState().AssertMutable()
v.getOrig().Value = &otlpcommon.AnyValue_IntValue{IntValue: iv}
}
@ -271,6 +285,7 @@ func (v Value) SetInt(iv int64) {
// it also changes the type to be ValueTypeDouble.
// Calling this function on zero-initialized Value will cause a panic.
func (v Value) SetDouble(dv float64) {
v.getState().AssertMutable()
v.getOrig().Value = &otlpcommon.AnyValue_DoubleValue{DoubleValue: dv}
}
@ -278,35 +293,40 @@ func (v Value) SetDouble(dv float64) {
// it also changes the type to be ValueTypeBool.
// Calling this function on zero-initialized Value will cause a panic.
func (v Value) SetBool(bv bool) {
v.getState().AssertMutable()
v.getOrig().Value = &otlpcommon.AnyValue_BoolValue{BoolValue: bv}
}
// SetEmptyBytes sets value to an empty byte slice and returns it.
// Calling this function on zero-initialized Value will cause a panic.
func (v Value) SetEmptyBytes() ByteSlice {
v.getState().AssertMutable()
bv := otlpcommon.AnyValue_BytesValue{BytesValue: nil}
v.getOrig().Value = &bv
return ByteSlice(internal.NewByteSlice(&bv.BytesValue))
return ByteSlice(internal.NewByteSlice(&bv.BytesValue, v.getState()))
}
// SetEmptyMap sets value to an empty map and returns it.
// Calling this function on zero-initialized Value will cause a panic.
func (v Value) SetEmptyMap() Map {
v.getState().AssertMutable()
kv := &otlpcommon.AnyValue_KvlistValue{KvlistValue: &otlpcommon.KeyValueList{}}
v.getOrig().Value = kv
return newMap(&kv.KvlistValue.Values)
return newMap(&kv.KvlistValue.Values, v.getState())
}
// SetEmptySlice sets value to an empty slice and returns it.
// Calling this function on zero-initialized Value will cause a panic.
func (v Value) SetEmptySlice() Slice {
v.getState().AssertMutable()
av := &otlpcommon.AnyValue_ArrayValue{ArrayValue: &otlpcommon.ArrayValue{}}
v.getOrig().Value = av
return newSlice(&av.ArrayValue.Values)
return newSlice(&av.ArrayValue.Values, v.getState())
}
// CopyTo copies the Value instance overriding the destination.
func (v Value) CopyTo(dest Value) {
dest.getState().AssertMutable()
destOrig := dest.getOrig()
switch ov := v.getOrig().Value.(type) {
case *otlpcommon.AnyValue_KvlistValue:
@ -320,7 +340,7 @@ func (v Value) CopyTo(dest Value) {
return
}
// Deep copy to dest.
newMap(&ov.KvlistValue.Values).CopyTo(newMap(&kv.KvlistValue.Values))
newMap(&ov.KvlistValue.Values, v.getState()).CopyTo(newMap(&kv.KvlistValue.Values, dest.getState()))
case *otlpcommon.AnyValue_ArrayValue:
av, ok := destOrig.Value.(*otlpcommon.AnyValue_ArrayValue)
if !ok {
@ -332,7 +352,7 @@ func (v Value) CopyTo(dest Value) {
return
}
// Deep copy to dest.
newSlice(&ov.ArrayValue.Values).CopyTo(newSlice(&av.ArrayValue.Values))
newSlice(&ov.ArrayValue.Values, v.getState()).CopyTo(newSlice(&av.ArrayValue.Values, dest.getState()))
case *otlpcommon.AnyValue_BytesValue:
bv, ok := destOrig.Value.(*otlpcommon.AnyValue_BytesValue)
if !ok {
@ -438,28 +458,32 @@ func (v Value) AsRaw() any {
func newKeyValueString(k string, v string) otlpcommon.KeyValue {
orig := otlpcommon.KeyValue{Key: k}
akv := newValue(&orig.Value)
state := internal.StateMutable
akv := newValue(&orig.Value, &state)
akv.SetStr(v)
return orig
}
func newKeyValueInt(k string, v int64) otlpcommon.KeyValue {
orig := otlpcommon.KeyValue{Key: k}
akv := newValue(&orig.Value)
state := internal.StateMutable
akv := newValue(&orig.Value, &state)
akv.SetInt(v)
return orig
}
func newKeyValueDouble(k string, v float64) otlpcommon.KeyValue {
orig := otlpcommon.KeyValue{Key: k}
akv := newValue(&orig.Value)
state := internal.StateMutable
akv := newValue(&orig.Value, &state)
akv.SetDouble(v)
return orig
}
func newKeyValueBool(k string, v bool) otlpcommon.KeyValue {
orig := otlpcommon.KeyValue{Key: k}
akv := newValue(&orig.Value)
state := internal.StateMutable
akv := newValue(&orig.Value, &state)
akv.SetBool(v)
return orig
}

View File

@ -11,6 +11,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/pdata/internal"
otlpcommon "go.opentelemetry.io/collector/pdata/internal/data/protogen/common/v1"
)
@ -44,6 +45,36 @@ func TestValue(t *testing.T) {
assert.EqualValues(t, ValueTypeSlice, v.Type())
}
func TestValueReadOnly(t *testing.T) {
state := internal.StateReadOnly
v := newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_StringValue{StringValue: "v"}}, &state)
assert.EqualValues(t, ValueTypeStr, v.Type())
assert.EqualValues(t, "v", v.Str())
assert.EqualValues(t, 0, v.Int())
assert.EqualValues(t, 0, v.Double())
assert.False(t, v.Bool())
assert.EqualValues(t, ByteSlice{}, v.Bytes())
assert.EqualValues(t, Map{}, v.Map())
assert.EqualValues(t, Slice{}, v.Slice())
assert.EqualValues(t, "v", v.AsString())
assert.Panics(t, func() { v.SetStr("abc") })
assert.Panics(t, func() { v.SetInt(123) })
assert.Panics(t, func() { v.SetDouble(3.4) })
assert.Panics(t, func() { v.SetBool(true) })
assert.Panics(t, func() { v.SetEmptyBytes() })
assert.Panics(t, func() { v.SetEmptyMap() })
assert.Panics(t, func() { v.SetEmptySlice() })
v2 := NewValueEmpty()
v.CopyTo(v2)
assert.Equal(t, v.AsRaw(), v2.AsRaw())
assert.Panics(t, func() { v2.CopyTo(v) })
}
func TestValueType(t *testing.T) {
assert.EqualValues(t, "Empty", ValueTypeEmpty.String())
assert.EqualValues(t, "Str", ValueTypeStr.String())
@ -128,7 +159,8 @@ func TestValueMap(t *testing.T) {
// Test nil KvlistValue case for Map() func.
orig := &otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_KvlistValue{KvlistValue: nil}}
m1 = newValue(orig)
state := internal.StateMutable
m1 = newValue(orig, &state)
assert.EqualValues(t, Map{}, m1.Map())
}
@ -165,8 +197,9 @@ func TestValueSlice(t *testing.T) {
assert.EqualValues(t, "somestr", v.Str())
// Test nil values case for Slice() func.
a1 = newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_ArrayValue{ArrayValue: nil}})
assert.EqualValues(t, newSlice(nil), a1.Slice())
state := internal.StateMutable
a1 = newValue(&otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_ArrayValue{ArrayValue: nil}}, &state)
assert.EqualValues(t, newSlice(nil, nil), a1.Slice())
}
func TestNilOrigSetValue(t *testing.T) {
@ -200,26 +233,28 @@ func TestNilOrigSetValue(t *testing.T) {
}
func TestValue_CopyTo(t *testing.T) {
state := internal.StateMutable
// Test nil KvlistValue case for Map() func.
dest := NewValueEmpty()
orig := &otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_KvlistValue{KvlistValue: nil}}
newValue(orig).CopyTo(dest)
newValue(orig, &state).CopyTo(dest)
assert.Nil(t, dest.getOrig().Value.(*otlpcommon.AnyValue_KvlistValue).KvlistValue)
// Test nil ArrayValue case for Slice() func.
dest = NewValueEmpty()
orig = &otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_ArrayValue{ArrayValue: nil}}
newValue(orig).CopyTo(dest)
newValue(orig, &state).CopyTo(dest)
assert.Nil(t, dest.getOrig().Value.(*otlpcommon.AnyValue_ArrayValue).ArrayValue)
// Test copy empty value.
orig = &otlpcommon.AnyValue{}
newValue(orig).CopyTo(dest)
newValue(orig, &state).CopyTo(dest)
assert.Nil(t, dest.getOrig().Value)
av := NewValueEmpty()
destVal := otlpcommon.AnyValue{Value: &otlpcommon.AnyValue_IntValue{}}
av.CopyTo(newValue(&destVal))
av.CopyTo(newValue(&destVal, &state))
assert.EqualValues(t, nil, destVal.Value)
}
@ -228,7 +263,8 @@ func TestSliceWithNilValues(t *testing.T) {
{},
{Value: &otlpcommon.AnyValue_StringValue{StringValue: "test_value"}},
}
sm := newSlice(&origWithNil)
state := internal.StateMutable
sm := newSlice(&origWithNil, &state)
val := sm.At(0)
assert.EqualValues(t, ValueTypeEmpty, val.Type())

View File

@ -21,11 +21,12 @@ import (
// Must use NewLogRecord function to create new instances.
// Important: zero-initialized instance is not valid for use.
type LogRecord struct {
orig *otlplogs.LogRecord
orig *otlplogs.LogRecord
state *internal.State
}
func newLogRecord(orig *otlplogs.LogRecord) LogRecord {
return LogRecord{orig}
func newLogRecord(orig *otlplogs.LogRecord, state *internal.State) LogRecord {
return LogRecord{orig: orig, state: state}
}
// NewLogRecord creates a new empty LogRecord.
@ -33,12 +34,15 @@ func newLogRecord(orig *otlplogs.LogRecord) LogRecord {
// This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice,
// OR directly access the member if this is embedded in another struct.
func NewLogRecord() LogRecord {
return newLogRecord(&otlplogs.LogRecord{})
state := internal.StateMutable
return newLogRecord(&otlplogs.LogRecord{}, &state)
}
// MoveTo moves all properties from the current struct overriding the destination and
// resetting the current instance to its zero value
func (ms LogRecord) MoveTo(dest LogRecord) {
ms.state.AssertMutable()
dest.state.AssertMutable()
*dest.orig = *ms.orig
*ms.orig = otlplogs.LogRecord{}
}
@ -50,6 +54,7 @@ func (ms LogRecord) ObservedTimestamp() pcommon.Timestamp {
// SetObservedTimestamp replaces the observedtimestamp associated with this LogRecord.
func (ms LogRecord) SetObservedTimestamp(v pcommon.Timestamp) {
ms.state.AssertMutable()
ms.orig.ObservedTimeUnixNano = uint64(v)
}
@ -60,6 +65,7 @@ func (ms LogRecord) Timestamp() pcommon.Timestamp {
// SetTimestamp replaces the timestamp associated with this LogRecord.
func (ms LogRecord) SetTimestamp(v pcommon.Timestamp) {
ms.state.AssertMutable()
ms.orig.TimeUnixNano = uint64(v)
}
@ -70,6 +76,7 @@ func (ms LogRecord) TraceID() pcommon.TraceID {
// SetTraceID replaces the traceid associated with this LogRecord.
func (ms LogRecord) SetTraceID(v pcommon.TraceID) {
ms.state.AssertMutable()
ms.orig.TraceId = data.TraceID(v)
}
@ -80,6 +87,7 @@ func (ms LogRecord) SpanID() pcommon.SpanID {
// SetSpanID replaces the spanid associated with this LogRecord.
func (ms LogRecord) SetSpanID(v pcommon.SpanID) {
ms.state.AssertMutable()
ms.orig.SpanId = data.SpanID(v)
}
@ -90,6 +98,7 @@ func (ms LogRecord) Flags() LogRecordFlags {
// SetFlags replaces the flags associated with this LogRecord.
func (ms LogRecord) SetFlags(v LogRecordFlags) {
ms.state.AssertMutable()
ms.orig.Flags = uint32(v)
}
@ -100,6 +109,7 @@ func (ms LogRecord) SeverityText() string {
// SetSeverityText replaces the severitytext associated with this LogRecord.
func (ms LogRecord) SetSeverityText(v string) {
ms.state.AssertMutable()
ms.orig.SeverityText = v
}
@ -110,17 +120,18 @@ func (ms LogRecord) SeverityNumber() SeverityNumber {
// SetSeverityNumber replaces the severitynumber associated with this LogRecord.
func (ms LogRecord) SetSeverityNumber(v SeverityNumber) {
ms.state.AssertMutable()
ms.orig.SeverityNumber = otlplogs.SeverityNumber(v)
}
// Body returns the body associated with this LogRecord.
func (ms LogRecord) Body() pcommon.Value {
return pcommon.Value(internal.NewValue(&ms.orig.Body))
return pcommon.Value(internal.NewValue(&ms.orig.Body, ms.state))
}
// Attributes returns the Attributes associated with this LogRecord.
func (ms LogRecord) Attributes() pcommon.Map {
return pcommon.Map(internal.NewMap(&ms.orig.Attributes))
return pcommon.Map(internal.NewMap(&ms.orig.Attributes, ms.state))
}
// DroppedAttributesCount returns the droppedattributescount associated with this LogRecord.
@ -130,11 +141,13 @@ func (ms LogRecord) DroppedAttributesCount() uint32 {
// SetDroppedAttributesCount replaces the droppedattributescount associated with this LogRecord.
func (ms LogRecord) SetDroppedAttributesCount(v uint32) {
ms.state.AssertMutable()
ms.orig.DroppedAttributesCount = v
}
// CopyTo copies all properties from the current struct overriding the destination.
func (ms LogRecord) CopyTo(dest LogRecord) {
dest.state.AssertMutable()
dest.SetObservedTimestamp(ms.ObservedTimestamp())
dest.SetTimestamp(ms.Timestamp())
dest.SetTraceID(ms.TraceID())

View File

@ -23,6 +23,9 @@ func TestLogRecord_MoveTo(t *testing.T) {
ms.MoveTo(dest)
assert.Equal(t, NewLogRecord(), ms)
assert.Equal(t, generateTestLogRecord(), dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.MoveTo(newLogRecord(&otlplogs.LogRecord{}, &sharedState)) })
assert.Panics(t, func() { newLogRecord(&otlplogs.LogRecord{}, &sharedState).MoveTo(dest) })
}
func TestLogRecord_CopyTo(t *testing.T) {
@ -33,6 +36,8 @@ func TestLogRecord_CopyTo(t *testing.T) {
orig = generateTestLogRecord()
orig.CopyTo(ms)
assert.Equal(t, orig, ms)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.CopyTo(newLogRecord(&otlplogs.LogRecord{}, &sharedState)) })
}
func TestLogRecord_ObservedTimestamp(t *testing.T) {
@ -80,6 +85,8 @@ func TestLogRecord_SeverityText(t *testing.T) {
assert.Equal(t, "", ms.SeverityText())
ms.SetSeverityText("INFO")
assert.Equal(t, "INFO", ms.SeverityText())
sharedState := internal.StateReadOnly
assert.Panics(t, func() { newLogRecord(&otlplogs.LogRecord{}, &sharedState).SetSeverityText("INFO") })
}
func TestLogRecord_SeverityNumber(t *testing.T) {
@ -108,6 +115,8 @@ func TestLogRecord_DroppedAttributesCount(t *testing.T) {
assert.Equal(t, uint32(0), ms.DroppedAttributesCount())
ms.SetDroppedAttributesCount(uint32(17))
assert.Equal(t, uint32(17), ms.DroppedAttributesCount())
sharedState := internal.StateReadOnly
assert.Panics(t, func() { newLogRecord(&otlplogs.LogRecord{}, &sharedState).SetDroppedAttributesCount(uint32(17)) })
}
func generateTestLogRecord() LogRecord {
@ -124,7 +133,7 @@ func fillTestLogRecord(tv LogRecord) {
tv.orig.Flags = 1
tv.orig.SeverityText = "INFO"
tv.orig.SeverityNumber = otlplogs.SeverityNumber(5)
internal.FillTestValue(internal.NewValue(&tv.orig.Body))
internal.FillTestMap(internal.NewMap(&tv.orig.Attributes))
internal.FillTestValue(internal.NewValue(&tv.orig.Body, tv.state))
internal.FillTestMap(internal.NewMap(&tv.orig.Attributes, tv.state))
tv.orig.DroppedAttributesCount = uint32(17)
}

View File

@ -9,6 +9,7 @@ package plog
import (
"sort"
"go.opentelemetry.io/collector/pdata/internal"
otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1"
)
@ -20,18 +21,20 @@ import (
// Must use NewLogRecordSlice function to create new instances.
// Important: zero-initialized instance is not valid for use.
type LogRecordSlice struct {
orig *[]*otlplogs.LogRecord
orig *[]*otlplogs.LogRecord
state *internal.State
}
func newLogRecordSlice(orig *[]*otlplogs.LogRecord) LogRecordSlice {
return LogRecordSlice{orig}
func newLogRecordSlice(orig *[]*otlplogs.LogRecord, state *internal.State) LogRecordSlice {
return LogRecordSlice{orig: orig, state: state}
}
// NewLogRecordSlice creates a LogRecordSlice with 0 elements.
// Can use "EnsureCapacity" to initialize with a given capacity.
func NewLogRecordSlice() LogRecordSlice {
orig := []*otlplogs.LogRecord(nil)
return newLogRecordSlice(&orig)
state := internal.StateMutable
return newLogRecordSlice(&orig, &state)
}
// Len returns the number of elements in the slice.
@ -50,7 +53,7 @@ func (es LogRecordSlice) Len() int {
// ... // Do something with the element
// }
func (es LogRecordSlice) At(i int) LogRecord {
return newLogRecord((*es.orig)[i])
return newLogRecord((*es.orig)[i], es.state)
}
// EnsureCapacity is an operation that ensures the slice has at least the specified capacity.
@ -66,6 +69,7 @@ func (es LogRecordSlice) At(i int) LogRecord {
// // Here should set all the values for e.
// }
func (es LogRecordSlice) EnsureCapacity(newCap int) {
es.state.AssertMutable()
oldCap := cap(*es.orig)
if newCap <= oldCap {
return
@ -79,6 +83,7 @@ func (es LogRecordSlice) EnsureCapacity(newCap int) {
// AppendEmpty will append to the end of the slice an empty LogRecord.
// It returns the newly added LogRecord.
func (es LogRecordSlice) AppendEmpty() LogRecord {
es.state.AssertMutable()
*es.orig = append(*es.orig, &otlplogs.LogRecord{})
return es.At(es.Len() - 1)
}
@ -86,6 +91,8 @@ func (es LogRecordSlice) AppendEmpty() LogRecord {
// MoveAndAppendTo moves all elements from the current slice and appends them to the dest.
// The current slice will be cleared.
func (es LogRecordSlice) MoveAndAppendTo(dest LogRecordSlice) {
es.state.AssertMutable()
dest.state.AssertMutable()
if *dest.orig == nil {
// We can simply move the entire vector and avoid any allocations.
*dest.orig = *es.orig
@ -98,6 +105,7 @@ func (es LogRecordSlice) MoveAndAppendTo(dest LogRecordSlice) {
// RemoveIf calls f sequentially for each element present in the slice.
// If f returns true, the element is removed from the slice.
func (es LogRecordSlice) RemoveIf(f func(LogRecord) bool) {
es.state.AssertMutable()
newLen := 0
for i := 0; i < len(*es.orig); i++ {
if f(es.At(i)) {
@ -117,12 +125,13 @@ func (es LogRecordSlice) RemoveIf(f func(LogRecord) bool) {
// CopyTo copies all elements from the current slice overriding the destination.
func (es LogRecordSlice) CopyTo(dest LogRecordSlice) {
dest.state.AssertMutable()
srcLen := es.Len()
destCap := cap(*dest.orig)
if srcLen <= destCap {
(*dest.orig) = (*dest.orig)[:srcLen:destCap]
for i := range *es.orig {
newLogRecord((*es.orig)[i]).CopyTo(newLogRecord((*dest.orig)[i]))
newLogRecord((*es.orig)[i], es.state).CopyTo(newLogRecord((*dest.orig)[i], dest.state))
}
return
}
@ -130,7 +139,7 @@ func (es LogRecordSlice) CopyTo(dest LogRecordSlice) {
wrappers := make([]*otlplogs.LogRecord, srcLen)
for i := range *es.orig {
wrappers[i] = &origs[i]
newLogRecord((*es.orig)[i]).CopyTo(newLogRecord(wrappers[i]))
newLogRecord((*es.orig)[i], es.state).CopyTo(newLogRecord(wrappers[i], dest.state))
}
*dest.orig = wrappers
}
@ -139,5 +148,6 @@ func (es LogRecordSlice) CopyTo(dest LogRecordSlice) {
// provided less function so that two instances of LogRecordSlice
// can be compared.
func (es LogRecordSlice) Sort(less func(a, b LogRecord) bool) {
es.state.AssertMutable()
sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) })
}

View File

@ -12,13 +12,15 @@ import (
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1"
)
func TestLogRecordSlice(t *testing.T) {
es := NewLogRecordSlice()
assert.Equal(t, 0, es.Len())
es = newLogRecordSlice(&[]*otlplogs.LogRecord{})
state := internal.StateMutable
es = newLogRecordSlice(&[]*otlplogs.LogRecord{}, &state)
assert.Equal(t, 0, es.Len())
emptyVal := NewLogRecord()
@ -32,6 +34,19 @@ func TestLogRecordSlice(t *testing.T) {
assert.Equal(t, 7, es.Len())
}
func TestLogRecordSliceReadOnly(t *testing.T) {
sharedState := internal.StateReadOnly
es := newLogRecordSlice(&[]*otlplogs.LogRecord{}, &sharedState)
assert.Equal(t, 0, es.Len())
assert.Panics(t, func() { es.AppendEmpty() })
assert.Panics(t, func() { es.EnsureCapacity(2) })
es2 := NewLogRecordSlice()
es.CopyTo(es2)
assert.Panics(t, func() { es2.CopyTo(es) })
assert.Panics(t, func() { es.MoveAndAppendTo(es2) })
assert.Panics(t, func() { es2.MoveAndAppendTo(es) })
}
func TestLogRecordSlice_CopyTo(t *testing.T) {
dest := NewLogRecordSlice()
// Test CopyTo to empty
@ -134,6 +149,6 @@ func fillTestLogRecordSlice(es LogRecordSlice) {
*es.orig = make([]*otlplogs.LogRecord, 7)
for i := 0; i < 7; i++ {
(*es.orig)[i] = &otlplogs.LogRecord{}
fillTestLogRecord(newLogRecord((*es.orig)[i]))
fillTestLogRecord(newLogRecord((*es.orig)[i], es.state))
}
}

View File

@ -20,11 +20,12 @@ import (
// Must use NewResourceLogs function to create new instances.
// Important: zero-initialized instance is not valid for use.
type ResourceLogs struct {
orig *otlplogs.ResourceLogs
orig *otlplogs.ResourceLogs
state *internal.State
}
func newResourceLogs(orig *otlplogs.ResourceLogs) ResourceLogs {
return ResourceLogs{orig}
func newResourceLogs(orig *otlplogs.ResourceLogs, state *internal.State) ResourceLogs {
return ResourceLogs{orig: orig, state: state}
}
// NewResourceLogs creates a new empty ResourceLogs.
@ -32,19 +33,22 @@ func newResourceLogs(orig *otlplogs.ResourceLogs) ResourceLogs {
// This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice,
// OR directly access the member if this is embedded in another struct.
func NewResourceLogs() ResourceLogs {
return newResourceLogs(&otlplogs.ResourceLogs{})
state := internal.StateMutable
return newResourceLogs(&otlplogs.ResourceLogs{}, &state)
}
// MoveTo moves all properties from the current struct overriding the destination and
// resetting the current instance to its zero value
func (ms ResourceLogs) MoveTo(dest ResourceLogs) {
ms.state.AssertMutable()
dest.state.AssertMutable()
*dest.orig = *ms.orig
*ms.orig = otlplogs.ResourceLogs{}
}
// Resource returns the resource associated with this ResourceLogs.
func (ms ResourceLogs) Resource() pcommon.Resource {
return pcommon.Resource(internal.NewResource(&ms.orig.Resource))
return pcommon.Resource(internal.NewResource(&ms.orig.Resource, ms.state))
}
// SchemaUrl returns the schemaurl associated with this ResourceLogs.
@ -54,16 +58,18 @@ func (ms ResourceLogs) SchemaUrl() string {
// SetSchemaUrl replaces the schemaurl associated with this ResourceLogs.
func (ms ResourceLogs) SetSchemaUrl(v string) {
ms.state.AssertMutable()
ms.orig.SchemaUrl = v
}
// ScopeLogs returns the ScopeLogs associated with this ResourceLogs.
func (ms ResourceLogs) ScopeLogs() ScopeLogsSlice {
return newScopeLogsSlice(&ms.orig.ScopeLogs)
return newScopeLogsSlice(&ms.orig.ScopeLogs, ms.state)
}
// CopyTo copies all properties from the current struct overriding the destination.
func (ms ResourceLogs) CopyTo(dest ResourceLogs) {
dest.state.AssertMutable()
ms.Resource().CopyTo(dest.Resource())
dest.SetSchemaUrl(ms.SchemaUrl())
ms.ScopeLogs().CopyTo(dest.ScopeLogs())

View File

@ -12,6 +12,7 @@ import (
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1"
"go.opentelemetry.io/collector/pdata/pcommon"
)
@ -21,6 +22,9 @@ func TestResourceLogs_MoveTo(t *testing.T) {
ms.MoveTo(dest)
assert.Equal(t, NewResourceLogs(), ms)
assert.Equal(t, generateTestResourceLogs(), dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.MoveTo(newResourceLogs(&otlplogs.ResourceLogs{}, &sharedState)) })
assert.Panics(t, func() { newResourceLogs(&otlplogs.ResourceLogs{}, &sharedState).MoveTo(dest) })
}
func TestResourceLogs_CopyTo(t *testing.T) {
@ -31,6 +35,8 @@ func TestResourceLogs_CopyTo(t *testing.T) {
orig = generateTestResourceLogs()
orig.CopyTo(ms)
assert.Equal(t, orig, ms)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.CopyTo(newResourceLogs(&otlplogs.ResourceLogs{}, &sharedState)) })
}
func TestResourceLogs_Resource(t *testing.T) {
@ -44,6 +50,10 @@ func TestResourceLogs_SchemaUrl(t *testing.T) {
assert.Equal(t, "", ms.SchemaUrl())
ms.SetSchemaUrl("https://opentelemetry.io/schemas/1.5.0")
assert.Equal(t, "https://opentelemetry.io/schemas/1.5.0", ms.SchemaUrl())
sharedState := internal.StateReadOnly
assert.Panics(t, func() {
newResourceLogs(&otlplogs.ResourceLogs{}, &sharedState).SetSchemaUrl("https://opentelemetry.io/schemas/1.5.0")
})
}
func TestResourceLogs_ScopeLogs(t *testing.T) {
@ -60,7 +70,7 @@ func generateTestResourceLogs() ResourceLogs {
}
func fillTestResourceLogs(tv ResourceLogs) {
internal.FillTestResource(internal.NewResource(&tv.orig.Resource))
internal.FillTestResource(internal.NewResource(&tv.orig.Resource, tv.state))
tv.orig.SchemaUrl = "https://opentelemetry.io/schemas/1.5.0"
fillTestScopeLogsSlice(newScopeLogsSlice(&tv.orig.ScopeLogs))
fillTestScopeLogsSlice(newScopeLogsSlice(&tv.orig.ScopeLogs, tv.state))
}

View File

@ -9,6 +9,7 @@ package plog
import (
"sort"
"go.opentelemetry.io/collector/pdata/internal"
otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1"
)
@ -20,18 +21,20 @@ import (
// Must use NewResourceLogsSlice function to create new instances.
// Important: zero-initialized instance is not valid for use.
type ResourceLogsSlice struct {
orig *[]*otlplogs.ResourceLogs
orig *[]*otlplogs.ResourceLogs
state *internal.State
}
func newResourceLogsSlice(orig *[]*otlplogs.ResourceLogs) ResourceLogsSlice {
return ResourceLogsSlice{orig}
func newResourceLogsSlice(orig *[]*otlplogs.ResourceLogs, state *internal.State) ResourceLogsSlice {
return ResourceLogsSlice{orig: orig, state: state}
}
// NewResourceLogsSlice creates a ResourceLogsSlice with 0 elements.
// Can use "EnsureCapacity" to initialize with a given capacity.
func NewResourceLogsSlice() ResourceLogsSlice {
orig := []*otlplogs.ResourceLogs(nil)
return newResourceLogsSlice(&orig)
state := internal.StateMutable
return newResourceLogsSlice(&orig, &state)
}
// Len returns the number of elements in the slice.
@ -50,7 +53,7 @@ func (es ResourceLogsSlice) Len() int {
// ... // Do something with the element
// }
func (es ResourceLogsSlice) At(i int) ResourceLogs {
return newResourceLogs((*es.orig)[i])
return newResourceLogs((*es.orig)[i], es.state)
}
// EnsureCapacity is an operation that ensures the slice has at least the specified capacity.
@ -66,6 +69,7 @@ func (es ResourceLogsSlice) At(i int) ResourceLogs {
// // Here should set all the values for e.
// }
func (es ResourceLogsSlice) EnsureCapacity(newCap int) {
es.state.AssertMutable()
oldCap := cap(*es.orig)
if newCap <= oldCap {
return
@ -79,6 +83,7 @@ func (es ResourceLogsSlice) EnsureCapacity(newCap int) {
// AppendEmpty will append to the end of the slice an empty ResourceLogs.
// It returns the newly added ResourceLogs.
func (es ResourceLogsSlice) AppendEmpty() ResourceLogs {
es.state.AssertMutable()
*es.orig = append(*es.orig, &otlplogs.ResourceLogs{})
return es.At(es.Len() - 1)
}
@ -86,6 +91,8 @@ func (es ResourceLogsSlice) AppendEmpty() ResourceLogs {
// MoveAndAppendTo moves all elements from the current slice and appends them to the dest.
// The current slice will be cleared.
func (es ResourceLogsSlice) MoveAndAppendTo(dest ResourceLogsSlice) {
es.state.AssertMutable()
dest.state.AssertMutable()
if *dest.orig == nil {
// We can simply move the entire vector and avoid any allocations.
*dest.orig = *es.orig
@ -98,6 +105,7 @@ func (es ResourceLogsSlice) MoveAndAppendTo(dest ResourceLogsSlice) {
// RemoveIf calls f sequentially for each element present in the slice.
// If f returns true, the element is removed from the slice.
func (es ResourceLogsSlice) RemoveIf(f func(ResourceLogs) bool) {
es.state.AssertMutable()
newLen := 0
for i := 0; i < len(*es.orig); i++ {
if f(es.At(i)) {
@ -117,12 +125,13 @@ func (es ResourceLogsSlice) RemoveIf(f func(ResourceLogs) bool) {
// CopyTo copies all elements from the current slice overriding the destination.
func (es ResourceLogsSlice) CopyTo(dest ResourceLogsSlice) {
dest.state.AssertMutable()
srcLen := es.Len()
destCap := cap(*dest.orig)
if srcLen <= destCap {
(*dest.orig) = (*dest.orig)[:srcLen:destCap]
for i := range *es.orig {
newResourceLogs((*es.orig)[i]).CopyTo(newResourceLogs((*dest.orig)[i]))
newResourceLogs((*es.orig)[i], es.state).CopyTo(newResourceLogs((*dest.orig)[i], dest.state))
}
return
}
@ -130,7 +139,7 @@ func (es ResourceLogsSlice) CopyTo(dest ResourceLogsSlice) {
wrappers := make([]*otlplogs.ResourceLogs, srcLen)
for i := range *es.orig {
wrappers[i] = &origs[i]
newResourceLogs((*es.orig)[i]).CopyTo(newResourceLogs(wrappers[i]))
newResourceLogs((*es.orig)[i], es.state).CopyTo(newResourceLogs(wrappers[i], dest.state))
}
*dest.orig = wrappers
}
@ -139,5 +148,6 @@ func (es ResourceLogsSlice) CopyTo(dest ResourceLogsSlice) {
// provided less function so that two instances of ResourceLogsSlice
// can be compared.
func (es ResourceLogsSlice) Sort(less func(a, b ResourceLogs) bool) {
es.state.AssertMutable()
sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) })
}

View File

@ -12,13 +12,15 @@ import (
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1"
)
func TestResourceLogsSlice(t *testing.T) {
es := NewResourceLogsSlice()
assert.Equal(t, 0, es.Len())
es = newResourceLogsSlice(&[]*otlplogs.ResourceLogs{})
state := internal.StateMutable
es = newResourceLogsSlice(&[]*otlplogs.ResourceLogs{}, &state)
assert.Equal(t, 0, es.Len())
emptyVal := NewResourceLogs()
@ -32,6 +34,19 @@ func TestResourceLogsSlice(t *testing.T) {
assert.Equal(t, 7, es.Len())
}
func TestResourceLogsSliceReadOnly(t *testing.T) {
sharedState := internal.StateReadOnly
es := newResourceLogsSlice(&[]*otlplogs.ResourceLogs{}, &sharedState)
assert.Equal(t, 0, es.Len())
assert.Panics(t, func() { es.AppendEmpty() })
assert.Panics(t, func() { es.EnsureCapacity(2) })
es2 := NewResourceLogsSlice()
es.CopyTo(es2)
assert.Panics(t, func() { es2.CopyTo(es) })
assert.Panics(t, func() { es.MoveAndAppendTo(es2) })
assert.Panics(t, func() { es2.MoveAndAppendTo(es) })
}
func TestResourceLogsSlice_CopyTo(t *testing.T) {
dest := NewResourceLogsSlice()
// Test CopyTo to empty
@ -134,6 +149,6 @@ func fillTestResourceLogsSlice(es ResourceLogsSlice) {
*es.orig = make([]*otlplogs.ResourceLogs, 7)
for i := 0; i < 7; i++ {
(*es.orig)[i] = &otlplogs.ResourceLogs{}
fillTestResourceLogs(newResourceLogs((*es.orig)[i]))
fillTestResourceLogs(newResourceLogs((*es.orig)[i], es.state))
}
}

View File

@ -20,11 +20,12 @@ import (
// Must use NewScopeLogs function to create new instances.
// Important: zero-initialized instance is not valid for use.
type ScopeLogs struct {
orig *otlplogs.ScopeLogs
orig *otlplogs.ScopeLogs
state *internal.State
}
func newScopeLogs(orig *otlplogs.ScopeLogs) ScopeLogs {
return ScopeLogs{orig}
func newScopeLogs(orig *otlplogs.ScopeLogs, state *internal.State) ScopeLogs {
return ScopeLogs{orig: orig, state: state}
}
// NewScopeLogs creates a new empty ScopeLogs.
@ -32,19 +33,22 @@ func newScopeLogs(orig *otlplogs.ScopeLogs) ScopeLogs {
// This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice,
// OR directly access the member if this is embedded in another struct.
func NewScopeLogs() ScopeLogs {
return newScopeLogs(&otlplogs.ScopeLogs{})
state := internal.StateMutable
return newScopeLogs(&otlplogs.ScopeLogs{}, &state)
}
// MoveTo moves all properties from the current struct overriding the destination and
// resetting the current instance to its zero value
func (ms ScopeLogs) MoveTo(dest ScopeLogs) {
ms.state.AssertMutable()
dest.state.AssertMutable()
*dest.orig = *ms.orig
*ms.orig = otlplogs.ScopeLogs{}
}
// Scope returns the scope associated with this ScopeLogs.
func (ms ScopeLogs) Scope() pcommon.InstrumentationScope {
return pcommon.InstrumentationScope(internal.NewInstrumentationScope(&ms.orig.Scope))
return pcommon.InstrumentationScope(internal.NewInstrumentationScope(&ms.orig.Scope, ms.state))
}
// SchemaUrl returns the schemaurl associated with this ScopeLogs.
@ -54,16 +58,18 @@ func (ms ScopeLogs) SchemaUrl() string {
// SetSchemaUrl replaces the schemaurl associated with this ScopeLogs.
func (ms ScopeLogs) SetSchemaUrl(v string) {
ms.state.AssertMutable()
ms.orig.SchemaUrl = v
}
// LogRecords returns the LogRecords associated with this ScopeLogs.
func (ms ScopeLogs) LogRecords() LogRecordSlice {
return newLogRecordSlice(&ms.orig.LogRecords)
return newLogRecordSlice(&ms.orig.LogRecords, ms.state)
}
// CopyTo copies all properties from the current struct overriding the destination.
func (ms ScopeLogs) CopyTo(dest ScopeLogs) {
dest.state.AssertMutable()
ms.Scope().CopyTo(dest.Scope())
dest.SetSchemaUrl(ms.SchemaUrl())
ms.LogRecords().CopyTo(dest.LogRecords())

View File

@ -12,6 +12,7 @@ import (
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1"
"go.opentelemetry.io/collector/pdata/pcommon"
)
@ -21,6 +22,9 @@ func TestScopeLogs_MoveTo(t *testing.T) {
ms.MoveTo(dest)
assert.Equal(t, NewScopeLogs(), ms)
assert.Equal(t, generateTestScopeLogs(), dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.MoveTo(newScopeLogs(&otlplogs.ScopeLogs{}, &sharedState)) })
assert.Panics(t, func() { newScopeLogs(&otlplogs.ScopeLogs{}, &sharedState).MoveTo(dest) })
}
func TestScopeLogs_CopyTo(t *testing.T) {
@ -31,6 +35,8 @@ func TestScopeLogs_CopyTo(t *testing.T) {
orig = generateTestScopeLogs()
orig.CopyTo(ms)
assert.Equal(t, orig, ms)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.CopyTo(newScopeLogs(&otlplogs.ScopeLogs{}, &sharedState)) })
}
func TestScopeLogs_Scope(t *testing.T) {
@ -44,6 +50,10 @@ func TestScopeLogs_SchemaUrl(t *testing.T) {
assert.Equal(t, "", ms.SchemaUrl())
ms.SetSchemaUrl("https://opentelemetry.io/schemas/1.5.0")
assert.Equal(t, "https://opentelemetry.io/schemas/1.5.0", ms.SchemaUrl())
sharedState := internal.StateReadOnly
assert.Panics(t, func() {
newScopeLogs(&otlplogs.ScopeLogs{}, &sharedState).SetSchemaUrl("https://opentelemetry.io/schemas/1.5.0")
})
}
func TestScopeLogs_LogRecords(t *testing.T) {
@ -60,7 +70,7 @@ func generateTestScopeLogs() ScopeLogs {
}
func fillTestScopeLogs(tv ScopeLogs) {
internal.FillTestInstrumentationScope(internal.NewInstrumentationScope(&tv.orig.Scope))
internal.FillTestInstrumentationScope(internal.NewInstrumentationScope(&tv.orig.Scope, tv.state))
tv.orig.SchemaUrl = "https://opentelemetry.io/schemas/1.5.0"
fillTestLogRecordSlice(newLogRecordSlice(&tv.orig.LogRecords))
fillTestLogRecordSlice(newLogRecordSlice(&tv.orig.LogRecords, tv.state))
}

View File

@ -9,6 +9,7 @@ package plog
import (
"sort"
"go.opentelemetry.io/collector/pdata/internal"
otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1"
)
@ -20,18 +21,20 @@ import (
// Must use NewScopeLogsSlice function to create new instances.
// Important: zero-initialized instance is not valid for use.
type ScopeLogsSlice struct {
orig *[]*otlplogs.ScopeLogs
orig *[]*otlplogs.ScopeLogs
state *internal.State
}
func newScopeLogsSlice(orig *[]*otlplogs.ScopeLogs) ScopeLogsSlice {
return ScopeLogsSlice{orig}
func newScopeLogsSlice(orig *[]*otlplogs.ScopeLogs, state *internal.State) ScopeLogsSlice {
return ScopeLogsSlice{orig: orig, state: state}
}
// NewScopeLogsSlice creates a ScopeLogsSlice with 0 elements.
// Can use "EnsureCapacity" to initialize with a given capacity.
func NewScopeLogsSlice() ScopeLogsSlice {
orig := []*otlplogs.ScopeLogs(nil)
return newScopeLogsSlice(&orig)
state := internal.StateMutable
return newScopeLogsSlice(&orig, &state)
}
// Len returns the number of elements in the slice.
@ -50,7 +53,7 @@ func (es ScopeLogsSlice) Len() int {
// ... // Do something with the element
// }
func (es ScopeLogsSlice) At(i int) ScopeLogs {
return newScopeLogs((*es.orig)[i])
return newScopeLogs((*es.orig)[i], es.state)
}
// EnsureCapacity is an operation that ensures the slice has at least the specified capacity.
@ -66,6 +69,7 @@ func (es ScopeLogsSlice) At(i int) ScopeLogs {
// // Here should set all the values for e.
// }
func (es ScopeLogsSlice) EnsureCapacity(newCap int) {
es.state.AssertMutable()
oldCap := cap(*es.orig)
if newCap <= oldCap {
return
@ -79,6 +83,7 @@ func (es ScopeLogsSlice) EnsureCapacity(newCap int) {
// AppendEmpty will append to the end of the slice an empty ScopeLogs.
// It returns the newly added ScopeLogs.
func (es ScopeLogsSlice) AppendEmpty() ScopeLogs {
es.state.AssertMutable()
*es.orig = append(*es.orig, &otlplogs.ScopeLogs{})
return es.At(es.Len() - 1)
}
@ -86,6 +91,8 @@ func (es ScopeLogsSlice) AppendEmpty() ScopeLogs {
// MoveAndAppendTo moves all elements from the current slice and appends them to the dest.
// The current slice will be cleared.
func (es ScopeLogsSlice) MoveAndAppendTo(dest ScopeLogsSlice) {
es.state.AssertMutable()
dest.state.AssertMutable()
if *dest.orig == nil {
// We can simply move the entire vector and avoid any allocations.
*dest.orig = *es.orig
@ -98,6 +105,7 @@ func (es ScopeLogsSlice) MoveAndAppendTo(dest ScopeLogsSlice) {
// RemoveIf calls f sequentially for each element present in the slice.
// If f returns true, the element is removed from the slice.
func (es ScopeLogsSlice) RemoveIf(f func(ScopeLogs) bool) {
es.state.AssertMutable()
newLen := 0
for i := 0; i < len(*es.orig); i++ {
if f(es.At(i)) {
@ -117,12 +125,13 @@ func (es ScopeLogsSlice) RemoveIf(f func(ScopeLogs) bool) {
// CopyTo copies all elements from the current slice overriding the destination.
func (es ScopeLogsSlice) CopyTo(dest ScopeLogsSlice) {
dest.state.AssertMutable()
srcLen := es.Len()
destCap := cap(*dest.orig)
if srcLen <= destCap {
(*dest.orig) = (*dest.orig)[:srcLen:destCap]
for i := range *es.orig {
newScopeLogs((*es.orig)[i]).CopyTo(newScopeLogs((*dest.orig)[i]))
newScopeLogs((*es.orig)[i], es.state).CopyTo(newScopeLogs((*dest.orig)[i], dest.state))
}
return
}
@ -130,7 +139,7 @@ func (es ScopeLogsSlice) CopyTo(dest ScopeLogsSlice) {
wrappers := make([]*otlplogs.ScopeLogs, srcLen)
for i := range *es.orig {
wrappers[i] = &origs[i]
newScopeLogs((*es.orig)[i]).CopyTo(newScopeLogs(wrappers[i]))
newScopeLogs((*es.orig)[i], es.state).CopyTo(newScopeLogs(wrappers[i], dest.state))
}
*dest.orig = wrappers
}
@ -139,5 +148,6 @@ func (es ScopeLogsSlice) CopyTo(dest ScopeLogsSlice) {
// provided less function so that two instances of ScopeLogsSlice
// can be compared.
func (es ScopeLogsSlice) Sort(less func(a, b ScopeLogs) bool) {
es.state.AssertMutable()
sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) })
}

View File

@ -12,13 +12,15 @@ import (
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1"
)
func TestScopeLogsSlice(t *testing.T) {
es := NewScopeLogsSlice()
assert.Equal(t, 0, es.Len())
es = newScopeLogsSlice(&[]*otlplogs.ScopeLogs{})
state := internal.StateMutable
es = newScopeLogsSlice(&[]*otlplogs.ScopeLogs{}, &state)
assert.Equal(t, 0, es.Len())
emptyVal := NewScopeLogs()
@ -32,6 +34,19 @@ func TestScopeLogsSlice(t *testing.T) {
assert.Equal(t, 7, es.Len())
}
func TestScopeLogsSliceReadOnly(t *testing.T) {
sharedState := internal.StateReadOnly
es := newScopeLogsSlice(&[]*otlplogs.ScopeLogs{}, &sharedState)
assert.Equal(t, 0, es.Len())
assert.Panics(t, func() { es.AppendEmpty() })
assert.Panics(t, func() { es.EnsureCapacity(2) })
es2 := NewScopeLogsSlice()
es.CopyTo(es2)
assert.Panics(t, func() { es2.CopyTo(es) })
assert.Panics(t, func() { es.MoveAndAppendTo(es2) })
assert.Panics(t, func() { es2.MoveAndAppendTo(es) })
}
func TestScopeLogsSlice_CopyTo(t *testing.T) {
dest := NewScopeLogsSlice()
// Test CopyTo to empty
@ -134,6 +149,6 @@ func fillTestScopeLogsSlice(es ScopeLogsSlice) {
*es.orig = make([]*otlplogs.ScopeLogs, 7)
for i := 0; i < 7; i++ {
(*es.orig)[i] = &otlplogs.ScopeLogs{}
fillTestScopeLogs(newScopeLogs((*es.orig)[i]))
fillTestScopeLogs(newScopeLogs((*es.orig)[i], es.state))
}
}

View File

@ -13,7 +13,8 @@ import (
type Logs internal.Logs
func newLogs(orig *otlpcollectorlog.ExportLogsServiceRequest) Logs {
return Logs(internal.NewLogs(orig))
state := internal.StateMutable
return Logs(internal.NewLogs(orig, &state))
}
func (ms Logs) getOrig() *otlpcollectorlog.ExportLogsServiceRequest {
@ -47,5 +48,10 @@ func (ms Logs) LogRecordCount() int {
// ResourceLogs returns the ResourceLogsSlice associated with this Logs.
func (ms Logs) ResourceLogs() ResourceLogsSlice {
return newResourceLogsSlice(&ms.getOrig().ResourceLogs)
return newResourceLogsSlice(&ms.getOrig().ResourceLogs, internal.GetLogsState(internal.Logs(ms)))
}
// MarkReadOnly marks the Logs as shared so that no further modifications can be done on it.
func (ms Logs) MarkReadOnly() {
internal.SetLogsState(internal.Logs(ms), internal.StateReadOnly)
}

View File

@ -5,6 +5,7 @@ package plog
import (
"testing"
"time"
gogoproto "github.com/gogo/protobuf/proto"
"github.com/stretchr/testify/assert"
@ -13,6 +14,7 @@ import (
otlpcollectorlog "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/logs/v1"
otlplogs "go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1"
"go.opentelemetry.io/collector/pdata/pcommon"
)
func TestLogRecordCount(t *testing.T) {
@ -112,3 +114,58 @@ func TestLogsCopyTo(t *testing.T) {
logs.CopyTo(logsCopy)
assert.EqualValues(t, logs, logsCopy)
}
func TestReadOnlyLogsInvalidUsage(t *testing.T) {
logs := NewLogs()
res := logs.ResourceLogs().AppendEmpty().Resource()
res.Attributes().PutStr("k1", "v1")
logs.MarkReadOnly()
assert.Panics(t, func() { res.Attributes().PutStr("k2", "v2") })
}
func BenchmarkLogsUsage(b *testing.B) {
logs := NewLogs()
fillTestResourceLogsSlice(logs.ResourceLogs())
ts := pcommon.NewTimestampFromTime(time.Now())
b.ReportAllocs()
b.ResetTimer()
for bb := 0; bb < b.N; bb++ {
for i := 0; i < logs.ResourceLogs().Len(); i++ {
rl := logs.ResourceLogs().At(i)
res := rl.Resource()
res.Attributes().PutStr("foo", "bar")
v, ok := res.Attributes().Get("foo")
assert.True(b, ok)
assert.Equal(b, "bar", v.Str())
v.SetStr("new-bar")
assert.Equal(b, "new-bar", v.Str())
res.Attributes().Remove("foo")
for j := 0; j < rl.ScopeLogs().Len(); j++ {
sl := rl.ScopeLogs().At(j)
sl.Scope().SetName("new_test_name")
assert.Equal(b, "new_test_name", sl.Scope().Name())
for k := 0; k < sl.LogRecords().Len(); k++ {
lr := sl.LogRecords().At(k)
lr.Body().SetStr("new_body")
assert.Equal(b, "new_body", lr.Body().Str())
lr.SetTimestamp(ts)
assert.Equal(b, ts, lr.Timestamp())
}
lr := sl.LogRecords().AppendEmpty()
lr.Body().SetStr("another_log_record")
lr.SetTimestamp(ts)
lr.SetObservedTimestamp(ts)
lr.SetSeverityText("info")
lr.SetSeverityNumber(SeverityNumberInfo)
lr.Attributes().PutStr("foo", "bar")
lr.SetSpanID([8]byte{1, 2, 3, 4, 5, 6, 7, 8})
sl.LogRecords().RemoveIf(func(lr LogRecord) bool {
return lr.Body().Str() == "another_log_record"
})
}
}
}
}

View File

@ -7,6 +7,7 @@
package plogotlp
import (
"go.opentelemetry.io/collector/pdata/internal"
otlpcollectorlog "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/logs/v1"
)
@ -18,11 +19,12 @@ import (
// Must use NewExportPartialSuccess function to create new instances.
// Important: zero-initialized instance is not valid for use.
type ExportPartialSuccess struct {
orig *otlpcollectorlog.ExportLogsPartialSuccess
orig *otlpcollectorlog.ExportLogsPartialSuccess
state *internal.State
}
func newExportPartialSuccess(orig *otlpcollectorlog.ExportLogsPartialSuccess) ExportPartialSuccess {
return ExportPartialSuccess{orig}
func newExportPartialSuccess(orig *otlpcollectorlog.ExportLogsPartialSuccess, state *internal.State) ExportPartialSuccess {
return ExportPartialSuccess{orig: orig, state: state}
}
// NewExportPartialSuccess creates a new empty ExportPartialSuccess.
@ -30,12 +32,15 @@ func newExportPartialSuccess(orig *otlpcollectorlog.ExportLogsPartialSuccess) Ex
// This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice,
// OR directly access the member if this is embedded in another struct.
func NewExportPartialSuccess() ExportPartialSuccess {
return newExportPartialSuccess(&otlpcollectorlog.ExportLogsPartialSuccess{})
state := internal.StateMutable
return newExportPartialSuccess(&otlpcollectorlog.ExportLogsPartialSuccess{}, &state)
}
// MoveTo moves all properties from the current struct overriding the destination and
// resetting the current instance to its zero value
func (ms ExportPartialSuccess) MoveTo(dest ExportPartialSuccess) {
ms.state.AssertMutable()
dest.state.AssertMutable()
*dest.orig = *ms.orig
*ms.orig = otlpcollectorlog.ExportLogsPartialSuccess{}
}
@ -47,6 +52,7 @@ func (ms ExportPartialSuccess) RejectedLogRecords() int64 {
// SetRejectedLogRecords replaces the rejectedlogrecords associated with this ExportPartialSuccess.
func (ms ExportPartialSuccess) SetRejectedLogRecords(v int64) {
ms.state.AssertMutable()
ms.orig.RejectedLogRecords = v
}
@ -57,11 +63,13 @@ func (ms ExportPartialSuccess) ErrorMessage() string {
// SetErrorMessage replaces the errormessage associated with this ExportPartialSuccess.
func (ms ExportPartialSuccess) SetErrorMessage(v string) {
ms.state.AssertMutable()
ms.orig.ErrorMessage = v
}
// CopyTo copies all properties from the current struct overriding the destination.
func (ms ExportPartialSuccess) CopyTo(dest ExportPartialSuccess) {
dest.state.AssertMutable()
dest.SetRejectedLogRecords(ms.RejectedLogRecords())
dest.SetErrorMessage(ms.ErrorMessage())
}

View File

@ -10,6 +10,9 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlpcollectorlog "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/logs/v1"
)
func TestExportPartialSuccess_MoveTo(t *testing.T) {
@ -18,6 +21,11 @@ func TestExportPartialSuccess_MoveTo(t *testing.T) {
ms.MoveTo(dest)
assert.Equal(t, NewExportPartialSuccess(), ms)
assert.Equal(t, generateTestExportPartialSuccess(), dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.MoveTo(newExportPartialSuccess(&otlpcollectorlog.ExportLogsPartialSuccess{}, &sharedState)) })
assert.Panics(t, func() {
newExportPartialSuccess(&otlpcollectorlog.ExportLogsPartialSuccess{}, &sharedState).MoveTo(dest)
})
}
func TestExportPartialSuccess_CopyTo(t *testing.T) {
@ -28,6 +36,8 @@ func TestExportPartialSuccess_CopyTo(t *testing.T) {
orig = generateTestExportPartialSuccess()
orig.CopyTo(ms)
assert.Equal(t, orig, ms)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.CopyTo(newExportPartialSuccess(&otlpcollectorlog.ExportLogsPartialSuccess{}, &sharedState)) })
}
func TestExportPartialSuccess_RejectedLogRecords(t *testing.T) {
@ -35,6 +45,10 @@ func TestExportPartialSuccess_RejectedLogRecords(t *testing.T) {
assert.Equal(t, int64(0), ms.RejectedLogRecords())
ms.SetRejectedLogRecords(int64(13))
assert.Equal(t, int64(13), ms.RejectedLogRecords())
sharedState := internal.StateReadOnly
assert.Panics(t, func() {
newExportPartialSuccess(&otlpcollectorlog.ExportLogsPartialSuccess{}, &sharedState).SetRejectedLogRecords(int64(13))
})
}
func TestExportPartialSuccess_ErrorMessage(t *testing.T) {
@ -42,6 +56,10 @@ func TestExportPartialSuccess_ErrorMessage(t *testing.T) {
assert.Equal(t, "", ms.ErrorMessage())
ms.SetErrorMessage("error message")
assert.Equal(t, "error message", ms.ErrorMessage())
sharedState := internal.StateReadOnly
assert.Panics(t, func() {
newExportPartialSuccess(&otlpcollectorlog.ExportLogsPartialSuccess{}, &sharedState).SetErrorMessage("error message")
})
}
func generateTestExportPartialSuccess() ExportPartialSuccess {

View File

@ -10,6 +10,7 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"go.opentelemetry.io/collector/pdata/internal"
otlpcollectorlog "go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/logs/v1"
"go.opentelemetry.io/collector/pdata/internal/otlp"
)
@ -39,7 +40,11 @@ type grpcClient struct {
func (c *grpcClient) Export(ctx context.Context, request ExportRequest, opts ...grpc.CallOption) (ExportResponse, error) {
rsp, err := c.rawClient.Export(ctx, request.orig, opts...)
return ExportResponse{orig: rsp}, err
if err != nil {
return ExportResponse{}, err
}
state := internal.StateMutable
return ExportResponse{orig: rsp, state: &state}, err
}
func (c *grpcClient) unexported() {}
@ -79,6 +84,7 @@ type rawLogsServer struct {
func (s rawLogsServer) Export(ctx context.Context, request *otlpcollectorlog.ExportLogsServiceRequest) (*otlpcollectorlog.ExportLogsServiceResponse, error) {
otlp.MigrateLogs(request.ResourceLogs)
rsp, err := s.srv.Export(ctx, ExportRequest{orig: request})
state := internal.StateMutable
rsp, err := s.srv.Export(ctx, ExportRequest{orig: request, state: &state})
return rsp.orig, err
}

View File

@ -18,19 +18,27 @@ var jsonUnmarshaler = &plog.JSONUnmarshaler{}
// ExportRequest represents the request for gRPC/HTTP client/server.
// It's a wrapper for plog.Logs data.
type ExportRequest struct {
orig *otlpcollectorlog.ExportLogsServiceRequest
orig *otlpcollectorlog.ExportLogsServiceRequest
state *internal.State
}
// NewExportRequest returns an empty ExportRequest.
func NewExportRequest() ExportRequest {
return ExportRequest{orig: &otlpcollectorlog.ExportLogsServiceRequest{}}
state := internal.StateMutable
return ExportRequest{
orig: &otlpcollectorlog.ExportLogsServiceRequest{},
state: &state,
}
}
// NewExportRequestFromLogs returns a ExportRequest from plog.Logs.
// Because ExportRequest is a wrapper for plog.Logs,
// any changes to the provided Logs struct will be reflected in the ExportRequest and vice versa.
func NewExportRequestFromLogs(ld plog.Logs) ExportRequest {
return ExportRequest{orig: internal.GetOrigLogs(internal.Logs(ld))}
return ExportRequest{
orig: internal.GetOrigLogs(internal.Logs(ld)),
state: internal.GetLogsState(internal.Logs(ld)),
}
}
// MarshalProto marshals ExportRequest into proto bytes.
@ -67,5 +75,5 @@ func (ms ExportRequest) UnmarshalJSON(data []byte) error {
}
func (ms ExportRequest) Logs() plog.Logs {
return plog.Logs(internal.NewLogs(ms.orig))
return plog.Logs(internal.NewLogs(ms.orig, ms.state))
}

View File

@ -8,18 +8,24 @@ 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"
)
// ExportResponse represents the response for gRPC/HTTP client/server.
type ExportResponse struct {
orig *otlpcollectorlog.ExportLogsServiceResponse
orig *otlpcollectorlog.ExportLogsServiceResponse
state *internal.State
}
// NewExportResponse returns an empty ExportResponse.
func NewExportResponse() ExportResponse {
return ExportResponse{orig: &otlpcollectorlog.ExportLogsServiceResponse{}}
state := internal.StateMutable
return ExportResponse{
orig: &otlpcollectorlog.ExportLogsServiceResponse{},
state: &state,
}
}
// MarshalProto marshals ExportResponse into proto bytes.
@ -51,7 +57,7 @@ func (ms ExportResponse) UnmarshalJSON(data []byte) error {
// PartialSuccess returns the ExportPartialSuccess associated with this ExportResponse.
func (ms ExportResponse) PartialSuccess() ExportPartialSuccess {
return newExportPartialSuccess(&ms.orig.PartialSuccess)
return newExportPartialSuccess(&ms.orig.PartialSuccess, ms.state)
}
func (ms ExportResponse) unmarshalJsoniter(iter *jsoniter.Iterator) {

View File

@ -24,11 +24,12 @@ import (
// Must use NewExemplar function to create new instances.
// Important: zero-initialized instance is not valid for use.
type Exemplar struct {
orig *otlpmetrics.Exemplar
orig *otlpmetrics.Exemplar
state *internal.State
}
func newExemplar(orig *otlpmetrics.Exemplar) Exemplar {
return Exemplar{orig}
func newExemplar(orig *otlpmetrics.Exemplar, state *internal.State) Exemplar {
return Exemplar{orig: orig, state: state}
}
// NewExemplar creates a new empty Exemplar.
@ -36,12 +37,15 @@ func newExemplar(orig *otlpmetrics.Exemplar) Exemplar {
// This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice,
// OR directly access the member if this is embedded in another struct.
func NewExemplar() Exemplar {
return newExemplar(&otlpmetrics.Exemplar{})
state := internal.StateMutable
return newExemplar(&otlpmetrics.Exemplar{}, &state)
}
// MoveTo moves all properties from the current struct overriding the destination and
// resetting the current instance to its zero value
func (ms Exemplar) MoveTo(dest Exemplar) {
ms.state.AssertMutable()
dest.state.AssertMutable()
*dest.orig = *ms.orig
*ms.orig = otlpmetrics.Exemplar{}
}
@ -53,6 +57,7 @@ func (ms Exemplar) Timestamp() pcommon.Timestamp {
// SetTimestamp replaces the timestamp associated with this Exemplar.
func (ms Exemplar) SetTimestamp(v pcommon.Timestamp) {
ms.state.AssertMutable()
ms.orig.TimeUnixNano = uint64(v)
}
@ -75,6 +80,7 @@ func (ms Exemplar) DoubleValue() float64 {
// SetDoubleValue replaces the double associated with this Exemplar.
func (ms Exemplar) SetDoubleValue(v float64) {
ms.state.AssertMutable()
ms.orig.Value = &otlpmetrics.Exemplar_AsDouble{
AsDouble: v,
}
@ -87,6 +93,7 @@ func (ms Exemplar) IntValue() int64 {
// SetIntValue replaces the int associated with this Exemplar.
func (ms Exemplar) SetIntValue(v int64) {
ms.state.AssertMutable()
ms.orig.Value = &otlpmetrics.Exemplar_AsInt{
AsInt: v,
}
@ -94,7 +101,7 @@ func (ms Exemplar) SetIntValue(v int64) {
// FilteredAttributes returns the FilteredAttributes associated with this Exemplar.
func (ms Exemplar) FilteredAttributes() pcommon.Map {
return pcommon.Map(internal.NewMap(&ms.orig.FilteredAttributes))
return pcommon.Map(internal.NewMap(&ms.orig.FilteredAttributes, ms.state))
}
// TraceID returns the traceid associated with this Exemplar.
@ -104,6 +111,7 @@ func (ms Exemplar) TraceID() pcommon.TraceID {
// SetTraceID replaces the traceid associated with this Exemplar.
func (ms Exemplar) SetTraceID(v pcommon.TraceID) {
ms.state.AssertMutable()
ms.orig.TraceId = data.TraceID(v)
}
@ -114,11 +122,13 @@ func (ms Exemplar) SpanID() pcommon.SpanID {
// SetSpanID replaces the spanid associated with this Exemplar.
func (ms Exemplar) SetSpanID(v pcommon.SpanID) {
ms.state.AssertMutable()
ms.orig.SpanId = data.SpanID(v)
}
// CopyTo copies all properties from the current struct overriding the destination.
func (ms Exemplar) CopyTo(dest Exemplar) {
dest.state.AssertMutable()
dest.SetTimestamp(ms.Timestamp())
switch ms.ValueType() {
case ExemplarValueTypeDouble:

View File

@ -23,6 +23,9 @@ func TestExemplar_MoveTo(t *testing.T) {
ms.MoveTo(dest)
assert.Equal(t, NewExemplar(), ms)
assert.Equal(t, generateTestExemplar(), dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.MoveTo(newExemplar(&otlpmetrics.Exemplar{}, &sharedState)) })
assert.Panics(t, func() { newExemplar(&otlpmetrics.Exemplar{}, &sharedState).MoveTo(dest) })
}
func TestExemplar_CopyTo(t *testing.T) {
@ -33,6 +36,8 @@ func TestExemplar_CopyTo(t *testing.T) {
orig = generateTestExemplar()
orig.CopyTo(ms)
assert.Equal(t, orig, ms)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.CopyTo(newExemplar(&otlpmetrics.Exemplar{}, &sharedState)) })
}
func TestExemplar_Timestamp(t *testing.T) {
@ -54,6 +59,8 @@ func TestExemplar_DoubleValue(t *testing.T) {
ms.SetDoubleValue(float64(17.13))
assert.Equal(t, float64(17.13), ms.DoubleValue())
assert.Equal(t, ExemplarValueTypeDouble, ms.ValueType())
sharedState := internal.StateReadOnly
assert.Panics(t, func() { newExemplar(&otlpmetrics.Exemplar{}, &sharedState).SetDoubleValue(float64(17.13)) })
}
func TestExemplar_IntValue(t *testing.T) {
@ -62,6 +69,8 @@ func TestExemplar_IntValue(t *testing.T) {
ms.SetIntValue(int64(17))
assert.Equal(t, int64(17), ms.IntValue())
assert.Equal(t, ExemplarValueTypeInt, ms.ValueType())
sharedState := internal.StateReadOnly
assert.Panics(t, func() { newExemplar(&otlpmetrics.Exemplar{}, &sharedState).SetIntValue(int64(17)) })
}
func TestExemplar_FilteredAttributes(t *testing.T) {
@ -96,7 +105,7 @@ func generateTestExemplar() Exemplar {
func fillTestExemplar(tv Exemplar) {
tv.orig.TimeUnixNano = 1234567890
tv.orig.Value = &otlpmetrics.Exemplar_AsInt{AsInt: int64(17)}
internal.FillTestMap(internal.NewMap(&tv.orig.FilteredAttributes))
internal.FillTestMap(internal.NewMap(&tv.orig.FilteredAttributes, tv.state))
tv.orig.TraceId = data.TraceID([16]byte{1, 2, 3, 4, 5, 6, 7, 8, 8, 7, 6, 5, 4, 3, 2, 1})
tv.orig.SpanId = data.SpanID([8]byte{8, 7, 6, 5, 4, 3, 2, 1})
}

View File

@ -7,6 +7,7 @@
package pmetric
import (
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
@ -18,18 +19,20 @@ import (
// Must use NewExemplarSlice function to create new instances.
// Important: zero-initialized instance is not valid for use.
type ExemplarSlice struct {
orig *[]otlpmetrics.Exemplar
orig *[]otlpmetrics.Exemplar
state *internal.State
}
func newExemplarSlice(orig *[]otlpmetrics.Exemplar) ExemplarSlice {
return ExemplarSlice{orig}
func newExemplarSlice(orig *[]otlpmetrics.Exemplar, state *internal.State) ExemplarSlice {
return ExemplarSlice{orig: orig, state: state}
}
// NewExemplarSlice creates a ExemplarSlice with 0 elements.
// Can use "EnsureCapacity" to initialize with a given capacity.
func NewExemplarSlice() ExemplarSlice {
orig := []otlpmetrics.Exemplar(nil)
return newExemplarSlice(&orig)
state := internal.StateMutable
return newExemplarSlice(&orig, &state)
}
// Len returns the number of elements in the slice.
@ -48,7 +51,7 @@ func (es ExemplarSlice) Len() int {
// ... // Do something with the element
// }
func (es ExemplarSlice) At(i int) Exemplar {
return newExemplar(&(*es.orig)[i])
return newExemplar(&(*es.orig)[i], es.state)
}
// EnsureCapacity is an operation that ensures the slice has at least the specified capacity.
@ -64,6 +67,7 @@ func (es ExemplarSlice) At(i int) Exemplar {
// // Here should set all the values for e.
// }
func (es ExemplarSlice) EnsureCapacity(newCap int) {
es.state.AssertMutable()
oldCap := cap(*es.orig)
if newCap <= oldCap {
return
@ -77,6 +81,7 @@ func (es ExemplarSlice) EnsureCapacity(newCap int) {
// AppendEmpty will append to the end of the slice an empty Exemplar.
// It returns the newly added Exemplar.
func (es ExemplarSlice) AppendEmpty() Exemplar {
es.state.AssertMutable()
*es.orig = append(*es.orig, otlpmetrics.Exemplar{})
return es.At(es.Len() - 1)
}
@ -84,6 +89,8 @@ func (es ExemplarSlice) AppendEmpty() Exemplar {
// MoveAndAppendTo moves all elements from the current slice and appends them to the dest.
// The current slice will be cleared.
func (es ExemplarSlice) MoveAndAppendTo(dest ExemplarSlice) {
es.state.AssertMutable()
dest.state.AssertMutable()
if *dest.orig == nil {
// We can simply move the entire vector and avoid any allocations.
*dest.orig = *es.orig
@ -96,6 +103,7 @@ func (es ExemplarSlice) MoveAndAppendTo(dest ExemplarSlice) {
// RemoveIf calls f sequentially for each element present in the slice.
// If f returns true, the element is removed from the slice.
func (es ExemplarSlice) RemoveIf(f func(Exemplar) bool) {
es.state.AssertMutable()
newLen := 0
for i := 0; i < len(*es.orig); i++ {
if f(es.At(i)) {
@ -115,6 +123,7 @@ func (es ExemplarSlice) RemoveIf(f func(Exemplar) bool) {
// CopyTo copies all elements from the current slice overriding the destination.
func (es ExemplarSlice) CopyTo(dest ExemplarSlice) {
dest.state.AssertMutable()
srcLen := es.Len()
destCap := cap(*dest.orig)
if srcLen <= destCap {
@ -123,6 +132,6 @@ func (es ExemplarSlice) CopyTo(dest ExemplarSlice) {
(*dest.orig) = make([]otlpmetrics.Exemplar, srcLen)
}
for i := range *es.orig {
newExemplar(&(*es.orig)[i]).CopyTo(newExemplar(&(*dest.orig)[i]))
newExemplar(&(*es.orig)[i], es.state).CopyTo(newExemplar(&(*dest.orig)[i], dest.state))
}
}

View File

@ -11,13 +11,15 @@ import (
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
func TestExemplarSlice(t *testing.T) {
es := NewExemplarSlice()
assert.Equal(t, 0, es.Len())
es = newExemplarSlice(&[]otlpmetrics.Exemplar{})
state := internal.StateMutable
es = newExemplarSlice(&[]otlpmetrics.Exemplar{}, &state)
assert.Equal(t, 0, es.Len())
emptyVal := NewExemplar()
@ -31,6 +33,19 @@ func TestExemplarSlice(t *testing.T) {
assert.Equal(t, 7, es.Len())
}
func TestExemplarSliceReadOnly(t *testing.T) {
sharedState := internal.StateReadOnly
es := newExemplarSlice(&[]otlpmetrics.Exemplar{}, &sharedState)
assert.Equal(t, 0, es.Len())
assert.Panics(t, func() { es.AppendEmpty() })
assert.Panics(t, func() { es.EnsureCapacity(2) })
es2 := NewExemplarSlice()
es.CopyTo(es2)
assert.Panics(t, func() { es2.CopyTo(es) })
assert.Panics(t, func() { es.MoveAndAppendTo(es2) })
assert.Panics(t, func() { es2.MoveAndAppendTo(es) })
}
func TestExemplarSlice_CopyTo(t *testing.T) {
dest := NewExemplarSlice()
// Test CopyTo to empty
@ -117,6 +132,6 @@ func fillTestExemplarSlice(es ExemplarSlice) {
*es.orig = make([]otlpmetrics.Exemplar, 7)
for i := 0; i < 7; i++ {
(*es.orig)[i] = otlpmetrics.Exemplar{}
fillTestExemplar(newExemplar(&(*es.orig)[i]))
fillTestExemplar(newExemplar(&(*es.orig)[i], es.state))
}
}

View File

@ -7,6 +7,7 @@
package pmetric
import (
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
@ -19,11 +20,12 @@ import (
// Must use NewExponentialHistogram function to create new instances.
// Important: zero-initialized instance is not valid for use.
type ExponentialHistogram struct {
orig *otlpmetrics.ExponentialHistogram
orig *otlpmetrics.ExponentialHistogram
state *internal.State
}
func newExponentialHistogram(orig *otlpmetrics.ExponentialHistogram) ExponentialHistogram {
return ExponentialHistogram{orig}
func newExponentialHistogram(orig *otlpmetrics.ExponentialHistogram, state *internal.State) ExponentialHistogram {
return ExponentialHistogram{orig: orig, state: state}
}
// NewExponentialHistogram creates a new empty ExponentialHistogram.
@ -31,12 +33,15 @@ func newExponentialHistogram(orig *otlpmetrics.ExponentialHistogram) Exponential
// This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice,
// OR directly access the member if this is embedded in another struct.
func NewExponentialHistogram() ExponentialHistogram {
return newExponentialHistogram(&otlpmetrics.ExponentialHistogram{})
state := internal.StateMutable
return newExponentialHistogram(&otlpmetrics.ExponentialHistogram{}, &state)
}
// MoveTo moves all properties from the current struct overriding the destination and
// resetting the current instance to its zero value
func (ms ExponentialHistogram) MoveTo(dest ExponentialHistogram) {
ms.state.AssertMutable()
dest.state.AssertMutable()
*dest.orig = *ms.orig
*ms.orig = otlpmetrics.ExponentialHistogram{}
}
@ -48,16 +53,18 @@ func (ms ExponentialHistogram) AggregationTemporality() AggregationTemporality {
// SetAggregationTemporality replaces the aggregationtemporality associated with this ExponentialHistogram.
func (ms ExponentialHistogram) SetAggregationTemporality(v AggregationTemporality) {
ms.state.AssertMutable()
ms.orig.AggregationTemporality = otlpmetrics.AggregationTemporality(v)
}
// DataPoints returns the DataPoints associated with this ExponentialHistogram.
func (ms ExponentialHistogram) DataPoints() ExponentialHistogramDataPointSlice {
return newExponentialHistogramDataPointSlice(&ms.orig.DataPoints)
return newExponentialHistogramDataPointSlice(&ms.orig.DataPoints, ms.state)
}
// CopyTo copies all properties from the current struct overriding the destination.
func (ms ExponentialHistogram) CopyTo(dest ExponentialHistogram) {
dest.state.AssertMutable()
dest.SetAggregationTemporality(ms.AggregationTemporality())
ms.DataPoints().CopyTo(dest.DataPoints())
}

View File

@ -11,6 +11,7 @@ import (
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
@ -20,6 +21,9 @@ func TestExponentialHistogram_MoveTo(t *testing.T) {
ms.MoveTo(dest)
assert.Equal(t, NewExponentialHistogram(), ms)
assert.Equal(t, generateTestExponentialHistogram(), dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.MoveTo(newExponentialHistogram(&otlpmetrics.ExponentialHistogram{}, &sharedState)) })
assert.Panics(t, func() { newExponentialHistogram(&otlpmetrics.ExponentialHistogram{}, &sharedState).MoveTo(dest) })
}
func TestExponentialHistogram_CopyTo(t *testing.T) {
@ -30,6 +34,8 @@ func TestExponentialHistogram_CopyTo(t *testing.T) {
orig = generateTestExponentialHistogram()
orig.CopyTo(ms)
assert.Equal(t, orig, ms)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.CopyTo(newExponentialHistogram(&otlpmetrics.ExponentialHistogram{}, &sharedState)) })
}
func TestExponentialHistogram_AggregationTemporality(t *testing.T) {
@ -55,5 +61,5 @@ func generateTestExponentialHistogram() ExponentialHistogram {
func fillTestExponentialHistogram(tv ExponentialHistogram) {
tv.orig.AggregationTemporality = otlpmetrics.AggregationTemporality(1)
fillTestExponentialHistogramDataPointSlice(newExponentialHistogramDataPointSlice(&tv.orig.DataPoints))
fillTestExponentialHistogramDataPointSlice(newExponentialHistogramDataPointSlice(&tv.orig.DataPoints, tv.state))
}

View File

@ -23,11 +23,12 @@ import (
// Must use NewExponentialHistogramDataPoint function to create new instances.
// Important: zero-initialized instance is not valid for use.
type ExponentialHistogramDataPoint struct {
orig *otlpmetrics.ExponentialHistogramDataPoint
orig *otlpmetrics.ExponentialHistogramDataPoint
state *internal.State
}
func newExponentialHistogramDataPoint(orig *otlpmetrics.ExponentialHistogramDataPoint) ExponentialHistogramDataPoint {
return ExponentialHistogramDataPoint{orig}
func newExponentialHistogramDataPoint(orig *otlpmetrics.ExponentialHistogramDataPoint, state *internal.State) ExponentialHistogramDataPoint {
return ExponentialHistogramDataPoint{orig: orig, state: state}
}
// NewExponentialHistogramDataPoint creates a new empty ExponentialHistogramDataPoint.
@ -35,19 +36,22 @@ func newExponentialHistogramDataPoint(orig *otlpmetrics.ExponentialHistogramData
// This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice,
// OR directly access the member if this is embedded in another struct.
func NewExponentialHistogramDataPoint() ExponentialHistogramDataPoint {
return newExponentialHistogramDataPoint(&otlpmetrics.ExponentialHistogramDataPoint{})
state := internal.StateMutable
return newExponentialHistogramDataPoint(&otlpmetrics.ExponentialHistogramDataPoint{}, &state)
}
// MoveTo moves all properties from the current struct overriding the destination and
// resetting the current instance to its zero value
func (ms ExponentialHistogramDataPoint) MoveTo(dest ExponentialHistogramDataPoint) {
ms.state.AssertMutable()
dest.state.AssertMutable()
*dest.orig = *ms.orig
*ms.orig = otlpmetrics.ExponentialHistogramDataPoint{}
}
// Attributes returns the Attributes associated with this ExponentialHistogramDataPoint.
func (ms ExponentialHistogramDataPoint) Attributes() pcommon.Map {
return pcommon.Map(internal.NewMap(&ms.orig.Attributes))
return pcommon.Map(internal.NewMap(&ms.orig.Attributes, ms.state))
}
// StartTimestamp returns the starttimestamp associated with this ExponentialHistogramDataPoint.
@ -57,6 +61,7 @@ func (ms ExponentialHistogramDataPoint) StartTimestamp() pcommon.Timestamp {
// SetStartTimestamp replaces the starttimestamp associated with this ExponentialHistogramDataPoint.
func (ms ExponentialHistogramDataPoint) SetStartTimestamp(v pcommon.Timestamp) {
ms.state.AssertMutable()
ms.orig.StartTimeUnixNano = uint64(v)
}
@ -67,6 +72,7 @@ func (ms ExponentialHistogramDataPoint) Timestamp() pcommon.Timestamp {
// SetTimestamp replaces the timestamp associated with this ExponentialHistogramDataPoint.
func (ms ExponentialHistogramDataPoint) SetTimestamp(v pcommon.Timestamp) {
ms.state.AssertMutable()
ms.orig.TimeUnixNano = uint64(v)
}
@ -77,6 +83,7 @@ func (ms ExponentialHistogramDataPoint) Count() uint64 {
// SetCount replaces the count associated with this ExponentialHistogramDataPoint.
func (ms ExponentialHistogramDataPoint) SetCount(v uint64) {
ms.state.AssertMutable()
ms.orig.Count = v
}
@ -87,6 +94,7 @@ func (ms ExponentialHistogramDataPoint) Scale() int32 {
// SetScale replaces the scale associated with this ExponentialHistogramDataPoint.
func (ms ExponentialHistogramDataPoint) SetScale(v int32) {
ms.state.AssertMutable()
ms.orig.Scale = v
}
@ -97,22 +105,23 @@ func (ms ExponentialHistogramDataPoint) ZeroCount() uint64 {
// SetZeroCount replaces the zerocount associated with this ExponentialHistogramDataPoint.
func (ms ExponentialHistogramDataPoint) SetZeroCount(v uint64) {
ms.state.AssertMutable()
ms.orig.ZeroCount = v
}
// Positive returns the positive associated with this ExponentialHistogramDataPoint.
func (ms ExponentialHistogramDataPoint) Positive() ExponentialHistogramDataPointBuckets {
return newExponentialHistogramDataPointBuckets(&ms.orig.Positive)
return newExponentialHistogramDataPointBuckets(&ms.orig.Positive, ms.state)
}
// Negative returns the negative associated with this ExponentialHistogramDataPoint.
func (ms ExponentialHistogramDataPoint) Negative() ExponentialHistogramDataPointBuckets {
return newExponentialHistogramDataPointBuckets(&ms.orig.Negative)
return newExponentialHistogramDataPointBuckets(&ms.orig.Negative, ms.state)
}
// Exemplars returns the Exemplars associated with this ExponentialHistogramDataPoint.
func (ms ExponentialHistogramDataPoint) Exemplars() ExemplarSlice {
return newExemplarSlice(&ms.orig.Exemplars)
return newExemplarSlice(&ms.orig.Exemplars, ms.state)
}
// Flags returns the flags associated with this ExponentialHistogramDataPoint.
@ -122,6 +131,7 @@ func (ms ExponentialHistogramDataPoint) Flags() DataPointFlags {
// SetFlags replaces the flags associated with this ExponentialHistogramDataPoint.
func (ms ExponentialHistogramDataPoint) SetFlags(v DataPointFlags) {
ms.state.AssertMutable()
ms.orig.Flags = uint32(v)
}
@ -138,11 +148,13 @@ func (ms ExponentialHistogramDataPoint) HasSum() bool {
// SetSum replaces the sum associated with this ExponentialHistogramDataPoint.
func (ms ExponentialHistogramDataPoint) SetSum(v float64) {
ms.state.AssertMutable()
ms.orig.Sum_ = &otlpmetrics.ExponentialHistogramDataPoint_Sum{Sum: v}
}
// RemoveSum removes the sum associated with this ExponentialHistogramDataPoint.
func (ms ExponentialHistogramDataPoint) RemoveSum() {
ms.state.AssertMutable()
ms.orig.Sum_ = nil
}
@ -159,11 +171,13 @@ func (ms ExponentialHistogramDataPoint) HasMin() bool {
// SetMin replaces the min associated with this ExponentialHistogramDataPoint.
func (ms ExponentialHistogramDataPoint) SetMin(v float64) {
ms.state.AssertMutable()
ms.orig.Min_ = &otlpmetrics.ExponentialHistogramDataPoint_Min{Min: v}
}
// RemoveMin removes the min associated with this ExponentialHistogramDataPoint.
func (ms ExponentialHistogramDataPoint) RemoveMin() {
ms.state.AssertMutable()
ms.orig.Min_ = nil
}
@ -180,16 +194,19 @@ func (ms ExponentialHistogramDataPoint) HasMax() bool {
// SetMax replaces the max associated with this ExponentialHistogramDataPoint.
func (ms ExponentialHistogramDataPoint) SetMax(v float64) {
ms.state.AssertMutable()
ms.orig.Max_ = &otlpmetrics.ExponentialHistogramDataPoint_Max{Max: v}
}
// RemoveMax removes the max associated with this ExponentialHistogramDataPoint.
func (ms ExponentialHistogramDataPoint) RemoveMax() {
ms.state.AssertMutable()
ms.orig.Max_ = nil
}
// CopyTo copies all properties from the current struct overriding the destination.
func (ms ExponentialHistogramDataPoint) CopyTo(dest ExponentialHistogramDataPoint) {
dest.state.AssertMutable()
ms.Attributes().CopyTo(dest.Attributes())
dest.SetStartTimestamp(ms.StartTimestamp())
dest.SetTimestamp(ms.Timestamp())

View File

@ -22,6 +22,13 @@ func TestExponentialHistogramDataPoint_MoveTo(t *testing.T) {
ms.MoveTo(dest)
assert.Equal(t, NewExponentialHistogramDataPoint(), ms)
assert.Equal(t, generateTestExponentialHistogramDataPoint(), dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() {
ms.MoveTo(newExponentialHistogramDataPoint(&otlpmetrics.ExponentialHistogramDataPoint{}, &sharedState))
})
assert.Panics(t, func() {
newExponentialHistogramDataPoint(&otlpmetrics.ExponentialHistogramDataPoint{}, &sharedState).MoveTo(dest)
})
}
func TestExponentialHistogramDataPoint_CopyTo(t *testing.T) {
@ -32,6 +39,10 @@ func TestExponentialHistogramDataPoint_CopyTo(t *testing.T) {
orig = generateTestExponentialHistogramDataPoint()
orig.CopyTo(ms)
assert.Equal(t, orig, ms)
sharedState := internal.StateReadOnly
assert.Panics(t, func() {
ms.CopyTo(newExponentialHistogramDataPoint(&otlpmetrics.ExponentialHistogramDataPoint{}, &sharedState))
})
}
func TestExponentialHistogramDataPoint_Attributes(t *testing.T) {
@ -62,6 +73,10 @@ func TestExponentialHistogramDataPoint_Count(t *testing.T) {
assert.Equal(t, uint64(0), ms.Count())
ms.SetCount(uint64(17))
assert.Equal(t, uint64(17), ms.Count())
sharedState := internal.StateReadOnly
assert.Panics(t, func() {
newExponentialHistogramDataPoint(&otlpmetrics.ExponentialHistogramDataPoint{}, &sharedState).SetCount(uint64(17))
})
}
func TestExponentialHistogramDataPoint_Scale(t *testing.T) {
@ -69,6 +84,10 @@ func TestExponentialHistogramDataPoint_Scale(t *testing.T) {
assert.Equal(t, int32(0), ms.Scale())
ms.SetScale(int32(4))
assert.Equal(t, int32(4), ms.Scale())
sharedState := internal.StateReadOnly
assert.Panics(t, func() {
newExponentialHistogramDataPoint(&otlpmetrics.ExponentialHistogramDataPoint{}, &sharedState).SetScale(int32(4))
})
}
func TestExponentialHistogramDataPoint_ZeroCount(t *testing.T) {
@ -76,6 +95,10 @@ func TestExponentialHistogramDataPoint_ZeroCount(t *testing.T) {
assert.Equal(t, uint64(0), ms.ZeroCount())
ms.SetZeroCount(uint64(201))
assert.Equal(t, uint64(201), ms.ZeroCount())
sharedState := internal.StateReadOnly
assert.Panics(t, func() {
newExponentialHistogramDataPoint(&otlpmetrics.ExponentialHistogramDataPoint{}, &sharedState).SetZeroCount(uint64(201))
})
}
func TestExponentialHistogramDataPoint_Positive(t *testing.T) {
@ -142,15 +165,15 @@ func generateTestExponentialHistogramDataPoint() ExponentialHistogramDataPoint {
}
func fillTestExponentialHistogramDataPoint(tv ExponentialHistogramDataPoint) {
internal.FillTestMap(internal.NewMap(&tv.orig.Attributes))
internal.FillTestMap(internal.NewMap(&tv.orig.Attributes, tv.state))
tv.orig.StartTimeUnixNano = 1234567890
tv.orig.TimeUnixNano = 1234567890
tv.orig.Count = uint64(17)
tv.orig.Scale = int32(4)
tv.orig.ZeroCount = uint64(201)
fillTestExponentialHistogramDataPointBuckets(newExponentialHistogramDataPointBuckets(&tv.orig.Positive))
fillTestExponentialHistogramDataPointBuckets(newExponentialHistogramDataPointBuckets(&tv.orig.Negative))
fillTestExemplarSlice(newExemplarSlice(&tv.orig.Exemplars))
fillTestExponentialHistogramDataPointBuckets(newExponentialHistogramDataPointBuckets(&tv.orig.Positive, tv.state))
fillTestExponentialHistogramDataPointBuckets(newExponentialHistogramDataPointBuckets(&tv.orig.Negative, tv.state))
fillTestExemplarSlice(newExemplarSlice(&tv.orig.Exemplars, tv.state))
tv.orig.Flags = 1
tv.orig.Sum_ = &otlpmetrics.ExponentialHistogramDataPoint_Sum{Sum: float64(17.13)}
tv.orig.Min_ = &otlpmetrics.ExponentialHistogramDataPoint_Min{Min: float64(9.23)}

View File

@ -20,11 +20,12 @@ import (
// Must use NewExponentialHistogramDataPointBuckets function to create new instances.
// Important: zero-initialized instance is not valid for use.
type ExponentialHistogramDataPointBuckets struct {
orig *otlpmetrics.ExponentialHistogramDataPoint_Buckets
orig *otlpmetrics.ExponentialHistogramDataPoint_Buckets
state *internal.State
}
func newExponentialHistogramDataPointBuckets(orig *otlpmetrics.ExponentialHistogramDataPoint_Buckets) ExponentialHistogramDataPointBuckets {
return ExponentialHistogramDataPointBuckets{orig}
func newExponentialHistogramDataPointBuckets(orig *otlpmetrics.ExponentialHistogramDataPoint_Buckets, state *internal.State) ExponentialHistogramDataPointBuckets {
return ExponentialHistogramDataPointBuckets{orig: orig, state: state}
}
// NewExponentialHistogramDataPointBuckets creates a new empty ExponentialHistogramDataPointBuckets.
@ -32,12 +33,15 @@ func newExponentialHistogramDataPointBuckets(orig *otlpmetrics.ExponentialHistog
// This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice,
// OR directly access the member if this is embedded in another struct.
func NewExponentialHistogramDataPointBuckets() ExponentialHistogramDataPointBuckets {
return newExponentialHistogramDataPointBuckets(&otlpmetrics.ExponentialHistogramDataPoint_Buckets{})
state := internal.StateMutable
return newExponentialHistogramDataPointBuckets(&otlpmetrics.ExponentialHistogramDataPoint_Buckets{}, &state)
}
// MoveTo moves all properties from the current struct overriding the destination and
// resetting the current instance to its zero value
func (ms ExponentialHistogramDataPointBuckets) MoveTo(dest ExponentialHistogramDataPointBuckets) {
ms.state.AssertMutable()
dest.state.AssertMutable()
*dest.orig = *ms.orig
*ms.orig = otlpmetrics.ExponentialHistogramDataPoint_Buckets{}
}
@ -49,16 +53,18 @@ func (ms ExponentialHistogramDataPointBuckets) Offset() int32 {
// SetOffset replaces the offset associated with this ExponentialHistogramDataPointBuckets.
func (ms ExponentialHistogramDataPointBuckets) SetOffset(v int32) {
ms.state.AssertMutable()
ms.orig.Offset = v
}
// BucketCounts returns the bucketcounts associated with this ExponentialHistogramDataPointBuckets.
func (ms ExponentialHistogramDataPointBuckets) BucketCounts() pcommon.UInt64Slice {
return pcommon.UInt64Slice(internal.NewUInt64Slice(&ms.orig.BucketCounts))
return pcommon.UInt64Slice(internal.NewUInt64Slice(&ms.orig.BucketCounts, ms.state))
}
// CopyTo copies all properties from the current struct overriding the destination.
func (ms ExponentialHistogramDataPointBuckets) CopyTo(dest ExponentialHistogramDataPointBuckets) {
dest.state.AssertMutable()
dest.SetOffset(ms.Offset())
ms.BucketCounts().CopyTo(dest.BucketCounts())
}

View File

@ -10,6 +10,9 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
func TestExponentialHistogramDataPointBuckets_MoveTo(t *testing.T) {
@ -18,6 +21,13 @@ func TestExponentialHistogramDataPointBuckets_MoveTo(t *testing.T) {
ms.MoveTo(dest)
assert.Equal(t, NewExponentialHistogramDataPointBuckets(), ms)
assert.Equal(t, generateTestExponentialHistogramDataPointBuckets(), dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() {
ms.MoveTo(newExponentialHistogramDataPointBuckets(&otlpmetrics.ExponentialHistogramDataPoint_Buckets{}, &sharedState))
})
assert.Panics(t, func() {
newExponentialHistogramDataPointBuckets(&otlpmetrics.ExponentialHistogramDataPoint_Buckets{}, &sharedState).MoveTo(dest)
})
}
func TestExponentialHistogramDataPointBuckets_CopyTo(t *testing.T) {
@ -28,6 +38,10 @@ func TestExponentialHistogramDataPointBuckets_CopyTo(t *testing.T) {
orig = generateTestExponentialHistogramDataPointBuckets()
orig.CopyTo(ms)
assert.Equal(t, orig, ms)
sharedState := internal.StateReadOnly
assert.Panics(t, func() {
ms.CopyTo(newExponentialHistogramDataPointBuckets(&otlpmetrics.ExponentialHistogramDataPoint_Buckets{}, &sharedState))
})
}
func TestExponentialHistogramDataPointBuckets_Offset(t *testing.T) {
@ -35,6 +49,10 @@ func TestExponentialHistogramDataPointBuckets_Offset(t *testing.T) {
assert.Equal(t, int32(0), ms.Offset())
ms.SetOffset(int32(909))
assert.Equal(t, int32(909), ms.Offset())
sharedState := internal.StateReadOnly
assert.Panics(t, func() {
newExponentialHistogramDataPointBuckets(&otlpmetrics.ExponentialHistogramDataPoint_Buckets{}, &sharedState).SetOffset(int32(909))
})
}
func TestExponentialHistogramDataPointBuckets_BucketCounts(t *testing.T) {

View File

@ -9,6 +9,7 @@ package pmetric
import (
"sort"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
@ -20,18 +21,20 @@ import (
// Must use NewExponentialHistogramDataPointSlice function to create new instances.
// Important: zero-initialized instance is not valid for use.
type ExponentialHistogramDataPointSlice struct {
orig *[]*otlpmetrics.ExponentialHistogramDataPoint
orig *[]*otlpmetrics.ExponentialHistogramDataPoint
state *internal.State
}
func newExponentialHistogramDataPointSlice(orig *[]*otlpmetrics.ExponentialHistogramDataPoint) ExponentialHistogramDataPointSlice {
return ExponentialHistogramDataPointSlice{orig}
func newExponentialHistogramDataPointSlice(orig *[]*otlpmetrics.ExponentialHistogramDataPoint, state *internal.State) ExponentialHistogramDataPointSlice {
return ExponentialHistogramDataPointSlice{orig: orig, state: state}
}
// NewExponentialHistogramDataPointSlice creates a ExponentialHistogramDataPointSlice with 0 elements.
// Can use "EnsureCapacity" to initialize with a given capacity.
func NewExponentialHistogramDataPointSlice() ExponentialHistogramDataPointSlice {
orig := []*otlpmetrics.ExponentialHistogramDataPoint(nil)
return newExponentialHistogramDataPointSlice(&orig)
state := internal.StateMutable
return newExponentialHistogramDataPointSlice(&orig, &state)
}
// Len returns the number of elements in the slice.
@ -50,7 +53,7 @@ func (es ExponentialHistogramDataPointSlice) Len() int {
// ... // Do something with the element
// }
func (es ExponentialHistogramDataPointSlice) At(i int) ExponentialHistogramDataPoint {
return newExponentialHistogramDataPoint((*es.orig)[i])
return newExponentialHistogramDataPoint((*es.orig)[i], es.state)
}
// EnsureCapacity is an operation that ensures the slice has at least the specified capacity.
@ -66,6 +69,7 @@ func (es ExponentialHistogramDataPointSlice) At(i int) ExponentialHistogramDataP
// // Here should set all the values for e.
// }
func (es ExponentialHistogramDataPointSlice) EnsureCapacity(newCap int) {
es.state.AssertMutable()
oldCap := cap(*es.orig)
if newCap <= oldCap {
return
@ -79,6 +83,7 @@ func (es ExponentialHistogramDataPointSlice) EnsureCapacity(newCap int) {
// AppendEmpty will append to the end of the slice an empty ExponentialHistogramDataPoint.
// It returns the newly added ExponentialHistogramDataPoint.
func (es ExponentialHistogramDataPointSlice) AppendEmpty() ExponentialHistogramDataPoint {
es.state.AssertMutable()
*es.orig = append(*es.orig, &otlpmetrics.ExponentialHistogramDataPoint{})
return es.At(es.Len() - 1)
}
@ -86,6 +91,8 @@ func (es ExponentialHistogramDataPointSlice) AppendEmpty() ExponentialHistogramD
// MoveAndAppendTo moves all elements from the current slice and appends them to the dest.
// The current slice will be cleared.
func (es ExponentialHistogramDataPointSlice) MoveAndAppendTo(dest ExponentialHistogramDataPointSlice) {
es.state.AssertMutable()
dest.state.AssertMutable()
if *dest.orig == nil {
// We can simply move the entire vector and avoid any allocations.
*dest.orig = *es.orig
@ -98,6 +105,7 @@ func (es ExponentialHistogramDataPointSlice) MoveAndAppendTo(dest ExponentialHis
// RemoveIf calls f sequentially for each element present in the slice.
// If f returns true, the element is removed from the slice.
func (es ExponentialHistogramDataPointSlice) RemoveIf(f func(ExponentialHistogramDataPoint) bool) {
es.state.AssertMutable()
newLen := 0
for i := 0; i < len(*es.orig); i++ {
if f(es.At(i)) {
@ -117,12 +125,13 @@ func (es ExponentialHistogramDataPointSlice) RemoveIf(f func(ExponentialHistogra
// CopyTo copies all elements from the current slice overriding the destination.
func (es ExponentialHistogramDataPointSlice) CopyTo(dest ExponentialHistogramDataPointSlice) {
dest.state.AssertMutable()
srcLen := es.Len()
destCap := cap(*dest.orig)
if srcLen <= destCap {
(*dest.orig) = (*dest.orig)[:srcLen:destCap]
for i := range *es.orig {
newExponentialHistogramDataPoint((*es.orig)[i]).CopyTo(newExponentialHistogramDataPoint((*dest.orig)[i]))
newExponentialHistogramDataPoint((*es.orig)[i], es.state).CopyTo(newExponentialHistogramDataPoint((*dest.orig)[i], dest.state))
}
return
}
@ -130,7 +139,7 @@ func (es ExponentialHistogramDataPointSlice) CopyTo(dest ExponentialHistogramDat
wrappers := make([]*otlpmetrics.ExponentialHistogramDataPoint, srcLen)
for i := range *es.orig {
wrappers[i] = &origs[i]
newExponentialHistogramDataPoint((*es.orig)[i]).CopyTo(newExponentialHistogramDataPoint(wrappers[i]))
newExponentialHistogramDataPoint((*es.orig)[i], es.state).CopyTo(newExponentialHistogramDataPoint(wrappers[i], dest.state))
}
*dest.orig = wrappers
}
@ -139,5 +148,6 @@ func (es ExponentialHistogramDataPointSlice) CopyTo(dest ExponentialHistogramDat
// provided less function so that two instances of ExponentialHistogramDataPointSlice
// can be compared.
func (es ExponentialHistogramDataPointSlice) Sort(less func(a, b ExponentialHistogramDataPoint) bool) {
es.state.AssertMutable()
sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) })
}

View File

@ -12,13 +12,15 @@ import (
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
func TestExponentialHistogramDataPointSlice(t *testing.T) {
es := NewExponentialHistogramDataPointSlice()
assert.Equal(t, 0, es.Len())
es = newExponentialHistogramDataPointSlice(&[]*otlpmetrics.ExponentialHistogramDataPoint{})
state := internal.StateMutable
es = newExponentialHistogramDataPointSlice(&[]*otlpmetrics.ExponentialHistogramDataPoint{}, &state)
assert.Equal(t, 0, es.Len())
emptyVal := NewExponentialHistogramDataPoint()
@ -32,6 +34,19 @@ func TestExponentialHistogramDataPointSlice(t *testing.T) {
assert.Equal(t, 7, es.Len())
}
func TestExponentialHistogramDataPointSliceReadOnly(t *testing.T) {
sharedState := internal.StateReadOnly
es := newExponentialHistogramDataPointSlice(&[]*otlpmetrics.ExponentialHistogramDataPoint{}, &sharedState)
assert.Equal(t, 0, es.Len())
assert.Panics(t, func() { es.AppendEmpty() })
assert.Panics(t, func() { es.EnsureCapacity(2) })
es2 := NewExponentialHistogramDataPointSlice()
es.CopyTo(es2)
assert.Panics(t, func() { es2.CopyTo(es) })
assert.Panics(t, func() { es.MoveAndAppendTo(es2) })
assert.Panics(t, func() { es2.MoveAndAppendTo(es) })
}
func TestExponentialHistogramDataPointSlice_CopyTo(t *testing.T) {
dest := NewExponentialHistogramDataPointSlice()
// Test CopyTo to empty
@ -134,6 +149,6 @@ func fillTestExponentialHistogramDataPointSlice(es ExponentialHistogramDataPoint
*es.orig = make([]*otlpmetrics.ExponentialHistogramDataPoint, 7)
for i := 0; i < 7; i++ {
(*es.orig)[i] = &otlpmetrics.ExponentialHistogramDataPoint{}
fillTestExponentialHistogramDataPoint(newExponentialHistogramDataPoint((*es.orig)[i]))
fillTestExponentialHistogramDataPoint(newExponentialHistogramDataPoint((*es.orig)[i], es.state))
}
}

View File

@ -7,6 +7,7 @@
package pmetric
import (
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
@ -18,11 +19,12 @@ import (
// Must use NewGauge function to create new instances.
// Important: zero-initialized instance is not valid for use.
type Gauge struct {
orig *otlpmetrics.Gauge
orig *otlpmetrics.Gauge
state *internal.State
}
func newGauge(orig *otlpmetrics.Gauge) Gauge {
return Gauge{orig}
func newGauge(orig *otlpmetrics.Gauge, state *internal.State) Gauge {
return Gauge{orig: orig, state: state}
}
// NewGauge creates a new empty Gauge.
@ -30,22 +32,26 @@ func newGauge(orig *otlpmetrics.Gauge) Gauge {
// This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice,
// OR directly access the member if this is embedded in another struct.
func NewGauge() Gauge {
return newGauge(&otlpmetrics.Gauge{})
state := internal.StateMutable
return newGauge(&otlpmetrics.Gauge{}, &state)
}
// MoveTo moves all properties from the current struct overriding the destination and
// resetting the current instance to its zero value
func (ms Gauge) MoveTo(dest Gauge) {
ms.state.AssertMutable()
dest.state.AssertMutable()
*dest.orig = *ms.orig
*ms.orig = otlpmetrics.Gauge{}
}
// DataPoints returns the DataPoints associated with this Gauge.
func (ms Gauge) DataPoints() NumberDataPointSlice {
return newNumberDataPointSlice(&ms.orig.DataPoints)
return newNumberDataPointSlice(&ms.orig.DataPoints, ms.state)
}
// CopyTo copies all properties from the current struct overriding the destination.
func (ms Gauge) CopyTo(dest Gauge) {
dest.state.AssertMutable()
ms.DataPoints().CopyTo(dest.DataPoints())
}

View File

@ -10,6 +10,9 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
func TestGauge_MoveTo(t *testing.T) {
@ -18,6 +21,9 @@ func TestGauge_MoveTo(t *testing.T) {
ms.MoveTo(dest)
assert.Equal(t, NewGauge(), ms)
assert.Equal(t, generateTestGauge(), dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.MoveTo(newGauge(&otlpmetrics.Gauge{}, &sharedState)) })
assert.Panics(t, func() { newGauge(&otlpmetrics.Gauge{}, &sharedState).MoveTo(dest) })
}
func TestGauge_CopyTo(t *testing.T) {
@ -28,6 +34,8 @@ func TestGauge_CopyTo(t *testing.T) {
orig = generateTestGauge()
orig.CopyTo(ms)
assert.Equal(t, orig, ms)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.CopyTo(newGauge(&otlpmetrics.Gauge{}, &sharedState)) })
}
func TestGauge_DataPoints(t *testing.T) {
@ -44,5 +52,5 @@ func generateTestGauge() Gauge {
}
func fillTestGauge(tv Gauge) {
fillTestNumberDataPointSlice(newNumberDataPointSlice(&tv.orig.DataPoints))
fillTestNumberDataPointSlice(newNumberDataPointSlice(&tv.orig.DataPoints, tv.state))
}

View File

@ -7,6 +7,7 @@
package pmetric
import (
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
@ -18,11 +19,12 @@ import (
// Must use NewHistogram function to create new instances.
// Important: zero-initialized instance is not valid for use.
type Histogram struct {
orig *otlpmetrics.Histogram
orig *otlpmetrics.Histogram
state *internal.State
}
func newHistogram(orig *otlpmetrics.Histogram) Histogram {
return Histogram{orig}
func newHistogram(orig *otlpmetrics.Histogram, state *internal.State) Histogram {
return Histogram{orig: orig, state: state}
}
// NewHistogram creates a new empty Histogram.
@ -30,12 +32,15 @@ func newHistogram(orig *otlpmetrics.Histogram) Histogram {
// This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice,
// OR directly access the member if this is embedded in another struct.
func NewHistogram() Histogram {
return newHistogram(&otlpmetrics.Histogram{})
state := internal.StateMutable
return newHistogram(&otlpmetrics.Histogram{}, &state)
}
// MoveTo moves all properties from the current struct overriding the destination and
// resetting the current instance to its zero value
func (ms Histogram) MoveTo(dest Histogram) {
ms.state.AssertMutable()
dest.state.AssertMutable()
*dest.orig = *ms.orig
*ms.orig = otlpmetrics.Histogram{}
}
@ -47,16 +52,18 @@ func (ms Histogram) AggregationTemporality() AggregationTemporality {
// SetAggregationTemporality replaces the aggregationtemporality associated with this Histogram.
func (ms Histogram) SetAggregationTemporality(v AggregationTemporality) {
ms.state.AssertMutable()
ms.orig.AggregationTemporality = otlpmetrics.AggregationTemporality(v)
}
// DataPoints returns the DataPoints associated with this Histogram.
func (ms Histogram) DataPoints() HistogramDataPointSlice {
return newHistogramDataPointSlice(&ms.orig.DataPoints)
return newHistogramDataPointSlice(&ms.orig.DataPoints, ms.state)
}
// CopyTo copies all properties from the current struct overriding the destination.
func (ms Histogram) CopyTo(dest Histogram) {
dest.state.AssertMutable()
dest.SetAggregationTemporality(ms.AggregationTemporality())
ms.DataPoints().CopyTo(dest.DataPoints())
}

View File

@ -11,6 +11,7 @@ import (
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
@ -20,6 +21,9 @@ func TestHistogram_MoveTo(t *testing.T) {
ms.MoveTo(dest)
assert.Equal(t, NewHistogram(), ms)
assert.Equal(t, generateTestHistogram(), dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.MoveTo(newHistogram(&otlpmetrics.Histogram{}, &sharedState)) })
assert.Panics(t, func() { newHistogram(&otlpmetrics.Histogram{}, &sharedState).MoveTo(dest) })
}
func TestHistogram_CopyTo(t *testing.T) {
@ -30,6 +34,8 @@ func TestHistogram_CopyTo(t *testing.T) {
orig = generateTestHistogram()
orig.CopyTo(ms)
assert.Equal(t, orig, ms)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.CopyTo(newHistogram(&otlpmetrics.Histogram{}, &sharedState)) })
}
func TestHistogram_AggregationTemporality(t *testing.T) {
@ -55,5 +61,5 @@ func generateTestHistogram() Histogram {
func fillTestHistogram(tv Histogram) {
tv.orig.AggregationTemporality = otlpmetrics.AggregationTemporality(1)
fillTestHistogramDataPointSlice(newHistogramDataPointSlice(&tv.orig.DataPoints))
fillTestHistogramDataPointSlice(newHistogramDataPointSlice(&tv.orig.DataPoints, tv.state))
}

View File

@ -20,11 +20,12 @@ import (
// Must use NewHistogramDataPoint function to create new instances.
// Important: zero-initialized instance is not valid for use.
type HistogramDataPoint struct {
orig *otlpmetrics.HistogramDataPoint
orig *otlpmetrics.HistogramDataPoint
state *internal.State
}
func newHistogramDataPoint(orig *otlpmetrics.HistogramDataPoint) HistogramDataPoint {
return HistogramDataPoint{orig}
func newHistogramDataPoint(orig *otlpmetrics.HistogramDataPoint, state *internal.State) HistogramDataPoint {
return HistogramDataPoint{orig: orig, state: state}
}
// NewHistogramDataPoint creates a new empty HistogramDataPoint.
@ -32,19 +33,22 @@ func newHistogramDataPoint(orig *otlpmetrics.HistogramDataPoint) HistogramDataPo
// This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice,
// OR directly access the member if this is embedded in another struct.
func NewHistogramDataPoint() HistogramDataPoint {
return newHistogramDataPoint(&otlpmetrics.HistogramDataPoint{})
state := internal.StateMutable
return newHistogramDataPoint(&otlpmetrics.HistogramDataPoint{}, &state)
}
// MoveTo moves all properties from the current struct overriding the destination and
// resetting the current instance to its zero value
func (ms HistogramDataPoint) MoveTo(dest HistogramDataPoint) {
ms.state.AssertMutable()
dest.state.AssertMutable()
*dest.orig = *ms.orig
*ms.orig = otlpmetrics.HistogramDataPoint{}
}
// Attributes returns the Attributes associated with this HistogramDataPoint.
func (ms HistogramDataPoint) Attributes() pcommon.Map {
return pcommon.Map(internal.NewMap(&ms.orig.Attributes))
return pcommon.Map(internal.NewMap(&ms.orig.Attributes, ms.state))
}
// StartTimestamp returns the starttimestamp associated with this HistogramDataPoint.
@ -54,6 +58,7 @@ func (ms HistogramDataPoint) StartTimestamp() pcommon.Timestamp {
// SetStartTimestamp replaces the starttimestamp associated with this HistogramDataPoint.
func (ms HistogramDataPoint) SetStartTimestamp(v pcommon.Timestamp) {
ms.state.AssertMutable()
ms.orig.StartTimeUnixNano = uint64(v)
}
@ -64,6 +69,7 @@ func (ms HistogramDataPoint) Timestamp() pcommon.Timestamp {
// SetTimestamp replaces the timestamp associated with this HistogramDataPoint.
func (ms HistogramDataPoint) SetTimestamp(v pcommon.Timestamp) {
ms.state.AssertMutable()
ms.orig.TimeUnixNano = uint64(v)
}
@ -74,22 +80,23 @@ func (ms HistogramDataPoint) Count() uint64 {
// SetCount replaces the count associated with this HistogramDataPoint.
func (ms HistogramDataPoint) SetCount(v uint64) {
ms.state.AssertMutable()
ms.orig.Count = v
}
// BucketCounts returns the bucketcounts associated with this HistogramDataPoint.
func (ms HistogramDataPoint) BucketCounts() pcommon.UInt64Slice {
return pcommon.UInt64Slice(internal.NewUInt64Slice(&ms.orig.BucketCounts))
return pcommon.UInt64Slice(internal.NewUInt64Slice(&ms.orig.BucketCounts, ms.state))
}
// ExplicitBounds returns the explicitbounds associated with this HistogramDataPoint.
func (ms HistogramDataPoint) ExplicitBounds() pcommon.Float64Slice {
return pcommon.Float64Slice(internal.NewFloat64Slice(&ms.orig.ExplicitBounds))
return pcommon.Float64Slice(internal.NewFloat64Slice(&ms.orig.ExplicitBounds, ms.state))
}
// Exemplars returns the Exemplars associated with this HistogramDataPoint.
func (ms HistogramDataPoint) Exemplars() ExemplarSlice {
return newExemplarSlice(&ms.orig.Exemplars)
return newExemplarSlice(&ms.orig.Exemplars, ms.state)
}
// Flags returns the flags associated with this HistogramDataPoint.
@ -99,6 +106,7 @@ func (ms HistogramDataPoint) Flags() DataPointFlags {
// SetFlags replaces the flags associated with this HistogramDataPoint.
func (ms HistogramDataPoint) SetFlags(v DataPointFlags) {
ms.state.AssertMutable()
ms.orig.Flags = uint32(v)
}
@ -115,11 +123,13 @@ func (ms HistogramDataPoint) HasSum() bool {
// SetSum replaces the sum associated with this HistogramDataPoint.
func (ms HistogramDataPoint) SetSum(v float64) {
ms.state.AssertMutable()
ms.orig.Sum_ = &otlpmetrics.HistogramDataPoint_Sum{Sum: v}
}
// RemoveSum removes the sum associated with this HistogramDataPoint.
func (ms HistogramDataPoint) RemoveSum() {
ms.state.AssertMutable()
ms.orig.Sum_ = nil
}
@ -136,11 +146,13 @@ func (ms HistogramDataPoint) HasMin() bool {
// SetMin replaces the min associated with this HistogramDataPoint.
func (ms HistogramDataPoint) SetMin(v float64) {
ms.state.AssertMutable()
ms.orig.Min_ = &otlpmetrics.HistogramDataPoint_Min{Min: v}
}
// RemoveMin removes the min associated with this HistogramDataPoint.
func (ms HistogramDataPoint) RemoveMin() {
ms.state.AssertMutable()
ms.orig.Min_ = nil
}
@ -157,16 +169,19 @@ func (ms HistogramDataPoint) HasMax() bool {
// SetMax replaces the max associated with this HistogramDataPoint.
func (ms HistogramDataPoint) SetMax(v float64) {
ms.state.AssertMutable()
ms.orig.Max_ = &otlpmetrics.HistogramDataPoint_Max{Max: v}
}
// RemoveMax removes the max associated with this HistogramDataPoint.
func (ms HistogramDataPoint) RemoveMax() {
ms.state.AssertMutable()
ms.orig.Max_ = nil
}
// CopyTo copies all properties from the current struct overriding the destination.
func (ms HistogramDataPoint) CopyTo(dest HistogramDataPoint) {
dest.state.AssertMutable()
ms.Attributes().CopyTo(dest.Attributes())
dest.SetStartTimestamp(ms.StartTimestamp())
dest.SetTimestamp(ms.Timestamp())

View File

@ -22,6 +22,9 @@ func TestHistogramDataPoint_MoveTo(t *testing.T) {
ms.MoveTo(dest)
assert.Equal(t, NewHistogramDataPoint(), ms)
assert.Equal(t, generateTestHistogramDataPoint(), dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.MoveTo(newHistogramDataPoint(&otlpmetrics.HistogramDataPoint{}, &sharedState)) })
assert.Panics(t, func() { newHistogramDataPoint(&otlpmetrics.HistogramDataPoint{}, &sharedState).MoveTo(dest) })
}
func TestHistogramDataPoint_CopyTo(t *testing.T) {
@ -32,6 +35,8 @@ func TestHistogramDataPoint_CopyTo(t *testing.T) {
orig = generateTestHistogramDataPoint()
orig.CopyTo(ms)
assert.Equal(t, orig, ms)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.CopyTo(newHistogramDataPoint(&otlpmetrics.HistogramDataPoint{}, &sharedState)) })
}
func TestHistogramDataPoint_Attributes(t *testing.T) {
@ -62,6 +67,8 @@ func TestHistogramDataPoint_Count(t *testing.T) {
assert.Equal(t, uint64(0), ms.Count())
ms.SetCount(uint64(17))
assert.Equal(t, uint64(17), ms.Count())
sharedState := internal.StateReadOnly
assert.Panics(t, func() { newHistogramDataPoint(&otlpmetrics.HistogramDataPoint{}, &sharedState).SetCount(uint64(17)) })
}
func TestHistogramDataPoint_BucketCounts(t *testing.T) {
@ -130,13 +137,13 @@ func generateTestHistogramDataPoint() HistogramDataPoint {
}
func fillTestHistogramDataPoint(tv HistogramDataPoint) {
internal.FillTestMap(internal.NewMap(&tv.orig.Attributes))
internal.FillTestMap(internal.NewMap(&tv.orig.Attributes, tv.state))
tv.orig.StartTimeUnixNano = 1234567890
tv.orig.TimeUnixNano = 1234567890
tv.orig.Count = uint64(17)
tv.orig.BucketCounts = []uint64{1, 2, 3}
tv.orig.ExplicitBounds = []float64{1, 2, 3}
fillTestExemplarSlice(newExemplarSlice(&tv.orig.Exemplars))
fillTestExemplarSlice(newExemplarSlice(&tv.orig.Exemplars, tv.state))
tv.orig.Flags = 1
tv.orig.Sum_ = &otlpmetrics.HistogramDataPoint_Sum{Sum: float64(17.13)}
tv.orig.Min_ = &otlpmetrics.HistogramDataPoint_Min{Min: float64(9.23)}

View File

@ -9,6 +9,7 @@ package pmetric
import (
"sort"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
@ -20,18 +21,20 @@ import (
// Must use NewHistogramDataPointSlice function to create new instances.
// Important: zero-initialized instance is not valid for use.
type HistogramDataPointSlice struct {
orig *[]*otlpmetrics.HistogramDataPoint
orig *[]*otlpmetrics.HistogramDataPoint
state *internal.State
}
func newHistogramDataPointSlice(orig *[]*otlpmetrics.HistogramDataPoint) HistogramDataPointSlice {
return HistogramDataPointSlice{orig}
func newHistogramDataPointSlice(orig *[]*otlpmetrics.HistogramDataPoint, state *internal.State) HistogramDataPointSlice {
return HistogramDataPointSlice{orig: orig, state: state}
}
// NewHistogramDataPointSlice creates a HistogramDataPointSlice with 0 elements.
// Can use "EnsureCapacity" to initialize with a given capacity.
func NewHistogramDataPointSlice() HistogramDataPointSlice {
orig := []*otlpmetrics.HistogramDataPoint(nil)
return newHistogramDataPointSlice(&orig)
state := internal.StateMutable
return newHistogramDataPointSlice(&orig, &state)
}
// Len returns the number of elements in the slice.
@ -50,7 +53,7 @@ func (es HistogramDataPointSlice) Len() int {
// ... // Do something with the element
// }
func (es HistogramDataPointSlice) At(i int) HistogramDataPoint {
return newHistogramDataPoint((*es.orig)[i])
return newHistogramDataPoint((*es.orig)[i], es.state)
}
// EnsureCapacity is an operation that ensures the slice has at least the specified capacity.
@ -66,6 +69,7 @@ func (es HistogramDataPointSlice) At(i int) HistogramDataPoint {
// // Here should set all the values for e.
// }
func (es HistogramDataPointSlice) EnsureCapacity(newCap int) {
es.state.AssertMutable()
oldCap := cap(*es.orig)
if newCap <= oldCap {
return
@ -79,6 +83,7 @@ func (es HistogramDataPointSlice) EnsureCapacity(newCap int) {
// AppendEmpty will append to the end of the slice an empty HistogramDataPoint.
// It returns the newly added HistogramDataPoint.
func (es HistogramDataPointSlice) AppendEmpty() HistogramDataPoint {
es.state.AssertMutable()
*es.orig = append(*es.orig, &otlpmetrics.HistogramDataPoint{})
return es.At(es.Len() - 1)
}
@ -86,6 +91,8 @@ func (es HistogramDataPointSlice) AppendEmpty() HistogramDataPoint {
// MoveAndAppendTo moves all elements from the current slice and appends them to the dest.
// The current slice will be cleared.
func (es HistogramDataPointSlice) MoveAndAppendTo(dest HistogramDataPointSlice) {
es.state.AssertMutable()
dest.state.AssertMutable()
if *dest.orig == nil {
// We can simply move the entire vector and avoid any allocations.
*dest.orig = *es.orig
@ -98,6 +105,7 @@ func (es HistogramDataPointSlice) MoveAndAppendTo(dest HistogramDataPointSlice)
// RemoveIf calls f sequentially for each element present in the slice.
// If f returns true, the element is removed from the slice.
func (es HistogramDataPointSlice) RemoveIf(f func(HistogramDataPoint) bool) {
es.state.AssertMutable()
newLen := 0
for i := 0; i < len(*es.orig); i++ {
if f(es.At(i)) {
@ -117,12 +125,13 @@ func (es HistogramDataPointSlice) RemoveIf(f func(HistogramDataPoint) bool) {
// CopyTo copies all elements from the current slice overriding the destination.
func (es HistogramDataPointSlice) CopyTo(dest HistogramDataPointSlice) {
dest.state.AssertMutable()
srcLen := es.Len()
destCap := cap(*dest.orig)
if srcLen <= destCap {
(*dest.orig) = (*dest.orig)[:srcLen:destCap]
for i := range *es.orig {
newHistogramDataPoint((*es.orig)[i]).CopyTo(newHistogramDataPoint((*dest.orig)[i]))
newHistogramDataPoint((*es.orig)[i], es.state).CopyTo(newHistogramDataPoint((*dest.orig)[i], dest.state))
}
return
}
@ -130,7 +139,7 @@ func (es HistogramDataPointSlice) CopyTo(dest HistogramDataPointSlice) {
wrappers := make([]*otlpmetrics.HistogramDataPoint, srcLen)
for i := range *es.orig {
wrappers[i] = &origs[i]
newHistogramDataPoint((*es.orig)[i]).CopyTo(newHistogramDataPoint(wrappers[i]))
newHistogramDataPoint((*es.orig)[i], es.state).CopyTo(newHistogramDataPoint(wrappers[i], dest.state))
}
*dest.orig = wrappers
}
@ -139,5 +148,6 @@ func (es HistogramDataPointSlice) CopyTo(dest HistogramDataPointSlice) {
// provided less function so that two instances of HistogramDataPointSlice
// can be compared.
func (es HistogramDataPointSlice) Sort(less func(a, b HistogramDataPoint) bool) {
es.state.AssertMutable()
sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) })
}

View File

@ -12,13 +12,15 @@ import (
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
func TestHistogramDataPointSlice(t *testing.T) {
es := NewHistogramDataPointSlice()
assert.Equal(t, 0, es.Len())
es = newHistogramDataPointSlice(&[]*otlpmetrics.HistogramDataPoint{})
state := internal.StateMutable
es = newHistogramDataPointSlice(&[]*otlpmetrics.HistogramDataPoint{}, &state)
assert.Equal(t, 0, es.Len())
emptyVal := NewHistogramDataPoint()
@ -32,6 +34,19 @@ func TestHistogramDataPointSlice(t *testing.T) {
assert.Equal(t, 7, es.Len())
}
func TestHistogramDataPointSliceReadOnly(t *testing.T) {
sharedState := internal.StateReadOnly
es := newHistogramDataPointSlice(&[]*otlpmetrics.HistogramDataPoint{}, &sharedState)
assert.Equal(t, 0, es.Len())
assert.Panics(t, func() { es.AppendEmpty() })
assert.Panics(t, func() { es.EnsureCapacity(2) })
es2 := NewHistogramDataPointSlice()
es.CopyTo(es2)
assert.Panics(t, func() { es2.CopyTo(es) })
assert.Panics(t, func() { es.MoveAndAppendTo(es2) })
assert.Panics(t, func() { es2.MoveAndAppendTo(es) })
}
func TestHistogramDataPointSlice_CopyTo(t *testing.T) {
dest := NewHistogramDataPointSlice()
// Test CopyTo to empty
@ -134,6 +149,6 @@ func fillTestHistogramDataPointSlice(es HistogramDataPointSlice) {
*es.orig = make([]*otlpmetrics.HistogramDataPoint, 7)
for i := 0; i < 7; i++ {
(*es.orig)[i] = &otlpmetrics.HistogramDataPoint{}
fillTestHistogramDataPoint(newHistogramDataPoint((*es.orig)[i]))
fillTestHistogramDataPoint(newHistogramDataPoint((*es.orig)[i], es.state))
}
}

View File

@ -7,6 +7,7 @@
package pmetric
import (
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
@ -19,11 +20,12 @@ import (
// Must use NewMetric function to create new instances.
// Important: zero-initialized instance is not valid for use.
type Metric struct {
orig *otlpmetrics.Metric
orig *otlpmetrics.Metric
state *internal.State
}
func newMetric(orig *otlpmetrics.Metric) Metric {
return Metric{orig}
func newMetric(orig *otlpmetrics.Metric, state *internal.State) Metric {
return Metric{orig: orig, state: state}
}
// NewMetric creates a new empty Metric.
@ -31,12 +33,15 @@ func newMetric(orig *otlpmetrics.Metric) Metric {
// This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice,
// OR directly access the member if this is embedded in another struct.
func NewMetric() Metric {
return newMetric(&otlpmetrics.Metric{})
state := internal.StateMutable
return newMetric(&otlpmetrics.Metric{}, &state)
}
// MoveTo moves all properties from the current struct overriding the destination and
// resetting the current instance to its zero value
func (ms Metric) MoveTo(dest Metric) {
ms.state.AssertMutable()
dest.state.AssertMutable()
*dest.orig = *ms.orig
*ms.orig = otlpmetrics.Metric{}
}
@ -48,6 +53,7 @@ func (ms Metric) Name() string {
// SetName replaces the name associated with this Metric.
func (ms Metric) SetName(v string) {
ms.state.AssertMutable()
ms.orig.Name = v
}
@ -58,6 +64,7 @@ func (ms Metric) Description() string {
// SetDescription replaces the description associated with this Metric.
func (ms Metric) SetDescription(v string) {
ms.state.AssertMutable()
ms.orig.Description = v
}
@ -68,6 +75,7 @@ func (ms Metric) Unit() string {
// SetUnit replaces the unit associated with this Metric.
func (ms Metric) SetUnit(v string) {
ms.state.AssertMutable()
ms.orig.Unit = v
}
@ -100,7 +108,7 @@ func (ms Metric) Gauge() Gauge {
if !ok {
return Gauge{}
}
return newGauge(v.Gauge)
return newGauge(v.Gauge, ms.state)
}
// SetEmptyGauge sets an empty gauge to this Metric.
@ -109,9 +117,10 @@ func (ms Metric) Gauge() Gauge {
//
// Calling this function on zero-initialized Metric will cause a panic.
func (ms Metric) SetEmptyGauge() Gauge {
ms.state.AssertMutable()
val := &otlpmetrics.Gauge{}
ms.orig.Data = &otlpmetrics.Metric_Gauge{Gauge: val}
return newGauge(val)
return newGauge(val, ms.state)
}
// Sum returns the sum associated with this Metric.
@ -125,7 +134,7 @@ func (ms Metric) Sum() Sum {
if !ok {
return Sum{}
}
return newSum(v.Sum)
return newSum(v.Sum, ms.state)
}
// SetEmptySum sets an empty sum to this Metric.
@ -134,9 +143,10 @@ func (ms Metric) Sum() Sum {
//
// Calling this function on zero-initialized Metric will cause a panic.
func (ms Metric) SetEmptySum() Sum {
ms.state.AssertMutable()
val := &otlpmetrics.Sum{}
ms.orig.Data = &otlpmetrics.Metric_Sum{Sum: val}
return newSum(val)
return newSum(val, ms.state)
}
// Histogram returns the histogram associated with this Metric.
@ -150,7 +160,7 @@ func (ms Metric) Histogram() Histogram {
if !ok {
return Histogram{}
}
return newHistogram(v.Histogram)
return newHistogram(v.Histogram, ms.state)
}
// SetEmptyHistogram sets an empty histogram to this Metric.
@ -159,9 +169,10 @@ func (ms Metric) Histogram() Histogram {
//
// Calling this function on zero-initialized Metric will cause a panic.
func (ms Metric) SetEmptyHistogram() Histogram {
ms.state.AssertMutable()
val := &otlpmetrics.Histogram{}
ms.orig.Data = &otlpmetrics.Metric_Histogram{Histogram: val}
return newHistogram(val)
return newHistogram(val, ms.state)
}
// ExponentialHistogram returns the exponentialhistogram associated with this Metric.
@ -175,7 +186,7 @@ func (ms Metric) ExponentialHistogram() ExponentialHistogram {
if !ok {
return ExponentialHistogram{}
}
return newExponentialHistogram(v.ExponentialHistogram)
return newExponentialHistogram(v.ExponentialHistogram, ms.state)
}
// SetEmptyExponentialHistogram sets an empty exponentialhistogram to this Metric.
@ -184,9 +195,10 @@ func (ms Metric) ExponentialHistogram() ExponentialHistogram {
//
// Calling this function on zero-initialized Metric will cause a panic.
func (ms Metric) SetEmptyExponentialHistogram() ExponentialHistogram {
ms.state.AssertMutable()
val := &otlpmetrics.ExponentialHistogram{}
ms.orig.Data = &otlpmetrics.Metric_ExponentialHistogram{ExponentialHistogram: val}
return newExponentialHistogram(val)
return newExponentialHistogram(val, ms.state)
}
// Summary returns the summary associated with this Metric.
@ -200,7 +212,7 @@ func (ms Metric) Summary() Summary {
if !ok {
return Summary{}
}
return newSummary(v.Summary)
return newSummary(v.Summary, ms.state)
}
// SetEmptySummary sets an empty summary to this Metric.
@ -209,13 +221,15 @@ func (ms Metric) Summary() Summary {
//
// Calling this function on zero-initialized Metric will cause a panic.
func (ms Metric) SetEmptySummary() Summary {
ms.state.AssertMutable()
val := &otlpmetrics.Summary{}
ms.orig.Data = &otlpmetrics.Metric_Summary{Summary: val}
return newSummary(val)
return newSummary(val, ms.state)
}
// CopyTo copies all properties from the current struct overriding the destination.
func (ms Metric) CopyTo(dest Metric) {
dest.state.AssertMutable()
dest.SetName(ms.Name())
dest.SetDescription(ms.Description())
dest.SetUnit(ms.Unit())

View File

@ -11,6 +11,7 @@ import (
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
@ -20,6 +21,9 @@ func TestMetric_MoveTo(t *testing.T) {
ms.MoveTo(dest)
assert.Equal(t, NewMetric(), ms)
assert.Equal(t, generateTestMetric(), dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.MoveTo(newMetric(&otlpmetrics.Metric{}, &sharedState)) })
assert.Panics(t, func() { newMetric(&otlpmetrics.Metric{}, &sharedState).MoveTo(dest) })
}
func TestMetric_CopyTo(t *testing.T) {
@ -30,6 +34,8 @@ func TestMetric_CopyTo(t *testing.T) {
orig = generateTestMetric()
orig.CopyTo(ms)
assert.Equal(t, orig, ms)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.CopyTo(newMetric(&otlpmetrics.Metric{}, &sharedState)) })
}
func TestMetric_Name(t *testing.T) {
@ -37,6 +43,8 @@ func TestMetric_Name(t *testing.T) {
assert.Equal(t, "", ms.Name())
ms.SetName("test_name")
assert.Equal(t, "test_name", ms.Name())
sharedState := internal.StateReadOnly
assert.Panics(t, func() { newMetric(&otlpmetrics.Metric{}, &sharedState).SetName("test_name") })
}
func TestMetric_Description(t *testing.T) {
@ -44,6 +52,8 @@ func TestMetric_Description(t *testing.T) {
assert.Equal(t, "", ms.Description())
ms.SetDescription("test_description")
assert.Equal(t, "test_description", ms.Description())
sharedState := internal.StateReadOnly
assert.Panics(t, func() { newMetric(&otlpmetrics.Metric{}, &sharedState).SetDescription("test_description") })
}
func TestMetric_Unit(t *testing.T) {
@ -51,6 +61,8 @@ func TestMetric_Unit(t *testing.T) {
assert.Equal(t, "", ms.Unit())
ms.SetUnit("1")
assert.Equal(t, "1", ms.Unit())
sharedState := internal.StateReadOnly
assert.Panics(t, func() { newMetric(&otlpmetrics.Metric{}, &sharedState).SetUnit("1") })
}
func TestMetric_Type(t *testing.T) {
@ -63,6 +75,8 @@ func TestMetric_Gauge(t *testing.T) {
fillTestGauge(ms.SetEmptyGauge())
assert.Equal(t, MetricTypeGauge, ms.Type())
assert.Equal(t, generateTestGauge(), ms.Gauge())
sharedState := internal.StateReadOnly
assert.Panics(t, func() { newMetric(&otlpmetrics.Metric{}, &sharedState).SetEmptyGauge() })
}
func TestMetric_CopyTo_Gauge(t *testing.T) {
@ -71,6 +85,8 @@ func TestMetric_CopyTo_Gauge(t *testing.T) {
dest := NewMetric()
ms.CopyTo(dest)
assert.Equal(t, ms, dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.CopyTo(newMetric(&otlpmetrics.Metric{}, &sharedState)) })
}
func TestMetric_Sum(t *testing.T) {
@ -78,6 +94,8 @@ func TestMetric_Sum(t *testing.T) {
fillTestSum(ms.SetEmptySum())
assert.Equal(t, MetricTypeSum, ms.Type())
assert.Equal(t, generateTestSum(), ms.Sum())
sharedState := internal.StateReadOnly
assert.Panics(t, func() { newMetric(&otlpmetrics.Metric{}, &sharedState).SetEmptySum() })
}
func TestMetric_CopyTo_Sum(t *testing.T) {
@ -86,6 +104,8 @@ func TestMetric_CopyTo_Sum(t *testing.T) {
dest := NewMetric()
ms.CopyTo(dest)
assert.Equal(t, ms, dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.CopyTo(newMetric(&otlpmetrics.Metric{}, &sharedState)) })
}
func TestMetric_Histogram(t *testing.T) {
@ -93,6 +113,8 @@ func TestMetric_Histogram(t *testing.T) {
fillTestHistogram(ms.SetEmptyHistogram())
assert.Equal(t, MetricTypeHistogram, ms.Type())
assert.Equal(t, generateTestHistogram(), ms.Histogram())
sharedState := internal.StateReadOnly
assert.Panics(t, func() { newMetric(&otlpmetrics.Metric{}, &sharedState).SetEmptyHistogram() })
}
func TestMetric_CopyTo_Histogram(t *testing.T) {
@ -101,6 +123,8 @@ func TestMetric_CopyTo_Histogram(t *testing.T) {
dest := NewMetric()
ms.CopyTo(dest)
assert.Equal(t, ms, dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.CopyTo(newMetric(&otlpmetrics.Metric{}, &sharedState)) })
}
func TestMetric_ExponentialHistogram(t *testing.T) {
@ -108,6 +132,8 @@ func TestMetric_ExponentialHistogram(t *testing.T) {
fillTestExponentialHistogram(ms.SetEmptyExponentialHistogram())
assert.Equal(t, MetricTypeExponentialHistogram, ms.Type())
assert.Equal(t, generateTestExponentialHistogram(), ms.ExponentialHistogram())
sharedState := internal.StateReadOnly
assert.Panics(t, func() { newMetric(&otlpmetrics.Metric{}, &sharedState).SetEmptyExponentialHistogram() })
}
func TestMetric_CopyTo_ExponentialHistogram(t *testing.T) {
@ -116,6 +142,8 @@ func TestMetric_CopyTo_ExponentialHistogram(t *testing.T) {
dest := NewMetric()
ms.CopyTo(dest)
assert.Equal(t, ms, dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.CopyTo(newMetric(&otlpmetrics.Metric{}, &sharedState)) })
}
func TestMetric_Summary(t *testing.T) {
@ -123,6 +151,8 @@ func TestMetric_Summary(t *testing.T) {
fillTestSummary(ms.SetEmptySummary())
assert.Equal(t, MetricTypeSummary, ms.Type())
assert.Equal(t, generateTestSummary(), ms.Summary())
sharedState := internal.StateReadOnly
assert.Panics(t, func() { newMetric(&otlpmetrics.Metric{}, &sharedState).SetEmptySummary() })
}
func TestMetric_CopyTo_Summary(t *testing.T) {
@ -131,6 +161,8 @@ func TestMetric_CopyTo_Summary(t *testing.T) {
dest := NewMetric()
ms.CopyTo(dest)
assert.Equal(t, ms, dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.CopyTo(newMetric(&otlpmetrics.Metric{}, &sharedState)) })
}
func generateTestMetric() Metric {
@ -144,5 +176,5 @@ func fillTestMetric(tv Metric) {
tv.orig.Description = "test_description"
tv.orig.Unit = "1"
tv.orig.Data = &otlpmetrics.Metric_Sum{Sum: &otlpmetrics.Sum{}}
fillTestSum(newSum(tv.orig.GetSum()))
fillTestSum(newSum(tv.orig.GetSum(), tv.state))
}

View File

@ -9,6 +9,7 @@ package pmetric
import (
"sort"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
@ -20,18 +21,20 @@ import (
// Must use NewMetricSlice function to create new instances.
// Important: zero-initialized instance is not valid for use.
type MetricSlice struct {
orig *[]*otlpmetrics.Metric
orig *[]*otlpmetrics.Metric
state *internal.State
}
func newMetricSlice(orig *[]*otlpmetrics.Metric) MetricSlice {
return MetricSlice{orig}
func newMetricSlice(orig *[]*otlpmetrics.Metric, state *internal.State) MetricSlice {
return MetricSlice{orig: orig, state: state}
}
// NewMetricSlice creates a MetricSlice with 0 elements.
// Can use "EnsureCapacity" to initialize with a given capacity.
func NewMetricSlice() MetricSlice {
orig := []*otlpmetrics.Metric(nil)
return newMetricSlice(&orig)
state := internal.StateMutable
return newMetricSlice(&orig, &state)
}
// Len returns the number of elements in the slice.
@ -50,7 +53,7 @@ func (es MetricSlice) Len() int {
// ... // Do something with the element
// }
func (es MetricSlice) At(i int) Metric {
return newMetric((*es.orig)[i])
return newMetric((*es.orig)[i], es.state)
}
// EnsureCapacity is an operation that ensures the slice has at least the specified capacity.
@ -66,6 +69,7 @@ func (es MetricSlice) At(i int) Metric {
// // Here should set all the values for e.
// }
func (es MetricSlice) EnsureCapacity(newCap int) {
es.state.AssertMutable()
oldCap := cap(*es.orig)
if newCap <= oldCap {
return
@ -79,6 +83,7 @@ func (es MetricSlice) EnsureCapacity(newCap int) {
// AppendEmpty will append to the end of the slice an empty Metric.
// It returns the newly added Metric.
func (es MetricSlice) AppendEmpty() Metric {
es.state.AssertMutable()
*es.orig = append(*es.orig, &otlpmetrics.Metric{})
return es.At(es.Len() - 1)
}
@ -86,6 +91,8 @@ func (es MetricSlice) AppendEmpty() Metric {
// MoveAndAppendTo moves all elements from the current slice and appends them to the dest.
// The current slice will be cleared.
func (es MetricSlice) MoveAndAppendTo(dest MetricSlice) {
es.state.AssertMutable()
dest.state.AssertMutable()
if *dest.orig == nil {
// We can simply move the entire vector and avoid any allocations.
*dest.orig = *es.orig
@ -98,6 +105,7 @@ func (es MetricSlice) MoveAndAppendTo(dest MetricSlice) {
// RemoveIf calls f sequentially for each element present in the slice.
// If f returns true, the element is removed from the slice.
func (es MetricSlice) RemoveIf(f func(Metric) bool) {
es.state.AssertMutable()
newLen := 0
for i := 0; i < len(*es.orig); i++ {
if f(es.At(i)) {
@ -117,12 +125,13 @@ func (es MetricSlice) RemoveIf(f func(Metric) bool) {
// CopyTo copies all elements from the current slice overriding the destination.
func (es MetricSlice) CopyTo(dest MetricSlice) {
dest.state.AssertMutable()
srcLen := es.Len()
destCap := cap(*dest.orig)
if srcLen <= destCap {
(*dest.orig) = (*dest.orig)[:srcLen:destCap]
for i := range *es.orig {
newMetric((*es.orig)[i]).CopyTo(newMetric((*dest.orig)[i]))
newMetric((*es.orig)[i], es.state).CopyTo(newMetric((*dest.orig)[i], dest.state))
}
return
}
@ -130,7 +139,7 @@ func (es MetricSlice) CopyTo(dest MetricSlice) {
wrappers := make([]*otlpmetrics.Metric, srcLen)
for i := range *es.orig {
wrappers[i] = &origs[i]
newMetric((*es.orig)[i]).CopyTo(newMetric(wrappers[i]))
newMetric((*es.orig)[i], es.state).CopyTo(newMetric(wrappers[i], dest.state))
}
*dest.orig = wrappers
}
@ -139,5 +148,6 @@ func (es MetricSlice) CopyTo(dest MetricSlice) {
// provided less function so that two instances of MetricSlice
// can be compared.
func (es MetricSlice) Sort(less func(a, b Metric) bool) {
es.state.AssertMutable()
sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) })
}

View File

@ -12,13 +12,15 @@ import (
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
func TestMetricSlice(t *testing.T) {
es := NewMetricSlice()
assert.Equal(t, 0, es.Len())
es = newMetricSlice(&[]*otlpmetrics.Metric{})
state := internal.StateMutable
es = newMetricSlice(&[]*otlpmetrics.Metric{}, &state)
assert.Equal(t, 0, es.Len())
emptyVal := NewMetric()
@ -32,6 +34,19 @@ func TestMetricSlice(t *testing.T) {
assert.Equal(t, 7, es.Len())
}
func TestMetricSliceReadOnly(t *testing.T) {
sharedState := internal.StateReadOnly
es := newMetricSlice(&[]*otlpmetrics.Metric{}, &sharedState)
assert.Equal(t, 0, es.Len())
assert.Panics(t, func() { es.AppendEmpty() })
assert.Panics(t, func() { es.EnsureCapacity(2) })
es2 := NewMetricSlice()
es.CopyTo(es2)
assert.Panics(t, func() { es2.CopyTo(es) })
assert.Panics(t, func() { es.MoveAndAppendTo(es2) })
assert.Panics(t, func() { es2.MoveAndAppendTo(es) })
}
func TestMetricSlice_CopyTo(t *testing.T) {
dest := NewMetricSlice()
// Test CopyTo to empty
@ -134,6 +149,6 @@ func fillTestMetricSlice(es MetricSlice) {
*es.orig = make([]*otlpmetrics.Metric, 7)
for i := 0; i < 7; i++ {
(*es.orig)[i] = &otlpmetrics.Metric{}
fillTestMetric(newMetric((*es.orig)[i]))
fillTestMetric(newMetric((*es.orig)[i], es.state))
}
}

View File

@ -20,11 +20,12 @@ import (
// Must use NewNumberDataPoint function to create new instances.
// Important: zero-initialized instance is not valid for use.
type NumberDataPoint struct {
orig *otlpmetrics.NumberDataPoint
orig *otlpmetrics.NumberDataPoint
state *internal.State
}
func newNumberDataPoint(orig *otlpmetrics.NumberDataPoint) NumberDataPoint {
return NumberDataPoint{orig}
func newNumberDataPoint(orig *otlpmetrics.NumberDataPoint, state *internal.State) NumberDataPoint {
return NumberDataPoint{orig: orig, state: state}
}
// NewNumberDataPoint creates a new empty NumberDataPoint.
@ -32,19 +33,22 @@ func newNumberDataPoint(orig *otlpmetrics.NumberDataPoint) NumberDataPoint {
// This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice,
// OR directly access the member if this is embedded in another struct.
func NewNumberDataPoint() NumberDataPoint {
return newNumberDataPoint(&otlpmetrics.NumberDataPoint{})
state := internal.StateMutable
return newNumberDataPoint(&otlpmetrics.NumberDataPoint{}, &state)
}
// MoveTo moves all properties from the current struct overriding the destination and
// resetting the current instance to its zero value
func (ms NumberDataPoint) MoveTo(dest NumberDataPoint) {
ms.state.AssertMutable()
dest.state.AssertMutable()
*dest.orig = *ms.orig
*ms.orig = otlpmetrics.NumberDataPoint{}
}
// Attributes returns the Attributes associated with this NumberDataPoint.
func (ms NumberDataPoint) Attributes() pcommon.Map {
return pcommon.Map(internal.NewMap(&ms.orig.Attributes))
return pcommon.Map(internal.NewMap(&ms.orig.Attributes, ms.state))
}
// StartTimestamp returns the starttimestamp associated with this NumberDataPoint.
@ -54,6 +58,7 @@ func (ms NumberDataPoint) StartTimestamp() pcommon.Timestamp {
// SetStartTimestamp replaces the starttimestamp associated with this NumberDataPoint.
func (ms NumberDataPoint) SetStartTimestamp(v pcommon.Timestamp) {
ms.state.AssertMutable()
ms.orig.StartTimeUnixNano = uint64(v)
}
@ -64,6 +69,7 @@ func (ms NumberDataPoint) Timestamp() pcommon.Timestamp {
// SetTimestamp replaces the timestamp associated with this NumberDataPoint.
func (ms NumberDataPoint) SetTimestamp(v pcommon.Timestamp) {
ms.state.AssertMutable()
ms.orig.TimeUnixNano = uint64(v)
}
@ -86,6 +92,7 @@ func (ms NumberDataPoint) DoubleValue() float64 {
// SetDoubleValue replaces the double associated with this NumberDataPoint.
func (ms NumberDataPoint) SetDoubleValue(v float64) {
ms.state.AssertMutable()
ms.orig.Value = &otlpmetrics.NumberDataPoint_AsDouble{
AsDouble: v,
}
@ -98,6 +105,7 @@ func (ms NumberDataPoint) IntValue() int64 {
// SetIntValue replaces the int associated with this NumberDataPoint.
func (ms NumberDataPoint) SetIntValue(v int64) {
ms.state.AssertMutable()
ms.orig.Value = &otlpmetrics.NumberDataPoint_AsInt{
AsInt: v,
}
@ -105,7 +113,7 @@ func (ms NumberDataPoint) SetIntValue(v int64) {
// Exemplars returns the Exemplars associated with this NumberDataPoint.
func (ms NumberDataPoint) Exemplars() ExemplarSlice {
return newExemplarSlice(&ms.orig.Exemplars)
return newExemplarSlice(&ms.orig.Exemplars, ms.state)
}
// Flags returns the flags associated with this NumberDataPoint.
@ -115,11 +123,13 @@ func (ms NumberDataPoint) Flags() DataPointFlags {
// SetFlags replaces the flags associated with this NumberDataPoint.
func (ms NumberDataPoint) SetFlags(v DataPointFlags) {
ms.state.AssertMutable()
ms.orig.Flags = uint32(v)
}
// CopyTo copies all properties from the current struct overriding the destination.
func (ms NumberDataPoint) CopyTo(dest NumberDataPoint) {
dest.state.AssertMutable()
ms.Attributes().CopyTo(dest.Attributes())
dest.SetStartTimestamp(ms.StartTimestamp())
dest.SetTimestamp(ms.Timestamp())

View File

@ -22,6 +22,9 @@ func TestNumberDataPoint_MoveTo(t *testing.T) {
ms.MoveTo(dest)
assert.Equal(t, NewNumberDataPoint(), ms)
assert.Equal(t, generateTestNumberDataPoint(), dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.MoveTo(newNumberDataPoint(&otlpmetrics.NumberDataPoint{}, &sharedState)) })
assert.Panics(t, func() { newNumberDataPoint(&otlpmetrics.NumberDataPoint{}, &sharedState).MoveTo(dest) })
}
func TestNumberDataPoint_CopyTo(t *testing.T) {
@ -32,6 +35,8 @@ func TestNumberDataPoint_CopyTo(t *testing.T) {
orig = generateTestNumberDataPoint()
orig.CopyTo(ms)
assert.Equal(t, orig, ms)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.CopyTo(newNumberDataPoint(&otlpmetrics.NumberDataPoint{}, &sharedState)) })
}
func TestNumberDataPoint_Attributes(t *testing.T) {
@ -68,6 +73,10 @@ func TestNumberDataPoint_DoubleValue(t *testing.T) {
ms.SetDoubleValue(float64(17.13))
assert.Equal(t, float64(17.13), ms.DoubleValue())
assert.Equal(t, NumberDataPointValueTypeDouble, ms.ValueType())
sharedState := internal.StateReadOnly
assert.Panics(t, func() {
newNumberDataPoint(&otlpmetrics.NumberDataPoint{}, &sharedState).SetDoubleValue(float64(17.13))
})
}
func TestNumberDataPoint_IntValue(t *testing.T) {
@ -76,6 +85,8 @@ func TestNumberDataPoint_IntValue(t *testing.T) {
ms.SetIntValue(int64(17))
assert.Equal(t, int64(17), ms.IntValue())
assert.Equal(t, NumberDataPointValueTypeInt, ms.ValueType())
sharedState := internal.StateReadOnly
assert.Panics(t, func() { newNumberDataPoint(&otlpmetrics.NumberDataPoint{}, &sharedState).SetIntValue(int64(17)) })
}
func TestNumberDataPoint_Exemplars(t *testing.T) {
@ -100,10 +111,10 @@ func generateTestNumberDataPoint() NumberDataPoint {
}
func fillTestNumberDataPoint(tv NumberDataPoint) {
internal.FillTestMap(internal.NewMap(&tv.orig.Attributes))
internal.FillTestMap(internal.NewMap(&tv.orig.Attributes, tv.state))
tv.orig.StartTimeUnixNano = 1234567890
tv.orig.TimeUnixNano = 1234567890
tv.orig.Value = &otlpmetrics.NumberDataPoint_AsDouble{AsDouble: float64(17.13)}
fillTestExemplarSlice(newExemplarSlice(&tv.orig.Exemplars))
fillTestExemplarSlice(newExemplarSlice(&tv.orig.Exemplars, tv.state))
tv.orig.Flags = 1
}

View File

@ -9,6 +9,7 @@ package pmetric
import (
"sort"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
@ -20,18 +21,20 @@ import (
// Must use NewNumberDataPointSlice function to create new instances.
// Important: zero-initialized instance is not valid for use.
type NumberDataPointSlice struct {
orig *[]*otlpmetrics.NumberDataPoint
orig *[]*otlpmetrics.NumberDataPoint
state *internal.State
}
func newNumberDataPointSlice(orig *[]*otlpmetrics.NumberDataPoint) NumberDataPointSlice {
return NumberDataPointSlice{orig}
func newNumberDataPointSlice(orig *[]*otlpmetrics.NumberDataPoint, state *internal.State) NumberDataPointSlice {
return NumberDataPointSlice{orig: orig, state: state}
}
// NewNumberDataPointSlice creates a NumberDataPointSlice with 0 elements.
// Can use "EnsureCapacity" to initialize with a given capacity.
func NewNumberDataPointSlice() NumberDataPointSlice {
orig := []*otlpmetrics.NumberDataPoint(nil)
return newNumberDataPointSlice(&orig)
state := internal.StateMutable
return newNumberDataPointSlice(&orig, &state)
}
// Len returns the number of elements in the slice.
@ -50,7 +53,7 @@ func (es NumberDataPointSlice) Len() int {
// ... // Do something with the element
// }
func (es NumberDataPointSlice) At(i int) NumberDataPoint {
return newNumberDataPoint((*es.orig)[i])
return newNumberDataPoint((*es.orig)[i], es.state)
}
// EnsureCapacity is an operation that ensures the slice has at least the specified capacity.
@ -66,6 +69,7 @@ func (es NumberDataPointSlice) At(i int) NumberDataPoint {
// // Here should set all the values for e.
// }
func (es NumberDataPointSlice) EnsureCapacity(newCap int) {
es.state.AssertMutable()
oldCap := cap(*es.orig)
if newCap <= oldCap {
return
@ -79,6 +83,7 @@ func (es NumberDataPointSlice) EnsureCapacity(newCap int) {
// AppendEmpty will append to the end of the slice an empty NumberDataPoint.
// It returns the newly added NumberDataPoint.
func (es NumberDataPointSlice) AppendEmpty() NumberDataPoint {
es.state.AssertMutable()
*es.orig = append(*es.orig, &otlpmetrics.NumberDataPoint{})
return es.At(es.Len() - 1)
}
@ -86,6 +91,8 @@ func (es NumberDataPointSlice) AppendEmpty() NumberDataPoint {
// MoveAndAppendTo moves all elements from the current slice and appends them to the dest.
// The current slice will be cleared.
func (es NumberDataPointSlice) MoveAndAppendTo(dest NumberDataPointSlice) {
es.state.AssertMutable()
dest.state.AssertMutable()
if *dest.orig == nil {
// We can simply move the entire vector and avoid any allocations.
*dest.orig = *es.orig
@ -98,6 +105,7 @@ func (es NumberDataPointSlice) MoveAndAppendTo(dest NumberDataPointSlice) {
// RemoveIf calls f sequentially for each element present in the slice.
// If f returns true, the element is removed from the slice.
func (es NumberDataPointSlice) RemoveIf(f func(NumberDataPoint) bool) {
es.state.AssertMutable()
newLen := 0
for i := 0; i < len(*es.orig); i++ {
if f(es.At(i)) {
@ -117,12 +125,13 @@ func (es NumberDataPointSlice) RemoveIf(f func(NumberDataPoint) bool) {
// CopyTo copies all elements from the current slice overriding the destination.
func (es NumberDataPointSlice) CopyTo(dest NumberDataPointSlice) {
dest.state.AssertMutable()
srcLen := es.Len()
destCap := cap(*dest.orig)
if srcLen <= destCap {
(*dest.orig) = (*dest.orig)[:srcLen:destCap]
for i := range *es.orig {
newNumberDataPoint((*es.orig)[i]).CopyTo(newNumberDataPoint((*dest.orig)[i]))
newNumberDataPoint((*es.orig)[i], es.state).CopyTo(newNumberDataPoint((*dest.orig)[i], dest.state))
}
return
}
@ -130,7 +139,7 @@ func (es NumberDataPointSlice) CopyTo(dest NumberDataPointSlice) {
wrappers := make([]*otlpmetrics.NumberDataPoint, srcLen)
for i := range *es.orig {
wrappers[i] = &origs[i]
newNumberDataPoint((*es.orig)[i]).CopyTo(newNumberDataPoint(wrappers[i]))
newNumberDataPoint((*es.orig)[i], es.state).CopyTo(newNumberDataPoint(wrappers[i], dest.state))
}
*dest.orig = wrappers
}
@ -139,5 +148,6 @@ func (es NumberDataPointSlice) CopyTo(dest NumberDataPointSlice) {
// provided less function so that two instances of NumberDataPointSlice
// can be compared.
func (es NumberDataPointSlice) Sort(less func(a, b NumberDataPoint) bool) {
es.state.AssertMutable()
sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) })
}

View File

@ -12,13 +12,15 @@ import (
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
func TestNumberDataPointSlice(t *testing.T) {
es := NewNumberDataPointSlice()
assert.Equal(t, 0, es.Len())
es = newNumberDataPointSlice(&[]*otlpmetrics.NumberDataPoint{})
state := internal.StateMutable
es = newNumberDataPointSlice(&[]*otlpmetrics.NumberDataPoint{}, &state)
assert.Equal(t, 0, es.Len())
emptyVal := NewNumberDataPoint()
@ -32,6 +34,19 @@ func TestNumberDataPointSlice(t *testing.T) {
assert.Equal(t, 7, es.Len())
}
func TestNumberDataPointSliceReadOnly(t *testing.T) {
sharedState := internal.StateReadOnly
es := newNumberDataPointSlice(&[]*otlpmetrics.NumberDataPoint{}, &sharedState)
assert.Equal(t, 0, es.Len())
assert.Panics(t, func() { es.AppendEmpty() })
assert.Panics(t, func() { es.EnsureCapacity(2) })
es2 := NewNumberDataPointSlice()
es.CopyTo(es2)
assert.Panics(t, func() { es2.CopyTo(es) })
assert.Panics(t, func() { es.MoveAndAppendTo(es2) })
assert.Panics(t, func() { es2.MoveAndAppendTo(es) })
}
func TestNumberDataPointSlice_CopyTo(t *testing.T) {
dest := NewNumberDataPointSlice()
// Test CopyTo to empty
@ -134,6 +149,6 @@ func fillTestNumberDataPointSlice(es NumberDataPointSlice) {
*es.orig = make([]*otlpmetrics.NumberDataPoint, 7)
for i := 0; i < 7; i++ {
(*es.orig)[i] = &otlpmetrics.NumberDataPoint{}
fillTestNumberDataPoint(newNumberDataPoint((*es.orig)[i]))
fillTestNumberDataPoint(newNumberDataPoint((*es.orig)[i], es.state))
}
}

View File

@ -20,11 +20,12 @@ import (
// Must use NewResourceMetrics function to create new instances.
// Important: zero-initialized instance is not valid for use.
type ResourceMetrics struct {
orig *otlpmetrics.ResourceMetrics
orig *otlpmetrics.ResourceMetrics
state *internal.State
}
func newResourceMetrics(orig *otlpmetrics.ResourceMetrics) ResourceMetrics {
return ResourceMetrics{orig}
func newResourceMetrics(orig *otlpmetrics.ResourceMetrics, state *internal.State) ResourceMetrics {
return ResourceMetrics{orig: orig, state: state}
}
// NewResourceMetrics creates a new empty ResourceMetrics.
@ -32,19 +33,22 @@ func newResourceMetrics(orig *otlpmetrics.ResourceMetrics) ResourceMetrics {
// This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice,
// OR directly access the member if this is embedded in another struct.
func NewResourceMetrics() ResourceMetrics {
return newResourceMetrics(&otlpmetrics.ResourceMetrics{})
state := internal.StateMutable
return newResourceMetrics(&otlpmetrics.ResourceMetrics{}, &state)
}
// MoveTo moves all properties from the current struct overriding the destination and
// resetting the current instance to its zero value
func (ms ResourceMetrics) MoveTo(dest ResourceMetrics) {
ms.state.AssertMutable()
dest.state.AssertMutable()
*dest.orig = *ms.orig
*ms.orig = otlpmetrics.ResourceMetrics{}
}
// Resource returns the resource associated with this ResourceMetrics.
func (ms ResourceMetrics) Resource() pcommon.Resource {
return pcommon.Resource(internal.NewResource(&ms.orig.Resource))
return pcommon.Resource(internal.NewResource(&ms.orig.Resource, ms.state))
}
// SchemaUrl returns the schemaurl associated with this ResourceMetrics.
@ -54,16 +58,18 @@ func (ms ResourceMetrics) SchemaUrl() string {
// SetSchemaUrl replaces the schemaurl associated with this ResourceMetrics.
func (ms ResourceMetrics) SetSchemaUrl(v string) {
ms.state.AssertMutable()
ms.orig.SchemaUrl = v
}
// ScopeMetrics returns the ScopeMetrics associated with this ResourceMetrics.
func (ms ResourceMetrics) ScopeMetrics() ScopeMetricsSlice {
return newScopeMetricsSlice(&ms.orig.ScopeMetrics)
return newScopeMetricsSlice(&ms.orig.ScopeMetrics, ms.state)
}
// CopyTo copies all properties from the current struct overriding the destination.
func (ms ResourceMetrics) CopyTo(dest ResourceMetrics) {
dest.state.AssertMutable()
ms.Resource().CopyTo(dest.Resource())
dest.SetSchemaUrl(ms.SchemaUrl())
ms.ScopeMetrics().CopyTo(dest.ScopeMetrics())

View File

@ -12,6 +12,7 @@ import (
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
"go.opentelemetry.io/collector/pdata/pcommon"
)
@ -21,6 +22,9 @@ func TestResourceMetrics_MoveTo(t *testing.T) {
ms.MoveTo(dest)
assert.Equal(t, NewResourceMetrics(), ms)
assert.Equal(t, generateTestResourceMetrics(), dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.MoveTo(newResourceMetrics(&otlpmetrics.ResourceMetrics{}, &sharedState)) })
assert.Panics(t, func() { newResourceMetrics(&otlpmetrics.ResourceMetrics{}, &sharedState).MoveTo(dest) })
}
func TestResourceMetrics_CopyTo(t *testing.T) {
@ -31,6 +35,8 @@ func TestResourceMetrics_CopyTo(t *testing.T) {
orig = generateTestResourceMetrics()
orig.CopyTo(ms)
assert.Equal(t, orig, ms)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.CopyTo(newResourceMetrics(&otlpmetrics.ResourceMetrics{}, &sharedState)) })
}
func TestResourceMetrics_Resource(t *testing.T) {
@ -44,6 +50,10 @@ func TestResourceMetrics_SchemaUrl(t *testing.T) {
assert.Equal(t, "", ms.SchemaUrl())
ms.SetSchemaUrl("https://opentelemetry.io/schemas/1.5.0")
assert.Equal(t, "https://opentelemetry.io/schemas/1.5.0", ms.SchemaUrl())
sharedState := internal.StateReadOnly
assert.Panics(t, func() {
newResourceMetrics(&otlpmetrics.ResourceMetrics{}, &sharedState).SetSchemaUrl("https://opentelemetry.io/schemas/1.5.0")
})
}
func TestResourceMetrics_ScopeMetrics(t *testing.T) {
@ -60,7 +70,7 @@ func generateTestResourceMetrics() ResourceMetrics {
}
func fillTestResourceMetrics(tv ResourceMetrics) {
internal.FillTestResource(internal.NewResource(&tv.orig.Resource))
internal.FillTestResource(internal.NewResource(&tv.orig.Resource, tv.state))
tv.orig.SchemaUrl = "https://opentelemetry.io/schemas/1.5.0"
fillTestScopeMetricsSlice(newScopeMetricsSlice(&tv.orig.ScopeMetrics))
fillTestScopeMetricsSlice(newScopeMetricsSlice(&tv.orig.ScopeMetrics, tv.state))
}

View File

@ -9,6 +9,7 @@ package pmetric
import (
"sort"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
@ -20,18 +21,20 @@ import (
// Must use NewResourceMetricsSlice function to create new instances.
// Important: zero-initialized instance is not valid for use.
type ResourceMetricsSlice struct {
orig *[]*otlpmetrics.ResourceMetrics
orig *[]*otlpmetrics.ResourceMetrics
state *internal.State
}
func newResourceMetricsSlice(orig *[]*otlpmetrics.ResourceMetrics) ResourceMetricsSlice {
return ResourceMetricsSlice{orig}
func newResourceMetricsSlice(orig *[]*otlpmetrics.ResourceMetrics, state *internal.State) ResourceMetricsSlice {
return ResourceMetricsSlice{orig: orig, state: state}
}
// NewResourceMetricsSlice creates a ResourceMetricsSlice with 0 elements.
// Can use "EnsureCapacity" to initialize with a given capacity.
func NewResourceMetricsSlice() ResourceMetricsSlice {
orig := []*otlpmetrics.ResourceMetrics(nil)
return newResourceMetricsSlice(&orig)
state := internal.StateMutable
return newResourceMetricsSlice(&orig, &state)
}
// Len returns the number of elements in the slice.
@ -50,7 +53,7 @@ func (es ResourceMetricsSlice) Len() int {
// ... // Do something with the element
// }
func (es ResourceMetricsSlice) At(i int) ResourceMetrics {
return newResourceMetrics((*es.orig)[i])
return newResourceMetrics((*es.orig)[i], es.state)
}
// EnsureCapacity is an operation that ensures the slice has at least the specified capacity.
@ -66,6 +69,7 @@ func (es ResourceMetricsSlice) At(i int) ResourceMetrics {
// // Here should set all the values for e.
// }
func (es ResourceMetricsSlice) EnsureCapacity(newCap int) {
es.state.AssertMutable()
oldCap := cap(*es.orig)
if newCap <= oldCap {
return
@ -79,6 +83,7 @@ func (es ResourceMetricsSlice) EnsureCapacity(newCap int) {
// AppendEmpty will append to the end of the slice an empty ResourceMetrics.
// It returns the newly added ResourceMetrics.
func (es ResourceMetricsSlice) AppendEmpty() ResourceMetrics {
es.state.AssertMutable()
*es.orig = append(*es.orig, &otlpmetrics.ResourceMetrics{})
return es.At(es.Len() - 1)
}
@ -86,6 +91,8 @@ func (es ResourceMetricsSlice) AppendEmpty() ResourceMetrics {
// MoveAndAppendTo moves all elements from the current slice and appends them to the dest.
// The current slice will be cleared.
func (es ResourceMetricsSlice) MoveAndAppendTo(dest ResourceMetricsSlice) {
es.state.AssertMutable()
dest.state.AssertMutable()
if *dest.orig == nil {
// We can simply move the entire vector and avoid any allocations.
*dest.orig = *es.orig
@ -98,6 +105,7 @@ func (es ResourceMetricsSlice) MoveAndAppendTo(dest ResourceMetricsSlice) {
// RemoveIf calls f sequentially for each element present in the slice.
// If f returns true, the element is removed from the slice.
func (es ResourceMetricsSlice) RemoveIf(f func(ResourceMetrics) bool) {
es.state.AssertMutable()
newLen := 0
for i := 0; i < len(*es.orig); i++ {
if f(es.At(i)) {
@ -117,12 +125,13 @@ func (es ResourceMetricsSlice) RemoveIf(f func(ResourceMetrics) bool) {
// CopyTo copies all elements from the current slice overriding the destination.
func (es ResourceMetricsSlice) CopyTo(dest ResourceMetricsSlice) {
dest.state.AssertMutable()
srcLen := es.Len()
destCap := cap(*dest.orig)
if srcLen <= destCap {
(*dest.orig) = (*dest.orig)[:srcLen:destCap]
for i := range *es.orig {
newResourceMetrics((*es.orig)[i]).CopyTo(newResourceMetrics((*dest.orig)[i]))
newResourceMetrics((*es.orig)[i], es.state).CopyTo(newResourceMetrics((*dest.orig)[i], dest.state))
}
return
}
@ -130,7 +139,7 @@ func (es ResourceMetricsSlice) CopyTo(dest ResourceMetricsSlice) {
wrappers := make([]*otlpmetrics.ResourceMetrics, srcLen)
for i := range *es.orig {
wrappers[i] = &origs[i]
newResourceMetrics((*es.orig)[i]).CopyTo(newResourceMetrics(wrappers[i]))
newResourceMetrics((*es.orig)[i], es.state).CopyTo(newResourceMetrics(wrappers[i], dest.state))
}
*dest.orig = wrappers
}
@ -139,5 +148,6 @@ func (es ResourceMetricsSlice) CopyTo(dest ResourceMetricsSlice) {
// provided less function so that two instances of ResourceMetricsSlice
// can be compared.
func (es ResourceMetricsSlice) Sort(less func(a, b ResourceMetrics) bool) {
es.state.AssertMutable()
sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) })
}

View File

@ -12,13 +12,15 @@ import (
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
func TestResourceMetricsSlice(t *testing.T) {
es := NewResourceMetricsSlice()
assert.Equal(t, 0, es.Len())
es = newResourceMetricsSlice(&[]*otlpmetrics.ResourceMetrics{})
state := internal.StateMutable
es = newResourceMetricsSlice(&[]*otlpmetrics.ResourceMetrics{}, &state)
assert.Equal(t, 0, es.Len())
emptyVal := NewResourceMetrics()
@ -32,6 +34,19 @@ func TestResourceMetricsSlice(t *testing.T) {
assert.Equal(t, 7, es.Len())
}
func TestResourceMetricsSliceReadOnly(t *testing.T) {
sharedState := internal.StateReadOnly
es := newResourceMetricsSlice(&[]*otlpmetrics.ResourceMetrics{}, &sharedState)
assert.Equal(t, 0, es.Len())
assert.Panics(t, func() { es.AppendEmpty() })
assert.Panics(t, func() { es.EnsureCapacity(2) })
es2 := NewResourceMetricsSlice()
es.CopyTo(es2)
assert.Panics(t, func() { es2.CopyTo(es) })
assert.Panics(t, func() { es.MoveAndAppendTo(es2) })
assert.Panics(t, func() { es2.MoveAndAppendTo(es) })
}
func TestResourceMetricsSlice_CopyTo(t *testing.T) {
dest := NewResourceMetricsSlice()
// Test CopyTo to empty
@ -134,6 +149,6 @@ func fillTestResourceMetricsSlice(es ResourceMetricsSlice) {
*es.orig = make([]*otlpmetrics.ResourceMetrics, 7)
for i := 0; i < 7; i++ {
(*es.orig)[i] = &otlpmetrics.ResourceMetrics{}
fillTestResourceMetrics(newResourceMetrics((*es.orig)[i]))
fillTestResourceMetrics(newResourceMetrics((*es.orig)[i], es.state))
}
}

View File

@ -20,11 +20,12 @@ import (
// Must use NewScopeMetrics function to create new instances.
// Important: zero-initialized instance is not valid for use.
type ScopeMetrics struct {
orig *otlpmetrics.ScopeMetrics
orig *otlpmetrics.ScopeMetrics
state *internal.State
}
func newScopeMetrics(orig *otlpmetrics.ScopeMetrics) ScopeMetrics {
return ScopeMetrics{orig}
func newScopeMetrics(orig *otlpmetrics.ScopeMetrics, state *internal.State) ScopeMetrics {
return ScopeMetrics{orig: orig, state: state}
}
// NewScopeMetrics creates a new empty ScopeMetrics.
@ -32,19 +33,22 @@ func newScopeMetrics(orig *otlpmetrics.ScopeMetrics) ScopeMetrics {
// This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice,
// OR directly access the member if this is embedded in another struct.
func NewScopeMetrics() ScopeMetrics {
return newScopeMetrics(&otlpmetrics.ScopeMetrics{})
state := internal.StateMutable
return newScopeMetrics(&otlpmetrics.ScopeMetrics{}, &state)
}
// MoveTo moves all properties from the current struct overriding the destination and
// resetting the current instance to its zero value
func (ms ScopeMetrics) MoveTo(dest ScopeMetrics) {
ms.state.AssertMutable()
dest.state.AssertMutable()
*dest.orig = *ms.orig
*ms.orig = otlpmetrics.ScopeMetrics{}
}
// Scope returns the scope associated with this ScopeMetrics.
func (ms ScopeMetrics) Scope() pcommon.InstrumentationScope {
return pcommon.InstrumentationScope(internal.NewInstrumentationScope(&ms.orig.Scope))
return pcommon.InstrumentationScope(internal.NewInstrumentationScope(&ms.orig.Scope, ms.state))
}
// SchemaUrl returns the schemaurl associated with this ScopeMetrics.
@ -54,16 +58,18 @@ func (ms ScopeMetrics) SchemaUrl() string {
// SetSchemaUrl replaces the schemaurl associated with this ScopeMetrics.
func (ms ScopeMetrics) SetSchemaUrl(v string) {
ms.state.AssertMutable()
ms.orig.SchemaUrl = v
}
// Metrics returns the Metrics associated with this ScopeMetrics.
func (ms ScopeMetrics) Metrics() MetricSlice {
return newMetricSlice(&ms.orig.Metrics)
return newMetricSlice(&ms.orig.Metrics, ms.state)
}
// CopyTo copies all properties from the current struct overriding the destination.
func (ms ScopeMetrics) CopyTo(dest ScopeMetrics) {
dest.state.AssertMutable()
ms.Scope().CopyTo(dest.Scope())
dest.SetSchemaUrl(ms.SchemaUrl())
ms.Metrics().CopyTo(dest.Metrics())

View File

@ -12,6 +12,7 @@ import (
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
"go.opentelemetry.io/collector/pdata/pcommon"
)
@ -21,6 +22,9 @@ func TestScopeMetrics_MoveTo(t *testing.T) {
ms.MoveTo(dest)
assert.Equal(t, NewScopeMetrics(), ms)
assert.Equal(t, generateTestScopeMetrics(), dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.MoveTo(newScopeMetrics(&otlpmetrics.ScopeMetrics{}, &sharedState)) })
assert.Panics(t, func() { newScopeMetrics(&otlpmetrics.ScopeMetrics{}, &sharedState).MoveTo(dest) })
}
func TestScopeMetrics_CopyTo(t *testing.T) {
@ -31,6 +35,8 @@ func TestScopeMetrics_CopyTo(t *testing.T) {
orig = generateTestScopeMetrics()
orig.CopyTo(ms)
assert.Equal(t, orig, ms)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.CopyTo(newScopeMetrics(&otlpmetrics.ScopeMetrics{}, &sharedState)) })
}
func TestScopeMetrics_Scope(t *testing.T) {
@ -44,6 +50,10 @@ func TestScopeMetrics_SchemaUrl(t *testing.T) {
assert.Equal(t, "", ms.SchemaUrl())
ms.SetSchemaUrl("https://opentelemetry.io/schemas/1.5.0")
assert.Equal(t, "https://opentelemetry.io/schemas/1.5.0", ms.SchemaUrl())
sharedState := internal.StateReadOnly
assert.Panics(t, func() {
newScopeMetrics(&otlpmetrics.ScopeMetrics{}, &sharedState).SetSchemaUrl("https://opentelemetry.io/schemas/1.5.0")
})
}
func TestScopeMetrics_Metrics(t *testing.T) {
@ -60,7 +70,7 @@ func generateTestScopeMetrics() ScopeMetrics {
}
func fillTestScopeMetrics(tv ScopeMetrics) {
internal.FillTestInstrumentationScope(internal.NewInstrumentationScope(&tv.orig.Scope))
internal.FillTestInstrumentationScope(internal.NewInstrumentationScope(&tv.orig.Scope, tv.state))
tv.orig.SchemaUrl = "https://opentelemetry.io/schemas/1.5.0"
fillTestMetricSlice(newMetricSlice(&tv.orig.Metrics))
fillTestMetricSlice(newMetricSlice(&tv.orig.Metrics, tv.state))
}

View File

@ -9,6 +9,7 @@ package pmetric
import (
"sort"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
@ -20,18 +21,20 @@ import (
// Must use NewScopeMetricsSlice function to create new instances.
// Important: zero-initialized instance is not valid for use.
type ScopeMetricsSlice struct {
orig *[]*otlpmetrics.ScopeMetrics
orig *[]*otlpmetrics.ScopeMetrics
state *internal.State
}
func newScopeMetricsSlice(orig *[]*otlpmetrics.ScopeMetrics) ScopeMetricsSlice {
return ScopeMetricsSlice{orig}
func newScopeMetricsSlice(orig *[]*otlpmetrics.ScopeMetrics, state *internal.State) ScopeMetricsSlice {
return ScopeMetricsSlice{orig: orig, state: state}
}
// NewScopeMetricsSlice creates a ScopeMetricsSlice with 0 elements.
// Can use "EnsureCapacity" to initialize with a given capacity.
func NewScopeMetricsSlice() ScopeMetricsSlice {
orig := []*otlpmetrics.ScopeMetrics(nil)
return newScopeMetricsSlice(&orig)
state := internal.StateMutable
return newScopeMetricsSlice(&orig, &state)
}
// Len returns the number of elements in the slice.
@ -50,7 +53,7 @@ func (es ScopeMetricsSlice) Len() int {
// ... // Do something with the element
// }
func (es ScopeMetricsSlice) At(i int) ScopeMetrics {
return newScopeMetrics((*es.orig)[i])
return newScopeMetrics((*es.orig)[i], es.state)
}
// EnsureCapacity is an operation that ensures the slice has at least the specified capacity.
@ -66,6 +69,7 @@ func (es ScopeMetricsSlice) At(i int) ScopeMetrics {
// // Here should set all the values for e.
// }
func (es ScopeMetricsSlice) EnsureCapacity(newCap int) {
es.state.AssertMutable()
oldCap := cap(*es.orig)
if newCap <= oldCap {
return
@ -79,6 +83,7 @@ func (es ScopeMetricsSlice) EnsureCapacity(newCap int) {
// AppendEmpty will append to the end of the slice an empty ScopeMetrics.
// It returns the newly added ScopeMetrics.
func (es ScopeMetricsSlice) AppendEmpty() ScopeMetrics {
es.state.AssertMutable()
*es.orig = append(*es.orig, &otlpmetrics.ScopeMetrics{})
return es.At(es.Len() - 1)
}
@ -86,6 +91,8 @@ func (es ScopeMetricsSlice) AppendEmpty() ScopeMetrics {
// MoveAndAppendTo moves all elements from the current slice and appends them to the dest.
// The current slice will be cleared.
func (es ScopeMetricsSlice) MoveAndAppendTo(dest ScopeMetricsSlice) {
es.state.AssertMutable()
dest.state.AssertMutable()
if *dest.orig == nil {
// We can simply move the entire vector and avoid any allocations.
*dest.orig = *es.orig
@ -98,6 +105,7 @@ func (es ScopeMetricsSlice) MoveAndAppendTo(dest ScopeMetricsSlice) {
// RemoveIf calls f sequentially for each element present in the slice.
// If f returns true, the element is removed from the slice.
func (es ScopeMetricsSlice) RemoveIf(f func(ScopeMetrics) bool) {
es.state.AssertMutable()
newLen := 0
for i := 0; i < len(*es.orig); i++ {
if f(es.At(i)) {
@ -117,12 +125,13 @@ func (es ScopeMetricsSlice) RemoveIf(f func(ScopeMetrics) bool) {
// CopyTo copies all elements from the current slice overriding the destination.
func (es ScopeMetricsSlice) CopyTo(dest ScopeMetricsSlice) {
dest.state.AssertMutable()
srcLen := es.Len()
destCap := cap(*dest.orig)
if srcLen <= destCap {
(*dest.orig) = (*dest.orig)[:srcLen:destCap]
for i := range *es.orig {
newScopeMetrics((*es.orig)[i]).CopyTo(newScopeMetrics((*dest.orig)[i]))
newScopeMetrics((*es.orig)[i], es.state).CopyTo(newScopeMetrics((*dest.orig)[i], dest.state))
}
return
}
@ -130,7 +139,7 @@ func (es ScopeMetricsSlice) CopyTo(dest ScopeMetricsSlice) {
wrappers := make([]*otlpmetrics.ScopeMetrics, srcLen)
for i := range *es.orig {
wrappers[i] = &origs[i]
newScopeMetrics((*es.orig)[i]).CopyTo(newScopeMetrics(wrappers[i]))
newScopeMetrics((*es.orig)[i], es.state).CopyTo(newScopeMetrics(wrappers[i], dest.state))
}
*dest.orig = wrappers
}
@ -139,5 +148,6 @@ func (es ScopeMetricsSlice) CopyTo(dest ScopeMetricsSlice) {
// provided less function so that two instances of ScopeMetricsSlice
// can be compared.
func (es ScopeMetricsSlice) Sort(less func(a, b ScopeMetrics) bool) {
es.state.AssertMutable()
sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) })
}

View File

@ -12,13 +12,15 @@ import (
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
func TestScopeMetricsSlice(t *testing.T) {
es := NewScopeMetricsSlice()
assert.Equal(t, 0, es.Len())
es = newScopeMetricsSlice(&[]*otlpmetrics.ScopeMetrics{})
state := internal.StateMutable
es = newScopeMetricsSlice(&[]*otlpmetrics.ScopeMetrics{}, &state)
assert.Equal(t, 0, es.Len())
emptyVal := NewScopeMetrics()
@ -32,6 +34,19 @@ func TestScopeMetricsSlice(t *testing.T) {
assert.Equal(t, 7, es.Len())
}
func TestScopeMetricsSliceReadOnly(t *testing.T) {
sharedState := internal.StateReadOnly
es := newScopeMetricsSlice(&[]*otlpmetrics.ScopeMetrics{}, &sharedState)
assert.Equal(t, 0, es.Len())
assert.Panics(t, func() { es.AppendEmpty() })
assert.Panics(t, func() { es.EnsureCapacity(2) })
es2 := NewScopeMetricsSlice()
es.CopyTo(es2)
assert.Panics(t, func() { es2.CopyTo(es) })
assert.Panics(t, func() { es.MoveAndAppendTo(es2) })
assert.Panics(t, func() { es2.MoveAndAppendTo(es) })
}
func TestScopeMetricsSlice_CopyTo(t *testing.T) {
dest := NewScopeMetricsSlice()
// Test CopyTo to empty
@ -134,6 +149,6 @@ func fillTestScopeMetricsSlice(es ScopeMetricsSlice) {
*es.orig = make([]*otlpmetrics.ScopeMetrics, 7)
for i := 0; i < 7; i++ {
(*es.orig)[i] = &otlpmetrics.ScopeMetrics{}
fillTestScopeMetrics(newScopeMetrics((*es.orig)[i]))
fillTestScopeMetrics(newScopeMetrics((*es.orig)[i], es.state))
}
}

View File

@ -7,6 +7,7 @@
package pmetric
import (
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
@ -18,11 +19,12 @@ import (
// Must use NewSum function to create new instances.
// Important: zero-initialized instance is not valid for use.
type Sum struct {
orig *otlpmetrics.Sum
orig *otlpmetrics.Sum
state *internal.State
}
func newSum(orig *otlpmetrics.Sum) Sum {
return Sum{orig}
func newSum(orig *otlpmetrics.Sum, state *internal.State) Sum {
return Sum{orig: orig, state: state}
}
// NewSum creates a new empty Sum.
@ -30,12 +32,15 @@ func newSum(orig *otlpmetrics.Sum) Sum {
// This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice,
// OR directly access the member if this is embedded in another struct.
func NewSum() Sum {
return newSum(&otlpmetrics.Sum{})
state := internal.StateMutable
return newSum(&otlpmetrics.Sum{}, &state)
}
// MoveTo moves all properties from the current struct overriding the destination and
// resetting the current instance to its zero value
func (ms Sum) MoveTo(dest Sum) {
ms.state.AssertMutable()
dest.state.AssertMutable()
*dest.orig = *ms.orig
*ms.orig = otlpmetrics.Sum{}
}
@ -47,6 +52,7 @@ func (ms Sum) AggregationTemporality() AggregationTemporality {
// SetAggregationTemporality replaces the aggregationtemporality associated with this Sum.
func (ms Sum) SetAggregationTemporality(v AggregationTemporality) {
ms.state.AssertMutable()
ms.orig.AggregationTemporality = otlpmetrics.AggregationTemporality(v)
}
@ -57,16 +63,18 @@ func (ms Sum) IsMonotonic() bool {
// SetIsMonotonic replaces the ismonotonic associated with this Sum.
func (ms Sum) SetIsMonotonic(v bool) {
ms.state.AssertMutable()
ms.orig.IsMonotonic = v
}
// DataPoints returns the DataPoints associated with this Sum.
func (ms Sum) DataPoints() NumberDataPointSlice {
return newNumberDataPointSlice(&ms.orig.DataPoints)
return newNumberDataPointSlice(&ms.orig.DataPoints, ms.state)
}
// CopyTo copies all properties from the current struct overriding the destination.
func (ms Sum) CopyTo(dest Sum) {
dest.state.AssertMutable()
dest.SetAggregationTemporality(ms.AggregationTemporality())
dest.SetIsMonotonic(ms.IsMonotonic())
ms.DataPoints().CopyTo(dest.DataPoints())

View File

@ -11,6 +11,7 @@ import (
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
@ -20,6 +21,9 @@ func TestSum_MoveTo(t *testing.T) {
ms.MoveTo(dest)
assert.Equal(t, NewSum(), ms)
assert.Equal(t, generateTestSum(), dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.MoveTo(newSum(&otlpmetrics.Sum{}, &sharedState)) })
assert.Panics(t, func() { newSum(&otlpmetrics.Sum{}, &sharedState).MoveTo(dest) })
}
func TestSum_CopyTo(t *testing.T) {
@ -30,6 +34,8 @@ func TestSum_CopyTo(t *testing.T) {
orig = generateTestSum()
orig.CopyTo(ms)
assert.Equal(t, orig, ms)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.CopyTo(newSum(&otlpmetrics.Sum{}, &sharedState)) })
}
func TestSum_AggregationTemporality(t *testing.T) {
@ -45,6 +51,8 @@ func TestSum_IsMonotonic(t *testing.T) {
assert.Equal(t, false, ms.IsMonotonic())
ms.SetIsMonotonic(true)
assert.Equal(t, true, ms.IsMonotonic())
sharedState := internal.StateReadOnly
assert.Panics(t, func() { newSum(&otlpmetrics.Sum{}, &sharedState).SetIsMonotonic(true) })
}
func TestSum_DataPoints(t *testing.T) {
@ -63,5 +71,5 @@ func generateTestSum() Sum {
func fillTestSum(tv Sum) {
tv.orig.AggregationTemporality = otlpmetrics.AggregationTemporality(1)
tv.orig.IsMonotonic = true
fillTestNumberDataPointSlice(newNumberDataPointSlice(&tv.orig.DataPoints))
fillTestNumberDataPointSlice(newNumberDataPointSlice(&tv.orig.DataPoints, tv.state))
}

View File

@ -7,6 +7,7 @@
package pmetric
import (
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
@ -18,11 +19,12 @@ import (
// Must use NewSummary function to create new instances.
// Important: zero-initialized instance is not valid for use.
type Summary struct {
orig *otlpmetrics.Summary
orig *otlpmetrics.Summary
state *internal.State
}
func newSummary(orig *otlpmetrics.Summary) Summary {
return Summary{orig}
func newSummary(orig *otlpmetrics.Summary, state *internal.State) Summary {
return Summary{orig: orig, state: state}
}
// NewSummary creates a new empty Summary.
@ -30,22 +32,26 @@ func newSummary(orig *otlpmetrics.Summary) Summary {
// This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice,
// OR directly access the member if this is embedded in another struct.
func NewSummary() Summary {
return newSummary(&otlpmetrics.Summary{})
state := internal.StateMutable
return newSummary(&otlpmetrics.Summary{}, &state)
}
// MoveTo moves all properties from the current struct overriding the destination and
// resetting the current instance to its zero value
func (ms Summary) MoveTo(dest Summary) {
ms.state.AssertMutable()
dest.state.AssertMutable()
*dest.orig = *ms.orig
*ms.orig = otlpmetrics.Summary{}
}
// DataPoints returns the DataPoints associated with this Summary.
func (ms Summary) DataPoints() SummaryDataPointSlice {
return newSummaryDataPointSlice(&ms.orig.DataPoints)
return newSummaryDataPointSlice(&ms.orig.DataPoints, ms.state)
}
// CopyTo copies all properties from the current struct overriding the destination.
func (ms Summary) CopyTo(dest Summary) {
dest.state.AssertMutable()
ms.DataPoints().CopyTo(dest.DataPoints())
}

View File

@ -10,6 +10,9 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
func TestSummary_MoveTo(t *testing.T) {
@ -18,6 +21,9 @@ func TestSummary_MoveTo(t *testing.T) {
ms.MoveTo(dest)
assert.Equal(t, NewSummary(), ms)
assert.Equal(t, generateTestSummary(), dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.MoveTo(newSummary(&otlpmetrics.Summary{}, &sharedState)) })
assert.Panics(t, func() { newSummary(&otlpmetrics.Summary{}, &sharedState).MoveTo(dest) })
}
func TestSummary_CopyTo(t *testing.T) {
@ -28,6 +34,8 @@ func TestSummary_CopyTo(t *testing.T) {
orig = generateTestSummary()
orig.CopyTo(ms)
assert.Equal(t, orig, ms)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.CopyTo(newSummary(&otlpmetrics.Summary{}, &sharedState)) })
}
func TestSummary_DataPoints(t *testing.T) {
@ -44,5 +52,5 @@ func generateTestSummary() Summary {
}
func fillTestSummary(tv Summary) {
fillTestSummaryDataPointSlice(newSummaryDataPointSlice(&tv.orig.DataPoints))
fillTestSummaryDataPointSlice(newSummaryDataPointSlice(&tv.orig.DataPoints, tv.state))
}

View File

@ -20,11 +20,12 @@ import (
// Must use NewSummaryDataPoint function to create new instances.
// Important: zero-initialized instance is not valid for use.
type SummaryDataPoint struct {
orig *otlpmetrics.SummaryDataPoint
orig *otlpmetrics.SummaryDataPoint
state *internal.State
}
func newSummaryDataPoint(orig *otlpmetrics.SummaryDataPoint) SummaryDataPoint {
return SummaryDataPoint{orig}
func newSummaryDataPoint(orig *otlpmetrics.SummaryDataPoint, state *internal.State) SummaryDataPoint {
return SummaryDataPoint{orig: orig, state: state}
}
// NewSummaryDataPoint creates a new empty SummaryDataPoint.
@ -32,19 +33,22 @@ func newSummaryDataPoint(orig *otlpmetrics.SummaryDataPoint) SummaryDataPoint {
// This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice,
// OR directly access the member if this is embedded in another struct.
func NewSummaryDataPoint() SummaryDataPoint {
return newSummaryDataPoint(&otlpmetrics.SummaryDataPoint{})
state := internal.StateMutable
return newSummaryDataPoint(&otlpmetrics.SummaryDataPoint{}, &state)
}
// MoveTo moves all properties from the current struct overriding the destination and
// resetting the current instance to its zero value
func (ms SummaryDataPoint) MoveTo(dest SummaryDataPoint) {
ms.state.AssertMutable()
dest.state.AssertMutable()
*dest.orig = *ms.orig
*ms.orig = otlpmetrics.SummaryDataPoint{}
}
// Attributes returns the Attributes associated with this SummaryDataPoint.
func (ms SummaryDataPoint) Attributes() pcommon.Map {
return pcommon.Map(internal.NewMap(&ms.orig.Attributes))
return pcommon.Map(internal.NewMap(&ms.orig.Attributes, ms.state))
}
// StartTimestamp returns the starttimestamp associated with this SummaryDataPoint.
@ -54,6 +58,7 @@ func (ms SummaryDataPoint) StartTimestamp() pcommon.Timestamp {
// SetStartTimestamp replaces the starttimestamp associated with this SummaryDataPoint.
func (ms SummaryDataPoint) SetStartTimestamp(v pcommon.Timestamp) {
ms.state.AssertMutable()
ms.orig.StartTimeUnixNano = uint64(v)
}
@ -64,6 +69,7 @@ func (ms SummaryDataPoint) Timestamp() pcommon.Timestamp {
// SetTimestamp replaces the timestamp associated with this SummaryDataPoint.
func (ms SummaryDataPoint) SetTimestamp(v pcommon.Timestamp) {
ms.state.AssertMutable()
ms.orig.TimeUnixNano = uint64(v)
}
@ -74,6 +80,7 @@ func (ms SummaryDataPoint) Count() uint64 {
// SetCount replaces the count associated with this SummaryDataPoint.
func (ms SummaryDataPoint) SetCount(v uint64) {
ms.state.AssertMutable()
ms.orig.Count = v
}
@ -84,12 +91,13 @@ func (ms SummaryDataPoint) Sum() float64 {
// SetSum replaces the sum associated with this SummaryDataPoint.
func (ms SummaryDataPoint) SetSum(v float64) {
ms.state.AssertMutable()
ms.orig.Sum = v
}
// QuantileValues returns the QuantileValues associated with this SummaryDataPoint.
func (ms SummaryDataPoint) QuantileValues() SummaryDataPointValueAtQuantileSlice {
return newSummaryDataPointValueAtQuantileSlice(&ms.orig.QuantileValues)
return newSummaryDataPointValueAtQuantileSlice(&ms.orig.QuantileValues, ms.state)
}
// Flags returns the flags associated with this SummaryDataPoint.
@ -99,11 +107,13 @@ func (ms SummaryDataPoint) Flags() DataPointFlags {
// SetFlags replaces the flags associated with this SummaryDataPoint.
func (ms SummaryDataPoint) SetFlags(v DataPointFlags) {
ms.state.AssertMutable()
ms.orig.Flags = uint32(v)
}
// CopyTo copies all properties from the current struct overriding the destination.
func (ms SummaryDataPoint) CopyTo(dest SummaryDataPoint) {
dest.state.AssertMutable()
ms.Attributes().CopyTo(dest.Attributes())
dest.SetStartTimestamp(ms.StartTimestamp())
dest.SetTimestamp(ms.Timestamp())

View File

@ -12,6 +12,7 @@ import (
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
"go.opentelemetry.io/collector/pdata/pcommon"
)
@ -21,6 +22,9 @@ func TestSummaryDataPoint_MoveTo(t *testing.T) {
ms.MoveTo(dest)
assert.Equal(t, NewSummaryDataPoint(), ms)
assert.Equal(t, generateTestSummaryDataPoint(), dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.MoveTo(newSummaryDataPoint(&otlpmetrics.SummaryDataPoint{}, &sharedState)) })
assert.Panics(t, func() { newSummaryDataPoint(&otlpmetrics.SummaryDataPoint{}, &sharedState).MoveTo(dest) })
}
func TestSummaryDataPoint_CopyTo(t *testing.T) {
@ -31,6 +35,8 @@ func TestSummaryDataPoint_CopyTo(t *testing.T) {
orig = generateTestSummaryDataPoint()
orig.CopyTo(ms)
assert.Equal(t, orig, ms)
sharedState := internal.StateReadOnly
assert.Panics(t, func() { ms.CopyTo(newSummaryDataPoint(&otlpmetrics.SummaryDataPoint{}, &sharedState)) })
}
func TestSummaryDataPoint_Attributes(t *testing.T) {
@ -61,6 +67,8 @@ func TestSummaryDataPoint_Count(t *testing.T) {
assert.Equal(t, uint64(0), ms.Count())
ms.SetCount(uint64(17))
assert.Equal(t, uint64(17), ms.Count())
sharedState := internal.StateReadOnly
assert.Panics(t, func() { newSummaryDataPoint(&otlpmetrics.SummaryDataPoint{}, &sharedState).SetCount(uint64(17)) })
}
func TestSummaryDataPoint_Sum(t *testing.T) {
@ -68,6 +76,8 @@ func TestSummaryDataPoint_Sum(t *testing.T) {
assert.Equal(t, float64(0.0), ms.Sum())
ms.SetSum(float64(17.13))
assert.Equal(t, float64(17.13), ms.Sum())
sharedState := internal.StateReadOnly
assert.Panics(t, func() { newSummaryDataPoint(&otlpmetrics.SummaryDataPoint{}, &sharedState).SetSum(float64(17.13)) })
}
func TestSummaryDataPoint_QuantileValues(t *testing.T) {
@ -92,11 +102,11 @@ func generateTestSummaryDataPoint() SummaryDataPoint {
}
func fillTestSummaryDataPoint(tv SummaryDataPoint) {
internal.FillTestMap(internal.NewMap(&tv.orig.Attributes))
internal.FillTestMap(internal.NewMap(&tv.orig.Attributes, tv.state))
tv.orig.StartTimeUnixNano = 1234567890
tv.orig.TimeUnixNano = 1234567890
tv.orig.Count = uint64(17)
tv.orig.Sum = float64(17.13)
fillTestSummaryDataPointValueAtQuantileSlice(newSummaryDataPointValueAtQuantileSlice(&tv.orig.QuantileValues))
fillTestSummaryDataPointValueAtQuantileSlice(newSummaryDataPointValueAtQuantileSlice(&tv.orig.QuantileValues, tv.state))
tv.orig.Flags = 1
}

View File

@ -9,6 +9,7 @@ package pmetric
import (
"sort"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
@ -20,18 +21,20 @@ import (
// Must use NewSummaryDataPointSlice function to create new instances.
// Important: zero-initialized instance is not valid for use.
type SummaryDataPointSlice struct {
orig *[]*otlpmetrics.SummaryDataPoint
orig *[]*otlpmetrics.SummaryDataPoint
state *internal.State
}
func newSummaryDataPointSlice(orig *[]*otlpmetrics.SummaryDataPoint) SummaryDataPointSlice {
return SummaryDataPointSlice{orig}
func newSummaryDataPointSlice(orig *[]*otlpmetrics.SummaryDataPoint, state *internal.State) SummaryDataPointSlice {
return SummaryDataPointSlice{orig: orig, state: state}
}
// NewSummaryDataPointSlice creates a SummaryDataPointSlice with 0 elements.
// Can use "EnsureCapacity" to initialize with a given capacity.
func NewSummaryDataPointSlice() SummaryDataPointSlice {
orig := []*otlpmetrics.SummaryDataPoint(nil)
return newSummaryDataPointSlice(&orig)
state := internal.StateMutable
return newSummaryDataPointSlice(&orig, &state)
}
// Len returns the number of elements in the slice.
@ -50,7 +53,7 @@ func (es SummaryDataPointSlice) Len() int {
// ... // Do something with the element
// }
func (es SummaryDataPointSlice) At(i int) SummaryDataPoint {
return newSummaryDataPoint((*es.orig)[i])
return newSummaryDataPoint((*es.orig)[i], es.state)
}
// EnsureCapacity is an operation that ensures the slice has at least the specified capacity.
@ -66,6 +69,7 @@ func (es SummaryDataPointSlice) At(i int) SummaryDataPoint {
// // Here should set all the values for e.
// }
func (es SummaryDataPointSlice) EnsureCapacity(newCap int) {
es.state.AssertMutable()
oldCap := cap(*es.orig)
if newCap <= oldCap {
return
@ -79,6 +83,7 @@ func (es SummaryDataPointSlice) EnsureCapacity(newCap int) {
// AppendEmpty will append to the end of the slice an empty SummaryDataPoint.
// It returns the newly added SummaryDataPoint.
func (es SummaryDataPointSlice) AppendEmpty() SummaryDataPoint {
es.state.AssertMutable()
*es.orig = append(*es.orig, &otlpmetrics.SummaryDataPoint{})
return es.At(es.Len() - 1)
}
@ -86,6 +91,8 @@ func (es SummaryDataPointSlice) AppendEmpty() SummaryDataPoint {
// MoveAndAppendTo moves all elements from the current slice and appends them to the dest.
// The current slice will be cleared.
func (es SummaryDataPointSlice) MoveAndAppendTo(dest SummaryDataPointSlice) {
es.state.AssertMutable()
dest.state.AssertMutable()
if *dest.orig == nil {
// We can simply move the entire vector and avoid any allocations.
*dest.orig = *es.orig
@ -98,6 +105,7 @@ func (es SummaryDataPointSlice) MoveAndAppendTo(dest SummaryDataPointSlice) {
// RemoveIf calls f sequentially for each element present in the slice.
// If f returns true, the element is removed from the slice.
func (es SummaryDataPointSlice) RemoveIf(f func(SummaryDataPoint) bool) {
es.state.AssertMutable()
newLen := 0
for i := 0; i < len(*es.orig); i++ {
if f(es.At(i)) {
@ -117,12 +125,13 @@ func (es SummaryDataPointSlice) RemoveIf(f func(SummaryDataPoint) bool) {
// CopyTo copies all elements from the current slice overriding the destination.
func (es SummaryDataPointSlice) CopyTo(dest SummaryDataPointSlice) {
dest.state.AssertMutable()
srcLen := es.Len()
destCap := cap(*dest.orig)
if srcLen <= destCap {
(*dest.orig) = (*dest.orig)[:srcLen:destCap]
for i := range *es.orig {
newSummaryDataPoint((*es.orig)[i]).CopyTo(newSummaryDataPoint((*dest.orig)[i]))
newSummaryDataPoint((*es.orig)[i], es.state).CopyTo(newSummaryDataPoint((*dest.orig)[i], dest.state))
}
return
}
@ -130,7 +139,7 @@ func (es SummaryDataPointSlice) CopyTo(dest SummaryDataPointSlice) {
wrappers := make([]*otlpmetrics.SummaryDataPoint, srcLen)
for i := range *es.orig {
wrappers[i] = &origs[i]
newSummaryDataPoint((*es.orig)[i]).CopyTo(newSummaryDataPoint(wrappers[i]))
newSummaryDataPoint((*es.orig)[i], es.state).CopyTo(newSummaryDataPoint(wrappers[i], dest.state))
}
*dest.orig = wrappers
}
@ -139,5 +148,6 @@ func (es SummaryDataPointSlice) CopyTo(dest SummaryDataPointSlice) {
// provided less function so that two instances of SummaryDataPointSlice
// can be compared.
func (es SummaryDataPointSlice) Sort(less func(a, b SummaryDataPoint) bool) {
es.state.AssertMutable()
sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) })
}

View File

@ -12,13 +12,15 @@ import (
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
func TestSummaryDataPointSlice(t *testing.T) {
es := NewSummaryDataPointSlice()
assert.Equal(t, 0, es.Len())
es = newSummaryDataPointSlice(&[]*otlpmetrics.SummaryDataPoint{})
state := internal.StateMutable
es = newSummaryDataPointSlice(&[]*otlpmetrics.SummaryDataPoint{}, &state)
assert.Equal(t, 0, es.Len())
emptyVal := NewSummaryDataPoint()
@ -32,6 +34,19 @@ func TestSummaryDataPointSlice(t *testing.T) {
assert.Equal(t, 7, es.Len())
}
func TestSummaryDataPointSliceReadOnly(t *testing.T) {
sharedState := internal.StateReadOnly
es := newSummaryDataPointSlice(&[]*otlpmetrics.SummaryDataPoint{}, &sharedState)
assert.Equal(t, 0, es.Len())
assert.Panics(t, func() { es.AppendEmpty() })
assert.Panics(t, func() { es.EnsureCapacity(2) })
es2 := NewSummaryDataPointSlice()
es.CopyTo(es2)
assert.Panics(t, func() { es2.CopyTo(es) })
assert.Panics(t, func() { es.MoveAndAppendTo(es2) })
assert.Panics(t, func() { es2.MoveAndAppendTo(es) })
}
func TestSummaryDataPointSlice_CopyTo(t *testing.T) {
dest := NewSummaryDataPointSlice()
// Test CopyTo to empty
@ -134,6 +149,6 @@ func fillTestSummaryDataPointSlice(es SummaryDataPointSlice) {
*es.orig = make([]*otlpmetrics.SummaryDataPoint, 7)
for i := 0; i < 7; i++ {
(*es.orig)[i] = &otlpmetrics.SummaryDataPoint{}
fillTestSummaryDataPoint(newSummaryDataPoint((*es.orig)[i]))
fillTestSummaryDataPoint(newSummaryDataPoint((*es.orig)[i], es.state))
}
}

View File

@ -7,6 +7,7 @@
package pmetric
import (
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
@ -18,11 +19,12 @@ import (
// Must use NewSummaryDataPointValueAtQuantile function to create new instances.
// Important: zero-initialized instance is not valid for use.
type SummaryDataPointValueAtQuantile struct {
orig *otlpmetrics.SummaryDataPoint_ValueAtQuantile
orig *otlpmetrics.SummaryDataPoint_ValueAtQuantile
state *internal.State
}
func newSummaryDataPointValueAtQuantile(orig *otlpmetrics.SummaryDataPoint_ValueAtQuantile) SummaryDataPointValueAtQuantile {
return SummaryDataPointValueAtQuantile{orig}
func newSummaryDataPointValueAtQuantile(orig *otlpmetrics.SummaryDataPoint_ValueAtQuantile, state *internal.State) SummaryDataPointValueAtQuantile {
return SummaryDataPointValueAtQuantile{orig: orig, state: state}
}
// NewSummaryDataPointValueAtQuantile creates a new empty SummaryDataPointValueAtQuantile.
@ -30,12 +32,15 @@ func newSummaryDataPointValueAtQuantile(orig *otlpmetrics.SummaryDataPoint_Value
// This must be used only in testing code. Users should use "AppendEmpty" when part of a Slice,
// OR directly access the member if this is embedded in another struct.
func NewSummaryDataPointValueAtQuantile() SummaryDataPointValueAtQuantile {
return newSummaryDataPointValueAtQuantile(&otlpmetrics.SummaryDataPoint_ValueAtQuantile{})
state := internal.StateMutable
return newSummaryDataPointValueAtQuantile(&otlpmetrics.SummaryDataPoint_ValueAtQuantile{}, &state)
}
// MoveTo moves all properties from the current struct overriding the destination and
// resetting the current instance to its zero value
func (ms SummaryDataPointValueAtQuantile) MoveTo(dest SummaryDataPointValueAtQuantile) {
ms.state.AssertMutable()
dest.state.AssertMutable()
*dest.orig = *ms.orig
*ms.orig = otlpmetrics.SummaryDataPoint_ValueAtQuantile{}
}
@ -47,6 +52,7 @@ func (ms SummaryDataPointValueAtQuantile) Quantile() float64 {
// SetQuantile replaces the quantile associated with this SummaryDataPointValueAtQuantile.
func (ms SummaryDataPointValueAtQuantile) SetQuantile(v float64) {
ms.state.AssertMutable()
ms.orig.Quantile = v
}
@ -57,11 +63,13 @@ func (ms SummaryDataPointValueAtQuantile) Value() float64 {
// SetValue replaces the value associated with this SummaryDataPointValueAtQuantile.
func (ms SummaryDataPointValueAtQuantile) SetValue(v float64) {
ms.state.AssertMutable()
ms.orig.Value = v
}
// CopyTo copies all properties from the current struct overriding the destination.
func (ms SummaryDataPointValueAtQuantile) CopyTo(dest SummaryDataPointValueAtQuantile) {
dest.state.AssertMutable()
dest.SetQuantile(ms.Quantile())
dest.SetValue(ms.Value())
}

View File

@ -10,6 +10,9 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/internal"
otlpmetrics "go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1"
)
func TestSummaryDataPointValueAtQuantile_MoveTo(t *testing.T) {
@ -18,6 +21,13 @@ func TestSummaryDataPointValueAtQuantile_MoveTo(t *testing.T) {
ms.MoveTo(dest)
assert.Equal(t, NewSummaryDataPointValueAtQuantile(), ms)
assert.Equal(t, generateTestSummaryDataPointValueAtQuantile(), dest)
sharedState := internal.StateReadOnly
assert.Panics(t, func() {
ms.MoveTo(newSummaryDataPointValueAtQuantile(&otlpmetrics.SummaryDataPoint_ValueAtQuantile{}, &sharedState))
})
assert.Panics(t, func() {
newSummaryDataPointValueAtQuantile(&otlpmetrics.SummaryDataPoint_ValueAtQuantile{}, &sharedState).MoveTo(dest)
})
}
func TestSummaryDataPointValueAtQuantile_CopyTo(t *testing.T) {
@ -28,6 +38,10 @@ func TestSummaryDataPointValueAtQuantile_CopyTo(t *testing.T) {
orig = generateTestSummaryDataPointValueAtQuantile()
orig.CopyTo(ms)
assert.Equal(t, orig, ms)
sharedState := internal.StateReadOnly
assert.Panics(t, func() {
ms.CopyTo(newSummaryDataPointValueAtQuantile(&otlpmetrics.SummaryDataPoint_ValueAtQuantile{}, &sharedState))
})
}
func TestSummaryDataPointValueAtQuantile_Quantile(t *testing.T) {
@ -35,6 +49,10 @@ func TestSummaryDataPointValueAtQuantile_Quantile(t *testing.T) {
assert.Equal(t, float64(0.0), ms.Quantile())
ms.SetQuantile(float64(17.13))
assert.Equal(t, float64(17.13), ms.Quantile())
sharedState := internal.StateReadOnly
assert.Panics(t, func() {
newSummaryDataPointValueAtQuantile(&otlpmetrics.SummaryDataPoint_ValueAtQuantile{}, &sharedState).SetQuantile(float64(17.13))
})
}
func TestSummaryDataPointValueAtQuantile_Value(t *testing.T) {
@ -42,6 +60,10 @@ func TestSummaryDataPointValueAtQuantile_Value(t *testing.T) {
assert.Equal(t, float64(0.0), ms.Value())
ms.SetValue(float64(17.13))
assert.Equal(t, float64(17.13), ms.Value())
sharedState := internal.StateReadOnly
assert.Panics(t, func() {
newSummaryDataPointValueAtQuantile(&otlpmetrics.SummaryDataPoint_ValueAtQuantile{}, &sharedState).SetValue(float64(17.13))
})
}
func generateTestSummaryDataPointValueAtQuantile() SummaryDataPointValueAtQuantile {

Some files were not shown because too many files have changed in this diff Show More