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 21 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

    • Enjoy an enhanced logging experience with attractive, easy-to-read log displays. The new system offers visually refined log levels and supports customizable output destinations for a more informative monitoring experience.
  • Refactor

    • The logging initialization and error-handling processes have been streamlined for improved consistency and reliability without altering core functionality.

- 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 logger initialization across CLI commands by changing the logger creation call to pass a pointer to the Atmos configuration. Additionally, a new logging package leveraging the Charmbracelet library is introduced with corresponding functions and tests added to support styled logging output. The core logger is updated to integrate Charmbracelet, with added support for custom log files and improved error handling. A new file permission constant and test utilities for logger functionalities are also included.

Changes

File(s) Change Summary
internal/exec/describe_affected.go
internal/exec/pro.go
Updated logger initialization calls: changed from passing atmosConfig by value to passing a pointer (&atmosConfig).
pkg/logger/charmbracelet.go
pkg/logger/charmbracelet_test.go
Introduced a new logger package using the Charmbracelet library with Atmos styling; added pre-configured logging functions (Error, Warn, Info, Debug, Trace, Fatal) and tests.
pkg/logger/logger.go
pkg/logger/logger_test.go
Integrated Charmbracelet logging into the core logger; updated NewLoggerFromCliConfig to accept a pointer; added custom log file handling functions (shouldUseCustomLogFile, openLogFile).
pkg/config/const.go Added new constant StandardFilePermissions with value 0o644.
pkg/logger/test_logger.go Added a test logger file defining custom error ErrTest, constants, and test functions for individual logging methods and logger struct verification.

Sequence Diagram(s)

sequenceDiagram
    participant CLI_Command as CLI Command
    participant LoggerInit as Logger Initialization
    participant Logger as Logger Instance

    CLI_Command->>LoggerInit: Call NewLoggerFromCliConfig(&atmosConfig)
    LoggerInit->>Logger: Create and configure logger (with Charmbracelet)
    Logger-->>LoggerInit: Return logger instance or error
    LoggerInit-->>CLI_Command: Return logger instance or propagate error
    CLI_Command->>Logger: Invoke logger methods (Info, Debug, etc.)
Loading

Possibly related PRs

Suggested labels

minor

Suggested reviewers

  • mcalhoun
  • osterman
  • aknysh

📜 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 a9e4709 and e615ef9.

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

[error] 19-19: func main is unused

(unused)


[error] 30-30: func testIndividualLogFunctions is unused

(unused)


[error] 39-39: func testLoggerStruct is unused

(unused)


[error] 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 (1)
pkg/logger/test_logger.go (1)

8-17: Well-structured constants and error definition.

Good job organizing logging keys as constants. This provides consistent keys across the codebase and makes maintenance easier.

✨ 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)

coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 10, 2025
@github-actions github-actions bot added size/m and removed size/l labels Mar 10, 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 (3)
pkg/schema/schema.go (1)

82-86: Add a period to the YAMLSettings comment.

The YAMLSettings struct is a great addition for controlling YAML output formatting. To adhere to Go conventions, the comment should end with a period.

-// YAMLSettings defines configuration for YAML output formatting
+// YAMLSettings defines configuration for YAML output formatting.
🧰 Tools
🪛 GitHub Check: golangci

[failure] 82-82: [golangci] pkg/schema/schema.go#L82
Comment should end in a period (godot)

internal/exec/file_utils.go (2)

62-77: Good conditional handling for different output scenarios.

The implementation correctly handles both cases with and without configuration, providing appropriate fallbacks.

This block has high complexity according to static analysis. Consider extracting the printing logic to a separate helper function to reduce nesting.

🧰 Tools
🪛 GitHub Check: golangci

[failure] 62-62: [golangci] internal/exec/file_utils.go#L62
if file == "" has complex nested blocks (complexity: 8) (nestif)


38-38: Simplify variable declaration.

The type declaration for actualData is redundant since it can be inferred from the right-hand side.

-	var actualData any = data
+	var actualData = data
🧰 Tools
🪛 GitHub Check: golangci

[failure] 38-38: [golangci] internal/exec/file_utils.go#L38
var-declaration: should omit type any from declaration of var actualData; it will be inferred from the right-hand side (revive)

🛑 Comments failed to post (2)
internal/exec/file_utils.go (1)

80-80: 🛠️ Refactor suggestion

Extract file permission constant.

The magic number 0o644 for file permissions should be extracted to a named constant.

-			err := u.WriteToFileAsYAML(file, actualData, 0o644)
+			const DefaultFilePermissions = 0o644
+			err := u.WriteToFileAsYAML(file, actualData, DefaultFilePermissions)

Consider adding this constant at the package level for reuse with other file operations.

📝 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.

			const DefaultFilePermissions = 0o644
			err := u.WriteToFileAsYAML(file, actualData, DefaultFilePermissions)
🧰 Tools
🪛 GitHub Check: golangci

[failure] 80-80: [golangci] internal/exec/file_utils.go#L80
add-constant: avoid magic numbers like '0o644', create a named constant for it (revive)

pkg/utils/yaml_utils.go (1)

69-89: 🛠️ Refactor suggestion

Optimize large parameter passing.

The function accepts a large struct by value, which can impact performance.

-func PrintAsYAMLToFileDescriptor(atmosConfig schema.AtmosConfiguration, data any) error {
+func PrintAsYAMLToFileDescriptor(atmosConfig *schema.AtmosConfiguration, data any) error {
-	indent := GetYAMLIndent(&atmosConfig)
+	indent := GetYAMLIndent(atmosConfig)

-	highlighted, err := HighlightCodeWithConfig(y, atmosConfig, "yaml")
+	highlighted, err := HighlightCodeWithConfig(y, *atmosConfig, "yaml")

Also update any call sites to pass a pointer instead of the value.

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 GitHub Check: golangci

[failure] 70-70: [golangci] pkg/utils/yaml_utils.go#L70
hugeParam: atmosConfig is heavy (5776 bytes); consider passing it by pointer (gocritic)

@@ -114,7 +114,7 @@ func TestUnlockStack(t *testing.T) {
}

func TestUnlockStack_Error(t *testing.T) {
mockLogger, err := logger.NewLogger("test", "/dev/stdout")
mockLogger, err := logger.InitializeLogger("test", "/dev/stdout")
Copy link
Member

Choose a reason for hiding this comment

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

Use /dev/stderr for logs. Not that it matters here, what happened to us was for a example atmos configuration we used /dev/stdout, that got copied over and over again so that it became the default but it was always wrong. So everywhere update this to stderr.

// configureLogLevelStyles configures the styles for different log levels.
func configureLogLevelStyles(styles *log.Styles, paddingVertical, paddingHorizontal int) {
const (
errorLevelLabel = "ERROR"
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
errorLevelLabel = "ERROR"
errorLevelLabel = "ERRO"

helperLogger = GetCharmLogger()
}

// GetCharmLogger returns a pre-configured Charmbracelet logger with Atmos styling.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// GetCharmLogger returns a pre-configured Charmbracelet logger with Atmos styling.
// GetAtmosLogger returns a pre-configured Charmbracelet logger with Atmos styling.

assert.NotNil(t, styles.Keys["stack"], "stack key should have styling")
}

func ExampleGetCharmLogger() {
Copy link
Member

Choose a reason for hiding this comment

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

Where is this used?

@@ -20,7 +21,7 @@ const (
LogLevelWarning LogLevel = "Warning"
)

Copy link
Member

Choose a reason for hiding this comment

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

Note, why don't we have LogLevelError above?


// Set log level
charmLevel := log.InfoLevel
switch logLevel {
Copy link
Member

Choose a reason for hiding this comment

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

No log level error?

}, nil
}

func NewLoggerFromCliConfig(cfg schema.AtmosConfiguration) (*Logger, error) {
// InitializeLoggerFromCliConfig creates a logger based on Atmos CLI configuration.
func InitializeLoggerFromCliConfig(cfg *schema.AtmosConfiguration) (*Logger, error) {
Copy link
Member

Choose a reason for hiding this comment

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

The NewX naming convention is the standard way to create and return a new instance of a type.

}

func NewLogger(logLevel LogLevel, file string) (*Logger, error) {
func InitializeLogger(logLevel LogLevel, file string) (*Logger, error) {
Copy link
Member

Choose a reason for hiding this comment

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

The NewX naming convention is the standard way to create and return a new instance of a type.

Copy link
Member

Choose a reason for hiding this comment

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

I guess i'm confused now between this and the functions above that were called GetX but should also have been NewX and these here, without investing too much mental effort.

Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <[email protected]>
coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 10, 2025
Co-authored-by: Erik Osterman (CEO @ Cloud Posse) <[email protected]>
coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 10, 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 (11)
pkg/logger/charmbracelet.go (11)

11-11: Consider documenting the custom TraceLevel constant.

The TraceLevel constant is defined but lacks documentation that explains its purpose and relationship to standard log levels.

+// TraceLevel is a custom log level below DebugLevel for more granular tracing information.
 const TraceLevel log.Level = log.DebugLevel - 1

13-17: Consider making the helper logger configurable after initialization.

The global logger is initialized at package level with fixed configuration. Consider adding a way to update it after initialization for more flexibility in testing or different runtime environments.

 var helperLogger *log.Logger
 
 func init() {
 	helperLogger = GetCharmLogger()
 }
+
+// SetHelperLogger allows replacing the default helper logger with a custom configured one.
+func SetHelperLogger(logger *log.Logger) {
+	helperLogger = logger
+}

35-36: Improve documentation for clarity.

The function documentation should be a complete sentence for consistency.

-// getAtmosLogStyles returns custom styles for the Charmbracelet logger using Atmos theme colors.
+// getAtmosLogStyles returns custom styles for the Charmbracelet logger using Atmos theme colors.

50-51: Update function documentation to complete sentence.

For consistency with standard Golang documentation practices.

-// configureLogLevelStyles configures the styles for different log levels.
+// configureLogLevelStyles configures the styles for different log levels.

96-97: Update function documentation to complete sentence.

For consistency with Golang documentation standards.

-// configureKeyStyles configures the styles for different log keys.
+// configureKeyStyles configures the styles for different log keys.

105-105: Inconsistent comment compared to other similar comments.

The comment doesn't match the format of other key style comments. Also, there's a discrepancy between 'err' in the comment and 'error' in the code.

-// Custom style for 'err' key
+// Custom style for 'error' key.

109-109: Update comment format to use complete sentences.

For consistency with Golang documentation standards.

-// Custom style for 'component' key
+// Custom style for 'component' key.

112-112: Update comment format to use complete sentences.

For consistency with Golang documentation standards.

-// Custom style for 'stack' key
+// Custom style for 'stack' key.

115-115: Update comment format to use complete sentences.

For consistency with Golang documentation standards.

-// Custom style for 'duration' key
+// Custom style for 'duration' key.

119-122: Add a log level parameter to the helper functions.

Consider adding an optional log level parameter to these helper functions, allowing for more flexibility when logging.

 // Error logs an error message with context.
 func Error(message string, keyvals ...interface{}) {
 	helperLogger.Error(message, keyvals...)
 }

144-147: Document that Fatal exits the program.

The Fatal function documentation should explicitly mention that it terminates the program with exit code 1, as this is a critical behavior.

-// Fatal logs an error message and exits with status code 1.
+// Fatal logs an error message and exits the program with status code 1.
 func Fatal(message string, keyvals ...interface{}) {
 	helperLogger.Fatal(message, keyvals...)
 }
🛑 Comments failed to post (2)
pkg/logger/charmbracelet.go (2)

15-25: 💡 Verification agent

🧩 Analysis chain

Update helperLogger initialization to use new function name.

If you rename GetCharmLogger to NewAtmosLogger, don't forget to update the initialization in the init function as well.


🏁 Script executed:

#!/bin/bash
# Check for other references to GetCharmLogger that would need updating
grep -r "GetCharmLogger" --include="*.go" .

Length of output: 1105


Action Required: Update function name consistently

The initialization in pkg/logger/charmbracelet.go is still calling GetCharmLogger(). If you’ve renamed this function to NewAtmosLogger(), please update the call in the init function accordingly. Also, review and update all related references (including in documentation comments and tests such as in pkg/logger/charmbracelet_test.go, pkg/logger/logger.go, and pkg/logger/test_logger.go) to ensure consistency across the codebase.


139-142: 💡 Verification agent

🧩 Analysis chain

Consider using a custom level constant in the logger initialization.

The Trace function calls Log with TraceLevel, but the logger isn't explicitly configured to handle this custom level. Consider registering the custom level with the logger at initialization.


🏁 Script executed:

#!/bin/bash
# Check if the Charmbracelet log package supports registering custom levels
cat << EOF > /tmp/check_custom_level.go
package main

import (
	"fmt"
	"os"
	
	log "github.com/charmbracelet/log"
)

const CustomLevel log.Level = log.DebugLevel - 1

func main() {
	logger := log.New(os.Stdout)
	
	// Check if there's a method to register custom levels
	fmt.Println("Checking for methods to register custom log levels:")
	// This is just a simulation as we can't actually reflect on the methods
	fmt.Println("Available methods (simulated):", "SetLevel, SetReportCaller, SetReportTimestamp, SetStyles")
	
	logger.Log(CustomLevel, "This is a custom level message")
	fmt.Println("Does the message appear with the correct level indicator?")
}
EOF

go mod init checklogger
go get github.com/charmbracelet/log
go run /tmp/check_custom_level.go

Length of output: 1601


Action Required: Explicitly Register the Custom Trace Level

While the Trace function logs messages using TraceLevel, the logger's initialization isn’t currently set up to recognize this custom level. Our verification confirms that the Charmbracelet log package exposes configuration methods (such as SetStyles) but does not automatically handle custom levels. To ensure that trace logs are rendered with the proper style and behavior, please update the logger initialization to explicitly register or configure TraceLevel.

  • File: pkg/logger/charmbracelet.go (lines 139–142)
  • Suggestion: In the logger’s setup, map or register TraceLevel using the available configuration methods (e.g., SetStyles) so that the custom level is recognized and applied correctly.

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: 5

🔭 Outside diff range comments (1)
pkg/logger/test_logger.go (1)

1-68: 🛠️ Refactor suggestion

Review overall file purpose and implementation.

This file combines a number of test functions but isn't structured as a proper Go test file. It appears to be a manual test utility rather than an automated test. Consider:

  1. Renaming the file to logger_test.go if it's meant to be a test file
  2. Converting all functions to proper Go test functions (func TestXxx(t *testing.T))
  3. Adding assertions to verify the expected behavior instead of just executing functions
  4. Removing sleep calls which slow down tests unnecessarily

This approach will make the tests more reliable, automatically runnable with the Go test command, and more maintainable.

🧰 Tools
🪛 golangci-lint (1.62.2)

[error] 19-19: func main is unused

(unused)


[error] 30-30: func testIndividualLogFunctions is unused

(unused)


[error] 39-39: func testLoggerStruct is unused

(unused)


[error] 54-54: func testCharmLogger is unused

(unused)

🪛 GitHub Check: golangci

[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)

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

1-7: 🛠️ Refactor suggestion

Add proper imports for Go testing.

Since this file appears to be for testing, you should add the testing package import.

 package logger
 
 import (
 	"errors"
 	"time"
+	"testing"
 )
📝 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.

package logger

import (
	"errors"
	"time"
	"testing"
)

54-67: ⚠️ Potential issue

Convert to proper Go test function.

This function is unused and should be converted to a standard Go test function.

-func testCharmLogger() {
+func TestCharmLogger(t *testing.T) {
 	charmLogger := GetCharmLogger()
 
 	charmLogger.SetTimeFormat(time.Kitchen)
 
 	charmLogger.Info("Processing component", KeyComponent, "station", KeyStack, "dev-ue1")
 	charmLogger.Debug("Found configuration", KeyPath, "/stacks/deploy/us-east-1/dev/station.yaml")
 	charmLogger.Warn("Component configuration outdated", KeyComponent, "weather", "lastUpdated", "90 days ago")
 	charmLogger.Error("Failed to apply changes",
 		KeyError, "validation failed",
 		KeyComponent, "weather",
 		KeyDetails, "required variables missing",
 		KeyStack, "dev-ue1")
 }
📝 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.

func TestCharmLogger(t *testing.T) {
	charmLogger := GetCharmLogger()

	charmLogger.SetTimeFormat(time.Kitchen)

	charmLogger.Info("Processing component", KeyComponent, "station", KeyStack, "dev-ue1")
	charmLogger.Debug("Found configuration", KeyPath, "/stacks/deploy/us-east-1/dev/station.yaml")
	charmLogger.Warn("Component configuration outdated", KeyComponent, "weather", "lastUpdated", "90 days ago")
	charmLogger.Error("Failed to apply changes",
		KeyError, "validation failed",
		KeyComponent, "weather",
		KeyDetails, "required variables missing",
		KeyStack, "dev-ue1")
}
🧰 Tools
🪛 golangci-lint (1.62.2)

[error] 54-54: func testCharmLogger is unused

(unused)

🪛 GitHub Check: golangci

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


19-28: ⚠️ Potential issue

Remove unused main function from package.

The main function can't be executed in a non-main package. This appears to be a manual test runner, but Go has a built-in testing framework that should be used instead.

-func main() {
-	// Test individual log functions
-	testIndividualLogFunctions()
-
-	// Test complete Logger struct
-	testLoggerStruct()
-
-	// Test direct charmbracelet logger
-	testCharmLogger()
-}

If you need to test these functions, convert them to proper Go tests or create an example package.

📝 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.


🧰 Tools
🪛 golangci-lint (1.62.2)

[error] 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)


39-52: ⚠️ Potential issue

Convert to proper Go test function and improve error handling.

This function should follow Go's testing conventions and needs better error handling.

-func testLoggerStruct() {
+func TestLoggerStruct(t *testing.T) {
 	atmosLogger, err := NewLogger(LogLevelTrace, "")
 	if err != nil {
-		panic(err)
+		t.Fatalf("Failed to create logger: %v", err)
 	}
 
 	atmosLogger.Trace("This is a trace message")
 	atmosLogger.Debug("This is a debug message")
 	atmosLogger.Info("This is an info message")
 	atmosLogger.Warning("This is a warning message")
 	atmosLogger.Error(ErrTest)
-
-	time.Sleep(500 * time.Millisecond)
 }
📝 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.

func TestLoggerStruct(t *testing.T) {
	atmosLogger, err := NewLogger(LogLevelTrace, "")
	if err != nil {
		t.Fatalf("Failed to create logger: %v", err)
	}

	atmosLogger.Trace("This is a trace message")
	atmosLogger.Debug("This is a debug message")
	atmosLogger.Info("This is an info message")
	atmosLogger.Warning("This is a warning message")
	atmosLogger.Error(ErrTest)
}
🧰 Tools
🪛 golangci-lint (1.62.2)

[error] 39-39: func testLoggerStruct is unused

(unused)

🪛 GitHub Check: golangci

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


30-37: ⚠️ Potential issue

Convert to proper Go test function.

This function is flagged as unused. Convert it to a standard Go test function to make it part of the test suite.

-func testIndividualLogFunctions() {
+func TestIndividualLogFunctions(t *testing.T) {
 	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)
+	// Remove sleep as it slows down tests unnecessarily
 }

Don't forget to import the testing package at the top of the 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.

package logger

import (
	"testing"
	"time" // assuming time is used elsewhere in the file; remove if not needed
)

func TestIndividualLogFunctions(t *testing.T) {
	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")

	// Remove sleep as it slows down tests unnecessarily
}
🧰 Tools
🪛 golangci-lint (1.62.2)

[error] 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)

// isLevelEnabled checks if a given log level should be enabled based on the logger's current level
// shouldUseCustomLogFile returns true if a custom log file should be used instead of standard streams.
func shouldUseCustomLogFile(file string) bool {
return file != "" && file != "/dev/stdout" && file != "/dev/stderr"
Copy link
Member

Choose a reason for hiding this comment

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

What about /dev/null?

@@ -46,6 +45,8 @@ func TestNewLogger(t *testing.T) {
assert.NotNil(t, logger)
assert.Equal(t, LogLevelDebug, logger.LogLevel)
assert.Equal(t, "/dev/stdout", logger.File)
Copy link
Member

@osterman osterman Mar 10, 2025

Choose a reason for hiding this comment

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

Actually, let's add a warning somewhere in our code if using /dev/stdout because that will break downstream tools like our github actions. And recommend using /dev/stderr

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