Skip to content

fix(sdk): force_flush returns meaningful bool on MetricReader#5085

Open
ravitheja4531-cell wants to merge 3 commits intoopen-telemetry:mainfrom
ravitheja4531-cell:fix/force-flush-return-meaningful-bool
Open

fix(sdk): force_flush returns meaningful bool on MetricReader#5085
ravitheja4531-cell wants to merge 3 commits intoopen-telemetry:mainfrom
ravitheja4531-cell:fix/force-flush-return-meaningful-bool

Conversation

@ravitheja4531-cell
Copy link
Copy Markdown

Fixes #5020

Description

force_flush on MetricReader and PeriodicExportingMetricReader always
returned True regardless of whether the export succeeded or failed, violating
the OTel specification:

ForceFlush SHOULD provide a way to let the caller know whether it succeeded,
failed or timed out.

This PR threads the actual export result up through _receive_metrics
collectforce_flush so callers get a meaningful bool.

Also fixes a pre-existing bug where detach(token) in
PeriodicExportingMetricReader._receive_metrics was only called on the happy
path — moved to finally so it always runs.

Type of change

  • Bug fix (non-breaking change which fixes an issue)

How Has This Been Tested?

Ran the full existing metrics test suite locally:

@ravitheja4531-cell
Copy link
Copy Markdown
Author

ravitheja4531-cell commented Apr 14, 2026

could someone from @jd take a look when you have a moment?
Happy to make any changes needed. Thanks!

@Asquator
Copy link
Copy Markdown

I personally like this pretty much. After it's merged, we'll have to open a new issue to indicate failure reason.

Will look at the code with more attention soon.

Btw, are you planning to add unit tests for the new behavior?

**kwargs,
) -> None:
"""Called by `MetricReader.collect` when it receives a batch of metrics"""
) -> bool:
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.

Suggested change
) -> bool:
) -> bool | None:


@final
def collect(self, timeout_millis: float = 10_000) -> None:
def collect(self, timeout_millis: float = 10_000) -> Optional[bool]:
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.

Suggested change
def collect(self, timeout_millis: float = 10_000) -> Optional[bool]:
def collect(self, timeout_millis: float = 10_000) -> bool | None:

@github-project-automation github-project-automation bot moved this to Reviewed PRs that need fixes in Python PR digest Apr 16, 2026
Comment on lines +611 to +613
collect_ok = super().force_flush(timeout_millis=timeout_millis)
exporter_ok = self._exporter.force_flush(timeout_millis=timeout_millis)
return collect_ok and exporter_ok
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

  1. Should we test this logic?
  2. Should we even call the exporter's force_flush if the general one fails?

Copy link
Copy Markdown
Author

@ravitheja4531-cell ravitheja4531-cell left a comment

Choose a reason for hiding this comment

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

Addressed all review feedback:

Changed Optional[bool] → bool | None on collect and _receive_metrics (per @herin049)
Removed Optional from imports entirely
Fixed force_flush short-circuit: exporter.force_flush is now skipped if super().force_flush fails (per @Asquator)
Added 4 unit tests covering success, failure, short-circuit, and detach always running in finally

Ready for re-review. Thanks!

@ravitheja4531-cell ravitheja4531-cell force-pushed the fix/force-flush-return-meaningful-bool branch from 60da606 to 5680779 Compare April 20, 2026 12:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Reviewed PRs that need fixes

Development

Successfully merging this pull request may close these issues.

force_flush should provide a way to let the caller know whether it succeeded, failed or timed out.

3 participants