Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions cmd/lapp/analyze.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package main

import (
"bufio"
"fmt"
"log/slog"
"os"
"strings"

Expand Down Expand Up @@ -47,7 +47,7 @@ func runAnalyze(cmd *cobra.Command, args []string) error {
}

// Read all lines
fmt.Fprintf(os.Stderr, "Reading logs...\n")
slog.Info("Reading logs...")
lines, err := readLines(logFile)
if err != nil {
return errors.Errorf("read log file: %w", err)
Expand All @@ -61,7 +61,7 @@ func runAnalyze(cmd *cobra.Command, args []string) error {
for i, m := range merged {
mergedLines[i] = m.Content
}
fmt.Fprintf(os.Stderr, "Read %d lines, merged into %d entries\n", len(lines), len(mergedLines))
slog.Info("Read lines", "lines", len(lines), "merged_entries", len(mergedLines))

config := analyzer.Config{
APIKey: apiKey,
Expand All @@ -73,7 +73,7 @@ func runAnalyze(cmd *cobra.Command, args []string) error {
return err
}

fmt.Println(result)
slog.Info(result)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Print analyze output to stdout

analyze's primary payload is the model's final answer, but this now goes through slog.Info, which uses the default logger and writes via the log package to stderr by default; this breaks scripting/piping (lapp analyze ... > answer.txt captures nothing) and also prefixes the response with log metadata instead of returning raw analysis text.

Useful? React with 👍 / 👎.

return nil
}

Expand Down
15 changes: 7 additions & 8 deletions cmd/lapp/debug.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package main

import (
"fmt"
"log/slog"
"os"

"github.com/go-errors/errors"
Expand Down Expand Up @@ -41,7 +41,7 @@ files (raw.log, summary.txt, errors.txt) in a local directory for inspection.`,
func runDebugWorkspace(cmd *cobra.Command, args []string) error {
logFile := args[0]

fmt.Fprintf(os.Stderr, "Reading logs...\n")
slog.Info("Reading logs...")
lines, err := readLines(logFile)
if err != nil {
return errors.Errorf("read log file: %w", err)
Expand All @@ -55,7 +55,7 @@ func runDebugWorkspace(cmd *cobra.Command, args []string) error {
for i, m := range merged {
mergedLines[i] = m.Content
}
fmt.Fprintf(os.Stderr, "Read %d lines, merged into %d entries\n", len(lines), len(mergedLines))
slog.Info("Read lines", "lines", len(lines), "merged_entries", len(mergedLines))

outDir := debugWorkspaceOutput
if outDir == "" {
Expand All @@ -74,7 +74,7 @@ func runDebugWorkspace(cmd *cobra.Command, args []string) error {
return errors.Errorf("drain parser: %w", err)
}

fmt.Fprintf(os.Stderr, "Parsing %d entries...\n", len(mergedLines))
slog.Info("Parsing entries", "count", len(mergedLines))
if err := drainParser.Feed(mergedLines); err != nil {
return errors.Errorf("drain feed: %w", err)
}
Expand All @@ -87,8 +87,7 @@ func runDebugWorkspace(cmd *cobra.Command, args []string) error {
return errors.Errorf("build workspace: %w", err)
}

fmt.Fprintf(os.Stderr, "Workspace created at: %s\n", outDir)
fmt.Println(outDir)
slog.Info("Workspace created", "dir", outDir)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep workspace directory path on stdout

In runDebugWorkspace, the only post-success output is now slog.Info("Workspace created", "dir", outDir), which goes through the default slog logger and is written to stderr with log metadata; this removes the plain stdout path that callers could reliably capture when --output is omitted. As a result, shell workflows like workdir=$(lapp debug workspace app.log) (and chaining into debug run) now get an empty variable and fail to locate the generated workspace.

Useful? React with 👍 / 👎.

return nil
}

Expand Down Expand Up @@ -130,12 +129,12 @@ func runDebugRun(cmd *cobra.Command, args []string) error {
Model: debugRunModel,
}

fmt.Fprintf(os.Stderr, "Running agent on workspace: %s\n", workDir)
slog.Info("Running agent on workspace", "dir", workDir)
result, err := analyzer.RunAgent(cmd.Context(), config, workDir, question)
if err != nil {
return err
}

fmt.Println(result)
slog.Info(result)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Print debug-run agent result to stdout

debug run previously emitted the agent result as command output, but replacing it with slog.Info sends it to stderr (default logger behavior) and adds log prefixes, so command substitution and redirection workflows cannot reliably consume the generated analysis.

Useful? React with 👍 / 👎.

return nil
}
13 changes: 8 additions & 5 deletions cmd/lapp/ingest.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package main

import (
"context"
"fmt"
"log/slog"
"os"
"time"

Expand Down Expand Up @@ -97,9 +97,12 @@ func runIngest(cmd *cobra.Command, args []string, model string) error {
return err
}

fmt.Fprintf(os.Stderr, "Ingested %d lines, discovered %d patterns (%d with 2+ matches)\n",
len(lines), templateCount, patternCount)
fmt.Fprintf(os.Stderr, "Database: %s\n", dbPath)
slog.Info("Ingestion complete",
"lines", len(lines),
"templates", templateCount,
"patterns_with_2+_matches", patternCount,
)
slog.Info("Database stored", "path", dbPath)
return nil
}

Expand Down Expand Up @@ -148,7 +151,7 @@ func discoverAndSavePatterns(
// Build labeler inputs with sample lines from in-memory data
inputs := buildLabelInputs(filtered, lines)

fmt.Fprintf(os.Stderr, "Labeling %d patterns...\n", len(inputs))
slog.Info("Labeling patterns", "count", len(inputs))

labels, err := semantic.Label(ctx, labelCfg, inputs)
if err != nil {
Expand Down
21 changes: 14 additions & 7 deletions cmd/lapp/templates.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package main

import (
"fmt"
"log/slog"

"github.com/go-errors/errors"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -45,8 +45,6 @@ func runTemplates(cmd *cobra.Command, _ []string) error {
}

if hasLabels {
fmt.Printf("%-12s %-6s %-22s %-6s %s\n", "ID", "TYPE", "SEMANTIC_ID", "COUNT", "DESCRIPTION")
fmt.Println("------------ ------ ---------------------- ------ ----------------------------------------")
for _, ts := range summaries {
semanticID := ts.SemanticID
if semanticID == "" {
Expand All @@ -60,17 +58,26 @@ func runTemplates(cmd *cobra.Command, _ []string) error {
if pType == "" {
pType = "-"
}
fmt.Printf("%-12s %-6s %-22s %-6d %s\n", ts.PatternUUIDString, pType, semanticID, ts.Count, desc)
slog.Info("template",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Emit template rows on stdout

The templates command is documented to list discovered templates, but rows are now emitted with slog.Info; with default slog configuration these records go to stderr, so lapp templates > templates.txt produces an empty file and downstream tooling can no longer consume template listings as command output.

Useful? React with 👍 / 👎.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Emit template rows on stdout, not structured logs

The templates subcommand now emits each template via slog.Info instead of writing rows to stdout, so the command’s data output is redirected to stderr and prefixed by logger formatting rather than remaining a clean stream. This breaks common non-interactive usage (lapp templates > templates.txt, piping into text tools) because stdout is no longer the source of template data.

Useful? React with 👍 / 👎.

"id", ts.PatternUUIDString,
"type", pType,
"semantic_id", semanticID,
"count", ts.Count,
"description", desc,
)
}
} else {
fmt.Printf("%-12s %-6s %-6s %s\n", "ID", "TYPE", "COUNT", "PATTERN")
fmt.Println("------------ ------ ------ ----------------------------------------")
for _, ts := range summaries {
pType := ts.PatternType
if pType == "" {
pType = "-"
}
fmt.Printf("%-12s %-6s %-6d %s\n", ts.PatternUUIDString, pType, ts.Count, ts.Pattern)
slog.Info("template",
"id", ts.PatternUUIDString,
"type", pType,
"count", ts.Count,
"pattern", ts.Pattern,
)
}
}
return nil
Expand Down
5 changes: 3 additions & 2 deletions pkg/analyzer/analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"encoding/json"
"fmt"
"io"
"log/slog"
"net/http"
"os"
"path/filepath"
Expand Down Expand Up @@ -73,7 +74,7 @@ func Analyze(ctx context.Context, config Config, lines []string, question string
return "", errors.Errorf("drain parser: %w", err)
}

fmt.Fprintf(os.Stderr, "Parsing %d lines...\n", len(lines))
slog.Info("Parsing lines", "count", len(lines))
if err := drainParser.Feed(lines); err != nil {
return "", errors.Errorf("drain feed: %w", err)
}
Expand All @@ -98,7 +99,7 @@ func RunAgent(ctx context.Context, config Config, workDir, question string) (str
return "", errors.Errorf("resolve workspace dir: %w", err)
}

fmt.Fprintf(os.Stderr, "Analyzing with model %s...\n", config.Model)
slog.Info("Analyzing with model", "model", config.Model)

// Preflight check: verify API key works
if err := preflightCheck(ctx, config); err != nil {
Expand Down