@Summary Get insights about templates @ID get-insights-about-templates @Security CoderSessionToken @Produce json @Tags Insights @Param start_time query string true "Start time" format(date-time) @Param end_time query string true "End time" format(date-time) @Param interval query string true "Interva
(rw http.ResponseWriter, r *http.Request)
| 398 | // @Success 200 {object} codersdk.TemplateInsightsResponse |
| 399 | // @Router /api/v2/insights/templates [get] |
| 400 | func (api *API) insightsTemplates(rw http.ResponseWriter, r *http.Request) { |
| 401 | ctx := r.Context() |
| 402 | |
| 403 | p := httpapi.NewQueryParamParser(). |
| 404 | RequiredNotEmpty("start_time"). |
| 405 | RequiredNotEmpty("end_time") |
| 406 | vals := r.URL.Query() |
| 407 | var ( |
| 408 | // The QueryParamParser does not preserve timezone, so we need |
| 409 | // to parse the time ourselves. |
| 410 | startTimeString = p.String(vals, "", "start_time") |
| 411 | endTimeString = p.String(vals, "", "end_time") |
| 412 | intervalString = p.String(vals, "", "interval") |
| 413 | templateIDs = p.UUIDs(vals, []uuid.UUID{}, "template_ids") |
| 414 | sectionStrings = p.Strings(vals, templateInsightsSectionAsStrings(codersdk.TemplateInsightsSectionIntervalReports, codersdk.TemplateInsightsSectionReport), "sections") |
| 415 | ) |
| 416 | p.ErrorExcessParams(vals) |
| 417 | if len(p.Errors) > 0 { |
| 418 | httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 419 | Message: "Query parameters have invalid values.", |
| 420 | Validations: p.Errors, |
| 421 | }) |
| 422 | return |
| 423 | } |
| 424 | |
| 425 | startTime, endTime, ok := parseInsightsStartAndEndTime(ctx, rw, time.Now(), startTimeString, endTimeString) |
| 426 | if !ok { |
| 427 | return |
| 428 | } |
| 429 | interval, ok := parseInsightsInterval(ctx, rw, intervalString, startTime, endTime) |
| 430 | if !ok { |
| 431 | return |
| 432 | } |
| 433 | sections, ok := parseTemplateInsightsSections(ctx, rw, sectionStrings) |
| 434 | if !ok { |
| 435 | return |
| 436 | } |
| 437 | |
| 438 | var usage database.GetTemplateInsightsRow |
| 439 | var appUsage []database.GetTemplateAppInsightsRow |
| 440 | var dailyUsage []database.GetTemplateInsightsByIntervalRow |
| 441 | var parameterRows []database.GetTemplateParameterInsightsRow |
| 442 | |
| 443 | eg, egCtx := errgroup.WithContext(ctx) |
| 444 | eg.SetLimit(4) |
| 445 | |
| 446 | // The following insights data queries have a theoretical chance to be |
| 447 | // inconsistent between each other when looking at "today", however, the |
| 448 | // overhead from a transaction is not worth it. |
| 449 | eg.Go(func() error { |
| 450 | var err error |
| 451 | if interval != "" && slices.Contains(sections, codersdk.TemplateInsightsSectionIntervalReports) { |
| 452 | dailyUsage, err = api.Database.GetTemplateInsightsByInterval(egCtx, database.GetTemplateInsightsByIntervalParams{ |
| 453 | StartTime: startTime, |
| 454 | EndTime: endTime, |
| 455 | TemplateIDs: templateIDs, |
| 456 | IntervalDays: interval.Days(), |
| 457 | }) |
nothing calls this directly
no test coverage detected