mirror of
https://github.com/coder/coder.git
synced 2025-07-03 16:13:58 +00:00
feat!: add sections
parameter to template insights (#10010)
This commit is contained in:
@ -257,6 +257,7 @@ func (api *API) insightsTemplates(rw http.ResponseWriter, r *http.Request) {
|
||||
endTimeString = p.String(vals, "", "end_time")
|
||||
intervalString = p.String(vals, "", "interval")
|
||||
templateIDs = p.UUIDs(vals, []uuid.UUID{}, "template_ids")
|
||||
sectionStrings = p.Strings(vals, templateInsightsSectionAsStrings(codersdk.TemplateInsightsSectionIntervalReports, codersdk.TemplateInsightsSectionReport), "sections")
|
||||
)
|
||||
p.ErrorExcessParams(vals)
|
||||
if len(p.Errors) > 0 {
|
||||
@ -275,6 +276,10 @@ func (api *API) insightsTemplates(rw http.ResponseWriter, r *http.Request) {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
sections, ok := parseTemplateInsightsSections(ctx, rw, sectionStrings)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var usage database.GetTemplateInsightsRow
|
||||
var appUsage []database.GetTemplateAppInsightsRow
|
||||
@ -289,7 +294,7 @@ func (api *API) insightsTemplates(rw http.ResponseWriter, r *http.Request) {
|
||||
// overhead from a transaction is not worth it.
|
||||
eg.Go(func() error {
|
||||
var err error
|
||||
if interval != "" {
|
||||
if interval != "" && slices.Contains(sections, codersdk.TemplateInsightsSectionIntervalReports) {
|
||||
dailyUsage, err = api.Database.GetTemplateInsightsByInterval(egCtx, database.GetTemplateInsightsByIntervalParams{
|
||||
StartTime: startTime,
|
||||
EndTime: endTime,
|
||||
@ -303,6 +308,10 @@ func (api *API) insightsTemplates(rw http.ResponseWriter, r *http.Request) {
|
||||
return nil
|
||||
})
|
||||
eg.Go(func() error {
|
||||
if !slices.Contains(sections, codersdk.TemplateInsightsSectionReport) {
|
||||
return nil
|
||||
}
|
||||
|
||||
var err error
|
||||
usage, err = api.Database.GetTemplateInsights(egCtx, database.GetTemplateInsightsParams{
|
||||
StartTime: startTime,
|
||||
@ -315,6 +324,10 @@ func (api *API) insightsTemplates(rw http.ResponseWriter, r *http.Request) {
|
||||
return nil
|
||||
})
|
||||
eg.Go(func() error {
|
||||
if !slices.Contains(sections, codersdk.TemplateInsightsSectionReport) {
|
||||
return nil
|
||||
}
|
||||
|
||||
var err error
|
||||
appUsage, err = api.Database.GetTemplateAppInsights(egCtx, database.GetTemplateAppInsightsParams{
|
||||
StartTime: startTime,
|
||||
@ -330,6 +343,10 @@ func (api *API) insightsTemplates(rw http.ResponseWriter, r *http.Request) {
|
||||
// Template parameter insights have no risk of inconsistency with the other
|
||||
// insights.
|
||||
eg.Go(func() error {
|
||||
if !slices.Contains(sections, codersdk.TemplateInsightsSectionReport) {
|
||||
return nil
|
||||
}
|
||||
|
||||
var err error
|
||||
parameterRows, err = api.Database.GetTemplateParameterInsights(ctx, database.GetTemplateParameterInsightsParams{
|
||||
StartTime: startTime,
|
||||
@ -365,16 +382,20 @@ func (api *API) insightsTemplates(rw http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
resp := codersdk.TemplateInsightsResponse{
|
||||
Report: codersdk.TemplateInsightsReport{
|
||||
IntervalReports: []codersdk.TemplateInsightsIntervalReport{},
|
||||
}
|
||||
|
||||
if slices.Contains(sections, codersdk.TemplateInsightsSectionReport) {
|
||||
resp.Report = &codersdk.TemplateInsightsReport{
|
||||
StartTime: startTime,
|
||||
EndTime: endTime,
|
||||
TemplateIDs: convertTemplateInsightsTemplateIDs(usage, appUsage),
|
||||
ActiveUsers: convertTemplateInsightsActiveUsers(usage, appUsage),
|
||||
AppsUsage: convertTemplateInsightsApps(usage, appUsage),
|
||||
ParametersUsage: parametersUsage,
|
||||
},
|
||||
IntervalReports: []codersdk.TemplateInsightsIntervalReport{},
|
||||
}
|
||||
}
|
||||
|
||||
for _, row := range dailyUsage {
|
||||
resp.IntervalReports = append(resp.IntervalReports, codersdk.TemplateInsightsIntervalReport{
|
||||
// NOTE(mafredri): This might not be accurate over DST since the
|
||||
@ -654,3 +675,33 @@ func lastReportIntervalHasAtLeastSixDays(startTime, endTime time.Time) bool {
|
||||
// when the duration can be shorter than 6 days: 5 days 23 hours.
|
||||
return lastReportIntervalDays >= 6*24*time.Hour || startTime.AddDate(0, 0, 6).Equal(endTime)
|
||||
}
|
||||
|
||||
func templateInsightsSectionAsStrings(sections ...codersdk.TemplateInsightsSection) []string {
|
||||
t := make([]string, len(sections))
|
||||
for i, s := range sections {
|
||||
t[i] = string(s)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func parseTemplateInsightsSections(ctx context.Context, rw http.ResponseWriter, sections []string) ([]codersdk.TemplateInsightsSection, bool) {
|
||||
t := make([]codersdk.TemplateInsightsSection, len(sections))
|
||||
for i, s := range sections {
|
||||
switch v := codersdk.TemplateInsightsSection(s); v {
|
||||
case codersdk.TemplateInsightsSectionIntervalReports, codersdk.TemplateInsightsSectionReport:
|
||||
t[i] = v
|
||||
default:
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: "Query parameter has invalid value.",
|
||||
Validations: []codersdk.ValidationError{
|
||||
{
|
||||
Field: "sections",
|
||||
Detail: fmt.Sprintf("must be one of %v", []codersdk.TemplateInsightsSection{codersdk.TemplateInsightsSectionIntervalReports, codersdk.TemplateInsightsSectionReport}),
|
||||
},
|
||||
},
|
||||
})
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
return t, true
|
||||
}
|
||||
|
Reference in New Issue
Block a user