You've already forked focalboard
							
							
				mirror of
				https://github.com/mattermost/focalboard.git
				synced 2025-10-31 00:17:42 +02:00 
			
		
		
		
	GH-3797 Update telemetry to send boards count (#3820)
* update telemetry to send boards count * fix lint * fix unit test
This commit is contained in:
		| @@ -29,6 +29,10 @@ func (a *App) GetBoard(boardID string) (*model.Board, error) { | ||||
| 	return board, nil | ||||
| } | ||||
|  | ||||
| func (a *App) GetBoardCount() (int64, error) { | ||||
| 	return a.store.GetBoardCount() | ||||
| } | ||||
|  | ||||
| func (a *App) GetBoardMetadata(boardID string) (*model.Board, *model.BoardMetadata, error) { | ||||
| 	license := a.store.GetLicense() | ||||
| 	if license == nil || !(*license.Features.Compliance) { | ||||
|   | ||||
| @@ -364,3 +364,17 @@ func TestPatchBoard(t *testing.T) { | ||||
| 		require.Equal(t, boardID, patchedBoard.ID) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func TestGetBoardCount(t *testing.T) { | ||||
| 	th, tearDown := SetupTestHelper(t) | ||||
| 	defer tearDown() | ||||
|  | ||||
| 	t.Run("base case", func(t *testing.T) { | ||||
| 		boardCount := int64(100) | ||||
| 		th.Store.EXPECT().GetBoardCount().Return(boardCount, nil) | ||||
|  | ||||
| 		count, err := th.App.GetBoardCount() | ||||
| 		require.NoError(t, err) | ||||
| 		require.Equal(t, boardCount, count) | ||||
| 	}) | ||||
| } | ||||
|   | ||||
| @@ -276,6 +276,13 @@ func (s *Server) Start() error { | ||||
| 		for blockType, count := range blockCounts { | ||||
| 			s.metricsService.ObserveBlockCount(blockType, count) | ||||
| 		} | ||||
| 		boardCount, err := s.store.GetBoardCount() | ||||
| 		if err != nil { | ||||
| 			s.logger.Error("Error updating metrics", mlog.String("group", "boards"), mlog.Err(err)) | ||||
| 			return | ||||
| 		} | ||||
| 		s.logger.Log(mlog.LvlFBMetrics, "Board metrics collected", mlog.Int64("board_count", boardCount)) | ||||
| 		s.metricsService.ObserveBoardCount(boardCount) | ||||
| 		teamCount, err := s.store.GetTeamCount() | ||||
| 		if err != nil { | ||||
| 			s.logger.Error("Error updating metrics", mlog.String("group", "teams"), mlog.Err(err)) | ||||
| @@ -482,6 +489,16 @@ func initTelemetry(opts telemetryOptions) *telemetry.Service { | ||||
| 		} | ||||
| 		return m, nil | ||||
| 	}) | ||||
| 	telemetryService.RegisterTracker("boards", func() (telemetry.Tracker, error) { | ||||
| 		boardCount, err := opts.app.GetBoardCount() | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		m := map[string]interface{}{ | ||||
| 			"boards": boardCount, | ||||
| 		} | ||||
| 		return m, nil | ||||
| 	}) | ||||
| 	telemetryService.RegisterTracker("teams", func() (telemetry.Tracker, error) { | ||||
| 		count, err := opts.app.GetTeamCount() | ||||
| 		if err != nil { | ||||
|   | ||||
| @@ -10,6 +10,7 @@ import ( | ||||
| const ( | ||||
| 	MetricsNamespace       = "focalboard" | ||||
| 	MetricsSubsystemBlocks = "blocks" | ||||
| 	MetricsSubsystemBoards = "boards" | ||||
| 	MetricsSubsystemTeams  = "teams" | ||||
| 	MetricsSubsystemSystem = "system" | ||||
|  | ||||
| @@ -39,6 +40,7 @@ type Metrics struct { | ||||
| 	blocksDeletedCount  prometheus.Counter | ||||
|  | ||||
| 	blockCount *prometheus.GaugeVec | ||||
| 	boardCount prometheus.Gauge | ||||
| 	teamCount  prometheus.Gauge | ||||
|  | ||||
| 	blockLastActivity prometheus.Gauge | ||||
| @@ -143,6 +145,15 @@ func NewMetrics(info InstanceInfo) *Metrics { | ||||
| 	}, []string{"BlockType"}) | ||||
| 	m.registry.MustRegister(m.blockCount) | ||||
|  | ||||
| 	m.boardCount = prometheus.NewGauge(prometheus.GaugeOpts{ | ||||
| 		Namespace:   MetricsNamespace, | ||||
| 		Subsystem:   MetricsSubsystemBoards, | ||||
| 		Name:        "boards_total", | ||||
| 		Help:        "Total number of boards.", | ||||
| 		ConstLabels: additionalLabels, | ||||
| 	}) | ||||
| 	m.registry.MustRegister(m.boardCount) | ||||
|  | ||||
| 	m.teamCount = prometheus.NewGauge(prometheus.GaugeOpts{ | ||||
| 		Namespace:   MetricsNamespace, | ||||
| 		Subsystem:   MetricsSubsystemTeams, | ||||
| @@ -209,6 +220,12 @@ func (m *Metrics) ObserveBlockCount(blockType string, count int64) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (m *Metrics) ObserveBoardCount(count int64) { | ||||
| 	if m != nil { | ||||
| 		m.boardCount.Set(float64(count)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (m *Metrics) ObserveTeamCount(count int64) { | ||||
| 	if m != nil { | ||||
| 		m.teamCount.Set(float64(count)) | ||||
|   | ||||
| @@ -551,6 +551,21 @@ func (mr *MockStoreMockRecorder) GetBoardAndCardByID(arg0 interface{}) *gomock.C | ||||
| 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBoardAndCardByID", reflect.TypeOf((*MockStore)(nil).GetBoardAndCardByID), arg0) | ||||
| } | ||||
|  | ||||
| // GetBoardCount mocks base method. | ||||
| func (m *MockStore) GetBoardCount() (int64, error) { | ||||
| 	m.ctrl.T.Helper() | ||||
| 	ret := m.ctrl.Call(m, "GetBoardCount") | ||||
| 	ret0, _ := ret[0].(int64) | ||||
| 	ret1, _ := ret[1].(error) | ||||
| 	return ret0, ret1 | ||||
| } | ||||
|  | ||||
| // GetBoardCount indicates an expected call of GetBoardCount. | ||||
| func (mr *MockStoreMockRecorder) GetBoardCount() *gomock.Call { | ||||
| 	mr.mock.ctrl.T.Helper() | ||||
| 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBoardCount", reflect.TypeOf((*MockStore)(nil).GetBoardCount)) | ||||
| } | ||||
|  | ||||
| // GetBoardHistory mocks base method. | ||||
| func (m *MockStore) GetBoardHistory(arg0 string, arg1 model.QueryBoardHistoryOptions) ([]*model.Board, error) { | ||||
| 	m.ctrl.T.Helper() | ||||
|   | ||||
| @@ -517,6 +517,23 @@ func (s *SQLStore) getBlockCountsByType(db sq.BaseRunner) (map[string]int64, err | ||||
| 	return m, nil | ||||
| } | ||||
|  | ||||
| func (s *SQLStore) getBoardCount(db sq.BaseRunner) (int64, error) { | ||||
| 	query := s.getQueryBuilder(db). | ||||
| 		Select("COUNT(*) AS count"). | ||||
| 		From(s.tablePrefix + "boards"). | ||||
| 		Where(sq.Eq{"delete_at": 0}) | ||||
|  | ||||
| 	row := query.QueryRow() | ||||
|  | ||||
| 	var count int64 | ||||
| 	err := row.Scan(&count) | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
|  | ||||
| 	return count, nil | ||||
| } | ||||
|  | ||||
| func (s *SQLStore) getBlock(db sq.BaseRunner, blockID string) (*model.Block, error) { | ||||
| 	query := s.getQueryBuilder(db). | ||||
| 		Select(s.blockFields()...). | ||||
|   | ||||
| @@ -344,6 +344,11 @@ func (s *SQLStore) GetBoardAndCardByID(blockID string) (*model.Board, *model.Blo | ||||
|  | ||||
| } | ||||
|  | ||||
| func (s *SQLStore) GetBoardCount() (int64, error) { | ||||
| 	return s.getBoardCount(s.db) | ||||
|  | ||||
| } | ||||
|  | ||||
| func (s *SQLStore) GetBoardHistory(boardID string, opts model.QueryBoardHistoryOptions) ([]*model.Board, error) { | ||||
| 	return s.getBoardHistory(s.db, boardID, opts) | ||||
|  | ||||
|   | ||||
| @@ -32,6 +32,7 @@ type Store interface { | ||||
| 	// @withTransaction | ||||
| 	UndeleteBoard(boardID string, modifiedBy string) error | ||||
| 	GetBlockCountsByType() (map[string]int64, error) | ||||
| 	GetBoardCount() (int64, error) | ||||
| 	GetBlock(blockID string) (*model.Block, error) | ||||
| 	// @withTransaction | ||||
| 	PatchBlock(blockID string, blockPatch *model.BlockPatch, userID string) error | ||||
|   | ||||
| @@ -92,6 +92,11 @@ func StoreTestBoardStore(t *testing.T, setup func(t *testing.T) (store.Store, fu | ||||
| 		defer tearDown() | ||||
| 		testGetBoardHistory(t, store) | ||||
| 	}) | ||||
| 	t.Run("GetBoardCount", func(t *testing.T) { | ||||
| 		store, tearDown := setup(t) | ||||
| 		defer tearDown() | ||||
| 		testGetBoardCount(t, store) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func testGetBoard(t *testing.T, store store.Store) { | ||||
| @@ -1139,3 +1144,28 @@ func testGetBoardHistory(t *testing.T, store store.Store) { | ||||
| 		require.Len(t, boards, 0) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func testGetBoardCount(t *testing.T, store store.Store) { | ||||
| 	userID := testUserID | ||||
|  | ||||
| 	t.Run("test GetBoardCount", func(t *testing.T) { | ||||
| 		originalCount, err := store.GetBoardCount() | ||||
| 		require.NoError(t, err) | ||||
|  | ||||
| 		title := "Board: original title" | ||||
| 		boardID := utils.NewID(utils.IDTypeBoard) | ||||
| 		board := &model.Board{ | ||||
| 			ID:     boardID, | ||||
| 			Title:  title, | ||||
| 			TeamID: testTeamID, | ||||
| 			Type:   model.BoardTypeOpen, | ||||
| 		} | ||||
|  | ||||
| 		_, err = store.InsertBoard(board, userID) | ||||
| 		require.NoError(t, err) | ||||
|  | ||||
| 		newCount, err := store.GetBoardCount() | ||||
| 		require.NoError(t, err) | ||||
| 		require.Equal(t, originalCount+1, newCount) | ||||
| 	}) | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user