From c3d22a40db7f46dbfae8ab73056fe72bacaf1125 Mon Sep 17 00:00:00 2001 From: Thomas Verchow Date: Thu, 19 Dec 2019 23:24:41 +0100 Subject: [PATCH] tcp from Soontao/cachet-monitor # Conflicts: # .gitignore # cli/main.go --- cli/main.go | 6 +++- example.config.json | 52 +++---------------------------- tcp.go | 76 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 48 deletions(-) create mode 100644 tcp.go diff --git a/cli/main.go b/cli/main.go index 5f9ada0..fd021ab 100644 --- a/cli/main.go +++ b/cli/main.go @@ -39,7 +39,7 @@ Options: --version Show version --immediate Tick immediately (by default waits for first defined interval) --restarted Get open incidents before start monitoring (if monitor died or restarted) - + Environment varaibles: CACHET_API override API url from configuration CACHET_TOKEN override API token from configuration @@ -184,6 +184,10 @@ func getConfiguration(path string) (*cachet.CachetMonitor, error) { var s cachet.DNSMonitor err = mapstructure.Decode(rawMonitor, &s) t = &s + case "tcp": + var s cachet.TCPMonitor + err = mapstructure.Decode(rawMonitor, &s) + t = &s default: logrus.Errorf("Invalid monitor type (index: %d) %v", index, monType) continue diff --git a/example.config.json b/example.config.json index 6ec4bbf..ff43d90 100644 --- a/example.config.json +++ b/example.config.json @@ -8,53 +8,11 @@ "slack_webhook": "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX", "monitors": [ { - "name": "google", - "target": "https://google.com", - "strict": true, - "method": "POST", - "component_id": 1, - "metric_id": 4, - "template": { - "investigating": { - "subject": "{{ .Monitor.Name }} - {{ .SystemName }}", - "message": "{{ .Monitor.Name }} check **failed** (server time: {{ .now }})\n\n{{ .FailReason }}" - }, - "fixed": { - "subject": "I HAVE BEEN FIXED" - } - }, - "interval": 1, - "timeout": 1, - "threshold": 80, - "headers": { - "Authorization": "Basic " - }, - "expected_status_code": 200, - "expected_body": "P.*NG" - }, - { - "name": "dns", - "target": "matej.me.", - "question": "mx", - "type": "dns", - "component_id": 2, - "interval": 1, - "timeout": 1, - "dns": "8.8.4.4:53", - "answers": [ - { - "regex": "[1-9] alt[1-9].aspmx.l.google.com." - }, - { - "exact": "10 aspmx2.googlemail.com." - }, - { - "exact": "1 aspmx.l.google.com." - }, - { - "exact": "10 aspmx3.googlemail.com." - } - ] + "name": "IN-Ulm IRC", + "target": "irc.in-ulm.de", + "type": "tcp", + "port": "6660", + "component_id": 4 } ] } diff --git a/tcp.go b/tcp.go new file mode 100644 index 0000000..653d3e4 --- /dev/null +++ b/tcp.go @@ -0,0 +1,76 @@ +// Thanks go to https://github.com/Soontao/cachet-monitor/blob/master/tcp.go +package cachet + +import ( + "fmt" + "net" + "time" +) + +// Investigating template +var defaultTCPInvestigatingTpl = MessageTemplate{ + Subject: `{{ .Monitor.Name }} - {{ .SystemName }}`, + Message: `{{ .Monitor.Name }} check **failed** (server time: {{ .now }}) + +{{ .FailReason }}`, +} + +// Fixed template +var defaultTCPFixedTpl = MessageTemplate{ + Subject: `{{ .Monitor.Name }} - {{ .SystemName }}`, + Message: `**Resolved** - {{ .now }} + +Down seconds: {{ .downSeconds }}s`, +} + +// TCPMonitor struct +type TCPMonitor struct { + AbstractMonitor `mapstructure:",squash"` + Port string +} + +// CheckTCPPortAlive func +func CheckTCPPortAlive(ip, port string, timeout int64) (bool, error) { + + conn, err := net.DialTimeout("tcp", net.JoinHostPort(ip, port), time.Duration(timeout)*time.Second) + if conn != nil { + defer conn.Close() + } + if err != nil { + return false, err + } else { + return true, nil + } + +} + +// test if it available +func (m *TCPMonitor) test() bool { + if alive, e := CheckTCPPortAlive(m.Target, m.Port, int64(m.Timeout)); alive { + return true + } else { + m.lastFailReason = fmt.Sprintf("TCP check failed: %v", e) + return false + } +} + +// Validate configuration +func (m *TCPMonitor) Validate() []string { + + // set incident temp + m.Template.Investigating.SetDefault(defaultTCPInvestigatingTpl) + m.Template.Fixed.SetDefault(defaultTCPFixedTpl) + + // super.Validate() + errs := m.AbstractMonitor.Validate() + + if m.Target == "" { + errs = append(errs, "Target is required") + } + + if m.Port == "" { + errs = append(errs, "Port is required") + } + + return errs +}