Thanks to visit codestin.com
Credit goes to github.com

Skip to content

feat: Honor FORCE_COLOR for logging#10139

Open
gbadedata wants to merge 1 commit into
meltano:mainfrom
gbadedata:fix-honor-force-color-for-logging
Open

feat: Honor FORCE_COLOR for logging#10139
gbadedata wants to merge 1 commit into
meltano:mainfrom
gbadedata:fix-honor-force-color-for-logging

Conversation

@gbadedata

@gbadedata gbadedata commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #10118.

This updates Meltano’s generated default logging configuration to honor FORCE_COLOR when deciding whether to emit colored log output.

The change keeps the existing precedence:

  • NO_COLOR still disables colors.
  • TTY detection still controls colors by default.
  • FORCE_COLOR enables colored logging when stderr is not a TTY.
  • Non-colored log formats remain unchanged.

Details

The colored logging path now enables colors when either stderr is attached to a TTY or FORCE_COLOR is truthy:

colors = (
    sys.stderr.isatty() or get_boolean_env_var("FORCE_COLOR")
) and not get_no_color_flag()

This preserves NO_COLOR precedence because the final condition still requires not get_no_color_flag().

The existing colored-non-tty-force-color test case already described the intended behavior and was marked xfail because FORCE_COLOR was not honored. This PR implements that behavior and removes the xfail.

Tests

uv run pytest tests/meltano/core/logging/test_logging_utils.py::test_default_logging_config_format

uv run pytest \
  tests/meltano/core/logging/test_logging_utils.py \
  tests/meltano/core/logging/test_formatters.py \
  tests/meltano/core/logging/test_renderers.py \
  tests/meltano/cli/test_cli.py::TestCliColors \
  tests/meltano/cli/test_run.py::TestCliRunScratchpadOne::test_color_console_exception_handler

uv run --with ruff ruff check src/meltano/core/logging/utils.py tests/meltano/core/logging/test_logging_utils.py
uv run --with ruff ruff format --check src/meltano/core/logging/utils.py tests/meltano/core/logging/test_logging_utils.py
GIT_PAGER=cat git diff --check

Results:

  • test_default_logging_config_format: 7 passed
  • Wider relevant logging/CLI test set: 61 passed
  • Ruff check passed
  • Ruff format check passed
  • git diff --check passed

Summary by Sourcery

Honor the FORCE_COLOR environment variable in default logging configuration so colored logs can be enabled even when stderr is not a TTY, while preserving NO_COLOR precedence.

Bug Fixes:

  • Ensure colored logging is correctly enabled when FORCE_COLOR is set in non-TTY environments.

Tests:

  • Update logging configuration tests to reflect FORCE_COLOR behavior and remove the previous expected failure for the colored non-tty FORCE_COLOR case.

@netlify

netlify Bot commented Jul 4, 2026

Copy link
Copy Markdown

Deploy Preview for docs-meltano ready!

Name Link
🔨 Latest commit e57026d
🔍 Latest deploy log https://app.netlify.com/projects/docs-meltano/deploys/6a48d7100a7c96000846f344
😎 Deploy Preview https://deploy-preview-10139--docs-meltano.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@sourcery-ai

sourcery-ai Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Update default logging configuration to honor the FORCE_COLOR environment variable for colored logging while preserving NO_COLOR precedence and existing TTY-based behavior, and align tests with the new behavior by removing an xfail marker.

Flow diagram for colored logging decision with FORCE_COLOR

flowchart TD
    A["stderr_is_tty = sys.stderr.isatty()"] --> C
    B["force_color = get_boolean_env_var(FORCE_COLOR)"] --> C
    D["no_color = get_no_color_flag()"] --> E
    C["tty_or_force = stderr_is_tty OR force_color"] --> E
    E["colors = tty_or_force AND NOT no_color"] --> F["Emit colored log output"]
    E --> G["Emit non-colored log output"]
Loading

File-Level Changes

Change Details Files
Honor FORCE_COLOR when deciding whether to enable colored logging output while preserving NO_COLOR precedence and TTY-based defaults.
  • Import generic boolean environment variable helper used to read FORCE_COLOR.
  • Change the colored log-format path to enable colors when stderr is a TTY or FORCE_COLOR is truthy, still disabling colors when NO_COLOR is set.
  • Ensure terminal detection runs before any stream capture as before, keeping behavior consistent except for FORCE_COLOR support.
src/meltano/core/logging/utils.py
Align logging tests with new FORCE_COLOR behavior by turning a previously expected failure into a normal passing case.
  • Remove xfail mark and associated reason from the colored-non-tty-force-color parametrized test case, since FORCE_COLOR is now honored.
  • Keep the test case inputs and expected output intact to validate the new behavior under non-TTY with FORCE_COLOR enabled.
tests/meltano/core/logging/test_logging_utils.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • Consider avoiding the hard-coded "FORCE_COLOR" string in default_config by centralizing it as a constant or reusing an existing helper, so changes to the env var name only need to happen in one place.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Consider avoiding the hard-coded "FORCE_COLOR" string in `default_config` by centralizing it as a constant or reusing an existing helper, so changes to the env var name only need to happen in one place.

## Individual Comments

### Comment 1
<location path="tests/meltano/core/logging/test_logging_utils.py" line_range="74" />
<code_context>
             False,
             "\x1b[2m2021-01-01T00:00:00Z\x1b[0m [\x1b[32minfo     \x1b[0m] \x1b[36mmeltano     \x1b[0m \x1b[1mtest                          \x1b[0m",  # noqa: E501
             id="colored-non-tty-force-color",
-            marks=(
-                pytest.mark.xfail(
</code_context>
<issue_to_address>
**suggestion (testing):** Add an explicit test case for `FORCE_COLOR` + `NO_COLOR` precedence

With `colored-non-tty-force-color` now enabled, please also add a test that sets both `FORCE_COLOR` and `NO_COLOR` and asserts that colors are disabled. This will encode the intended precedence and guard against regressions where `FORCE_COLOR` incorrectly wins over `NO_COLOR`.

Suggested implementation:

```python
            False,
            "\x1b[2m2021-01-01T00:00:00Z\x1b[0m [\x1b[32minfo     \x1b[0m] \x1b[36mmeltano     \x1b[0m \x1b[1mtest                          \x1b[0m",  # noqa: E501
            id="colored-non-tty-force-color",
        ),
        pytest.param(
            LogFormat.uncolored,
            False,
            "2021-01-01T00:00:00Z [info     ] meltano     test                          ",
            id="uncolored-non-tty-force-and-no-color",
        ),
        pytest.param(
            LogFormat.uncolored,

```

To fully implement the precedence test, you should:
1. Ensure this new `pytest.param` is included in the same parametrized test that configures environment variables. Mirror the pattern used by other cases (e.g., existing `NO_COLOR` or `FORCE_COLOR` cases) to set both `FORCE_COLOR` and `NO_COLOR` for this `id="uncolored-non-tty-force-and-no-color"` case.
2. If environment setup is driven by parametrized marks (like `marks=pytest.mark.parametrize` or custom marks that inject `env`), add the appropriate mark so that `FORCE_COLOR` and `NO_COLOR` are both set in the environment for this case, and verify that the logging output matches the uncolored string above.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread tests/meltano/core/logging/test_logging_utils.py
@codspeed-hq

codspeed-hq Bot commented Jul 4, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 4 untouched benchmarks


Comparing gbadedata:fix-honor-force-color-for-logging (e57026d) with main (e428ef1)

Open in CodSpeed

@codecov

codecov Bot commented Jul 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.79%. Comparing base (e428ef1) to head (e57026d).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main   #10139   +/-   ##
=======================================
  Coverage   96.79%   96.79%           
=======================================
  Files         286      286           
  Lines       25960    25962    +2     
  Branches     1493     1493           
=======================================
+ Hits        25127    25129    +2     
  Misses        671      671           
  Partials      162      162           

☔ View full report in Codecov by Harness.
📢 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.

@gbadedata gbadedata force-pushed the fix-honor-force-color-for-logging branch from 82e9a6a to bf6a13a Compare July 4, 2026 09:34
@gbadedata gbadedata force-pushed the fix-honor-force-color-for-logging branch from bf6a13a to e57026d Compare July 4, 2026 09:49
@gbadedata

Copy link
Copy Markdown
Contributor Author

I pushed an amended commit to isolate the existing CLI color tests from any ambient FORCE_COLOR value in CI. Since this PR intentionally makes FORCE_COLOR affect default logging colors, the older NO_COLOR-focused CLI test cases now explicitly clear FORCE_COLOR before asserting non-TTY behavior.

@gbadedata

gbadedata commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

The two remaining failed checks appear to be unrelated tracking/Snowplow tests rather than the logging color path changed by this PR:

  • tests/meltano/core/tracking/test_tracker.py::TestTracker::test_exit_event_is_fired
  • tests/meltano/core/tracking/test_project_context.py::test_environment_name_hash[default-no-env]

The logging-related tests touched by this PR are passing locally, including the FORCE_COLOR and NO_COLOR precedence cases. Could @edgarrmondragon please rerun the failed jobs it seems I am not able to rerun those two?

@edgarrmondragon edgarrmondragon added the Logging Logging & Monitoring with Meltano label Jul 7, 2026
@edgarrmondragon edgarrmondragon changed the title fix: honor FORCE_COLOR for logging feat: Honor FORCE_COLOR for logging Jul 7, 2026
@edgarrmondragon edgarrmondragon self-assigned this Jul 7, 2026
@edgarrmondragon edgarrmondragon added this to the v4.3 milestone Jul 7, 2026

@edgarrmondragon edgarrmondragon left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks @gbadedata!

We should mention FORCE_COLOR support in https://deploy-preview-10139--docs-meltano.netlify.app/reference/command-line-interface, and clarify the precedence between it and NO_COLOR.

Also, an admonition block explaining that this was added in Meltano v4.3.0:

:::tip
  `FORCE_COLOR` support was added in v4.3.0
:::

that way readers are not left wondering why it doesn't work if they read this before we publish it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Logging Logging & Monitoring with Meltano

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants