Skip to content

FEATURE: Added profile build for "has_no_outliers" check#1317

Merged
mwojtyczka merged 31 commits into
databrickslabs:mainfrom
IvannKurchenko:feature/has_no_outliers
Jul 24, 2026
Merged

FEATURE: Added profile build for "has_no_outliers" check#1317
mwojtyczka merged 31 commits into
databrickslabs:mainfrom
IvannKurchenko:feature/has_no_outliers

Conversation

@IvannKurchenko

Copy link
Copy Markdown
Contributor

Changes

Summary of changes:

  • Extracted MAD related calculations to common package;
  • Refactored profiler internal - extracted configs and default to constants;
  • Implemented has_no_outliers profile build to generate corresponding check;
  • Corresponding documentation updated;

Linked issues

Resolves #977

Tests

  • manually tested
  • added unit tests
  • added integration tests
  • added end-to-end tests
  • added performance tests

Documentation and Demos

  • added/updated demos
  • added/updated docs
  • added/updated agent skills

@IvannKurchenko
IvannKurchenko marked this pull request as ready for review July 10, 2026 07:32
@IvannKurchenko
IvannKurchenko requested a review from a team as a code owner July 10, 2026 07:32
@IvannKurchenko
IvannKurchenko requested review from nehamilak-db and removed request for a team July 10, 2026 07:32

@mwojtyczka mwojtyczka 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.

Re-review of the has_no_outliers profile builder. The MAD extraction and option-constant refactor are clean, but there are two blocking issues plus some cleanup. Most points are inline; two that can't be anchored to this diff:

🔴 Blocking — has_no_outliers profiles never become checks

DQGenerator._checks_mapping (src/databricks/labs/dqx/profiler/generator.py) maps only is_not_null, is_in, min_max, is_not_null_or_empty, is_not_empty, is_unique, and generate_dq_rules() skips any profile whose name isn't a key. This PR builds a DQProfile(name="has_no_outliers") but never adds a mapping entry / dq_generate_has_no_outliers, and doesn't touch generator.py — so the profile is silently dropped and no check is generated end-to-end, which is the PR's stated goal.

Test coverage

Unit tests cover only the non-numeric early-exit; the positive / threshold-negative paths and the MAD math are integration-only, and nothing tests the profile → generate_dq_rules → check path. That's exactly why the mapping gap above and the filter crash (inline) both slip through — the tests call the builder directly with a single-column frame and no cross-column filter. A generate-path test and a cross-column-filter test would catch both blocking issues.

See inline comments for the filter crash (blocking), numeric-type narrowing, ratio denominator, the Any convention, and module placement.

Comment thread src/databricks/labs/dqx/profiler/profile_builder.py Outdated
Comment thread src/databricks/labs/dqx/profiler/profile_builder.py Outdated
Comment thread src/databricks/labs/dqx/profiler/profile_builder.py Outdated
Comment thread src/databricks/labs/dqx/profiler/profile_options.py Outdated
Comment thread src/databricks/labs/dqx/calculations_utils.py Outdated
@mwojtyczka mwojtyczka added under-review This PR is currently being reviewed by one of DQX maintainers. needs-changes Changes required after review labels Jul 11, 2026

@ghanse ghanse 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.

This will be a nice addition. Agree with the other feedback. Left a few small comments.

Comment thread src/databricks/labs/dqx/profiler/profile_options.py
Comment thread src/databricks/labs/dqx/profiler/profile_builder.py Outdated
Comment thread src/databricks/labs/dqx/calculations_utils.py Outdated
Comment thread src/databricks/labs/dqx/calculations_utils.py Outdated
Comment thread tests/integration/test_profile_builder.py Outdated
Comment thread tests/integration/test_profile_builder.py Outdated
Comment thread tests/integration/test_profile_builder.py
@IvannKurchenko

Copy link
Copy Markdown
Contributor Author

@mwojtyczka @mwojtyczka Thank you so much for your review. May I ask for second round?

@mwojtyczka mwojtyczka 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.

Re-review of 794cf15. All prior findings (mine + @ghanse's) are addressed — the profiler-filter crash is fixed, the builder uses NumericType, the outlier ratio uses count_non_null consistently, dict[str, Any] is gone, calculations_utils.py was folded into profiling_utils.py (MAD shared by the check and the builder), and the requested tests (numeric-type parametrization, all-nulls→None) were added. Thanks for the thorough turnaround.

New findings below. #1 (filter dropped) and #2 (outliers_ratio not plumbed through ProfilerConfig/ProfilerRunner) are the two I'd fix before merge — they make the feature behave inconsistently with the rest of the profiler and silently ignore a documented config. The rest are a perf/toggle decision, two edge cases (zero-MAD, Decimal bounds), and doc/style cleanup.

Minor (not inline): the 0.01 default is duplicated between DEFAULT_PROFILE_OPTIONS and the inline .get(..., 0.01) fallback; dq_generate_has_no_outliers has an unused params (params = params or {} is dead); and column_name is interpolated into the logged DQProfile.description without newline sanitization (CWE-117, low — schema-derived).

Comment thread src/databricks/labs/dqx/profiler/profile_builder.py Outdated
Comment thread src/databricks/labs/dqx/profiler/profiler_runner.py
Comment thread src/databricks/labs/dqx/profiler/profile_builder.py
Comment thread src/databricks/labs/dqx/profiler/profile_builder.py Outdated
Comment thread src/databricks/labs/dqx/profiler/profile_builder.py Outdated
Comment thread src/databricks/labs/dqx/profiler/generator.py
Comment thread src/databricks/labs/dqx/profiler/profile_builder.py Outdated
Comment thread tests/integration/test_profiler.py Outdated
@IvannKurchenko

Copy link
Copy Markdown
Contributor Author

@mwojtyczka Im sorry for failed integration tests, I'll work on fix

@mwojtyczka

Copy link
Copy Markdown
Contributor

@mwojtyczka Im sorry for failed integration tests, I'll work on fix

no worries, let me know if you need help

The has_no_outliers profiler feature is opt-in (PROFILE_OPTION_HAS_NO_OUTLIERS
defaults to False), but the integration tests were written assuming it was
enabled by default. They expected has_no_outliers entries in the profile
output (or asserted exactly one profile) without setting the flag, so the
builder short-circuited and emitted nothing -> DQProfile list mismatches and
assert 0 == 1.

Pass "has_no_outliers": True in the options of every profiler test that
expects the profile, so they exercise the feature explicitly. Also enable it
in the negative threshold test so it actually verifies suppression instead of
passing coincidentally while the feature is disabled.

Co-authored-by: Isaac
@mwojtyczka

Copy link
Copy Markdown
Contributor

@mwojtyczka Im sorry for failed integration tests, I'll work on fix

no worries, let me know if you need help

I think you just missed enabling it in the test, just updated

@mwojtyczka
mwojtyczka merged commit b3c5ec6 into databrickslabs:main Jul 24, 2026
42 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Approved to Merge When PR is reviewed and approved. To be merged once all tests pass

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE]: Add has_no_outliers function to automated generated rules with profiler

3 participants