forked from gnolang/gno
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add watchdog and monit (gnolang#2329)
This PR introduces the `r/gnoland/monit` realm, which can be used by an external tool to verify if everything is working well, including: - gnokey compatibility (and all the tx/amino/etc) - networking (rpc) - realm state persistency (counter should be higher than the previous value) In addition to being a good target for an external monitoring agent, the realm displays (`Render`) some information, including whether the agent appears to be missing. - [x] improve ownable (depends on gnolang#2330) - [x] p/demo/watchdog - [x] r/gnoland/monit - [ ] ~update contribs/autocounterd~ -> let's @gnolang/devops tackle this in another PR. -> gnolang#1443 --------- Signed-off-by: moul <[email protected]> Co-authored-by: Miloš Živković <[email protected]>
- Loading branch information
Showing
6 changed files
with
181 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module gno.land/p/demo/watchdog | ||
|
||
require gno.land/p/demo/uassert v0.0.0-latest |
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,39 @@ | ||
package watchdog | ||
|
||
import "time" | ||
|
||
type Watchdog struct { | ||
Duration time.Duration | ||
lastUpdate time.Time | ||
lastDown time.Time | ||
} | ||
|
||
func (w *Watchdog) Alive() { | ||
now := time.Now() | ||
if !w.IsAlive() { | ||
w.lastDown = now | ||
} | ||
w.lastUpdate = now | ||
} | ||
|
||
func (w Watchdog) Status() string { | ||
if w.IsAlive() { | ||
return "OK" | ||
} | ||
return "KO" | ||
} | ||
|
||
func (w Watchdog) IsAlive() bool { | ||
return time.Since(w.lastUpdate) < w.Duration | ||
} | ||
|
||
func (w Watchdog) UpSince() time.Time { | ||
return w.lastDown | ||
} | ||
|
||
func (w Watchdog) DownSince() time.Time { | ||
if !w.IsAlive() { | ||
return w.lastUpdate | ||
} | ||
return time.Time{} | ||
} |
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,16 @@ | ||
package watchdog | ||
|
||
import ( | ||
"testing" | ||
"time" | ||
|
||
"gno.land/p/demo/uassert" | ||
) | ||
|
||
func TestPackage(t *testing.T) { | ||
w := Watchdog{Duration: 5 * time.Minute} | ||
uassert.False(t, w.IsAlive()) | ||
w.Alive() | ||
uassert.True(t, w.IsAlive()) | ||
// XXX: add more tests when we'll be able to "skip time". | ||
} |
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,8 @@ | ||
module gno.land/r/gnoland/monit | ||
|
||
require ( | ||
gno.land/p/demo/ownable v0.0.0-latest | ||
gno.land/p/demo/uassert v0.0.0-latest | ||
gno.land/p/demo/ufmt v0.0.0-latest | ||
gno.land/p/demo/watchdog v0.0.0-latest | ||
) |
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,59 @@ | ||
// Package monit links a monitoring system with the chain in both directions. | ||
// | ||
// The agent will periodically call Incr() and verify that the value is always | ||
// higher than the previously known one. The contract will store the last update | ||
// time and use it to detect whether or not the monitoring agent is functioning | ||
// correctly. | ||
package monit | ||
|
||
import ( | ||
"std" | ||
"time" | ||
|
||
"gno.land/p/demo/ownable" | ||
"gno.land/p/demo/ufmt" | ||
"gno.land/p/demo/watchdog" | ||
) | ||
|
||
var ( | ||
counter int | ||
lastUpdate time.Time | ||
lastCaller std.Address | ||
wd = watchdog.Watchdog{Duration: 5 * time.Minute} | ||
owner = ownable.New() // TODO: replace with -> ownable.NewWithAddress... | ||
watchdogDuration = 5 * time.Minute | ||
) | ||
|
||
// Incr increments the counter and informs the watchdog that we're alive. | ||
// This function can be called by anyone. | ||
func Incr() int { | ||
counter++ | ||
lastUpdate = time.Now() | ||
lastCaller = std.PrevRealm().Addr() | ||
wd.Alive() | ||
return counter | ||
} | ||
|
||
// Reset resets the realm state. | ||
// This function can only be called by the admin. | ||
func Reset() { | ||
if owner.CallerIsOwner() != nil { // TODO: replace with owner.AssertCallerIsOwner | ||
panic("unauthorized") | ||
} | ||
counter = 0 | ||
lastCaller = std.PrevRealm().Addr() | ||
lastUpdate = time.Now() | ||
wd = watchdog.Watchdog{Duration: 5 * time.Minute} | ||
} | ||
|
||
func Render(_ string) string { | ||
status := wd.Status() | ||
return ufmt.Sprintf( | ||
"counter=%d\nlast update=%s\nlast caller=%s\nstatus=%s", | ||
counter, lastUpdate, lastCaller, status, | ||
) | ||
} | ||
|
||
// TransferOwnership transfers ownership to a new owner. This is a proxy to | ||
// ownable.Ownable.TransferOwnership. | ||
func TransferOwnership(newOwner std.Address) { owner.TransferOwnership(newOwner) } |
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,56 @@ | ||
package monit | ||
|
||
import ( | ||
"testing" | ||
|
||
"gno.land/p/demo/uassert" | ||
) | ||
|
||
func TestPackage(t *testing.T) { | ||
// initial state, watchdog is KO. | ||
{ | ||
expected := `counter=0 | ||
last update=0001-01-01 00:00:00 +0000 UTC | ||
last caller= | ||
status=KO` | ||
got := Render("") | ||
uassert.Equal(t, expected, got) | ||
} | ||
|
||
// call Incr(), watchdog is OK. | ||
Incr() | ||
Incr() | ||
Incr() | ||
{ | ||
expected := `counter=3 | ||
last update=2009-02-13 23:31:30 +0000 UTC m=+1234567890.000000001 | ||
last caller=g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm | ||
status=OK` | ||
got := Render("") | ||
uassert.Equal(t, expected, got) | ||
} | ||
|
||
/* XXX: improve tests once we've the missing std.TestSkipTime feature | ||
// wait 1h, watchdog is KO. | ||
use std.TestSkipTime(time.Hour) | ||
{ | ||
expected := `counter=3 | ||
last update=2009-02-13 22:31:30 +0000 UTC m=+1234564290.000000001 | ||
last caller=g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm | ||
status=KO` | ||
got := Render("") | ||
uassert.Equal(t, expected, got) | ||
} | ||
// call Incr(), watchdog is OK. | ||
Incr() | ||
{ | ||
expected := `counter=4 | ||
last update=2009-02-13 23:31:30 +0000 UTC m=+1234567890.000000001 | ||
last caller=g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm | ||
status=OK` | ||
got := Render("") | ||
uassert.Equal(t, expected, got) | ||
} | ||
*/ | ||
} |