-
Notifications
You must be signed in to change notification settings - Fork 48
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
105 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
package collectors | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"sync" | ||
"time" | ||
|
||
"github.com/lightninglabs/lndclient" | ||
"github.com/prometheus/client_golang/prometheus" | ||
) | ||
|
||
type StateCollector struct { | ||
lnd *lndclient.LndServices | ||
|
||
// Use one gauge to track the starting time of LND. | ||
timeToStartDesc *prometheus.Desc | ||
|
||
// startTime records a best-effort timestamp of when LND was started. | ||
startTime time.Time | ||
|
||
// endTime records when LND makes a transition from RPC_ACTIVE to | ||
// SERVER_ACTIVE. | ||
endTime time.Time | ||
|
||
// mutex is a lock for preventing concurrent writes to startTime or | ||
// endTime. | ||
mutex sync.RWMutex | ||
|
||
// errChan is a channel that we send any errors that we encounter into. | ||
// This channel should be buffered so that it does not block sends. | ||
errChan chan<- error | ||
} | ||
|
||
// NewStateCollector returns a new instance of the StateCollector. | ||
func NewStateCollector(lnd *lndclient.LndServices, | ||
errChan chan<- error) *StateCollector { | ||
|
||
sc := &StateCollector{ | ||
lnd: lnd, | ||
timeToStartDesc: prometheus.NewDesc( | ||
"lnd_time_to_start_secs", | ||
"time to start in seconds", | ||
nil, nil, | ||
), | ||
errChan: errChan, | ||
} | ||
|
||
go sc.monitorStateChanges() | ||
return sc | ||
} | ||
|
||
// monitorStateChanges checks the state every second to catch fast transitions. | ||
func (s *StateCollector) monitorStateChanges() { | ||
for { | ||
state, err := s.lnd.State.GetState(context.Background()) | ||
if err != nil { | ||
s.errChan <- fmt.Errorf("StateCollector GetState failed with: %v", err) | ||
continue | ||
} | ||
|
||
serverActiveReached := false | ||
s.mutex.Lock() | ||
if state.String() == "RPC_ACTIVE" { | ||
s.startTime = time.Now() | ||
} else if state.String() == "SERVER_ACTIVE" && !s.startTime.IsZero() { | ||
s.endTime = time.Now() | ||
serverActiveReached = true | ||
} | ||
s.mutex.Unlock() | ||
|
||
if serverActiveReached { | ||
break | ||
} else { | ||
time.Sleep(1 * time.Second) | ||
} | ||
} | ||
} | ||
|
||
// Describe sends the super-set of all possible descriptors of metrics | ||
// collected by this Collector to the provided channel and returns once the | ||
// last descriptor has been sent. | ||
// | ||
// NOTE: Part of the prometheus.Collector interface. | ||
func (s *StateCollector) Describe(ch chan<- *prometheus.Desc) { | ||
ch <- s.timeToStartDesc | ||
} | ||
|
||
// Collect is called by the Prometheus registry when collecting metrics. | ||
// | ||
// NOTE: Part of the prometheus.Collector interface. | ||
func (s *StateCollector) Collect(ch chan<- prometheus.Metric) { | ||
// Lock for read | ||
s.mutex.RLock() | ||
defer s.mutex.RUnlock() | ||
|
||
// We have set both a startTime and endTime, calculate the difference and emit a metric. | ||
if !s.startTime.IsZero() && !s.endTime.IsZero() { | ||
timeToStartInSecs := s.endTime.Sub(s.startTime).Seconds() | ||
ch <- prometheus.MustNewConstMetric( | ||
s.timeToStartDesc, prometheus.GaugeValue, timeToStartInSecs, | ||
) | ||
} | ||
} |