Skip to content

Commit 313cdc6

Browse files
committed
add diagnostics module to allow exposing peers list (and other data) as the JSON document
1 parent 63460aa commit 313cdc6

1 file changed

Lines changed: 79 additions & 0 deletions

File tree

pkg/diagnostics/diagnostics.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Package `diagnostics` provides some tools useful for gathering and
2+
// exposing arbitrary diagnositcs information for external monitoring tools.
3+
//
4+
// Possible usage: integration nodes list into dashboard
5+
package diagnostics
6+
7+
import (
8+
"encoding/json"
9+
"io"
10+
"net/http"
11+
"strconv"
12+
"sync"
13+
14+
"github.com/ipfs/go-log"
15+
)
16+
17+
var logger = log.Logger("keep-diagnostics")
18+
19+
// Registry performs all management of diagnostic. Specifically, it allows
20+
// to registering new diagnostics sources and exposing them through the diagnostics server.
21+
type DiagnosticsRegistry struct {
22+
diagnosticsSources map[string]func() string
23+
diagnosticsMutex sync.RWMutex
24+
}
25+
26+
// NewRegistry creates a new metrics registry.
27+
func NewRegistry() *DiagnosticsRegistry {
28+
return &DiagnosticsRegistry{
29+
diagnosticsSources: make(map[string]func() string),
30+
}
31+
}
32+
33+
// EnableServer enables the diagnostics server on the given port. Data will
34+
// be exposed on `/diagnostics` path in JSON format.
35+
func (r *DiagnosticsRegistry) EnableServer(port int) {
36+
server := &http.Server{Addr: ":" + strconv.Itoa(port)}
37+
38+
http.HandleFunc("/diagnostics", func(response http.ResponseWriter, _ *http.Request) {
39+
if _, err := io.WriteString(response, r.exposeDiagnostics()); err != nil {
40+
logger.Errorf("could not write response: [%v]", err)
41+
}
42+
})
43+
44+
go func() {
45+
if err := server.ListenAndServe(); err != http.ErrServerClosed {
46+
logger.Errorf("diagnostics server error: [%v]", err)
47+
}
48+
}()
49+
}
50+
51+
func (r *DiagnosticsRegistry) RegisterSource(name string, source func() string) {
52+
r.diagnosticsMutex.Lock()
53+
defer r.diagnosticsMutex.Unlock()
54+
55+
r.diagnosticsSources[name] = source
56+
}
57+
58+
// Exposes all registered diagnostics sources in a single JSON document.
59+
func (r *DiagnosticsRegistry) exposeDiagnostics() string {
60+
r.diagnosticsMutex.RLock()
61+
defer r.diagnosticsMutex.RUnlock()
62+
63+
diagnostics := make(map[string]interface{})
64+
for sourceName, sourceGetter := range r.diagnosticsSources {
65+
var jsonString = sourceGetter()
66+
var jsonObject interface{}
67+
err := json.Unmarshal([]byte(jsonString), &jsonObject)
68+
if err == nil {
69+
diagnostics[sourceName] = jsonObject
70+
}
71+
}
72+
73+
bytes, err := json.Marshal(diagnostics)
74+
if err != nil {
75+
return ""
76+
}
77+
78+
return string(bytes)
79+
}

0 commit comments

Comments
 (0)