func TestHealthD(t *testing.T) { // Make two sinks: sink := health.NewJsonPollingSink(time.Minute, time.Minute*5) sink.StartServer(":6050") sink.EmitEvent("foo", "bar", nil) sink.EmitTiming("foo", "baz", 1234, nil) sink.EmitComplete("foo", health.Success, 5678, nil) sink2 := health.NewJsonPollingSink(time.Minute, time.Minute*5) sink2.StartServer(":6051") sink2.EmitEvent("foo", "bar", nil) sink2.EmitTiming("foo", "baz", 4321, nil) sink2.EmitComplete("foo", health.ValidationError, 8765, nil) hd := StartNewHealthD([]string{":6050", ":6051"}, ":6060", health.NewStream()) defer func() { hd.Stop() time.Sleep(time.Millisecond) }() time.Sleep(time.Millisecond * 15) testAggregations(t, hd) testAggregationsOverall(t, hd) testJobs(t, hd) testHosts(t, hd) }
func TestPoll(t *testing.T) { setNowMock("2011-09-09T23:36:13Z") defer resetNowMock() intAgg := health.NewIntervalAggregation(now()) data := &health.HealthAggregationsResponse{ InstanceId: "web22.12345", IntervalDuration: time.Minute, IntervalAggregations: []*health.IntervalAggregation{intAgg}, } stop := serveJson(":5050", data) defer func() { stop() }() responses := make(chan *pollResponse, 2) poll(health.NewStream(), ":5050", responses) response := <-responses assert.NotNil(t, response) assert.Equal(t, response.HostPort, ":5050") assert.Equal(t, response.Timestamp, now()) assert.Nil(t, response.Err) assert.Equal(t, response.Code, 200) assert.True(t, response.Nanos > 0 && response.Nanos < int64(time.Second)) assert.Equal(t, response.InstanceId, "web22.12345") // we'll just "trust" that the other stuff gets unmarshalled correctly. We didn't really put anything in there anyway in this test. }
// nice to have's // - handle the case when time goes backwards. // - we need some way to not return all data from clients on every request. Necessary? func main() { // Get inputs. Read from env variables for now (command line options?) monitoredHostPorts := getMonitoredHostPorts() serverHostPort := getServerHostPort() healthHostPort := getHealthHostPort() // Monitor ourselves. This will make our own instrumentation show up in the healthd output // I'm not totally sure we want to do this, but (shrug) seems reasonable right now. monitoredHostPorts = append(monitoredHostPorts, healthHostPort) // Setup our health stream. // Log to stdout and a setup an polling sink stream := health.NewStream() stream.AddSink(&health.WriterSink{os.Stdout}) jsonPollingSink := health.NewJsonPollingSink(time.Minute, time.Minute*5) jsonPollingSink.StartServer(healthHostPort) stream.AddSink(jsonPollingSink) // Say we're starting! stream.EventKv("starting", health.Kvs{ "monitored_host_ports": strings.Join(monitoredHostPorts, ","), "server_host_port": serverHostPort, "health_host_port": healthHostPort, }) // Start the healthd aggregators in a goroutine(s) healthd.StartNewHealthD(monitoredHostPorts, serverHostPort, stream) // Block select {} }
package main import ( "fmt" "net/http" "os" "runtime/debug" "strconv" "time" "github.com/gocraft/health" ) var applicationGCStats = debug.GCStats{} var instrument = health.NewStream() // SetupInstrumentation handles all the intialisation of the instrumentation handler func SetupInstrumentation(enabled bool) { thisInstr := os.Getenv("TYK_INSTRUMENTATION") if thisInstr == "1" { enabled = true } if !enabled { return } if config.StatsdConnectionString == "" { log.Error("Instrumentation is enabled, but no connectionstring set for statsd") return
"github.com/gocraft/health" "github.com/gocraft/web" "github.com/nu7hatch/gouuid" "io" "net/http" "runtime" "strconv" ) type Context struct { Job *health.Job Panic bool } var ( stream = health.NewStream() router = web.New(Context{}) ) func init() { router.Middleware((*Context).Log) router.Middleware((*Context).CatchPanics) router.Middleware((*Context).SetContentType) router.Middleware((*Context).Cors) router.NotFound((*Context).NotFound) } func ListenAndServe(addr string, sink io.Writer) { if sink != nil { stream.AddSink(&health.WriterSink{sink}) }