Giter Club home page Giter Club logo

opencensus-go's Introduction

Warning

OpenCensus and OpenTracing have merged to form OpenTelemetry, which serves as the next major version of OpenCensus and OpenTracing.

OpenTelemetry has now reached feature parity with OpenCensus, with tracing and metrics SDKs available in .NET, Golang, Java, NodeJS, and Python. All OpenCensus Github repositories, except census-instrumentation/opencensus-python, will be archived on July 31st, 2023. We encourage users to migrate to OpenTelemetry by this date.

To help you gradually migrate your instrumentation to OpenTelemetry, bridges are available in Java, Go, Python, and JS. Read the full blog post to learn more.

OpenCensus Libraries for Go

Build Status Windows Build Status GoDoc Gitter chat

OpenCensus Go is a Go implementation of OpenCensus, a toolkit for collecting application performance and behavior monitoring data. Currently it consists of three major components: tags, stats and tracing.

OpenCensus and OpenTracing have merged to form OpenTelemetry, which serves as the next major version of OpenCensus and OpenTracing. OpenTelemetry will offer backwards compatibility with existing OpenCensus integrations, and we will continue to make security patches to existing OpenCensus libraries for two years. Read more about the merger here.

Installation

$ go get -u go.opencensus.io

The API of this project is still evolving, see: Deprecation Policy. The use of vendoring or a dependency management tool is recommended.

Prerequisites

OpenCensus Go libraries require Go 1.8 or later.

Getting Started

The easiest way to get started using OpenCensus in your application is to use an existing integration with your RPC framework:

If you're using a framework not listed here, you could either implement your own middleware for your framework or use custom stats and spans directly in your application.

Exporters

OpenCensus can export instrumentation data to various backends. OpenCensus has exporter implementations for the following, users can implement their own exporters by implementing the exporter interfaces (stats, trace):

Overview

OpenCensus Overview

In a microservices environment, a user request may go through multiple services until there is a response. OpenCensus allows you to instrument your services and collect diagnostics data all through your services end-to-end.

Tags

Tags represent propagated key-value pairs. They are propagated using context.Context in the same process or can be encoded to be transmitted on the wire. Usually, this will be handled by an integration plugin, e.g. ocgrpc.ServerHandler and ocgrpc.ClientHandler for gRPC.

Package tag allows adding or modifying tags in the current context.

ctx, err := tag.New(ctx,
	tag.Insert(osKey, "macOS-10.12.5"),
	tag.Upsert(userIDKey, "cde36753ed"),
)
if err != nil {
	log.Fatal(err)
}

Stats

OpenCensus is a low-overhead framework even if instrumentation is always enabled. In order to be so, it is optimized to make recording of data points fast and separate from the data aggregation.

OpenCensus stats collection happens in two stages:

  • Definition of measures and recording of data points
  • Definition of views and aggregation of the recorded data

Recording

Measurements are data points associated with a measure. Recording implicitly tags the set of Measurements with the tags from the provided context:

stats.Record(ctx, videoSize.M(102478))

Views

Views are how Measures are aggregated. You can think of them as queries over the set of recorded data points (measurements).

Views have two parts: the tags to group by and the aggregation type used.

Currently three types of aggregations are supported:

  • CountAggregation is used to count the number of times a sample was recorded.
  • DistributionAggregation is used to provide a histogram of the values of the samples.
  • SumAggregation is used to sum up all sample values.
distAgg := view.Distribution(1<<32, 2<<32, 3<<32)
countAgg := view.Count()
sumAgg := view.Sum()

Here we create a view with the DistributionAggregation over our measure.

if err := view.Register(&view.View{
	Name:        "example.com/video_size_distribution",
	Description: "distribution of processed video size over time",
	Measure:     videoSize,
	Aggregation: view.Distribution(1<<32, 2<<32, 3<<32),
}); err != nil {
	log.Fatalf("Failed to register view: %v", err)
}

Register begins collecting data for the view. Registered views' data will be exported via the registered exporters.

Traces

A distributed trace tracks the progression of a single user request as it is handled by the services and processes that make up an application. Each step is called a span in the trace. Spans include metadata about the step, including especially the time spent in the step, called the span’s latency.

Below you see a trace and several spans underneath it.

Traces and spans

Spans

Span is the unit step in a trace. Each span has a name, latency, status and additional metadata.

Below we are starting a span for a cache read and ending it when we are done:

ctx, span := trace.StartSpan(ctx, "cache.Get")
defer span.End()

// Do work to get from cache.

Propagation

Spans can have parents or can be root spans if they don't have any parents. The current span is propagated in-process and across the network to allow associating new child spans with the parent.

In the same process, context.Context is used to propagate spans. trace.StartSpan creates a new span as a root if the current context doesn't contain a span. Or, it creates a child of the span that is already in current context. The returned context can be used to keep propagating the newly created span in the current context.

ctx, span := trace.StartSpan(ctx, "cache.Get")
defer span.End()

// Do work to get from cache.

Across the network, OpenCensus provides different propagation methods for different protocols.

Execution Tracer

With Go 1.11, OpenCensus Go will support integration with the Go execution tracer. See Debugging Latency in Go for an example of their mutual use.

Profiles

OpenCensus tags can be applied as profiler labels for users who are on Go 1.9 and above.

ctx, err = tag.New(ctx,
	tag.Insert(osKey, "macOS-10.12.5"),
	tag.Insert(userIDKey, "fff0989878"),
)
if err != nil {
	log.Fatal(err)
}
tag.Do(ctx, func(ctx context.Context) {
	// Do work.
	// When profiling is on, samples will be
	// recorded with the key/values from the tag map.
})

A screenshot of the CPU profile from the program above:

CPU profile

Deprecation Policy

Before version 1.0.0, the following deprecation policy will be observed:

No backwards-incompatible changes will be made except for the removal of symbols that have been marked as Deprecated for at least one minor release (e.g. 0.9.0 to 0.10.0). A release removing the Deprecated functionality will be made no sooner than 28 days after the first release in which the functionality was marked Deprecated.

opencensus-go's People

Contributors

acetechnologist avatar basvanbeek avatar bogdandrutu avatar bpot avatar bvwells avatar cooldarkdryplace avatar dashpole avatar diogenes avatar evankanderson avatar feloy avatar ferhatelmas avatar freddygv avatar howardjohn avatar hyangah avatar ian-mi avatar jcd2 avatar jeanbza avatar jkohen avatar johanbrandhorst avatar jsuereth avatar odeke-em avatar punya avatar purple4reina avatar rakyll avatar rghetia avatar rogpeppe avatar savaki avatar semistrict avatar smhendrickson avatar songy23 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

opencensus-go's Issues

Remove force collection

Force collection became identical to the subscription after subscription via channels is removed. Remove force collection related APIs.

tag: add pprof.Do equivalent to record profiler samples with a tag map

Add a pprof.Do like utility to record profiler samples with a given tag map. Do looks for the tags inside the given context and sets them as pprof labels. Any goroutine started in f needs to propagate the tag map via c in order to be able to keep setting the labels in the new goroutines.

func Do(ctx context.Context, m *Map, f func(c context.Context))

Rename aggregations and windows

Aggregation implementations are using "Aggregation" as a prefix, Window implementations are using "Window" as a prefix. In Go, we prefer the natural language order.

Some example type names with the new order:

type CountAggregation struct{}
type DistributionAggregation struct{}

type SlidingTimeWindow struct {}
type SlidingCountWindow struct {}

exporter/stackdriver: missing distribution value for CountAggregation

Consider the following view:

        view := stats.NewView(
		"my.org/views/video_size_cum",
		"processed video size over time",
		nil,
		videoSize,
		stats.CountAggregation{},
		stats.Cumulative{},
	)

It fails with:

2017/11/21 14:52:52 Failed to export to Stackdriver Monitoring: rpc error: code = InvalidArgument desc = Request was missing field timeSeries[0].points[0].distributionValue.

trace: reduce the number of the printing APIs

The trace package currently allows users to print in a few different ways:

func LazyPrint(ctx context.Context, str fmt.Stringer)
func LazyPrintWithAttributes(ctx context.Context, attributes []Attribute, str fmt.Stringer)
func LazyPrintf(ctx context.Context, format string, a ...interface{})
func LazyPrintfWithAttributes(ctx context.Context, attributes []Attribute, format string, a ...interface{})
func Print(ctx context.Context, str string)
func PrintWithAttributes(ctx context.Context, attributes []Attribute, str string)

Instead of giving users different combinations of these options, we should provide a printing entry type and allow user to provide their options via the new type.

type Entry struct {
	Text       fmt.Stringer
	Attributes []Attribute
}

func LazyPrint(ctx context.Context, e Entry)

Then, we can provide maybe one other option for convience:

func LazyPrintf(ctx context.Context, format string, a ...interface{})

Users who doesn't want lazy formatting can always implement their own fmt.Stringer to format it at the point LazyPrint is called.

/cc @jcd2 @bogdandrutu

exporter/stackdriver: creation fails with AlreadyExists for new metrics

Metrics description creation is failing with "AlreadyExists" if the metric descriptor is being created for the first time:

Wait longer than the reporting duration...
2017/11/21 15:03:27 Failed to export to Stackdriver Monitoring: rpc error: code = AlreadyExists desc = Errors during metric descriptor creation: {(metric: custom.googleapis.com/opencensus%2Fmy.org%2Fviews%2Fvideoooosizeovertime, error: The metric already exists.)}.

Support Go 1.6?

gRPC and AppEngine requires 1.6 support to be around for a little while. Support 1.6 by removing the sort.Slice and context package dependencies.

See also grpc/grpc-go#1603.

Finalize the case for typed keys

Tags allow typed keys such (e.g. StringKey) but there is interest to drop typed keys and have StringKey as the only option. Determine the future for the tag package and remove the unnecessary abstractions before freezing the APIs.

/cc @dinooliva

Measures should return unit

All measure types need to be able to report their unit. Enforce measures to return a unit as string.

type Measure interface {
     Name() string
     Unit() string
}

Hide non-user facing testing utilities

ContainsRow and EqualRows are both utilities to support the stats package tests. Hide them from the user, given they will never be required by the end user.

NewMap should take a context

We would like to avoid users accidentally dropping the tags in the current context. Make NewMap working against a context.Context rather than an initial tag.Map.

func NewMap(ctx context.Context, m ...Mutator)

Remove ValueAsString?

func (k *KeyString) ValueAsString(b []byte) string

is not accessing any of the Key fields and is doing a redundant job of casting a []byte into string.

/cc @acetechnologist

FindX should return boolean rather than error

All FindX functions are looking for an item in the map and return and error if not found. We should instead return a boolean for the convince of the user to handle nonexistence cases.

func FindMeasure(name string) (m Measure, ok bool)

func FindView(name string) (v *View, ok bool)

Think about tags.Set design

It's unclear whether tags.Set is intended to be mutable or immutable. @rakyll mentioned wanting to hide the encoding details from the user, so I recommended the following:

type Set map[Key]Value

func (set Set) Copy() Set

type Value struct {
  b []byte
}

func StringValue(s string) Value {
  return Value{[]byte(s)}
}

func Int64Value(i int64) Value {
  return Value{[]byte{/* encode the int */}}
}

Introduce exporters

Rather than allowing users access to the low-level buffer, introduce exporters and report the view data via the registered ones.

// Exporter exports the collected records as view data.
type Exporter interface {
	Export(viewData *ViewData)
}

// RegisterExporter registers an exporter.
func RegisterExporter(name string, e Exporter)

// UnregisterExporter unregisters an exporter.
func UnregisterExporter(name string)

As a follow up, we also need a rethinking of the current subscription model. In order to access to the view data of a view, you currently need to subscribe to a view after it is registered globally. Regardless of the registration status, view data can still be collected by force collection. Instead of having both methods available, we should either allow users to force collect or subscribe but not both.

Rename utility encoder/decoder

ToOrderedTagsSlice can be redesigned into:

func DecodeOrderedTags(buf []byte, keys []Key) []Tag

ToValuesString can be redesigned into:

func EncodeOrderedTags(set *Set, keys []Key) []byte

We should also consider whether we need to provide these utilities from the tags package.

stats: define Measurement as a struct

stats.Measurement is a value with a defined set of types, so it should be defined as a struct that can only be constructed inside the stats package, not as an interface with an unexported method.

Sketch:

type Measurement struct {
  m interface{} // one of *Float64Measure or *Int64Measure
  v interface{} // one of int64 or float64
}

exporter/stackdriver: add labels

Metrics are uploaded without the recorded tags being attached as Stackdriver Monitoring labels. Fix the exporter by adding the labels.

Setup vanity import paths

To reduce to dependencies to a specific git provider and to enhance the the current long and noisy import path, setup a vanity URL for the package and enforce the vanity URL everywhere. The vanity URL is either going to be "go.opencensus.io" or "opencensus.io/go".

Rename TagSet to Set

tags.TagSet is repeating the "tag" twice and we don't like to stuttering in Go. Rename it to Set.

exporter/stackdriver: MetricDescriptor name should be under domain "custom.googleapis.com/opencensus/"

Thanks @bogdandrutu for catching this.

For the Stackdriver Stats exporter, the name of MetricDescriptor needs to be under "custom.googleapis.com/opencensus/". The format of the whole name should be String.format("projects/%s/metricDescriptors/custom.googleapis.com%%2Fopencensus%%2F%s", projectId, viewName.replace("/", "%2F")). Stackdriver might return a permission denied error if we don't follow the name convention.

See https://github.com/census-instrumentation/opencensus-java/pull/827/files#diff-d2886f5b11a5e3be7a00a8f5fff5a1f0R84 for changes to Java exporter. Also refer to https://cloud.google.com/monitoring/custom-metrics/creating-metrics#custom_metric_names.

exporter/stackdriver: distribution range is not allowed

Consider the following view:

        // Create view to see the processed video size cumulatively.
	view := stats.NewView(
		"my.org/views/video_size_cum",
		"processed video size over time",
		nil,
		videoSize,
		stats.DistributionAggregation([]float64{0, 1 << 16, 1 << 32}),
		stats.Cumulative{},
	)

While exporting, it errors with:

Wait longer than the reporting duration...
2017/11/21 13:45:34 Failed to export to Stackdriver Monitoring: rpc error: code = InvalidArgument desc = Field timeSeries[0].points[0].distributionValue.range is not allowed: Distribution range is not yet supported.

Rename AggregationValue to AggregationData

To be more consistent with the Java library, rename AggregationValue to AggregationData.

All types named after AggregationValue will also be renamed:

  • CountAggregationValue -> CountData
  • DistributionAggregationValue -> DistributionData

Provide View related APIs as View methods

Currently the stats API contains quite a few package-level APIs works primarily with a View instance.

func RegisterView(v View) error
func RetrieveData(v View) ([]*Row, error)
func StopForcedCollection(v View) error
func SubscribeToView(v View, c chan *ViewData) error
func UnregisterView(v View) error
func UnsubscribeFromView(v View, c chan *ViewData) error

They could instead accept a View as a receiver. There are two advantages: (a) some function names will be shorter because we will be able to drop the "View" suffix from their names, (b) godoc will render them under the View type and it is easy for their discoverability.

func (v View) Register() error
func (v View) RetrieveData() ([]*Row, error)
func (v View) StopForcedCollection() error
func (v View) Subscribe(c chan *ViewData) error
func (v View) Unregister() error
func (v View) Unsubscribe(c chan *ViewData) error

Happy to send a PR.

/cc @acetechnologist @bogdandrutu

Remove unnecessary constructors

There are lightweight types such as WindowSlidingTime, WindowSlidingCount, and WindowCumulative that are not complicated enough to require a constructor. Remove NewWindowCumulative and make the zero value useful, remove NewWindowSlidingCount and export fields on WindowSlidingCount, and remove NewWindowSlidingTime and export the fields of WindowSlidingTime.

/cc @hyangah @bogdandrutu

Complicated sequence is required to collect data from views

Currently, in the stats package:

  • Views are required to be initialized, registered and subscribed to in order to collect data via exporters.
  • Views are also automatically registered if they are subscribed to after initialization.
  • Views are required to be initialized, registered and force collected in order to collect data via force collection.

This is a complicated sequence of actions required from the user and it is easy to get it wrong. It seems like registration can be handled as a part of subscription and force collection.

I am suggesting the following sequence instead:

  • Views are required to be initialized and subscribed to in order to collect data. If a view with the same name exists, subscription returns an error. Unsubscribe to free the name.
  • Views are required to be initialized and force collected from in order to collect data. If a view with the same name exists, force collection API returns an error. Stop force collection to free the name.

Thoughts?

/cc @dinooliva @bogdandrutu

Provide composite gRPC stats handler

Provide a stats handler that does enables both stats and tracing. Users who prefer not to have both can depend on grpcstats and grpctrace packages individually.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.