diff --git a/broker/src/hidra2_broker/database/database_test.go b/broker/src/hidra2_broker/database/database_test.go index 207b40683c2a6575b546a468a4b698d6f7071d9a..3073ed61b1a621ae47e3a41903e75f2a85836255 100644 --- a/broker/src/hidra2_broker/database/database_test.go +++ b/broker/src/hidra2_broker/database/database_test.go @@ -12,7 +12,10 @@ func TestMockDataBase(t *testing.T) { db.On("Close").Return() db.On("Copy").Return(nil) db.On("GetNextRecord", "").Return([]byte(""), nil) - db.Connect("") db.GetNextRecord("") + db.Close() + db.Copy() + var err DBError + err.Error() } diff --git a/broker/src/hidra2_broker/database/mock_database.go b/broker/src/hidra2_broker/database/mock_database.go index fbeb4582c4e4304979a1d05f7ee70b7dd2a04ce8..cf25a1eea71a73fa8973027b8a70cfc574643fda 100644 --- a/broker/src/hidra2_broker/database/mock_database.go +++ b/broker/src/hidra2_broker/database/mock_database.go @@ -19,7 +19,7 @@ func (db *MockedDatabase) Close() { db.Called() } -func (db *MockedDatabase) Copy() Agent{ +func (db *MockedDatabase) Copy() Agent { db.Called() return db } diff --git a/broker/src/hidra2_broker/server/get_next.go b/broker/src/hidra2_broker/server/get_next.go index ae29d355f5d7f1181d867b32cc811df9df7910cd..672a398987e0a85d40f93d98537beb0e68d77263 100644 --- a/broker/src/hidra2_broker/server/get_next.go +++ b/broker/src/hidra2_broker/server/get_next.go @@ -15,8 +15,8 @@ func extractRequestParameters(r *http.Request) (string, bool) { func routeGetNext(w http.ResponseWriter, r *http.Request) { r.Header.Set("Content-type", "application/json") - // w.Write([]byte("Hello")) - // return + // w.Write([]byte("Hello")) + // return db_name, ok := extractRequestParameters(r) if !ok { w.WriteHeader(http.StatusBadRequest) @@ -31,6 +31,7 @@ func routeGetNext(w http.ResponseWriter, r *http.Request) { func getNextRecord(db_name string) (answer []byte, code int) { db_new := db.Copy() defer db_new.Close() + statistics.IncreaseCounter() answer, err := db_new.GetNextRecord(db_name) if err != nil { err_db, ok := err.(*database.DBError) diff --git a/broker/src/hidra2_broker/server/get_next_test.go b/broker/src/hidra2_broker/server/get_next_test.go index 11385f121b5412533e9d30ff6c87357ca211fe07..36f5cad439a721ed9f94d552752f3605b6d876be 100644 --- a/broker/src/hidra2_broker/server/get_next_test.go +++ b/broker/src/hidra2_broker/server/get_next_test.go @@ -3,6 +3,7 @@ package server import ( "errors" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" "hidra2_broker/database" "hidra2_broker/utils" "net/http" @@ -30,45 +31,57 @@ func TestGetNextWithoutDatabaseName(t *testing.T) { assert.Equal(t, http.StatusNotFound, w.Code, "no database name") } -func ExpectCopyClose(mock_db *database.MockedDatabase){ +func ExpectCopyClose(mock_db *database.MockedDatabase) { mock_db.On("Copy").Return(mock_db) mock_db.On("Close").Return() } -func TestGetNextWithWrongDatabaseName(t *testing.T) { - mock_db := new(database.MockedDatabase) - db = mock_db - defer func() { db = nil }() - ExpectCopyClose(mock_db) - mock_db.On("GetNextRecord", "foo").Return([]byte(""), +type GetNextTestSuite struct { + suite.Suite + mock_db *database.MockedDatabase +} + +func (suite *GetNextTestSuite) SetupTest() { + statistics.Reset() + suite.mock_db = new(database.MockedDatabase) + db = suite.mock_db + ExpectCopyClose(suite.mock_db) +} + +func (suite *GetNextTestSuite) TearDownTest() { + assertExpectations(suite.T(), suite.mock_db) + db = nil +} + +func TestGetNextTestSuite(t *testing.T) { + suite.Run(t, new(GetNextTestSuite)) +} + +func (suite *GetNextTestSuite) TestGetNextWithWrongDatabaseName() { + suite.mock_db.On("GetNextRecord", "foo").Return([]byte(""), &database.DBError{utils.StatusWrongInput, ""}) w := doRequest("/database/foo/next") - assert.Equal(t, http.StatusBadRequest, w.Code, "wrong database name") - assertExpectations(t, mock_db) + suite.Equal(http.StatusBadRequest, w.Code, "wrong database name") } -func TestGetNextWithInternalDBError(t *testing.T) { - mock_db := new(database.MockedDatabase) - db = mock_db - defer func() { db = nil }() - ExpectCopyClose(mock_db) - mock_db.On("GetNextRecord", "foo").Return([]byte(""), errors.New("")) - +func (suite *GetNextTestSuite) TestGetNextWithInternalDBError() { + suite.mock_db.On("GetNextRecord", "foo").Return([]byte(""), errors.New("")) w := doRequest("/database/foo/next") - assert.Equal(t, http.StatusInternalServerError, w.Code, "internal error") - assertExpectations(t, mock_db) + suite.Equal(http.StatusInternalServerError, w.Code, "internal error") } -func TestGetNextWithGoodDatabaseName(t *testing.T) { - mock_db := new(database.MockedDatabase) - db = mock_db - defer func() { db = nil }() - ExpectCopyClose(mock_db) - mock_db.On("GetNextRecord", "dbname").Return([]byte("Hello"), nil) +func (suite *GetNextTestSuite) TestGetNextWithGoodDatabaseName() { + suite.mock_db.On("GetNextRecord", "dbname").Return([]byte("Hello"), nil) w := doRequest("/database/dbname/next") - assert.Equal(t, http.StatusOK, w.Code, "GetNext OK") - assert.Equal(t, "Hello", string(w.Body.Bytes()), "GetNext sends data") - assertExpectations(t, mock_db) + suite.Equal(http.StatusOK, w.Code, "GetNext OK") + suite.Equal("Hello", string(w.Body.Bytes()), "GetNext sends data") +} + +func (suite *GetNextTestSuite) TestGetNextAddsCounter() { + suite.mock_db.On("GetNextRecord", "dbname").Return([]byte("Hello"), nil) + + doRequest("/database/dbname/next") + suite.Equal(1, statistics.GetCounter(), "GetNext increases counter") } diff --git a/broker/src/hidra2_broker/server/server.go b/broker/src/hidra2_broker/server/server.go index 7e85cbca759de0a7b43a76bd1c25af1aa12dd1d6..d517d373ff0bdaadc11445ee7c0cdd93cd34bedf 100644 --- a/broker/src/hidra2_broker/server/server.go +++ b/broker/src/hidra2_broker/server/server.go @@ -12,6 +12,7 @@ type serverSettings struct { } var settings serverSettings +var statistics serverStatistics func InitDB(dbAgent database.Agent) error { db = dbAgent diff --git a/broker/src/hidra2_broker/server/server_nottested.go b/broker/src/hidra2_broker/server/server_nottested.go index cf6bd72f72fff462af1860df2d8bcec5587ed83f..e31a0d2df355b2dcc7b3a8c010399a8f3aed61f1 100644 --- a/broker/src/hidra2_broker/server/server_nottested.go +++ b/broker/src/hidra2_broker/server/server_nottested.go @@ -9,7 +9,14 @@ import ( "strconv" ) +func StartStatistics() { + statistics.Writer = new(StatisticInfluxDbWriter) + statistics.Reset() + go statistics.Monitor() +} + func Start() { + StartStatistics() mux := utils.NewRouter(listRoutes) log.Fatal(http.ListenAndServe("localhost:"+strconv.Itoa(settings.Port), http.HandlerFunc(mux.ServeHTTP))) } diff --git a/broker/src/hidra2_broker/server/statistics.go b/broker/src/hidra2_broker/server/statistics.go new file mode 100644 index 0000000000000000000000000000000000000000..860c766ea38f97a214061970ff72c6f19f0bdf6d --- /dev/null +++ b/broker/src/hidra2_broker/server/statistics.go @@ -0,0 +1,47 @@ +package server + +import ( + "fmt" + "log" + "time" +) + +type statisticsWriter interface { + Write(*serverStatistics) error +} + +type serverStatistics struct { + counter int + Writer statisticsWriter +} + +func (st *serverStatistics) IncreaseCounter() { + st.counter++ +} + +func (st *serverStatistics) GetCounter() int { + return st.counter +} + +func (st *serverStatistics) Reset() { + st.counter = 0 +} + +func (st *serverStatistics) WriteStatistic() (err error) { + defer func() { + if p := recover(); p != nil { + err = fmt.Errorf("WriteStatistic error: %v", p) + } + }() + return st.Writer.Write(st) +} + +func (st *serverStatistics) Monitor() { + for { + time.Sleep(1000 * time.Millisecond) + if err := st.WriteStatistic(); err != nil { + log.Println(err.Error()) + } + st.Reset() + } +} diff --git a/broker/src/hidra2_broker/server/statistics_test.go b/broker/src/hidra2_broker/server/statistics_test.go new file mode 100644 index 0000000000000000000000000000000000000000..a16a8be4a10fccdfb1b60ce8b81c6b8e1dc97d85 --- /dev/null +++ b/broker/src/hidra2_broker/server/statistics_test.go @@ -0,0 +1,41 @@ +package server + +import ( + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "testing" +) + +type mockWriter struct { + mock.Mock +} + +func (writer *mockWriter) Write(statistics *serverStatistics) error { + args := writer.Called(statistics) + return args.Error(0) +} + +func assertMockWriterExpectations(t *testing.T, mock_writer *mockWriter) { + mock_writer.AssertExpectations(t) + mock_writer.ExpectedCalls = nil +} + +func TestMonitorOK(t *testing.T) { + mock_writer := new(mockWriter) + statistics.Writer = mock_writer + statistics.Reset() + statistics.IncreaseCounter() + + mock_writer.On("Write", &statistics).Return(nil) + + err := statistics.WriteStatistic() + assert.Nil(t, err, "Statistics written") + + assertMockWriterExpectations(t, mock_writer) +} + +func TestMonitorCatchesError(t *testing.T) { + statistics.Writer = nil + err := statistics.WriteStatistic() + assert.NotNil(t, err, "Error with nil pointer") +} diff --git a/broker/src/hidra2_broker/server/statistics_writer.go b/broker/src/hidra2_broker/server/statistics_writer.go new file mode 100644 index 0000000000000000000000000000000000000000..ffc619145736391933f41935089712368196950f --- /dev/null +++ b/broker/src/hidra2_broker/server/statistics_writer.go @@ -0,0 +1,47 @@ +//+build !test + +package server + +import ( + "github.com/influxdata/influxdb/client/v2" + "log" + "time" +) + +type StatisticLogWriter struct { +} + +func (writer *StatisticLogWriter) Write(statistics *serverStatistics) error { + log.Println(statistics.GetCounter()) + return nil +} + +type StatisticInfluxDbWriter struct { +} + +func (writer *StatisticInfluxDbWriter) Write(statistics *serverStatistics) error { + c, err := client.NewHTTPClient(client.HTTPConfig{ + Addr: "http://localhost:8086", + }) + if err != nil { + return err + } + defer c.Close() + + bp, _ := client.NewBatchPoints(client.BatchPointsConfig{ + Database: "db", + Precision: "s", + }) + + // tags := map[string]string{"rate": "rate-total"} + fields := map[string]interface{}{ + "rate": statistics.GetCounter(), + } + pt, err := client.NewPoint("RequestsRate", nil, fields, time.Now()) + if err != nil { + return err + } + bp.AddPoint(pt) + + return c.Write(bp) +}