一键导入
working-with-steplogger
Complete guide to integrating StepLogger for user progress feedback in commands and runtimes
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Complete guide to integrating StepLogger for user progress feedback in commands and runtimes
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | working-with-steplogger |
| description | Complete guide to integrating StepLogger for user progress feedback in commands and runtimes |
| argument-hint |
The StepLogger system provides user-facing progress feedback during runtime operations. It displays operational steps with spinners and completion messages in text mode, improving the user experience for long-running operations.
StepLogger enables commands and runtimes to show users what's happening during multi-step operations like creating containers, building images, or starting instances. It automatically handles different output modes (text with spinners vs JSON with silence).
pkg/steplogger/steplogger.go): Contract for logging operational stepspkg/steplogger/text.go): Implementation with spinner animations for text outputpkg/steplogger/noop.go): Silent implementation for JSON mode and testspkg/steplogger/context.go): Attach/retrieve loggers from contextCommands are responsible for creating and injecting the appropriate StepLogger into the context before calling runtime methods:
func (c *myCmd) run(cmd *cobra.Command, args []string) error {
// Create appropriate logger based on output mode
var logger steplogger.StepLogger
if c.output == "json" {
// No step logging in JSON mode
logger = steplogger.NewNoOpLogger()
} else {
// Use text logger with spinners for text output
logger = steplogger.NewTextLogger(cmd.ErrOrStderr())
}
defer logger.Complete()
// Attach logger to context
ctx := steplogger.WithLogger(cmd.Context(), logger)
// Pass context to runtime methods
info, err := runtime.Create(ctx, params)
if err != nil {
return err
}
return nil
}
--output json): Use steplogger.NewNoOpLogger() - completely silent, no outputsteplogger.NewTextLogger(cmd.ErrOrStderr()) - displays spinners and messages to stderrdefer logger.Complete() immediately after creating the loggersteplogger.WithLogger(cmd.Context(), logger)cmd.Context()) to all runtime methodscmd.ErrOrStderr()) so it doesn't interfere with stdout JSON outputAll runtime methods that accept a context.Context should use the StepLogger for user feedback.
Note for Runtime Implementers: You don't need to create or inject the StepLogger - it's already in the context. Simply retrieve it using steplogger.FromContext(ctx) and use it as shown below:
func (r *myRuntime) Create(ctx context.Context, params runtime.CreateParams) (runtime.RuntimeInfo, error) {
logger := steplogger.FromContext(ctx)
defer logger.Complete()
// Step 1: Create resources
logger.Start("Creating workspace directory", "Workspace directory created")
if err := r.createDirectory(params.Name); err != nil {
logger.Fail(err)
return runtime.RuntimeInfo{}, err
}
// Step 2: Build image
logger.Start("Building container image", "Container image built")
if err := r.buildImage(ctx, params.Name); err != nil {
logger.Fail(err)
return runtime.RuntimeInfo{}, err
}
// Step 3: Create instance
logger.Start("Creating instance", "Instance created")
info, err := r.createInstance(ctx, params)
if err != nil {
logger.Fail(err)
return runtime.RuntimeInfo{}, err
}
return info, nil
}
Begin a new step with progress and completion messages.
inProgress: Message shown while the step is running (e.g., "Building container image")completed: Message shown when the step completes (e.g., "Container image built")Mark the current step as successfully completed.
defer at the start of the method to complete the last stepMark the current step as failed.
Complete() with defer at the start of the methodFail() before returning errors to show which step failedsteplogger.FromContext(ctx)--output json is set// Create
func (r *myRuntime) Create(ctx context.Context, params runtime.CreateParams) (runtime.RuntimeInfo, error) {
logger := steplogger.FromContext(ctx)
defer logger.Complete()
logger.Start("Creating resource", "Resource created")
// ... implementation ...
}
// Start
func (r *myRuntime) Start(ctx context.Context, id string) (runtime.RuntimeInfo, error) {
logger := steplogger.FromContext(ctx)
defer logger.Complete()
logger.Start("Starting instance", "Instance started")
// ... implementation ...
}
// Stop
func (r *myRuntime) Stop(ctx context.Context, id string) error {
logger := steplogger.FromContext(ctx)
defer logger.Complete()
logger.Start("Stopping instance", "Instance stopped")
// ... implementation ...
}
// Remove
func (r *myRuntime) Remove(ctx context.Context, id string) error {
logger := steplogger.FromContext(ctx)
defer logger.Complete()
logger.Start("Removing instance", "Instance removed")
// ... implementation ...
}
steplogger.NewNoOpLogger() or don't attach a logger (defaults to NoOp)Create a fake step logger to verify step behavior in tests:
// Create fake logger
type fakeStepLogger struct {
startCalls []stepCall
failCalls []error
completeCalls int
}
type stepCall struct {
inProgress string
completed string
}
func (f *fakeStepLogger) Start(inProgress, completed string) {
f.startCalls = append(f.startCalls, stepCall{inProgress, completed})
}
func (f *fakeStepLogger) Fail(err error) {
f.failCalls = append(f.failCalls, err)
}
func (f *fakeStepLogger) Complete() {
f.completeCalls++
}
// Use in tests
func TestCreate_StepLogger(t *testing.T) {
fakeLogger := &fakeStepLogger{}
ctx := steplogger.WithLogger(context.Background(), fakeLogger)
_, err := runtime.Create(ctx, params)
// Verify step calls
if len(fakeLogger.startCalls) != 3 {
t.Errorf("Expected 3 Start() calls, got %d", len(fakeLogger.startCalls))
}
if fakeLogger.completeCalls != 1 {
t.Errorf("Expected 1 Complete() call, got %d", fakeLogger.completeCalls)
}
}
See pkg/runtime/podman/ for complete examples:
create.go - Multi-step Create operation with 4 stepsstart.go - Start operation with verification stepstop.go - Simple single-step Stop operationremove.go - Remove operation with state checkingSee pkg/runtime/podman/steplogger_test.go and step logger tests in create_test.go, start_test.go, stop_test.go, remove_test.go.
/working-with-runtime-system - Runtime architecture overview/add-runtime - Creating new runtimes with StepLogger/implementing-command-patterns - Command patterns including StepLogger integrationpkg/steplogger/steplogger.gopkg/steplogger/text.gopkg/steplogger/noop.gopkg/steplogger/context.gopkg/cmd/init.go, pkg/cmd/workspace_start.go, pkg/cmd/workspace_stop.go, pkg/cmd/workspace_remove.goAdd a new runtime implementation to the kdn runtime system
Guide to using the instances manager API for workspace management and project detection
Guide to understanding and working with the kdn runtime system architecture
Guide to configuring the Podman runtime including image setup, agent configuration, and containerfile generation
Conventional Commit Message Generator
Guide to the autoconf package — how secret detection, filtering, and the runner are wired together, and how to extend the system with new detector types