Skip to content

Commit 694c9a4

Browse files
authored
Interface stability documentation (open-telemetry#2012)
* Interface stability documentation * Update versioning policy * Update CONTRIBUTING * Document how to extend immutable interfaces * Markdown format VERSIONING changes
1 parent 39fe809 commit 694c9a4

File tree

12 files changed

+165
-2
lines changed

12 files changed

+165
-2
lines changed

CONTRIBUTING.md

+64-1
Original file line numberDiff line numberDiff line change
@@ -380,14 +380,77 @@ func NewDog(name string, o ...DogOption) Dog {…}
380380
func NewBird(name string, o ...BirdOption) Bird {…}
381381
```
382382

383-
### Interface Type
383+
### Interfaces
384384

385385
To allow other developers to better comprehend the code, it is important
386386
to ensure it is sufficiently documented. One simple measure that contributes
387387
to this aim is self-documenting by naming method parameters. Therefore,
388388
where appropriate, methods of every exported interface type should have
389389
their parameters appropriately named.
390390

391+
#### Interface Stability
392+
393+
All exported stable interfaces that include the following warning in their
394+
doumentation are allowed to be extended with additional methods.
395+
396+
> Warning: methods may be added to this interface in minor releases.
397+
398+
Otherwise, stable interfaces MUST NOT be modified.
399+
400+
If new functionality is needed for an interface that cannot be changed it MUST
401+
be added by including an additional interface. That added interface can be a
402+
simple interface for the specific functionality that you want to add or it can
403+
be a super-set of the original interface. For example, if you wanted to a
404+
`Close` method to the `Exporter` interface:
405+
406+
```go
407+
type Exporter interface {
408+
Export()
409+
}
410+
```
411+
412+
A new interface, `Closer`, can be added:
413+
414+
```go
415+
type Closer interface {
416+
Close()
417+
}
418+
```
419+
420+
Code that is passed the `Exporter` interface can now check to see if the passed
421+
value also satisfies the new interface. E.g.
422+
423+
```go
424+
func caller(e Exporter) {
425+
/* ... */
426+
if c, ok := e.(Closer); ok {
427+
c.Close()
428+
}
429+
/* ... */
430+
}
431+
```
432+
433+
Alternatively, a new type that is the super-set of an `Exporter` can be created.
434+
435+
```go
436+
type ClosingExporter struct {
437+
Exporter
438+
Close()
439+
}
440+
```
441+
442+
This new type can be used similar to the simple interface above in that a
443+
passed `Exporter` type can be asserted to satisfy the `ClosingExporter` type
444+
and the `Close` method called.
445+
446+
This super-set approach can be useful if there is explicit behavior that needs
447+
to be coupled with the original type and passed as a unified type to a new
448+
function, but, because of this coupling, it also limits the applicability of
449+
the added functionality. If there exist other interfaces where this
450+
functionality should be added, each one will need their own super-set
451+
interfaces and will duplicate the pattern. For this reason, the simple targeted
452+
interface that defines the specific functionality should be preferred.
453+
391454
## Approvers and Maintainers
392455

393456
Approvers:

VERSIONING.md

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

error_handler.go

+5
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@ package otel // import "go.opentelemetry.io/otel"
1616

1717
// ErrorHandler handles irremediable events.
1818
type ErrorHandler interface {
19+
// DO NOT CHANGE: any modification will not be backwards compatible and
20+
// must never be done outside of a new major release.
21+
1922
// Handle handles any error deemed irremediable by an OpenTelemetry
2023
// component.
2124
Handle(error)
25+
// DO NOT CHANGE: any modification will not be backwards compatible and
26+
// must never be done outside of a new major release.
2227
}

exporters/otlp/otlptrace/clients.go

+11
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,16 @@ import (
2424
// transformation of data into wire format, and the transmission of that
2525
// data to the collector.
2626
type Client interface {
27+
// DO NOT CHANGE: any modification will not be backwards compatible and
28+
// must never be done outside of a new major release.
29+
2730
// Start should establish connection(s) to endpoint(s). It is
2831
// called just once by the exporter, so the implementation
2932
// does not need to worry about idempotence and locking.
3033
Start(ctx context.Context) error
34+
// DO NOT CHANGE: any modification will not be backwards compatible and
35+
// must never be done outside of a new major release.
36+
3137
// Stop should close the connections. The function is called
3238
// only once by the exporter, so the implementation does not
3339
// need to worry about idempotence, but it may be called
@@ -36,8 +42,13 @@ type Client interface {
3642
// synchronization point - after the function returns, the
3743
// process of closing connections is assumed to be finished.
3844
Stop(ctx context.Context) error
45+
// DO NOT CHANGE: any modification will not be backwards compatible and
46+
// must never be done outside of a new major release.
47+
3948
// UploadTraces should transform the passed traces to the wire
4049
// format and send it to the collector. May be called
4150
// concurrently.
4251
UploadTraces(ctx context.Context, protoSpans []*tracepb.ResourceSpans) error
52+
// DO NOT CHANGE: any modification will not be backwards compatible and
53+
// must never be done outside of a new major release.
4354
}

propagation/propagation.go

+22
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,23 @@ import (
2121

2222
// TextMapCarrier is the storage medium used by a TextMapPropagator.
2323
type TextMapCarrier interface {
24+
// DO NOT CHANGE: any modification will not be backwards compatible and
25+
// must never be done outside of a new major release.
26+
2427
// Get returns the value associated with the passed key.
2528
Get(key string) string
29+
// DO NOT CHANGE: any modification will not be backwards compatible and
30+
// must never be done outside of a new major release.
31+
2632
// Set stores the key-value pair.
2733
Set(key string, value string)
34+
// DO NOT CHANGE: any modification will not be backwards compatible and
35+
// must never be done outside of a new major release.
36+
2837
// Keys lists the keys stored in this carrier.
2938
Keys() []string
39+
// DO NOT CHANGE: any modification will not be backwards compatible and
40+
// must never be done outside of a new major release.
3041
}
3142

3243
// HeaderCarrier adapts http.Header to satisfy the TextMapCarrier interface.
@@ -54,12 +65,23 @@ func (hc HeaderCarrier) Keys() []string {
5465
// TextMapPropagator propagates cross-cutting concerns as key-value text
5566
// pairs within a carrier that travels in-band across process boundaries.
5667
type TextMapPropagator interface {
68+
// DO NOT CHANGE: any modification will not be backwards compatible and
69+
// must never be done outside of a new major release.
70+
5771
// Inject set cross-cutting concerns from the Context into the carrier.
5872
Inject(ctx context.Context, carrier TextMapCarrier)
73+
// DO NOT CHANGE: any modification will not be backwards compatible and
74+
// must never be done outside of a new major release.
75+
5976
// Extract reads cross-cutting concerns from the carrier into a Context.
6077
Extract(ctx context.Context, carrier TextMapCarrier) context.Context
78+
// DO NOT CHANGE: any modification will not be backwards compatible and
79+
// must never be done outside of a new major release.
80+
6181
// Fields returns the keys who's values are set with Inject.
6282
Fields() []string
83+
// DO NOT CHANGE: any modification will not be backwards compatible and
84+
// must never be done outside of a new major release.
6385
}
6486

6587
type compositeTextMapPropagator []TextMapPropagator

sdk/resource/auto.go

+5
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,17 @@ var (
2929

3030
// Detector detects OpenTelemetry resource information
3131
type Detector interface {
32+
// DO NOT CHANGE: any modification will not be backwards compatible and
33+
// must never be done outside of a new major release.
34+
3235
// Detect returns an initialized Resource based on gathered information.
3336
// If the source information to construct a Resource contains invalid
3437
// values, a Resource is returned with the valid parts of the source
3538
// information used for initialization along with an appropriately
3639
// wrapped ErrPartialResource error.
3740
Detect(ctx context.Context) (*Resource, error)
41+
// DO NOT CHANGE: any modification will not be backwards compatible and
42+
// must never be done outside of a new major release.
3843
}
3944

4045
// Detect calls all input detectors sequentially and merges each result with the previous one.

sdk/trace/id_generator.go

+10
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,18 @@ import (
2626

2727
// IDGenerator allows custom generators for TraceID and SpanID.
2828
type IDGenerator interface {
29+
// DO NOT CHANGE: any modification will not be backwards compatible and
30+
// must never be done outside of a new major release.
31+
32+
// NewIDs returns a new trace and span ID.
2933
NewIDs(ctx context.Context) (trace.TraceID, trace.SpanID)
34+
// DO NOT CHANGE: any modification will not be backwards compatible and
35+
// must never be done outside of a new major release.
36+
37+
// NewSpanID returns a ID for a new span in the trace with traceID.
3038
NewSpanID(ctx context.Context, traceID trace.TraceID) trace.SpanID
39+
// DO NOT CHANGE: any modification will not be backwards compatible and
40+
// must never be done outside of a new major release.
3141
}
3242

3343
type randomIDGenerator struct {

sdk/trace/sampling.go

+11
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,19 @@ import (
2525

2626
// Sampler decides whether a trace should be sampled and exported.
2727
type Sampler interface {
28+
// DO NOT CHANGE: any modification will not be backwards compatible and
29+
// must never be done outside of a new major release.
30+
31+
// ShouldSample returns a SamplingResult based on a decision made from the
32+
// passed parameters.
2833
ShouldSample(parameters SamplingParameters) SamplingResult
34+
// DO NOT CHANGE: any modification will not be backwards compatible and
35+
// must never be done outside of a new major release.
36+
37+
// Description returns information describing the Sampler.
2938
Description() string
39+
// DO NOT CHANGE: any modification will not be backwards compatible and
40+
// must never be done outside of a new major release.
3041
}
3142

3243
// SamplingParameters contains the values passed to a Sampler.

sdk/trace/span.go

+4
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ import (
3434
// ReadOnlySpan allows reading information from the data structure underlying a
3535
// trace.Span. It is used in places where reading information from a span is
3636
// necessary but changing the span isn't necessary or allowed.
37+
//
38+
// Warning: methods may be added to this interface in minor releases.
3739
type ReadOnlySpan interface {
3840
// Name returns the name of the span.
3941
Name() string
@@ -88,6 +90,8 @@ type ReadOnlySpan interface {
8890
// This interface exposes the union of the methods of trace.Span (which is a
8991
// "write-only" span) and ReadOnlySpan. New methods for writing or reading span
9092
// information should be added under trace.Span or ReadOnlySpan, respectively.
93+
//
94+
// Warning: methods may be added to this interface in minor releases.
9195
type ReadWriteSpan interface {
9296
trace.Span
9397
ReadOnlySpan

sdk/trace/span_exporter.go

+8
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ import "context"
1919
// SpanExporter handles the delivery of spans to external receivers. This is
2020
// the final component in the trace export pipeline.
2121
type SpanExporter interface {
22+
// DO NOT CHANGE: any modification will not be backwards compatible and
23+
// must never be done outside of a new major release.
24+
2225
// ExportSpans exports a batch of spans.
2326
//
2427
// This function is called synchronously, so there is no concurrency
@@ -31,9 +34,14 @@ type SpanExporter interface {
3134
// returned by this function are considered unrecoverable and will be
3235
// reported to a configured error Handler.
3336
ExportSpans(ctx context.Context, spans []ReadOnlySpan) error
37+
// DO NOT CHANGE: any modification will not be backwards compatible and
38+
// must never be done outside of a new major release.
39+
3440
// Shutdown notifies the exporter of a pending halt to operations. The
3541
// exporter is expected to preform any cleanup or synchronization it
3642
// requires while honoring all timeouts and cancellations contained in
3743
// the passed context.
3844
Shutdown(ctx context.Context) error
45+
// DO NOT CHANGE: any modification will not be backwards compatible and
46+
// must never be done outside of a new major release.
3947
}

sdk/trace/span_processor.go

+11
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,20 @@ import (
2424
// and end of a Span's lifecycle, and are called in the order they are
2525
// registered.
2626
type SpanProcessor interface {
27+
// DO NOT CHANGE: any modification will not be backwards compatible and
28+
// must never be done outside of a new major release.
29+
2730
// OnStart is called when a span is started. It is called synchronously
2831
// and should not block.
2932
OnStart(parent context.Context, s ReadWriteSpan)
33+
// DO NOT CHANGE: any modification will not be backwards compatible and
34+
// must never be done outside of a new major release.
3035

3136
// OnEnd is called when span is finished. It is called synchronously and
3237
// hence not block.
3338
OnEnd(s ReadOnlySpan)
39+
// DO NOT CHANGE: any modification will not be backwards compatible and
40+
// must never be done outside of a new major release.
3441

3542
// Shutdown is called when the SDK shuts down. Any cleanup or release of
3643
// resources held by the processor should be done in this call.
@@ -41,12 +48,16 @@ type SpanProcessor interface {
4148
// All timeouts and cancellations contained in ctx must be honored, this
4249
// should not block indefinitely.
4350
Shutdown(ctx context.Context) error
51+
// DO NOT CHANGE: any modification will not be backwards compatible and
52+
// must never be done outside of a new major release.
4453

4554
// ForceFlush exports all ended spans to the configured Exporter that have not yet
4655
// been exported. It should only be called when absolutely necessary, such as when
4756
// using a FaaS provider that may suspend the process after an invocation, but before
4857
// the Processor can export the completed spans.
4958
ForceFlush(ctx context.Context) error
59+
// DO NOT CHANGE: any modification will not be backwards compatible and
60+
// must never be done outside of a new major release.
5061
}
5162

5263
type spanProcessorState struct {

trace/trace.go

+6
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,8 @@ func (sc SpanContext) MarshalJSON() ([]byte, error) {
337337
// and timed operation of a workflow that is traced. A Tracer is used to
338338
// create a Span and it is then up to the operation the Span represents to
339339
// properly end the Span when the operation itself ends.
340+
//
341+
// Warning: methods may be added to this interface in minor releases.
340342
type Span interface {
341343
// End completes the Span. The Span is considered complete and ready to be
342344
// delivered through the rest of the telemetry pipeline after this method
@@ -478,6 +480,8 @@ func (sk SpanKind) String() string {
478480
}
479481

480482
// Tracer is the creator of Spans.
483+
//
484+
// Warning: methods may be added to this interface in minor releases.
481485
type Tracer interface {
482486
// Start creates a span and a context.Context containing the newly-created span.
483487
//
@@ -496,6 +500,8 @@ type Tracer interface {
496500
}
497501

498502
// TracerProvider provides access to instrumentation Tracers.
503+
//
504+
// Warning: methods may be added to this interface in minor releases.
499505
type TracerProvider interface {
500506
// Tracer creates an implementation of the Tracer interface.
501507
// The instrumentationName must be the name of the library providing

0 commit comments

Comments
 (0)