You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

repo_statistic.go 13 kB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. package repo
  2. import (
  3. "errors"
  4. "time"
  5. "code.gitea.io/gitea/models"
  6. "code.gitea.io/gitea/modules/log"
  7. "code.gitea.io/gitea/modules/normalization"
  8. "code.gitea.io/gitea/modules/repository"
  9. "code.gitea.io/gitea/modules/setting"
  10. "code.gitea.io/gitea/services/mailer"
  11. "gitea.com/macaron/macaron"
  12. )
  13. func StatisticAuto() {
  14. RepoStatisticAuto()
  15. TimingCountData()
  16. }
  17. //auto daily
  18. func RepoStatisticAuto() {
  19. yesterday := time.Now().AddDate(0, 0, -1).Format("2006-01-02")
  20. setting.UpdateRadarMap()
  21. RepoStatisticDaily(yesterday)
  22. }
  23. func RepoStatisticDaily(date string) {
  24. log.Info("%s", date)
  25. log.Info("begin Repo Statistic")
  26. t, _ := time.Parse("2006-01-02", date)
  27. warnEmailMessage := "项目统计信息入库失败,请尽快定位。"
  28. if err := models.DeleteRepoStatDaily(date); err != nil {
  29. log.Error("DeleteRepoStatDaily failed: %v", err.Error())
  30. mailer.SendWarnNotifyMail(setting.Warn_Notify_Mails, warnEmailMessage)
  31. return
  32. }
  33. repos, err := models.GetAllRepositories()
  34. if err != nil {
  35. log.Error("GetAllRepositories failed: %v", err.Error())
  36. mailer.SendWarnNotifyMail(setting.Warn_Notify_Mails, warnEmailMessage)
  37. return
  38. }
  39. var reposRadar = make([]*models.RepoStatistic, 0)
  40. var minRepoRadar models.RepoStatistic
  41. var maxRepoRadar models.RepoStatistic
  42. isInitMinMaxRadar := false
  43. var error_projects = make([]string, 0)
  44. for _, repo := range repos {
  45. projectName := getDistinctProjectName(repo)
  46. log.Info("start statistic: %s", projectName)
  47. var numDevMonths, numWikiViews, numContributor, numKeyContributor, numCommitsGrowth, numCommitLinesGrowth, numContributorsGrowth, numCommits int64
  48. repoGitStat, err := models.GetRepoKPIStats(repo)
  49. if err != nil {
  50. log.Error("GetRepoKPIStats failed: %s", projectName)
  51. } else {
  52. numDevMonths = repoGitStat.DevelopAge
  53. numKeyContributor = repoGitStat.KeyContributors
  54. numWikiViews = repoGitStat.WikiPages
  55. numContributor = repoGitStat.Contributors
  56. numCommitsGrowth = repoGitStat.CommitsAdded
  57. numCommitLinesGrowth = repoGitStat.CommitLinesModified
  58. numContributorsGrowth = repoGitStat.ContributorsAdded
  59. numCommits = repoGitStat.Commits
  60. }
  61. var issueFixedRate float32
  62. if repo.NumIssues != 0 {
  63. issueFixedRate = float32(repo.NumClosedIssues) / float32(repo.NumIssues)
  64. } else {
  65. issueFixedRate = float32(setting.RadarMap.ProjectHealth0IssueCloseRatio)
  66. }
  67. var numVersions int64
  68. numVersions, err = models.GetReleaseCountByRepoID(repo.ID, models.FindReleasesOptions{})
  69. if err != nil {
  70. log.Error("GetReleaseCountByRepoID failed(%s): %v", projectName, err)
  71. }
  72. var datasetSize int64
  73. datasetSize, err = getDatasetSize(repo)
  74. if err != nil {
  75. log.Error("getDatasetSize failed(%s): %v", projectName, err)
  76. }
  77. var numComments int64
  78. numComments, err = models.GetCommentCountByRepoID(repo.ID)
  79. if err != nil {
  80. log.Error("GetCommentCountByRepoID failed(%s): %v", projectName, err)
  81. }
  82. beginTime, endTime := getStatTime(date)
  83. var numVisits int
  84. numVisits, err = repository.AppointProjectView(repo.OwnerName, repo.Name, beginTime, endTime)
  85. if err != nil {
  86. log.Error("AppointProjectView failed(%s): %v", projectName, err)
  87. }
  88. repoStat := models.RepoStatistic{
  89. RepoID: repo.ID,
  90. Date: date,
  91. Name: repo.Name,
  92. Alias: repo.Alias,
  93. IsPrivate: repo.IsPrivate,
  94. IsMirror: repo.IsMirror,
  95. IsFork: repo.IsFork,
  96. RepoCreatedUnix: repo.CreatedUnix,
  97. OwnerName: repo.OwnerName,
  98. NumWatches: int64(repo.NumWatches),
  99. NumStars: int64(repo.NumStars),
  100. NumForks: int64(repo.NumForks),
  101. NumDownloads: repo.CloneCnt,
  102. NumComments: numComments,
  103. NumVisits: int64(numVisits),
  104. NumClosedIssues: int64(repo.NumClosedIssues),
  105. NumVersions: numVersions,
  106. NumDevMonths: numDevMonths,
  107. RepoSize: repo.Size,
  108. DatasetSize: datasetSize,
  109. NumModels: repo.ModelCnt,
  110. NumWikiViews: numWikiViews,
  111. NumCommits: numCommits,
  112. NumIssues: int64(repo.NumIssues),
  113. NumPulls: int64(repo.NumPulls),
  114. IssueFixedRate: issueFixedRate,
  115. NumContributor: numContributor,
  116. NumKeyContributor: numKeyContributor,
  117. NumCommitsGrowth: numCommitsGrowth,
  118. NumCommitLinesGrowth: numCommitLinesGrowth,
  119. NumContributorsGrowth: numContributorsGrowth,
  120. NumCloudbrain: repo.AiTaskCnt,
  121. NumDatasetFile: repo.DatasetCnt,
  122. NumModelConvert: models.QueryModelConvertCountByRepoID(repo.ID),
  123. }
  124. dayBeforeDate := t.AddDate(0, 0, -1).Format("2006-01-02")
  125. repoStatisticsBefore, err := models.GetRepoStatisticByDate(dayBeforeDate, repo.ID)
  126. if err != nil {
  127. log.Error("get data of day before the date failed ", err)
  128. } else {
  129. if len(repoStatisticsBefore) > 0 {
  130. repoStatisticBefore := repoStatisticsBefore[0]
  131. repoStat.NumWatchesAdded = repoStat.NumWatches - repoStatisticBefore.NumWatches
  132. repoStat.NumStarsAdded = repoStat.NumStars - repoStatisticBefore.NumStars
  133. repoStat.NumForksAdded = repoStat.NumForks - repoStatisticBefore.NumForks
  134. repoStat.NumDownloadsAdded = repoStat.NumDownloads - repoStatisticBefore.NumDownloads
  135. repoStat.NumCommentsAdded = repoStat.NumComments - repoStatisticBefore.NumComments
  136. repoStat.NumClosedIssuesAdded = repoStat.NumClosedIssues - repoStatisticBefore.NumClosedIssues
  137. repoStat.NumCommitsAdded = repoStat.NumCommits - repoStatisticBefore.NumCommits
  138. repoStat.NumIssuesAdded = repoStat.NumIssues - repoStatisticBefore.NumIssues
  139. repoStat.NumPullsAdded = repoStat.NumPulls - repoStatisticBefore.NumPulls
  140. repoStat.NumContributorAdded = repoStat.NumContributor - repoStatisticBefore.NumContributor
  141. repoStat.NumModelsAdded = repoStat.NumModels - repoStatisticBefore.NumModels
  142. repoStat.NumCloudbrainAdded = repoStat.NumCloudbrain - repoStatisticBefore.NumCloudbrain
  143. repoStat.NumModelConvertAdded = repoStat.NumModelConvert - repoStatisticBefore.NumModelConvert
  144. repoStat.NumDatasetFileAdded = repoStat.NumDatasetFile - repoStatisticBefore.NumDatasetFile
  145. }
  146. }
  147. day4MonthsAgo := t.AddDate(0, -4, 0)
  148. repoStatisticFourMonthsAgo, err := models.GetOneRepoStatisticBeforeTime(day4MonthsAgo)
  149. if err != nil {
  150. log.Error("Get data of 4 moth ago failed.", err)
  151. } else {
  152. repoStat.NumCommentsGrowth = repoStat.NumComments - repoStatisticFourMonthsAgo.NumComments
  153. repoStat.NumIssuesGrowth = repoStat.NumIssues - repoStatisticFourMonthsAgo.NumIssues
  154. }
  155. models.SyncStatDataToRepo(repo)
  156. if _, err = models.InsertRepoStat(&repoStat); err != nil {
  157. log.Error("InsertRepoStat failed(%s): %v", projectName, err)
  158. log.Error("failed statistic: %s", projectName)
  159. error_projects = append(error_projects, projectName)
  160. continue
  161. }
  162. tempRepoStat := models.RepoStatistic{
  163. RepoID: repoStat.RepoID,
  164. Date: repoStat.Date,
  165. IsMirror: repoStat.IsMirror,
  166. Impact: normalization.GetImpactInitValue(repoStat.NumWatches, repoStat.NumStars, repoStat.NumForks, repoStat.NumDownloads, repoStat.NumComments, repoStat.NumVisits),
  167. Completeness: normalization.GetCompleteInitValue(repoStat.NumClosedIssues, repoStat.NumVersions, repoStat.NumDevMonths, repoStat.DatasetSize, repoStat.NumModels, repoStat.NumWikiViews),
  168. Liveness: normalization.GetLivenessInitValue(repoStat.NumCommits, repoStat.NumIssues, repoStat.NumPulls, repoStat.NumVisits),
  169. ProjectHealth: normalization.GetProjectHealthInitValue(repoStat.IssueFixedRate),
  170. TeamHealth: normalization.GetTeamHealthInitValue(repoStat.NumContributor, repoStat.NumKeyContributor, repoStat.NumContributorsGrowth),
  171. Growth: normalization.GetRepoGrowthInitValue(repoStat.NumCommitLinesGrowth, repoStat.NumIssuesGrowth, repoStat.NumCommitsGrowth, repoStat.NumContributorsGrowth, repoStat.NumCommentsGrowth),
  172. }
  173. reposRadar = append(reposRadar, &tempRepoStat)
  174. if !isInitMinMaxRadar {
  175. if !setting.RadarMap.IgnoreMirrorRepo || (setting.RadarMap.IgnoreMirrorRepo && !tempRepoStat.IsMirror) {
  176. minRepoRadar = tempRepoStat
  177. maxRepoRadar = tempRepoStat
  178. isInitMinMaxRadar = true
  179. }
  180. } else {
  181. if !setting.RadarMap.IgnoreMirrorRepo || (setting.RadarMap.IgnoreMirrorRepo && !tempRepoStat.IsMirror) {
  182. if tempRepoStat.Impact < minRepoRadar.Impact {
  183. minRepoRadar.Impact = tempRepoStat.Impact
  184. }
  185. if tempRepoStat.Impact > maxRepoRadar.Impact {
  186. maxRepoRadar.Impact = tempRepoStat.Impact
  187. }
  188. if tempRepoStat.Completeness < minRepoRadar.Completeness {
  189. minRepoRadar.Completeness = tempRepoStat.Completeness
  190. }
  191. if tempRepoStat.Completeness > maxRepoRadar.Completeness {
  192. maxRepoRadar.Completeness = tempRepoStat.Completeness
  193. }
  194. if tempRepoStat.Liveness < minRepoRadar.Liveness {
  195. minRepoRadar.Liveness = tempRepoStat.Liveness
  196. }
  197. if tempRepoStat.Liveness > maxRepoRadar.Liveness {
  198. maxRepoRadar.Liveness = tempRepoStat.Liveness
  199. }
  200. if tempRepoStat.ProjectHealth < minRepoRadar.ProjectHealth {
  201. minRepoRadar.ProjectHealth = tempRepoStat.ProjectHealth
  202. }
  203. if tempRepoStat.ProjectHealth > maxRepoRadar.ProjectHealth {
  204. maxRepoRadar.ProjectHealth = tempRepoStat.ProjectHealth
  205. }
  206. if tempRepoStat.TeamHealth < minRepoRadar.TeamHealth {
  207. minRepoRadar.TeamHealth = tempRepoStat.TeamHealth
  208. }
  209. if tempRepoStat.TeamHealth > maxRepoRadar.TeamHealth {
  210. maxRepoRadar.TeamHealth = tempRepoStat.TeamHealth
  211. }
  212. if tempRepoStat.Growth < minRepoRadar.Growth {
  213. minRepoRadar.Growth = tempRepoStat.Growth
  214. }
  215. if tempRepoStat.Growth > maxRepoRadar.Growth {
  216. maxRepoRadar.Growth = tempRepoStat.Growth
  217. }
  218. }
  219. }
  220. log.Info("finish statistic: %s", getDistinctProjectName(repo))
  221. }
  222. if len(error_projects) > 0 {
  223. mailer.SendWarnNotifyMail(setting.Warn_Notify_Mails, warnEmailMessage)
  224. }
  225. //radar map
  226. log.Info("begin statistic radar")
  227. for _, radarInit := range reposRadar {
  228. if radarInit.IsMirror && setting.RadarMap.IgnoreMirrorRepo {
  229. radarInit.Impact = 0
  230. radarInit.Completeness = 0
  231. radarInit.Liveness = 0
  232. radarInit.ProjectHealth = 0
  233. radarInit.TeamHealth = 0
  234. radarInit.Growth = 0
  235. radarInit.RadarTotal = 0
  236. } else {
  237. radarInit.Impact = normalization.Normalization(radarInit.Impact, minRepoRadar.Impact, maxRepoRadar.Impact)
  238. radarInit.Completeness = normalization.Normalization(radarInit.Completeness, minRepoRadar.Completeness, maxRepoRadar.Completeness)
  239. radarInit.Liveness = normalization.Normalization(radarInit.Liveness, minRepoRadar.Liveness, maxRepoRadar.Liveness)
  240. radarInit.ProjectHealth = normalization.Normalization(radarInit.ProjectHealth, minRepoRadar.ProjectHealth, maxRepoRadar.ProjectHealth)
  241. radarInit.TeamHealth = normalization.Normalization(radarInit.TeamHealth, minRepoRadar.TeamHealth, maxRepoRadar.TeamHealth)
  242. radarInit.Growth = normalization.Normalization(radarInit.Growth, minRepoRadar.Growth, maxRepoRadar.Growth)
  243. radarInit.RadarTotal = normalization.GetRadarValue(radarInit.Impact, radarInit.Completeness, radarInit.Liveness, radarInit.ProjectHealth, radarInit.TeamHealth, radarInit.Growth)
  244. }
  245. models.UpdateRepoStat(radarInit)
  246. }
  247. log.Info("finish statistic: radar")
  248. }
  249. func getDistinctProjectName(repo *models.Repository) string {
  250. return repo.OwnerName + "/" + repo.Alias
  251. }
  252. func getDatasetSize(repo *models.Repository) (int64, error) {
  253. dataset, err := models.GetDatasetByRepo(repo)
  254. if err != nil {
  255. return 0, err
  256. }
  257. return models.GetAttachmentSizeByDatasetID(dataset.ID)
  258. }
  259. func getStatTime(timeStr string) (string, string) {
  260. t, _ := time.Parse("2006-01-02", timeStr)
  261. timeNumber := t.Unix()
  262. beginTimeNumber := timeNumber - 8*60*60
  263. endTimeNumber := timeNumber + 16*60*60
  264. beginTime := time.Unix(beginTimeNumber, 0).Format(time.RFC3339)
  265. endTime := time.Unix(endTimeNumber, 0).Format(time.RFC3339)
  266. log.Info("%s, %s", beginTime, endTime)
  267. return beginTime, endTime
  268. }
  269. func UpdateRepoVisits(ctx *macaron.Context, repo *models.Repository, date string) error {
  270. beginTime, endTime := getStatTime(date)
  271. var numVisits int
  272. numVisits, err := repository.AppointProjectView(repo.OwnerName, repo.Name, beginTime, endTime)
  273. if err != nil {
  274. log.Error("AppointProjectView failed(%s): %v", getDistinctProjectName(repo), err)
  275. return err
  276. }
  277. repoStat, err := models.GetRepoStatisticByDate(date, repo.ID)
  278. if err != nil {
  279. log.Error("GetRepoStatisticByDate failed(%s): %v", getDistinctProjectName(repo), err)
  280. return err
  281. } else if len(repoStat) != 1 {
  282. log.Error("GetRepoStatisticByDate failed(%s): %v", getDistinctProjectName(repo), err)
  283. return errors.New("not find repo")
  284. }
  285. repoStat[0].NumVisits = int64(numVisits)
  286. if err = models.UpdateRepoStatVisits(repoStat[0]); err != nil {
  287. log.Error("UpdateRepoStatVisits failed(%s): %v", getDistinctProjectName(repo), err)
  288. return err
  289. }
  290. return nil
  291. }