instafasthttp

package module
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Feb 18, 2025 License: MIT Imports: 11 Imported by: 0

README

instafasthttp - Instana instrumentation for fasthttp

This package provides Instana instrumentation for the fasthttp package.

PkgGoDev

Installation

To add the module to your go.mod file run the following command in your project directory:

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

Usage

Server

The instafasthttp.TraceHandler returns an instrumented fasthttp.RequestHandler, which can be used to add instrumentation to calls in a fasthttp server. Please refer to the details below for more information.

// Create a collector  for instana instrumentation
c = instana.InitCollector(&instana.Options{
	Service:  "fasthttp-example",
	LogLevel: instana.Debug,
})

// request handler
func fastHTTPHandler(ctx *fasthttp.RequestCtx) {
	fmt.Fprintf(ctx, "Hi there! RequestURI is %q\n", ctx.RequestURI())
	switch string(ctx.Path()) {
	case "/greet":
        // Use the instafasthttp.TraceHandler for instrumenting the greet handler
		instafasthttp.TraceHandler(c, "greet", "/greet", func(ctx *fasthttp.RequestCtx) {
			ctx.SetStatusCode(fasthttp.StatusOK)
			fmt.Fprintf(ctx, "Hello brother!\n")

		})(ctx)
	default:
		ctx.Error("Unsupported path", fasthttp.StatusNotFound)
	}
}

log.Fatal(fasthttp.ListenAndServe(":7070", fastHTTPHandler))

Trace propagation

Trace propagation is achieved by correctly using the context. In an instrumented handler, if you need to perform additional operations such as a database call and want the trace propagation to ensure that spans fall under the HTTP span, you must use the instafasthttp.UserContext function. This function provides the appropriate context containing the parent span information, which should then be passed to the subsequent database operation to get the parent span. Refer to the example code below for further clarity.

func greetEndpointHandler(ctx *fasthttp.RequestCtx) {
	ctx.SetStatusCode(fasthttp.StatusOK)
	fmt.Fprintf(ctx, "This is the first part of body!\n")

	var stud student

	// This context is required for span propagation.
	// It will be set by instafasthttp, ensuring it contains the parent span info.
	uCtx := instafasthttp.UserContext(ctx)
	db.WithContext(uCtx).First(&stud)

	fmt.Fprintf(ctx, "Hello "+stud.StudentName+"!\n")
}
HostClient

The instafasthttp.RoundTripper provides an implementation of the fasthttp.RoundTripper interface. It can be used to instrument client calls with the help of instafasthttp.HostClient. Refer to the details below for more information.

// Create a collector for instana instrumentation
c = instana.InitCollector(&instana.Options{
	Service:  "fasthttp-example",
	LogLevel: instana.Debug,
})

// request handler
func fastHTTPHandler(ctx *fasthttp.RequestCtx) {
	fmt.Fprintf(ctx, "Hi there! RequestURI is %q\n", ctx.RequestURI())
	switch string(ctx.Path()) {
	case "/round-trip":
		instafasthttp.TraceHandler(c, "round-trip", "/round-trip", func(ctx *fasthttp.RequestCtx) {
			// user context
			uCtx := instafasthttp.UserContext(ctx)

			hc := &fasthttp.HostClient{
				Transport: instafasthttp.RoundTripper(uCtx, c, nil),
				Addr:      "localhost:7070",
			}

			url := fasthttp.AcquireURI()
			url.Parse(nil, []byte("http://localhost:7070/greet"))
			req := fasthttp.AcquireRequest()
			defer fasthttp.ReleaseRequest(req)
			req.SetURI(url)
			fasthttp.ReleaseURI(url) // now you may release the URI
			req.Header.SetMethod(fasthttp.MethodGet)

			resp := fasthttp.AcquireResponse()
			defer fasthttp.ReleaseResponse(resp)

			// Make the request
			err := hc.Do(req, resp)
			if err != nil {
				log.Fatalf("failed to GET http://localhost:7070/greet: %s", err)
			}

			// getting response body
			bs := string(resp.Body())
			fmt.Println(bs)

			// Respond with a 200 status code and include the body as well
			ctx.SetStatusCode(fasthttp.StatusOK)
			fmt.Fprintf(ctx, bs)
		})(ctx)
	default:
		ctx.Error("Unsupported path", fasthttp.StatusNotFound)
	}
}

log.Fatal(fasthttp.ListenAndServe(":7070", fastHTTPHandler))

Client

The client.Do and related methods can be traced using Instana. However, the usage differs slightly from that of the standard HostClient. Below are the steps to use an Instana instrumented client.

  • To enable tracing, you must create an instrumented client using the instafasthttp.GetInstrumentedClient method as shown below:
	// fasthttp client
	client := &fasthttp.Client{
		ReadTimeout:                   readTimeout,
		WriteTimeout:                  writeTimeout,
		MaxIdleConnDuration:           maxIdleConnDuration,
		NoDefaultUserAgentHeader:      true, // Don't send: User-Agent: fasthttp
		DisableHeaderNamesNormalizing: true, // If you set the case on your headers correctly you can enable this
		DisablePathNormalizing:        true,
		// increase DNS cache time to an hour instead of default minute
		Dial: (&fasthttp.TCPDialer{
			Concurrency:      4096,
			DNSCacheDuration: time.Hour,
		}).Dial,
	}

	// create instana instrumented client
	ic := instafasthttp.GetInstrumentedClient(collector, client)
  • Use the instrumented client(ic) for all requests instead of the original client.
  • Tracing is supported for the following methods, where an additional context.Context parameter is required as the first argument. Ensure the context is set properly for span correlation:
  1. Do
  2. DoTimeout
  3. DoDeadline
  4. DoRedirects
	req := fasthttp.AcquireRequest()
	defer fasthttp.ReleaseRequest(req)
	req.SetURI(url)
	fasthttp.ReleaseURI(url) // now you may release the URI
	req.Header.SetMethod(fasthttp.MethodGet)

	resp := fasthttp.AcquireResponse()
	defer fasthttp.ReleaseResponse(resp)

	// Make the request
	err := ic.Do(uCtx, req, resp)
	if err != nil {
		log.Fatalf("failed to GET http://localhost:7070/greet: %s", err)
	}
  • For methods other than the four mentioned above, use the standard method signatures without passing a context. These methods do not support tracing. For example, client.Get and client.Post do not currently support Instana tracing. If you wish to trace the GET and POST requests, please use client.Do method instead.
  • Use the Unwrap() method if you require the original fasthttp.Client instance. However, avoid using the unwrapped instance directly for the above four methods, as Instana tracing will not be applied in such cases.

Documentation

Overview

Package instafasthttp provides Instana instrumentation for fasthttp package.

Index

Constants

View Source
const Version = "0.7.0"

Version is the instrumentation module semantic version

Variables

This section is empty.

Functions

func RoundTripper

func RoundTripper(ctx context.Context, sensor instana.TracerLogger, original fasthttp.RoundTripper) fasthttp.RoundTripper

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

func TraceHandler

func TraceHandler(sensor instana.TracerLogger, routeID, pathTemplate string, handler fasthttp.RequestHandler) fasthttp.RequestHandler

TraceHandler adds Instana instrumentation to the fasthttp.RequestHandler

func UserContext

func UserContext(c *fasthttp.RequestCtx) context.Context

UserContext returns a context implementation set by the user earlier. If not set, it returns a context.Context derived from *fasthttp.RequestCtx.

Types

type Client added in v0.2.0

type Client interface {

	// Get returns the status code and body of url.
	//
	// The contents of dst will be replaced by the body and returned, if the dst
	// is too small a new slice will be allocated.
	//
	// The function follows redirects. Use Do* for manually handling redirects.
	Get(dst []byte, url string) (statusCode int, body []byte, err error)

	// GetTimeout returns the status code and body of url.
	//
	// The contents of dst will be replaced by the body and returned, if the dst
	// is too small a new slice will be allocated.
	//
	// The function follows redirects. Use Do* for manually handling redirects.
	//
	// ErrTimeout error is returned if url contents couldn't be fetched
	// during the given timeout.
	GetTimeout(dst []byte, url string, timeout time.Duration) (statusCode int, body []byte, err error)

	// GetDeadline returns the status code and body of url.
	//
	// The contents of dst will be replaced by the body and returned, if the dst
	// is too small a new slice will be allocated.
	//
	// The function follows redirects. Use Do* for manually handling redirects.
	//
	// ErrTimeout error is returned if url contents couldn't be fetched
	// until the given deadline.
	GetDeadline(dst []byte, url string, deadline time.Time) (statusCode int, body []byte, err error)

	// Post sends POST request to the given url with the given POST arguments.
	//
	// The contents of dst will be replaced by the body and returned, if the dst
	// is too small a new slice will be allocated.
	//
	// The function follows redirects. Use Do* for manually handling redirects.
	//
	// Empty POST body is sent if postArgs is nil.
	Post(dst []byte, url string, postArgs *fasthttp.Args) (statusCode int, body []byte, err error)

	// CloseIdleConnections closes any connections which were previously
	// connected from previous requests but are now sitting idle in a
	// "keep-alive" state. It does not interrupt any connections currently
	// in use.
	CloseIdleConnections()

	// DoTimeout performs the given request and waits for response during
	// the given timeout duration.
	//
	// Request must contain at least non-zero RequestURI with full url (including
	// scheme and host) or non-zero Host header + RequestURI.
	//
	// Client determines the server to be requested in the following order:
	//
	//   - from RequestURI if it contains full url with scheme and host;
	//   - from Host header otherwise.
	//
	// The function doesn't follow redirects. Use Get* for following redirects.
	//
	// Response is ignored if resp is nil.
	//
	// ErrTimeout is returned if the response wasn't returned during
	// the given timeout.
	// Immediately returns ErrTimeout if timeout value is negative.
	//
	// ErrNoFreeConns is returned if all Client.MaxConnsPerHost connections
	// to the requested host are busy.
	//
	// It is recommended obtaining req and resp via Acquire
	//
	// Pass a valid context as the first argument for for span correlation
	DoTimeout(ctx context.Context, req *fasthttp.Request, resp *fasthttp.Response, timeout time.Duration) error

	// DoDeadline performs the given request and waits for response until
	// the given deadline.
	//
	// Request must contain at least non-zero RequestURI with full url (including
	// scheme and host) or non-zero Host header + RequestURI.
	//
	// Client determines the server to be requested in the following order:
	//
	//   - from RequestURI if it contains full url with scheme and host;
	//   - from Host header otherwise.
	//
	// The function doesn't follow redirects. Use Get* for following redirects.
	//
	// Response is ignored if resp is nil.
	//
	// ErrTimeout is returned if the response wasn't returned until
	// the given deadline.
	// Immediately returns ErrTimeout if the deadline has already been reached.
	//
	// ErrNoFreeConns is returned if all Client.MaxConnsPerHost connections
	// to the requested host are busy.
	//
	// It is recommended obtaining req and resp via AcquireRequest
	// and AcquireResponse in performance-critical code.
	//
	// Pass a valid context as the first argument for for span correlation
	DoDeadline(ctx context.Context, req *fasthttp.Request, resp *fasthttp.Response, deadline time.Time) error

	// DoRedirects performs the given http request and fills the given http response,
	// following up to maxRedirectsCount redirects. When the redirect count exceeds
	// maxRedirectsCount, ErrTooManyRedirects is returned.
	//
	// Request must contain at least non-zero RequestURI with full url (including
	// scheme and host) or non-zero Host header + RequestURI.
	//
	// Client determines the server to be requested in the following order:
	//
	//   - from RequestURI if it contains full url with scheme and host;
	//   - from Host header otherwise.
	//
	// Response is ignored if resp is nil.
	//
	// ErrNoFreeConns is returned if all DefaultMaxConnsPerHost connections
	// to the requested host are busy.
	//
	// It is recommended obtaining req and resp via AcquireRequest
	// and AcquireResponse in performance-critical code.
	//
	// Pass a valid context as the first argument for for span correlation
	DoRedirects(ctx context.Context, req *fasthttp.Request, resp *fasthttp.Response, maxRedirectsCount int) error

	// Do performs the given http request and fills the given http response.
	//
	// Request must contain at least non-zero RequestURI with full url (including
	// scheme and host) or non-zero Host header + RequestURI.
	//
	// Client determines the server to be requested in the following order:
	//
	//   - from RequestURI if it contains full url with scheme and host;
	//   - from Host header otherwise.
	//
	// Response is ignored if resp is nil.
	//
	// The function doesn't follow redirects. Use Get* for following redirects.
	//
	// ErrNoFreeConns is returned if all Client.MaxConnsPerHost connections
	// to the requested host are busy.
	//
	// It is recommended obtaining req and resp via AcquireRequest
	// and AcquireResponse in performance-critical code.
	//
	// Pass a valid context as the first argument for for span correlation
	Do(ctx context.Context, req *fasthttp.Request, resp *fasthttp.Response) error

	// Unwrap returns the original *fasthttp.Client
	Unwrap() *fasthttp.Client
}

Instrumented fasthttp.Client

Most of the methods are the same as those in fasthttp.Client.

Only Do, DoTimeout, and DoDeadline differ from fasthttp.Client. Please use these methods instead of their fasthttp.Client counterparts to enable tracing.

func GetInstrumentedClient added in v0.2.0

func GetInstrumentedClient(sensor instana.TracerLogger, orgClient *fasthttp.Client) Client

GetInstrumentedClient returns an instrumented instafasthttp.Client instance derived from a *fasthttp.Client instance

Jump to

Keyboard shortcuts

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