Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce model translation and encoding interfaces #3200

Merged
merged 16 commits into from
May 20, 2021
9 changes: 9 additions & 0 deletions model/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Protocols

This package provides common ways for decoding serialized bytes into protocol-specific in-memory data models (e.g. Zipkin Span). These data models can then be translated to internal pdata representations. Similarly, pdata can be translated from a data model which can then be serialized into bytes.

[serializer](serializer): Common interfaces for serializing/deserializing bytes from/to protocol-specific data models.

[translator](translator): Common interfaces for translating protocol-specific data models from/to pdata.

This package provides higher level APIs that do both encoding of bytes and data model if going directly pdata ⇔ bytes.
30 changes: 30 additions & 0 deletions model/serializer/deserialize.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package encoding
jrcamp marked this conversation as resolved.
Show resolved Hide resolved

// MetricsDeserializer decodes bytes into protocol-specific data model.
type MetricsDeserializer interface {
DeserializeMetrics(bytes []byte) (interface{}, error)
jrcamp marked this conversation as resolved.
Show resolved Hide resolved
}

// TracesDeserializer decodes bytes into protocol-specific data model.
type TracesDeserializer interface {
DeserializeTraces(bytes []byte) (interface{}, error)
}

// LogsDeserializer decodes bytes into protocol-specific data model.
type LogsDeserializer interface {
DeserializeLogs(bytes []byte) (interface{}, error)
}
30 changes: 30 additions & 0 deletions model/serializer/serialize.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package encoding

// MetricsSerializer encodes protocol-specific data model into bytes.
type MetricsSerializer interface {
SerializeMetrics(model interface{}) ([]byte, error)
}

// TracesSerializer encodes protocol-specific data model into bytes.
type TracesSerializer interface {
SerializeTraces(model interface{}) ([]byte, error)
}

// LogsSerializer encodes protocol-specific data model into bytes.
type LogsSerializer interface {
SerializeLogs(model interface{}) ([]byte, error)
}
43 changes: 43 additions & 0 deletions model/serializer/serializer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package encoding

import "fmt"

// Encoding is the encoding format that a model is serialized to.
type Encoding string

const (
Protobuf Encoding = "protobuf"
JSON Encoding = "json"
Thrift Encoding = "thrift"
)

func (e Encoding) String() string {
return string(e)
}

// ErrUnavailableEncoding is returned when the requested encoding is not supported.
type ErrUnavailableEncoding struct {
encoding Encoding
}

func (e *ErrUnavailableEncoding) Error() string {
return fmt.Sprintf("unsupported encoding %q", e.encoding)
}

func NewErrUnavailableEncoding(encoding Encoding) *ErrUnavailableEncoding {
return &ErrUnavailableEncoding{encoding: encoding}
}
31 changes: 31 additions & 0 deletions model/serializer/serializer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package encoding

import (
"testing"

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

func TestNewErrUnavailableEncoding(t *testing.T) {
err := NewErrUnavailableEncoding("unknown")
assert.IsType(t, &ErrUnavailableEncoding{}, err)
assert.EqualError(t, err, `unsupported encoding "unknown"`)
}

func TestEncoding_String(t *testing.T) {
assert.Equal(t, "protobuf", Protobuf.String())
}
38 changes: 38 additions & 0 deletions model/translator/decoder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package translation
jrcamp marked this conversation as resolved.
Show resolved Hide resolved

import "go.opentelemetry.io/collector/consumer/pdata"

type MetricsDecoder interface {
// ToMetrics converts a protocol-specific data model into pdata.
ToMetrics(src interface{}) (pdata.Metrics, error)
// NewModel returns an instance of the model.
NewModel() interface{}
jrcamp marked this conversation as resolved.
Show resolved Hide resolved
}

type TracesDecoder interface {
// ToTraces converts a protocol-specific data model into pdata.
ToTraces(src interface{}) (pdata.Traces, error)
// NewModel returns an instance of the model.
NewModel() interface{}
}

type LogsDecoder interface {
// ToLogs converts a protocol-specific data model into pdata.
ToLogs(src interface{}) (pdata.Logs, error)
// NewModel returns an instance of the model.
NewModel() interface{}
}
38 changes: 38 additions & 0 deletions model/translator/encoder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package translation

import "go.opentelemetry.io/collector/consumer/pdata"

type MetricsEncoder interface {
// FromMetrics converts pdata to protocol-specific data model.
FromMetrics(md pdata.Metrics, out interface{}) error
// NewModel returns an instance of the model.
NewModel() interface{}
}
jrcamp marked this conversation as resolved.
Show resolved Hide resolved

type TracesEncoder interface {
// FromTraces converts pdata to protocol-specific data model.
FromTraces(md pdata.Traces, out interface{}) error
// NewModel returns an instance of the model.
NewModel() interface{}
}

type LogsEncoder interface {
// FromLogs converts pdata to protocol-specific data model.
FromLogs(md pdata.Logs, out interface{}) error
// NewModel returns an instance of the model.
NewModel() interface{}
}
37 changes: 37 additions & 0 deletions model/translator/translator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package translation

import (
"fmt"
)

// ErrIncompatibleType details a type conversion error during translation.
type ErrIncompatibleType struct {
jrcamp marked this conversation as resolved.
Show resolved Hide resolved
given interface{}
expected interface{}
}

func (i *ErrIncompatibleType) Error() string {
return fmt.Sprintf("expected model type %T but given %T", i.expected, i.given)
}

// NewErrIncompatibleType returns ErrIncompatibleType instance
func NewErrIncompatibleType(expected, given interface{}) *ErrIncompatibleType {
return &ErrIncompatibleType{
given: given,
expected: expected,
}
}
28 changes: 28 additions & 0 deletions model/translator/translator_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package translation

import (
"testing"

zipkinmodel "github.com/openzipkin/zipkin-go/model"
"github.com/stretchr/testify/assert"
)

func TestNewErrIncompatibleType(t *testing.T) {
err := NewErrIncompatibleType([]*zipkinmodel.SpanModel{}, "given")
assert.IsType(t, &ErrIncompatibleType{}, err)
assert.EqualError(t, err, "expected model type []*model.SpanModel but given string")
}