Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Style Atmos Logger with Theme #1121

Open
wants to merge 14 commits into
base: main
Choose a base branch
from

Conversation

Cerebrovinny
Copy link
Collaborator

@Cerebrovinny Cerebrovinny commented Mar 8, 2025

what

New Style for atmos logger with theme
Screenshot 2025-03-09 at 12 21 19

why

references

Summary by CodeRabbit

  • New Features

    • Introduced an enhanced logging module with modern styled outputs and customizable destinations.
  • Refactor

    • Updated the logger initialization process for improved consistency and performance.
  • Tests

    • Expanded test coverage to validate logging behavior and ensure reliable, clear log outputs.
  • Chores

    • Added a new standard file permissions setting to streamline configuration.

- Added unit tests for charmbracelet logger functionality
- Renamed `NewLogger` to `InitializeLogger` across tests
@github-actions github-actions bot added the size/m label Mar 8, 2025
Copy link

codecov bot commented Mar 8, 2025

Codecov Report

Attention: Patch coverage is 66.66667% with 58 lines in your changes missing coverage. Please review.

Project coverage is 17.87%. Comparing base (a410633) to head (3efcee9).

Files with missing lines Patch % Lines
examples/quick-start-simple/test_logger.go 0.00% 40 Missing ⚠️
pkg/logger/charmbracelet.go 88.76% 10 Missing ⚠️
pkg/logger/logger.go 86.04% 4 Missing and 2 partials ⚠️
internal/exec/describe_affected.go 0.00% 1 Missing ⚠️
internal/exec/pro.go 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1121      +/-   ##
==========================================
+ Coverage   17.44%   17.87%   +0.42%     
==========================================
  Files         170      172       +2     
  Lines       18764    18933     +169     
==========================================
+ Hits         3274     3384     +110     
- Misses      14892    14948      +56     
- Partials      598      601       +3     
Flag Coverage Δ
unittests 17.87% <66.66%> (+0.42%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Cerebrovinny Cerebrovinny marked this pull request as ready for review March 8, 2025 16:44
@Cerebrovinny Cerebrovinny requested a review from a team as a code owner March 8, 2025 16:44
Copy link
Contributor

coderabbitai bot commented Mar 8, 2025

📝 Walkthrough

Walkthrough

This pull request updates the logger initialization across several components. The CLI argument parsing in both the describe affected and lock/unlock commands now calls an updated logger initialization function that accepts a pointer to the configuration. In addition, the underlying logging mechanism has been revamped with a new Charmbracelet-based logger package, enhancements for custom log file handling, and comprehensive tests for the new functionality. A new constant for standard file permissions and a dedicated test suite for logging functions have also been added.

Changes

File(s) Change Summary
internal/exec/describe_affected.go
internal/exec/pro.go
pkg/pro/api_client_test.go
Updated logger initialization calls from NewLoggerFromCliConfig/NewLogger to InitializeLoggerFromCliConfig/InitializeLogger (passing pointer to configuration), preserving error handling and control flow.
pkg/logger/logger.go
pkg/logger/logger_test.go
Renamed constructor functions and updated method signatures from NewLogger/NewLoggerFromCliConfig to InitializeLogger/InitializeLoggerFromCliConfig; added a new charm logger field and functions for custom log file handling.
pkg/logger/charmbracelet.go
pkg/logger/charmbracelet_test.go
Introduced a new logger package utilizing the Charmbracelet library with Atmos styling, including functions for obtaining loggers with default or custom outputs, plus associated tests for log styling and output.
pkg/config/const.go Added a new constant StandardFilePermissions with the value 0o644.
pkg/logger/test_logger.go New file providing a test suite that exercises individual logging methods, the logger struct functionality, and Charmbracelet logger testing with defined constants and a custom error.

Sequence Diagram(s)

sequenceDiagram
    participant CLI as CLI Command
    participant Parser as CLI Parser Function
    participant LoggerInit as InitializeLogger/InitializeLoggerFromCliConfig
    participant Logger as Logger Package
    participant ErrorHandler as Error Handling

    CLI->>Parser: Execute command (e.g., "describe affected")
    Parser->>LoggerInit: Call logger initialization with &config
    LoggerInit->>Logger: Initialize Logger (with Charmbracelet support)
    Logger-->>LoggerInit: Return logger instance or error
    alt Logger initialization fails
        LoggerInit->>ErrorHandler: Return error and empty args
    else Logger initialization succeeds
        LoggerInit->>Parser: Return logger instance
        Parser->>Parser: Continue processing CLI arguments
    end
Loading

Possibly related PRs

Suggested labels

minor

Suggested reviewers

  • aknysh
  • osterman

📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8634014 and a3e053e.

📒 Files selected for processing (4)
  • pkg/logger/charmbracelet.go (1 hunks)
  • pkg/logger/logger.go (6 hunks)
  • pkg/logger/logger_test.go (10 hunks)
  • pkg/logger/test_logger.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/logger/logger.go
🧰 Additional context used
🪛 golangci-lint (1.62.2)
pkg/logger/test_logger.go

19-19: func main is unused

(unused)


30-30: func testIndividualLogFunctions is unused

(unused)


39-39: func testLoggerStruct is unused

(unused)


54-54: func testCharmLogger is unused

(unused)

🪛 GitHub Check: golangci
pkg/logger/test_logger.go

[failure] 19-19: [golangci] pkg/logger/test_logger.go#L19
func main is unused (unused)


[failure] 30-30: [golangci] pkg/logger/test_logger.go#L30
func testIndividualLogFunctions is unused (unused)


[failure] 39-39: [golangci] pkg/logger/test_logger.go#L39
func testLoggerStruct is unused (unused)


[failure] 54-54: [golangci] pkg/logger/test_logger.go#L54
func testCharmLogger is unused (unused)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Summary
🔇 Additional comments (7)
pkg/logger/charmbracelet.go (3)

60-66: Good implementation of the error log styling.

The styling for error logs uses appropriate colors and padding. The error level stands out well with the pink background and white foreground.


105-108: Style consistency for error key values looks good.

The styling for the error key enhances readability with the pink color and bold values.


139-142: Trace implementation handles custom level correctly.

Good implementation of the Trace logging level using the custom TraceLevel constant.

pkg/logger/test_logger.go (1)

8-17: Good definition of constants for log keys.

These constants provide a consistent way to reference log keys throughout the codebase, improving readability and reducing the chance of typos.

pkg/logger/logger_test.go (3)

42-50: Good update to test initialization and verification.

The test correctly verifies the initialization of the logger and now includes verification of the Charmbracelet logger initialization.


52-65: Pointer parameter passed correctly for configuration.

Good update to pass the configuration by reference to match the new function signature.


148-155: Good use of the standardized error variable.

Using the ErrTest variable here instead of creating a new error provides consistency across tests.

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary or @auto-summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @auto-title anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

🧹 Nitpick comments (8)
cmd/root.go (1)

127-154: Comprehensive output configuration with error handling

The log output configuration handles all standard cases as well as custom files. Good error handling with fallback to stderr when file operations fail.

Replace the magic number 0o644 with a named constant to improve code readability:

+// DefaultLogFilePermissions defines standard permissions for log files
+const DefaultLogFilePermissions = 0o644

 func configureLogOutput(logFile string) {
     // ...
-    customFile, err := os.OpenFile(logFile, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0o644)
+    customFile, err := os.OpenFile(logFile, os.O_WRONLY|os.O_APPEND|os.O_CREATE, DefaultLogFilePermissions)
     // ...
 }
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 133-135: cmd/root.go#L133-L135
Added lines #L133 - L135 were not covered by tests


[warning] 137-138: cmd/root.go#L137-L138
Added lines #L137 - L138 were not covered by tests


[warning] 142-147: cmd/root.go#L142-L147
Added lines #L142 - L147 were not covered by tests


[warning] 153-153: cmd/root.go#L153
Added line #L153 was not covered by tests

🪛 GitHub Check: golangci

[failure] 142-142: [golangci] cmd/root.go#L142
add-constant: avoid magic numbers like '0o644', create a named constant for it (revive)

pkg/logger/charmbracelet.go (5)

109-112: Add test coverage for the global Error method.
Coverage tools indicate these lines are not covered. Consider calling logger.Error(...) in a dedicated test to ensure coverage.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 110-111: pkg/logger/charmbracelet.go#L110-L111
Added lines #L110 - L111 were not covered by tests


114-117: Add test coverage for the global Warn method.
Similarly, ensure that Warn is invoked in tests to improve coverage.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 115-116: pkg/logger/charmbracelet.go#L115-L116
Added lines #L115 - L116 were not covered by tests


119-122: Consider verifying Info in tests.
Including a direct test call to logger.Info(...) will strengthen coverage.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 120-121: pkg/logger/charmbracelet.go#L120-L121
Added lines #L120 - L121 were not covered by tests


124-127: Extend coverage for Debug.
Like the others, confirming a debug log call in tests would be beneficial.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 125-126: pkg/logger/charmbracelet.go#L125-L126
Added lines #L125 - L126 were not covered by tests


129-132: Test calls to Fatal for completeness.
Even though it terminates the program, consider a controlled test approach or mocking to verify.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 130-131: pkg/logger/charmbracelet.go#L130-L131
Added lines #L130 - L131 were not covered by tests

examples/quick-start-simple/test_logger.go (1)

21-30: Runnable example is practical but not a standard test.
Since this is in the main function, test coverage tools likely won't track it. If coverage is needed, consider a _test.go approach.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 21-29: examples/quick-start-simple/test_logger.go#L21-L29
Added lines #L21 - L29 were not covered by tests

pkg/logger/logger.go (1)

142-145: Improve coverage by calling Error(err).
Currently, these lines may remain untested. Testing ensures robust error logging.

🛑 Comments failed to post (1)
pkg/logger/logger.go (1)

161-168: 🛠️ Refactor suggestion

Avoid magic number for file permissions.
Use a named constant for 0o644 to improve readability and maintainability.

- f, err := os.OpenFile(file, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0o644)
+ const filePerm = 0o644
+ f, err := os.OpenFile(file, os.O_WRONLY|os.O_APPEND|os.O_CREATE, filePerm)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

// openLogFile opens a log file for writing with appropriate flags.
func openLogFile(file string) (*os.File, error) {
	const filePerm = 0o644
	f, err := os.OpenFile(file, os.O_WRONLY|os.O_APPEND|os.O_CREATE, filePerm)
	if err != nil {
		return nil, fmt.Errorf("failed to open log file: %w", err)
	}
	return f, nil
}
🧰 Tools
🪛 golangci-lint (1.62.2)

[warning] 163-163: add-constant: avoid magic numbers like '0o644', create a named constant for it

(revive)

🪛 GitHub Check: codecov/patch

[warning] 165-166: pkg/logger/logger.go#L165-L166
Added lines #L165 - L166 were not covered by tests

🪛 GitHub Check: golangci

[failure] 163-163: [golangci] pkg/logger/logger.go#L163
add-constant: avoid magic numbers like '0o644', create a named constant for it (revive)

@github-actions github-actions bot added size/l and removed size/m labels Mar 8, 2025
coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 8, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
cmd/root.go (3)

91-106: Well-structured logger initialization.

The setupLogger function cleanly separates logger initialization logic from the main execution flow, with good error handling that defaults to stderr and info level when initialization fails.

However, consider if the atmosLogger variable has other properties that might be useful beyond just extracting the LogLevel.


108-124: Good log level mapping implementation.

The function handles all log levels appropriately with a sensible default fallback to InfoLevel.

Note that for LogLevelOff, using log.FatalLevel + 1 works but depends on internal implementation details of the Charmbracelet library. Consider if there's a more explicit way to disable logging that would be more resilient to library changes.


126-154: Comprehensive log output configuration.

The function handles all standard output destinations and custom log files with proper error handling and permissions.

The comments about file descriptor management are helpful. For production environments with long-running applications, consider adding log rotation capabilities to prevent log files from growing indefinitely.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fdfb3bb and f8ce952.

📒 Files selected for processing (1)
  • cmd/root.go (4 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Summary
🔇 Additional comments (3)
cmd/root.go (3)

18-19: Clean import declarations for logger module.

The imports are properly organized and include the necessary packages for the refactored logger functionality.


61-66: Improved error handling.

The code now uses errors.Is(err, config.NotFound) instead of type assertion, which is more reliable. The warning message also uses structured logging for better readability.


199-201: Consistent configuration initialization.

The error handling approach is consistent with other changes in the file, using errors.Is for more reliable error type checking.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
cmd/root.go (2)

63-69: Consider simplifying the error handling logic.

The current error handling structure can be simplified for better readability.

-	if errors.Is(err, config.NotFound) {
-		// For help commands or when help flag is set, we don't want to show the error
-		if !isHelpRequested {
-			log.Warn("CLI configuration issue", "error", err)
-		}
-	} else {
-		log.Fatal("CLI configuration error", "error", err)
-	}
+	// For help commands or when help flag is set, we don't want to show the error
+	if !errors.Is(err, config.NotFound) {
+		log.Fatal("CLI configuration error", "error", err)
+	} else if !isHelpRequested {
+		log.Warn("CLI configuration issue", "error", err)
+	}
🧰 Tools
🪛 GitHub Check: golangci

[failure] 63-63: [golangci] cmd/root.go#L63
early-return: if c { ... } else { ... log.Fatal() } can be simplified to if !c { ... log.Fatal() } ... (revive)


[failure] 69-69: [golangci] cmd/root.go#L69
deep-exit: calls to log.Fatal only in main() or init() functions (revive)


69-69: Avoid log.Fatal outside main() or init() functions.

Using log.Fatal in non-main/init functions can make testing difficult as it terminates the program immediately.

Consider propagating the error back to the caller instead and handle the termination at a higher level.

🧰 Tools
🪛 GitHub Check: golangci

[failure] 69-69: [golangci] cmd/root.go#L69
deep-exit: calls to log.Fatal only in main() or init() functions (revive)

pkg/logger/logger.go (1)

161-163: Add period to comment and consider moving constant.

The comment for FilePermDefault should end with a period as noted by the static analysis.

-// FilePermDefault is the default permission for log files (0644 in octal) TODO: refactor this later
+// FilePermDefault is the default permission for log files (0644 in octal). TODO: refactor this later.

Also, consider moving this constant to a more appropriate location if it might be used elsewhere in the codebase.

🧰 Tools
🪛 GitHub Check: golangci

[failure] 161-161: [golangci] pkg/logger/logger.go#L161
Comment should end in a period (godot)

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f8ce952 and 3abe383.

📒 Files selected for processing (2)
  • cmd/root.go (4 hunks)
  • pkg/logger/logger.go (6 hunks)
🧰 Additional context used
🪛 GitHub Check: golangci
cmd/root.go

[failure] 63-63: [golangci] cmd/root.go#L63
early-return: if c { ... } else { ... log.Fatal() } can be simplified to if !c { ... log.Fatal() } ... (revive)


[failure] 69-69: [golangci] cmd/root.go#L69
deep-exit: calls to log.Fatal only in main() or init() functions (revive)

pkg/logger/logger.go

[failure] 161-161: [golangci] pkg/logger/logger.go#L161
Comment should end in a period (godot)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Summary
🔇 Additional comments (8)
cmd/root.go (3)

91-106: Well-structured logger setup function.

The new setupLogger function nicely encapsulates the logger initialization logic, with good error handling that defaults to a sensible configuration (Info level on stderr) when initialization fails.


108-124: Good log level mapping implementation.

The mapToCharmLevel function clearly maps internal log levels to Charmbracelet log levels with appropriate fallbacks. The handling of LogLevelTrace mapping to log.DebugLevel with a clear comment about the limitation is particularly good.


126-154: Thorough output configuration with clear comments.

The configureLogOutput function handles all output destinations well, including standard streams and custom files. The comments explaining the need to register files for cleanup are informative.

pkg/logger/logger.go (5)

39-72: Good refactoring of logger initialization.

The renamed InitializeLogger function implements a cleaner approach to logger setup with proper error handling for custom log files.


74-81: Function signature improvement.

Good change to accept a pointer to schema.AtmosConfiguration rather than passing by value, which is more efficient for larger structs.


156-159: Clear helper function for log file determination.

The shouldUseCustomLogFile function makes the code more readable by extracting this logic into a well-named function.


164-171: Good abstraction for file opening.

The openLogFile function properly handles file opening with appropriate flags and error wrapping.


181-208: Consistent logging implementation.

All logging methods now consistently use both the Charmbracelet logger and the original colored output. The special handling for Trace level (which doesn't exist in Charmbracelet) is well implemented.

coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 8, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 2

🧹 Nitpick comments (1)
pkg/logger/logger.go (1)

161-163: Address TODO comment in the code

The code contains a TODO comment about refactoring the FilePermDefault constant. Consider addressing this now to avoid technical debt.

-// FilePermDefault is the default permission for log files (0644 in octal). TODO: refactor this later.
-const FilePermDefault = 0o644
+// FilePermDefault defines standard permission (0644) for log files
+const FilePermDefault = 0o644
🛑 Comments failed to post (2)
cmd/root.go (2)

130-158: 🛠️ Refactor suggestion

File descriptor leakage risk in configureLogOutput

While the comments mention the importance of closing file descriptors, there's no actual cleanup mechanism implemented for the custom log file.

Consider registering the file with a cleanup handler:

// Handle custom log file (anything not a standard stream)
customFile, err := os.OpenFile(logFile, os.O_WRONLY|os.O_APPEND|os.O_CREATE, config.StandardFilePermissions)
if err != nil {
    log.Error("Failed to open log file, using stderr", "error", err)
    log.SetOutput(os.Stderr)
    return
}

+// Register file to be closed at program exit
+utils.RegisterCleanupHandler(func() {
+    if err := customFile.Close(); err != nil {
+        fmt.Fprintf(os.Stderr, "Error closing log file: %v\n", err)
+    }
+})

log.SetOutput(customFile)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

// configureLogOutput sets up the output destination for the global logger.
func configureLogOutput(logFile string) {
	// Handle standard output destinations
	switch logFile {
	case "/dev/stderr":
		log.SetOutput(os.Stderr)
		return
	case "/dev/stdout", "":
		log.SetOutput(os.Stdout)
		return
	case "/dev/null":
		log.SetOutput(io.Discard)
		return
	}

	// Handle custom log file (anything not a standard stream)
	customFile, err := os.OpenFile(logFile, os.O_WRONLY|os.O_APPEND|os.O_CREATE, config.StandardFilePermissions)
	if err != nil {
		log.Error("Failed to open log file, using stderr", "error", err)
		log.SetOutput(os.Stderr)
		return
	}

	// Register file to be closed at program exit
	utils.RegisterCleanupHandler(func() {
		if err := customFile.Close(); err != nil {
			fmt.Fprintf(os.Stderr, "Error closing log file: %v\n", err)
		}
	})

	log.SetOutput(customFile)
}

65-75: ⚠️ Potential issue

Avoid os.Exit outside of main or init functions

The current code calls os.Exit directly within a function, which violates the deep-exit rule. This practice can prevent proper cleanup of resources and make testing harder.

Consider refactoring this to return an error instead:

if errors.Is(err, config.NotFound) {
    // For help commands or when help flag is set, we don't want to show the error
    if !isHelpRequested {
        log.Warn("CLI configuration issue", "error", err)
    }
    return
}

log.Error("CLI configuration error", "error", err)
-os.Exit(1)
+return fmt.Errorf("CLI configuration error: %w", err)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

		if errors.Is(err, config.NotFound) {
			// For help commands or when help flag is set, we don't want to show the error
			if !isHelpRequested {
				log.Warn("CLI configuration issue", "error", err)
			}
			return
		}

		log.Error("CLI configuration error", "error", err)
		return fmt.Errorf("CLI configuration error: %w", err)
🧰 Tools
🪛 GitHub Check: golangci

[failure] 75-75: [golangci] cmd/root.go#L75
deep-exit: calls to os.Exit only in main() or init() functions (revive)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

🧹 Nitpick comments (2)
cmd/root.go (2)

116-132: Refine 'Off' log level handling.
Using 'FatalLevel+1' for 'Off' is clever. Alternatively, consider discarding output to avoid potential confusion.


134-157: Ensure file closure.
You're correct that runtime closes files, but explicitly closing them is tidier. Consider adding a global teardown method for best practice.

🛑 Comments failed to post (1)
cmd/root.go (1)

211-211: 🛠️ Refactor suggestion

Question about repeating InitCliConfig.
You call InitCliConfig again. Evaluate merging with earlier config logic or confirming necessity for double initialization.

@github-actions github-actions bot added size/m and removed size/l labels Mar 9, 2025
coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 9, 2025
coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 9, 2025
@Cerebrovinny Cerebrovinny requested a review from osterman March 9, 2025 12:22
Copy link
Member

@osterman osterman left a comment

Choose a reason for hiding this comment

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

I think the screenshot is misleading because it demonstrates the logger is working, but not in atmos.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 2

🧹 Nitpick comments (1)
pkg/logger/charmbracelet.go (1)

67-73: Consider revising the warning style color combination.

The warning style uses pink background with dark gray foreground, which might not provide enough contrast compared to the error style. Consider using a different background color like yellow or orange to distinguish it more clearly from error messages.

 	styles.Levels[log.WarnLevel] = lipgloss.NewStyle().
 		SetString(warnLevelLabel).
 		Padding(paddingVertical, paddingHorizontal, paddingVertical, paddingHorizontal).
-		Background(lipgloss.Color(theme.ColorPink)).
+		Background(lipgloss.Color(theme.ColorYellow)).
 		Foreground(lipgloss.Color(theme.ColorDarkGray))
🛑 Comments failed to post (2)
pkg/logger/test_logger.go (2)

30-37: ⚠️ Potential issue

Unused test functions should be moved to test files.

These functions are flagged as unused by static analysis. They appear to be demonstration code that should be moved to proper test files or example files.

Consider moving these functions to a file with the _test.go suffix, or convert them to proper examples with the Example prefix and appropriate documentation.

-func testIndividualLogFunctions() {
+func ExampleLoggerFunctions() {
 	Info("This is an info message")
 	Debug("This is a debug message with context", KeyComponent, "station", KeyDuration, "500ms")
 	Warn("This is a warning message", KeyStack, "prod-ue1")
 	Error("Whoops! Something went wrong", KeyError, "kitchen on fire", KeyComponent, "weather")
 
 	time.Sleep(500 * time.Millisecond)
+	// Output:
+	// This is an info message
+	// This is a debug message with context
+	// This is a warning message
+	// Whoops! Something went wrong
 }

Also applies to: 39-52, 54-67

🧰 Tools
🪛 golangci-lint (1.62.2)

30-30: func testIndividualLogFunctions is unused

(unused)

🪛 GitHub Check: golangci

[failure] 30-30: [golangci] pkg/logger/test_logger.go#L30
func testIndividualLogFunctions is unused (unused)


19-28: ⚠️ Potential issue

Remove main function from non-main package.

This file contains a main function but is part of the logger package, not a main package. This will cause build issues and has been flagged by static analysis.

Consider converting this file to a proper example or test file by:

  1. Either renaming it to have the _example.go suffix if it's meant as an example
  2. Or moving the code to a proper test file with the _test.go suffix
-func main() {
-	// Test individual log functions
-	testIndividualLogFunctions()
-
-	// Test complete Logger struct
-	testLoggerStruct()
-
-	// Test direct charmbracelet logger
-	testCharmLogger()
-}
+// Example usage of logger functionality
+// This can be moved to a proper test or example file
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

// Example usage of logger functionality
// This can be moved to a proper test or example file
🧰 Tools
🪛 golangci-lint (1.62.2)

19-19: func main is unused

(unused)

🪛 GitHub Check: golangci

[failure] 19-19: [golangci] pkg/logger/test_logger.go#L19
func main is unused (unused)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants