From 1e3bba2ff9ea81b243d0372caa268ec904f1ebf9 Mon Sep 17 00:00:00 2001 From: Noah Hanjun Lee Date: Sat, 16 Oct 2021 18:09:54 +0900 Subject: [PATCH] Add lead time metrics (#170) --- ent/deploymentstatistics.go | 12 +- .../deploymentstatistics.go | 5 + ent/deploymentstatistics/where.go | 83 +++++++++++ ent/deploymentstatistics_create.go | 29 ++++ ent/deploymentstatistics_update.go | 70 +++++++++ ent/migrate/schema.go | 7 +- ent/mutation.go | 133 +++++++++++++++--- ent/runtime.go | 8 +- ent/schema/deploymentstatistics.go | 2 + internal/interactor/deploymentstatistics.go | 10 +- internal/pkg/store/deploymentstatistics.go | 2 + internal/server/metrics/metrics.go | 16 +++ 12 files changed, 345 insertions(+), 32 deletions(-) diff --git a/ent/deploymentstatistics.go b/ent/deploymentstatistics.go index 441631ba..cf111a8e 100644 --- a/ent/deploymentstatistics.go +++ b/ent/deploymentstatistics.go @@ -29,6 +29,8 @@ type DeploymentStatistics struct { Deletions int `json:"deletions"` // Changes holds the value of the "changes" field. Changes int `json:"changes"` + // LeadTimeSeconds holds the value of the "lead_time_seconds" field. + LeadTimeSeconds int `json:"lead_time_seconds"` // CreatedAt holds the value of the "created_at" field. CreatedAt time.Time `json:"created_at"` // UpdatedAt holds the value of the "updated_at" field. @@ -68,7 +70,7 @@ func (*DeploymentStatistics) scanValues(columns []string) ([]interface{}, error) values := make([]interface{}, len(columns)) for i := range columns { switch columns[i] { - case deploymentstatistics.FieldID, deploymentstatistics.FieldCount, deploymentstatistics.FieldRollbackCount, deploymentstatistics.FieldAdditions, deploymentstatistics.FieldDeletions, deploymentstatistics.FieldChanges, deploymentstatistics.FieldRepoID: + case deploymentstatistics.FieldID, deploymentstatistics.FieldCount, deploymentstatistics.FieldRollbackCount, deploymentstatistics.FieldAdditions, deploymentstatistics.FieldDeletions, deploymentstatistics.FieldChanges, deploymentstatistics.FieldLeadTimeSeconds, deploymentstatistics.FieldRepoID: values[i] = new(sql.NullInt64) case deploymentstatistics.FieldEnv: values[i] = new(sql.NullString) @@ -131,6 +133,12 @@ func (ds *DeploymentStatistics) assignValues(columns []string, values []interfac } else if value.Valid { ds.Changes = int(value.Int64) } + case deploymentstatistics.FieldLeadTimeSeconds: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field lead_time_seconds", values[i]) + } else if value.Valid { + ds.LeadTimeSeconds = int(value.Int64) + } case deploymentstatistics.FieldCreatedAt: if value, ok := values[i].(*sql.NullTime); !ok { return fmt.Errorf("unexpected type %T for field created_at", values[i]) @@ -194,6 +202,8 @@ func (ds *DeploymentStatistics) String() string { builder.WriteString(fmt.Sprintf("%v", ds.Deletions)) builder.WriteString(", changes=") builder.WriteString(fmt.Sprintf("%v", ds.Changes)) + builder.WriteString(", lead_time_seconds=") + builder.WriteString(fmt.Sprintf("%v", ds.LeadTimeSeconds)) builder.WriteString(", created_at=") builder.WriteString(ds.CreatedAt.Format(time.ANSIC)) builder.WriteString(", updated_at=") diff --git a/ent/deploymentstatistics/deploymentstatistics.go b/ent/deploymentstatistics/deploymentstatistics.go index 74992a8d..962afefc 100644 --- a/ent/deploymentstatistics/deploymentstatistics.go +++ b/ent/deploymentstatistics/deploymentstatistics.go @@ -23,6 +23,8 @@ const ( FieldDeletions = "deletions" // FieldChanges holds the string denoting the changes field in the database. FieldChanges = "changes" + // FieldLeadTimeSeconds holds the string denoting the lead_time_seconds field in the database. + FieldLeadTimeSeconds = "lead_time_seconds" // FieldCreatedAt holds the string denoting the created_at field in the database. FieldCreatedAt = "created_at" // FieldUpdatedAt holds the string denoting the updated_at field in the database. @@ -51,6 +53,7 @@ var Columns = []string{ FieldAdditions, FieldDeletions, FieldChanges, + FieldLeadTimeSeconds, FieldCreatedAt, FieldUpdatedAt, FieldRepoID, @@ -77,6 +80,8 @@ var ( DefaultDeletions int // DefaultChanges holds the default value on creation for the "changes" field. DefaultChanges int + // DefaultLeadTimeSeconds holds the default value on creation for the "lead_time_seconds" field. + DefaultLeadTimeSeconds int // DefaultCreatedAt holds the default value on creation for the "created_at" field. DefaultCreatedAt func() time.Time // DefaultUpdatedAt holds the default value on creation for the "updated_at" field. diff --git a/ent/deploymentstatistics/where.go b/ent/deploymentstatistics/where.go index 901a5eb1..f5a6545a 100644 --- a/ent/deploymentstatistics/where.go +++ b/ent/deploymentstatistics/where.go @@ -135,6 +135,13 @@ func Changes(v int) predicate.DeploymentStatistics { }) } +// LeadTimeSeconds applies equality check predicate on the "lead_time_seconds" field. It's identical to LeadTimeSecondsEQ. +func LeadTimeSeconds(v int) predicate.DeploymentStatistics { + return predicate.DeploymentStatistics(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldLeadTimeSeconds), v)) + }) +} + // CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ. func CreatedAt(v time.Time) predicate.DeploymentStatistics { return predicate.DeploymentStatistics(func(s *sql.Selector) { @@ -647,6 +654,82 @@ func ChangesLTE(v int) predicate.DeploymentStatistics { }) } +// LeadTimeSecondsEQ applies the EQ predicate on the "lead_time_seconds" field. +func LeadTimeSecondsEQ(v int) predicate.DeploymentStatistics { + return predicate.DeploymentStatistics(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldLeadTimeSeconds), v)) + }) +} + +// LeadTimeSecondsNEQ applies the NEQ predicate on the "lead_time_seconds" field. +func LeadTimeSecondsNEQ(v int) predicate.DeploymentStatistics { + return predicate.DeploymentStatistics(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldLeadTimeSeconds), v)) + }) +} + +// LeadTimeSecondsIn applies the In predicate on the "lead_time_seconds" field. +func LeadTimeSecondsIn(vs ...int) predicate.DeploymentStatistics { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.DeploymentStatistics(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldLeadTimeSeconds), v...)) + }) +} + +// LeadTimeSecondsNotIn applies the NotIn predicate on the "lead_time_seconds" field. +func LeadTimeSecondsNotIn(vs ...int) predicate.DeploymentStatistics { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.DeploymentStatistics(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldLeadTimeSeconds), v...)) + }) +} + +// LeadTimeSecondsGT applies the GT predicate on the "lead_time_seconds" field. +func LeadTimeSecondsGT(v int) predicate.DeploymentStatistics { + return predicate.DeploymentStatistics(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldLeadTimeSeconds), v)) + }) +} + +// LeadTimeSecondsGTE applies the GTE predicate on the "lead_time_seconds" field. +func LeadTimeSecondsGTE(v int) predicate.DeploymentStatistics { + return predicate.DeploymentStatistics(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldLeadTimeSeconds), v)) + }) +} + +// LeadTimeSecondsLT applies the LT predicate on the "lead_time_seconds" field. +func LeadTimeSecondsLT(v int) predicate.DeploymentStatistics { + return predicate.DeploymentStatistics(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldLeadTimeSeconds), v)) + }) +} + +// LeadTimeSecondsLTE applies the LTE predicate on the "lead_time_seconds" field. +func LeadTimeSecondsLTE(v int) predicate.DeploymentStatistics { + return predicate.DeploymentStatistics(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldLeadTimeSeconds), v)) + }) +} + // CreatedAtEQ applies the EQ predicate on the "created_at" field. func CreatedAtEQ(v time.Time) predicate.DeploymentStatistics { return predicate.DeploymentStatistics(func(s *sql.Selector) { diff --git a/ent/deploymentstatistics_create.go b/ent/deploymentstatistics_create.go index 1a24b272..23379151 100644 --- a/ent/deploymentstatistics_create.go +++ b/ent/deploymentstatistics_create.go @@ -97,6 +97,20 @@ func (dsc *DeploymentStatisticsCreate) SetNillableChanges(i *int) *DeploymentSta return dsc } +// SetLeadTimeSeconds sets the "lead_time_seconds" field. +func (dsc *DeploymentStatisticsCreate) SetLeadTimeSeconds(i int) *DeploymentStatisticsCreate { + dsc.mutation.SetLeadTimeSeconds(i) + return dsc +} + +// SetNillableLeadTimeSeconds sets the "lead_time_seconds" field if the given value is not nil. +func (dsc *DeploymentStatisticsCreate) SetNillableLeadTimeSeconds(i *int) *DeploymentStatisticsCreate { + if i != nil { + dsc.SetLeadTimeSeconds(*i) + } + return dsc +} + // SetCreatedAt sets the "created_at" field. func (dsc *DeploymentStatisticsCreate) SetCreatedAt(t time.Time) *DeploymentStatisticsCreate { dsc.mutation.SetCreatedAt(t) @@ -227,6 +241,10 @@ func (dsc *DeploymentStatisticsCreate) defaults() { v := deploymentstatistics.DefaultChanges dsc.mutation.SetChanges(v) } + if _, ok := dsc.mutation.LeadTimeSeconds(); !ok { + v := deploymentstatistics.DefaultLeadTimeSeconds + dsc.mutation.SetLeadTimeSeconds(v) + } if _, ok := dsc.mutation.CreatedAt(); !ok { v := deploymentstatistics.DefaultCreatedAt() dsc.mutation.SetCreatedAt(v) @@ -257,6 +275,9 @@ func (dsc *DeploymentStatisticsCreate) check() error { if _, ok := dsc.mutation.Changes(); !ok { return &ValidationError{Name: "changes", err: errors.New(`ent: missing required field "changes"`)} } + if _, ok := dsc.mutation.LeadTimeSeconds(); !ok { + return &ValidationError{Name: "lead_time_seconds", err: errors.New(`ent: missing required field "lead_time_seconds"`)} + } if _, ok := dsc.mutation.CreatedAt(); !ok { return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "created_at"`)} } @@ -344,6 +365,14 @@ func (dsc *DeploymentStatisticsCreate) createSpec() (*DeploymentStatistics, *sql }) _node.Changes = value } + if value, ok := dsc.mutation.LeadTimeSeconds(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: deploymentstatistics.FieldLeadTimeSeconds, + }) + _node.LeadTimeSeconds = value + } if value, ok := dsc.mutation.CreatedAt(); ok { _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ Type: field.TypeTime, diff --git a/ent/deploymentstatistics_update.go b/ent/deploymentstatistics_update.go index db5aa014..d3f5b3fc 100644 --- a/ent/deploymentstatistics_update.go +++ b/ent/deploymentstatistics_update.go @@ -140,6 +140,27 @@ func (dsu *DeploymentStatisticsUpdate) AddChanges(i int) *DeploymentStatisticsUp return dsu } +// SetLeadTimeSeconds sets the "lead_time_seconds" field. +func (dsu *DeploymentStatisticsUpdate) SetLeadTimeSeconds(i int) *DeploymentStatisticsUpdate { + dsu.mutation.ResetLeadTimeSeconds() + dsu.mutation.SetLeadTimeSeconds(i) + return dsu +} + +// SetNillableLeadTimeSeconds sets the "lead_time_seconds" field if the given value is not nil. +func (dsu *DeploymentStatisticsUpdate) SetNillableLeadTimeSeconds(i *int) *DeploymentStatisticsUpdate { + if i != nil { + dsu.SetLeadTimeSeconds(*i) + } + return dsu +} + +// AddLeadTimeSeconds adds i to the "lead_time_seconds" field. +func (dsu *DeploymentStatisticsUpdate) AddLeadTimeSeconds(i int) *DeploymentStatisticsUpdate { + dsu.mutation.AddLeadTimeSeconds(i) + return dsu +} + // SetCreatedAt sets the "created_at" field. func (dsu *DeploymentStatisticsUpdate) SetCreatedAt(t time.Time) *DeploymentStatisticsUpdate { dsu.mutation.SetCreatedAt(t) @@ -354,6 +375,20 @@ func (dsu *DeploymentStatisticsUpdate) sqlSave(ctx context.Context) (n int, err Column: deploymentstatistics.FieldChanges, }) } + if value, ok := dsu.mutation.LeadTimeSeconds(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: deploymentstatistics.FieldLeadTimeSeconds, + }) + } + if value, ok := dsu.mutation.AddedLeadTimeSeconds(); ok { + _spec.Fields.Add = append(_spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: deploymentstatistics.FieldLeadTimeSeconds, + }) + } if value, ok := dsu.mutation.CreatedAt(); ok { _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ Type: field.TypeTime, @@ -533,6 +568,27 @@ func (dsuo *DeploymentStatisticsUpdateOne) AddChanges(i int) *DeploymentStatisti return dsuo } +// SetLeadTimeSeconds sets the "lead_time_seconds" field. +func (dsuo *DeploymentStatisticsUpdateOne) SetLeadTimeSeconds(i int) *DeploymentStatisticsUpdateOne { + dsuo.mutation.ResetLeadTimeSeconds() + dsuo.mutation.SetLeadTimeSeconds(i) + return dsuo +} + +// SetNillableLeadTimeSeconds sets the "lead_time_seconds" field if the given value is not nil. +func (dsuo *DeploymentStatisticsUpdateOne) SetNillableLeadTimeSeconds(i *int) *DeploymentStatisticsUpdateOne { + if i != nil { + dsuo.SetLeadTimeSeconds(*i) + } + return dsuo +} + +// AddLeadTimeSeconds adds i to the "lead_time_seconds" field. +func (dsuo *DeploymentStatisticsUpdateOne) AddLeadTimeSeconds(i int) *DeploymentStatisticsUpdateOne { + dsuo.mutation.AddLeadTimeSeconds(i) + return dsuo +} + // SetCreatedAt sets the "created_at" field. func (dsuo *DeploymentStatisticsUpdateOne) SetCreatedAt(t time.Time) *DeploymentStatisticsUpdateOne { dsuo.mutation.SetCreatedAt(t) @@ -771,6 +827,20 @@ func (dsuo *DeploymentStatisticsUpdateOne) sqlSave(ctx context.Context) (_node * Column: deploymentstatistics.FieldChanges, }) } + if value, ok := dsuo.mutation.LeadTimeSeconds(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: deploymentstatistics.FieldLeadTimeSeconds, + }) + } + if value, ok := dsuo.mutation.AddedLeadTimeSeconds(); ok { + _spec.Fields.Add = append(_spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: deploymentstatistics.FieldLeadTimeSeconds, + }) + } if value, ok := dsuo.mutation.CreatedAt(); ok { _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ Type: field.TypeTime, diff --git a/ent/migrate/schema.go b/ent/migrate/schema.go index 27bc2da5..6d1a10af 100644 --- a/ent/migrate/schema.go +++ b/ent/migrate/schema.go @@ -166,6 +166,7 @@ var ( {Name: "additions", Type: field.TypeInt, Default: 0}, {Name: "deletions", Type: field.TypeInt, Default: 0}, {Name: "changes", Type: field.TypeInt, Default: 0}, + {Name: "lead_time_seconds", Type: field.TypeInt, Default: 0}, {Name: "created_at", Type: field.TypeTime}, {Name: "updated_at", Type: field.TypeTime}, {Name: "repo_id", Type: field.TypeInt64, Nullable: true}, @@ -178,7 +179,7 @@ var ( ForeignKeys: []*schema.ForeignKey{ { Symbol: "deployment_statistics_repos_deployment_statistics", - Columns: []*schema.Column{DeploymentStatisticsColumns[9]}, + Columns: []*schema.Column{DeploymentStatisticsColumns[10]}, RefColumns: []*schema.Column{ReposColumns[0]}, OnDelete: schema.Cascade, }, @@ -187,12 +188,12 @@ var ( { Name: "deploymentstatistics_repo_id_env", Unique: true, - Columns: []*schema.Column{DeploymentStatisticsColumns[9], DeploymentStatisticsColumns[1]}, + Columns: []*schema.Column{DeploymentStatisticsColumns[10], DeploymentStatisticsColumns[1]}, }, { Name: "deploymentstatistics_updated_at", Unique: false, - Columns: []*schema.Column{DeploymentStatisticsColumns[8]}, + Columns: []*schema.Column{DeploymentStatisticsColumns[9]}, }, }, } diff --git a/ent/mutation.go b/ent/mutation.go index 88379fc2..75fcdffe 100644 --- a/ent/mutation.go +++ b/ent/mutation.go @@ -3605,28 +3605,30 @@ func (m *DeploymentMutation) ResetEdge(name string) error { // DeploymentStatisticsMutation represents an operation that mutates the DeploymentStatistics nodes in the graph. type DeploymentStatisticsMutation struct { config - op Op - typ string - id *int - env *string - count *int - addcount *int - rollback_count *int - addrollback_count *int - additions *int - addadditions *int - deletions *int - adddeletions *int - changes *int - addchanges *int - created_at *time.Time - updated_at *time.Time - clearedFields map[string]struct{} - repo *int64 - clearedrepo bool - done bool - oldValue func(context.Context) (*DeploymentStatistics, error) - predicates []predicate.DeploymentStatistics + op Op + typ string + id *int + env *string + count *int + addcount *int + rollback_count *int + addrollback_count *int + additions *int + addadditions *int + deletions *int + adddeletions *int + changes *int + addchanges *int + lead_time_seconds *int + addlead_time_seconds *int + created_at *time.Time + updated_at *time.Time + clearedFields map[string]struct{} + repo *int64 + clearedrepo bool + done bool + oldValue func(context.Context) (*DeploymentStatistics, error) + predicates []predicate.DeploymentStatistics } var _ ent.Mutation = (*DeploymentStatisticsMutation)(nil) @@ -4024,6 +4026,62 @@ func (m *DeploymentStatisticsMutation) ResetChanges() { m.addchanges = nil } +// SetLeadTimeSeconds sets the "lead_time_seconds" field. +func (m *DeploymentStatisticsMutation) SetLeadTimeSeconds(i int) { + m.lead_time_seconds = &i + m.addlead_time_seconds = nil +} + +// LeadTimeSeconds returns the value of the "lead_time_seconds" field in the mutation. +func (m *DeploymentStatisticsMutation) LeadTimeSeconds() (r int, exists bool) { + v := m.lead_time_seconds + if v == nil { + return + } + return *v, true +} + +// OldLeadTimeSeconds returns the old "lead_time_seconds" field's value of the DeploymentStatistics entity. +// If the DeploymentStatistics object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *DeploymentStatisticsMutation) OldLeadTimeSeconds(ctx context.Context) (v int, err error) { + if !m.op.Is(OpUpdateOne) { + return v, fmt.Errorf("OldLeadTimeSeconds is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, fmt.Errorf("OldLeadTimeSeconds requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldLeadTimeSeconds: %w", err) + } + return oldValue.LeadTimeSeconds, nil +} + +// AddLeadTimeSeconds adds i to the "lead_time_seconds" field. +func (m *DeploymentStatisticsMutation) AddLeadTimeSeconds(i int) { + if m.addlead_time_seconds != nil { + *m.addlead_time_seconds += i + } else { + m.addlead_time_seconds = &i + } +} + +// AddedLeadTimeSeconds returns the value that was added to the "lead_time_seconds" field in this mutation. +func (m *DeploymentStatisticsMutation) AddedLeadTimeSeconds() (r int, exists bool) { + v := m.addlead_time_seconds + if v == nil { + return + } + return *v, true +} + +// ResetLeadTimeSeconds resets all changes to the "lead_time_seconds" field. +func (m *DeploymentStatisticsMutation) ResetLeadTimeSeconds() { + m.lead_time_seconds = nil + m.addlead_time_seconds = nil +} + // SetCreatedAt sets the "created_at" field. func (m *DeploymentStatisticsMutation) SetCreatedAt(t time.Time) { m.created_at = &t @@ -4177,7 +4235,7 @@ func (m *DeploymentStatisticsMutation) Type() string { // order to get all numeric fields that were incremented/decremented, call // AddedFields(). func (m *DeploymentStatisticsMutation) Fields() []string { - fields := make([]string, 0, 9) + fields := make([]string, 0, 10) if m.env != nil { fields = append(fields, deploymentstatistics.FieldEnv) } @@ -4196,6 +4254,9 @@ func (m *DeploymentStatisticsMutation) Fields() []string { if m.changes != nil { fields = append(fields, deploymentstatistics.FieldChanges) } + if m.lead_time_seconds != nil { + fields = append(fields, deploymentstatistics.FieldLeadTimeSeconds) + } if m.created_at != nil { fields = append(fields, deploymentstatistics.FieldCreatedAt) } @@ -4225,6 +4286,8 @@ func (m *DeploymentStatisticsMutation) Field(name string) (ent.Value, bool) { return m.Deletions() case deploymentstatistics.FieldChanges: return m.Changes() + case deploymentstatistics.FieldLeadTimeSeconds: + return m.LeadTimeSeconds() case deploymentstatistics.FieldCreatedAt: return m.CreatedAt() case deploymentstatistics.FieldUpdatedAt: @@ -4252,6 +4315,8 @@ func (m *DeploymentStatisticsMutation) OldField(ctx context.Context, name string return m.OldDeletions(ctx) case deploymentstatistics.FieldChanges: return m.OldChanges(ctx) + case deploymentstatistics.FieldLeadTimeSeconds: + return m.OldLeadTimeSeconds(ctx) case deploymentstatistics.FieldCreatedAt: return m.OldCreatedAt(ctx) case deploymentstatistics.FieldUpdatedAt: @@ -4309,6 +4374,13 @@ func (m *DeploymentStatisticsMutation) SetField(name string, value ent.Value) er } m.SetChanges(v) return nil + case deploymentstatistics.FieldLeadTimeSeconds: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetLeadTimeSeconds(v) + return nil case deploymentstatistics.FieldCreatedAt: v, ok := value.(time.Time) if !ok { @@ -4353,6 +4425,9 @@ func (m *DeploymentStatisticsMutation) AddedFields() []string { if m.addchanges != nil { fields = append(fields, deploymentstatistics.FieldChanges) } + if m.addlead_time_seconds != nil { + fields = append(fields, deploymentstatistics.FieldLeadTimeSeconds) + } return fields } @@ -4371,6 +4446,8 @@ func (m *DeploymentStatisticsMutation) AddedField(name string) (ent.Value, bool) return m.AddedDeletions() case deploymentstatistics.FieldChanges: return m.AddedChanges() + case deploymentstatistics.FieldLeadTimeSeconds: + return m.AddedLeadTimeSeconds() } return nil, false } @@ -4415,6 +4492,13 @@ func (m *DeploymentStatisticsMutation) AddField(name string, value ent.Value) er } m.AddChanges(v) return nil + case deploymentstatistics.FieldLeadTimeSeconds: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddLeadTimeSeconds(v) + return nil } return fmt.Errorf("unknown DeploymentStatistics numeric field %s", name) } @@ -4460,6 +4544,9 @@ func (m *DeploymentStatisticsMutation) ResetField(name string) error { case deploymentstatistics.FieldChanges: m.ResetChanges() return nil + case deploymentstatistics.FieldLeadTimeSeconds: + m.ResetLeadTimeSeconds() + return nil case deploymentstatistics.FieldCreatedAt: m.ResetCreatedAt() return nil diff --git a/ent/runtime.go b/ent/runtime.go index b12e3bcb..7d2ab986 100644 --- a/ent/runtime.go +++ b/ent/runtime.go @@ -117,12 +117,16 @@ func init() { deploymentstatisticsDescChanges := deploymentstatisticsFields[5].Descriptor() // deploymentstatistics.DefaultChanges holds the default value on creation for the changes field. deploymentstatistics.DefaultChanges = deploymentstatisticsDescChanges.Default.(int) + // deploymentstatisticsDescLeadTimeSeconds is the schema descriptor for lead_time_seconds field. + deploymentstatisticsDescLeadTimeSeconds := deploymentstatisticsFields[6].Descriptor() + // deploymentstatistics.DefaultLeadTimeSeconds holds the default value on creation for the lead_time_seconds field. + deploymentstatistics.DefaultLeadTimeSeconds = deploymentstatisticsDescLeadTimeSeconds.Default.(int) // deploymentstatisticsDescCreatedAt is the schema descriptor for created_at field. - deploymentstatisticsDescCreatedAt := deploymentstatisticsFields[6].Descriptor() + deploymentstatisticsDescCreatedAt := deploymentstatisticsFields[7].Descriptor() // deploymentstatistics.DefaultCreatedAt holds the default value on creation for the created_at field. deploymentstatistics.DefaultCreatedAt = deploymentstatisticsDescCreatedAt.Default.(func() time.Time) // deploymentstatisticsDescUpdatedAt is the schema descriptor for updated_at field. - deploymentstatisticsDescUpdatedAt := deploymentstatisticsFields[7].Descriptor() + deploymentstatisticsDescUpdatedAt := deploymentstatisticsFields[8].Descriptor() // deploymentstatistics.DefaultUpdatedAt holds the default value on creation for the updated_at field. deploymentstatistics.DefaultUpdatedAt = deploymentstatisticsDescUpdatedAt.Default.(func() time.Time) // deploymentstatistics.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field. diff --git a/ent/schema/deploymentstatistics.go b/ent/schema/deploymentstatistics.go index 709daee5..1db5676d 100644 --- a/ent/schema/deploymentstatistics.go +++ b/ent/schema/deploymentstatistics.go @@ -28,6 +28,8 @@ func (DeploymentStatistics) Fields() []ent.Field { Default(0), field.Int("changes"). Default(0), + field.Int("lead_time_seconds"). + Default(0), field.Time("created_at"). Default(time.Now), field.Time("updated_at"). diff --git a/internal/interactor/deploymentstatistics.go b/internal/interactor/deploymentstatistics.go index b12e2a97..327464b6 100644 --- a/internal/interactor/deploymentstatistics.go +++ b/internal/interactor/deploymentstatistics.go @@ -27,7 +27,6 @@ func (i *Interactor) ProduceDeploymentStatisticsOfRepo(ctx context.Context, r *e } func (i *Interactor) produceDeploymentStatisticsOfRepo(ctx context.Context, r *ent.Repo, d *ent.Deployment, s *ent.DeploymentStatistics) (*ent.DeploymentStatistics, error) { - // Increase the count of deployment. { if d.IsRollback { s.RollbackCount = s.RollbackCount + 1 @@ -36,7 +35,6 @@ func (i *Interactor) produceDeploymentStatisticsOfRepo(ctx context.Context, r *e } } - // Calculate changes from the lastest deployment. { ld, err := i.Store.FindPrevSuccessDeployment(ctx, d) if ent.IsNotFound(err) { @@ -53,11 +51,17 @@ func (i *Interactor) produceDeploymentStatisticsOfRepo(ctx context.Context, r *e } } - _, fs, err := i.SCM.CompareCommits(ctx, d.Edges.User, r, ld.Sha, d.Sha, 1, 100) + cms, fs, err := i.SCM.CompareCommits(ctx, d.Edges.User, r, ld.Sha, d.Sha, 1, 100) if err != nil { return nil, err } + for _, cm := range cms { + leadTime := d.UpdatedAt.Sub(cm.Author.Date) + s.LeadTimeSeconds = s.LeadTimeSeconds + int(leadTime.Seconds()) + } + + // Changes from the latest deployment. for _, f := range fs { s.Additions = s.Additions + f.Additions s.Deletions = s.Deletions + f.Deletions diff --git a/internal/pkg/store/deploymentstatistics.go b/internal/pkg/store/deploymentstatistics.go index b28b8866..34f8e4e5 100644 --- a/internal/pkg/store/deploymentstatistics.go +++ b/internal/pkg/store/deploymentstatistics.go @@ -46,6 +46,7 @@ func (s *Store) CreateDeploymentStatistics(ctx context.Context, ds *ent.Deployme SetAdditions(ds.Additions). SetDeletions(ds.Deletions). SetChanges(ds.Changes). + SetLeadTimeSeconds(ds.LeadTimeSeconds). SetRepoID(ds.RepoID). Save(ctx) } @@ -58,5 +59,6 @@ func (s *Store) UpdateDeploymentStatistics(ctx context.Context, ds *ent.Deployme SetAdditions(ds.Additions). SetDeletions(ds.Deletions). SetChanges(ds.Changes). + SetLeadTimeSeconds(ds.LeadTimeSeconds). Save(ctx) } diff --git a/internal/server/metrics/metrics.go b/internal/server/metrics/metrics.go index 5cc5c874..cec002cc 100644 --- a/internal/server/metrics/metrics.go +++ b/internal/server/metrics/metrics.go @@ -192,6 +192,22 @@ func (c *collector) Collect(ch chan<- prometheus.Metric) { float64(dc.Changes), dc.Edges.Repo.Namespace, dc.Edges.Repo.Name, dc.Env, ) + + ch <- prometheus.MustNewConstMetric( + prometheus.NewDesc( + prometheus.BuildFQName( + namespace, + "", + "lead_time_seconds", + ), + "The amount of time it takes a commit to get into production.", + []string{"namespace", "name", "env"}, + nil, + ), + prometheus.GaugeValue, + float64(dc.LeadTimeSeconds), + dc.Edges.Repo.Namespace, dc.Edges.Repo.Name, dc.Env, + ) } c.log.Debug("Collect deployment_count metrics successfully.")