console: add an API to get flow rate

This commit is contained in:
Vincent Bernat
2022-04-14 13:50:00 +02:00
parent 12344a3684
commit 793e55db52
3 changed files with 67 additions and 8 deletions

View File

@@ -55,8 +55,9 @@ func (c *Component) Start() error {
c.d.HTTP.AddHandler("/", netHTTP.HandlerFunc(c.assetsHandlerFunc)) c.d.HTTP.AddHandler("/", netHTTP.HandlerFunc(c.assetsHandlerFunc))
c.d.HTTP.GinRouter.GET("/api/v0/console/docs/:name", c.docsHandlerFunc) c.d.HTTP.GinRouter.GET("/api/v0/console/docs/:name", c.docsHandlerFunc)
c.d.HTTP.GinRouter.GET("/api/v0/console/last-flow", c.apiLastFlowHandlerFunc) c.d.HTTP.GinRouter.GET("/api/v0/console/widget/flow-last", c.widgetFlowLastHandlerFunc)
c.d.HTTP.GinRouter.GET("/api/v0/console/exporters", c.apiExportersHandlerFunc) c.d.HTTP.GinRouter.GET("/api/v0/console/widget/flow-rate", c.widgetFlowRateHandlerFunc)
c.d.HTTP.GinRouter.GET("/api/v0/console/widget/exporters", c.widgetExportersHandlerFunc)
c.t.Go(func() error { c.t.Go(func() error {
select { select {

View File

@@ -7,7 +7,7 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
func (c *Component) apiLastFlowHandlerFunc(gc *gin.Context) { func (c *Component) widgetFlowLastHandlerFunc(gc *gin.Context) {
ctx := c.t.Context(gc.Request.Context()) ctx := c.t.Context(gc.Request.Context())
rows, err := c.d.ClickHouseDB.Conn.Query(ctx, rows, err := c.d.ClickHouseDB.Conn.Query(ctx,
`SELECT * FROM flows WHERE TimeReceived = (SELECT MAX(TimeReceived) FROM flows) LIMIT 1`) `SELECT * FROM flows WHERE TimeReceived = (SELECT MAX(TimeReceived) FROM flows) LIMIT 1`)
@@ -42,7 +42,28 @@ func (c *Component) apiLastFlowHandlerFunc(gc *gin.Context) {
gc.IndentedJSON(http.StatusOK, response) gc.IndentedJSON(http.StatusOK, response)
} }
func (c *Component) apiExportersHandlerFunc(gc *gin.Context) { func (c *Component) widgetFlowRateHandlerFunc(gc *gin.Context) {
ctx := c.t.Context(gc.Request.Context())
row := c.d.ClickHouseDB.Conn.QueryRow(ctx,
`SELECT COUNT(*)/300 AS rate FROM flows WHERE TimeReceived > date_sub(minute, 5, now())`)
if err := row.Err(); err != nil {
c.r.Err(err).Msg("unable to query database")
gc.JSON(http.StatusInternalServerError, gin.H{"message": "Unable to query database."})
return
}
var result float64
if err := row.Scan(&result); err != nil {
c.r.Err(err).Msg("unable to parse result")
gc.JSON(http.StatusInternalServerError, gin.H{"message": "Unable to parse result."})
return
}
gc.IndentedJSON(http.StatusOK, gin.H{
"rate": result,
"period": "second",
})
}
func (c *Component) widgetExportersHandlerFunc(gc *gin.Context) {
ctx := c.t.Context(gc.Request.Context()) ctx := c.t.Context(gc.Request.Context())
exporters := []struct { exporters := []struct {

View File

@@ -17,7 +17,7 @@ import (
"akvorado/common/reporter" "akvorado/common/reporter"
) )
func TestAPILastFlow(t *testing.T) { func TestWidgetLastFlow(t *testing.T) {
r := reporter.NewMock(t) r := reporter.NewMock(t)
ch, mockConn := clickhousedb.NewMock(t, r) ch, mockConn := clickhousedb.NewMock(t, r)
h := http.NewMock(t, r) h := http.NewMock(t, r)
@@ -89,7 +89,7 @@ func TestAPILastFlow(t *testing.T) {
helpers.TestHTTPEndpoints(t, h.Address, helpers.HTTPEndpointCases{ helpers.TestHTTPEndpoints(t, h.Address, helpers.HTTPEndpointCases{
{ {
URL: "/api/v0/console/last-flow", URL: "/api/v0/console/widget/flow-last",
ContentType: "application/json; charset=utf-8", ContentType: "application/json; charset=utf-8",
FirstLines: []string{ FirstLines: []string{
`{`, `{`,
@@ -106,7 +106,44 @@ func TestAPILastFlow(t *testing.T) {
}) })
} }
func TestAPIExporters(t *testing.T) { func TestFlowRate(t *testing.T) {
r := reporter.NewMock(t)
ch, mockConn := clickhousedb.NewMock(t, r)
h := http.NewMock(t, r)
c, err := New(r, Configuration{}, Dependencies{
Daemon: daemon.NewMock(t),
HTTP: h,
ClickHouseDB: ch,
})
if err != nil {
t.Fatalf("New() error:\n%+v", err)
}
helpers.StartStop(t, c)
ctrl := gomock.NewController(t)
mockRow := mocks.NewMockRow(ctrl)
mockRow.EXPECT().Err().Return(nil)
mockRow.EXPECT().Scan(gomock.Any()).SetArg(0, float64(100.1)).Return(nil)
mockConn.EXPECT().
QueryRow(gomock.Any(),
`SELECT COUNT(*)/300 AS rate FROM flows WHERE TimeReceived > date_sub(minute, 5, now())`).
Return(mockRow)
helpers.TestHTTPEndpoints(t, h.Address, helpers.HTTPEndpointCases{
{
URL: "/api/v0/console/widget/flow-rate",
ContentType: "application/json; charset=utf-8",
FirstLines: []string{
`{`,
` "period": "second",`,
` "rate": 100.1`,
`}`,
},
},
})
}
func TestWidgetExporters(t *testing.T) {
r := reporter.NewMock(t) r := reporter.NewMock(t)
ch, mockConn := clickhousedb.NewMock(t, r) ch, mockConn := clickhousedb.NewMock(t, r)
h := http.NewMock(t, r) h := http.NewMock(t, r)
@@ -135,7 +172,7 @@ func TestAPIExporters(t *testing.T) {
helpers.TestHTTPEndpoints(t, h.Address, helpers.HTTPEndpointCases{ helpers.TestHTTPEndpoints(t, h.Address, helpers.HTTPEndpointCases{
{ {
URL: "/api/v0/console/exporters", URL: "/api/v0/console/widget/exporters",
ContentType: "application/json; charset=utf-8", ContentType: "application/json; charset=utf-8",
FirstLines: []string{ FirstLines: []string{
`{`, `{`,