Files
devstar/services/user/stats.go
zhufengliang 85fc3665d4
Some checks failed
DevStar Studio Auto Test Pipeline / unit-frontend-test (pull_request) Failing after 41s
DevStar Studio Auto Test Pipeline / unit-backend-test (pull_request) Failing after 32s
DevStar Studio CI/CD Pipeline / build-and-push-x86-64-docker-image (pull_request) Failing after 37s
DevStar E2E Test / e2e-test (pull_request) Has been cancelled
用户存储用量统计
2025-12-01 21:11:57 +08:00

237 lines
7.3 KiB
Go

// Copyright 2024 The DevStar Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package user
import (
"context"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
devcontainer_model "code.gitea.io/gitea/models/devcontainer"
"code.gitea.io/gitea/modules/log"
)
// UserStats represents the user's data statistics
type UserStats struct {
UserID int64 `json:"user_id"`
// Repository statistics
TotalRepositories int `json:"total_repositories"`
PublicRepositories int `json:"public_repositories"`
PrivateRepositories int `json:"private_repositories"`
// Storage statistics
TotalStorage int64 `json:"total_storage"`
GitStorage int64 `json:"git_storage"`
LFSStorage int64 `json:"lfs_storage"`
AssetsStorage int64 `json:"assets_storage"`
// DevContainer statistics
TotalDevContainers int `json:"total_devcontainers"`
ActiveDevContainers int `json:"active_devcontainers"`
// Activity statistics
TotalCommits int `json:"total_commits"`
TotalIssues int `json:"total_issues"`
PullRequests int `json:"pull_requests"`
ClosedIssues int `json:"closed_issues"`
MergedPullRequests int `json:"merged_pull_requests"`
}
// GetUserStatistics calculates and returns comprehensive statistics for a user
func GetUserStatistics(ctx context.Context, userID int64) (*UserStats, error) {
stats := &UserStats{
UserID: userID,
}
// Get repository statistics
if err := getRepoStats(ctx, userID, stats); err != nil {
log.Error("Failed to get repository statistics for user %d: %v", userID, err)
return nil, err
}
// Get devcontainer statistics
if err := getDevContainerStats(ctx, userID, stats); err != nil {
log.Error("Failed to get devcontainer statistics for user %d: %v", userID, err)
return nil, err
}
// Get activity statistics (commits, issues, PRs)
if err := getActivityStats(ctx, userID, stats); err != nil {
log.Error("Failed to get activity statistics for user %d: %v", userID, err)
return nil, err
}
return stats, nil
}
// getRepoStats calculates repository-related statistics
func getRepoStats(ctx context.Context, userID int64, stats *UserStats) error {
// Count total repositories for the user
count, err := repo_model.CountRepositories(ctx, repo_model.CountRepositoryOptions{
OwnerID: userID,
})
if err != nil {
return err
}
stats.TotalRepositories = int(count)
// Get all repositories to calculate storage and visibility breakdown
repos, _, err := repo_model.GetUserRepositories(ctx, repo_model.SearchRepoOptions{
ListOptions: db.ListOptions{
PageSize: 1000, // Get all repos
},
Actor: &user_model.User{ID: userID},
})
if err != nil {
return err
}
var totalSize, gitSize, lfsSize int64
publicCount, privateCount := 0, 0
for _, repo := range repos {
// Count by visibility
if repo.IsPrivate {
privateCount++
} else {
publicCount++
}
// Sum storage sizes
totalSize += repo.Size
gitSize += repo.GitSize
lfsSize += repo.LFSSize
}
stats.PublicRepositories = publicCount
stats.PrivateRepositories = privateCount
stats.TotalStorage = totalSize
stats.GitStorage = gitSize
stats.LFSStorage = lfsSize
// Assets storage would need additional calculation from attachments, releases, etc.
stats.AssetsStorage = 0 // TODO: Implement assets storage calculation
return nil
}
// getDevContainerStats calculates devcontainer-related statistics
func getDevContainerStats(ctx context.Context, userID int64, stats *UserStats) error {
// Count total devcontainers for the user
count, err := db.GetEngine(ctx).
Where("user_id = ?", userID).
Count(&devcontainer_model.Devcontainer{})
if err != nil {
return err
}
stats.TotalDevContainers = int(count)
// Count active devcontainers (assuming status 1 means active)
activeCount, err := db.GetEngine(ctx).
Where("user_id = ? AND devcontainer_status = ?", userID, 1).
Count(&devcontainer_model.Devcontainer{})
if err != nil {
return err
}
stats.ActiveDevContainers = int(activeCount)
return nil
}
// getActivityStats calculates activity-related statistics (commits, issues, PRs)
func getActivityStats(ctx context.Context, userID int64, stats *UserStats) error {
// Get user's commits count across all their repositories
// This is a simplified version - in reality you'd need to query git logs
commitCount, err := getUserCommitCount(ctx, userID)
if err != nil {
log.Warn("Failed to get commit count for user %d: %v", userID, err)
commitCount = 0 // Continue without commit stats
}
stats.TotalCommits = commitCount
// Count issues created by user
issueCount, err := getUserIssueCount(ctx, userID)
if err != nil {
log.Warn("Failed to get issue count for user %d: %v", userID, err)
issueCount = 0
}
stats.TotalIssues = issueCount
// Count pull requests created by user
prCount, err := getUserPullRequestCount(ctx, userID)
if err != nil {
log.Warn("Failed to get PR count for user %d: %v", userID, err)
prCount = 0
}
stats.PullRequests = prCount
// Count closed issues and merged PRs
closedIssues, err := getUserClosedIssueCount(ctx, userID)
if err != nil {
log.Warn("Failed to get closed issue count for user %d: %v", userID, err)
closedIssues = 0
}
stats.ClosedIssues = closedIssues
mergedPRs, err := getUserMergedPullRequestCount(ctx, userID)
if err != nil {
log.Warn("Failed to get merged PR count for user %d: %v", userID, err)
mergedPRs = 0
}
stats.MergedPullRequests = mergedPRs
return nil
}
// getUserCommitCount gets the total number of commits made by the user
func getUserCommitCount(ctx context.Context, userID int64) (int, error) {
// This is a placeholder implementation
// In a real implementation, you would:
// 1. Get all repositories owned by the user
// 2. For each repository, query git log for commits by this user's email
// 3. Sum up all commits
user, err := user_model.GetUserByID(ctx, userID)
if err != nil {
return 0, err
}
// For now, return 0 as this would require git log parsing
// TODO: Implement actual commit counting
log.Info("Commit counting not yet implemented for user %s (%s)", user.Name, user.Email)
return 0, nil
}
// getUserIssueCount gets the total number of issues created by the user
func getUserIssueCount(ctx context.Context, userID int64) (int, error) {
// This would query the issues table
// For now, return a placeholder value
// TODO: Implement actual issue counting
return 0, nil
}
// getUserPullRequestCount gets the total number of pull requests created by the user
func getUserPullRequestCount(ctx context.Context, userID int64) (int, error) {
// This would query the pull_requests table
// For now, return a placeholder value
// TODO: Implement actual PR counting
return 0, nil
}
// getUserClosedIssueCount gets the number of closed issues created by the user
func getUserClosedIssueCount(ctx context.Context, userID int64) (int, error) {
// This would query the issues table for closed issues
// For now, return a placeholder value
// TODO: Implement actual closed issue counting
return 0, nil
}
// getUserMergedPullRequestCount gets the number of merged pull requests created by the user
func getUserMergedPullRequestCount(ctx context.Context, userID int64) (int, error) {
// This would query the pull_requests table for merged PRs
// For now, return a placeholder value
// TODO: Implement actual merged PR counting
return 0, nil
}