Client
Introduction
OpenCensus provides a package go.opencensus.io/plugin/ochttp which has a custom HTTP roundtripper ochttp.Transport that can wrap your HTTP Transport. For example
package main
import (
"net/http"
"go.opencensus.io/plugin/ochttp"
)
func main() {
octr := &ochttp.Transport{}
client := &http.Client{Transport: octr}
// Use the client
_ = client
}When chaining multiple Transports, please make sure that the ochttp.Transport.Base is the out-most Transport
package main
import (
"net/http"
"go.opencensus.io/plugin/ochttp"
)
func main() {
octr := &ochttp.Transport{Base: &http.Transport{}}
client := &http.Client{Transport: octr}
// Use the client
_ = client
}Traces
Traces can be continued and used simply by passing the context that contains traces into the request that will then be used to roundtrip the request
package main
import (
"context"
"io"
"io/ioutil"
"log"
"net/http"
"go.opencensus.io/plugin/ochttp"
)
func main() {
ctx := context.Background() // In other usages, the context would have been passed down after starting some traces.
req, _ := http.NewRequest("GET", "https://opencensus.io/", nil)
// It is imperative that req.WithContext is used to
// propagate context and use it in the request.
req = req.WithContext(ctx)
client := &http.Client{Transport: &ochttp.Transport{}}
res, err := client.Do(req)
if err != nil {
log.Fatalf("Failed to make the request: %v", err)
}
// Consume the body and close it.
io.Copy(ioutil.Discard, res.Body)
_ = res.Body.Close()
}To examine the traces, please make sure to enable a Trace exporter that will send the data to a Tracing backend.
Metrics
Metrics can be enabled by simply registering the ochttp.DefaultClientViews
// In our main, register ochttp Client views
if err := view.Register(ochttp.DefaultClientViews...); err != nil {
log.Fatalf("Failed to register client views for HTTP metrics: %v", err)
}To examine the metrics, please make sure to enable a Stats exporter that will send the data to a Metrics backend.
which provide the following metrics
| Metric | Prefix | Description | Tags | Aggregation |
|---|---|---|---|---|
| Requests completed | “opencensus.io/http/client/completed_count” | The number of requests made | “http_client_method”, “http_client_status” | Count |
| Bytes sent | “opencensus.io/http/client/sent_bytes” | The number of bytes sent | “http_client_method”, “http_client_status” | Distribution |
| Bytes received | “opencensus.io/http/client/received_bytes” | The number of bytes received | “http_client_method”, “http_client_status” | Distribution |
| Roundtrip Latency | “opencensus.io/http/client/roundtrip_latency” | The end-to-end latency | “http_client_method”, “http_client_status” | Distribution |
End to end example
The following example uses the ochttp.Transport to make requests to the OpenCensus website every 5 seconds and exports traces and metrics with our Zipkin trace and Prometheus stats respectively. Of course you can use any other exporters of your choice
For assistance setting up any of the exporters, please refer to:
| Exporter | URL |
|---|---|
| Prometheus | Prometheus codelab |
| Zipkin | Zipkin codelab |
package main
import (
"context"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"time"
openzipkin "github.com/openzipkin/zipkin-go"
zipkinHTTP "github.com/openzipkin/zipkin-go/reporter/http"
"contrib.go.opencensus.io/exporter/prometheus"
"contrib.go.opencensus.io/exporter/zipkin"
"go.opencensus.io/plugin/ochttp"
"go.opencensus.io/stats/view"
"go.opencensus.io/trace"
)
func main() {
// Firstly, we'll register ochttp Client views
if err := view.Register(ochttp.DefaultClientViews...); err != nil {
log.Fatalf("Failed to register client views for HTTP metrics: %v", err)
}
// For tracing, let's always sample for the purposes of this demo
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
// Enable observability to extract and examine traces and metrics.
enableObservabilityAndExporters()
// Create our HTTP client that uses the ochttp.Transport.
client := &http.Client{Transport: &ochttp.Transport{}}
i := uint64(0)
// Then finally do the work every 5 seconds.
for {
i += 1
log.Printf("Performing fetch #%d", i)
ctx, span := trace.StartSpan(context.Background(), fmt.Sprintf("Fetch-%d", i))
doWork(ctx, client)
span.End()
<-time.After(5 * time.Second)
}
}
func doWork(ctx context.Context, client *http.Client) {
req, _ := http.NewRequest("GET", "https://opencensus.io/", nil)
// It is imperative that req.WithContext is used to
// propagate context and use it in the request.
req = req.WithContext(ctx)
// Now make the request to the remote end.
res, err := client.Do(req)
if err != nil {
log.Printf("Failed to make the request: %v", err)
return
}
// Consume the body and close it.
io.Copy(ioutil.Discard, res.Body)
_ = res.Body.Close()
}
func enableObservabilityAndExporters() {
// Stats exporter: Prometheus
pe, err := prometheus.NewExporter(prometheus.Options{
Namespace: "ochttp_tutorial",
})
if err != nil {
log.Fatalf("Failed to create the Prometheus stats exporter: %v", err)
}
go func() {
mux := http.NewServeMux()
mux.Handle("/metrics", pe)
log.Fatal(http.ListenAndServe(":8888", mux))
}()
// Trace exporter: Zipkin
localEndpoint, _ := openzipkin.NewEndpoint("ochttp_tutorial", "localhost:0")
reporter := zipkinHTTP.NewReporter("http://localhost:9411/api/v2/spans")
ze := zipkin.NewExporter(reporter, localEndpoint)
trace.RegisterExporter(ze)
}and to run the example
go run main.goand then start Prometheus with this configuration file prometheus.yaml with
scrape_configs:
- job_name: 'ochttp_tutorial'
scrape_interval: 10s
static_configs:
- targets: ['localhost:8888']by running
prometheus --config.file=prometheus.yamlViewing traces
On navigating to the Zipkin UI at http://localhost:9411/zipkin
All traces

Single trace

Single trace detail for the HTTP request “/”

Viewing metrics
On navigating to the Prometheus UI at http://localhost:9090/graph
All metrics

Latency buckets

Request bytes buckets

Response bytes buckets

References
| Resource | URL |
|---|---|
| ochttp.Transport GoDoc | https://godoc.org/go.opencensus.io/plugin/ochttp |
| ochttp.DefaultClientViews | https://godoc.org/go.opencensus.io/plugin/ochttp#DefaultClientViews |
| net/http Godoc | https://golang.org/pkg/net/http |