Comments (2)
Hi @cgilling! -- good question!
The code is written that way (creating a new http.Client
upon each request) primarily for simplicity -- it's not too difficult to rework it and make it more efficient and support persistent connections, I've hacked the example into this which uses a global http.Client
instead by swapping out the recorder on the http.Transport
of the http.Client
(see below).
In a real application you will probably want to use a pool of clients rather than a single global one for all incoming requests to your app (depending on what you are doing) -- but the concepts here remain applicable to that situation just as well.
Let me know if you have any other questions! 😃
// webapp: a standalone example Negroni / Gorilla based webapp.
//
// This example demonstrates basic usage of Appdash in a Negroni / Gorilla
// based web application. The entire application is ran locally (i.e. on the
// same server) -- even the Appdash web UI.
package main
import (
"fmt"
"log"
"net/http"
"sync"
"time"
"sourcegraph.com/sourcegraph/appdash"
"sourcegraph.com/sourcegraph/appdash/httptrace"
"sourcegraph.com/sourcegraph/appdash/traceapp"
"github.com/codegangsta/negroni"
"github.com/gorilla/context"
"github.com/gorilla/mux"
)
// Used to store the SpanID in a request's context (see gorilla/context docs
// for more information).
const CtxSpanID = 0
// We want to create HTTP clients recording to this collector inside our Home
// handler below, so we use a global variable (for simplicity sake) to store
// the collector in use. We could also use gorilla/context to store it.
var collector appdash.Collector
func main() {
// Create a recent in-memory store, evicting data after 20s.
//
// The store defines where information about traces (i.e. spans and
// annotations) will be stored during the lifetime of the application. This
// application uses a MemoryStore store wrapped by a RecentStore with an
// eviction time of 20s (i.e. all data after 20s is deleted from memory).
memStore := appdash.NewMemoryStore()
store := &appdash.RecentStore{
MinEvictAge: 20 * time.Second,
DeleteStore: memStore,
}
// Start the Appdash web UI on port 8700.
//
// This is the actual Appdash web UI -- usable as a Go package itself, We
// embed it directly into our application such that visiting the web server
// on HTTP port 8700 will bring us to the web UI, displaying information
// about this specific web-server (another alternative would be to connect
// to a centralized Appdash collection server).
tapp := traceapp.New(nil)
tapp.Store = store
tapp.Queryer = memStore
log.Println("Appdash web UI running on HTTP :8700")
go func() {
log.Fatal(http.ListenAndServe(":8700", tapp))
}()
// We will use a local collector (as we are running the Appdash web UI
// embedded within our app).
//
// A collector is responsible for collecting the information about traces
// (i.e. spans and annotations) and placing them into a store. In this app
// we use a local collector (we could also use a remote collector, sending
// the information to a remote Appdash collection server).
collector = appdash.NewLocalCollector(store)
// Create the appdash/httptrace middleware.
//
// Here we initialize the appdash/httptrace middleware. It is a Negroni
// compliant HTTP middleware that will generate HTTP events for Appdash to
// display. We could also instruct Appdash with events manually, if we
// wanted to.
tracemw := httptrace.Middleware(collector, &httptrace.MiddlewareConfig{
RouteName: func(r *http.Request) string { return r.URL.Path },
SetContextSpan: func(r *http.Request, spanID appdash.SpanID) {
context.Set(r, CtxSpanID, spanID)
},
})
// Setup our router (for information, see the gorilla/mux docs):
router := mux.NewRouter()
router.HandleFunc("/", Home)
router.HandleFunc("/endpoint", Endpoint)
// Setup Negroni for our app (for information, see the negroni docs):
n := negroni.Classic()
n.Use(negroni.HandlerFunc(tracemw)) // Register appdash's HTTP middleware.
n.UseHandler(router)
n.Run(":8699")
}
// The global HTTP client and transport:
//
// Note: in a high-performance app you would probably want to use a pool of
// reusable HTTP clients, rather than a single one for all requests.
var (
clientLock sync.Mutex
httpTransport = &httptrace.Transport{
SetName: true,
}
httpClient = &http.Client{Transport: httpTransport}
)
// Home is the homepage handler for our app.
func Home(w http.ResponseWriter, r *http.Request) {
// Grab the span from the gorilla context. We do this so that we can grab
// the span.Trace ID and link directly to the trace on the web-page itself!
span := context.Get(r, CtxSpanID).(appdash.SpanID)
// Protect against data races on the client as HTTP handlers are invoked in
// different goroutines.
clientLock.Lock()
defer clientLock.Unlock()
// Assign the transport's event recorder.
httpTransport.Recorder = appdash.NewRecorder(span, collector)
// Make three API requests using our HTTP client.
for i := 0; i < 3; i++ {
resp, err := httpClient.Get("http://localhost:8699/endpoint")
if err != nil {
log.Println("/endpoint:", err)
continue
}
resp.Body.Close()
}
// Render the page.
fmt.Fprintf(w, `<p>Three API requests have been made!</p>`)
fmt.Fprintf(w, `<p><a href="http://localhost:8700/traces/%s" target="_">View the trace (ID:%s)</a></p>`, span.Trace, span.Trace)
}
// Endpoint is an example API endpoint. In a real application, the backend of
// your service would be contacting several external and internal API endpoints
// which may be the bottleneck of your application.
//
// For example purposes we just sleep for 200ms before responding to simulate a
// slow API endpoint as the bottleneck of your application.
func Endpoint(w http.ResponseWriter, r *http.Request) {
time.Sleep(200 * time.Millisecond)
fmt.Fprintf(w, "Slept for 200ms!")
}
from appdash.
I'm going to close this issue as it appears a bit stale. @cgilling if you have any other questions just let me know and I'll re-open this 😃
from appdash.
Related Issues (20)
- slack link
- HTTPS support
- Can't figure how to mount traceapp to anything other than "/" HOT 1
- Remove unmaintained influxdbstore backend
- Python examples: An Issue and a question HOT 2
- Appdash Tracing in microseconds precision HOT 1
- build error "use of internal package not allowed" with thrid-part store implementation.
- webapp example panic: interface conversion: interface {} is nil, not appdash.SpanID HOT 5
- appdash client support java and other language?
- only can store in memory?support redis or mysql in future?
- Slack link in README is not valid HOT 1
- Travis build failing on latest Go version HOT 2
- deadlinks HOT 5
- why Annotations type is slice , not map[string][]byte? HOT 4
- a Span storage specification issue HOT 3
- Setting up appdash in Go, not seeing traces HOT 1
- Dependency Dashboard
- 503 Service Temporarily Unavailable about sourcegraph.com HOT 3
- Error highlighting HOT 2
- Regression in change from fmt to strconv HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from appdash.