7
7
"io"
8
8
"os"
9
9
"os/signal"
10
+ "strings"
10
11
"sync"
11
12
"time"
12
13
@@ -69,21 +70,20 @@ func ProvisionerJob(ctx context.Context, writer io.Writer, opts ProvisionerJobOp
69
70
jobMutex sync.Mutex
70
71
)
71
72
73
+ sw := & stageWriter {w : writer , verbose : opts .Verbose , silentLogs : opts .Silent }
74
+
72
75
printStage := func () {
73
- _ , _ = fmt . Fprintf ( writer , "==> ⧗ %s \n " , currentStage )
76
+ sw . Start ( currentStage )
74
77
}
75
78
76
79
updateStage := func (stage string , startedAt time.Time ) {
77
80
if currentStage != "" {
78
- mark := "✔"
81
+ duration := startedAt . Sub ( currentStageStartedAt )
79
82
if job .CompletedAt != nil && job .Status != codersdk .ProvisionerJobSucceeded {
80
- mark = "✘"
81
- }
82
- dur := startedAt .Sub (currentStageStartedAt ).Milliseconds ()
83
- if dur < 0 {
84
- dur = 0
83
+ sw .Fail (currentStage , duration )
84
+ } else {
85
+ sw .Complete (currentStage , duration )
85
86
}
86
- _ , _ = fmt .Fprintf (writer , "=== %s %s [%dms]\n " , mark , currentStage , dur )
87
87
}
88
88
if stage == "" {
89
89
return
@@ -147,30 +147,15 @@ func ProvisionerJob(ctx context.Context, writer io.Writer, opts ProvisionerJobOp
147
147
}
148
148
defer closer .Close ()
149
149
150
- var (
151
- // logOutput is where log output is written
152
- logOutput = writer
153
- // logBuffer is where logs are buffered if opts.Silent is true
154
- logBuffer = & bytes.Buffer {}
155
- )
156
- if opts .Silent {
157
- logOutput = logBuffer
158
- }
159
- flushLogBuffer := func () {
160
- if opts .Silent {
161
- _ , _ = io .Copy (writer , logBuffer )
162
- }
163
- }
164
-
165
150
ticker := time .NewTicker (opts .FetchInterval )
166
151
defer ticker .Stop ()
167
152
for {
168
153
select {
169
154
case err = <- errChan :
170
- flushLogBuffer ( )
155
+ sw . Fail ( currentStage , time . Since ( currentStageStartedAt ) )
171
156
return err
172
157
case <- ctx .Done ():
173
- flushLogBuffer ( )
158
+ sw . Fail ( currentStage , time . Since ( currentStageStartedAt ) )
174
159
return ctx .Err ()
175
160
case <- ticker .C :
176
161
updateJob ()
@@ -194,34 +179,83 @@ func ProvisionerJob(ctx context.Context, writer io.Writer, opts ProvisionerJobOp
194
179
Message : job .Error ,
195
180
Code : job .ErrorCode ,
196
181
}
182
+ sw .Fail (currentStage , time .Since (currentStageStartedAt ))
197
183
jobMutex .Unlock ()
198
- flushLogBuffer ()
199
184
return err
200
185
}
201
186
202
- output := ""
203
- switch log .Level {
204
- case codersdk .LogLevelTrace , codersdk .LogLevelDebug :
205
- if ! opts .Verbose {
206
- continue
207
- }
208
- output = DefaultStyles .Placeholder .Render (log .Output )
209
- case codersdk .LogLevelError :
210
- output = DefaultStyles .Error .Render (log .Output )
211
- case codersdk .LogLevelWarn :
212
- output = DefaultStyles .Warn .Render (log .Output )
213
- case codersdk .LogLevelInfo :
214
- output = log .Output
215
- }
216
-
217
187
jobMutex .Lock ()
218
188
if log .Stage != currentStage && log .Stage != "" {
219
189
updateStage (log .Stage , log .CreatedAt )
220
190
jobMutex .Unlock ()
221
191
continue
222
192
}
223
- _ , _ = fmt . Fprintf ( logOutput , "%s \n " , output )
193
+ sw . Log ( log . CreatedAt , log . Level , log . Output )
224
194
jobMutex .Unlock ()
225
195
}
226
196
}
227
197
}
198
+
199
+ type stageWriter struct {
200
+ w io.Writer
201
+ verbose bool
202
+ silentLogs bool
203
+ logBuf bytes.Buffer
204
+ }
205
+
206
+ func (s * stageWriter ) Start (stage string ) {
207
+ _ , _ = fmt .Fprintf (s .w , " => ⧗ %s\n " , stage )
208
+ }
209
+
210
+ func (s * stageWriter ) Complete (stage string , duration time.Duration ) {
211
+ s .end (stage , duration , true )
212
+ }
213
+
214
+ func (s * stageWriter ) Fail (stage string , duration time.Duration ) {
215
+ s .flushLogs ()
216
+ s .end (stage , duration , false )
217
+ }
218
+
219
+ //nolint:revive
220
+ func (s * stageWriter ) end (stage string , duration time.Duration , ok bool ) {
221
+ s .logBuf .Reset ()
222
+
223
+ mark := "✔"
224
+ if ! ok {
225
+ mark = "✘"
226
+ }
227
+ if duration < 0 {
228
+ duration = 0
229
+ }
230
+ _ , _ = fmt .Fprintf (s .w , " == %s %s [%dms]\n " , mark , stage , duration .Milliseconds ())
231
+ }
232
+
233
+ func (s * stageWriter ) Log (createdAt time.Time , level codersdk.LogLevel , line string ) {
234
+ w := s .w
235
+ if s .silentLogs {
236
+ w = & s .logBuf
237
+ }
238
+
239
+ render := func (s ... string ) string { return strings .Join (s , " " ) }
240
+
241
+ switch level {
242
+ case codersdk .LogLevelTrace , codersdk .LogLevelDebug :
243
+ if ! s .verbose {
244
+ return
245
+ }
246
+ render = DefaultStyles .Placeholder .Render
247
+ case codersdk .LogLevelError :
248
+ render = DefaultStyles .Error .Render
249
+ case codersdk .LogLevelWarn :
250
+ render = DefaultStyles .Warn .Render
251
+ case codersdk .LogLevelInfo :
252
+ }
253
+ _ , _ = fmt .Fprintf (w , " %s\n " , render (fmt .Sprintf ("%s %s" , createdAt .Local ().Format ("2006-01-02 15:04:05.000Z07:00" ), line )))
254
+ }
255
+
256
+ func (s * stageWriter ) flushLogs () {
257
+ if s .silentLogs {
258
+ _ , _ = io .Copy (s .w , & s .logBuf )
259
+ }
260
+ s .logBuf .Reset ()
261
+ }
0 commit comments