instana

package module
v1.16.0 Latest Latest
Warning

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

Go to latest
Published: Jul 21, 2020 License: MIT Imports: 37 Imported by: 88

README

golang banner 2017-07-11

Instana Go Sensor

go-sensor requires Go version 1.9 or greater.

The Instana Go sensor consists of two parts:

  • metrics sensor
  • OpenTracing tracer
  • AutoProfile™ continuous profiler

Build Status GoDoc OpenTracing Badge

Table of Contents

Installation

To add Instana Go sensor to your service run:

$ go get github.com/instana/go-sensor

To activate background metrics collection, add following line at the beginning of your service initialization (typically this would be the beginning of your main() function):

func main() {
	instana.InitSensor(instana.DefaultOptions())

	// ...
}

The instana.InitSensor() function takes an *instana.Options struct with the following optional fields:

  • Service - global service name that will be used to identify the program in the Instana backend
  • AgentHost, AgentPort - default to localhost:42699, set the coordinates of the Instana proxy agent
  • LogLevel - one of Error, Warn, Info or Debug
  • EnableAutoProfile - enables automatic continuous process profiling when true
  • MaxBufferedSpans - the maximum number of spans to buffer
  • ForceTransmissionStartingAt - the number of spans to collect before flushing the buffer to the agent
  • MaxBufferedProfiles - the maximum number of profiles to buffer
  • IncludeProfilerFrames - whether to include profiler calls into the profile or not

Once initialized, the sensor performs a host agent lookup using following list of addresses (in order of priority):

  1. The value of INSTANA_AGENT_HOST env variable
  2. localhost
  3. Default gateway

Once a host agent found listening on port 42699 (or the port specified in INSTANA_AGENT_PORT env variable) the sensor begins collecting in-app metrics and sending them to the host agent.

Running on AWS Fargate

To use Instana Go sensor for monitoring a service running on AWS Fargate make sure that you have INSTANA_ENDPOINT_URL and INSTANA_AGENT_KEY env variables set in your task definition. Note that the INSTANA_AGENT_HOST and INSTANA_AGENT_PORT env variables will be ignored in this case. Please refer to Instana documentation for detailed explanation on how to do this.

Using Instana to gather process metrics only

To use sensor without tracing ability, import the instana package and add the following line at the beginning of your main() function:

instana.InitSensor(opt)

Common Operations

The Instana Go sensor offers a set of quick features to support tracing of the most common operations like handling HTTP requests and executing HTTP requests.

To create an instance of the Instana sensor just request a new instance using the instana.NewSensor factory method and providing the name of the application. It is recommended to use a single instance only. The sensor implementation is fully thread-safe and can be shared by multiple threads.

var sensor = instana.NewSensor("my-service")

A full example can be found under the examples folder in example/webserver/instana/http.go.

Setting the sensor log output

The Go sensor uses a leveled logger to log internal errors and diagnostic information. The default logger.Logger uses log.Logger configured with log.Lstdflags as a backend and writes messages to os.Stderr. By default this logger only prints out the ERROR level messages unless the environment variable INSTANA_DEBUG is set.

To change the min log level in runtime it is recommended to configure and inject an instance of instana.LeveledLogger instead of using the deprecated instana.SetLogLevel() method:

l := logger.New(log.New(os.Stderr, "", os.Lstdflags))
instana.SetLogger(l)

// ...

l.SetLevel(logger.WarnLevel)

The logger.LeveledLogger interface is implemented by such popular logging libraries as github.com/sirupsen/logrus and go.uber.org/zap, so they can be used as a replacement.

Note: the value of INSTANA_DEBUG environment variable does not affect custom loggers. You'd need to explicitly check whether it's set and enable the debug logging while onfiguring your logger:

import (
	instana "github.com/instana/go-sensor"
	"github.com/sirupsen/logrus"
)

func main() {	
	// initialize Instana sensor
	instana.InitSensor(&instana.Options{Service: SERVICE})

	// initialize and configure the logger
	logger := logrus.New()
	logger.Level = logrus.InfoLevel

	// check if INSTANA_DEBUG is set and set the log level to DEBUG if needed
	if _, ok := os.LookupEnv("INSTANA_DEBUG"); ok {
		logger.Level = logrus.DebugLevel
	}

	// use logrus to log the Instana Go sensor messages
	instana.SetLogger(logger)

	// ...
}

The Go sensor AutoProfile™ by default uses the same logger as the sensor itself, however it can be configured to use its own, for example to write messages with different tags/prefix or use a different logging level. The following snippet demonstrates how to configure the custom logger for autoprofiler:

autoprofile.SetLogger(autoprofileLogger)
Trace Context Propagation

Instana Go sensor provides an API to propagate the trace context throughout the call chain:

func MyFunc(ctx context.Context) {
	var spanOpts []ot.StartSpanOption

	// retrieve parent span from context and reference it in the new one
	if parent, ok := instana.SpanFromContext(ctx); ok {
	    spanOpts = append(spanOpts, ot.ChildOf(parent.Context()))
	}

	// start a new span
	span := tracer.StartSpan("my-func", spanOpts...)
	defer span.Finish()

	// and use it as a new parent inside the context
	SubCall(instana.ContextWithSpan(ctx, span))
}
HTTP servers and clients
Instrumenting HTTP request handling

With support to wrap a http.HandlerFunc, Instana quickly adds the possibility to trace requests and collect child spans, executed in the context of the request span.

Minimal changes are required for Instana to be able to capture the necessary information. By simply wrapping the currently existing http.HandlerFunc Instana collects and injects necessary information automatically.

That said, a simple handler function like the following will simple be wrapped and registered like normal.

The following example code demonstrates how to instrument an HTTP handler using instana.TracingHandlerFunc():

sensor := instana.NewSensor("my-http-server")

http.HandleFunc("/", instana.TracingHandlerFunc(sensor, "/", func(w http.ResponseWriter, req *http.Request) {
	// Extract the parent span and use its tracer to initialize any child spans to trace the calls
	// inside the handler, e.g. database queries, 3rd-party API requests, etc.
	if parent, ok := instana.SpanFromContext(req.Context()); ok {
		sp := parent.Tracer().StartSpan("index")
		defer sp.Finish()
	}

	// ...
}))

In case your handler is implemented as an http.Handler, pass its ServeHTTP method instead:

h := http.FileServer(http.Dir("./"))
http.HandleFunc("/files", instana.TracingHandlerFunc(sensor, "index", h.ServeHTTP))
Instrumenting HTTP request execution

Requesting data or information from other, often external systems, is commonly implemented through HTTP requests. To make sure traces contain all spans, especially over all the different systems, certain span information have to be injected into the HTTP request headers before sending it out. Instana's Go sensor provides support to automate this process as much as possible.

To have Instana inject information into the request headers, create the http.Client, wrap its Transport with instana.RoundTripper() and use it as in the following example.

req, err := http.NewRequest("GET", url, nil)
client := &http.Client{
	Transport: instana.RoundTripper(sensor, nil),
}

ctx := instana.ContextWithSpan(context.Background(), parentSpan)
resp, err := client.Do(req.WithContext(ctx))

The provided parentSpan is the incoming request from the request handler (see above) and provides the necessary tracing and span information to create a child span and inject it into the request.

Database Calls

The Go sensor provides instana.InstrumentSQLDriver() and instana.WrapSQLConnector() (since Go v1.10+) to instrument SQL database calls made with database/sql. The tracer will then automatically capture the Query and Exec calls, gather information about the query, such as statement, execution time, etc. and forward them to be displayed as a part of the trace.

Instrumenting sql.Open()

To instrument a database driver, register it using instana.InstrumentSQLDriver() first and replace the call to sql.Open() with instana.SQLOpen(). Here is an example on how to do this for github.com/lib/pq PostgreSQL driver:

// Create a new instana.Sensor instance
sensor := instana.NewSensor("my-daatabase-app")

// Instrument the driver
instana.InstrumentSQLDriver(sensor, "postgres", &pq.Driver{})

// Create an instance of *sql.DB to use for database queries
db, err := instana.SQLOpen("postgres", "postgres://...")

You can find the complete example in the Examples section of package documentation on pkg.go.dev.

The instrumented driver is registered with the name <original_name>_with_instana, e.g. in the example above the name would be postgres_with_instana.

Instrumenting sql.OpenDB()

Starting from Go v1.10 database/sql provides a new way to initialize *sql.DB that does not require the use of global driver registry. If the database driver library provides a type that satisfies the database/sql/driver.Connector interface, it can be used to create a database connection.

To instrument a driver.Connector instance, wrap it using instana.WrapSQLConnector(). Here is an example on how this can be done for github.com/go-sql-driver/mysql/ MySQL driver:

// Create a new instana.Sensor instance
sensor := instana.NewSensor("my-daatabase-app")

// Initialize a new connector
connector, err := mysql.NewConnector(cfg)
// ...

// Wrap the connector before passing it to sql.OpenDB()
db, err := sql.OpenDB(instana.WrapSQLConnector(sensor, "mysql://...", connector))

You can find the complete example in the Examples section of package documentation on pkg.go.dev.

GRPC servers and clients

github.com/instana/go-sensor/instrumentation/instagrpc provides both unary and stream interceptors to instrument GRPC servers and clients that use google.golang.org/grpc.

Kafka producers and consumers

github.com/instana/go-sensor/instrumentation/instasarama provides both unary and stream interceptors to instrument Kafka producers and consumers built on top of github.com/Shopify/sarama.

OpenTracing

In case you want to use the OpenTracing tracer, it will automatically initialize the sensor and thus also activate the metrics stream. To activate the global tracer, run for example

ot.InitGlobalTracer(instana.NewTracerWithOptions(&instana.Options{
	Service:  SERVICE,
	LogLevel: instana.DEBUG,
}))

in your main function. The tracer takes the same options that the sensor takes for initialization, described above.

The tracer is able to protocol and piggyback OpenTracing baggage, tags and logs. Only text mapping is implemented yet, binary is not supported. Also, the tracer tries to map the OpenTracing spans to the Instana model based on OpenTracing recommended tags. See simple.go example for details on how recommended tags are used.

The Instana tracer will remap OpenTracing HTTP headers into Instana Headers, so parallel use with some other OpenTracing model is not possible. The Instana tracer is based on the OpenTracing Go basictracer with necessary modifications to map to the Instana tracing model. Also, sampling isn't implemented yet and will be focus of future work.

W3C Trace Context

The Go sensor library fully supports the W3C Trace Context standard:

  • An instrumented http.Client sends the traceparent and tracestate headers, updating them with the exit span ID and flags.
  • Any http.Handler instrumented with instana.TracingHandlerFunc() picks up the trace context passed in the traceparent header, potentially restoring the trace from tracestate even if the upstream service is not instrumented with Instana.

Events API

The sensor, be it instantiated explicitly or implicitly through the tracer, provides a simple wrapper API to send events to Instana as described in its documentation.

To learn more, see the Events API document in this repository.

AutoProfile™

AutoProfile™ generates and reports process profiles to Instana. Unlike development-time and on-demand profilers, where a user must manually initiate profiling, AutoProfile™ automatically schedules and continuously performs profiling appropriate for critical production environments.

Activation from within the application code

To enable continuous profiling for your service provide EnableAutoProfile: true while initializing the sensor:

func main() {
	instana.InitSensor(&instana.Options{
		EnableAutoProfile: true,
		// ...other options
	})

	// ...
}

To temporarily turn AutoProfile™ on and off from your code, call autoprofile.Enable() and autoprofile.Disable().

Activation without code changes

To enable AutoProfile™ for an app without code changes, set INSTANA_AUTO_PROFILE=true env variable. Note that this value takes precedence and overrides any attempt to disable profiling from inside the application code.

Examples

Following examples are included in the example folder:

  • ot-simple/simple.go - Demonstrates basic usage of the tracer
  • database/elasticsearch.go - Demonstrates how to instrument a database client (Elasticsearch in this case)
  • many.go - Demonstrates how to create nested spans within the same execution context
  • event/ - Demonstrates usage of the Events API
  • autoprofile/ - Demonstrates usage of the AutoProfile™

For more examples please consult the godoc.

Documentation

Overview

Example (HttpRoutePatternMatching)

This example demonstrates how to instrument a 3rd-party HTTP router that uses pattern matching to make sure the original path template is forwarded to Instana

package main

import (
	"log"
	"net/http"

	instana "github.com/instana/go-sensor"
)

func main() {
	sensor := instana.NewSensor("my-http-server")

	// Initialize your router. Here for simplicity we use stdlib http.ServeMux, however you
	// can use any router that supports http.Handler/http.HandlerFunc, such as github.com/gorilla/mux
	r := http.NewServeMux()

	// Wrap the handler using instana.TracingHandlerFunc() and pass the path template
	// used to route requests to it. This value will be attached to the span and displayed
	// in UI as `http.path_tpl` if the request path is different (we assume that this request
	// has been routed to the handler via a matched pattern)
	r.HandleFunc("/articles/{category}/{id:[0-9]+}", instana.TracingHandlerFunc(
		sensor,
		"/articles/{category}/{id:[0-9]+}",
		func(w http.ResponseWriter, req *http.Request) {
			// ...
		},
	))

	if err := http.ListenAndServe(":0", nil); err != nil {
		log.Fatalf("failed to start server: %s", err)
	}
}
Output:

Example (RoundTripper)

This example shows how to instrument an HTTP client with Instana tracing

package main

import (
	"context"
	"log"
	"net/http"

	instana "github.com/instana/go-sensor"
	"github.com/opentracing/opentracing-go/ext"
)

func main() {
	sensor := instana.NewSensor("my-http-client")

	// Wrap the original http.Client transport with instana.RoundTripper().
	// The http.DefaultTransport will be used if there was no transport provided.
	client := &http.Client{
		Transport: instana.RoundTripper(sensor, nil),
	}

	// The call should always start with an entry span (https://docs.instana.io/quick_start/custom_tracing/#always-start-new-traces-with-entry-spans)
	// Normally this would be your HTTP/GRPC/message queue request span, but here we need to
	// create it explicitly.
	sp := sensor.Tracer().StartSpan("client-call")
	sp.SetTag(string(ext.SpanKind), "entry")

	req, err := http.NewRequest(http.MethodGet, "https://www.instana.com", nil)
	if err != nil {
		log.Fatalf("failed to create request: %s", err)
	}

	// Inject the parent span into request context
	ctx := instana.ContextWithSpan(context.Background(), sp)

	// Use your instrumented http.Client to propagate tracing context with the request
	_, err = client.Do(req.WithContext(ctx))
	if err != nil {
		log.Fatalf("failed to GET https://www.instana.com: %s", err)
	}
}
Output:

Example (TracingHandlerFunc)

This example shows how to instrument an HTTP server with Instana tracing

package main

import (
	"log"
	"net/http"

	instana "github.com/instana/go-sensor"
)

func main() {
	sensor := instana.NewSensor("my-http-server")

	// To instrument a handler function, pass it as an argument to instana.TracingHandlerFunc()
	http.HandleFunc("/", instana.TracingHandlerFunc(sensor, "/", func(w http.ResponseWriter, req *http.Request) {
		// Extract the parent span and use its tracer to initialize any child spans to trace the calls
		// inside the handler, e.g. database queries, 3rd-party API requests, etc.
		if parent, ok := instana.SpanFromContext(req.Context()); ok {
			sp := parent.Tracer().StartSpan("index")
			defer sp.Finish()
		}

		// ...

		w.Write([]byte("OK"))
	}))

	// In case your handler is implemented as an http.Handler, pass its ServeHTTP method instead
	http.HandleFunc("/files", instana.TracingHandlerFunc(sensor, "index", http.FileServer(http.Dir("./")).ServeHTTP))

	if err := http.ListenAndServe(":0", nil); err != nil {
		log.Fatalf("failed to start server: %s", err)
	}
}
Output:

Index

Examples

Constants

View Source
const (
	SeverityChange   severity = -1
	SeverityWarning  severity = 5
	SeverityCritical severity = 10
)

Severity values for events sent to the instana agent

View Source
const (
	ServicePlugin = "com.instana.forge.connection.http.logical.LogicalWebApp"
	ServiceHost   = ""
)

Defaults for the Event API

View Source
const (
	// SDK span, a generic span containing arbitrary data. Spans with operation name
	// not listed in the subsequent list will be sent as an SDK spans forwarding all
	// attached tags to the agent
	SDKSpanType = RegisteredSpanType("sdk")
	// HTTP server and client spans
	HTTPServerSpanType = RegisteredSpanType("g.http")
	HTTPClientSpanType = RegisteredSpanType("http")
	// RPC server and client spans
	RPCServerSpanType = RegisteredSpanType("rpc-server")
	RPCClientSpanType = RegisteredSpanType("rpc-client")
	// Kafka consumer/producer span
	KafkaSpanType = RegisteredSpanType("kafka")
)

Registered types supported by Instana. The span type is determined based on the operation name passed to the `StartSpan()` call of a tracer.

It is NOT RECOMMENDED to use operation names that match any of these constants in your custom instrumentation code unless you explicitly wish to send data as a registered span. The conversion will result in loss of custom tags that are not supported for this span type. The list of supported tags can be found in the godoc of the respective span tags type below.

View Source
const (
	Error = 0
	Warn  = 1
	Info  = 2
	Debug = 3
)

Valid log levels

View Source
const (
	// FieldT Trace ID header
	FieldT = "x-instana-t"
	// FieldS Span ID header
	FieldS = "x-instana-s"
	// FieldL Level header
	FieldL = "x-instana-l"
	// FieldB OT Baggage header
	FieldB = "x-instana-b-"
	// FieldSynthetic if set to 1, marks the call as synthetic, e.g.
	// a healthcheck request
	FieldSynthetic = "x-instana-synthetic"
)

Instana header constants

View Source
const (
	DefaultMaxBufferedSpans = 1000
	DefaultForceSpanSendAt  = 500
)
View Source
const (
	// MaxLogsPerSpan The maximum number of logs allowed on a span.
	MaxLogsPerSpan = 2
)
View Source
const (

	// SnapshotPeriod is the amount of time in seconds between snapshot reports.
	SnapshotPeriod = 600
)

Variables

This section is empty.

Functions

func BatchSize added in v1.10.0

func BatchSize(n int) ot.Tag

BatchSize returns an opentracing.Tag to mark the span as a batched span representing similar span categories. An example of such span would be batch writes to a queue, a database, etc. If the batch size less than 2, then this option has no effect

func ContextWithSpan added in v1.7.0

func ContextWithSpan(ctx context.Context, sp ot.Span) context.Context

ContextWithSpan returns a new context.Context holding a reference to an active span

func EumSnippet deprecated

func EumSnippet(apiKey string, traceID string, meta map[string]string) string

EumSnippet generates javascript code to initialize JavaScript agent

Deprecated: this snippet is outdated and this method will be removed in the next major version. To learn about the way to install Instana EUM snippet please refer to https://docs.instana.io/products/website_monitoring/#installation

func FormatID added in v1.8.0

func FormatID(id int64) string

FormatID converts an Instana ID to a value that can be used in context propagation (such as HTTP headers). More specifically, this converts a signed 64 bit integer into an unsigned hex string.

func Header2ID deprecated

func Header2ID(header string) (int64, error)

Header2ID calls instana.ParseID() and returns its result. This is kept here for backward compatibility with go-sensor@v1.x

Deprecated: please use instana.ParseID() instead

func ID2Header deprecated

func ID2Header(id int64) (string, error)

ID2Header calls instana.FormatID() and returns its result and a nil error. This is kept here for backward compatibility with go-sensor@v1.x

Deprecated: please use instana.FormatID() instead

func InitSensor

func InitSensor(options *Options)

InitSensor intializes the sensor (without tracing) to begin collecting and reporting metrics.

func InstrumentSQLDriver added in v1.15.0

func InstrumentSQLDriver(sensor *Sensor, name string, driver driver.Driver)

InstrumentSQLDriver instruments provided database driver for use with `sql.Open()`. The instrumented version is registered with `_with_instana` suffix, e.g. if `postgres` provided as a name, the instrumented version is registered as `postgres_with_instana`.

func NewTracer

func NewTracer() ot.Tracer

NewTracer Get a new Tracer with the default options applied.

func NewTracerWithEverything

func NewTracerWithEverything(options *Options, recorder SpanRecorder) ot.Tracer

NewTracerWithEverything Get a new Tracer with the works.

func NewTracerWithOptions

func NewTracerWithOptions(options *Options) ot.Tracer

NewTracerWithOptions Get a new Tracer with the specified options.

func ParseID added in v1.8.0

func ParseID(header string) (int64, error)

Header2ID converts an header context value into an Instana ID. More specifically, this converts an unsigned 64 bit hex value into a signed 64bit integer.

func RoundTripper added in v1.8.0

func RoundTripper(sensor *Sensor, original http.RoundTripper) http.RoundTripper

RoundTripper wraps an existing http.RoundTripper and injects the tracing headers into the outgoing request. If the original RoundTripper is nil, the http.DefaultTransport will be used.

Example

This example demonstrates how to instrument an HTTP client with Instana

package main

import (
	"context"
	"net/http"

	instana "github.com/instana/go-sensor"
)

func main() {
	// Here we initialize a new instance of instana.Sensor, however it is STRONGLY recommended
	// to use a single instance throughout your application
	sensor := instana.NewSensor("my-http-client")
	span := sensor.Tracer().StartSpan("entry")

	// http.DefaultTransport is used as a default RoundTripper, however you can provide
	// your own implementation
	client := &http.Client{
		Transport: instana.RoundTripper(sensor, nil),
	}

	// Inject parent span into the request context
	ctx := instana.ContextWithSpan(context.Background(), span)
	req, _ := http.NewRequest("GET", "https://www.instana.com", nil)

	// Execute request as usual
	client.Do(req.WithContext(ctx))
}
Output:

func SQLOpen added in v1.15.0

func SQLOpen(driverName, dataSourceName string) (*sql.DB, error)

SQLOpen is a convenience wrapper for `sql.Open()` to use the instrumented version of a driver previosly registered using `instana.InstrumentSQLDriver()`

Example

This example demonstrates how to instrument an *sql.DB instance created with sql.Open()

// Here we initialize a new instance of instana.Sensor, however it is STRONGLY recommended
// to use a single instance throughout your application
sensor := instana.NewSensor("my-http-client")

// Instrument the driver. Normally this would be a type provided by the driver library, e.g.
// pq.Driver{} or mysql.Driver{}, but here we use a test mock to avoid bringing external dependencies
instana.InstrumentSQLDriver(sensor, "your_db_driver", sqlDriver{})

// Replace sql.Open() with instana.SQLOpen()
db, _ := instana.SQLOpen("your_db_driver", "driver connection string")

// Inject parent span into the context
span := sensor.Tracer().StartSpan("entry")
ctx := instana.ContextWithSpan(context.Background(), span)

// Query the database, passing the context containing the active span
db.QueryContext(ctx, "SELECT * FROM users;")

// SQL queries that are not expected to return a result set are also supported
db.ExecContext(ctx, "UPDATE users SET last_seen_at = NOW();")
Output:

func SendDefaultServiceEvent

func SendDefaultServiceEvent(title string, text string, sev severity, duration time.Duration)

SendDefaultServiceEvent sends a default event which already contains the service and host

func SendHostEvent

func SendHostEvent(title string, text string, sev severity, duration time.Duration)

SendHostEvent sends an event on the current host

func SendServiceEvent

func SendServiceEvent(service string, title string, text string, sev severity, duration time.Duration)

SendServiceEvent sends an event on a specific service

func SetLogger added in v1.8.0

func SetLogger(l LeveledLogger)

SetLogger configures the default logger to be used by Instana go-sensor. Note that changing the logger will not affect already initialized instana.Sensor instances. To make them use the new logger please call (*instana.Sensor).SetLogger() explicitly.

func SpanFromContext added in v1.7.0

func SpanFromContext(ctx context.Context) (ot.Span, bool)

SpanFromContext retrieves previously stored active span from context. If there is no span, this method returns false.

func SuppressTracing added in v1.11.0

func SuppressTracing() ot.Tag

SuppressTracing returns an opentracing.Tag to mark the span and any of its child spans as not to be sent to the agent

func TracingHandlerFunc added in v1.8.0

func TracingHandlerFunc(sensor *Sensor, pathTemplate string, handler http.HandlerFunc) http.HandlerFunc

TracingHandlerFunc is an HTTP middleware that captures the tracing data and ensures trace context propagation via OpenTracing headers. The pathTemplate parameter, when provided, will be added to the span as a template string used to match the route containing variables, regular expressions, etc.

The wrapped handler will also propagate the W3C trace context (https://www.w3.org/TR/trace-context/) if found in request.

Example

This example demonstrates how to instrument an HTTP handler with Instana and register it in http.DefaultServeMux

package main

import (
	"net/http"

	instana "github.com/instana/go-sensor"
)

func main() {
	// Here we initialize a new instance of instana.Sensor, however it is STRONGLY recommended
	// to use a single instance throughout your application
	sensor := instana.NewSensor("my-http-server")

	http.HandleFunc("/", instana.TracingHandlerFunc(sensor, "root", func(w http.ResponseWriter, req *http.Request) {
		// handler code
	}))
}
Output:

func WrapSQLConnector added in v1.15.0

func WrapSQLConnector(sensor *Sensor, name string, connector driver.Connector) *wrappedSQLConnector

WrapSQLConnector wraps an existing sql.Connector and instruments the DB calls made using it

Example

This example demonstrates how to instrument an *sql.DB instance created with sql.OpenDB() and driver.Connector

// Here we initialize a new instance of instana.Sensor, however it is STRONGLY recommended
// to use a single instance throughout your application
sensor := instana.NewSensor("my-http-client")

// Instrument the connector. Normally this would be a type provided by the driver library.
// Here we use a test mock to avoid bringing external dependencies.
//
// Note that instana.WrapSQLConnector() requires the connection string to send it later
// along with database spans.
connector := instana.WrapSQLConnector(sensor, "driver connection string", &sqlConnector{})

// Use wrapped connector to initialize the database client. Note that
db := sql.OpenDB(connector)

// Inject parent span into the context
span := sensor.Tracer().StartSpan("entry")
ctx := instana.ContextWithSpan(context.Background(), span)

// Query the database, passing the context containing the active span
db.QueryContext(ctx, "SELECT * FROM users;")

// SQL queries that are not expected to return a result set are also supported
db.ExecContext(ctx, "UPDATE users SET last_seen_at = NOW();")
Output:

Types

type ContextSensitiveFunc added in v1.4.14

type ContextSensitiveFunc func(span ot.Span, ctx context.Context)

type EUMCorrelationData added in v1.16.0

type EUMCorrelationData struct {
	Type string
	ID   string
}

EUMCorrelationData represents the data sent by the Instana End-User Monitoring script integrated into frontend

type EntityData

type EntityData acceptor.GoProcessData

EntityData struct to hold snapshot data

type EventData

type EventData struct {
	Title string `json:"title"`
	Text  string `json:"text"`
	// Duration in milliseconds
	Duration int `json:"duration"`
	// Severity with value of -1, 5, 10 : see type severity
	Severity int    `json:"severity"`
	Plugin   string `json:"plugin,omitempty"`
	ID       string `json:"id,omitempty"`
	Host     string `json:"host"`
}

EventData is the construct serialized for the host agent

type ForeignParent added in v1.13.0

type ForeignParent struct {
	TraceID          string `json:"t"`
	ParentID         string `json:"p"`
	LatestTraceState string `json:"lts,omitempty"`
}

ForeignParent represents a related 3rd-party trace context, e.g. a W3C Trace Context

type HTTPSpanData added in v1.9.0

type HTTPSpanData struct {
	SpanData
	Tags HTTPSpanTags `json:"http"`
}

HTTPSpanData represents the `data` section of an HTTP span sent within an OT span document

func NewHTTPSpanData added in v1.9.0

func NewHTTPSpanData(span *spanS) HTTPSpanData

NewHTTPSpanData initializes a new HTTP span data from tracer span

type HTTPSpanTags added in v1.9.0

type HTTPSpanTags struct {
	// Full request/response URL
	URL string `json:"url,omitempty"`
	// The HTTP status code returned with client/server response
	Status int `json:"status,omitempty"`
	// The HTTP method of the request
	Method string `json:"method,omitempty"`
	// Path is the path part of the request URL
	Path string `json:"path,omitempty"`
	// PathTemplate is the raw template string used to route the request
	PathTemplate string `json:"path_tpl,omitempty"`
	// The name:port of the host to which the request had been sent
	Host string `json:"host,omitempty"`
	// The name of the protocol used for request ("http" or "https")
	Protocol string `json:"protocol,omitempty"`
	// The message describing an error occured during the request handling
	Error string `json:"error,omitempty"`
}

HTTPSpanTags contains fields within the `data.http` section of an OT span document

func NewHTTPSpanTags added in v1.9.0

func NewHTTPSpanTags(span *spanS) HTTPSpanTags

NewHTTPSpanTags extracts HTTP-specific span tags from a tracer span

type KafkaSpanData added in v1.9.0

type KafkaSpanData struct {
	SpanData
	Tags KafkaSpanTags `json:"kafka"`
}

KafkaSpanData represents the `data` section of an Kafka span sent within an OT span document

func NewKafkaSpanData added in v1.9.0

func NewKafkaSpanData(span *spanS) KafkaSpanData

NewKafkaSpanData initializes a new Kafka span data from tracer span

type KafkaSpanTags added in v1.9.0

type KafkaSpanTags struct {
	// Kafka topic
	Service string `json:"service"`
	// The access mode:, either "send" for publisher or "consume" for consumer
	Access string `json:"access"`
}

KafkaSpanTags contains fields within the `data.kafka` section of an OT span document

func NewKafkaSpanTags added in v1.9.0

func NewKafkaSpanTags(span *spanS) KafkaSpanTags

NewKafkaSpanTags extracts Kafka-specific span tags from a tracer span

type LeveledLogger added in v1.8.0

type LeveledLogger interface {
	Debug(v ...interface{})
	Info(v ...interface{})
	Warn(v ...interface{})
	Error(v ...interface{})
}

LeveledLogger is an interface of a generic logger that support different message levels. By default instana.Sensor uses logger.Logger with log.Logger as an output, however this interface is also compatible with such popular loggers as github.com/sirupsen/logrus.Logger and go.uber.org/zap.SugaredLogger

type MemoryS

type MemoryS acceptor.MemoryStats

MemoryS struct to hold snapshot data

type MetricsS

type MetricsS acceptor.Metrics

MetricsS struct to hold snapshot data

type Options

type Options struct {
	Service                     string
	AgentHost                   string
	AgentPort                   int
	MaxBufferedSpans            int
	ForceTransmissionStartingAt int
	LogLevel                    int
	EnableAutoProfile           bool
	MaxBufferedProfiles         int
	IncludeProfilerFrames       bool
}

Options allows the user to configure the to-be-initialized sensor

func DefaultOptions added in v1.11.0

func DefaultOptions() *Options

DefaultOptions returns the default set of options to configure Instana sensor. The service name is set to the name of current executable, the MaxBufferedSpans and ForceTransmissionStartingAt are set to instana.DefaultMaxBufferedSpans and instana.DefaultForceSpanSendAt correspondigly. The AgentHost and AgentPort are taken from the env INSTANA_AGENT_HOST and INSTANA_AGENT_PORT if set, and default to localhost and 46999 otherwise.

type RPCSpanData added in v1.9.0

type RPCSpanData struct {
	SpanData
	Tags RPCSpanTags `json:"rpc"`
}

RPCSpanData represents the `data` section of an RPC span sent within an OT span document

func NewRPCSpanData added in v1.9.0

func NewRPCSpanData(span *spanS) RPCSpanData

NewRPCSpanData initializes a new RPC span data from tracer span

type RPCSpanTags added in v1.9.0

type RPCSpanTags struct {
	// The name of the remote host for an RPC call
	Host string `json:"host,omitempty"`
	// The port of the remote host for an RPC call
	Port string `json:"port,omitempty"`
	// The name of the remote method to invoke
	Call string `json:"call,omitempty"`
	// The type of an RPC call, e.g. either "unary" or "stream" for GRPC requests
	CallType string `json:"call_type,omitempty"`
	// The RPC flavor used for this call, e.g. "grpc" for GRPC requests
	Flavor string `json:"flavor,omitempty"`
	// The message describing an error occured during the request handling
	Error string `json:"error,omitempty"`
}

RPCSpanTags contains fields within the `data.rpc` section of an OT span document

func NewRPCSpanTags added in v1.9.0

func NewRPCSpanTags(span *spanS) RPCSpanTags

NewRPCSpanTags extracts RPC-specific span tags from a tracer span

type Recorder

type Recorder struct {
	sync.RWMutex
	// contains filtered or unexported fields
}

Recorder accepts spans, processes and queues them for delivery to the backend.

func NewRecorder

func NewRecorder() *Recorder

NewRecorder initializes a new span recorder

func NewTestRecorder

func NewTestRecorder() *Recorder

NewTestRecorder initializes a new span recorder that keeps all collected until they are requested. This recorder does not send spans to the agent (used for testing)

func (*Recorder) GetQueuedSpans

func (r *Recorder) GetQueuedSpans() []Span

GetQueuedSpans returns a copy of the queued spans and clears the queue.

func (*Recorder) QueuedSpansCount

func (r *Recorder) QueuedSpansCount() int

QueuedSpansCount returns the number of queued spans

Used only in tests currently.

func (*Recorder) RecordSpan

func (r *Recorder) RecordSpan(span *spanS)

RecordSpan accepts spans to be recorded and and added to the span queue for eventual reporting to the host agent.

type RegisteredSpanType added in v1.9.0

type RegisteredSpanType string

RegisteredSpanType represents the span type supported by Instana

func (RegisteredSpanType) ExtractData added in v1.9.0

func (st RegisteredSpanType) ExtractData(span *spanS) typedSpanData

ExtractData is a factory method to create the `data` section for a typed span

type SDKSpanData added in v1.9.0

type SDKSpanData struct {
	SpanData
	Tags SDKSpanTags `json:"sdk"`
}

SDKSpanData represents the `data` section of an SDK span sent within an OT span document

func NewSDKSpanData added in v1.9.0

func NewSDKSpanData(span *spanS) SDKSpanData

NewSDKSpanData initializes a new SDK span data from tracer span

type SDKSpanTags added in v1.9.0

type SDKSpanTags struct {
	Name      string                 `json:"name"`
	Type      string                 `json:"type,omitempty"`
	Arguments string                 `json:"arguments,omitempty"`
	Return    string                 `json:"return,omitempty"`
	Custom    map[string]interface{} `json:"custom,omitempty"`
}

SDKSpanTags contains fields within the `data.sdk` section of an OT span document

func NewSDKSpanTags added in v1.9.0

func NewSDKSpanTags(span *spanS, spanType string) SDKSpanTags

NewSDKSpanTags extracts SDK span tags from a tracer span

type Sensor added in v1.4.14

type Sensor struct {
	// contains filtered or unexported fields
}

Sensor is used to inject tracing information into requests

func NewSensor added in v1.4.14

func NewSensor(serviceName string) *Sensor

NewSensor creates a new instana.Sensor

func NewSensorWithTracer added in v1.7.0

func NewSensorWithTracer(tracer ot.Tracer) *Sensor

NewSensorWithTracer returns a new instana.Sensor that uses provided tracer to report spans

func (*Sensor) Logger added in v1.8.0

func (s *Sensor) Logger() LeveledLogger

Logger returns the logger instance for this sensor

func (*Sensor) SetLogger added in v1.8.0

func (s *Sensor) SetLogger(l LeveledLogger)

SetLogger sets the logger for this sensor

func (*Sensor) TraceHandler deprecated added in v1.4.14

func (s *Sensor) TraceHandler(name, pattern string, handler http.HandlerFunc) (string, http.HandlerFunc)

TraceHandler is similar to TracingHandler in regards, that it wraps an existing http.HandlerFunc into a named instance to support capturing tracing information and data. The returned values are compatible with handler registration methods, e.g. http.Handle()

Deprecated: please use instana.TracingHandlerFunc() instead

func (*Sensor) Tracer added in v1.7.1

func (s *Sensor) Tracer() ot.Tracer

Tracer returns the tracer instance for this sensor

func (*Sensor) TracingHandler deprecated added in v1.4.14

func (s *Sensor) TracingHandler(name string, handler http.HandlerFunc) http.HandlerFunc

TracingHandler wraps an existing http.HandlerFunc into a named instance to support capturing tracing information and response data

Deprecated: please use instana.TracingHandlerFunc() instead

func (*Sensor) TracingHttpRequest deprecated added in v1.4.14

func (s *Sensor) TracingHttpRequest(name string, parent, req *http.Request, client http.Client) (*http.Response, error)

TracingHttpRequest wraps an existing http.Request instance into a named instance to inject tracing and span header information into the actual HTTP wire transfer

Deprecated: please use instana.RoundTripper() instead

func (*Sensor) WithTracingContext deprecated added in v1.4.14

func (s *Sensor) WithTracingContext(name string, w http.ResponseWriter, req *http.Request, f ContextSensitiveFunc)

Executes the given ContextSensitiveFunc and executes it under the scope of a newly created context.Context, that provides access to the parent span as 'parentSpan'.

Deprecated: please use instana.TracingHandlerFunc() to instrument an HTTP handler

func (*Sensor) WithTracingSpan deprecated added in v1.4.14

func (s *Sensor) WithTracingSpan(operationName string, w http.ResponseWriter, req *http.Request, f SpanSensitiveFunc)

WithTracingSpan takes the given SpanSensitiveFunc and executes it under the scope of a child span, which is injected as an argument when calling the function. It uses the name of the caller as a span operation name unless a non-empty value is provided

Deprecated: please use instana.TracingHandlerFunc() to instrument an HTTP handler

type SnapshotCollector added in v1.13.2

type SnapshotCollector struct {
	ServiceName        string
	CollectionInterval time.Duration
	// contains filtered or unexported fields
}

SnapshotCollector returns a snapshot of Go runtime

func (*SnapshotCollector) Collect added in v1.13.2

func (sc *SnapshotCollector) Collect() *acceptor.RuntimeInfo

Collect returns a snaphot of current runtime state. Any call this method made before the next interval elapses will return nil

type SnapshotS

type SnapshotS acceptor.RuntimeInfo

SnapshotS struct to hold snapshot data

type Span added in v1.9.0

type Span struct {
	TraceID         int64          `json:"t"`
	ParentID        int64          `json:"p,omitempty"`
	SpanID          int64          `json:"s"`
	Timestamp       uint64         `json:"ts"`
	Duration        uint64         `json:"d"`
	Name            string         `json:"n"`
	From            *fromS         `json:"f"`
	Batch           *batchInfo     `json:"b,omitempty"`
	Kind            int            `json:"k"`
	Ec              int            `json:"ec,omitempty"`
	Data            typedSpanData  `json:"data"`
	Synthetic       bool           `json:"sy,omitempty"`
	ForeignParent   *ForeignParent `json:"fp,omitempty"`
	CorrelationType string         `json:"crtp,omitempty"`
	CorrelationID   string         `json:"crid,omitempty"`
}

Span represents the OpenTracing span document to be sent to the agent

type SpanContext

type SpanContext struct {
	// A probabilistically unique identifier for a [multi-span] trace.
	TraceID int64
	// A probabilistically unique identifier for a span.
	SpanID int64
	// An optional parent span ID, 0 if this is the root span context.
	ParentID int64
	// Whether the trace is sampled.
	Sampled bool
	// Whether the trace is suppressed and should not be sent to the agent.
	Suppressed bool
	// The span's associated baggage.
	Baggage map[string]string // initialized on first use
	// The W3C trace context
	W3CContext w3ctrace.Context
	// Correlation is the correlation data sent by the frontend EUM script
	Correlation EUMCorrelationData
	// The 3rd party parent if the context is derived from non-Instana trace
	ForeignParent interface{}
}

SpanContext holds the basic Span metadata.

func NewRootSpanContext added in v1.9.0

func NewRootSpanContext() SpanContext

NewRootSpanContext initializes a new root span context issuing a new trace ID

func NewSpanContext added in v1.9.0

func NewSpanContext(parent SpanContext) SpanContext

NewSpanContext initializes a new child span context from its parent. It will ignore the parent context if it contains neither Instana trace and span IDs nor a W3C trace context

func (SpanContext) Clone added in v1.9.0

func (c SpanContext) Clone() SpanContext

Clone returns a deep copy of a SpanContext

func (SpanContext) ForeachBaggageItem

func (c SpanContext) ForeachBaggageItem(handler func(k, v string) bool)

ForeachBaggageItem belongs to the opentracing.SpanContext interface

func (SpanContext) WithBaggageItem

func (c SpanContext) WithBaggageItem(key, val string) SpanContext

WithBaggageItem returns an entirely new SpanContext with the given key:value baggage pair set.

type SpanData added in v1.9.0

type SpanData struct {
	Service string `json:"service,omitempty"`
	// contains filtered or unexported fields
}

SpanData contains fields to be sent in the `data` section of an OT span document. These fields are common for all span types.

func NewSpanData added in v1.9.0

func NewSpanData(span *spanS, st RegisteredSpanType) SpanData

NewSpanData initializes a new span data from tracer span

func (SpanData) Kind added in v1.9.1

func (d SpanData) Kind() SpanKind

Kind returns the kind of the span. It handles the github.com/opentracing/opentracing-go/ext.SpanKindEnum values as well as generic "entry" and "exit"

func (SpanData) Type added in v1.9.0

func (d SpanData) Type() RegisteredSpanType

Name returns the registered name for the span type suitable for use as the value of `n` field.

type SpanKind added in v1.9.0

type SpanKind uint8

SpanKind represents values of field `k` in OpenTracing span representation. It represents the direction of the call associated with a span.

const (
	// The kind of a span associated with an inbound call, this must be the first span in the trace.
	EntrySpanKind SpanKind = iota + 1
	// The kind of a span associated with an outbound call, e.g. an HTTP client request, posting to a message bus, etc.
	ExitSpanKind
	// The default kind for a span that is associated with a call within the same service.
	IntermediateSpanKind
)

Valid span kinds

func (SpanKind) String added in v1.9.0

func (k SpanKind) String() string

String returns string representation of a span kind suitable for use as a value for `data.sdk.type` tag of an SDK span. By default all spans are intermediate unless they are explicitly set to be "entry" or "exit"

type SpanRecorder

type SpanRecorder interface {
	// Implementations must determine whether and where to store `span`.
	RecordSpan(span *spanS)
}

A SpanRecorder handles all of the `RawSpan` data generated via an associated `Tracer` (see `NewStandardTracer`) instance. It also names the containing process and provides access to a straightforward tag map.

type SpanSensitiveFunc added in v1.4.14

type SpanSensitiveFunc func(span ot.Span)

type Tracer

type Tracer interface {
	opentracing.Tracer

	// Options gets the Options used in New() or NewWithOptions().
	Options() TracerOptions
}

Tracer extends the opentracing.Tracer interface

type TracerOptions

type TracerOptions struct {
	// ShouldSample is a function which is called when creating a new Span and
	// determines whether that Span is sampled. The randomized TraceID is supplied
	// to allow deterministic sampling decisions to be made across different nodes.
	// For example,
	//
	//   func(traceID uint64) { return traceID % 64 == 0 }
	//
	// samples every 64th trace on average.
	ShouldSample func(traceID int64) bool
	// TrimUnsampledSpans turns potentially expensive operations on unsampled
	// Spans into no-ops. More precisely, tags and log events are silently
	// discarded. If NewSpanEventListener is set, the callbacks will still fire.
	TrimUnsampledSpans bool
	// Recorder receives Spans which have been finished.
	Recorder SpanRecorder
	// NewSpanEventListener can be used to enhance the tracer by effectively
	// attaching external code to trace events. See NetTraceIntegrator for a
	// practical example, and event.go for the list of possible events.
	NewSpanEventListener func() func(bt.SpanEvent)
	// DropAllLogs turns log events on all Spans into no-ops.
	// If NewSpanEventListener is set, the callbacks will still fire.
	DropAllLogs bool
	// MaxLogsPerSpan limits the number of Logs in a span (if set to a nonzero
	// value). If a span has more logs than this value, logs are dropped as
	// necessary (and replaced with a log describing how many were dropped).
	//
	// About half of the MaxLogPerSpan logs kept are the oldest logs, and about
	// half are the newest logs.
	//
	// If NewSpanEventListener is set, the callbacks will still fire for all log
	// events. This value is ignored if DropAllLogs is true.
	MaxLogsPerSpan int
	// DebugAssertSingleGoroutine internally records the ID of the goroutine
	// creating each Span and verifies that no operation is carried out on
	// it on a different goroutine.
	// Provided strictly for development purposes.
	// Passing Spans between goroutine without proper synchronization often
	// results in use-after-Finish() errors. For a simple example, consider the
	// following pseudocode:
	//
	//  func (s *Server) Handle(req http.Request) error {
	//    sp := s.StartSpan("server")
	//    defer sp.Finish()
	//    wait := s.queueProcessing(opentracing.ContextWithSpan(context.Background(), sp), req)
	//    select {
	//    case resp := <-wait:
	//      return resp.Error
	//    case <-time.After(10*time.Second):
	//      sp.LogEvent("timed out waiting for processing")
	//      return ErrTimedOut
	//    }
	//  }
	//
	// This looks reasonable at first, but a request which spends more than ten
	// seconds in the queue is abandoned by the main goroutine and its trace
	// finished, leading to use-after-finish when the request is finally
	// processed. Note also that even joining on to a finished Span via
	// StartSpanWithOptions constitutes an illegal operation.
	//
	// Code bases which do not require (or decide they do not want) Spans to
	// be passed across goroutine boundaries can run with this flag enabled in
	// tests to increase their chances of spotting wrong-doers.
	DebugAssertSingleGoroutine bool
	// DebugAssertUseAfterFinish is provided strictly for development purposes.
	// When set, it attempts to exacerbate issues emanating from use of Spans
	// after calling Finish by running additional assertions.
	DebugAssertUseAfterFinish bool
	// EnableSpanPool enables the use of a pool, so that the tracer reuses spans
	// after Finish has been called on it. Adds a slight performance gain as it
	// reduces allocations. However, if you have any use-after-finish race
	// conditions the code may panic.
	EnableSpanPool bool
}

TracerOptions allows creating a customized Tracer via NewWithOptions. The object must not be updated when there is an active tracer using it.

Directories

Path Synopsis
Package acceptor provides marshaling structs for Instana serverless acceptor API
Package acceptor provides marshaling structs for Instana serverless acceptor API
internal/pprof/profile
Package profile provides a representation of profile.proto and methods to encode/decode profiles in this format.
Package profile provides a representation of profile.proto and methods to encode/decode profiles in this format.
rpc
beego Module
echo Module
gin Module
httprouter Module
instrumentation
instaamqp Module
instaamqp091 Module
instaawssdk Module
instaawsv2 Module
instabeego Module
instacosmos Module
instaecho Module
instafasthttp Module
instafiber Module
instagin Module
instagocb Module
instagorm Module
instagraphql Module
instagrpc Module
instalambda Module
instalogrus Module
instamongo Module
instamux Module
instapgx Module
instaredigo Module
instaredis Module
instasarama Module

Jump to

Keyboard shortcuts

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