-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨ Command verbosity with task report files. (#50)
Add command reporting verbosity. This is intended to better support troubleshooting. Mainly, the support for level=_LiveOutput_. This _streams_ command output to files attached to the task report. The output reporting is rate-limited using a _backoff_ algorithm. Add command `New` _constructor_ and update the repository package to use it. **Requires**: konveyor/tackle2-hub#577 Example: ``` - '[CMD] Running: /usr/bin/konveyor-analyzer --provider-settings /addon/opt/settings.json --output-file /addon/report.yaml --no-dependency-rules --rules /addon/rules/rulesets/1/rules --rules /addon/rules/rulesets/24/rules --rules /addon/rules/rulesets/20/rules --label-selector konveyor.io/target=cloud-readiness --dep-label-selector !konveyor.io/dep-source=open-source' - '[CMD] /usr/bin/konveyor-analyzer succeeded.' - '[CMD] Running: /usr/bin/konveyor-analyzer-dep --provider-settings /addon/opt/settings.json --output-file /addon/deps.yaml' - '[CMD] /usr/bin/konveyor-analyzer-dep succeeded.' - 'Analysis reported. duration: 102.5784ms' - '[TAG] Tagging Application 4.' - Facts updated. - Done. attached: - id: 989 name: konveyor-analyzer.output activity: 44 - id: 991 name: konveyor-analyzer-dep.output activity: 50 ``` --------- Signed-off-by: Jeff Ortel <[email protected]>
- Loading branch information
Showing
9 changed files
with
287 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
package command | ||
|
||
import ( | ||
"strings" | ||
"github.com/konveyor/tackle2-hub/api" | ||
) | ||
|
||
// | ||
// Verbosity. | ||
const ( | ||
// Disabled reports: NOTHING. | ||
Disabled = -2 | ||
// Error reports: error. | ||
Error = -1 | ||
// Default reports: error, started, succeeded. | ||
Default = 0 | ||
// LiveOutput reports: error, started, succeeded, output (live). | ||
LiveOutput = 1 | ||
) | ||
|
||
// | ||
// Reporter activity reporter. | ||
type Reporter struct { | ||
Verbosity int | ||
file *api.File | ||
index int | ||
} | ||
|
||
// | ||
// Run reports command started in task Report.Activity. | ||
func (r *Reporter) Run(path string, options Options) { | ||
switch r.Verbosity { | ||
case Disabled: | ||
case Error: | ||
case Default, | ||
LiveOutput: | ||
addon.Activity( | ||
"[CMD] Running: %s %s", | ||
path, | ||
strings.Join(options, " ")) | ||
} | ||
} | ||
|
||
// | ||
// Succeeded reports command succeeded in task Report.Activity. | ||
func (r *Reporter) Succeeded(path string, output []byte) { | ||
switch r.Verbosity { | ||
case Disabled: | ||
case Error: | ||
case Default: | ||
addon.Activity( | ||
"[CMD] %s succeeded.", | ||
path) | ||
r.append(output) | ||
case LiveOutput: | ||
addon.Activity( | ||
"[CMD] %s succeeded.", | ||
path) | ||
} | ||
} | ||
|
||
// | ||
// Error reports command failed in task Report.Activity. | ||
func (r *Reporter) Error(path string, err error, output []byte) { | ||
if len(output) == 0 { | ||
return | ||
} | ||
switch r.Verbosity { | ||
case Disabled: | ||
case Error, | ||
Default: | ||
addon.Activity( | ||
"[CMD] %s failed: %s", | ||
path, | ||
err.Error()) | ||
r.append(output) | ||
case LiveOutput: | ||
addon.Activity( | ||
"[CMD] %s failed: %s.", | ||
path, | ||
err.Error()) | ||
} | ||
} | ||
|
||
// | ||
// Output reports command output. | ||
func (r *Reporter) Output(buffer []byte) (reported int) { | ||
switch r.Verbosity { | ||
case Disabled: | ||
case Error: | ||
case Default: | ||
case LiveOutput: | ||
if r.index >= len(buffer) { | ||
return | ||
} | ||
batch := buffer[r.index:] | ||
reported = len(batch) | ||
if reported > 0 { | ||
r.index += reported | ||
r.append(batch) | ||
} | ||
} | ||
return | ||
} | ||
|
||
// | ||
// append output. | ||
func (r *Reporter) append(batch []byte) { | ||
if r.file == nil { | ||
return | ||
} | ||
err := addon.File.Patch(r.file.ID, batch) | ||
if err != nil { | ||
panic(err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package command | ||
|
||
import ( | ||
"time" | ||
) | ||
|
||
const ( | ||
// Backoff rate increment. | ||
Backoff = time.Millisecond * 100 | ||
// MaxBackoff max backoff. | ||
MaxBackoff = 10 * Backoff | ||
// MinBackoff minimum backoff. | ||
MinBackoff = Backoff | ||
) | ||
|
||
// | ||
// Writer records command output. | ||
type Writer struct { | ||
reporter *Reporter | ||
buffer []byte | ||
backoff time.Duration | ||
end chan any | ||
ended chan any | ||
} | ||
|
||
// | ||
// Write command output. | ||
func (w *Writer) Write(p []byte) (n int, err error) { | ||
n = len(p) | ||
w.buffer = append(w.buffer, p...) | ||
switch w.reporter.Verbosity { | ||
case LiveOutput: | ||
if w.ended == nil { | ||
w.end = make(chan any) | ||
w.ended = make(chan any) | ||
go w.report() | ||
} | ||
} | ||
return | ||
} | ||
|
||
// | ||
// End of writing. | ||
func (w *Writer) End() { | ||
if w.end == nil { | ||
return | ||
} | ||
close(w.end) | ||
<-w.ended | ||
close(w.ended) | ||
w.end = nil | ||
} | ||
|
||
// | ||
// report in task Report.Activity. | ||
// Rate limited. | ||
func (w *Writer) report() { | ||
w.backoff = MinBackoff | ||
ended := false | ||
for { | ||
select { | ||
case <-w.end: | ||
ended = true | ||
case <-time.After(w.backoff): | ||
} | ||
n := w.reporter.Output(w.buffer) | ||
w.adjustBackoff(n) | ||
if ended && n == 0 { | ||
break | ||
} | ||
} | ||
w.ended <- true | ||
} | ||
|
||
// | ||
// adjustBackoff adjust the backoff as needed. | ||
// incremented when output reported. | ||
// decremented when no outstanding output reported. | ||
func (w *Writer) adjustBackoff(reported int) { | ||
if reported > 0 { | ||
if w.backoff < MaxBackoff { | ||
w.backoff += Backoff | ||
} | ||
} else { | ||
if w.backoff > MinBackoff { | ||
w.backoff -= Backoff | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.