airbyte-internal-ops 0.10.0__py3-none-any.whl → 0.10.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {airbyte_internal_ops-0.10.0.dist-info → airbyte_internal_ops-0.10.2.dist-info}/METADATA +1 -1
- {airbyte_internal_ops-0.10.0.dist-info → airbyte_internal_ops-0.10.2.dist-info}/RECORD +9 -9
- airbyte_ops_mcp/cloud_admin/api_client.py +70 -0
- airbyte_ops_mcp/mcp/connector_rollout.py +104 -1
- airbyte_ops_mcp/mcp/prod_db_queries.py +0 -87
- airbyte_ops_mcp/prod_db_access/queries.py +0 -61
- airbyte_ops_mcp/prod_db_access/sql.py +0 -91
- {airbyte_internal_ops-0.10.0.dist-info → airbyte_internal_ops-0.10.2.dist-info}/WHEEL +0 -0
- {airbyte_internal_ops-0.10.0.dist-info → airbyte_internal_ops-0.10.2.dist-info}/entry_points.txt +0 -0
|
@@ -231,7 +231,7 @@ airbyte_ops_mcp/cli/gh.py,sha256=koJPu0MDB6AW7mJq2z4dZV65ofvsZTkqoeitGF8KJR8,536
|
|
|
231
231
|
airbyte_ops_mcp/cli/local.py,sha256=amxtJ7aY1nrOs36zuWkV7jZVMyHNLT7HDUvyyOXF8mM,44459
|
|
232
232
|
airbyte_ops_mcp/cli/registry.py,sha256=CVm15_6YWpLD99DZ8f8y68npXJw01Ckde7Ty3o89YNE,16631
|
|
233
233
|
airbyte_ops_mcp/cloud_admin/__init__.py,sha256=cqE96Q10Kp6elhH9DAi6TVsIwSUy3sooDLLrxTaktGk,816
|
|
234
|
-
airbyte_ops_mcp/cloud_admin/api_client.py,sha256=
|
|
234
|
+
airbyte_ops_mcp/cloud_admin/api_client.py,sha256=tqqXZumM5UGZ81RkA3ZAkIYp2z6e8izSnic9KBTnnSo,72851
|
|
235
235
|
airbyte_ops_mcp/cloud_admin/auth.py,sha256=qE2Aqe0qbZB755KscL65s54Jz78-F-X5a8fXKsrYEOQ,3749
|
|
236
236
|
airbyte_ops_mcp/cloud_admin/connection_config.py,sha256=9opGQer-cGMJANmm-LFLMwvMCNu3nzxa2n2XHkZj9Fw,4899
|
|
237
237
|
airbyte_ops_mcp/cloud_admin/models.py,sha256=Wn6O48Yp2QB3jsknmw-mG-LJ6GdBIyAg06MGLC1kOjM,8299
|
|
@@ -269,13 +269,13 @@ airbyte_ops_mcp/mcp/_guidance.py,sha256=n0dLggQXNi2PKZ0eFDqQx5YIjhQpMnI3xcjouub9
|
|
|
269
269
|
airbyte_ops_mcp/mcp/cloud_connector_versions.py,sha256=dRKrgsRGadQieTSvBrc5HYI6TTDzVAT6-4tiOHNcDHU,36244
|
|
270
270
|
airbyte_ops_mcp/mcp/connector_analysis.py,sha256=OC4KrOSkMkKPkOisWnSv96BDDE5TQYHq-Jxa2vtjJpo,298
|
|
271
271
|
airbyte_ops_mcp/mcp/connector_qa.py,sha256=aImpqdnqBPDrz10BS0owsV4kuIU2XdalzgbaGZsbOL0,258
|
|
272
|
-
airbyte_ops_mcp/mcp/connector_rollout.py,sha256=
|
|
272
|
+
airbyte_ops_mcp/mcp/connector_rollout.py,sha256=HxHAXZm3bIf_DjNJ04954twTyQHw-X9BEYJJFE6xCPg,32635
|
|
273
273
|
airbyte_ops_mcp/mcp/gcp_logs.py,sha256=QCDQHmsxQHJ26BB0sxkBgKXr7Ja9wVFkdpY6423H-xo,2677
|
|
274
274
|
airbyte_ops_mcp/mcp/github_actions.py,sha256=G0NmjNVWpVtLXdQnhX7qJwPFkfEX5gBXf55xt0FpJJ0,11752
|
|
275
275
|
airbyte_ops_mcp/mcp/github_repo_ops.py,sha256=YHeuN7Xc_L3xkJ-F3l1t1TIPW2j2CjecBDbb0DUvZO8,5306
|
|
276
276
|
airbyte_ops_mcp/mcp/metadata.py,sha256=fwGW97WknR5lfKcQnFtK6dU87aA6TmLj1NkKyqDAV9g,270
|
|
277
277
|
airbyte_ops_mcp/mcp/prerelease.py,sha256=jSrAwk95vZLfwYFn5Menb-ziAMTUZnzAMHIJAitd9x8,9553
|
|
278
|
-
airbyte_ops_mcp/mcp/prod_db_queries.py,sha256=
|
|
278
|
+
airbyte_ops_mcp/mcp/prod_db_queries.py,sha256=GzR_R4QXy15benTmF6sKdwP0YBx18GOvB-zGqz8AOeY,53228
|
|
279
279
|
airbyte_ops_mcp/mcp/prompts.py,sha256=v4bguskw7hSsISkseACzKQm5QwrIXmiwbs27oclXTE8,1591
|
|
280
280
|
airbyte_ops_mcp/mcp/registry.py,sha256=PW-VYUj42qx2pQ_apUkVaoUFq7VgB9zEU7-aGrkSCCw,290
|
|
281
281
|
airbyte_ops_mcp/mcp/regression_tests.py,sha256=zwdQ-ymUhWtVcIjwiNIZAC151GKhuxi55HDi4S91RnI,17046
|
|
@@ -283,8 +283,8 @@ airbyte_ops_mcp/mcp/server.py,sha256=7VO-awh4gh51EiYCkUvEyQd4r1gl6XRJ4-I-JybkEiA
|
|
|
283
283
|
airbyte_ops_mcp/prod_db_access/__init__.py,sha256=5pxouMPY1beyWlB0UwPnbaLTKTHqU6X82rbbgKY2vYU,1069
|
|
284
284
|
airbyte_ops_mcp/prod_db_access/db_engine.py,sha256=VUqEWZtharJUR-Cri_pMwtGh1C4Neu4s195mbEXlm-w,9190
|
|
285
285
|
airbyte_ops_mcp/prod_db_access/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
286
|
-
airbyte_ops_mcp/prod_db_access/queries.py,sha256=
|
|
287
|
-
airbyte_ops_mcp/prod_db_access/sql.py,sha256=
|
|
286
|
+
airbyte_ops_mcp/prod_db_access/queries.py,sha256=AkI6sclY2KNrolzXeDyh2s2aYFdUbaoTkLYxQpupasw,25577
|
|
287
|
+
airbyte_ops_mcp/prod_db_access/sql.py,sha256=6t4_ePFgEIGrZzoj9IRdeBydw7im1XxTS9bfsaZ290c,45888
|
|
288
288
|
airbyte_ops_mcp/registry/__init__.py,sha256=iEaPlt9GrnlaLbc__98TguNeZG8wuQu7S-_2QkhHcbA,858
|
|
289
289
|
airbyte_ops_mcp/registry/_gcs_util.py,sha256=3dL7iqpyoSPfl2nGBPp73TqrqGWI4Ks6egKpQXDnw24,2838
|
|
290
290
|
airbyte_ops_mcp/registry/connector_stubs.py,sha256=pBzaQIOgCfBvHuy3_N45amU9Do2ALDpU8q5HnZySPTQ,5807
|
|
@@ -310,7 +310,7 @@ airbyte_ops_mcp/regression_tests/regression/comparators.py,sha256=MJkLZEKHivgrG0
|
|
|
310
310
|
airbyte_ops_mcp/regression_tests/validation/__init__.py,sha256=MBEwGOoNuqT4_oCahtoK62OKWIjUCfWa7vZTxNj_0Ek,1532
|
|
311
311
|
airbyte_ops_mcp/regression_tests/validation/catalog_validators.py,sha256=jqqVAMOk0mtdPgwu4d0hA0ZEjtsNh5gapvGydRv3_qk,12553
|
|
312
312
|
airbyte_ops_mcp/regression_tests/validation/record_validators.py,sha256=RjauAhKWNwxMBTu0eNS2hMFNQVs5CLbQU51kp6FOVDk,7432
|
|
313
|
-
airbyte_internal_ops-0.10.
|
|
314
|
-
airbyte_internal_ops-0.10.
|
|
315
|
-
airbyte_internal_ops-0.10.
|
|
316
|
-
airbyte_internal_ops-0.10.
|
|
313
|
+
airbyte_internal_ops-0.10.2.dist-info/METADATA,sha256=R_eF8wt1HmZ88Ct0dLSqGnEV-N1y9BI2oUscodQO5wg,6002
|
|
314
|
+
airbyte_internal_ops-0.10.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
315
|
+
airbyte_internal_ops-0.10.2.dist-info/entry_points.txt,sha256=WxP0l7bRFss4Cr5uQqVj9mTEKwnRKouNuphXQF0lotA,171
|
|
316
|
+
airbyte_internal_ops-0.10.2.dist-info/RECORD,,
|
|
@@ -1768,3 +1768,73 @@ def finalize_connector_rollout(
|
|
|
1768
1768
|
)
|
|
1769
1769
|
|
|
1770
1770
|
return response.json()
|
|
1771
|
+
|
|
1772
|
+
|
|
1773
|
+
def get_actor_sync_info(
|
|
1774
|
+
rollout_id: str,
|
|
1775
|
+
config_api_root: str,
|
|
1776
|
+
client_id: str | None = None,
|
|
1777
|
+
client_secret: str | None = None,
|
|
1778
|
+
bearer_token: str | None = None,
|
|
1779
|
+
) -> dict[str, Any]:
|
|
1780
|
+
"""Get actor sync info for a connector rollout.
|
|
1781
|
+
|
|
1782
|
+
This function calls the platform API to get sync statistics for actors
|
|
1783
|
+
participating in a rollout. Unlike the SQL-based approach, this endpoint
|
|
1784
|
+
filters sync stats to only include syncs that actually used the RC version
|
|
1785
|
+
associated with the rollout.
|
|
1786
|
+
|
|
1787
|
+
Args:
|
|
1788
|
+
rollout_id: The rollout ID (UUID)
|
|
1789
|
+
config_api_root: The Config API root URL (e.g., CLOUD_CONFIG_API_ROOT)
|
|
1790
|
+
client_id: The Airbyte Cloud client ID (required if no bearer_token)
|
|
1791
|
+
client_secret: The Airbyte Cloud client secret (required if no bearer_token)
|
|
1792
|
+
bearer_token: Pre-existing bearer token (takes precedence over client credentials)
|
|
1793
|
+
|
|
1794
|
+
Returns:
|
|
1795
|
+
Dictionary containing:
|
|
1796
|
+
- data.actorSelectionInfo: Info about actor selection (numActors, numPinnedToConnectorRollout, etc.)
|
|
1797
|
+
- data.syncs: Dict mapping actor_id to sync stats (numConnections, numSucceeded, numFailed)
|
|
1798
|
+
|
|
1799
|
+
Raises:
|
|
1800
|
+
PyAirbyteInputError: If the API request fails or rollout not found
|
|
1801
|
+
"""
|
|
1802
|
+
access_token = _get_access_token(client_id, client_secret, bearer_token)
|
|
1803
|
+
|
|
1804
|
+
endpoint = f"{config_api_root}/connector_rollout/get_actor_sync_info"
|
|
1805
|
+
payload = {"id": rollout_id}
|
|
1806
|
+
|
|
1807
|
+
response = requests.post(
|
|
1808
|
+
endpoint,
|
|
1809
|
+
json=payload,
|
|
1810
|
+
headers={
|
|
1811
|
+
"Authorization": f"Bearer {access_token}",
|
|
1812
|
+
"User-Agent": ops_constants.USER_AGENT,
|
|
1813
|
+
"Content-Type": "application/json",
|
|
1814
|
+
},
|
|
1815
|
+
timeout=60,
|
|
1816
|
+
)
|
|
1817
|
+
|
|
1818
|
+
if response.status_code == 404:
|
|
1819
|
+
raise PyAirbyteInputError(
|
|
1820
|
+
message=f"Rollout not found: {rollout_id}",
|
|
1821
|
+
context={
|
|
1822
|
+
"rollout_id": rollout_id,
|
|
1823
|
+
"endpoint": endpoint,
|
|
1824
|
+
"status_code": response.status_code,
|
|
1825
|
+
"response": response.text,
|
|
1826
|
+
},
|
|
1827
|
+
)
|
|
1828
|
+
|
|
1829
|
+
if response.status_code != 200:
|
|
1830
|
+
raise PyAirbyteInputError(
|
|
1831
|
+
message=f"Failed to get actor sync info: {response.status_code} {response.text}",
|
|
1832
|
+
context={
|
|
1833
|
+
"rollout_id": rollout_id,
|
|
1834
|
+
"endpoint": endpoint,
|
|
1835
|
+
"status_code": response.status_code,
|
|
1836
|
+
"response": response.text,
|
|
1837
|
+
},
|
|
1838
|
+
)
|
|
1839
|
+
|
|
1840
|
+
return response.json()
|
|
@@ -17,7 +17,7 @@ from airbyte import constants
|
|
|
17
17
|
from airbyte.exceptions import PyAirbyteInputError
|
|
18
18
|
from fastmcp import Context, FastMCP
|
|
19
19
|
from fastmcp_extensions import get_mcp_config, mcp_tool, register_mcp_tools
|
|
20
|
-
from pydantic import Field
|
|
20
|
+
from pydantic import BaseModel, Field
|
|
21
21
|
|
|
22
22
|
from airbyte_ops_mcp.cloud_admin import api_client
|
|
23
23
|
from airbyte_ops_mcp.cloud_admin.auth import (
|
|
@@ -770,6 +770,109 @@ def finalize_connector_rollout(
|
|
|
770
770
|
)
|
|
771
771
|
|
|
772
772
|
|
|
773
|
+
class RolloutActorSelectionInfo(BaseModel):
|
|
774
|
+
"""Actor selection info for a connector rollout."""
|
|
775
|
+
|
|
776
|
+
num_actors: int = Field(description="Total actors using this connector")
|
|
777
|
+
num_pinned_to_connector_rollout: int = Field(
|
|
778
|
+
description="Actors specifically pinned to this rollout"
|
|
779
|
+
)
|
|
780
|
+
num_actors_eligible_or_already_pinned: int = Field(
|
|
781
|
+
description="Actors eligible for pinning or already pinned"
|
|
782
|
+
)
|
|
783
|
+
|
|
784
|
+
|
|
785
|
+
class RolloutActorSyncStats(BaseModel):
|
|
786
|
+
"""Per-actor sync stats for a rollout (only syncs using the RC version)."""
|
|
787
|
+
|
|
788
|
+
actor_id: str = Field(description="Actor UUID")
|
|
789
|
+
num_connections: int = Field(description="Number of connections using this actor")
|
|
790
|
+
num_succeeded: int = Field(
|
|
791
|
+
description="Number of successful syncs using the RC version"
|
|
792
|
+
)
|
|
793
|
+
num_failed: int = Field(description="Number of failed syncs using the RC version")
|
|
794
|
+
|
|
795
|
+
|
|
796
|
+
class RolloutMonitoringResult(BaseModel):
|
|
797
|
+
"""Complete monitoring result for a rollout from the platform API.
|
|
798
|
+
|
|
799
|
+
This uses the platform API's /get_actor_sync_info endpoint which filters
|
|
800
|
+
sync stats to only include syncs that actually used the RC version
|
|
801
|
+
associated with the rollout.
|
|
802
|
+
"""
|
|
803
|
+
|
|
804
|
+
rollout_id: str = Field(description="Rollout UUID")
|
|
805
|
+
actor_selection_info: RolloutActorSelectionInfo = Field(
|
|
806
|
+
description="Actor selection info for the rollout"
|
|
807
|
+
)
|
|
808
|
+
actor_sync_stats: list[RolloutActorSyncStats] = Field(
|
|
809
|
+
description="Per-actor sync stats for actors pinned to the rollout"
|
|
810
|
+
)
|
|
811
|
+
|
|
812
|
+
|
|
813
|
+
@mcp_tool(
|
|
814
|
+
read_only=True,
|
|
815
|
+
idempotent=True,
|
|
816
|
+
)
|
|
817
|
+
def query_prod_rollout_monitoring_stats(
|
|
818
|
+
rollout_id: Annotated[
|
|
819
|
+
str,
|
|
820
|
+
Field(description="Rollout UUID to get monitoring stats for"),
|
|
821
|
+
],
|
|
822
|
+
*,
|
|
823
|
+
ctx: Context,
|
|
824
|
+
) -> RolloutMonitoringResult:
|
|
825
|
+
"""Get monitoring stats for a connector rollout.
|
|
826
|
+
|
|
827
|
+
Returns actor selection info and per-actor sync stats for actors
|
|
828
|
+
participating in the rollout. This uses the platform API's
|
|
829
|
+
/get_actor_sync_info endpoint which filters sync stats to only include
|
|
830
|
+
syncs that actually used the RC version associated with the rollout.
|
|
831
|
+
|
|
832
|
+
This is more accurate than SQL-based approaches which count all syncs
|
|
833
|
+
regardless of which connector version was used.
|
|
834
|
+
"""
|
|
835
|
+
auth = _resolve_cloud_auth(ctx)
|
|
836
|
+
|
|
837
|
+
response = api_client.get_actor_sync_info(
|
|
838
|
+
rollout_id=rollout_id,
|
|
839
|
+
config_api_root=constants.CLOUD_CONFIG_API_ROOT,
|
|
840
|
+
client_id=auth.client_id,
|
|
841
|
+
client_secret=auth.client_secret,
|
|
842
|
+
bearer_token=auth.bearer_token,
|
|
843
|
+
)
|
|
844
|
+
|
|
845
|
+
data = response.get("data", {})
|
|
846
|
+
actor_selection_info_data = data.get("actor_selection_info", {})
|
|
847
|
+
syncs_data = data.get("syncs", {})
|
|
848
|
+
|
|
849
|
+
actor_selection_info = RolloutActorSelectionInfo(
|
|
850
|
+
num_actors=actor_selection_info_data.get("num_actors", 0),
|
|
851
|
+
num_pinned_to_connector_rollout=actor_selection_info_data.get(
|
|
852
|
+
"num_pinned_to_connector_rollout", 0
|
|
853
|
+
),
|
|
854
|
+
num_actors_eligible_or_already_pinned=actor_selection_info_data.get(
|
|
855
|
+
"num_actors_eligible_or_already_pinned", 0
|
|
856
|
+
),
|
|
857
|
+
)
|
|
858
|
+
|
|
859
|
+
actor_sync_stats = [
|
|
860
|
+
RolloutActorSyncStats(
|
|
861
|
+
actor_id=actor_id,
|
|
862
|
+
num_connections=sync_info.get("num_connections", 0),
|
|
863
|
+
num_succeeded=sync_info.get("num_succeeded", 0),
|
|
864
|
+
num_failed=sync_info.get("num_failed", 0),
|
|
865
|
+
)
|
|
866
|
+
for actor_id, sync_info in syncs_data.items()
|
|
867
|
+
]
|
|
868
|
+
|
|
869
|
+
return RolloutMonitoringResult(
|
|
870
|
+
rollout_id=rollout_id,
|
|
871
|
+
actor_selection_info=actor_selection_info,
|
|
872
|
+
actor_sync_stats=actor_sync_stats,
|
|
873
|
+
)
|
|
874
|
+
|
|
875
|
+
|
|
773
876
|
def register_connector_rollout_tools(app: FastMCP) -> None:
|
|
774
877
|
"""Register connector rollout tools with the FastMCP app.
|
|
775
878
|
|
|
@@ -1412,93 +1412,6 @@ def query_prod_connector_rollouts(
|
|
|
1412
1412
|
return [_row_to_connector_rollout_info(row) for row in rows]
|
|
1413
1413
|
|
|
1414
1414
|
|
|
1415
|
-
class RolloutMonitoringStats(BaseModel):
|
|
1416
|
-
"""Aggregate monitoring stats for a connector rollout."""
|
|
1417
|
-
|
|
1418
|
-
rollout_id: str = Field(description="Rollout UUID")
|
|
1419
|
-
actor_definition_id: str = Field(description="Connector definition UUID")
|
|
1420
|
-
num_actors: int = Field(description="Total actors using this connector")
|
|
1421
|
-
num_actors_pinned: int = Field(
|
|
1422
|
-
description="Actors with any version pin (eligible or already pinned)"
|
|
1423
|
-
)
|
|
1424
|
-
num_pinned_to_rollout: int = Field(
|
|
1425
|
-
description="Actors specifically pinned to this rollout"
|
|
1426
|
-
)
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
class RolloutActorSyncStats(BaseModel):
|
|
1430
|
-
"""Per-actor sync stats for a rollout."""
|
|
1431
|
-
|
|
1432
|
-
actor_id: str = Field(description="Actor UUID")
|
|
1433
|
-
num_succeeded: int = Field(description="Number of successful syncs")
|
|
1434
|
-
num_failed: int = Field(description="Number of failed syncs")
|
|
1435
|
-
num_connections: int = Field(description="Number of connections using this actor")
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
class RolloutMonitoringResult(BaseModel):
|
|
1439
|
-
"""Complete monitoring result for a rollout."""
|
|
1440
|
-
|
|
1441
|
-
aggregate_stats: RolloutMonitoringStats = Field(
|
|
1442
|
-
description="Aggregate counts for the rollout"
|
|
1443
|
-
)
|
|
1444
|
-
actor_stats: list[RolloutActorSyncStats] = Field(
|
|
1445
|
-
description="Per-actor sync stats for actors pinned to the rollout"
|
|
1446
|
-
)
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
@mcp_tool(
|
|
1450
|
-
read_only=True,
|
|
1451
|
-
idempotent=True,
|
|
1452
|
-
)
|
|
1453
|
-
def query_prod_rollout_monitoring_stats(
|
|
1454
|
-
rollout_id: Annotated[
|
|
1455
|
-
str,
|
|
1456
|
-
Field(description="Rollout UUID to get monitoring stats for"),
|
|
1457
|
-
],
|
|
1458
|
-
days_back: Annotated[
|
|
1459
|
-
int,
|
|
1460
|
-
Field(description="Number of days to look back for sync stats (default: 7)"),
|
|
1461
|
-
] = 7,
|
|
1462
|
-
) -> RolloutMonitoringResult:
|
|
1463
|
-
"""Get monitoring stats for a connector rollout.
|
|
1464
|
-
|
|
1465
|
-
Returns aggregate counts (total actors, pinned actors, rollout-pinned actors)
|
|
1466
|
-
and per-actor sync stats (succeeded, failed, connections) for actors
|
|
1467
|
-
participating in the rollout. This replaces the Retool rollout monitoring UI.
|
|
1468
|
-
"""
|
|
1469
|
-
from airbyte_ops_mcp.prod_db_access.queries import (
|
|
1470
|
-
query_rollout_actor_sync_stats,
|
|
1471
|
-
query_rollout_monitoring_stats,
|
|
1472
|
-
)
|
|
1473
|
-
|
|
1474
|
-
agg_stats = query_rollout_monitoring_stats(rollout_id=rollout_id)
|
|
1475
|
-
if agg_stats is None:
|
|
1476
|
-
raise ValueError(f"Rollout not found: {rollout_id}")
|
|
1477
|
-
|
|
1478
|
-
actor_stats = query_rollout_actor_sync_stats(
|
|
1479
|
-
rollout_id=rollout_id, days_back=days_back
|
|
1480
|
-
)
|
|
1481
|
-
|
|
1482
|
-
return RolloutMonitoringResult(
|
|
1483
|
-
aggregate_stats=RolloutMonitoringStats(
|
|
1484
|
-
rollout_id=str(agg_stats["rollout_id"]),
|
|
1485
|
-
actor_definition_id=str(agg_stats["actor_definition_id"]),
|
|
1486
|
-
num_actors=agg_stats["num_actors"] or 0,
|
|
1487
|
-
num_actors_pinned=agg_stats["num_actors_pinned"] or 0,
|
|
1488
|
-
num_pinned_to_rollout=agg_stats["num_pinned_to_rollout"] or 0,
|
|
1489
|
-
),
|
|
1490
|
-
actor_stats=[
|
|
1491
|
-
RolloutActorSyncStats(
|
|
1492
|
-
actor_id=str(row["actor_id"]),
|
|
1493
|
-
num_succeeded=row["num_succeeded"] or 0,
|
|
1494
|
-
num_failed=row["num_failed"] or 0,
|
|
1495
|
-
num_connections=row["num_connections"] or 0,
|
|
1496
|
-
)
|
|
1497
|
-
for row in actor_stats
|
|
1498
|
-
],
|
|
1499
|
-
)
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
1415
|
def register_prod_db_query_tools(app: FastMCP) -> None:
|
|
1503
1416
|
"""Register prod DB query tools with the FastMCP app."""
|
|
1504
1417
|
register_mcp_tools(app, mcp_module=__name__)
|
|
@@ -42,8 +42,6 @@ from airbyte_ops_mcp.prod_db_access.sql import (
|
|
|
42
42
|
SELECT_RECENT_SUCCESSFUL_SYNCS_FOR_SOURCE_CONNECTOR,
|
|
43
43
|
SELECT_RECENT_SYNCS_FOR_DESTINATION_CONNECTOR,
|
|
44
44
|
SELECT_RECENT_SYNCS_FOR_SOURCE_CONNECTOR,
|
|
45
|
-
SELECT_ROLLOUT_ACTOR_SYNC_STATS,
|
|
46
|
-
SELECT_ROLLOUT_AGGREGATE_STATS,
|
|
47
45
|
SELECT_SOURCE_CONNECTION_STATS,
|
|
48
46
|
SELECT_SUCCESSFUL_SYNCS_FOR_VERSION,
|
|
49
47
|
SELECT_SYNC_RESULTS_FOR_VERSION,
|
|
@@ -701,62 +699,3 @@ def query_connector_rollouts(
|
|
|
701
699
|
query_name="SELECT_ACTIVE_CONNECTOR_ROLLOUTS",
|
|
702
700
|
gsm_client=gsm_client,
|
|
703
701
|
)
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
def query_rollout_monitoring_stats(
|
|
707
|
-
rollout_id: str,
|
|
708
|
-
*,
|
|
709
|
-
gsm_client: secretmanager.SecretManagerServiceClient | None = None,
|
|
710
|
-
) -> dict[str, Any] | None:
|
|
711
|
-
"""Query aggregate monitoring stats for a rollout.
|
|
712
|
-
|
|
713
|
-
Returns counts of total actors, actors with any pin, and actors pinned
|
|
714
|
-
specifically to this rollout.
|
|
715
|
-
|
|
716
|
-
Args:
|
|
717
|
-
rollout_id: Rollout UUID to get stats for
|
|
718
|
-
gsm_client: GCP Secret Manager client. If None, a new client will be instantiated.
|
|
719
|
-
|
|
720
|
-
Returns:
|
|
721
|
-
Dict with rollout_id, actor_definition_id, num_actors, num_actors_pinned,
|
|
722
|
-
num_pinned_to_rollout, or None if rollout not found
|
|
723
|
-
"""
|
|
724
|
-
rows = _run_sql_query(
|
|
725
|
-
SELECT_ROLLOUT_AGGREGATE_STATS,
|
|
726
|
-
parameters={"rollout_id": rollout_id},
|
|
727
|
-
query_name="SELECT_ROLLOUT_AGGREGATE_STATS",
|
|
728
|
-
gsm_client=gsm_client,
|
|
729
|
-
)
|
|
730
|
-
# The SQL query uses scalar subqueries that always return one row,
|
|
731
|
-
# but with NULL values if the rollout doesn't exist
|
|
732
|
-
if rows and rows[0].get("rollout_id") is not None:
|
|
733
|
-
return rows[0]
|
|
734
|
-
return None
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
def query_rollout_actor_sync_stats(
|
|
738
|
-
rollout_id: str,
|
|
739
|
-
days_back: int = 7,
|
|
740
|
-
*,
|
|
741
|
-
gsm_client: secretmanager.SecretManagerServiceClient | None = None,
|
|
742
|
-
) -> list[dict[str, Any]]:
|
|
743
|
-
"""Query per-actor sync stats for actors pinned to a rollout.
|
|
744
|
-
|
|
745
|
-
Returns succeeded/failed job counts and connection counts for each actor
|
|
746
|
-
that is pinned to the specified rollout.
|
|
747
|
-
|
|
748
|
-
Args:
|
|
749
|
-
rollout_id: Rollout UUID to get actor stats for
|
|
750
|
-
days_back: Number of days to look back for job stats (default: 7)
|
|
751
|
-
gsm_client: GCP Secret Manager client. If None, a new client will be instantiated.
|
|
752
|
-
|
|
753
|
-
Returns:
|
|
754
|
-
List of dicts with actor_id, num_succeeded, num_failed, num_connections
|
|
755
|
-
"""
|
|
756
|
-
cutoff_date = datetime.now(timezone.utc) - timedelta(days=days_back)
|
|
757
|
-
return _run_sql_query(
|
|
758
|
-
SELECT_ROLLOUT_ACTOR_SYNC_STATS,
|
|
759
|
-
parameters={"rollout_id": rollout_id, "cutoff_date": cutoff_date},
|
|
760
|
-
query_name="SELECT_ROLLOUT_ACTOR_SYNC_STATS",
|
|
761
|
-
gsm_client=gsm_client,
|
|
762
|
-
)
|
|
@@ -1217,94 +1217,3 @@ SELECT_ACTORS_PINNED_TO_ROLLOUT = sqlalchemy.text(
|
|
|
1217
1217
|
scoped_configuration.created_at DESC
|
|
1218
1218
|
"""
|
|
1219
1219
|
)
|
|
1220
|
-
|
|
1221
|
-
# Get rollout monitoring stats: aggregate counts for a rollout
|
|
1222
|
-
# Returns: total actors for connector, actors with any pin, actors pinned to this rollout
|
|
1223
|
-
SELECT_ROLLOUT_AGGREGATE_STATS = sqlalchemy.text(
|
|
1224
|
-
"""
|
|
1225
|
-
WITH rollout_info AS (
|
|
1226
|
-
SELECT
|
|
1227
|
-
cr.id AS rollout_id,
|
|
1228
|
-
cr.actor_definition_id,
|
|
1229
|
-
cr.release_candidate_version_id
|
|
1230
|
-
FROM connector_rollout cr
|
|
1231
|
-
WHERE cr.id = :rollout_id
|
|
1232
|
-
),
|
|
1233
|
-
total_actors AS (
|
|
1234
|
-
SELECT COUNT(*) AS num_actors
|
|
1235
|
-
FROM actor
|
|
1236
|
-
WHERE actor.actor_definition_id = (SELECT actor_definition_id FROM rollout_info)
|
|
1237
|
-
AND actor.tombstone = false
|
|
1238
|
-
),
|
|
1239
|
-
pinned_actors AS (
|
|
1240
|
-
SELECT COUNT(DISTINCT scoped_configuration.scope_id) AS num_pinned
|
|
1241
|
-
FROM scoped_configuration
|
|
1242
|
-
JOIN actor ON scoped_configuration.scope_id = actor.id
|
|
1243
|
-
WHERE scoped_configuration.key = 'connector_version'
|
|
1244
|
-
AND scoped_configuration.scope_type = 'actor'
|
|
1245
|
-
AND actor.actor_definition_id = (SELECT actor_definition_id FROM rollout_info)
|
|
1246
|
-
AND actor.tombstone = false
|
|
1247
|
-
),
|
|
1248
|
-
rollout_pinned_actors AS (
|
|
1249
|
-
SELECT COUNT(DISTINCT scoped_configuration.scope_id) AS num_rollout_pinned
|
|
1250
|
-
FROM scoped_configuration
|
|
1251
|
-
WHERE scoped_configuration.key = 'connector_version'
|
|
1252
|
-
AND scoped_configuration.scope_type = 'actor'
|
|
1253
|
-
AND scoped_configuration.origin = :rollout_id
|
|
1254
|
-
)
|
|
1255
|
-
SELECT
|
|
1256
|
-
(SELECT rollout_id FROM rollout_info) AS rollout_id,
|
|
1257
|
-
(SELECT actor_definition_id FROM rollout_info) AS actor_definition_id,
|
|
1258
|
-
(SELECT num_actors FROM total_actors) AS num_actors,
|
|
1259
|
-
(SELECT num_pinned FROM pinned_actors) AS num_actors_pinned,
|
|
1260
|
-
(SELECT num_rollout_pinned FROM rollout_pinned_actors) AS num_pinned_to_rollout
|
|
1261
|
-
"""
|
|
1262
|
-
)
|
|
1263
|
-
|
|
1264
|
-
# Get per-actor sync stats for actors pinned to a rollout
|
|
1265
|
-
# Returns: actor_id, succeeded count, failed count, connection count
|
|
1266
|
-
SELECT_ROLLOUT_ACTOR_SYNC_STATS = sqlalchemy.text(
|
|
1267
|
-
"""
|
|
1268
|
-
WITH rollout_actors AS (
|
|
1269
|
-
SELECT DISTINCT
|
|
1270
|
-
scoped_configuration.scope_id AS actor_id
|
|
1271
|
-
FROM scoped_configuration
|
|
1272
|
-
WHERE scoped_configuration.key = 'connector_version'
|
|
1273
|
-
AND scoped_configuration.scope_type = 'actor'
|
|
1274
|
-
AND scoped_configuration.origin = :rollout_id
|
|
1275
|
-
),
|
|
1276
|
-
actor_connections AS (
|
|
1277
|
-
SELECT
|
|
1278
|
-
ra.actor_id,
|
|
1279
|
-
COUNT(DISTINCT c.id) AS num_connections
|
|
1280
|
-
FROM rollout_actors ra
|
|
1281
|
-
LEFT JOIN connection c
|
|
1282
|
-
ON c.source_id = ra.actor_id OR c.destination_id = ra.actor_id
|
|
1283
|
-
WHERE c.status != 'deprecated' OR c.status IS NULL
|
|
1284
|
-
GROUP BY ra.actor_id
|
|
1285
|
-
),
|
|
1286
|
-
actor_job_stats AS (
|
|
1287
|
-
SELECT
|
|
1288
|
-
ra.actor_id,
|
|
1289
|
-
COUNT(CASE WHEN j.status = 'succeeded' THEN 1 END) AS num_succeeded,
|
|
1290
|
-
COUNT(CASE WHEN j.status = 'failed' THEN 1 END) AS num_failed
|
|
1291
|
-
FROM rollout_actors ra
|
|
1292
|
-
LEFT JOIN connection c
|
|
1293
|
-
ON c.source_id = ra.actor_id OR c.destination_id = ra.actor_id
|
|
1294
|
-
LEFT JOIN jobs j
|
|
1295
|
-
ON j.scope = c.id::text
|
|
1296
|
-
AND j.config_type = 'sync'
|
|
1297
|
-
AND j.created_at >= :cutoff_date
|
|
1298
|
-
GROUP BY ra.actor_id
|
|
1299
|
-
)
|
|
1300
|
-
SELECT
|
|
1301
|
-
ra.actor_id,
|
|
1302
|
-
COALESCE(ajs.num_succeeded, 0) AS num_succeeded,
|
|
1303
|
-
COALESCE(ajs.num_failed, 0) AS num_failed,
|
|
1304
|
-
COALESCE(ac.num_connections, 0) AS num_connections
|
|
1305
|
-
FROM rollout_actors ra
|
|
1306
|
-
LEFT JOIN actor_job_stats ajs ON ra.actor_id = ajs.actor_id
|
|
1307
|
-
LEFT JOIN actor_connections ac ON ra.actor_id = ac.actor_id
|
|
1308
|
-
ORDER BY COALESCE(ajs.num_failed, 0) DESC, COALESCE(ajs.num_succeeded, 0) DESC
|
|
1309
|
-
"""
|
|
1310
|
-
)
|
|
File without changes
|
{airbyte_internal_ops-0.10.0.dist-info → airbyte_internal_ops-0.10.2.dist-info}/entry_points.txt
RENAMED
|
File without changes
|