diff options
| author | Shulhan <ms@kilabit.info> | 2026-01-21 01:12:11 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2026-01-21 01:12:11 +0700 |
| commit | fa4cc3a2ae6fa63bfbd8b005e4048dacc222dcc1 (patch) | |
| tree | b5566fe088dc51364101ab1db2a48ed845a4d832 | |
| parent | d0969869954c299c04ea58ab0fda1eba6a0350da (diff) | |
| download | lilin-fa4cc3a2ae6fa63bfbd8b005e4048dacc222dcc1.tar.xz | |
all: implement default down and up templates under section "[default"]
To minimize defining the same templates in notification, user can set
default down and up templates under the default section.
| -rw-r--r-- | README.md | 113 | ||||
| -rw-r--r-- | lilin.go | 3 | ||||
| -rw-r--r-- | notif_config.go | 10 | ||||
| -rw-r--r-- | notif_config_test.go | 3 | ||||
| -rw-r--r-- | server_config.go | 27 | ||||
| -rw-r--r-- | server_config_test.go | 11 |
6 files changed, 114 insertions, 53 deletions
@@ -9,9 +9,10 @@ Lilin is service monitoring for HTTP and TCP services. Features, -- Monitoring HTTP, TCP, UDP services +- Monitoring HTTP and TCP services - Sending notification when service up or down through, - Mattermost incoming webhook + - SMTP server (email) ## Building @@ -25,7 +26,9 @@ to build the program, The above command will create executable file named `lilin` in the current directory. -## Command options +## Usage + +### Command options The lilin program has the following options, @@ -33,7 +36,7 @@ The lilin program has the following options, service configurations, and storing the service logs. If not defined, its default to "/". -## Main configuration +### Main configuration Lilin read the main configuration from `${BASEDIR}etc/lilin/lilin.cfg`. The configuration is written in @@ -48,17 +51,52 @@ For example, The `lilin.cfg` has the following format, ``` +[default] +down_template = Service {{.ID}} is down: {{.Error}} +up_template = Service {{.ID}} is alive! + [server] -address = +address = 127.0.0.1:14507 +``` + +The `[default]` section define the default value for common configuration. + +The `down_template` and `up_template` define the text template to be send +for notification when the service down or up. +If its empty, it will use the default one (as written above). +The `down_template` and `up_template` can contains the following variables, + +- .ID: the service ID +- .At: the time when service up or down +- .Error: the error message that cause the service marked as down + +For example, given the following scan report value, + +``` +.ID: http-server +.At: 2025-09-26 06:38:11 +0000 UTC +.Error: 503 Service Unavailable +``` + +The following `down_template` + +``` +{{.At}}: Service {{.ID}} is down: {{.Error}} +``` + +will be rendered as + +``` +2025-09-26 06:38:11 +0000 UTC: Service http-server is down: 503 Service Unavailable ``` -**address**:: define the HTTP server address to view the status of monitored -services from web browser, default to 127.0.0.1:14507. +The server `address` define the HTTP server address to view the status +of monitored services from web browser, default to 127.0.0.1:14507. -## Monitoring services +### Monitoring services Lilin monitor the services by reading each service configuration inside the -`${BASEDIR}etc/lilin/service.d/` directory. +`${BASEDIR}/etc/lilin/service.d/` directory. Each service configuration is written in INI file format and must have `.cfg` file extension. @@ -81,7 +119,6 @@ For example - `http://example.com/health` for monitoring HTTP service, - `https://example.com:8443/health` for monitoring HTTPS service, - `tcp://127.0.0.1:22` for monitoring TCP service, -- `udp://127.0.0.1:53` for monitoring UDP service. **method**:: The HTTP method to be used to inquiry the HTTP or HTTPS service, default to GET. @@ -111,7 +148,7 @@ interval = 5m timeout = 60s ``` -Sample of service configuration that monitor TCP service at +Example of service configuration that monitor TCP service at 127.0.0.1:5432 every 90 seconds with 30 seconds timeout, ``` @@ -124,11 +161,16 @@ timeout = 30s ## Notification +Lilin send the down notification when the service check failed three times +consecutively. + Lilin support sending notification to, - Mattermost using incoming webhook. - SMTP server (email). +Each notification can have their own `down_template` and `up_template`. + See the next section on how to use the notification. ### Mattermost incoming webhook @@ -147,32 +189,6 @@ down_template = # Message template when service is down. up_template = # Message template when service is up. ``` -The `down_template` and `up_template` can contains the following variables, - -- .ID: the service ID -- .At: the time when service up or down -- .Error: the error message that cause the service marked as down - -For example, given the following scan report value, - -``` -.ID: http-server -.At: 2025-09-26 06:38:11 +0000 UTC -.Error: 503 Service Unavailable -``` - -The following `down_template` - -``` -{{.At}}: Service {{.ID}} is down: {{.Error}} -``` - -will be rendered as - -``` -2025-09-26 06:38:11 +0000 UTC: Service http-server is down: 503 Service Unavailable -``` - <!--}}}--> ### SMTP server @@ -183,9 +199,11 @@ will be rendered as [notif] kind = smtp remote_url = <scheme "://" (domain | ip_address [":" port])> -user = -password = -recipient = +user = # Sender email address. +password = # Sender SMTP password for authentication. +recipient = # Email address that receive notification. +down_template = # Custom text to be send when service down. +up_template = # Custom text to be send when service up. ``` The `remote_url` define the SMTP server address. @@ -194,27 +212,26 @@ The scheme in `remote_url` can be set either to, - smtps: implicit TLS, connect to port 465 by default - smtp+starttls: explicit STARTTLS, connect to port 587 by default. -The `user` field define the sender email address. +The `recipient` field can be defined multiple times. -The `password` field define the password for authentication, on behalf of -the `user`. +<!--}}}--> -The `recipient` is the email address that will receives the notification. -This field can be defined multiple times. +## License -<!--}}}--> +Lilin is licensed under GPL version 3.0. +See LICENSE file for more information. ## Links [Project page](https://sr.ht/~shulhan/lilin). -[Repository](https://git.sr.ht/~shulhan/lilin) -- +[Repository](https://git.sr.ht/~shulhan/lilin) - The repository of this software project. -[Mailing list](https://lists.sr.ht/~shulhan/lilin) -- +[Mailing list](https://lists.sr.ht/~shulhan/lilin) - Place for discussion and sending patches. -[Issues](https://todo.sr.ht/~shulhan/lilin) -- +[Issues](https://todo.sr.ht/~shulhan/lilin) - Place to open new issue or request for new feature. [Changelog](https://kilabit.info/project/lilin/CHANGELOG.html) - Log for @@ -17,5 +17,8 @@ const defTimeout = 5 * time.Second // defAddress default server address. const defAddress = `127.0.0.1:14507` +const defaultDownTemplate = `Service {{.ID}} is down: {{.Error}}` +const defaultUpTemplate = `Service {{.ID}} is alive!` + //go:embed _www var wwwFS embed.FS diff --git a/notif_config.go b/notif_config.go index c3ed43c..ca1a66b 100644 --- a/notif_config.go +++ b/notif_config.go @@ -43,7 +43,7 @@ type NotifConfig struct { Recipient []string `ini:"notif::recipient"` } -func (notifConfig *NotifConfig) init() (err error) { +func (notifConfig *NotifConfig) init(cfg *ServerConfig) (err error) { var logp = `notifConfig.init` switch notifConfig.Kind { @@ -66,7 +66,9 @@ func (notifConfig *NotifConfig) init() (err error) { default: return fmt.Errorf(`%s: unknown notif kind %q`, logp, notifConfig.Kind) } - if notifConfig.DownTemplate != "" { + if notifConfig.DownTemplate == `` { + notifConfig.downTmpl = cfg.downTmpl + } else { notifConfig.downTmpl = template.New(`down`) notifConfig.downTmpl, err = notifConfig.downTmpl.Parse(notifConfig.DownTemplate) if err != nil { @@ -74,7 +76,9 @@ func (notifConfig *NotifConfig) init() (err error) { logp, notifConfig.Kind, err) } } - if notifConfig.UpTemplate != "" { + if notifConfig.UpTemplate == `` { + notifConfig.upTmpl = cfg.upTmpl + } else { notifConfig.upTmpl = template.New(`up`) notifConfig.upTmpl, err = notifConfig.upTmpl.Parse(notifConfig.UpTemplate) if err != nil { diff --git a/notif_config_test.go b/notif_config_test.go index b7990b1..4c63e60 100644 --- a/notif_config_test.go +++ b/notif_config_test.go @@ -41,8 +41,9 @@ func TestNotifConfig_init(t *testing.T) { }, }, }} + cfg := &ServerConfig{} for _, tc := range listCase { - err := tc.config.init() + err := tc.config.init(cfg) if err != nil { test.Assert(t, ``, tc.expError, err.Error()) continue diff --git a/server_config.go b/server_config.go index c9c553c..2a320a2 100644 --- a/server_config.go +++ b/server_config.go @@ -5,6 +5,7 @@ package lilin import ( "fmt" + "html/template" "os" "path/filepath" @@ -13,6 +14,9 @@ import ( // ServerConfig define the options for Lilin Server. type ServerConfig struct { + downTmpl *template.Template + upTmpl *template.Template + // BaseDir define the base directory for running the server, default // to "/". // Its affect where to read the configuration, storing states, and @@ -28,6 +32,9 @@ type ServerConfig struct { // The BaseDir + "/var/log/lilin/service.d/". logServiceDir string + DownTemplate string `ini:"default::down_template"` + UpTemplate string `ini:"default::up_template"` + // The address to listen for HTTP server and APIs. Address string `ini:"server::address"` @@ -78,8 +85,26 @@ func (cfg *ServerConfig) init() (err error) { cfg.Address = defAddress } + if cfg.DownTemplate == `` { + cfg.DownTemplate = defaultDownTemplate + } + cfg.downTmpl = template.New(`down`) + cfg.downTmpl, err = cfg.downTmpl.Parse(cfg.DownTemplate) + if err != nil { + return fmt.Errorf(`%s: failed to parse down_template: %s`, logp, err) + } + + if cfg.UpTemplate == `` { + cfg.UpTemplate = defaultUpTemplate + } + cfg.upTmpl = template.New(`up`) + cfg.upTmpl, err = cfg.upTmpl.Parse(cfg.DownTemplate) + if err != nil { + return fmt.Errorf(`%s: failed to parse down_template: %s`, logp, err) + } + for _, notifConfig := range cfg.Notifs { - err = notifConfig.init() + err = notifConfig.init(cfg) if err != nil { return fmt.Errorf(`%s: %w`, logp, err) } diff --git a/server_config_test.go b/server_config_test.go index bd17b5e..56542d6 100644 --- a/server_config_test.go +++ b/server_config_test.go @@ -37,6 +37,8 @@ func TestServerConfig_init(t *testing.T) { configServiceDir: `testdata/server_config/ok/etc/lilin/service.d`, logServiceDir: `testdata/server_config/ok/var/log/lilin/service.d`, Address: `127.0.0.1:12121`, + DownTemplate: defaultDownTemplate, + UpTemplate: defaultUpTemplate, Notifs: []*NotifConfig{{ Kind: `mattermost`, RemoteURL: `http://127.0.0.1:12000`, @@ -76,6 +78,15 @@ func TestServerConfig_init(t *testing.T) { t.Fatal(err) } + if cfg.upTmpl == nil { + t.Fatal(`ServerConfig: got nil on upTmpl, want not-nil`) + } + if cfg.downTmpl == nil { + t.Fatal(`ServerConfig: got nil on downTmpl, want not-nil`) + } + cfg.upTmpl = nil + cfg.downTmpl = nil + for x, notifCfg := range cfg.Notifs { if notifCfg.upTmpl == nil { t.Fatalf(`ServerConfig.Notifs #%d: upTmpl is nil`, x) |
