Skip to content

Commit

Permalink
logging middleware, sentry middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
felipejfc committed Aug 2, 2016
1 parent aa6081d commit 9cad265
Show file tree
Hide file tree
Showing 10 changed files with 226 additions and 6 deletions.
27 changes: 26 additions & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ package app
import (
"fmt"

"github.com/getsentry/raven-go"
"github.com/kataras/iris"
"github.com/spf13/viper"
"github.com/topfreegames/mqttbot/bot"
"github.com/topfreegames/mqttbot/logger"
"github.com/topfreegames/mqttbot/redisclient"
"github.com/uber-go/zap"
)

// App is the struct that defines the application
Expand Down Expand Up @@ -44,6 +46,7 @@ func GetApp(host string, port int, debug bool) *App {
// Configure configures the application
func (app *App) Configure() {
app.setConfigurationDefaults()
app.configureSentry()
app.loadConfiguration()
app.configureApplication()
}
Expand All @@ -62,17 +65,39 @@ func (app *App) loadConfiguration() {
}
}

func (app *App) configureSentry() {
sentryURL := viper.GetString("sentry.url")
logger.Logger.Info(fmt.Sprintf("Configuring sentry with URL %s", sentryURL))
raven.SetDSN(sentryURL)
}

func (app *App) configureApplication() {
app.MqttBot = bot.GetMqttBot()
app.Api = iris.New()
a := app.Api

a.Use(NewLoggerMiddleware(zap.New(
zap.NewJSONEncoder(),
)))
a.Use(&SentryMiddleware{App: app})
a.Use(&VersionMiddleware{App: app})
a.Use(&RecoveryMiddleware{OnError: app.onErrorHandler})
a.Get("/healthcheck", HealthCheckHandler(app))
a.Get("/history/*topic", HistoryHandler(app))

app.RedisClient = redisclient.GetRedisClient(viper.GetString("redis.host"), viper.GetInt("redis.port"), viper.GetString("redis.password"))
}

func (app *App) onErrorHandler(err error, stack []byte) {
logger.Logger.Errorf(
"Panic occurred. stack: %s", string(stack),
)
tags := map[string]string{
"source": "app",
"type": "panic",
}
raven.CaptureError(err, tags)
}

// Start starts the application
func (app *App) Start() {
if viper.GetBool("api.tls") {
Expand Down
59 changes: 59 additions & 0 deletions app/glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions app/history.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func HistoryHandler(app *App) func(c *iris.Context) {
r, err := rc.Do("EXEC")
if err != nil {
logger.Logger.Error(err.Error())
c.SetStatusCode(iris.StatusInternalServerError)
c.Error(err.Error(), iris.StatusInternalServerError)
return
}
redisResults := (r.([]interface{}))
Expand All @@ -49,7 +49,7 @@ func HistoryHandler(app *App) func(c *iris.Context) {
Sort("timestamp", false).From(from).Size(limit).Do()
if err != nil {
logger.Logger.Error(err.Error())
c.SetStatusCode(iris.StatusInternalServerError)
c.Error(err.Error(), iris.StatusInternalServerError)
return
}
messages := []Message{}
Expand Down
126 changes: 126 additions & 0 deletions app/middleware.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package app

import (
"fmt"
"runtime/debug"
"time"

"github.com/getsentry/raven-go"
"github.com/kataras/iris"
"github.com/uber-go/zap"
)

//VersionMiddleware automatically adds a version header to response
type VersionMiddleware struct {
App *App
}

// Serve automatically adds a version header to response
func (m *VersionMiddleware) Serve(c *iris.Context) {
c.SetHeader("MQTTBOT-VERSION", VERSION)
c.Next()
}

//RecoveryMiddleware recovers from errors in Iris
type RecoveryMiddleware struct {
OnError func(error, []byte)
}

//Serve executes on error handler when errors happen
func (r RecoveryMiddleware) Serve(ctx *iris.Context) {
defer func() {
if err := recover(); err != nil {
if r.OnError != nil {
switch err.(type) {
case error:
r.OnError(err.(error), debug.Stack())
default:
r.OnError(fmt.Errorf("%v", err), debug.Stack())
}
}
ctx.Panic()
}
}()
ctx.Next()
}

//LoggerMiddleware is responsible for logging to Zap all requests
type LoggerMiddleware struct {
Logger zap.Logger
}

// Serve serves the middleware
func (l *LoggerMiddleware) Serve(ctx *iris.Context) {
log := l.Logger.With(
zap.String("source", "request"),
)

//all except latency to string
var ip, method, path string
var status int
var latency time.Duration
var startTime, endTime time.Time

path = ctx.PathString()
method = ctx.MethodString()

startTime = time.Now()

ctx.Next()

//no time.Since in order to format it well after
endTime = time.Now()
latency = endTime.Sub(startTime)

status = ctx.Response.StatusCode()
ip = ctx.RemoteAddr()

reqLog := log.With(
zap.Time("endTime", endTime),
zap.Int("statusCode", status),
zap.Duration("latency", latency),
zap.String("ip", ip),
zap.String("method", method),
zap.String("path", path),
)

//request failed
if status > 399 && status < 500 {
reqLog.Warn("Request failed.")
return
}

//request is ok, but server failed
if status > 499 {
reqLog.Error("Response failed.")
return
}

//Everything went ok
reqLog.Info("Request successful.")
}

// NewLoggerMiddleware returns the logger middleware
func NewLoggerMiddleware(theLogger zap.Logger) iris.HandlerFunc {
l := &LoggerMiddleware{Logger: theLogger}
return l.Serve
}

//SentryMiddleware is responsible for sending all exceptions to sentry
type SentryMiddleware struct {
App *App
}

// Serve serves the middleware
func (l *SentryMiddleware) Serve(ctx *iris.Context) {
ctx.Next()

if ctx.Response.StatusCode() > 499 {
tags := map[string]string{
"source": "app",
"type": "Internal server error",
"url": ctx.Request.URI().String(),
}
raven.CaptureError(fmt.Errorf("%s", string(ctx.Response.Body())), tags)
}
}
2 changes: 1 addition & 1 deletion app/version.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package app

var VERSION = "0.9.6"
var VERSION = "1.0.0"
8 changes: 6 additions & 2 deletions glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions glide.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ import:
- iris
- package: github.com/valyala/fasthttp
- package: gopkg.in/olivere/elastic.v3
- package: github.com/uber-go/zap
- package: github.com/uber-go/atomic
- package: github.com/getsentry/raven-go
1 change: 1 addition & 0 deletions vendor/github.com/getsentry/raven-go
Submodule raven-go added at ba4db4
1 change: 1 addition & 0 deletions vendor/github.com/uber-go/atomic
Submodule atomic added at 0c9e68
1 change: 1 addition & 0 deletions vendor/github.com/uber-go/zap
Submodule zap added at 67b225

0 comments on commit 9cad265

Please sign in to comment.