-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.go
144 lines (124 loc) · 3.71 KB
/
app.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package xecho
import (
"fmt"
"net/http"
"os"
"time"
"github.com/labstack/echo"
"github.com/newrelic/go-agent"
"github.com/newrelic/go-agent/_integrations/nrlogrus"
"github.com/sirupsen/logrus"
)
const headerBuildVersion = "Build-Version"
type Xecho struct {
Echo *echo.Echo
NewRelicApp newrelic.Application
}
type Config struct {
ProjectName string
AppName string
EnvName string
BuildVersion string
LogLevel logrus.Level
LogFormatter logrus.Formatter
IsDebug bool
NewRelicLicense string
NewRelicEnabled bool
ErrorHandler ErrorHandlerFunc
UseDefaultHeaders bool
RoutePrefix string
}
func NewConfig() Config {
return Config{
ProjectName: "",
AppName: "",
EnvName: "",
BuildVersion: "",
RoutePrefix: "",
LogLevel: logrus.InfoLevel,
LogFormatter: &logrus.JSONFormatter{},
IsDebug: false,
NewRelicLicense: "",
NewRelicEnabled: true,
ErrorHandler: DefaultErrorHandler(),
UseDefaultHeaders: true,
}
}
func New(conf Config) *Xecho {
e, nrApp := newEcho(conf)
return &Xecho{NewRelicApp: nrApp, Echo: e}
}
func Echo(conf Config) *echo.Echo {
e, _ := newEcho(conf)
return e
}
func newEcho(conf Config) (*echo.Echo, newrelic.Application) {
logger := logger(conf)
newRelicApp := createNewRelicApp(conf, logger)
e := echo.New()
e.HideBanner = true
e.HidePort = true
e.Logger = &Logger{logger}
// the order of these middleware is important - context should be first, error should be after logging ones
e.Use(ContextMiddleware(conf.BuildVersion, logger, conf.IsDebug, newRelicApp))
e.Use(PanicHandlerMiddleware(conf.ErrorHandler))
if conf.UseDefaultHeaders {
e.Use(DefaultHeadersMiddleware())
}
e.Use(RequestLoggerMiddleware(time.Now))
e.Use(DebugLoggerMiddleware(conf.IsDebug))
e.Use(ErrorHandlerMiddleware(conf.ErrorHandler))
addHealthCheck(conf, e)
return e, newRelicApp
}
func addHealthCheck(conf Config, e *echo.Echo) {
healthRoute := "/health"
if conf.RoutePrefix != "" {
healthRoute = fmt.Sprintf("%s/health", conf.RoutePrefix)
}
e.GET(healthRoute, EchoHandler(func(c *Context) error {
if len(conf.BuildVersion) > 0 {
c.Response().Header().Add(headerBuildVersion, conf.BuildVersion)
}
return c.JSONBlob(http.StatusOK, []byte(`{"status": "ok"}`))
}))
}
func getHostName() string {
name, err := os.Hostname()
if err != nil {
name = "ERROR"
}
return name
}
func getServiceName(projectName, appName, envName string) string {
return fmt.Sprintf("%s-%s-%s", projectName, appName, envName)
}
func logger(conf Config) *logrus.Entry {
logger := logrus.New()
logger.SetLevel(conf.LogLevel)
logger.SetFormatter(conf.LogFormatter)
entry := logger.WithFields(
logrus.Fields{
"service_name": getServiceName(conf.ProjectName, conf.AppName, conf.EnvName),
"project": conf.ProjectName,
"application": conf.AppName,
"environment": conf.EnvName,
"build_version": conf.BuildVersion,
"hostname": getHostName(),
})
entry.Infof("XEcho app created %s(%s)", conf.AppName, conf.BuildVersion)
return entry
}
func createNewRelicApp(conf Config, logger *logrus.Entry) newrelic.Application {
nrConf := newrelic.NewConfig(getServiceName(conf.ProjectName, conf.AppName, conf.EnvName), conf.NewRelicLicense)
nrConf.CrossApplicationTracer.Enabled = false
nrConf.DistributedTracer.Enabled = true
nrConf.Logger = nrlogrus.Transform(logger.Logger)
nrConf.Enabled = conf.NewRelicEnabled
nrConf.Labels = map[string]string{"Env": conf.EnvName, "Project": conf.ProjectName}
app, err := newrelic.NewApplication(nrConf)
if err != nil {
panic(fmt.Sprintf("Failed to register New Relic Agent, error: %s", err.Error()))
}
return app
}