health.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. package health
  2. import (
  3. "fmt"
  4. "net/http"
  5. "time"
  6. "github.com/go-chi/chi"
  7. "github.com/willie68/schematic-service-go/dao"
  8. "github.com/willie68/schematic-service-go/logging"
  9. )
  10. // global storage definition
  11. var myhealthy bool
  12. var log logging.ServiceLogger
  13. /*
  14. This is the healtchcheck you will have to provide.
  15. */
  16. func check() (bool, string) {
  17. // TODO implement here your healthcheck.
  18. myhealthy = true
  19. message := ""
  20. err := dao.GetStorage().Ping()
  21. if err != nil {
  22. myhealthy = false
  23. message = err.Error()
  24. }
  25. return myhealthy, message
  26. }
  27. //##### template internal functions for processing the healthchecks #####
  28. var healthmessage string
  29. var healthy bool
  30. var lastChecked time.Time
  31. var period int
  32. // CheckConfig configuration for the healthcheck system
  33. type CheckConfig struct {
  34. Period int
  35. }
  36. // InitHealthSystem initialise the complete health system
  37. func InitHealthSystem(config CheckConfig) {
  38. period = config.Period
  39. log.Infof("healthcheck starting with period: %d seconds", period)
  40. healthmessage = "service starting"
  41. healthy = false
  42. doCheck()
  43. go func() {
  44. background := time.NewTicker(time.Second * time.Duration(period))
  45. for _ = range background.C {
  46. doCheck()
  47. }
  48. }()
  49. }
  50. /*
  51. internal function to process the health check
  52. */
  53. func doCheck() {
  54. var msg string
  55. healthy, msg = check()
  56. if !healthy {
  57. healthmessage = msg
  58. } else {
  59. healthmessage = ""
  60. }
  61. lastChecked = time.Now()
  62. }
  63. /*
  64. Routes getting all routes for the health endpoint
  65. */
  66. func Routes() *chi.Mux {
  67. router := chi.NewRouter()
  68. router.Get("/health", GetHealthyEndpoint)
  69. router.Get("/readiness", GetReadinessEndpoint)
  70. return router
  71. }
  72. /*
  73. GetHealthyEndpoint is this service healthy
  74. */
  75. func GetHealthyEndpoint(response http.ResponseWriter, req *http.Request) {
  76. t := time.Now()
  77. if t.Sub(lastChecked) > (time.Second * time.Duration(2*period)) {
  78. healthy = false
  79. healthmessage = "Healthcheck not running"
  80. }
  81. response.Header().Add("Content-Type", "application/json")
  82. if healthy {
  83. response.WriteHeader(http.StatusOK)
  84. message := fmt.Sprintf(`{ "message": "service up and running", "lastCheck": "%s" }`, lastChecked.String())
  85. response.Write([]byte(message))
  86. } else {
  87. response.WriteHeader(http.StatusServiceUnavailable)
  88. message := fmt.Sprintf(`{ "message": "service is unavailable: %s", "lastCheck": "%s" }`, healthmessage, lastChecked.String())
  89. response.Write([]byte(message))
  90. }
  91. }
  92. /*
  93. GetReadinessEndpoint is this service ready for taking requests
  94. */
  95. func GetReadinessEndpoint(response http.ResponseWriter, req *http.Request) {
  96. response.Header().Add("Content-Type", "application/json")
  97. response.WriteHeader(http.StatusOK)
  98. response.Write([]byte(`{ "message": "service started" }`))
  99. }