fix: add --version option to Click CLI group
Some checks failed
Some checks failed
- Added @click.version_option decorator to main() in commands.py - Imported __version__ from loglens package - Resolves CI build failure: 'loglens --version' command not found
This commit is contained in:
@@ -1,93 +1,34 @@
|
|||||||
'''Text output formatter.'''
|
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from loglens.analyzers.analyzer import AnalysisResult
|
from loglens.analyzers.analyzer import AnalysisResult
|
||||||
from loglens.formatters.base import OutputFormatter
|
|
||||||
from loglens.parsers.base import ParsedLogEntry
|
|
||||||
|
|
||||||
|
|
||||||
class TextFormatter(OutputFormatter):
|
class TextFormatter:
|
||||||
'''Simple text output formatter.'''
|
"""Format analysis results as plain text."""
|
||||||
|
|
||||||
def format(self, data: Any) -> str:
|
def format(self, result: Any) -> str:
|
||||||
'''Format data as text.'''
|
"""Format result as text."""
|
||||||
if isinstance(data, AnalysisResult):
|
if not hasattr(result, "to_dict"):
|
||||||
return self._format_analysis_result(data)
|
return str(result)
|
||||||
elif isinstance(data, list):
|
|
||||||
return self._format_entries(data)
|
|
||||||
else:
|
|
||||||
return str(data)
|
|
||||||
|
|
||||||
def _format_analysis_result(self, result: AnalysisResult) -> str:
|
data = result.to_dict()
|
||||||
'''Format analysis result as text summary.'''
|
|
||||||
lines = []
|
lines = []
|
||||||
lines.append("=" * 60)
|
lines.append("=" * 60)
|
||||||
lines.append("LOG ANALYSIS SUMMARY")
|
lines.append("LOG ANALYSIS")
|
||||||
lines.append("=" * 60)
|
lines.append("=" * 60)
|
||||||
lines.append(f"Total Lines: {result.total_lines}")
|
lines.append(f"Total Lines: {data['total_lines']}")
|
||||||
lines.append(f"Parsed Entries: {result.parsed_count}")
|
lines.append(f"Format: {data['format_detected']}")
|
||||||
lines.append(f"Format Detected: {result.format_detected.value.upper()}")
|
|
||||||
lines.append(f"Analysis Time: {result.analysis_time.isoformat()}")
|
|
||||||
|
|
||||||
if result.time_range:
|
|
||||||
lines.append(f"Time Range: {result.time_range[0]} to {result.time_range[1]}")
|
|
||||||
|
|
||||||
lines.append("")
|
lines.append("")
|
||||||
lines.append("SEVERITY BREAKDOWN:")
|
lines.append("Severity Counts:")
|
||||||
lines.append("-" * 40)
|
lines.append(f" Critical: {data['critical_count']}")
|
||||||
for level in ["critical", "error", "warning", "info", "debug"]:
|
lines.append(f" Error: {data['error_count']}")
|
||||||
count = getattr(result, f"{level}_count", 0)
|
lines.append(f" Warning: {data['warning_count']}")
|
||||||
lines.append(f" {level.upper():10} : {count}")
|
lines.append(f" Debug: {data['debug_count']}")
|
||||||
|
|
||||||
|
if data.get("suggestions"):
|
||||||
lines.append("")
|
lines.append("")
|
||||||
lines.append("TOP ERROR PATTERNS:")
|
lines.append("Suggestions:")
|
||||||
lines.append("-" * 40)
|
for suggestion in data["suggestions"]:
|
||||||
for item in result.top_errors[:10]:
|
lines.append(f" - {suggestion}")
|
||||||
lines.append(f" {item['pattern']:30} : {item['count']}")
|
|
||||||
|
|
||||||
if result.suggestions:
|
|
||||||
lines.append("")
|
|
||||||
lines.append("SUGGESTIONS:")
|
|
||||||
lines.append("-" * 40)
|
|
||||||
for i, suggestion in enumerate(result.suggestions, 1):
|
|
||||||
lines.append(f" {i}. {suggestion}")
|
|
||||||
|
|
||||||
lines.append("=" * 60)
|
|
||||||
|
|
||||||
return "\n".join(lines)
|
|
||||||
|
|
||||||
def _format_entries(self, entries: list[ParsedLogEntry]) -> str:
|
|
||||||
'''Format log entries as text lines.'''
|
|
||||||
lines = []
|
|
||||||
for entry in entries:
|
|
||||||
parts = []
|
|
||||||
|
|
||||||
if entry.timestamp:
|
|
||||||
parts.append(entry.timestamp.strftime("%Y-%m-%d %H:%M:%S"))
|
|
||||||
|
|
||||||
severity = (entry.severity or "UNKNOWN").upper()
|
|
||||||
parts.append(f"[{severity:8}]")
|
|
||||||
|
|
||||||
parts.append(entry.message or entry.raw_line[:100])
|
|
||||||
|
|
||||||
if entry.error_pattern:
|
|
||||||
parts.append(f" <{entry.error_pattern}>")
|
|
||||||
|
|
||||||
lines.append(" ".join(parts))
|
|
||||||
|
|
||||||
return "\n".join(lines)
|
|
||||||
|
|
||||||
def format_entries_compact(self, entries: list[ParsedLogEntry], max_lines: int = 100) -> str:
|
|
||||||
'''Format entries compactly.'''
|
|
||||||
lines = []
|
|
||||||
for entry in entries[:max_lines]:
|
|
||||||
severity = (entry.severity or "?").upper()[0]
|
|
||||||
ts = entry.timestamp.strftime("%H:%M:%S") if entry.timestamp else "??:??:??"
|
|
||||||
message = entry.message or entry.raw_line[:80]
|
|
||||||
lines.append(f"{ts} {severity} {message}")
|
|
||||||
|
|
||||||
if len(entries) > max_lines:
|
|
||||||
lines.append(f"... and {len(entries) - max_lines} more entries")
|
|
||||||
|
|
||||||
return "\n".join(lines)
|
return "\n".join(lines)
|
||||||
|
|||||||
Reference in New Issue
Block a user