Skip to content

Commit f11c871

Browse files
authored
feat(fxcore): Added core dashboard options (#60)
1 parent 2d14ee0 commit f11c871

File tree

3 files changed

+222
-169
lines changed

3 files changed

+222
-169
lines changed

fxcore/README.md

Lines changed: 51 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ The fxcore module provides the foundation of your application:
3434
- a dependency injection system
3535
- a dedicated core http server
3636
- ready to use config, health check, logger and tracer and metrics components
37-
- a plugin system for the [Fx modules](https://github.com/ankorstore/yokai#fx-modules)
37+
- a plugin system for the [Fx modules](https://github.com/ankorstore/yokai#fx-modules)
3838

3939
The core http server runs automatically on a dedicated port (default `8081`), to serve:
4040

@@ -43,7 +43,7 @@ The core http server runs automatically on a dedicated port (default `8081`), to
4343
- the health check endpoints: to expose all configured health check probes of your application
4444
- the debug endpoints: to expose various information about your config, modules, build, etc.
4545

46-
Whatever your type of application (httpserver, gRPC server, worker, etc.), all platform concerns are handled by this
46+
Whatever your type of application (httpserver, gRPC server, worker, etc.), all platform concerns are handled by this
4747
dedicated server:
4848

4949
- to avoid to expose sensitive information (health checks, metrics, debug, etc) to your users
@@ -82,46 +82,56 @@ modules:
8282
type: stdout
8383
core:
8484
server:
85-
port: 8081 # core http server port (default 8081)
86-
errors:
87-
obfuscate: false # to obfuscate error messages on the core http server responses
88-
stack: false # to add error stack trace to error response of the core http server
85+
port: 8081 # core http server port (default 8081)
86+
errors:
87+
obfuscate: false # to obfuscate error messages on the core http server responses
88+
stack: false # to add error stack trace to error response of the core http server
89+
dashboard:
90+
enabled: true # to enable the core dashboard
91+
overview:
92+
app_env: true # to display the app env on the dashboard overview
93+
app_debug: true # to display the app debug on the dashboard overview
94+
app_version: true # to display the app version on the dashboard overview
95+
log_level: true # to display the log level on the dashboard overview
96+
log_output: true # to display the log output on the dashboard overview
97+
trace_sampler: true # to display the trace sampler on the dashboard overview
98+
trace_processor: true # to display the trace processor on the dashboard overview
8999
log:
90-
headers: # to log incoming request headers on the core http server
91-
x-foo: foo # to log for example the header x-foo in the log field foo
92-
x-bar: bar
93-
exclude: # to exclude specific routes from logging
100+
headers: # to log incoming request headers on the core http server
101+
x-foo: foo # to log for example the header x-foo in the log field foo
102+
x-bar: bar
103+
exclude: # to exclude specific routes from logging
94104
- /healthz
95105
- /livez
96106
- /readyz
97107
- /metrics
98-
level_from_response: true # to use response status code for log level (ex: 500=error)
99-
trace:
100-
enabled: true # to trace incoming request headers on the core http server
101-
exclude: # to exclude specific routes from tracing
102-
- /healthz
103-
- /livez
104-
- /readyz
105-
- /metrics
106-
metrics:
107-
expose: true # to expose metrics route, disabled by default
108-
path: /metrics # metrics route path (default /metrics)
109-
collect:
110-
enabled: true # to collect core http server metrics, disabled by default
111-
namespace: app # core http server metrics namespace (default app.name value)
112-
subsystem: fx-core # core http server metrics subsystem (default fx-core)
113-
buckets: 0.1, 1, 10 # to override default request duration buckets
114-
normalize: true # to normalize http status code (2xx, 3xx, ...)
108+
level_from_response: true # to use response status code for log level (ex: 500=error)
109+
trace:
110+
enabled: true # to trace incoming request headers on the core http server
111+
exclude: # to exclude specific routes from tracing
112+
- /healthz
113+
- /livez
114+
- /readyz
115+
- /metrics
116+
metrics:
117+
expose: true # to expose metrics route, disabled by default
118+
path: /metrics # metrics route path (default /metrics)
119+
collect:
120+
enabled: true # to collect core http server metrics, disabled by default
121+
namespace: app # core http server metrics namespace (default app.name value)
122+
subsystem: fx-core # core http server metrics subsystem (default fx-core)
123+
buckets: 0.1, 1, 10 # to override default request duration buckets
124+
normalize: true # to normalize http status code (2xx, 3xx, ...)
115125
healthcheck:
116126
startup:
117-
expose: true # to expose health check startup route, disabled by default
118-
path: /healthz # health check startup route path (default /healthz)
119-
readiness:
120-
expose: true # to expose health check readiness route, disabled by default
121-
path: /readyz # health check readiness route path (default /readyz)
122-
liveness:
123-
expose: true # to expose health check liveness route, disabled by default
124-
path: /livez # health check liveness route path (default /livez)
127+
expose: true # to expose health check startup route, disabled by default
128+
path: /healthz # health check startup route path (default /healthz)
129+
readiness:
130+
expose: true # to expose health check readiness route, disabled by default
131+
path: /readyz # health check readiness route path (default /readyz)
132+
liveness:
133+
expose: true # to expose health check liveness route, disabled by default
134+
path: /livez # health check liveness route path (default /livez)
125135
debug:
126136
config:
127137
expose: true # to expose debug config route
@@ -140,21 +150,19 @@ modules:
140150
path: /debug/build # debug build route path (default /debug/build)
141151
modules:
142152
expose: true # to expose debug modules route
143-
path: /debug/modules/:name # debug modules route path (default /debug/modules/:name)
153+
path: /debug/modules/:name # debug modules route path (default /debug/modules/:name)
144154
```
145155
146156
Notes:
147157
148-
- the core http server requests logging will be based on
149-
the [fxlog](https://github.com/ankorstore/yokai/tree/main/fxlog) module configuration
150-
- the core http server requests tracing will be based on
151-
the [fxtrace](https://github.com/ankorstore/yokai/tree/main/fxtrace) module configuration
158+
- the core http server requests logging will be based on the [fxlog](https://github.com/ankorstore/yokai/tree/main/fxlog) module configuration
159+
- the core http server requests tracing will be based on the [fxtrace](https://github.com/ankorstore/yokai/tree/main/fxtrace) module configuration
152160
- if `app.debug=true` (or env var `APP_DEBUG=true`):
153-
- all the debug endpoints will be automatically exposed
161+
- the dashboard will be automatically enabled
162+
- all the debug endpoints will be automatically exposed
154163
- error responses will not be obfuscated and stack trace will be added
155164

156-
Check the [configuration files documentation](https://github.com/ankorstore/yokai/tree/main/config#configuration-files)
157-
for more details.
165+
Check the [configuration files documentation](https://github.com/ankorstore/yokai/tree/main/config#configuration-files) for more details.
158166

159167
### Bootstrap
160168

fxcore/module.go

Lines changed: 87 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ import (
44
"context"
55
"embed"
66
"fmt"
7-
"github.com/labstack/echo/v4"
87
"net/http"
98
"strconv"
109
"strings"
1110

11+
"github.com/labstack/echo/v4"
12+
1213
"github.com/ankorstore/yokai/config"
1314
"github.com/ankorstore/yokai/fxconfig"
1415
"github.com/ankorstore/yokai/fxgenerate"
@@ -234,12 +235,24 @@ func withMiddlewares(coreServer *echo.Echo, p FxCoreParam) *echo.Echo {
234235
func withHandlers(coreServer *echo.Echo, p FxCoreParam) (*echo.Echo, error) {
235236
appDebug := p.Config.AppDebug()
236237

237-
// overview
238-
info, err := p.Registry.Find(ModuleName)
238+
// dashboard
239+
dashboardEnabled := p.Config.GetBool("modules.core.server.dashboard.enabled")
240+
241+
// dashboard overview
242+
overviewInfo, err := p.Registry.Find(ModuleName)
239243
if err != nil {
240244
return nil, err
241245
}
242246

247+
// dashboard overview expositions
248+
overviewAppEnvExpose := p.Config.GetBool("modules.core.server.dashboard.overview.app_env")
249+
overviewAppDebugExpose := p.Config.GetBool("modules.core.server.dashboard.overview.app_debug")
250+
overviewAppVersionExpose := p.Config.GetBool("modules.core.server.dashboard.overview.app_version")
251+
overviewLogLevelExpose := p.Config.GetBool("modules.core.server.dashboard.overview.log_level")
252+
overviewLogOutputExpose := p.Config.GetBool("modules.core.server.dashboard.overview.log_output")
253+
overviewTraceSamplerExpose := p.Config.GetBool("modules.core.server.dashboard.overview.trace_sampler")
254+
overviewTraceProcessorExpose := p.Config.GetBool("modules.core.server.dashboard.overview.trace_processor")
255+
243256
// template expositions
244257
metricsExpose := p.Config.GetBool("modules.core.server.metrics.expose")
245258
startupExpose := p.Config.GetBool("modules.core.server.healthcheck.startup.expose")
@@ -404,75 +417,87 @@ func withHandlers(coreServer *echo.Echo, p FxCoreParam) (*echo.Echo, error) {
404417
coreServer.Logger.Debug("registered debug modules handler")
405418
}
406419

407-
// theme
408-
coreServer.POST("/theme", func(c echo.Context) error {
409-
themeCookie := new(http.Cookie)
410-
themeCookie.Name = "theme"
411-
412-
var theme FxCoreDashboardTheme
413-
if err = c.Bind(&theme); err != nil {
414-
themeCookie.Value = ThemeLight
415-
} else {
416-
switch theme.Theme {
417-
case ThemeDark:
418-
themeCookie.Value = ThemeDark
419-
case ThemeLight:
420-
themeCookie.Value = ThemeLight
421-
default:
420+
// dashboard
421+
if dashboardEnabled || appDebug {
422+
// theme
423+
coreServer.POST("/theme", func(c echo.Context) error {
424+
themeCookie := new(http.Cookie)
425+
themeCookie.Name = "theme"
426+
427+
var theme FxCoreDashboardTheme
428+
if err = c.Bind(&theme); err != nil {
422429
themeCookie.Value = ThemeLight
430+
} else {
431+
switch theme.Theme {
432+
case ThemeDark:
433+
themeCookie.Value = ThemeDark
434+
case ThemeLight:
435+
themeCookie.Value = ThemeLight
436+
default:
437+
themeCookie.Value = ThemeLight
438+
}
423439
}
424-
}
425440

426-
c.SetCookie(themeCookie)
441+
c.SetCookie(themeCookie)
427442

428-
return c.Redirect(http.StatusMovedPermanently, "/")
429-
})
443+
return c.Redirect(http.StatusMovedPermanently, "/")
444+
})
430445

431-
// dashboard
432-
coreServer.GET("/", func(c echo.Context) error {
433-
var theme string
434-
themeCookie, err := c.Cookie("theme")
435-
if err == nil {
436-
switch themeCookie.Value {
437-
case ThemeDark:
438-
theme = ThemeDark
439-
case ThemeLight:
440-
theme = ThemeLight
441-
default:
446+
coreServer.Logger.Debug("registered dashboard theme handler")
447+
448+
// render
449+
coreServer.GET("/", func(c echo.Context) error {
450+
var theme string
451+
themeCookie, err := c.Cookie("theme")
452+
if err == nil {
453+
switch themeCookie.Value {
454+
case ThemeDark:
455+
theme = ThemeDark
456+
case ThemeLight:
457+
theme = ThemeLight
458+
default:
459+
theme = ThemeLight
460+
}
461+
} else {
442462
theme = ThemeLight
443463
}
444-
} else {
445-
theme = ThemeLight
446-
}
447464

448-
return c.Render(http.StatusOK, "dashboard.html", map[string]interface{}{
449-
"info": info,
450-
"metricsExpose": metricsExpose,
451-
"metricsPath": metricsPath,
452-
"startupExpose": startupExpose,
453-
"startupPath": startupPath,
454-
"livenessExpose": livenessExpose,
455-
"livenessPath": livenessPath,
456-
"readinessExpose": readinessExpose,
457-
"readinessPath": readinessPath,
458-
"configExpose": configExpose || appDebug,
459-
"configPath": configPath,
460-
"pprofExpose": pprofExpose || appDebug,
461-
"pprofPath": pprofPath,
462-
"routesExpose": routesExpose || appDebug,
463-
"routesPath": routesPath,
464-
"statsExpose": statsExpose || appDebug,
465-
"statsPath": statsPath,
466-
"buildExpose": buildExpose || appDebug,
467-
"buildPath": buildPath,
468-
"modulesExpose": modulesExpose || appDebug,
469-
"modulesPath": modulesPath,
470-
"modulesNames": p.Registry.Names(),
471-
"theme": theme,
465+
return c.Render(http.StatusOK, "dashboard.html", map[string]interface{}{
466+
"overviewInfo": overviewInfo,
467+
"overviewAppEnvExpose": overviewAppEnvExpose,
468+
"overviewAppDebugExpose": overviewAppDebugExpose,
469+
"overviewAppVersionExpose": overviewAppVersionExpose,
470+
"overviewLogLevelExpose": overviewLogLevelExpose,
471+
"overviewLogOutputExpose": overviewLogOutputExpose,
472+
"overviewTraceSamplerExpose": overviewTraceSamplerExpose,
473+
"overviewTraceProcessorExpose": overviewTraceProcessorExpose,
474+
"metricsExpose": metricsExpose,
475+
"metricsPath": metricsPath,
476+
"startupExpose": startupExpose,
477+
"startupPath": startupPath,
478+
"livenessExpose": livenessExpose,
479+
"livenessPath": livenessPath,
480+
"readinessExpose": readinessExpose,
481+
"readinessPath": readinessPath,
482+
"configExpose": configExpose || appDebug,
483+
"configPath": configPath,
484+
"pprofExpose": pprofExpose || appDebug,
485+
"pprofPath": pprofPath,
486+
"routesExpose": routesExpose || appDebug,
487+
"routesPath": routesPath,
488+
"statsExpose": statsExpose || appDebug,
489+
"statsPath": statsPath,
490+
"buildExpose": buildExpose || appDebug,
491+
"buildPath": buildPath,
492+
"modulesExpose": modulesExpose || appDebug,
493+
"modulesPath": modulesPath,
494+
"modulesNames": p.Registry.Names(),
495+
"theme": theme,
496+
})
472497
})
473-
})
474498

475-
coreServer.Logger.Debug("registered debug dashboard handler")
499+
coreServer.Logger.Debug("registered dashboard handler")
500+
}
476501

477502
return coreServer, nil
478503
}

0 commit comments

Comments
 (0)