Skip to content

Commit

Permalink
Feature/middlewares (#31)
Browse files Browse the repository at this point in the history
* add middlewares & bump
  • Loading branch information
Clivern committed Oct 13, 2020
1 parent 8f0de02 commit 7901bf0
Show file tree
Hide file tree
Showing 12 changed files with 272 additions and 34 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM golang:1.15.2

ARG RHINO_VERSION=1.2.2
ARG RHINO_VERSION=1.3.0

ENV GO111MODULE=on

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<p align="center">
<img alt="Rhino Logo" src="https://raw.githubusercontent.com/clivern/Rhino/master/assets/img/gopher.png?v=1.2.2" width="150" />
<img alt="Rhino Logo" src="https://raw.githubusercontent.com/clivern/Rhino/master/assets/img/gopher.png?v=1.3.0" width="150" />
<h3 align="center">Rhino</h3>
<p align="center">HTTP Mocking & Debugging Service</p>
<p align="center">
<a href="https://travis-ci.com/Clivern/Rhino"><img src="https://travis-ci.com/Clivern/Rhino.svg?branch=master"></a>
<a href="https://github.com/Clivern/Rhino/releases"><img src="https://img.shields.io/badge/Version-1.2.2-red.svg"></a>
<a href="https://goreportcard.com/report/github.com/Clivern/Rhino"><img src="https://goreportcard.com/badge/github.com/clivern/Rhino?v=1.2.2"></a>
<a href="https://github.com/Clivern/Rhino/releases"><img src="https://img.shields.io/badge/Version-1.3.0-red.svg"></a>
<a href="https://goreportcard.com/report/github.com/Clivern/Rhino"><img src="https://goreportcard.com/badge/github.com/clivern/Rhino?v=1.3.0"></a>
<a href="https://hub.docker.com/r/clivern/rhino"><img src="https://img.shields.io/badge/Docker-Latest-green"></a>
<a href="https://github.com/Clivern/Rhino/blob/master/LICENSE"><img src="https://img.shields.io/badge/LICENSE-MIT-orange.svg"></a>
</p>
Expand Down
5 changes: 4 additions & 1 deletion core/cmd/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,14 +126,17 @@ var serveCmd = &cobra.Command{
r := gin.Default()

r.Use(middleware.Cors())
r.Use(middleware.Correlation())
r.Use(middleware.Logger())
r.Use(middleware.Metric())

r.GET("/favicon.ico", func(c *gin.Context) {
c.String(http.StatusNoContent, "")
})

r.GET("/", controller.Index)
r.GET("/_health", controller.Health)
r.GET("/api/requests", controller.Requests)
r.GET("/_metrics", gin.WrapH(controller.Metrics()))

debugRoutes, err := model.GetDebugRoutes()

Expand Down
16 changes: 16 additions & 0 deletions core/controller/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright 2020 Clivern. All rights reserved.
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package controller

import (
"net/http"

"github.com/prometheus/client_golang/prometheus/promhttp"
)

// Metrics controller
func Metrics() http.Handler {
return promhttp.Handler()
}
19 changes: 0 additions & 19 deletions core/controller/requests.go

This file was deleted.

25 changes: 25 additions & 0 deletions core/middleware/correlation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2020 Clivern. All rights reserved.
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package middleware

import (
"strings"

"github.com/clivern/rhino/core/util"

"github.com/gin-gonic/gin"
)

// Correlation middleware
func Correlation() gin.HandlerFunc {
return func(c *gin.Context) {
corralationID := c.Request.Header.Get("X-Correlation-ID")

if strings.TrimSpace(corralationID) == "" {
c.Request.Header.Add("X-Correlation-ID", util.GenerateUUID4())
}
c.Next()
}
}
47 changes: 47 additions & 0 deletions core/middleware/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright 2020 Clivern. All rights reserved.
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package middleware

import (
"bytes"
"io/ioutil"

"github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
)

// Logger middleware
func Logger() gin.HandlerFunc {
return func(c *gin.Context) {
// before request
var bodyBytes []byte

// Workaround for issue https://github.com/gin-gonic/gin/issues/1651
if c.Request.Body != nil {
bodyBytes, _ = ioutil.ReadAll(c.Request.Body)
}

c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))

log.WithFields(log.Fields{
"correlation_id": c.Request.Header.Get("X-Correlation-ID"),
"http_method": c.Request.Method,
"http_path": c.Request.URL.Path,
"request_body": string(bodyBytes),
}).Info("Request started")

c.Next()

// after request
status := c.Writer.Status()
size := c.Writer.Size()

log.WithFields(log.Fields{
"correlation_id": c.Request.Header.Get("X-Correlation-ID"),
"http_status": status,
"response_size": size,
}).Info(`Request finished`)
}
}
80 changes: 80 additions & 0 deletions core/middleware/metric.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Copyright 2020 Clivern. All rights reserved.
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package middleware

import (
"strconv"
"time"

"github.com/gin-gonic/gin"
"github.com/prometheus/client_golang/prometheus"
log "github.com/sirupsen/logrus"
)

var (
httpRequests = prometheus.NewCounterVec(
prometheus.CounterOpts{
Namespace: "rhino",
Name: "total_http_requests",
Help: "How many HTTP requests processed, partitioned by status code and HTTP method.",
}, []string{"code", "method", "handler", "host", "url"})

requestDuration = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Subsystem: "rhino",
Name: "request_duration_seconds",
Help: "The HTTP request latencies in seconds.",
},
[]string{"code", "method", "url"},
)

responseSize = prometheus.NewSummary(
prometheus.SummaryOpts{
Namespace: "rhino",
Name: "response_size_bytes",
Help: "The HTTP response sizes in bytes.",
},
)
)

func init() {
prometheus.MustRegister(httpRequests)
prometheus.MustRegister(requestDuration)
prometheus.MustRegister(responseSize)
}

// Metric middleware
func Metric() gin.HandlerFunc {
return func(c *gin.Context) {
// before request
start := time.Now()

c.Next()

// after request
elapsed := float64(time.Since(start)) / float64(time.Second)

log.WithFields(log.Fields{
"correlation_id": c.Request.Header.Get("X-Correlation-ID"),
}).Info(`Collecting metrics`)

// Collect Metrics
httpRequests.WithLabelValues(
strconv.Itoa(c.Writer.Status()),
c.Request.Method,
c.HandlerName(),
c.Request.Host,
c.Request.URL.Path,
).Inc()

requestDuration.WithLabelValues(
strconv.Itoa(c.Writer.Status()),
c.Request.Method,
c.Request.URL.Path,
).Observe(elapsed)

responseSize.Observe(float64(c.Writer.Size()))
}
}
23 changes: 22 additions & 1 deletion deployment/docker-compose/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,31 @@
version: '3'
services:
rhino:
image: 'clivern/rhino:release-1.2.2'
image: 'clivern/rhino:release-1.3.0'
ports:
- "8080:8080"
command: '/app/rhino serve -c /app/configs/config.prod.json'
volumes:
- './configs/:/app/configs'
restart: unless-stopped

prometheus:
image: 'prom/prometheus:v2.21.0'
volumes:
- './prometheus/:/etc/prometheus'
command: '--config.file=/etc/prometheus/prometheus.yml'
ports:
- '9090:9090'
restart: unless-stopped

grafana:
image: 'grafana/grafana:6.7.4'
environment:
- GF_SECURITY_ADMIN_USER=${ADMIN_USER:-admin}
- GF_SECURITY_ADMIN_PASSWORD=${ADMIN_PASSWORD:-admin}
- GF_USERS_ALLOW_SIGN_UP=false
ports:
- '3000:3000'
depends_on:
- prometheus
restart: unless-stopped
23 changes: 23 additions & 0 deletions deployment/docker-compose/prometheus/prometheus.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# my global config
global:
evaluation_interval: 15s
external_labels:
monitor: rhino-monitor
scrape_interval: 15s
rule_files: ~
scrape_configs:
-
job_name: prometheus
scrape_interval: 5s
static_configs:
-
targets:
- "localhost:9090"
-
job_name: rhino
metrics_path: /_metrics
scrape_interval: 5s
static_configs:
-
targets:
- "localhost:8080"
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.15
require (
github.com/drone/envsubst v1.0.2
github.com/gin-gonic/gin v1.6.3
github.com/prometheus/client_golang v1.7.1
github.com/satori/go.uuid v1.2.0
github.com/sirupsen/logrus v1.7.0
github.com/spf13/cobra v1.0.0
Expand Down
Loading

0 comments on commit 7901bf0

Please sign in to comment.