OBSL-1019/1007 (soda-core part): raw feature-config passthroughs on the dataset-config DTO + MM/dialect seams#2777
Conversation
Add ProfilingConfigurationDTO (pydantic BaseModel, extra=allow) with is_enabled and sampling_strategy_configuration fields; wire it into DatasetConfigurationDTO replacing the commented-out dict placeholder. All fields Optional so existing payloads without profilingConfiguration parse unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…obsl-1019-profiling-config-dto
…obsl-1019-profiling-config-dto
…n on dataset config DTO (OBSL-1018) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…p type parameters from metadata (OBSL-1005) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…p (OBSL-1005) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…) (OBSL-1005) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…recision aggregate math (OBSL-1005) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…mparisons (OBSL-1005)
Base SqlDialect: identity — postgres/duckdb/snowflake implicitly coerce ISO
string window-bound literals against temporal columns (verified live on all
three). BigQuerySqlDialect: timestamp({expr}) — BigQuery coerces the string
literal to the COLUMN's type, and an ISO string with a UTC offset cannot
cast to a naive DATETIME column ('Could not cast literal
"...T12:00:00+00:00" to type DATETIME', verified live). v3 provenance:
get_time_between_sql TIMESTAMP({column}) BETWEEN ... (soda-library
bigquery_data_source.py:465-467); like v3 the wrap is unconditional on
BigQuery and is a no-op on TIMESTAMP columns (verified live).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…obsl-1019-profiling-config-dto
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…igquery APPROX_QUANTILES renderer (OBSL-1022) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… queries, identity helpers (OBSL-1007) - DatasetConfigurationDTO.metric_monitoring_configuration: raw list[dict] on purpose (metricMonitoringConfiguration); the metric-monitoring plugin's monitor_config owns parsing, like timePartitionConfiguration. - soda_core/common/observability_identity.py: get_metric_identity / get_check_identity ported byte-for-byte from v3 (profiling_metric.py:113-132, observability config.py:145-147); pins sourced by executing the actual v3 implementation in the pinned soda-library venv. - SodaCloud.get_historic_measurements / get_historic_check_results: v3 sodaCoreHistoricMeasurements2 / sodaCoreHistoricCheckResults2 queries with minScanTime/maxScanTime XOR limit, v3 millisecond-UTC scan-time strings, and batching+merge over the 500-identities-per-request BE constraint. - MockSodaCloud: fixture-driven historic-data responses keyed by identity; 400s oversized identity lists to keep the batching tests honest. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…lake/bigquery renderers (OBSL-1028) Base renderers are v3's postgres forms (epoch-floor partition index, interval-multiply scan_time reconstruction) — byte-parity on postgres, valid duckdb, unit-safe for the fixed-length units weeks/days/hours/seconds. Snowflake keeps v3's TIMESTAMPDIFF-in-seconds form; bigquery keeps TIMESTAMP_DIFF/TIMESTAMP_ADD with singular unit names. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…L-1028) v3 soda_cloud.py:703-712 verbatim semantics: sodaCoreHistoricMeasurements2 with limit 1, first-result-or-None; shares the OBSL-1007 historic-data fetch plumbing and mock/test pattern. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…t check shapes (OBSL-1008) CheckResult.build_soda_cloud_check_dict(contract, wire_source) defaults to None; _build_check_results_cloud_json_dicts uses a non-None return verbatim, else falls back to the generic _build_check_result_cloud_dict. Contract check dicts are byte-unchanged (pinned by unit test); metric monitoring subclasses CheckResult to emit v3-parity anomalyDetection check dicts through the same send_check_collection_results path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ig DTO The soda-profiling extension (soda_profiling.profiling_config) owns the parsing of profilingConfiguration, so soda-core stays free of profiling semantics — the same convention as metricMonitoringConfiguration (metric-monitoring's monitor_config) and timePartitionConfiguration (the partition detector). Wire JSON is unchanged: the dict arrives and round-trips verbatim. Removes ProfilingConfigurationDTO and the sampling-strategy union types (CardinalitySamplingStrategyConfigurationDTO, TimePartitionSamplingStrategyConfigurationDTO, SamplingStrategyConfiguration); their typed tests move to soda-profiling alongside the ported models. (OBSL-1019) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
CheckCollectionImpl.log_table_extra_columns(check_result) -> dict, default {}
so every existing collection type's table (contract verification, regular
metric monitoring) stays byte-identical — pinned by the existing
test_contract_verification_logs byte-exact lines plus an explicit
no-Window guard.
Overriding subtypes (the soda-extensions metric-monitoring BACKFILL
collection, whose N rows per check are otherwise visually identical — one
per backfilled window) return e.g. {"Window": "2026-07-09"}: new keys
become columns inserted right after Check and participate in the row sort
at that position; keys that already exist in the row (e.g. Diagnostics)
replace that cell's value in place.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
for more information, see https://pre-commit.ci
Second seam next to log_table_extra_columns: CheckCollectionImpl.
log_table_header_overrides() -> dict[str, str] (default {}) lets a
collection subtype rename rendered table headers, e.g. metric
monitoring renders the "Check" column as "Monitor". The rename is
applied by build_summary_table only at render time, so row-dict keys
stay internal: sorting and log_table_extra_columns cell overrides keep
targeting the internal names. Default {} keeps contract verification
output byte-identical (byte-identity pins extended).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ns-and-cte-union' into HEAD
…ns-and-cte-union' into HEAD
|
Reviewed (aware it's still draft) as a mixed PR, per group. Most of it is clean: DTO passthroughs round-trip by alias and the ownership rationale is documented; One finding I'd fix before undrafting:
Smaller notes:
|
- BigQuerySqlDialect.build_union_sql: render plain UNION as UNION DISTINCT (was UNION ALL), preserving set semantics for any caller; UNION_ALL still renders UNION ALL. Update tests accordingly. - Snowflake: move the "AI-generated / test thorough" TODO back above the type-map function it describes (a new method had been inserted between them). - get_historic_measurements/get_historic_check_results: document that `limit` is applied per identity-batch, so multi-batch merged results can exceed it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Addressed in 23a9ae9:
Deferred (noted, not changed): the Snowflake |
… package Metric/check identity generation is a cross-feature observability concern (profiling + metric monitoring), and soda-core neither generates nor consumes these identities — nothing here imported observability_identity. Only the generic ConsistentHashBuilder primitive belongs in soda-core. The helpers + pin test now live in the shared `soda` extensions package (soda.observability.identity), which both soda-profiling and soda-metric-monitoring already depend on. See soda-extensions obsl-1037-profiling-all-datasources. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… soda package) Mirrors the removal on #2777: soda-core neither generates nor consumes metric/ check identities. The helpers + pin test live in soda.observability.identity in the shared `soda` extensions package. Keeps this branch's tree consistent so the file never reaches main via the chain. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|



PR chain (soda-core)
metrics[]in scan-results payloadSummary
Cloud/dialect seams for the observability extensions (profiling, metric monitoring), stacked on #2776 (OBSL-1027).
Dataset-config DTO: raw feature-config passthroughs
DatasetConfigurationDTO.profiling_configuration(aliasprofilingConfiguration) is a rawOptional[dict]passthrough: the soda-profiling extension (soda_profiling.profiling_config, soda-extensions) owns the parsing, so soda-core stays free of profiling semantics — the same convention asmetricMonitoringConfiguration(metric-monitoring'smonitor_config) andtimePartitionConfiguration(the partition detector). Wire JSON unchanged; the dict arrives and round-trips verbatim. The earlier typedProfilingConfigurationDTO+ sampling-strategy union from this branch was removed again in favor of the passthrough; the typed models now live in soda-extensions.metric_monitoring_configurationrawlist[dict]field + historic-data queries + identity helpers (MM transport seams, OBSL-1007) andget_last_measurementsingle-identity historic query (OBSL-1028).CheckResultcloud-dict override hook for non-contract check shapes (OBSL-1008).SQL AST + dialect seams
TIME_DELTA+ADD_INTERVALtime-bucket nodes with snowflake/bigquery renderers (OBSL-1028).PERCENTILE_WITHIN_GROUPordered-set aggregate node + bigqueryAPPROX_QUANTILESrenderer (OBSL-1022).sql_expr_timestamp_coercedialect hook for partition-window comparisons andget_large_numeric_cast_type_namecapability for high-precision aggregate math (OBSL-1005).UNIONasUNION ALL; BigQueryDATETIME/BIGNUMERIC+ parameterized types in the soda-type reverse map; defensive Snowflake string-type aliases (OBSL-1005).Test Plan
profilingConfigurationpasses through as a raw dict via alias, round-trips by alias unchanged, omitted key parses toNone(no regression); typed parsing is covered in soda-extensions (soda-profiling/tests/test_profiling_config.py)pytest soda-tests/tests/unit -q: 1059 passed, 1 skipped; pre-commit clean🤖 Generated with Claude Code