otel

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 12, 2022 License: MIT Imports: 3 Imported by: 0

README

servicectx + opentelemetry integration

This package contains utility functions for integration with OpenTelemetry.

It facilitates the injection of properties into OpenTelemetry Baggage and reading them back.

Documentation

Overview

Example

An example HTTP client and server exchanging custom properties through opentelemetry baggage

// a client sends a request with a custom API url;
// this property is passed in HTTP headers as part of an opentelemetry baggage
props := servicectx.New()
props.Set("api", "url", "http://my-custom-api")

propagator := propagation.TextMapPropagator(propagation.Baggage{})
ctx := InjectIntoContext(context.Background(), props)
req := httptest.NewRequest(http.MethodGet, "/?username=Alex", nil)
propagator.Inject(ctx, propagation.HeaderCarrier(req.Header))

// a server handles this request, modifies the API url accordingly,
// and then also passes these custom properties in a remote call
handler := func(w http.ResponseWriter, r *http.Request) {
	// parse the properties from opentelemetry baggage and add them to a Go context for use in application code
	ctx := propagator.Extract(r.Context(), propagation.HeaderCarrier(r.Header))
	bag := baggage.FromContext(ctx)
	ctx = FromBaggage(bag).InjectIntoContext(ctx)

	// an apiCall is probably defined in another package;
	// its `username` argument is a part of business logic,
	// but properties, being an arbitrary ancillary data, are passed within the context.
	apiCall := func(ctx context.Context, username string) string {
		props := servicectx.FromContext(ctx)
		// the remote API address is taken from these properties (or default URL is used instead).
		url := props.Get("api", "url", "http://api")
		url += "?username=" + username
		apiRequest, _ := http.NewRequest("GET", url, nil)

		// the props are propagated further through opentelemetry baggage
		propagator.Inject(ctx, propagation.HeaderCarrier(apiRequest.Header))

		// ...execute remote call
		// _, _ = http.DefaultClient.Do(apiRequest)

		return fmt.Sprintf("Calling remote API at %s with baggage: %s", url, apiRequest.Header.Get("baggage"))
	}

	apiCallResult := apiCall(ctx, r.URL.Query().Get("username"))
	w.Write([]byte(apiCallResult))
}

w := httptest.NewRecorder()
handler(w, req)
res := w.Result()
responseBytes, _ := ioutil.ReadAll(res.Body)

fmt.Println(string(responseBytes))
Output:

Calling remote API at http://my-custom-api?username=Alex with baggage: x-service-api-url=http%3A%2F%2Fmy-custom-api

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func CreateBaggageMembers

func CreateBaggageMembers(props servicectx.Properties) []baggage.Member

CreateBaggageMembers creates opentelemetry "baggage members" from properties

func FromBaggage

func FromBaggage(bag baggage.Baggage) servicectx.Properties

FromBaggage retries properties from baggage

Example
prop := propagation.TextMapPropagator(propagation.Baggage{})
req, _ := http.NewRequest("GET", "http://opentelemetry.com", nil)
req.Header.Set("baggage", "x-service-a-version=2.0,x-service-b-branch=bugfix-123")

ctx := context.Background()
ctx = prop.Extract(ctx, propagation.HeaderCarrier(req.Header))
bag := baggage.FromContext(ctx)
props := FromBaggage(bag)

fmt.Println("service A version:", props.Get("a", "version", ""))
fmt.Println("service B branch:", props.Get("b", "branch", ""))
Output:

service A version: 2.0
service B branch: bugfix-123

func FromContextAndBaggage added in v0.2.0

func FromContextAndBaggage(ctx context.Context, bag baggage.Baggage) servicectx.Properties

FromContextAndBaggage retrieves properties from Go context and from baggage. This is convenient when the properties can be set both in application code via context and from outside world by opentelemetry. The properties from Go context have a preference over the baggage.

func InjectIntoBaggage

func InjectIntoBaggage(bag baggage.Baggage, props servicectx.Properties) baggage.Baggage

InjectIntoBaggage adds properties into opentelemetry baggage

Example
props := servicectx.New()
props.Set("a", "version", "1.0")
props.Set("b", "branch", "feature-123")

propagator := propagation.Baggage{}
bag := InjectIntoBaggage(baggage.Baggage{}, props)
ctx := baggage.ContextWithBaggage(context.Background(), bag)
req, _ := http.NewRequest("GET", "http://opentelemetry.com", nil)
propagator.Inject(ctx, propagation.HeaderCarrier(req.Header))

fmt.Println(req.Header.Get("baggage"))
Output:

x-service-a-version=1.0,x-service-b-branch=feature-123

func InjectIntoContext added in v0.2.0

func InjectIntoContext(ctx context.Context, props servicectx.Properties) context.Context

InjectIntoContext adds the properties into OpenTelemetry Baggage, then adds the baggage into the context.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL