@@ -19,23 +19,23 @@ type timingKind string
19
19
// Copied from https://github.com/hashicorp/terraform/blob/ffbcaf8bef12bb1f4d79f06437f414e280d08761/internal/command/views/json/message_types.go
20
20
// We cannot reference these because they're in an internal package.
21
21
const (
22
- applyStart timingKind = "apply_start"
23
- applyProgress timingKind = "apply_progress"
24
- applyComplete timingKind = "apply_complete"
25
- applyErrored timingKind = "apply_errored"
26
- provisionStart timingKind = "provision_start"
27
- provisionProgress timingKind = "provision_progress"
28
- provisionComplete timingKind = "provision_complete"
29
- provisionErrored timingKind = "provision_errored"
30
- refreshStart timingKind = "refresh_start"
31
- refreshComplete timingKind = "refresh_complete"
22
+ timingApplyStart timingKind = "apply_start"
23
+ timingApplyProgress timingKind = "apply_progress"
24
+ timingApplyComplete timingKind = "apply_complete"
25
+ timingApplyErrored timingKind = "apply_errored"
26
+ timingProvisionStart timingKind = "provision_start"
27
+ timingProvisionProgress timingKind = "provision_progress"
28
+ timingProvisionComplete timingKind = "provision_complete"
29
+ timingProvisionErrored timingKind = "provision_errored"
30
+ timingRefreshStart timingKind = "refresh_start"
31
+ timingRefreshComplete timingKind = "refresh_complete"
32
32
// These are not part of message_types, but we want to track init/graph timings as well.
33
- initStart timingKind = "init_start"
34
- initComplete timingKind = "init_complete"
35
- initErrored timingKind = "init_errored"
36
- graphStart timingKind = "graph_start"
37
- graphComplete timingKind = "graph_complete"
38
- graphErrored timingKind = "graph_errored"
33
+ timingInitStart timingKind = "init_start"
34
+ timingInitComplete timingKind = "init_complete"
35
+ timingInitErrored timingKind = "init_errored"
36
+ timingGraphStart timingKind = "graph_start"
37
+ timingGraphComplete timingKind = "graph_complete"
38
+ timingGraphErrored timingKind = "graph_errored"
39
39
)
40
40
41
41
type timingAggregator struct {
@@ -74,13 +74,13 @@ func (t *timingAggregator) ingest(ts time.Time, s *timingSpan) {
74
74
ts = dbtime .Time (ts )
75
75
76
76
switch s .kind {
77
- case applyStart , provisionStart , refreshStart , initStart , graphStart :
77
+ case timingApplyStart , timingProvisionStart , timingRefreshStart , timingInitStart , timingGraphStart :
78
78
s .start = ts
79
79
s .state = proto .TimingState_STARTED
80
- case applyComplete , provisionComplete , refreshComplete , initComplete , graphComplete :
80
+ case timingApplyComplete , timingProvisionComplete , timingRefreshComplete , timingInitComplete , timingGraphComplete :
81
81
s .end = ts
82
82
s .state = proto .TimingState_COMPLETED
83
- case applyErrored , provisionErrored , initErrored , graphErrored :
83
+ case timingApplyErrored , timingProvisionErrored , timingInitErrored , timingGraphErrored :
84
84
s .end = ts
85
85
s .state = proto .TimingState_FAILED
86
86
default :
@@ -137,33 +137,58 @@ func (t *timingAggregator) aggregate() []*proto.Timing {
137
137
138
138
func (l timingKind ) Valid () bool {
139
139
return slices .Contains ([]timingKind {
140
- applyStart ,
141
- applyProgress ,
142
- applyComplete ,
143
- applyErrored ,
144
- provisionStart ,
145
- provisionProgress ,
146
- provisionComplete ,
147
- provisionErrored ,
148
- refreshStart ,
149
- refreshComplete ,
150
- initStart ,
151
- initComplete ,
152
- initErrored ,
153
- graphStart ,
154
- graphComplete ,
155
- graphErrored ,
140
+ timingApplyStart ,
141
+ timingApplyProgress ,
142
+ timingApplyComplete ,
143
+ timingApplyErrored ,
144
+ timingProvisionStart ,
145
+ timingProvisionProgress ,
146
+ timingProvisionComplete ,
147
+ timingProvisionErrored ,
148
+ timingRefreshStart ,
149
+ timingRefreshComplete ,
150
+ timingInitStart ,
151
+ timingInitComplete ,
152
+ timingInitErrored ,
153
+ timingGraphStart ,
154
+ timingGraphComplete ,
155
+ timingGraphErrored ,
156
156
}, l )
157
157
}
158
158
159
+ // Category returns the category for a giving timing state so that timings can be aggregated by this category.
160
+ // We can't use the state itself because we need an `apply_start` and an `apply_complete` to both hash to the same entry
161
+ // if all other attributes are identical.
162
+ func (l timingKind ) Category () string {
163
+ switch l {
164
+ case timingInitStart , timingInitComplete , timingInitErrored :
165
+ return "init"
166
+ case timingGraphStart , timingGraphComplete , timingGraphErrored :
167
+ return "graph"
168
+ case timingApplyStart , timingApplyProgress , timingApplyComplete , timingApplyErrored :
169
+ return "apply"
170
+ case timingProvisionStart , timingProvisionProgress , timingProvisionComplete , timingProvisionErrored :
171
+ return "provision"
172
+ case timingRefreshStart , timingRefreshComplete :
173
+ return "state refresh"
174
+ default :
175
+ return "?"
176
+ }
177
+ }
178
+
159
179
// hashState computes a hash based on a timingSpan's unique properties and state.
160
180
// The combination of resource and provider names MUST be unique across entries.
161
181
func (e * timingSpan ) hashByState (state proto.TimingState ) uint64 {
162
- id := fmt .Sprintf ("%s:%s:%s" , state .String (), e .resource , e .provider )
182
+ id := fmt .Sprintf ("%s:%s:%s:%s" , e . kind . Category () , state .String (), e .resource , e .provider )
163
183
return xxhash .Sum64String (id )
164
184
}
165
185
166
186
func (e * timingSpan ) toProto () * proto.Timing {
187
+ // Some log entries, like state refreshes, don't have any "action" logged.
188
+ if e .action == "" {
189
+ e .action = e .kind .Category ()
190
+ }
191
+
167
192
return & proto.Timing {
168
193
Start : timestamppb .New (e .start ),
169
194
End : timestamppb .New (e .end ),
@@ -191,4 +216,4 @@ func createGraphTimingsEvent(event timingKind) (time.Time, *timingSpan) {
191
216
provider : "terraform" ,
192
217
resource : "state file" ,
193
218
}
194
- }
219
+ }
0 commit comments