diff --git a/exporter/html.go b/exporter/html.go
index e8537e22..137d31d4 100644
--- a/exporter/html.go
+++ b/exporter/html.go
@@ -12,22 +12,7 @@ import (
var htmlTemplate string
func HTMLExporter(s *store.Store) http.HandlerFunc {
- tmpl := template.Must(template.New("status").Funcs(template.FuncMap{
- "each_runes": func(s string) []string {
- r := make([]string, len(s))
- for i, c := range []rune(s) {
- r[i] = string(c)
- }
- return r
- },
- "invert_incidents": func(xs []frozenIncident) []frozenIncident {
- rs := make([]frozenIncident, len(xs))
- for i, x := range xs {
- rs[len(xs)-i-1] = x
- }
- return rs
- },
- }).Parse(htmlTemplate))
+ tmpl := template.Must(template.New("status.html").Funcs(templateFuncs).Parse(htmlTemplate))
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html; charset=UTF-8")
diff --git a/exporter/templates.go b/exporter/templates.go
new file mode 100644
index 00000000..b78c769e
--- /dev/null
+++ b/exporter/templates.go
@@ -0,0 +1,41 @@
+package exporter
+
+import (
+ "strings"
+)
+
+var (
+ templateFuncs = map[string]interface{}{
+ "each_runes": func(s string) []string {
+ r := make([]string, len(s))
+ for i, c := range []rune(s) {
+ r[i] = string(c)
+ }
+ return r
+ },
+ "invert_incidents": func(xs []frozenIncident) []frozenIncident {
+ rs := make([]frozenIncident, len(xs))
+ for i, x := range xs {
+ rs[len(xs)-i-1] = x
+ }
+ return rs
+ },
+ "break_text": func(s string, width int) []string {
+ r := []string{}
+ for start := 0; start < len(s); start += width {
+ end := start + width
+ if end >= len(s) {
+ end = len(s)
+ }
+ r = append(r, s[start:end])
+ }
+ return r
+ },
+ "align_center": func(s string, width int) string {
+ if len(s) > width {
+ return s
+ }
+ return strings.Repeat(" ", (width-len(s))/2) + s
+ },
+ }
+)
diff --git a/exporter/templates/status.txt b/exporter/templates/status.txt
new file mode 100644
index 00000000..fed759ed
--- /dev/null
+++ b/exporter/templates/status.txt
@@ -0,0 +1,44 @@
+───────────────────────────────┤ Current Status ├───────────────────────────────
+{{ range .CurrentStatus }}
+┌─ {{ .Target }}
+└{{ range .History | each_runes }}{{
+ if eq . "-" }}─{{ end }}{{
+ if eq . "?" }}━{{ end }}{{
+ if eq . "F" }}!{{ end }}{{
+ if eq . "O" }}✓{{ end }}{{ end }}┤ updated: {{ .Updated }}
+{{ end }}
+
+──────────────────────────────┤ Current Incident ├──────────────────────────────
+{{ range .CurrentIncidents | invert_incidents }}
+┳━ {{
+ if eq .Status "FAIL"
+ }}!FAILURE!{{
+ else
+ }}━UNKNOWN━{{
+ end
+ }} ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳
+┃{{ printf "%-78s" .Target }}┃
+┃ {{ printf "%-77s" (printf "%s - continue" .CausedAt) }}┃
+┃ ┃{{ range (break_text .Message 78) }}
+┃{{ printf "%-78s" . }}┃{{ end }}
+┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻
+{{ end }}
+
+──────────────────────────────┤ Incident History ├──────────────────────────────
+{{ range .IncidentHistory | invert_incidents }}
+┌─ {{
+ if eq .Status "FAIL"
+ }}!FAILURE!{{
+ else
+ }}━UNKNOWN━{{
+ end
+ }} ──────────────────────────────────────────────────────────────────┐
+│{{ printf "%-78s" .Target }}│
+│ {{ printf "%-77s" (printf "%s - %s" .CausedAt .ResolvedAt) }}│
+│ │{{ range (break_text .Message 78) }}
+│{{ printf "%-78s" . }}│{{ end }}
+└──────────────────────────────────────────────────────────────────────────────┘
+{{ end }}
+
+ ──────────────────────────────
+{{ align_center (printf "Reported by Ayd? (%s)" .ReportedAt) 80 }}
diff --git a/exporter/text.go b/exporter/text.go
index 85fec6a9..15d3aca9 100644
--- a/exporter/text.go
+++ b/exporter/text.go
@@ -1,100 +1,22 @@
package exporter
import (
- "fmt"
+ _ "embed"
"net/http"
- "strings"
- "time"
+ "text/template"
"github.com/macrat/ayd/store"
)
-func TextExporter(s *store.Store) http.HandlerFunc {
- showIncidentBox := func(w http.ResponseWriter, i *store.Incident, bold bool) {
- banner := "━UNKNOWN━"
- if i.Status == store.STATUS_FAIL {
- banner = "!FAILURE!"
- }
-
- vert := ""
- if bold {
- fmt.Fprintf(w, "┳━ %s ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳\n", banner)
- vert = "┃"
- } else {
- fmt.Fprintf(w, "┌─ %s ──────────────────────────────────────────────────────────────────┐\n", banner)
- vert = "│"
- }
-
- fmt.Fprintf(w, "%s%-78s%s\n", vert, i.Target, vert)
-
- period := fmt.Sprintf("%s - continue", i.CausedAt.Format(time.RFC3339))
- if !i.ResolvedAt.IsZero() {
- period = fmt.Sprintf("%s - %s", i.CausedAt.Format(time.RFC3339), i.ResolvedAt.Format(time.RFC3339))
- }
- fmt.Fprintf(w, "%s %-77s%s\n", vert, period, vert)
-
- fmt.Fprint(w, vert, strings.Repeat(" ", 78), vert, "\n")
+//go:embed templates/status.txt
+var textTemplate string
- for offset := 0; offset < len(i.Message); offset += 78 {
- end := offset + 78
- if end >= len(i.Message) {
- end = len(i.Message) - 1
- }
- fmt.Fprintf(w, "%s%-78s%s\n", vert, i.Message[offset:end], vert)
- }
-
- if bold {
- fmt.Fprintln(w, "┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻")
- } else {
- fmt.Fprintln(w, "└──────────────────────────────────────────────────────────────────────────────┘")
- }
- }
+func TextExporter(s *store.Store) http.HandlerFunc {
+ tmpl := template.Must(template.New("status.txt").Funcs(templateFuncs).Parse(textTemplate))
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain; charset=UTF-8")
- fmt.Fprintln(w, "───────────────────────────────┤ Current Status ├───────────────────────────────")
- fmt.Fprintln(w)
-
- for _, history := range s.ProbeHistory.AsSortedArray() {
- fmt.Fprint(w, " ┌─ ", history.Target, "\n")
- fmt.Fprint(w, " └", strings.Repeat("─", store.PROBE_HISTORY_LEN-len(history.Results)))
-
- for _, r := range history.Results {
- switch r.Status {
- case store.STATUS_OK:
- fmt.Fprintf(w, "✓")
- case store.STATUS_FAIL:
- fmt.Fprintf(w, "!")
- default:
- fmt.Fprintf(w, "━")
- }
- }
-
- fmt.Fprint(w, "┤ updated: ", history.Results[len(history.Results)-1].CheckedAt.Format(time.RFC3339))
-
- fmt.Fprintln(w)
- }
-
- fmt.Fprintln(w)
- fmt.Fprintln(w)
- fmt.Fprintln(w, "──────────────────────────────┤ Incident History ├──────────────────────────────")
- fmt.Fprintln(w)
-
- for i := range s.CurrentIncidents {
- showIncidentBox(w, s.CurrentIncidents[len(s.CurrentIncidents)-1-i], true)
- }
-
- for i := range s.IncidentHistory {
- showIncidentBox(w, s.IncidentHistory[len(s.IncidentHistory)-1-i], false)
- }
-
- fmt.Fprintln(w)
- fmt.Fprintln(w)
-
- footer := "Reported by Ayd? (" + time.Now().Format(time.RFC3339) + ")"
- pad := strings.Repeat(" ", (80-len(footer))/2)
- fmt.Fprint(w, pad, strings.Repeat("─", len(footer)), "\n")
- fmt.Fprint(w, pad, footer, "\n")
+ tmpl.Execute(w, freezeStatus(s))
}
}