Add GET /api/about
that returns useful system info. Closes #1354.
This commit is contained in:
parent
5b404615fc
commit
c581fe2f3a
7 changed files with 105 additions and 0 deletions
|
@ -86,6 +86,7 @@ func initHTTPHandlers(e *echo.Echo, app *App) {
|
||||||
g.POST("/api/settings/smtp/test", handleTestSMTPSettings)
|
g.POST("/api/settings/smtp/test", handleTestSMTPSettings)
|
||||||
g.POST("/api/admin/reload", handleReloadApp)
|
g.POST("/api/admin/reload", handleReloadApp)
|
||||||
g.GET("/api/logs", handleGetLogs)
|
g.GET("/api/logs", handleGetLogs)
|
||||||
|
g.GET("/api/about", handleGetAboutInfo)
|
||||||
|
|
||||||
g.GET("/api/subscribers/:id", handleGetSubscriber)
|
g.GET("/api/subscribers/:id", handleGetSubscriber)
|
||||||
g.GET("/api/subscribers/:id/export", handleExportSubscriberData)
|
g.GET("/api/subscribers/:id/export", handleExportSubscriberData)
|
||||||
|
|
40
cmd/init.go
40
cmd/init.go
|
@ -8,6 +8,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
@ -697,6 +698,45 @@ func initBounceManager(app *App) *bounce.Manager {
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func initAbout(q *models.Queries, db *sqlx.DB) about {
|
||||||
|
var (
|
||||||
|
mem runtime.MemStats
|
||||||
|
utsname syscall.Utsname
|
||||||
|
)
|
||||||
|
|
||||||
|
// Memory / alloc stats.
|
||||||
|
runtime.ReadMemStats(&mem)
|
||||||
|
|
||||||
|
// OS info.
|
||||||
|
if err := syscall.Uname(&utsname); err != nil {
|
||||||
|
lo.Printf("WARNING: error getting system info: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DB dbv.
|
||||||
|
info := types.JSONText(`{}`)
|
||||||
|
if err := db.QueryRow(q.GetDBInfo).Scan(&info); err != nil {
|
||||||
|
lo.Printf("WARNING: error getting database version: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return about{
|
||||||
|
Version: versionString,
|
||||||
|
Build: buildString,
|
||||||
|
GoArch: runtime.GOARCH,
|
||||||
|
GoVersion: runtime.Version(),
|
||||||
|
Database: info,
|
||||||
|
System: aboutSystem{
|
||||||
|
NumCPU: runtime.NumCPU(),
|
||||||
|
},
|
||||||
|
Host: aboutHost{
|
||||||
|
OS: int8ToStr(utsname.Sysname[:]),
|
||||||
|
OSRelease: int8ToStr(utsname.Release[:]),
|
||||||
|
Machine: int8ToStr(utsname.Machine[:]),
|
||||||
|
Hostname: int8ToStr(utsname.Nodename[:]),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// initHTTPServer sets up and runs the app's main HTTP server and blocks forever.
|
// initHTTPServer sets up and runs the app's main HTTP server and blocks forever.
|
||||||
func initHTTPServer(app *App) *echo.Echo {
|
func initHTTPServer(app *App) *echo.Echo {
|
||||||
// Initialize the HTTP server.
|
// Initialize the HTTP server.
|
||||||
|
|
|
@ -51,6 +51,7 @@ type App struct {
|
||||||
captcha *captcha.Captcha
|
captcha *captcha.Captcha
|
||||||
events *events.Events
|
events *events.Events
|
||||||
notifTpls *notifTpls
|
notifTpls *notifTpls
|
||||||
|
about about
|
||||||
log *log.Logger
|
log *log.Logger
|
||||||
bufLog *buflog.BufLog
|
bufLog *buflog.BufLog
|
||||||
|
|
||||||
|
@ -229,6 +230,9 @@ func main() {
|
||||||
app.manager.AddMessenger(m)
|
app.manager.AddMessenger(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load system information.
|
||||||
|
app.about = initAbout(queries, db)
|
||||||
|
|
||||||
// Start the campaign workers. The campaign batches (fetch from DB, push out
|
// Start the campaign workers. The campaign batches (fetch from DB, push out
|
||||||
// messages) get processed at the specified interval.
|
// messages) get processed at the specified interval.
|
||||||
go app.manager.Run()
|
go app.manager.Run()
|
||||||
|
|
|
@ -2,14 +2,17 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gofrs/uuid"
|
"github.com/gofrs/uuid"
|
||||||
|
"github.com/jmoiron/sqlx/types"
|
||||||
"github.com/knadh/koanf/parsers/json"
|
"github.com/knadh/koanf/parsers/json"
|
||||||
"github.com/knadh/koanf/providers/rawbytes"
|
"github.com/knadh/koanf/providers/rawbytes"
|
||||||
"github.com/knadh/koanf/v2"
|
"github.com/knadh/koanf/v2"
|
||||||
|
@ -18,6 +21,27 @@ import (
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type aboutHost struct {
|
||||||
|
OS string `json:"os"`
|
||||||
|
OSRelease string `json:"os_release"`
|
||||||
|
Machine string `json:"arch"`
|
||||||
|
Hostname string `json:"hostname"`
|
||||||
|
}
|
||||||
|
type aboutSystem struct {
|
||||||
|
NumCPU int `json:"num_cpu"`
|
||||||
|
AllocMB uint64 `json:"memory_alloc_mb"`
|
||||||
|
OSMB uint64 `json:"memory_from_os_mb"`
|
||||||
|
}
|
||||||
|
type about struct {
|
||||||
|
Version string `json:"version"`
|
||||||
|
Build string `json:"build"`
|
||||||
|
GoVersion string `json:"go_version"`
|
||||||
|
GoArch string `json:"go_arch"`
|
||||||
|
Database types.JSONText `json:"database"`
|
||||||
|
System aboutSystem `json:"system"`
|
||||||
|
Host aboutHost `json:"host"`
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
reAlphaNum = regexp.MustCompile(`[^a-z0-9\-]`)
|
reAlphaNum = regexp.MustCompile(`[^a-z0-9\-]`)
|
||||||
)
|
)
|
||||||
|
@ -266,3 +290,24 @@ func handleTestSMTPSettings(c echo.Context) error {
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, okResp{app.bufLog.Lines()})
|
return c.JSON(http.StatusOK, okResp{app.bufLog.Lines()})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleGetAboutInfo(c echo.Context) error {
|
||||||
|
app := c.Get("app").(*App)
|
||||||
|
|
||||||
|
var (
|
||||||
|
mem runtime.MemStats
|
||||||
|
utsname syscall.Utsname
|
||||||
|
)
|
||||||
|
|
||||||
|
runtime.ReadMemStats(&mem)
|
||||||
|
|
||||||
|
if err := syscall.Uname(&utsname); err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Errorf("error getting system info: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
out := app.about
|
||||||
|
out.System.AllocMB = mem.Alloc / 1024 / 1024
|
||||||
|
out.System.OSMB = mem.Sys / 1024 / 1024
|
||||||
|
|
||||||
|
return c.JSON(http.StatusOK, out)
|
||||||
|
}
|
||||||
|
|
10
cmd/utils.go
10
cmd/utils.go
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -99,3 +100,12 @@ func strSliceContains(str string, sl []string) bool {
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func int8ToStr(bs []int8) string {
|
||||||
|
b := make([]byte, len(bs))
|
||||||
|
for i, v := range bs {
|
||||||
|
b[i] = byte(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(bytes.Trim(b, "\x00"))
|
||||||
|
}
|
||||||
|
|
|
@ -106,6 +106,7 @@ type Queries struct {
|
||||||
QueryBounces string `query:"query-bounces"`
|
QueryBounces string `query:"query-bounces"`
|
||||||
DeleteBounces *sqlx.Stmt `query:"delete-bounces"`
|
DeleteBounces *sqlx.Stmt `query:"delete-bounces"`
|
||||||
DeleteBouncesBySubscriber *sqlx.Stmt `query:"delete-bounces-by-subscriber"`
|
DeleteBouncesBySubscriber *sqlx.Stmt `query:"delete-bounces-by-subscriber"`
|
||||||
|
GetDBInfo string `query:"get-db-info"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CompileSubscriberQueryTpl takes an arbitrary WHERE expressions
|
// CompileSubscriberQueryTpl takes an arbitrary WHERE expressions
|
||||||
|
|
|
@ -1067,3 +1067,7 @@ WITH sub AS (
|
||||||
)
|
)
|
||||||
DELETE FROM bounces WHERE subscriber_id = (SELECT id FROM sub);
|
DELETE FROM bounces WHERE subscriber_id = (SELECT id FROM sub);
|
||||||
|
|
||||||
|
|
||||||
|
-- name: get-db-info
|
||||||
|
SELECT JSON_BUILD_OBJECT('version', (SELECT VERSION()),
|
||||||
|
'size_mb', (SELECT ROUND(pg_database_size('listmonk')/(1024^2)))) AS info;
|
||||||
|
|
Loading…
Reference in a new issue