Skip to content

Commit 766a2d7

Browse files
thiagohoraclaude
andauthored
[OPIK-7773] [BE] feat: fail readiness when the traces wrap flag disagrees with the DB topology (#7948)
* [OPIK-7773] [BE] feat: fail readiness when the traces wrap flag disagrees with the DB Post-cutover `traces` is a Distributed table that cannot take mutations, so TraceDAO routes trace deletes at `traces_local` only while `databaseAnalyticsDataModel.tracesDistributedWrapEnabled` is on (OPIK-7455). If an install's flag does not match its database, every trace delete breaks — stale-`false` over a wrapped `traces` with code 36/48, stale-`true` over an unwrapped one with code 60 — and nothing says so until the first delete runs. The answer depends on each environment's Helm config plus its live database, so this cannot be a CI guard; it belongs at readiness. Adds ClickHouseTracesTopologyHealthCheck (`clickhouse-traces-topology`, critical/ready): one `system.tables` lookup covering both tables and both directions — flag on asserts `traces` is Distributed and `traces_local` exists, flag off asserts `traces` is a (Replicated)MergeTree — reporting the flag, the observed engine and the fix on a mismatch. An absent `traces` is unhealthy either way, since trace reads and writes cannot work at all. Unlike the sibling `clickhouse-cluster` / `clickhouse-cold-storage-disk` probes it is deliberately not toggle-gated: flag off over a MergeTree `traces` is the default on every install as shipped (OSS Docker, self-hosted, pre-cutover SaaS), so the assertion holds universally and only a genuine misconfiguration trips it. The flag stays the source of truth — the probe reports, it never re-routes, and no routing logic changed. Collects the db health checks into `infrastructure/db/healthchecks`: the new probe extends the package-private AbstractClickHouseHealthCheck, so it can only live alongside it, and the package now holds the family (both abstracts, the four ClickHouse probes, MysqlHealthyCheck) plus their tests instead of scattering them through `infrastructure/db`. Test coverage is three-layered. ClickHouseTracesTopologyHealthCheckTest asserts the exact message of every case, not merely that the probe went red — the message is all an operator sees. HealthCheckIntegrationTest covers the matching flag-off install (healthy, folded into the existing per-check and aggregate expectations) and the flag-on-without-the-wrap mismatch on the shared containers, since the probe only reads system.tables. ClickHouseTracesTopologyReadinessTest takes dedicated, non-reused ClickHouse and ZooKeeper containers — the wrap destructively renames the live `traces` — and walks the real transition: ready, apply the wrap block verbatim from 000003_exchange_and_wrap.sql, then not ready. Both mismatch directions assert `/health-check?name=all&type=ready` returns 503, the chart's actual `component.backend.readinessProbe` path, so the tests prove the pod really does leave rotation rather than merely that a row flipped. Documents the check where operators meet it: a self-host changelog entry and a troubleshooting section (mirrored into both docs trees) stating that the failure is intentional, giving the engine/flag table and the `system.tables` query to resolve it, and warning against removing the check instead of fixing the mismatch. The chart already wires the flag through values -> configmap -> env (OPIK-7455), so values.yaml gains only the note that the flag is asserted at readiness. The cutover runbook gains the operational consequence this introduces: the flag and the wrap cannot land simultaneously, so the unavoidable mismatch window is now a readiness window in either order — pods leave rotation rather than just failing deletes. It must therefore sit inside the maintenance window `--confirm-maintenance` already asserts for the wrap. The window is self-clearing, since the probe re-evaluates continuously and rotation returns once the two sides are back in step. The runbook's claim that no readiness endpoint exposes the flag's value is replaced by the endpoint that now does. Implements OPIK-7773. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * [OPIK-7773] [BE] test: make the readiness suite's wrap idempotent; drop the changelog entry The readiness suite assumed it starts on an unwrapped `traces`, which holds today (the wrap lives in data-migrations/, outside the migrations/ directory the analytics changelog includes) but breaks the day it lands as a regular migration: the container would arrive already Distributed, `CREATE TABLE traces_dist` would fail on the second pass, and asserting "healthy first" would fail on a correctly behaving probe. applyDistributedWrap() now returns early when `traces` is already Distributed, and the pre-wrap state is read rather than assumed: the healthy half of the transition runs only when there is something to transition from, while the mismatch half — the point of the test — always runs. probeWithTheFlagOnIsHealthyOverTheWrappedTopology wraps idempotently instead of asserting that a previous test left the topology in place, so it no longer depends on @order to pass; the ordering stays only so the transition test still gets the pristine pre-wrap state. Verified both ways by running the suite with the order reversed. Drops the self-host changelog entry: which release ships this is not decided yet, so the entry would state a version we cannot stand behind. The troubleshooting section carries the operator guidance in the meantime and does not link to the changelog, so nothing dangles. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * [OPIK-7773] [BE] fix: keep the topology probe's SQL literal and hold traces_local to a mutable engine Two review findings, both in scope. SQL is never assembled with Java string operations (.agents/skills/opik-backend/SKILL.md:146 — "don't copy them and don't add new ones"), and both new queries did. TOPOLOGY_QUERY is now a literal text block instead of `.formatted(TRACES_TABLE, TRACES_LOCAL_TABLE)`; the constants stay as the single source for the map lookups and the messages, and the unit test stubs the exact query text, so the two cannot drift apart unnoticed. The readiness suite's wrap DDL likewise spells the database out rather than interpolating DATABASE_NAME — ClickHouse cannot bind an identifier inside a Distributed() engine argument, so the literal is held honest by an assertion in beforeAll instead. The `.formatted(...)` calls that remain build health check messages, which the rule explicitly still allows. The flag-on branch accepted `traces_local` on presence alone, so a same-named View, Log or nested Distributed table would report healthy while TraceDAO's DELETEs failed against it — the same outcome as an absent table, which the probe already rejects. It now holds that table to the MergeTree family, sharing the existing family-suffix predicate with the flag-off branch. This needs no extra query: the engine was already in the row the probe reads, so the assertion is free. Validating the Distributed engine_full's cluster/database/sharding-key arguments and the shard's full schema was left out — that is a topology audit, well past the ticket's "one cheap system.tables check", and it belongs with the CI DDL guard. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * [OPIK-7773] [BE] fix: correct the runbook's restart attribution and the readiness DTO builder Two more review findings, both in scope. The runbook's self-clearing note had the restart on the wrong path: it read "no extra restart needed on the wrap-first path, and only the already-planned restart on the toggle-first path", which is backwards. Both orderings spend exactly the one planned rolling restart the toggle already requires, and neither needs another; what differs is its position, and with it what closes the mismatch window — the wrap DDL on the toggle-first path (the restart is already done by then), the restart completing on the wrap-first path. Reworded to say that. HealthCheckResponse used a plain @builder, copied from the same record in HealthCheckIntegrationTest, where the convention predates the rule. Records and DTOs take @builder(toBuilder = true) (.agents/skills/opik-backend/SKILL.md:52, which lists bare @builder as the anti-pattern), so the new copy uses it; the older one is left alone as unrelated to this ticket. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * [OPIK-7773] [BE] fix: correct the not-wrapped diagnosis and document the accepted engines Review feedback, and the first one was demonstrated by my own test fixture. **The not-wrapped message promised the wrong failure.** It ended "otherwise trace deletes fail with UNKNOWN_TABLE (60)", but that branch fires whenever the flag is on and `traces` is not Distributed — and `traces_local` may well still exist in that state. A rollback leaves exactly that shape: the wrapper dropped, the original `traces` promoted back, the old shard lingering. The routed delete then *succeeds against the stale shard* and the live rows are never touched, which is quieter than the error and worse. The check's own unit test seeds `traces_local` as present while asserting the UNKNOWN_TABLE wording, so the fixture disproved the message. Now states both outcomes and which one applies when, with the reasoning recorded on the constant so it does not get "simplified" back. **SharedMergeTree was accepted but undocumented.** The probe matches on the `MergeTree` suffix, so ClickHouse Cloud's SharedMergeTree family satisfies it, but config.yml, the Javadoc and the troubleshooting table all said "(Replicated)MergeTree" — leaving a valid Cloud install looking misconfigured. All three now describe the accepted family. **Documented that `critical: true` also gates /is-alive/ping.** IsAliveResource filters on isCritical alone and ignores `type`, so a readiness mismatch reports the server as down to SDKs and makes them buffer. That is the existing behaviour of every `ready` check here (`clickhouse`, `db`, `redis`, `mysql`), and it is intended for this one too — but it was an unstated consequence, so it is now stated where the flag is set. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * [OPIK-7773] [BE] docs: pin the topology probe's scope to the answering node Review follow-up: the probe reads the node-local system.tables, and nothing said so or said why. It stays node-local — clusterAllReplicas needs REMOTE + CLUSTER grants the app user is not guaranteed to hold (so a non-toggle-gated critical check would fail on installs as shipped), one unreachable replica would pull the whole fleet from rotation over a condition that breaks no delete, and on a shared catalog (ClickHouse Cloud / SharedMergeTree) node-local already is cluster-wide. The limit that follows is now stated instead of implied: a divergence confined to some replicas degrades into sporadic unhealthy reports rather than a fleet-wide outage, and the cluster-wide "did this ON CLUSTER DDL reach every replica" gate stays in exchange_and_wrap.sh / finalize.sh, where it is fail-loud and operator-run. The troubleshooting page gains the clusterAllReplicas form for an operator chasing an intermittent failure, with the fix being the lagging replica, not the flag. Comment and documentation only; no behaviour change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * [OPIK-7773] [BE] docs: disambiguate the per-replica check and the Helm env precedence Two review catches on the troubleshooting page. The cluster-wide diagnostic said "the engine must be identical on all of them", which reads as if `traces` and `traces_local` must match each other — the exact opposite of the healthy post-wrap shape. Compare down each table instead: one table's engine must be the same on every host, and the two tables differing from each other is the wrap working. The resolution told operators to set the chart value, but the configmap derives ANALYTICS_DB_DATA_MODEL_TRACES_DISTRIBUTED_WRAP_ENABLED only when it is absent from component.backend.env, so an explicit entry there silently wins and the check keeps failing after the change. Say so, and give the configmap read that shows what the backend actually receives. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * [OPIK-7773] [BE] docs: warn that an explicit Helm env entry overrides the flag Review feedback, and a good catch for a troubleshooting page specifically. configmap-backend.yaml emits the derived ANALYTICS_DB_DATA_MODEL_TRACES_DISTRIBUTED_WRAP_ENABLED key only when `component.backend.env` does not already define it (`if not (hasKey $env $k)`). So an operator following this page, changing databaseAnalyticsDataModel.tracesDistributedWrapEnabled while an explicit env entry exists, sees no effect at all: the check keeps failing with the same message and nothing they change appears to help. That is precisely the state a troubleshooting page exists to get someone out of. Adds a callout with the precedence, the `printenv` command to see what the pod actually received, and the fix — remove the explicit key so the setting is the single source, or update it there instead. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * [OPIK-7773] [BE] docs: revert duplicate Helm precedence callout The page already documented this, further down the same Resolution section. I added a second callout saying the same thing before checking, which is worse than having missed it. Reverted to the existing wording. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * [OPIK-7773] [BE] docs: parameterise the database in the topology diagnostic The node-local query hardcoded `database = 'opik'` while the cluster-wide one right below it used `<database_name>`, so the page contradicted itself — and on any install with a custom ANALYTICS_DB_DATABASE_NAME the hardcoded form returns no rows, which reads as "the tables are missing" rather than "wrong database". Both queries now take the placeholder, with the substitution stated once, up front, where it covers both. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * [OPIK-7773] [BE] test: admit the readiness probe as the wrap flag's second reader OPIK-7772's routing guard (#7953) landed on main after this branch last rebased and allows exactly one reader of tracesDistributedWrapEnabled — TraceDAOImpl's accessor. This probe is a second one, so the rebase turned it into a build failure. The guard is right to notice; the exemption is what was missing. Widened to an allowlist of two, still member-scoped so it is not a category hole: TraceDAOImpl#tracesDistributedWrapEnabled and the probe's constructor. What the rule protects is the routing decision — a second place that branches on the flag is a second place that can name the wrong table — and the probe names no table and issues no mutation. It reads the flag to assert it against the live `system.tables` engine and report a mismatch at readiness. byCodeUnitsThat rather than byMethodsThat because the flag is read at injection and a constructor is not a JavaMethod, so the method-only form could report the call but never admit it. Renamed the rule off "exactly_one_place", which two readers would have made a lie. Verified the teeth both ways: a third reader added as a method on a sibling health check in the same package, and again as a constructor on another, each fails the rule. Suites run: TraceMutationRoutingArchTest, TraceMutationSqlRoutingTest, Trace/SpanDeletionEventArchTest, the four healthcheck suites (55 tests, green). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 82f6bc2 commit 766a2d7

20 files changed

Lines changed: 966 additions & 28 deletions

apps/opik-backend/config.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,9 @@ databaseAnalyticsDataModel:
154154
# `traces`. Post-wrap, changes to `traces` split by kind: row mutations (DELETE) + MATERIALIZE COLUMN/ADD INDEX/
155155
# MODIFY TTL target `traces_local` only (the Distributed `traces` rejects them); ADD/DROP/MODIFY COLUMN must target
156156
# both `traces_local` and `traces`, else reads can't see the column (code 47).
157+
# This value is asserted against the live topology by the `clickhouse-traces-topology` readiness check below: set it
158+
# wrong in either direction and the backend fails readiness at startup with a message naming the flag and the
159+
# observed engine, rather than serving traffic whose trace deletes are guaranteed to fail.
157160
tracesDistributedWrapEnabled: ${ANALYTICS_DB_DATA_MODEL_TRACES_DISTRIBUTED_WRAP_ENABLED:-false}
158161

159162
# Description: UUIDv7 ingestion validation. Rejects writes whose `id` embeds a timestamp outside the
@@ -235,6 +238,27 @@ health:
235238
- name: clickhouse-cold-storage-disk
236239
critical: true
237240
type: ready
241+
# Fail-fast assertion that databaseAnalyticsDataModel.tracesDistributedWrapEnabled matches the actual `traces`
242+
# topology: flag on -> `traces` is Distributed and `traces_local` exists; flag off -> `traces` is any engine of the
243+
# MergeTree family that takes mutations directly - the check matches on the `MergeTree` suffix, so MergeTree,
244+
# ReplicatedMergeTree and ClickHouse Cloud's SharedMergeTree variants all satisfy it. Not toggle-gated on
245+
# purpose — flag off over a MergeTree `traces` is the default
246+
# everywhere, so only a genuine misconfiguration trips it, and either mismatch direction breaks trace deletes
247+
# (code 36/48 one way, 60 the other) with no symptom until the first delete. Critical so such an install is pulled
248+
# from rotation instead of serving traffic it cannot mutate; re-evaluated continuously, so it clears itself once
249+
# the operator brings flag and topology back in step. Note that `critical: true` also gates /is-alive/ping, which
250+
# ignores `type` (IsAliveResource filters on isCritical alone) - so a mismatch reports the server as down to SDKs,
251+
# exactly as the `clickhouse`, `db`, `redis` and `mysql` ready checks above already do. That is intended here: the
252+
# install is misconfigured and needs an operator, and buffering beats accepting traffic it cannot fully serve.
253+
# Scope is the node that answers: `system.tables` is node-local and the probe does not fan out with
254+
# clusterAllReplicas, which needs REMOTE + CLUSTER grants the app user isn't guaranteed to hold and would take
255+
# every pod out of rotation whenever a single replica is unreachable. So a divergence confined to some replicas
256+
# (an ON CLUSTER DDL still propagating, or one that failed on a host) degrades into sporadic unhealthy reports
257+
# rather than a fleet-wide outage; the cluster-wide "did this DDL reach every replica" gate lives in the cutover's
258+
# exchange_and_wrap.sh / finalize.sh, and the self-host troubleshooting page carries the query for operators.
259+
- name: clickhouse-traces-topology
260+
critical: true
261+
type: ready
238262
- name: mysql
239263
critical: true
240264
type: ready

apps/opik-backend/data-migrations/traces-local-v2-cutover/README.md

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,10 @@ new table before the EXCHANGE. The replay matches the **full key**, not `id` alo
212212
> `databaseAnalyticsDataModel.tracesDistributedWrapEnabled`. Set it **`true` in lockstep with applying the wrap** so those
213213
> deletes run against `traces_local`; reads and inserts stay on the Distributed `traces`. The flag is **startup-bound**
214214
> (read once at boot; no hot-reload), so making it "live across the fleet" means a **completed rolling restart of every
215-
> backend instance** — there is no readiness endpoint exposing its value, so confirm via the deploy's restart completion
216-
> or by observing that trace deletes hit the intended table (queries are `log_comment`-tagged). A mismatch is
215+
> backend instance**. Since OPIK-7773 the flag's value is observable per instance: the `clickhouse-traces-topology`
216+
> readiness check asserts it against the live `traces` engine on every probe, so
217+
> `GET /health-check?name=clickhouse-traces-topology` reports which side of the cutover that instance believes it is on
218+
> and, on a mismatch, names both the flag and the observed engine. A mismatch is
217219
> **fail-loud**, not silent: a stale-`false` instance issues `DELETE` against the `Distributed` `traces` (code 36/48), a
218220
> stale-`true` instance against an absent `traces_local` — both 500 the delete path, so a partial rollout surfaces at
219221
> once and is recoverable. While it is `false` (the deploy
@@ -227,7 +229,7 @@ new table before the EXCHANGE. The replay matches the **full key**, not `id` alo
227229
> the EXCHANGE. Defer the
228230
> wrap until the retarget flag is wired into the deploy. The wrap is the sharding-readiness layer, not the cutover.
229231
>
230-
> **"In lockstep" cannot mean simultaneous — plan for a short fail-loud delete window.** The toggle is a
232+
> **"In lockstep" cannot mean simultaneous — plan for a short mismatch window.** The toggle is a
231233
> config push plus a rolling restart; the wrap is a DDL statement. They cannot land at the same instant, so
232234
> one of two windows is unavoidable:
233235
> - **toggle first** (recommended): from the moment the last backend comes up with `true` until the wrap
@@ -236,10 +238,30 @@ new table before the EXCHANGE. The replay matches the **full key**, not `id` alo
236238
> - **wrap first**: from the swap until the rolling restart finishes, deletes hit the `Distributed` `traces`
237239
>`Code: 36`. Same blast radius, but it also exposes the cross-node `ON CLUSTER` skew with no buffer.
238240
>
241+
> **Since OPIK-7773 the mismatch window is also a readiness window.** `clickhouse-traces-topology` is a
242+
> `critical`/`ready` check, so for as long as flag and topology disagree — in **either** order — every instance that
243+
> sees the mismatch fails `/health-check?name=all&type=ready` and Kubernetes takes it out of rotation. That is the
244+
> point of the check (an instance whose deletes cannot work should not serve), but it changes the cost of the window
245+
> from "delete-path 500s" to "no backend in rotation", so the window must sit **inside the declared maintenance window**
246+
> that `--confirm-maintenance` already asserts for the wrap. It is self-clearing: the probe re-evaluates continuously,
247+
> so rotation returns on the next successful probe once the two sides are back in step. **Neither ordering needs an
248+
> extra restart** — both spend exactly the one planned rolling restart the toggle already requires; only its position
249+
> differs, and with it what closes the window: on the toggle-first path the restart comes first and the **wrap DDL**
250+
> closes the window, on the wrap-first path the wrap comes first and the **restart completing** closes it.
251+
>
252+
> **The check reads one replica per probe.** It queries the node-local `system.tables` on whichever ClickHouse node the
253+
> load-balanced service hands it, so across the cross-node `ON CLUSTER` skew described below the mismatch is seen only
254+
> by the probes that land on a not-yet-wrapped host: pods flap instead of the fleet going dark in lockstep. That is
255+
> expected inside the window and is why the probe is not the propagation gate — to confirm the wrap actually reached
256+
> every replica, use the cluster-wide `clusterAllReplicas('{cluster}', system.tables)` form that `finalize.sh`
257+
> classifies with (also in the self-host troubleshooting page). Fan-out is deliberately out of the probe: it needs
258+
> `REMOTE` + `CLUSTER` grants the app user is not guaranteed to hold, and one unreachable replica would take the whole
259+
> fleet out of rotation.
260+
>
239261
> Prefer **toggle first**, have the `--wrap-only` command ready to run the moment every backend instance is up, and
240-
> keep the window to seconds. Both directions are delete-path-only and fail loudly rather than corrupting
241-
> anything, which is what makes a short window acceptable — but on a shared environment announce it, and do
242-
> not leave the toggle `true` without the wrap (or vice versa) for any length of time.
262+
> keep the window to seconds. Nothing in either direction corrupts data — that is what makes a short window
263+
> acceptable — but announce it on a shared environment, and do not leave the toggle `true` without the wrap (or vice
264+
> versa) for any length of time: with the readiness check in place that is now an outage, not a degradation.
243265
>
244266
> **Monitoring consequence of the flip:** `system.parts` only knows `traces_local` post-wrap, so the
245267
> `opik.clickhouse.partition.*` parts gauges relabel from `table="traces"` to `table="traces_local"`, while the

apps/opik-backend/src/main/java/com/comet/opik/infrastructure/DatabaseAnalyticsDataModelConfig.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@
5050
* {@code MODIFY COLUMN} must be applied to <b>both</b> {@code traces_local} and the {@code Distributed} {@code traces}
5151
* (the wrapper accepts them as metadata-only, and targeting only {@code traces_local} leaves the wrapper without the
5252
* column, so reads fail with code 47).</p>
53+
*
54+
* <p>This flag is asserted against the live topology at readiness by
55+
* {@code ClickHouseTracesTopologyHealthCheck}: either direction of mismatch fails the
56+
* {@code clickhouse-traces-topology} probe with a message naming the flag and the observed engine, so an install whose
57+
* flag and database disagree is pulled from rotation instead of discovering it on its first trace delete. The flag
58+
* stays the source of truth — the probe only reports, it never re-routes.</p>
5359
*/
5460
@Builder(toBuilder = true)
5561
public record DatabaseAnalyticsDataModelConfig(

apps/opik-backend/src/main/java/com/comet/opik/infrastructure/db/AbstractClickHouseExistenceHealthCheck.java renamed to apps/opik-backend/src/main/java/com/comet/opik/infrastructure/db/healthchecks/AbstractClickHouseExistenceHealthCheck.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.comet.opik.infrastructure.db;
1+
package com.comet.opik.infrastructure.db.healthchecks;
22

33
import com.clickhouse.client.api.Client;
44
import com.clickhouse.client.api.query.Records;

apps/opik-backend/src/main/java/com/comet/opik/infrastructure/db/AbstractClickHouseHealthCheck.java renamed to apps/opik-backend/src/main/java/com/comet/opik/infrastructure/db/healthchecks/AbstractClickHouseHealthCheck.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.comet.opik.infrastructure.db;
1+
package com.comet.opik.infrastructure.db.healthchecks;
22

33
import com.clickhouse.client.api.Client;
44
import com.clickhouse.client.api.query.QuerySettings;

apps/opik-backend/src/main/java/com/comet/opik/infrastructure/db/ClickHouseClusterHealthCheck.java renamed to apps/opik-backend/src/main/java/com/comet/opik/infrastructure/db/healthchecks/ClickHouseClusterHealthCheck.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.comet.opik.infrastructure.db;
1+
package com.comet.opik.infrastructure.db.healthchecks;
22

33
import com.clickhouse.client.api.Client;
44
import com.comet.opik.infrastructure.DatabaseAnalyticsFactory;

apps/opik-backend/src/main/java/com/comet/opik/infrastructure/db/ClickHouseColdStorageDiskHealthCheck.java renamed to apps/opik-backend/src/main/java/com/comet/opik/infrastructure/db/healthchecks/ClickHouseColdStorageDiskHealthCheck.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.comet.opik.infrastructure.db;
1+
package com.comet.opik.infrastructure.db.healthchecks;
22

33
import com.clickhouse.client.api.Client;
44
import com.comet.opik.infrastructure.DatabaseAnalyticsFactory;

apps/opik-backend/src/main/java/com/comet/opik/infrastructure/db/ClickHouseHealthCheck.java renamed to apps/opik-backend/src/main/java/com/comet/opik/infrastructure/db/healthchecks/ClickHouseHealthCheck.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.comet.opik.infrastructure.db;
1+
package com.comet.opik.infrastructure.db.healthchecks;
22

33
import com.clickhouse.client.api.Client;
44
import io.dropwizard.util.Duration;

apps/opik-backend/src/main/java/com/comet/opik/infrastructure/db/ClickHouseReadOnlyFreeFormSqlHealthCheck.java renamed to apps/opik-backend/src/main/java/com/comet/opik/infrastructure/db/healthchecks/ClickHouseReadOnlyFreeFormSqlHealthCheck.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.comet.opik.infrastructure.db;
1+
package com.comet.opik.infrastructure.db.healthchecks;
22

33
import com.clickhouse.client.api.Client;
44
import com.clickhouse.client.api.query.QuerySettings;

0 commit comments

Comments
 (0)