Server
The Go CDK’s server
package provides a pre-configured HTTP server with
diagnostic hooks for request logging, health checks, and trace exporting via
OpenCensus. This guide will show you how to start up and shut down the server,
as well as how to work with the request logging and health checks.
Starting up the server🔗
The Go CDK Server constructor takes an http.Handler
and an Options
struct.
The simplest way to start the server is to use http.DefaultServeMux
and
pass nil
for the options.
import (
"fmt"
"net/http"
"gocloud.dev/server"
)
// Use the constructor function to create the server.
srv := server.New(http.DefaultServeMux, nil)
// Register a route.
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, World!")
})
// Start the server. If ListenAndServe returns an error, print it and exit.
if err := srv.ListenAndServe(":8080"); err != nil {
log.Fatalf("%v", err)
}
Adding a request logger🔗
You can use the server.Options
struct to specify a request logger.
The example is shown with the Go CDK requestlog
package’s NCSALogger
.
To get logs in the Stackdriver JSON format, use NewStackdriverLogger
in place
of NewNCSALogger
.
import (
"fmt"
"net/http"
"os"
"gocloud.dev/server"
"gocloud.dev/server/requestlog"
)
// Create a logger, and assign it to the RequestLogger field of a
// server.Options struct.
srvOptions := &server.Options{
RequestLogger: requestlog.NewNCSALogger(os.Stdout, func(error) {}),
}
// Pass the options to the Server constructor.
srv := server.New(http.DefaultServeMux, srvOptions)
// Register a route.
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, World!")
})
// Start the server. You will see requests logged to STDOUT.
if err := srv.ListenAndServe(":8080"); err != nil {
log.Fatalf("%v", err)
}
Adding health checks🔗
The Go CDK server
package affords a hook for you to define health checks for
your application and see the results at /healthz/readiness
. The server also
runs an endpoint at /healthz/liveness
, which is a conventional name for a
liveness check and is where Kubernetes, if you are using it, will look.
Health checks are an important part of application monitoring, and readiness
checks are subtly different than liveness checks. The liveness check will return
200 OK
if the server can serve requests. But because each application may have
a different definition of what it means to be “healthy” (perhaps your
application has a dependency on a back end service), you will need to define a
concrete type to implement the health.Checker
interface and define a
CheckHealth
method specific to your application for readiness checks.
// customHealthCheck is an example health check. It implements the
// health.Checker interface and reports the server is healthy when the healthy
// field is set to true.
type customHealthCheck struct {
mu sync.RWMutex
healthy bool
}
// customHealthCheck implements the health.Checker interface because it has a
// CheckHealth method.
func (h *customHealthCheck) CheckHealth() error {
h.mu.RLock()
defer h.mu.RUnlock()
if !h.healthy {
return errors.New("not ready yet!")
}
return nil
}
import (
"fmt"
"net/http"
"time"
"gocloud.dev/server"
"gocloud.dev/server/health"
)
// Create a health.Checker from the type we defined for our application.
// In this example, healthCheck will report the server is unhealthy for 10 seconds
// after startup, and as healthy henceforth. Check the /healthz/readiness
// HTTP path to see readiness.
healthCheck := new(customHealthCheck)
time.AfterFunc(10*time.Second, func() {
healthCheck.mu.Lock()
defer healthCheck.mu.Unlock()
healthCheck.healthy = true
})
// The server.Options struct takes a slice of health checks, because you
// may need to check several things.
srvOptions := &server.Options{
HealthChecks: []health.Checker{healthCheck},
}
// Pass the options to the Server constructor.
srv := server.New(http.DefaultServeMux, srvOptions)
// Register a route.
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, World!")
})
// Start the server. You will see requests logged to STDOUT.
if err := srv.ListenAndServe(":8080"); err != nil {
log.Fatalf("%v", err)
}