1
// Copyright 2014 Canonical Ltd.
2
// Licensed under the LGPLv3, see LICENCE file for details.
4
// Package debugstatus provides facilities for inspecting information
5
// about a running HTTP service.
16
// Check collects the status check results from the given checkers.
17
func Check(checkers ...CheckerFunc) map[string]CheckResult {
19
results := make(map[string]CheckResult, len(checkers))
22
for _, c := range checkers {
29
result.Duration = time.Since(t0)
39
// CheckResult holds the result of a single status check.
40
type CheckResult struct {
41
// Name is the human readable name for the check.
44
// Value is the check result.
47
// Passed reports whether the check passed.
50
// Duration holds the duration that the
51
// status check took to run.
52
Duration time.Duration
55
// CheckerFunc represents a function returning the check machine friendly key
57
type CheckerFunc func() (key string, result CheckResult)
59
// StartTime holds the time that the code started running.
60
var StartTime = time.Now().UTC()
62
// ServerStartTime reports the time when the application was started.
63
func ServerStartTime() (key string, result CheckResult) {
64
return "server_started", CheckResult{
65
Name: "Server started",
66
Value: StartTime.String(),
71
// Connection returns a status checker reporting whether the given Pinger is
73
func Connection(p Pinger) CheckerFunc {
74
return func() (key string, result CheckResult) {
75
result.Name = "MongoDB is connected"
76
if err := p.Ping(); err != nil {
77
result.Value = "Ping error: " + err.Error()
78
return "mongo_connected", result
80
result.Value = "Connected"
82
return "mongo_connected", result
86
// Pinger is an interface that wraps the Ping method.
87
// It is implemented by mgo.Session.
88
type Pinger interface {
92
var _ Pinger = (*mgo.Session)(nil)
94
// MongoCollections returns a status checker checking that all the
95
// expected Mongo collections are present in the database.
96
func MongoCollections(c Collector) CheckerFunc {
97
return func() (key string, result CheckResult) {
98
key = "mongo_collections"
99
result.Name = "MongoDB collections"
100
names, err := c.CollectionNames()
102
result.Value = "Cannot get collections: " + err.Error()
106
for _, coll := range c.Collections() {
108
for _, name := range names {
109
if name == coll.Name {
115
missing = append(missing, coll.Name)
118
if len(missing) == 0 {
119
result.Value = "All required collections exist"
123
result.Value = fmt.Sprintf("Missing collections: %s", missing)
128
// Collector is an interface that groups the methods used to check that
129
// a Mongo database has the expected collections.
130
// It is usually implemented by types extending mgo.Database to add the
131
// Collections() method.
132
type Collector interface {
133
// Collections returns the Mongo collections that we expect to exist in
134
// the Mongo database.
135
Collections() []*mgo.Collection
137
// CollectionNames returns the names of the collections actually present in
138
// the Mongo database.
139
CollectionNames() ([]string, error)
142
// Rename changes the key and/or result name returned by the given check.
143
// It is possible to pass an empty string to avoid changing one of the values.
144
// This means that if both key are name are empty, this closure is a no-op.
145
func Rename(newKey, newName string, check CheckerFunc) CheckerFunc {
146
return func() (key string, result CheckResult) {
147
key, result = check()
152
result.Name = newName
154
return newKey, result