Code Monkey home page Code Monkey logo

statusetat's Introduction

Statusetat ginkgo test badge

status page with very HA in mind and notification system to send information about incident(s) or scheduled task(s) to external system like slack, email or whatever plugin you implement.

home one incident and maintenance

Features:

  • Easy admin web interface to manage incidents and scheduled tasks
  • Send notifications to external system (slack, email, plugins...) when incident come
  • Full rest api to create/read/update/delete incident/scheduled tasks
  • Subscribes systems

Why another status page ?

A status page must be more resilient than the service you want to be monitored because you need to have the page always available even when your a part of your infra is partially down to give the information to your client.

When you're a hosting service be more resilient on your status page become complicated. This implementation allow you to set multiple storage system in same time to ensure you always can store/retrieve incidents and scheduled tasks.

Statusetat will replicate in all storage what you write and ensure that the data can be retrieved.

Getting started

  1. Download latest release for your system
  2. Create a config.yml file with this content for a dev deployment
listen: 0.0.0.0:8080 # this will listen in http on port 8080
targets:
  - sqlite://./store.db
log:
  level: debug
components:
  - name: my-service
    description: description of my service
    group: ~
notifiers:
- type: slack
  params:
    endpoint: http://my-mattermost.com/hooks/aj6na7hz5ib1mfs3eggc1bu8tk
- type: plugin
  params:
    path: /path/to/my/plugin.so
username: admin
password: admin
cookie_key: encryption-key-for-cookies
base_info:
  base_url: http://localhost:8080
  support: https://doc.to.my.service.com
  contact: http://my-mattermost.com/channel/town
  time_zone: UTC

Configuration

For understanding config definition format:

  • [] means optional (by default parameter is required)
  • <> means type to use

Root configuration in config.yml

# Listen address for listening in http
# If empty and env var `PORT` set default listen will 0.0.0.0:${PORT}
[ listen: <string> | default = 0.0.0.0:8080 ]
log:
  # log level to use for server
  # you can chose: `trace`, `debug`, `info`, `warn`, `error`, `fatal` or `panic`
  [ level: <string> | default = info ]
  # Set to true to force not have color when seeing logs
  [ no_color: <bool> ]
  # et to true to see logs as json format
  [ in_json: <bool> ]
# username for basic authentication to access admin page or api
username: <string>
# password for basic authentication to access admin page or api
password: <string>
# cookie key for cookie encryption (generate a random value and set it here)
cookie_key: <string>
base_info:
  # Url of your statusetat for forging urls on notifications
  base_url: <string>
  # Title of your status page
  [ title: <string> | default = "Statusetat" ]
  # Url for your user to know where they can found support/doc page
  [ support: <string> ]
  # Url for your user to know where they can contact you
  [ contact: <bool> ]
  # Default timezone when creating/updating/show incident(s)
  [ timezone: <string> | default = "UTC" ]
# customize web page
theme:
  # Markdown content to show before status boxes
  [ pre_status: <string> ]
  # Markdown content to show after status boxes
  [ post_status: <string> ]
  # Markdown content to show before timeline
  [ pre_timeline: <string> ]
  # Markdown content to show after timeline
  [ post_timeline: <string> ]
  # Markdown content to show before maintenance/scheduled tasks box
  [ pre_maintenance: <string> ]
  # Markdown content to show after maintenance/scheduled tasks box
  [ post_maintenance: <string> ]
  # Markdown content to put in footer
  [ footer: <string> ]
  # Persistent name to display, default to Persistent Incident but you could set Known Issues for example
  [ persistent_display_name: <string | default = "Persistent Incident"> ]
  # Markdown content to show before persistent incident tasks box
  [ pre_persistent: <string> ]
  # Markdown content to show after persistent incident tasks box
  [ post_persistent: <string> ]
# list of targets store to use, this can be in form of:
# mysql://user:password@host:3306?options
# mariadb://user:password@host:3306?options
# postgres://user:password@host:3306?options
# sqlite://:memory:
# sqlite:///a/path
# s3://access_key_id:[email protected]/bucket?region=us-east-1&insecure-skip-verify=false
# file:///a/path/to/a/folder
targets:
- <uri>
notifiers:
[ - <notifier> ]

notifiers configuration

# type of notifier to use, you can found them in notifiers section of this doc
type: <string>
# only trigger for particular component(s)
[ for: <for_component> ]
# map of params for the notifier you use
params:
  [ <string>: <any> ]

for_component configurations

# Set to true to mandatory match all filter
# Think that you want to use an AND condition on true and OR condition on false
[require_all: <bool> | default = false ]
# Group which match component(s)
groups:
[ - <string> ]
# Names which match component(s)
names:
[ - <string> ]

Notifiers

Slack

Notify on a slack channel or mattermost channel new incidents or scheduled tasks.

  • Type name: slack
  • Params:
# incoming endpoint url
endpoint: <string>
# Specify channel to send notif
[ channel: <string> ]
# Specify username to show on message
[ channel: <string> ]
# Specify icon emoji incident to show on message
[ icon_emoji_incident: <string> | default = "bell" ]
# Specify icon emoji scheduled tasks to show when planified
[ icon_emoji_scheduled: <string> | default = "clock1" ]
# Specify icon emoji scheduled tasks to show when started
[ icon_emoji_scheduled_started: <string> | default = "clock1" ]
# Specify icon emoji scheduled tasks to show when finished
[ icon_emoji_scheduled_finish: <string> | default = "clock1" ]
# skip ssl verification when sending notification
[ insecure_skip_verify: <bool> ]

Grafana annotation

Put a grafana annotation when incident start and when it's finished on a graph.

  • Type name: grafana_annotation
  • Params:
# Grafana api endpoint
endpoint: <string>
# Grafana api key to use
api_key: <string>
# Dashboard id to set annotation
dashboard_id: <string>
# Panel id in dashboard to set annotation
panel_id: <string>
# tag used in grafana to filter global annotations
[ tag: <string> ]
# time zone to use when sending annotation
[ time_zone: <string> ]
# skip ssl verification when sending notification
[ insecure_skip_verify: <bool> ]

Email

Send incidents and scheduled tasks to subscribers via subscribe api and/or emails in notifier param. Type name: email Params:

# Email server host
host: <string>
# Email server port
[ port: <int> | default = 25 ]
# Username to use when connect to email server
[ username: <string> ]
# Password to use when connect to email server
[ password: <string> ]
# Set to true to use ssl/tls when connect to email server
[ use_ssl: <bool> ]
# Email to insert in from field
[ From: <string> | default = "no-reply@local" ]
# List of emails address to send email, e.g.: admins of the monitored service
subscribers:
[ - <string> ]
# Go template to use to write subject for incident
[ subject_incident: <string> | default = "[{{ .TitleSite }} {{ .Incident.State | textIncidentState | title }} Incident] {{ .IncidentTitle | title }}" ]
# Go template to use to write subject for scheduled tasks
[ subject_scheduled: <string> | default = "[{{ .TitleSite }} Scheduled task] {{ .IncidentTitle | title }}" ]
# Go template to use to write content of email when get an incident
[ txt_incident: <string | default = "see https://github.com/orange-cloudfoundry/statusetat/blob/master/notifiers/email/email.go#L26-L38"]
# Go template to use to write content of email when get an scheduled task
[ txt_incident: <string | default = "see https://github.com/orange-cloudfoundry/statusetat/blob/master/notifiers/email/email.go#L39-L51"]
# skip ssl verification when sending notification
[ insecure_skip_verify: <bool> ]

For customize content of email you can see data passed to template at https://github.com/orange-cloudfoundry/statusetat/blob/master/notifiers/email/email.go#L223-L236 and template function available at https://github.com/orange-cloudfoundry/statusetat/blob/master/extemplate/template.go#L25-L51

Plugin

You can create a plugin for notification for your own need.

Plugin are grpc golang plugin which doc can be found here: https://github.com/hashicorp/go-plugin .

You must implement plugin.Notifier.

Example of implementation:

package main

import (
	pluginhc "github.com/hashicorp/go-plugin"
	"github.com/orange-cloudfoundry/statusetat/config"
	"github.com/orange-cloudfoundry/statusetat/models"
	"github.com/orange-cloudfoundry/statusetat/notifiers/plugin"
	log "github.com/sirupsen/logrus"
	"strings"
)

type LogNotifier struct {
}

func (n LogNotifier) PreCheck(incident models.Incident) error {
	return nil
}

func (n *LogNotifier) Init(baseInfo config.BaseInfo, params map[string]interface{}) error {
	return nil
}

func (n LogNotifier) Name() (string, error) {
	return "log_notifier", nil
}

func (n LogNotifier) Id() (string, error) {
	return "log_notifier1", nil
}

func (n LogNotifier) MetadataFields() ([]models.MetadataField, error) {
	return []models.MetadataField{}, nil
}

func (n LogNotifier) Notify(notifyReq *models.NotifyRequest) error {
	log.
		WithField("subscribers", strings.Join(notifyReq.Subscribers, ", ")).
		WithField("triggerred_by_user", notifyReq.TriggerByUser).
		Info(notifyReq.Incident)
	return nil
}

func main() {
	pluginhc.Serve(&pluginhc.ServeConfig{
		HandshakeConfig: plugin.Handshake,
		Plugins: map[string]pluginhc.Plugin{
			"notifier": &plugin.NotifierGRPCPlugin{
				Impl: &LogNotifier{},
			},
		},

		// A non-nil value here enables gRPC serving for this plugin...
		GRPCServer: pluginhc.DefaultGRPCServer,
	})
}

You can build it with command line go build -o log-notif .

You can now use it in your config with:

  • Type name: plugin or notifier name you have set in func signature Name() string
  • Params:
# path to .so to load
# in our example it would be `./log-notif`
path: <string>
# all remaining arguments will be pass at Init

Api

To document

Credits

This project was heavily inspired by statusfy mostly on the design part and models of incidents/components.

Cachethq is another source of inspiration for some details on the admin design part.

statusetat's People

Contributors

adamspd avatar alidorludovic avatar arthurhlt avatar clementdqn avatar dependabot[bot] avatar fredga avatar gmllt avatar mdimiceli avatar psycofdj avatar romain-dartigues avatar saadia-kadiri avatar smendaci avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

statusetat's Issues

Example config causes nil pointer dereference when launching binary

Reference to config in serves/init.go:70 causes nil pointer dereference when running statusetat and themes: persistent_display_name is not set.

Error:

โฏ ./statusetat -c config.yml
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x60 pc=0x1144877]

goroutine 1 [running]:
github.com/orange-cloudfoundry/statusetat/serves.RegisterWithHtmlTemplater({0x1a39440, 0xc0003e4860}, 0xc00057ad00, 0xc000a9fcd8, {0x1a04260, 0xc00057ad20}, {{0xc0004fa3f0, 0x1, 0x1}, {0xc00037d9f0, ...}, ...})
        /home/frigaut/Repos/src/pagestatus/sourcecode/statusetat-1.40.0/serves/init.go:70 +0x137
github.com/orange-cloudfoundry/statusetat/serves.Register({0x1a39440, 0xc0003e4860}, 0x42004b, 0x7ffbd186ae00, {{0xc0004fa3f0, 0x1, 0x1}, {0xc00037d9f0, 0xc}, 0xc0001260f0, ...})
        /home/frigaut/Repos/src/pagestatus/sourcecode/statusetat-1.40.0/serves/init.go:45 +0x127
main.main()
        /home/frigaut/Repos/src/pagestatus/sourcecode/statusetat-1.40.0/main.go:91 +0x71c

Code:

                        {
                                ID:          "maintenance",
                                DisplayName: "maintenance",
                        },
                        {
                                ID:          "persistent_incident",
                                DisplayName: config.Theme.PersistentDisplayName, // <--- This line
                        },
                        {
                                ID:          "info",
                                DisplayName: "info",
                        },

Possible solutions:

  • Set default value for this variable (idk which one) to avoid crashes when not set
  • Update example config with a default value such as:
theme:
  persistent_display_name: my_display_name

Edit: After further inspection, it looks like config.Validate() (config/config.go:62) is not called when loading conf from a file, but only when loading conf from env, if this is intended then I think there should be an error message when loading an invalid conf from a file if possible

Edit "know issues" impossible

hi,
When i try to edit a "know issues" via iIHM have a error 500.
Detail error: 500 Internal Server Error: file does not exist.

tested with different browser.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.