Skip to content

fix(mcp): set Datadog log status from JSON levels and quiet noisy hosted loggers - #1357

Merged
Caleb Evans (calebevans-ab) merged 2 commits into
release-candidate/v1from
devin/1791620431-mcp-json-log-levels
Oct 10, 2026
Merged

Caleb Evans (calebevans-ab) merged 2 commits into
release-candidate/v1from
devin/1791620431-mcp-json-log-levels

Conversation

@calebevans-ab

@calebevans-ab Caleb Evans (calebevans-ab) commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

TL;DR: In Datadog, cloud-mcp's hosted JSON logs all show as info, and some come through twice. This PR adds levelname to every JSON log line so Datadog reads the real level, routes ddtrace's logs through the root JSON handler so they're no longer duplicated, and quiets three noisy log sources in JSON mode only.

Summary

  • Status: our org's Datadog source:python pipeline takes the status from levelname, not severity. A direct Logs API test with three otherwise identical lines gave:

    • severity: ERROR → info
    • level: ERROR → info
    • levelname: ERROR → error

    _add_severity now writes both fields. Cloud Logging keeps reading severity.

    event_dict["levelname"] = levelname
    event_dict["severity"] = levelname
  • Duplicates: ddtrace installs its own stderr StreamHandler, so about 960 of the ~1,020 error lines a day were a second, raw copy of a ddtrace warning. ddtrace joins _SELF_HANDLED_LOGGERS, so the JSON setup clears that handler and lets ddtrace's records go through the root JSON handler.

    • The cleanup lives in apply_json_logger_overrides(). configure_logging("json") calls it, and main() calls it again after install(app), because importing ddtrace lazily (a start without ddtrace-run) reinstalls its handler. The hosted image starts with ddtrace-run, so prod already imports ddtrace first.
  • Noise (JSON mode only; text mode is unchanged):

    Source Change Lines it emits today
    mcp.server.streamable_http level WARNING Terminating session: None, about 7,700 lines a day
    ddtrace.contrib.internal.grpc.aio_client_interceptor level ERROR gRPC status parse warnings
    ddtrace.llmobs._llmobs filter drops only Failed to extract trace/span ID from request headers. Missing trace/span header warnings

    The LLMObs logger keeps its level, so warnings that matter (e.g. Failed to flush LLMObs spans and evaluation metrics.) still show up.

  • Heads-up for monitors: once this ships, Datadog will show about 900 real error lines a day for cloud-mcp. Most are fastmcp's Error calling tool ..., which fastmcp logs at ERROR for every tool failure, caller mistakes included. Any monitor on cloud-mcp error logs will start counting them.

  • Tests in tests/unit_tests/test_mcp_logging.py:

    • levelname == severity on the WARNING and ERROR JSON lines;
    • after JSON setup, the ddtrace logger has no handlers and propagates;
    • main() removes a ddtrace handler that install re-adds;
    • the LLMObs filter drops only the missing-header warning, isn't added twice, and isn't added in text mode;
    • the quiet levels apply in JSON mode and leave text mode alone.

    The restore_logging fixture restores the handlers, level, propagation and filters of every logger it touches.

Link to Devin session: https://app.devin.ai/sessions/85c491e543a74ab89151fdf7a0ba5d20
Open in Devin Desktop: https://app.devin.ai/desktop/session/85c491e543a74ab89151fdf7a0ba5d20?variant=devin
Requested by: Caleb Evans (@calebevans-ab)

@devin-ai-integration

Copy link
Copy Markdown
Contributor

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

@octavia-bot
octavia-bot Bot marked this pull request as draft October 10, 2026 08:51
@octavia-bot

octavia-bot Bot commented Oct 10, 2026

Copy link
Copy Markdown

Note

📝 PR Converted to Draft

More info...

Thank you for creating this PR. As a policy to protect our engineers' time, Airbyte requires all PRs to be created first in draft status. Your PR has been automatically converted to draft status in respect for this policy.

As soon as your PR is ready for formal review, you can proceed to convert the PR to "ready for review" status by clicking the "Ready for review" button at the bottom of the PR page.

To skip draft status in future PRs, please include [ready] in your PR title or add the skip-draft-status label when creating your PR.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-10T09:41:12.571938Z 42166c1 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

Copy link
Copy Markdown

👋 Greetings, Airbyte Team Member!

Here are some helpful tips and reminders for your convenience.

💡 Show Tips and Tricks

Testing This PyAirbyte Version

You can test this version of PyAirbyte using the following:

# Run PyAirbyte CLI from this branch:
uvx --from 'git+https://github.com/airbytehq/PyAirbyte.git@devin/1791620431-mcp-json-log-levels' pyairbyte --help

# Install PyAirbyte from this branch for development:
pip install 'git+https://github.com/airbytehq/PyAirbyte.git@devin/1791620431-mcp-json-log-levels'

PR Slash Commands

Airbyte Maintainers can execute the following slash commands on your PR:

  • /fix-pr - Fixes most formatting and linting issues
  • /uv-lock - Updates uv.lock file
  • /test-pr - Runs tests with the updated PyAirbyte
  • /prerelease - Builds and publishes a prerelease version to PyPI
📚 Show Repo Guidance

Helpful Resources

Community Support

Questions? Join the #pyairbyte channel in our Slack workspace.

📝 Edit this welcome message.

@github-code-quality

github-code-quality Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: Python

Python / code-coverage/pytest-no-creds

The overall line coverage in commit e56872d in the devin/1791620431-mcp... branch is 78%. The line coverage in commit d9f652f in the release-candidate/v1 branch is 65%.

Show a line coverage summary of the most impacted files.
File release-candidate/v1 d9f652f devin/1791620431-mcp... e56872d +/-
airbyte/mcp/cloud.py 52% 83% +31%
airbyte/_util/api_util.py 36% 68% +32%
airbyte/mcp/_datadog.py 0% 38% +38%
airbyte/cloud/connectors.py 34% 75% +41%
airbyte/mcp/_user_identity.py 0% 93% +93%
airbyte/_direct...ctors/models.py 0% 94% +94%
airbyte/mcp/_telemetry.py 0% 94% +94%
airbyte/mcp/_sso_auth.py 0% 96% +96%
airbyte/cloud/models.py 0% 97% +97%
airbyte/mcp/int...nc_status_ui.py 0% 97% +97%

Python / code-coverage/pytest

The overall line coverage in commit e56872d in the devin/1791620431-mcp... branch is 81%. The line coverage in commit d9f652f in the release-candidate/v1 branch is 71%.

Show a line coverage summary of the most impacted files.
File release-candidate/v1 d9f652f devin/1791620431-mcp... e56872d +/-
airbyte/mcp/cloud.py 52% 83% +31%
airbyte/mcp/_datadog.py 0% 38% +38%
airbyte/mcp/_error_handling.py 0% 89% +89%
airbyte/mcp/int..._registry_ui.py 0% 92% +92%
airbyte/mcp/_user_identity.py 0% 93% +93%
airbyte/_direct...ctors/models.py 0% 94% +94%
airbyte/mcp/_telemetry.py 0% 94% +94%
airbyte/mcp/_sso_auth.py 0% 96% +96%
airbyte/cloud/models.py 0% 97% +97%
airbyte/mcp/int...nc_status_ui.py 0% 97% +97%

Python / code-coverage/pytest-unit

The overall line coverage in commit e56872d in the devin/1791620431-mcp... branch is 75%. Line coverage data for the release-candidate/v1 branch is not yet available.

Show a line coverage summary of the most covered files.
File release-candidate/v1 devin/1791620431-mcp... e56872d +/-
airbyte/cloud/models.py — 97% —
airbyte/mcp/_sso_auth.py — 96% —
airbyte/_direct...ctors/models.py — 94% —
airbyte/cloud/client.py — 90% —
airbyte/exceptions.py — 89% —
airbyte/mcp/cloud.py — 83% —
airbyte/progress.py — 80% —
airbyte/cloud/connectors.py — 75% —
airbyte/_util/api_util.py — 68% —
airbyte/shared/...ql_processor.py — 68% —

Updated October 10, 2026 09:59 UTC

@calebevans-ab
Caleb Evans (calebevans-ab) marked this pull request as ready for review October 10, 2026 09:28
@calebevans-ab

Copy link
Copy Markdown
Contributor Author

Codex (@codex) review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 42166c13b5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "Codex (@codex) review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "Codex (@codex) address that feedback".

Comment thread airbyte/mcp/_logging.py
Comment thread airbyte/mcp/_logging.py Outdated
@calebevans-ab
Caleb Evans (calebevans-ab) merged commit b917bdd into release-candidate/v1 Oct 10, 2026
29 checks passed
@calebevans-ab
Caleb Evans (calebevans-ab) deleted the devin/1791620431-mcp-json-log-levels branch October 10, 2026 10:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant