1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-08-10 22:31:50 +02:00

Interface stability documentation (#2012)

* Interface stability documentation

* Update versioning policy

* Update CONTRIBUTING

* Document how to extend immutable interfaces

* Markdown format VERSIONING changes
This commit is contained in:
Tyler Yahn
2021-06-18 14:56:11 +00:00
committed by GitHub
parent 39fe8092ed
commit 694c9a413d
12 changed files with 165 additions and 2 deletions

View File

@@ -380,7 +380,7 @@ func NewDog(name string, o ...DogOption) Dog {…}
func NewBird(name string, o ...BirdOption) Bird {} func NewBird(name string, o ...BirdOption) Bird {}
``` ```
### Interface Type ### Interfaces
To allow other developers to better comprehend the code, it is important To allow other developers to better comprehend the code, it is important
to ensure it is sufficiently documented. One simple measure that contributes to ensure it is sufficiently documented. One simple measure that contributes
@@ -388,6 +388,69 @@ to this aim is self-documenting by naming method parameters. Therefore,
where appropriate, methods of every exported interface type should have where appropriate, methods of every exported interface type should have
their parameters appropriately named. their parameters appropriately named.
#### Interface Stability
All exported stable interfaces that include the following warning in their
doumentation are allowed to be extended with additional methods.
> Warning: methods may be added to this interface in minor releases.
Otherwise, stable interfaces MUST NOT be modified.
If new functionality is needed for an interface that cannot be changed it MUST
be added by including an additional interface. That added interface can be a
simple interface for the specific functionality that you want to add or it can
be a super-set of the original interface. For example, if you wanted to a
`Close` method to the `Exporter` interface:
```go
type Exporter interface {
Export()
}
```
A new interface, `Closer`, can be added:
```go
type Closer interface {
Close()
}
```
Code that is passed the `Exporter` interface can now check to see if the passed
value also satisfies the new interface. E.g.
```go
func caller(e Exporter) {
/* ... */
if c, ok := e.(Closer); ok {
c.Close()
}
/* ... */
}
```
Alternatively, a new type that is the super-set of an `Exporter` can be created.
```go
type ClosingExporter struct {
Exporter
Close()
}
```
This new type can be used similar to the simple interface above in that a
passed `Exporter` type can be asserted to satisfy the `ClosingExporter` type
and the `Close` method called.
This super-set approach can be useful if there is explicit behavior that needs
to be coupled with the original type and passed as a unified type to a new
function, but, because of this coupling, it also limits the applicability of
the added functionality. If there exist other interfaces where this
functionality should be added, each one will need their own super-set
interfaces and will duplicate the pattern. For this reason, the simple targeted
interface that defines the specific functionality should be preferred.
## Approvers and Maintainers ## Approvers and Maintainers
Approvers: Approvers:

View File

@@ -12,7 +12,14 @@ is designed so the following goals can be achieved.
* [Semantic import * [Semantic import
versioning](https://github.com/golang/go/wiki/Modules#semantic-import-versioning) versioning](https://github.com/golang/go/wiki/Modules#semantic-import-versioning)
will be used. will be used.
* Versions will comply with [semver 2.0](https://semver.org/spec/v2.0.0.html). * Versions will comply with [semver
2.0](https://semver.org/spec/v2.0.0.html) with the following exceptions.
* New methods may be added to exported API interfaces. All exported
interfaces that fall within this exception will include the following
paragraph in their public documentation.
> Warning: methods may be added to this interface in minor releases.
* If a module is version `v2` or higher, the major version of the module * If a module is version `v2` or higher, the major version of the module
must be included as a `/vN` at the end of the module paths used in must be included as a `/vN` at the end of the module paths used in
`go.mod` files (e.g., `module go.opentelemetry.io/otel/v2`, `require `go.mod` files (e.g., `module go.opentelemetry.io/otel/v2`, `require

View File

@@ -16,7 +16,12 @@ package otel // import "go.opentelemetry.io/otel"
// ErrorHandler handles irremediable events. // ErrorHandler handles irremediable events.
type ErrorHandler interface { type ErrorHandler interface {
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
// Handle handles any error deemed irremediable by an OpenTelemetry // Handle handles any error deemed irremediable by an OpenTelemetry
// component. // component.
Handle(error) Handle(error)
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
} }

View File

@@ -24,10 +24,16 @@ import (
// transformation of data into wire format, and the transmission of that // transformation of data into wire format, and the transmission of that
// data to the collector. // data to the collector.
type Client interface { type Client interface {
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
// Start should establish connection(s) to endpoint(s). It is // Start should establish connection(s) to endpoint(s). It is
// called just once by the exporter, so the implementation // called just once by the exporter, so the implementation
// does not need to worry about idempotence and locking. // does not need to worry about idempotence and locking.
Start(ctx context.Context) error Start(ctx context.Context) error
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
// Stop should close the connections. The function is called // Stop should close the connections. The function is called
// only once by the exporter, so the implementation does not // only once by the exporter, so the implementation does not
// need to worry about idempotence, but it may be called // need to worry about idempotence, but it may be called
@@ -36,8 +42,13 @@ type Client interface {
// synchronization point - after the function returns, the // synchronization point - after the function returns, the
// process of closing connections is assumed to be finished. // process of closing connections is assumed to be finished.
Stop(ctx context.Context) error Stop(ctx context.Context) error
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
// UploadTraces should transform the passed traces to the wire // UploadTraces should transform the passed traces to the wire
// format and send it to the collector. May be called // format and send it to the collector. May be called
// concurrently. // concurrently.
UploadTraces(ctx context.Context, protoSpans []*tracepb.ResourceSpans) error UploadTraces(ctx context.Context, protoSpans []*tracepb.ResourceSpans) error
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
} }

View File

@@ -21,12 +21,23 @@ import (
// TextMapCarrier is the storage medium used by a TextMapPropagator. // TextMapCarrier is the storage medium used by a TextMapPropagator.
type TextMapCarrier interface { type TextMapCarrier interface {
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
// Get returns the value associated with the passed key. // Get returns the value associated with the passed key.
Get(key string) string Get(key string) string
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
// Set stores the key-value pair. // Set stores the key-value pair.
Set(key string, value string) Set(key string, value string)
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
// Keys lists the keys stored in this carrier. // Keys lists the keys stored in this carrier.
Keys() []string Keys() []string
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
} }
// HeaderCarrier adapts http.Header to satisfy the TextMapCarrier interface. // HeaderCarrier adapts http.Header to satisfy the TextMapCarrier interface.
@@ -54,12 +65,23 @@ func (hc HeaderCarrier) Keys() []string {
// TextMapPropagator propagates cross-cutting concerns as key-value text // TextMapPropagator propagates cross-cutting concerns as key-value text
// pairs within a carrier that travels in-band across process boundaries. // pairs within a carrier that travels in-band across process boundaries.
type TextMapPropagator interface { type TextMapPropagator interface {
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
// Inject set cross-cutting concerns from the Context into the carrier. // Inject set cross-cutting concerns from the Context into the carrier.
Inject(ctx context.Context, carrier TextMapCarrier) Inject(ctx context.Context, carrier TextMapCarrier)
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
// Extract reads cross-cutting concerns from the carrier into a Context. // Extract reads cross-cutting concerns from the carrier into a Context.
Extract(ctx context.Context, carrier TextMapCarrier) context.Context Extract(ctx context.Context, carrier TextMapCarrier) context.Context
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
// Fields returns the keys who's values are set with Inject. // Fields returns the keys who's values are set with Inject.
Fields() []string Fields() []string
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
} }
type compositeTextMapPropagator []TextMapPropagator type compositeTextMapPropagator []TextMapPropagator

View File

@@ -29,12 +29,17 @@ var (
// Detector detects OpenTelemetry resource information // Detector detects OpenTelemetry resource information
type Detector interface { type Detector interface {
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
// Detect returns an initialized Resource based on gathered information. // Detect returns an initialized Resource based on gathered information.
// If the source information to construct a Resource contains invalid // If the source information to construct a Resource contains invalid
// values, a Resource is returned with the valid parts of the source // values, a Resource is returned with the valid parts of the source
// information used for initialization along with an appropriately // information used for initialization along with an appropriately
// wrapped ErrPartialResource error. // wrapped ErrPartialResource error.
Detect(ctx context.Context) (*Resource, error) Detect(ctx context.Context) (*Resource, error)
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
} }
// Detect calls all input detectors sequentially and merges each result with the previous one. // Detect calls all input detectors sequentially and merges each result with the previous one.

View File

@@ -26,8 +26,18 @@ import (
// IDGenerator allows custom generators for TraceID and SpanID. // IDGenerator allows custom generators for TraceID and SpanID.
type IDGenerator interface { type IDGenerator interface {
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
// NewIDs returns a new trace and span ID.
NewIDs(ctx context.Context) (trace.TraceID, trace.SpanID) NewIDs(ctx context.Context) (trace.TraceID, trace.SpanID)
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
// NewSpanID returns a ID for a new span in the trace with traceID.
NewSpanID(ctx context.Context, traceID trace.TraceID) trace.SpanID NewSpanID(ctx context.Context, traceID trace.TraceID) trace.SpanID
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
} }
type randomIDGenerator struct { type randomIDGenerator struct {

View File

@@ -25,8 +25,19 @@ import (
// Sampler decides whether a trace should be sampled and exported. // Sampler decides whether a trace should be sampled and exported.
type Sampler interface { type Sampler interface {
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
// ShouldSample returns a SamplingResult based on a decision made from the
// passed parameters.
ShouldSample(parameters SamplingParameters) SamplingResult ShouldSample(parameters SamplingParameters) SamplingResult
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
// Description returns information describing the Sampler.
Description() string Description() string
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
} }
// SamplingParameters contains the values passed to a Sampler. // SamplingParameters contains the values passed to a Sampler.

View File

@@ -34,6 +34,8 @@ import (
// ReadOnlySpan allows reading information from the data structure underlying a // ReadOnlySpan allows reading information from the data structure underlying a
// trace.Span. It is used in places where reading information from a span is // trace.Span. It is used in places where reading information from a span is
// necessary but changing the span isn't necessary or allowed. // necessary but changing the span isn't necessary or allowed.
//
// Warning: methods may be added to this interface in minor releases.
type ReadOnlySpan interface { type ReadOnlySpan interface {
// Name returns the name of the span. // Name returns the name of the span.
Name() string Name() string
@@ -88,6 +90,8 @@ type ReadOnlySpan interface {
// This interface exposes the union of the methods of trace.Span (which is a // This interface exposes the union of the methods of trace.Span (which is a
// "write-only" span) and ReadOnlySpan. New methods for writing or reading span // "write-only" span) and ReadOnlySpan. New methods for writing or reading span
// information should be added under trace.Span or ReadOnlySpan, respectively. // information should be added under trace.Span or ReadOnlySpan, respectively.
//
// Warning: methods may be added to this interface in minor releases.
type ReadWriteSpan interface { type ReadWriteSpan interface {
trace.Span trace.Span
ReadOnlySpan ReadOnlySpan

View File

@@ -19,6 +19,9 @@ import "context"
// SpanExporter handles the delivery of spans to external receivers. This is // SpanExporter handles the delivery of spans to external receivers. This is
// the final component in the trace export pipeline. // the final component in the trace export pipeline.
type SpanExporter interface { type SpanExporter interface {
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
// ExportSpans exports a batch of spans. // ExportSpans exports a batch of spans.
// //
// This function is called synchronously, so there is no concurrency // This function is called synchronously, so there is no concurrency
@@ -31,9 +34,14 @@ type SpanExporter interface {
// returned by this function are considered unrecoverable and will be // returned by this function are considered unrecoverable and will be
// reported to a configured error Handler. // reported to a configured error Handler.
ExportSpans(ctx context.Context, spans []ReadOnlySpan) error ExportSpans(ctx context.Context, spans []ReadOnlySpan) error
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
// Shutdown notifies the exporter of a pending halt to operations. The // Shutdown notifies the exporter of a pending halt to operations. The
// exporter is expected to preform any cleanup or synchronization it // exporter is expected to preform any cleanup or synchronization it
// requires while honoring all timeouts and cancellations contained in // requires while honoring all timeouts and cancellations contained in
// the passed context. // the passed context.
Shutdown(ctx context.Context) error Shutdown(ctx context.Context) error
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
} }

View File

@@ -24,13 +24,20 @@ import (
// and end of a Span's lifecycle, and are called in the order they are // and end of a Span's lifecycle, and are called in the order they are
// registered. // registered.
type SpanProcessor interface { type SpanProcessor interface {
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
// OnStart is called when a span is started. It is called synchronously // OnStart is called when a span is started. It is called synchronously
// and should not block. // and should not block.
OnStart(parent context.Context, s ReadWriteSpan) OnStart(parent context.Context, s ReadWriteSpan)
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
// OnEnd is called when span is finished. It is called synchronously and // OnEnd is called when span is finished. It is called synchronously and
// hence not block. // hence not block.
OnEnd(s ReadOnlySpan) OnEnd(s ReadOnlySpan)
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
// Shutdown is called when the SDK shuts down. Any cleanup or release of // Shutdown is called when the SDK shuts down. Any cleanup or release of
// resources held by the processor should be done in this call. // resources held by the processor should be done in this call.
@@ -41,12 +48,16 @@ type SpanProcessor interface {
// All timeouts and cancellations contained in ctx must be honored, this // All timeouts and cancellations contained in ctx must be honored, this
// should not block indefinitely. // should not block indefinitely.
Shutdown(ctx context.Context) error Shutdown(ctx context.Context) error
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
// ForceFlush exports all ended spans to the configured Exporter that have not yet // ForceFlush exports all ended spans to the configured Exporter that have not yet
// been exported. It should only be called when absolutely necessary, such as when // been exported. It should only be called when absolutely necessary, such as when
// using a FaaS provider that may suspend the process after an invocation, but before // using a FaaS provider that may suspend the process after an invocation, but before
// the Processor can export the completed spans. // the Processor can export the completed spans.
ForceFlush(ctx context.Context) error ForceFlush(ctx context.Context) error
// DO NOT CHANGE: any modification will not be backwards compatible and
// must never be done outside of a new major release.
} }
type spanProcessorState struct { type spanProcessorState struct {

View File

@@ -337,6 +337,8 @@ func (sc SpanContext) MarshalJSON() ([]byte, error) {
// and timed operation of a workflow that is traced. A Tracer is used to // and timed operation of a workflow that is traced. A Tracer is used to
// create a Span and it is then up to the operation the Span represents to // create a Span and it is then up to the operation the Span represents to
// properly end the Span when the operation itself ends. // properly end the Span when the operation itself ends.
//
// Warning: methods may be added to this interface in minor releases.
type Span interface { type Span interface {
// End completes the Span. The Span is considered complete and ready to be // End completes the Span. The Span is considered complete and ready to be
// delivered through the rest of the telemetry pipeline after this method // delivered through the rest of the telemetry pipeline after this method
@@ -478,6 +480,8 @@ func (sk SpanKind) String() string {
} }
// Tracer is the creator of Spans. // Tracer is the creator of Spans.
//
// Warning: methods may be added to this interface in minor releases.
type Tracer interface { type Tracer interface {
// Start creates a span and a context.Context containing the newly-created span. // Start creates a span and a context.Context containing the newly-created span.
// //
@@ -496,6 +500,8 @@ type Tracer interface {
} }
// TracerProvider provides access to instrumentation Tracers. // TracerProvider provides access to instrumentation Tracers.
//
// Warning: methods may be added to this interface in minor releases.
type TracerProvider interface { type TracerProvider interface {
// Tracer creates an implementation of the Tracer interface. // Tracer creates an implementation of the Tracer interface.
// The instrumentationName must be the name of the library providing // The instrumentationName must be the name of the library providing