From 793e55db528953749ffc6f728d16f66283f88a18 Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Thu, 14 Apr 2022 13:50:00 +0200 Subject: [PATCH] console: add an API to get flow rate --- console/root.go | 5 +-- console/{api.go => widgets.go} | 25 +++++++++++-- console/{api_test.go => widgets_test.go} | 45 +++++++++++++++++++++--- 3 files changed, 67 insertions(+), 8 deletions(-) rename console/{api.go => widgets.go} (66%) rename console/{api_test.go => widgets_test.go} (77%) diff --git a/console/root.go b/console/root.go index ea12bbe1..0a47f0f8 100644 --- a/console/root.go +++ b/console/root.go @@ -55,8 +55,9 @@ func (c *Component) Start() error { 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/last-flow", c.apiLastFlowHandlerFunc) - c.d.HTTP.GinRouter.GET("/api/v0/console/exporters", c.apiExportersHandlerFunc) + c.d.HTTP.GinRouter.GET("/api/v0/console/widget/flow-last", c.widgetFlowLastHandlerFunc) + 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 { select { diff --git a/console/api.go b/console/widgets.go similarity index 66% rename from console/api.go rename to console/widgets.go index 1421cea9..c50e0953 100644 --- a/console/api.go +++ b/console/widgets.go @@ -7,7 +7,7 @@ import ( "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()) rows, err := c.d.ClickHouseDB.Conn.Query(ctx, `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) } -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()) exporters := []struct { diff --git a/console/api_test.go b/console/widgets_test.go similarity index 77% rename from console/api_test.go rename to console/widgets_test.go index 078b17c4..7c34baec 100644 --- a/console/api_test.go +++ b/console/widgets_test.go @@ -17,7 +17,7 @@ import ( "akvorado/common/reporter" ) -func TestAPILastFlow(t *testing.T) { +func TestWidgetLastFlow(t *testing.T) { r := reporter.NewMock(t) ch, mockConn := clickhousedb.NewMock(t, r) h := http.NewMock(t, r) @@ -89,7 +89,7 @@ func TestAPILastFlow(t *testing.T) { 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", 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) ch, mockConn := clickhousedb.NewMock(t, r) h := http.NewMock(t, r) @@ -135,7 +172,7 @@ func TestAPIExporters(t *testing.T) { helpers.TestHTTPEndpoints(t, h.Address, helpers.HTTPEndpointCases{ { - URL: "/api/v0/console/exporters", + URL: "/api/v0/console/widget/exporters", ContentType: "application/json; charset=utf-8", FirstLines: []string{ `{`,