@@ -113,6 +113,59 @@ public async Task<IActionResult> GetOverviewAsync([FromQuery] DateTime startTime
113
113
}
114
114
}
115
115
116
+ /// <summary>
117
+ /// Get execution daily stats for a given time period.
118
+ /// </summary>
119
+ /// <param name="filter">TimeFiler defining start and end times, plus paging options.</param>
120
+ /// <param name="workflowId">WorkflowId if you want stats just for a given workflow. (both workflowId and TaskId must be given, if you give one).</param>
121
+ /// <returns>a paged obect with all the stat details.</returns>
122
+ [ ProducesResponseType ( typeof ( StatsPagedResponse < List < ExecutionStatDTO > > ) , StatusCodes . Status200OK ) ]
123
+ [ ProducesResponseType ( typeof ( ProblemDetails ) , StatusCodes . Status500InternalServerError ) ]
124
+ [ HttpGet ( "dailystats" ) ]
125
+ public async Task < IActionResult > GetDailyStatsAsync ( [ FromQuery ] TimeFilter filter , string workflowId = "" )
126
+ {
127
+ SetUpFilter ( filter , out var route , out var pageSize , out var validFilter ) ;
128
+
129
+ try
130
+ {
131
+ var allStats = await _repository . GetAllStatsAsync ( filter . StartTime , filter . EndTime , workflowId , string . Empty ) ;
132
+ var statsDto = allStats
133
+ . OrderBy ( a => a . StartedUTC )
134
+ . GroupBy ( s => s . StartedUTC . Date )
135
+ . Select ( g => new ExecutionStatDayOverview
136
+ {
137
+ Date = DateOnly . FromDateTime ( g . Key . Date ) ,
138
+ TotalExecutions = g . Count ( ) ,
139
+ TotalFailures = g . Count ( i => string . Compare ( i . Status , "Failed" , true ) == 0 ) ,
140
+ TotalApprovals = g . Count ( i => string . Compare ( i . Status , ApplicationReviewStatus . Approved . ToString ( ) , true ) == 0 ) ,
141
+ TotalRejections = g . Count ( i => string . Compare ( i . Status , ApplicationReviewStatus . Rejected . ToString ( ) , true ) == 0 ) ,
142
+ TotalCancelled = g . Count ( i => string . Compare ( i . Status , ApplicationReviewStatus . Cancelled . ToString ( ) , true ) == 0 ) ,
143
+ TotalAwaitingReview = g . Count ( i => string . Compare ( i . Status , ApplicationReviewStatus . AwaitingReview . ToString ( ) , true ) == 0 ) ,
144
+ } ) ;
145
+
146
+ var pagedStats = statsDto . Skip ( ( filter . PageNumber - 1 ) * pageSize ) . Take ( pageSize ) ;
147
+
148
+ var res = CreateStatsPagedResponse ( pagedStats , validFilter , statsDto . Count ( ) , _uriService , route ) ;
149
+ var ( avgTotalExecution , avgArgoExecution ) = await _repository . GetAverageStats ( filter . StartTime , filter . EndTime , workflowId , string . Empty ) ;
150
+
151
+ res . PeriodStart = filter . StartTime ;
152
+ res . PeriodEnd = filter . EndTime ;
153
+ res . TotalExecutions = allStats . Count ( ) ;
154
+ res . TotalSucceeded = statsDto . Sum ( s => s . TotalApprovals ) ;
155
+ res . TotalFailures = statsDto . Sum ( s => s . TotalFailures ) ;
156
+ res . TotalInprogress = statsDto . Sum ( s => s . TotalAwaitingReview ) ;
157
+ res . AverageTotalExecutionSeconds = Math . Round ( avgTotalExecution , 2 ) ;
158
+ res . AverageArgoExecutionSeconds = Math . Round ( avgArgoExecution , 2 ) ;
159
+
160
+ return Ok ( res ) ;
161
+ }
162
+ catch ( Exception e )
163
+ {
164
+ _logger . GetStatsAsyncError ( e ) ;
165
+ return Problem ( $ "Unexpected error occurred: { e . Message } ", $ "tasks/stats", InternalServerError ) ;
166
+ }
167
+ }
168
+
116
169
/// <summary>
117
170
/// Get execution stats for a given time period.
118
171
/// </summary>
@@ -133,63 +186,71 @@ public async Task<IActionResult> GetStatsAsync([FromQuery] TimeFilter filter, st
133
186
return Problem ( "Failed to validate ids, not a valid guid" , "tasks/stats/" , BadRequest ) ;
134
187
}
135
188
136
- if ( filter . EndTime == default )
137
- {
138
- filter . EndTime = DateTime . Now ;
139
- }
189
+ SetUpFilter ( filter , out var route , out var pageSize , out var validFilter ) ;
140
190
141
- if ( filter . StartTime == default )
191
+ try
142
192
{
143
- filter . StartTime = new DateTime ( 2023 , 1 , 1 ) ;
144
- }
145
-
146
- var route = Request ? . Path . Value ?? string . Empty ;
147
- var pageSize = filter . PageSize ?? Options . Value . EndpointSettings ? . DefaultPageSize ?? 10 ;
148
- var max = Options . Value . EndpointSettings ? . MaxPageSize ?? 20 ;
149
- var validFilter = new PaginationFilter ( filter . PageNumber , pageSize , max ) ;
193
+ var allStats = await _repository . GetStatsAsync ( filter . StartTime , filter . EndTime , pageSize , filter . PageNumber , workflowId , taskId ) ;
194
+ var statsDto = allStats
195
+ . OrderBy ( a => a . StartedUTC )
196
+ . Select ( s => new ExecutionStatDTO ( s ) ) ;
150
197
151
- try
198
+ var res = await GatherPagedStats ( filter , workflowId , taskId , route , validFilter , statsDto ) ;
199
+ return Ok ( res ) ;
200
+ }
201
+ catch ( Exception e )
152
202
{
153
- workflowId ??= string . Empty ;
154
- taskId ??= string . Empty ;
155
- var allStats = _repository . GetStatsAsync ( filter . StartTime , filter . EndTime , pageSize , filter . PageNumber , workflowId , taskId ) ;
203
+ _logger . GetStatsAsyncError ( e ) ;
204
+ return Problem ( $ "Unexpected error occurred: { e . Message } ", $ "tasks/stats", InternalServerError ) ;
205
+ }
206
+ }
156
207
157
- var successes = _repository . GetStatsStatusSucceededCountAsync ( filter . StartTime , filter . EndTime , workflowId , taskId ) ;
208
+ private async Task < StatsPagedResponse < IEnumerable < T > > > GatherPagedStats < T > ( TimeFilter filter , string workflowId , string taskId , string route , PaginationFilter validFilter , IEnumerable < T > statsDto )
209
+ {
210
+ workflowId ??= string . Empty ;
211
+ taskId ??= string . Empty ;
158
212
159
- var fails = _repository . GetStatsStatusFailedCountAsync ( filter . StartTime , filter . EndTime , workflowId , taskId ) ;
213
+ var successes = _repository . GetStatsStatusSucceededCountAsync ( filter . StartTime , filter . EndTime , workflowId , taskId ) ;
160
214
161
- var rangeCount = _repository . GetStatsTotalCompleteExecutionsCountAsync ( filter . StartTime , filter . EndTime , workflowId , taskId ) ;
215
+ var fails = _repository . GetStatsStatusFailedCountAsync ( filter . StartTime , filter . EndTime , workflowId , taskId ) ;
162
216
163
- var stats = _repository . GetAverageStats ( filter . StartTime , filter . EndTime , workflowId , taskId ) ;
217
+ var rangeCount = _repository . GetStatsTotalCompleteExecutionsCountAsync ( filter . StartTime , filter . EndTime , workflowId , taskId ) ;
164
218
165
- var running = _repository . GetStatsStatusCountAsync ( filter . StartTime , filter . EndTime , TaskExecutionStatus . Accepted . ToString ( ) , workflowId , taskId ) ;
219
+ var stats = _repository . GetAverageStats ( filter . StartTime , filter . EndTime , workflowId , taskId ) ;
166
220
167
- await Task . WhenAll ( allStats , fails , rangeCount , stats , running ) ;
221
+ var running = _repository . GetStatsStatusCountAsync ( filter . StartTime , filter . EndTime , TaskExecutionStatus . Accepted . ToString ( ) , workflowId , taskId ) ;
168
222
169
- ExecutionStatDTO [ ] statsDto ;
223
+ await Task . WhenAll ( fails , rangeCount , stats , running ) ;
170
224
171
- statsDto = allStats . Result
172
- . OrderBy ( a => a . StartedUTC )
173
- . Select ( s => new ExecutionStatDTO ( s ) )
174
- . ToArray ( ) ;
225
+ var res = CreateStatsPagedResponse ( statsDto , validFilter , rangeCount . Result , _uriService , route ) ;
175
226
176
- var res = CreateStatsPagedResponse ( statsDto , validFilter , rangeCount . Result , _uriService , route ) ;
227
+ res . PeriodStart = filter . StartTime ;
228
+ res . PeriodEnd = filter . EndTime ;
229
+ res . TotalExecutions = rangeCount . Result ;
230
+ res . TotalSucceeded = successes . Result ;
231
+ res . TotalFailures = fails . Result ;
232
+ res . TotalInprogress = running . Result ;
233
+ res . AverageTotalExecutionSeconds = Math . Round ( stats . Result . avgTotalExecution , 2 ) ;
234
+ res . AverageArgoExecutionSeconds = Math . Round ( stats . Result . avgArgoExecution , 2 ) ;
235
+ return res ;
236
+ }
177
237
178
- res . PeriodStart = filter . StartTime ;
179
- res . PeriodEnd = filter . EndTime ;
180
- res . TotalExecutions = rangeCount . Result ;
181
- res . TotalSucceeded = successes . Result ;
182
- res . TotalFailures = fails . Result ;
183
- res . TotalInprogress = running . Result ;
184
- res . AverageTotalExecutionSeconds = Math . Round ( stats . Result . avgTotalExecution , 2 ) ;
185
- res . AverageArgoExecutionSeconds = Math . Round ( stats . Result . avgArgoExecution , 2 ) ;
186
- return Ok ( res ) ;
238
+ private void SetUpFilter ( TimeFilter filter , out string route , out int pageSize , out PaginationFilter validFilter )
239
+ {
240
+ if ( filter . EndTime == default )
241
+ {
242
+ filter . EndTime = DateTime . Now ;
187
243
}
188
- catch ( Exception e )
244
+
245
+ if ( filter . StartTime == default )
189
246
{
190
- _logger . GetStatsAsyncError ( e ) ;
191
- return Problem ( $ "Unexpected error occurred: { e . Message } ", $ "tasks/stats", InternalServerError ) ;
247
+ filter . StartTime = new DateTime ( 2023 , 1 , 1 ) ;
192
248
}
249
+
250
+ route = Request ? . Path . Value ?? string . Empty ;
251
+ pageSize = filter . PageSize ?? Options . Value . EndpointSettings ? . DefaultPageSize ?? 10 ;
252
+ var max = Options . Value . EndpointSettings ? . MaxPageSize ?? 20 ;
253
+ validFilter = new PaginationFilter ( filter . PageNumber , pageSize , max ) ;
193
254
}
194
255
}
195
256
}
0 commit comments