hatchet-sdk 1.14.3__py3-none-any.whl → 1.15.0__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.
Potentially problematic release.
This version of hatchet-sdk might be problematic. Click here for more details.
- hatchet_sdk/clients/rest/api/tenant_api.py +266 -0
- hatchet_sdk/clients/rest/models/v1_task_summary.py +7 -0
- hatchet_sdk/features/metrics.py +101 -82
- hatchet_sdk/features/workflows.py +25 -0
- hatchet_sdk/runnables/workflow.py +16 -0
- hatchet_sdk/utils/serde.py +19 -9
- {hatchet_sdk-1.14.3.dist-info → hatchet_sdk-1.15.0.dist-info}/METADATA +1 -1
- {hatchet_sdk-1.14.3.dist-info → hatchet_sdk-1.15.0.dist-info}/RECORD +10 -10
- {hatchet_sdk-1.14.3.dist-info → hatchet_sdk-1.15.0.dist-info}/WHEEL +0 -0
- {hatchet_sdk-1.14.3.dist-info → hatchet_sdk-1.15.0.dist-info}/entry_points.txt +0 -0
|
@@ -2005,6 +2005,272 @@ class TenantApi:
|
|
|
2005
2005
|
_request_auth=_request_auth,
|
|
2006
2006
|
)
|
|
2007
2007
|
|
|
2008
|
+
@validate_call
|
|
2009
|
+
def tenant_get_prometheus_metrics(
|
|
2010
|
+
self,
|
|
2011
|
+
tenant: Annotated[
|
|
2012
|
+
str,
|
|
2013
|
+
Field(
|
|
2014
|
+
min_length=36, strict=True, max_length=36, description="The tenant id"
|
|
2015
|
+
),
|
|
2016
|
+
],
|
|
2017
|
+
_request_timeout: Union[
|
|
2018
|
+
None,
|
|
2019
|
+
Annotated[StrictFloat, Field(gt=0)],
|
|
2020
|
+
Tuple[
|
|
2021
|
+
Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
|
|
2022
|
+
],
|
|
2023
|
+
] = None,
|
|
2024
|
+
_request_auth: Optional[Dict[StrictStr, Any]] = None,
|
|
2025
|
+
_content_type: Optional[StrictStr] = None,
|
|
2026
|
+
_headers: Optional[Dict[StrictStr, Any]] = None,
|
|
2027
|
+
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
|
|
2028
|
+
) -> str:
|
|
2029
|
+
"""Get prometheus metrics
|
|
2030
|
+
|
|
2031
|
+
Get the prometheus metrics for the tenant
|
|
2032
|
+
|
|
2033
|
+
:param tenant: The tenant id (required)
|
|
2034
|
+
:type tenant: str
|
|
2035
|
+
:param _request_timeout: timeout setting for this request. If one
|
|
2036
|
+
number provided, it will be total request
|
|
2037
|
+
timeout. It can also be a pair (tuple) of
|
|
2038
|
+
(connection, read) timeouts.
|
|
2039
|
+
:type _request_timeout: int, tuple(int, int), optional
|
|
2040
|
+
:param _request_auth: set to override the auth_settings for an a single
|
|
2041
|
+
request; this effectively ignores the
|
|
2042
|
+
authentication in the spec for a single request.
|
|
2043
|
+
:type _request_auth: dict, optional
|
|
2044
|
+
:param _content_type: force content-type for the request.
|
|
2045
|
+
:type _content_type: str, Optional
|
|
2046
|
+
:param _headers: set to override the headers for a single
|
|
2047
|
+
request; this effectively ignores the headers
|
|
2048
|
+
in the spec for a single request.
|
|
2049
|
+
:type _headers: dict, optional
|
|
2050
|
+
:param _host_index: set to override the host_index for a single
|
|
2051
|
+
request; this effectively ignores the host_index
|
|
2052
|
+
in the spec for a single request.
|
|
2053
|
+
:type _host_index: int, optional
|
|
2054
|
+
:return: Returns the result object.
|
|
2055
|
+
""" # noqa: E501
|
|
2056
|
+
|
|
2057
|
+
_param = self._tenant_get_prometheus_metrics_serialize(
|
|
2058
|
+
tenant=tenant,
|
|
2059
|
+
_request_auth=_request_auth,
|
|
2060
|
+
_content_type=_content_type,
|
|
2061
|
+
_headers=_headers,
|
|
2062
|
+
_host_index=_host_index,
|
|
2063
|
+
)
|
|
2064
|
+
|
|
2065
|
+
_response_types_map: Dict[str, Optional[str]] = {
|
|
2066
|
+
"200": "str",
|
|
2067
|
+
"400": "APIErrors",
|
|
2068
|
+
"403": "APIErrors",
|
|
2069
|
+
"404": "APIErrors",
|
|
2070
|
+
}
|
|
2071
|
+
response_data = self.api_client.call_api(
|
|
2072
|
+
*_param, _request_timeout=_request_timeout
|
|
2073
|
+
)
|
|
2074
|
+
response_data.read()
|
|
2075
|
+
return self.api_client.response_deserialize(
|
|
2076
|
+
response_data=response_data,
|
|
2077
|
+
response_types_map=_response_types_map,
|
|
2078
|
+
).data
|
|
2079
|
+
|
|
2080
|
+
@validate_call
|
|
2081
|
+
def tenant_get_prometheus_metrics_with_http_info(
|
|
2082
|
+
self,
|
|
2083
|
+
tenant: Annotated[
|
|
2084
|
+
str,
|
|
2085
|
+
Field(
|
|
2086
|
+
min_length=36, strict=True, max_length=36, description="The tenant id"
|
|
2087
|
+
),
|
|
2088
|
+
],
|
|
2089
|
+
_request_timeout: Union[
|
|
2090
|
+
None,
|
|
2091
|
+
Annotated[StrictFloat, Field(gt=0)],
|
|
2092
|
+
Tuple[
|
|
2093
|
+
Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
|
|
2094
|
+
],
|
|
2095
|
+
] = None,
|
|
2096
|
+
_request_auth: Optional[Dict[StrictStr, Any]] = None,
|
|
2097
|
+
_content_type: Optional[StrictStr] = None,
|
|
2098
|
+
_headers: Optional[Dict[StrictStr, Any]] = None,
|
|
2099
|
+
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
|
|
2100
|
+
) -> ApiResponse[str]:
|
|
2101
|
+
"""Get prometheus metrics
|
|
2102
|
+
|
|
2103
|
+
Get the prometheus metrics for the tenant
|
|
2104
|
+
|
|
2105
|
+
:param tenant: The tenant id (required)
|
|
2106
|
+
:type tenant: str
|
|
2107
|
+
:param _request_timeout: timeout setting for this request. If one
|
|
2108
|
+
number provided, it will be total request
|
|
2109
|
+
timeout. It can also be a pair (tuple) of
|
|
2110
|
+
(connection, read) timeouts.
|
|
2111
|
+
:type _request_timeout: int, tuple(int, int), optional
|
|
2112
|
+
:param _request_auth: set to override the auth_settings for an a single
|
|
2113
|
+
request; this effectively ignores the
|
|
2114
|
+
authentication in the spec for a single request.
|
|
2115
|
+
:type _request_auth: dict, optional
|
|
2116
|
+
:param _content_type: force content-type for the request.
|
|
2117
|
+
:type _content_type: str, Optional
|
|
2118
|
+
:param _headers: set to override the headers for a single
|
|
2119
|
+
request; this effectively ignores the headers
|
|
2120
|
+
in the spec for a single request.
|
|
2121
|
+
:type _headers: dict, optional
|
|
2122
|
+
:param _host_index: set to override the host_index for a single
|
|
2123
|
+
request; this effectively ignores the host_index
|
|
2124
|
+
in the spec for a single request.
|
|
2125
|
+
:type _host_index: int, optional
|
|
2126
|
+
:return: Returns the result object.
|
|
2127
|
+
""" # noqa: E501
|
|
2128
|
+
|
|
2129
|
+
_param = self._tenant_get_prometheus_metrics_serialize(
|
|
2130
|
+
tenant=tenant,
|
|
2131
|
+
_request_auth=_request_auth,
|
|
2132
|
+
_content_type=_content_type,
|
|
2133
|
+
_headers=_headers,
|
|
2134
|
+
_host_index=_host_index,
|
|
2135
|
+
)
|
|
2136
|
+
|
|
2137
|
+
_response_types_map: Dict[str, Optional[str]] = {
|
|
2138
|
+
"200": "str",
|
|
2139
|
+
"400": "APIErrors",
|
|
2140
|
+
"403": "APIErrors",
|
|
2141
|
+
"404": "APIErrors",
|
|
2142
|
+
}
|
|
2143
|
+
response_data = self.api_client.call_api(
|
|
2144
|
+
*_param, _request_timeout=_request_timeout
|
|
2145
|
+
)
|
|
2146
|
+
response_data.read()
|
|
2147
|
+
return self.api_client.response_deserialize(
|
|
2148
|
+
response_data=response_data,
|
|
2149
|
+
response_types_map=_response_types_map,
|
|
2150
|
+
)
|
|
2151
|
+
|
|
2152
|
+
@validate_call
|
|
2153
|
+
def tenant_get_prometheus_metrics_without_preload_content(
|
|
2154
|
+
self,
|
|
2155
|
+
tenant: Annotated[
|
|
2156
|
+
str,
|
|
2157
|
+
Field(
|
|
2158
|
+
min_length=36, strict=True, max_length=36, description="The tenant id"
|
|
2159
|
+
),
|
|
2160
|
+
],
|
|
2161
|
+
_request_timeout: Union[
|
|
2162
|
+
None,
|
|
2163
|
+
Annotated[StrictFloat, Field(gt=0)],
|
|
2164
|
+
Tuple[
|
|
2165
|
+
Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
|
|
2166
|
+
],
|
|
2167
|
+
] = None,
|
|
2168
|
+
_request_auth: Optional[Dict[StrictStr, Any]] = None,
|
|
2169
|
+
_content_type: Optional[StrictStr] = None,
|
|
2170
|
+
_headers: Optional[Dict[StrictStr, Any]] = None,
|
|
2171
|
+
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
|
|
2172
|
+
) -> RESTResponseType:
|
|
2173
|
+
"""Get prometheus metrics
|
|
2174
|
+
|
|
2175
|
+
Get the prometheus metrics for the tenant
|
|
2176
|
+
|
|
2177
|
+
:param tenant: The tenant id (required)
|
|
2178
|
+
:type tenant: str
|
|
2179
|
+
:param _request_timeout: timeout setting for this request. If one
|
|
2180
|
+
number provided, it will be total request
|
|
2181
|
+
timeout. It can also be a pair (tuple) of
|
|
2182
|
+
(connection, read) timeouts.
|
|
2183
|
+
:type _request_timeout: int, tuple(int, int), optional
|
|
2184
|
+
:param _request_auth: set to override the auth_settings for an a single
|
|
2185
|
+
request; this effectively ignores the
|
|
2186
|
+
authentication in the spec for a single request.
|
|
2187
|
+
:type _request_auth: dict, optional
|
|
2188
|
+
:param _content_type: force content-type for the request.
|
|
2189
|
+
:type _content_type: str, Optional
|
|
2190
|
+
:param _headers: set to override the headers for a single
|
|
2191
|
+
request; this effectively ignores the headers
|
|
2192
|
+
in the spec for a single request.
|
|
2193
|
+
:type _headers: dict, optional
|
|
2194
|
+
:param _host_index: set to override the host_index for a single
|
|
2195
|
+
request; this effectively ignores the host_index
|
|
2196
|
+
in the spec for a single request.
|
|
2197
|
+
:type _host_index: int, optional
|
|
2198
|
+
:return: Returns the result object.
|
|
2199
|
+
""" # noqa: E501
|
|
2200
|
+
|
|
2201
|
+
_param = self._tenant_get_prometheus_metrics_serialize(
|
|
2202
|
+
tenant=tenant,
|
|
2203
|
+
_request_auth=_request_auth,
|
|
2204
|
+
_content_type=_content_type,
|
|
2205
|
+
_headers=_headers,
|
|
2206
|
+
_host_index=_host_index,
|
|
2207
|
+
)
|
|
2208
|
+
|
|
2209
|
+
_response_types_map: Dict[str, Optional[str]] = {
|
|
2210
|
+
"200": "str",
|
|
2211
|
+
"400": "APIErrors",
|
|
2212
|
+
"403": "APIErrors",
|
|
2213
|
+
"404": "APIErrors",
|
|
2214
|
+
}
|
|
2215
|
+
response_data = self.api_client.call_api(
|
|
2216
|
+
*_param, _request_timeout=_request_timeout
|
|
2217
|
+
)
|
|
2218
|
+
return response_data.response
|
|
2219
|
+
|
|
2220
|
+
def _tenant_get_prometheus_metrics_serialize(
|
|
2221
|
+
self,
|
|
2222
|
+
tenant,
|
|
2223
|
+
_request_auth,
|
|
2224
|
+
_content_type,
|
|
2225
|
+
_headers,
|
|
2226
|
+
_host_index,
|
|
2227
|
+
) -> RequestSerialized:
|
|
2228
|
+
|
|
2229
|
+
_host = None
|
|
2230
|
+
|
|
2231
|
+
_collection_formats: Dict[str, str] = {}
|
|
2232
|
+
|
|
2233
|
+
_path_params: Dict[str, str] = {}
|
|
2234
|
+
_query_params: List[Tuple[str, str]] = []
|
|
2235
|
+
_header_params: Dict[str, Optional[str]] = _headers or {}
|
|
2236
|
+
_form_params: List[Tuple[str, str]] = []
|
|
2237
|
+
_files: Dict[
|
|
2238
|
+
str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
|
|
2239
|
+
] = {}
|
|
2240
|
+
_body_params: Optional[bytes] = None
|
|
2241
|
+
|
|
2242
|
+
# process the path parameters
|
|
2243
|
+
if tenant is not None:
|
|
2244
|
+
_path_params["tenant"] = tenant
|
|
2245
|
+
# process the query parameters
|
|
2246
|
+
# process the header parameters
|
|
2247
|
+
# process the form parameters
|
|
2248
|
+
# process the body parameter
|
|
2249
|
+
|
|
2250
|
+
# set the HTTP header `Accept`
|
|
2251
|
+
if "Accept" not in _header_params:
|
|
2252
|
+
_header_params["Accept"] = self.api_client.select_header_accept(
|
|
2253
|
+
["text/plain", "application/json"]
|
|
2254
|
+
)
|
|
2255
|
+
|
|
2256
|
+
# authentication setting
|
|
2257
|
+
_auth_settings: List[str] = ["cookieAuth", "bearerAuth"]
|
|
2258
|
+
|
|
2259
|
+
return self.api_client.param_serialize(
|
|
2260
|
+
method="GET",
|
|
2261
|
+
resource_path="/api/v1/tenants/{tenant}/prometheus-metrics",
|
|
2262
|
+
path_params=_path_params,
|
|
2263
|
+
query_params=_query_params,
|
|
2264
|
+
header_params=_header_params,
|
|
2265
|
+
body=_body_params,
|
|
2266
|
+
post_params=_form_params,
|
|
2267
|
+
files=_files,
|
|
2268
|
+
auth_settings=_auth_settings,
|
|
2269
|
+
collection_formats=_collection_formats,
|
|
2270
|
+
_host=_host,
|
|
2271
|
+
_request_auth=_request_auth,
|
|
2272
|
+
)
|
|
2273
|
+
|
|
2008
2274
|
@validate_call
|
|
2009
2275
|
def tenant_get_step_run_queue_metrics(
|
|
2010
2276
|
self,
|
|
@@ -114,6 +114,11 @@ class V1TaskSummary(BaseModel):
|
|
|
114
114
|
workflow_config: Optional[Dict[str, Any]] = Field(
|
|
115
115
|
default=None, alias="workflowConfig"
|
|
116
116
|
)
|
|
117
|
+
parent_task_external_id: Optional[StrictStr] = Field(
|
|
118
|
+
default=None,
|
|
119
|
+
description="The external ID of the parent task.",
|
|
120
|
+
alias="parentTaskExternalId",
|
|
121
|
+
)
|
|
117
122
|
__properties: ClassVar[List[str]] = [
|
|
118
123
|
"metadata",
|
|
119
124
|
"actionId",
|
|
@@ -142,6 +147,7 @@ class V1TaskSummary(BaseModel):
|
|
|
142
147
|
"workflowRunExternalId",
|
|
143
148
|
"workflowVersionId",
|
|
144
149
|
"workflowConfig",
|
|
150
|
+
"parentTaskExternalId",
|
|
145
151
|
]
|
|
146
152
|
|
|
147
153
|
model_config = ConfigDict(
|
|
@@ -239,6 +245,7 @@ class V1TaskSummary(BaseModel):
|
|
|
239
245
|
"workflowRunExternalId": obj.get("workflowRunExternalId"),
|
|
240
246
|
"workflowVersionId": obj.get("workflowVersionId"),
|
|
241
247
|
"workflowConfig": obj.get("workflowConfig"),
|
|
248
|
+
"parentTaskExternalId": obj.get("parentTaskExternalId"),
|
|
242
249
|
}
|
|
243
250
|
)
|
|
244
251
|
return _obj
|
hatchet_sdk/features/metrics.py
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
from datetime import datetime, timedelta, timezone
|
|
3
|
+
from typing import Any
|
|
2
4
|
|
|
5
|
+
from pydantic import BaseModel
|
|
6
|
+
|
|
7
|
+
from hatchet_sdk.clients.rest.api.task_api import TaskApi
|
|
3
8
|
from hatchet_sdk.clients.rest.api.tenant_api import TenantApi
|
|
4
|
-
from hatchet_sdk.clients.rest.api.workflow_api import WorkflowApi
|
|
5
9
|
from hatchet_sdk.clients.rest.api_client import ApiClient
|
|
6
|
-
from hatchet_sdk.clients.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
)
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
retry,
|
|
16
|
-
)
|
|
17
|
-
from hatchet_sdk.utils.typing import JSONSerializableMapping
|
|
10
|
+
from hatchet_sdk.clients.v1.api_client import BaseRestClient, retry
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TaskMetrics(BaseModel):
|
|
14
|
+
cancelled: int
|
|
15
|
+
completed: int
|
|
16
|
+
failed: int
|
|
17
|
+
queued: int
|
|
18
|
+
running: int
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
class MetricsClient(BaseRestClient):
|
|
@@ -22,108 +23,126 @@ class MetricsClient(BaseRestClient):
|
|
|
22
23
|
The metrics client is a client for reading metrics out of Hatchet's metrics API.
|
|
23
24
|
"""
|
|
24
25
|
|
|
25
|
-
def
|
|
26
|
-
return
|
|
26
|
+
def _taskapi(self, client: ApiClient) -> TaskApi:
|
|
27
|
+
return TaskApi(client)
|
|
27
28
|
|
|
28
29
|
def _ta(self, client: ApiClient) -> TenantApi:
|
|
29
30
|
return TenantApi(client)
|
|
30
31
|
|
|
31
32
|
@retry
|
|
32
|
-
def
|
|
33
|
+
def get_queue_metrics(
|
|
33
34
|
self,
|
|
34
|
-
|
|
35
|
-
status: WorkflowRunStatus | None = None,
|
|
36
|
-
group_key: str | None = None,
|
|
37
|
-
) -> WorkflowMetrics:
|
|
35
|
+
) -> dict[str, Any]:
|
|
38
36
|
"""
|
|
39
|
-
Retrieve
|
|
37
|
+
Retrieve the current queue metrics for the tenant.
|
|
40
38
|
|
|
41
|
-
:
|
|
42
|
-
:param status: The status of the workflow run to filter by.
|
|
43
|
-
:param group_key: The key to group the metrics by.
|
|
44
|
-
|
|
45
|
-
:return: Workflow metrics for the specified workflow ID.
|
|
39
|
+
:return: The current queue metrics
|
|
46
40
|
"""
|
|
47
41
|
with self.client() as client:
|
|
48
|
-
return
|
|
49
|
-
|
|
50
|
-
|
|
42
|
+
return (
|
|
43
|
+
self._ta(client)
|
|
44
|
+
.tenant_get_step_run_queue_metrics(
|
|
45
|
+
tenant=self.client_config.tenant_id,
|
|
46
|
+
)
|
|
47
|
+
.queues
|
|
48
|
+
) or {}
|
|
51
49
|
|
|
52
|
-
async def
|
|
50
|
+
async def aio_get_queue_metrics(
|
|
53
51
|
self,
|
|
54
|
-
|
|
55
|
-
status: WorkflowRunStatus | None = None,
|
|
56
|
-
group_key: str | None = None,
|
|
57
|
-
) -> WorkflowMetrics:
|
|
52
|
+
) -> dict[str, Any]:
|
|
58
53
|
"""
|
|
59
|
-
Retrieve
|
|
60
|
-
|
|
61
|
-
:param workflow_id: The ID of the workflow to retrieve metrics for.
|
|
62
|
-
:param status: The status of the workflow run to filter by.
|
|
63
|
-
:param group_key: The key to group the metrics by.
|
|
54
|
+
Retrieve the current queue metrics for the tenant.
|
|
64
55
|
|
|
65
|
-
:return:
|
|
56
|
+
:return: The current queue metrics
|
|
66
57
|
"""
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
)
|
|
58
|
+
|
|
59
|
+
return await asyncio.to_thread(self.get_queue_metrics)
|
|
70
60
|
|
|
71
61
|
@retry
|
|
72
|
-
def
|
|
62
|
+
def scrape_tenant_prometheus_metrics(
|
|
73
63
|
self,
|
|
74
|
-
|
|
75
|
-
additional_metadata: JSONSerializableMapping | None = None,
|
|
76
|
-
) -> TenantQueueMetrics:
|
|
64
|
+
) -> str:
|
|
77
65
|
"""
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
:param workflow_ids: A list of workflow IDs to retrieve metrics for.
|
|
81
|
-
:param additional_metadata: Additional metadata to filter the metrics by.
|
|
66
|
+
Scrape Prometheus metrics for the tenant. Returns the metrics in Prometheus text format.
|
|
82
67
|
|
|
83
|
-
:return:
|
|
68
|
+
:return: The metrics, returned in Prometheus text format
|
|
84
69
|
"""
|
|
85
70
|
with self.client() as client:
|
|
86
|
-
return self.
|
|
71
|
+
return self._ta(client).tenant_get_prometheus_metrics(
|
|
87
72
|
tenant=self.client_config.tenant_id,
|
|
88
|
-
workflows=workflow_ids,
|
|
89
|
-
additional_metadata=maybe_additional_metadata_to_kv(
|
|
90
|
-
additional_metadata
|
|
91
|
-
),
|
|
92
73
|
)
|
|
93
74
|
|
|
94
|
-
async def
|
|
75
|
+
async def aio_scrape_tenant_prometheus_metrics(
|
|
95
76
|
self,
|
|
96
|
-
|
|
97
|
-
additional_metadata: JSONSerializableMapping | None = None,
|
|
98
|
-
) -> TenantQueueMetrics:
|
|
77
|
+
) -> str:
|
|
99
78
|
"""
|
|
100
|
-
|
|
79
|
+
Scrape Prometheus metrics for the tenant. Returns the metrics in Prometheus text format.
|
|
101
80
|
|
|
102
|
-
:
|
|
103
|
-
:param additional_metadata: Additional metadata to filter the metrics by.
|
|
104
|
-
|
|
105
|
-
:return: Workflow metrics for the specified workflow IDs.
|
|
81
|
+
:return: The metrics, returned in Prometheus text format
|
|
106
82
|
"""
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
)
|
|
83
|
+
|
|
84
|
+
return await asyncio.to_thread(self.scrape_tenant_prometheus_metrics)
|
|
110
85
|
|
|
111
86
|
@retry
|
|
112
|
-
def get_task_metrics(
|
|
87
|
+
def get_task_metrics(
|
|
88
|
+
self,
|
|
89
|
+
since: datetime | None = None,
|
|
90
|
+
until: datetime | None = None,
|
|
91
|
+
workflow_ids: list[str] | None = None,
|
|
92
|
+
parent_task_external_id: str | None = None,
|
|
93
|
+
triggering_event_external_id: str | None = None,
|
|
94
|
+
) -> TaskMetrics:
|
|
113
95
|
"""
|
|
114
|
-
Retrieve
|
|
115
|
-
|
|
116
|
-
:
|
|
96
|
+
Retrieve task metrics, grouped by status (queued, running, completed, failed, cancelled).
|
|
97
|
+
|
|
98
|
+
:param since: Start time for the metrics query (defaults to the past day if unset)
|
|
99
|
+
:param until: End time for the metrics query
|
|
100
|
+
:param workflow_ids: List of workflow IDs to filter the metrics by
|
|
101
|
+
:param parent_task_external_id: ID of the parent task to filter by (note that parent task here refers to the task that spawned this task as a child)
|
|
102
|
+
:param triggering_event_external_id: ID of the triggering event to filter by
|
|
103
|
+
:return: Task metrics
|
|
117
104
|
"""
|
|
118
|
-
with self.client() as client:
|
|
119
|
-
return self._ta(client).tenant_get_step_run_queue_metrics(
|
|
120
|
-
tenant=self.client_config.tenant_id
|
|
121
|
-
)
|
|
122
105
|
|
|
123
|
-
|
|
106
|
+
since = since or datetime.now(timezone.utc) - timedelta(days=1)
|
|
107
|
+
until = until or datetime.now(timezone.utc)
|
|
108
|
+
with self.client() as client:
|
|
109
|
+
metrics = {
|
|
110
|
+
m.status.name.lower(): m.count
|
|
111
|
+
for m in self._taskapi(client).v1_task_list_status_metrics(
|
|
112
|
+
tenant=self.client_config.tenant_id,
|
|
113
|
+
since=since,
|
|
114
|
+
until=until,
|
|
115
|
+
workflow_ids=workflow_ids,
|
|
116
|
+
parent_task_external_id=parent_task_external_id,
|
|
117
|
+
triggering_event_external_id=triggering_event_external_id,
|
|
118
|
+
)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return TaskMetrics.model_validate(metrics)
|
|
122
|
+
|
|
123
|
+
async def aio_get_task_metrics(
|
|
124
|
+
self,
|
|
125
|
+
since: datetime | None = None,
|
|
126
|
+
until: datetime | None = None,
|
|
127
|
+
workflow_ids: list[str] | None = None,
|
|
128
|
+
parent_task_external_id: str | None = None,
|
|
129
|
+
triggering_event_external_id: str | None = None,
|
|
130
|
+
) -> TaskMetrics:
|
|
124
131
|
"""
|
|
125
|
-
Retrieve
|
|
126
|
-
|
|
127
|
-
:
|
|
132
|
+
Retrieve task metrics, grouped by status (queued, running, completed, failed, cancelled).
|
|
133
|
+
|
|
134
|
+
:param since: Start time for the metrics query (defaults to the past day if unset)
|
|
135
|
+
:param until: End time for the metrics query
|
|
136
|
+
:param workflow_ids: List of workflow IDs to filter the metrics by
|
|
137
|
+
:param parent_task_external_id: ID of the parent task to filter by (note that parent task here refers to the task that spawned this task as a child)
|
|
138
|
+
:param triggering_event_external_id: ID of the triggering event to filter by
|
|
139
|
+
:return: Task metrics
|
|
128
140
|
"""
|
|
129
|
-
return await asyncio.to_thread(
|
|
141
|
+
return await asyncio.to_thread(
|
|
142
|
+
self.get_task_metrics,
|
|
143
|
+
since,
|
|
144
|
+
until,
|
|
145
|
+
workflow_ids,
|
|
146
|
+
parent_task_external_id,
|
|
147
|
+
triggering_event_external_id,
|
|
148
|
+
)
|
|
@@ -108,3 +108,28 @@ class WorkflowsClient(BaseRestClient):
|
|
|
108
108
|
:return: The workflow version.
|
|
109
109
|
"""
|
|
110
110
|
return await asyncio.to_thread(self.get_version, workflow_id, version)
|
|
111
|
+
|
|
112
|
+
def delete(self, workflow_id: str) -> None:
|
|
113
|
+
"""
|
|
114
|
+
Permanently delete a workflow.
|
|
115
|
+
|
|
116
|
+
**DANGEROUS: This will delete a workflow and all of its data**
|
|
117
|
+
|
|
118
|
+
:param workflow_id: The ID of the workflow to delete.
|
|
119
|
+
:return: None
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
with self.client() as client:
|
|
123
|
+
return self._wa(client).workflow_delete(workflow_id)
|
|
124
|
+
|
|
125
|
+
async def aio_delete(self, workflow_id: str) -> None:
|
|
126
|
+
"""
|
|
127
|
+
Permanently delete a workflow.
|
|
128
|
+
|
|
129
|
+
**DANGEROUS: This will delete a workflow and all of its data**
|
|
130
|
+
|
|
131
|
+
:param workflow_id: The ID of the workflow to delete.
|
|
132
|
+
:return: None
|
|
133
|
+
"""
|
|
134
|
+
|
|
135
|
+
return await asyncio.to_thread(self.delete, workflow_id)
|
|
@@ -509,6 +509,22 @@ class BaseWorkflow(Generic[TWorkflowInput]):
|
|
|
509
509
|
priority=priority,
|
|
510
510
|
)
|
|
511
511
|
|
|
512
|
+
def delete(self) -> None:
|
|
513
|
+
"""
|
|
514
|
+
Permanently delete the workflow.
|
|
515
|
+
|
|
516
|
+
**DANGEROUS: This will delete a workflow and all of its data**
|
|
517
|
+
"""
|
|
518
|
+
self.client.workflows.delete(self.id)
|
|
519
|
+
|
|
520
|
+
async def aio_delete(self) -> None:
|
|
521
|
+
"""
|
|
522
|
+
Permanently delete the workflow.
|
|
523
|
+
|
|
524
|
+
**DANGEROUS: This will delete a workflow and all of its data**
|
|
525
|
+
"""
|
|
526
|
+
await self.client.workflows.aio_delete(self.id)
|
|
527
|
+
|
|
512
528
|
|
|
513
529
|
class Workflow(BaseWorkflow[TWorkflowInput]):
|
|
514
530
|
"""
|
hatchet_sdk/utils/serde.py
CHANGED
|
@@ -5,23 +5,27 @@ K = TypeVar("K")
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
@overload
|
|
8
|
-
def remove_null_unicode_character(data: str) -> str: ...
|
|
8
|
+
def remove_null_unicode_character(data: str, replacement: str = "") -> str: ...
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
@overload
|
|
12
|
-
def remove_null_unicode_character(
|
|
12
|
+
def remove_null_unicode_character(
|
|
13
|
+
data: dict[K, T], replacement: str = ""
|
|
14
|
+
) -> dict[K, T]: ...
|
|
13
15
|
|
|
14
16
|
|
|
15
17
|
@overload
|
|
16
|
-
def remove_null_unicode_character(data: list[T]) -> list[T]: ...
|
|
18
|
+
def remove_null_unicode_character(data: list[T], replacement: str = "") -> list[T]: ...
|
|
17
19
|
|
|
18
20
|
|
|
19
21
|
@overload
|
|
20
|
-
def remove_null_unicode_character(
|
|
22
|
+
def remove_null_unicode_character(
|
|
23
|
+
data: tuple[T, ...], replacement: str = ""
|
|
24
|
+
) -> tuple[T, ...]: ...
|
|
21
25
|
|
|
22
26
|
|
|
23
27
|
def remove_null_unicode_character(
|
|
24
|
-
data: str | dict[K, T] | list[T] | tuple[T, ...],
|
|
28
|
+
data: str | dict[K, T] | list[T] | tuple[T, ...], replacement: str = ""
|
|
25
29
|
) -> str | dict[K, T] | list[T] | tuple[T, ...]:
|
|
26
30
|
"""
|
|
27
31
|
Recursively traverse a dictionary (a task's output) and remove the unicode escape sequence \\u0000 which will cause unexpected behavior in Hatchet.
|
|
@@ -29,23 +33,29 @@ def remove_null_unicode_character(
|
|
|
29
33
|
Needed as Hatchet does not support \\u0000 in task outputs
|
|
30
34
|
|
|
31
35
|
:param data: The task output (a JSON-serializable dictionary or mapping)
|
|
36
|
+
:param replacement: The string to replace \\u0000 with.
|
|
37
|
+
|
|
32
38
|
:return: The same dictionary with all \\u0000 characters removed from strings, and nested dictionaries/lists processed recursively.
|
|
33
39
|
:raises TypeError: If the input is not a string, dictionary, list, or tuple.
|
|
34
40
|
"""
|
|
35
41
|
if isinstance(data, str):
|
|
36
|
-
return data.replace("\u0000",
|
|
42
|
+
return data.replace("\u0000", replacement)
|
|
37
43
|
|
|
38
44
|
if isinstance(data, dict):
|
|
39
45
|
return {
|
|
40
|
-
key: remove_null_unicode_character(cast(Any, value))
|
|
46
|
+
key: remove_null_unicode_character(cast(Any, value), replacement)
|
|
41
47
|
for key, value in data.items()
|
|
42
48
|
}
|
|
43
49
|
|
|
44
50
|
if isinstance(data, list):
|
|
45
|
-
return [
|
|
51
|
+
return [
|
|
52
|
+
remove_null_unicode_character(cast(Any, item), replacement) for item in data
|
|
53
|
+
]
|
|
46
54
|
|
|
47
55
|
if isinstance(data, tuple):
|
|
48
|
-
return tuple(
|
|
56
|
+
return tuple(
|
|
57
|
+
remove_null_unicode_character(cast(Any, item), replacement) for item in data
|
|
58
|
+
)
|
|
49
59
|
|
|
50
60
|
raise TypeError(
|
|
51
61
|
f"Unsupported type {type(data)}. Expected str, dict, list, or tuple."
|
|
@@ -24,7 +24,7 @@ hatchet_sdk/clients/rest/api/slack_api.py,sha256=0xIUw3_1_3hSTn2yw7fLRO5yb38nYLu
|
|
|
24
24
|
hatchet_sdk/clients/rest/api/sns_api.py,sha256=1LfhnZEA450uHwtZCoM_wycOeH4UGwfNP1pw4RWSe08,33641
|
|
25
25
|
hatchet_sdk/clients/rest/api/step_run_api.py,sha256=rqP4UIJSkw8DwbDnlEgupBDWUL0jlVH_Rm7bNGMUoG8,84505
|
|
26
26
|
hatchet_sdk/clients/rest/api/task_api.py,sha256=erYaoDA2iJk52PPntfT0Y63hsBuk4eaqV5gaRTQ008w,89767
|
|
27
|
-
hatchet_sdk/clients/rest/api/tenant_api.py,sha256=
|
|
27
|
+
hatchet_sdk/clients/rest/api/tenant_api.py,sha256=iz67ow7wp9qgo1IRPI_IVTkoMh_ytx81wz4MPgEWWSg,198472
|
|
28
28
|
hatchet_sdk/clients/rest/api/user_api.py,sha256=NYuEKLeBjXO4q8gyYq1thtbuRm9m3g0R6-q6LIfv83U,115780
|
|
29
29
|
hatchet_sdk/clients/rest/api/worker_api.py,sha256=56jRXsyK7SDENly2b019EO80d8xOHU4bZnmOmjKY1iQ,33049
|
|
30
30
|
hatchet_sdk/clients/rest/api/workflow_api.py,sha256=rpPXy5xZDZWo1GXQGLapTC3A5M_spk1zoK_vu_J7SVA,251652
|
|
@@ -174,7 +174,7 @@ hatchet_sdk/clients/rest/models/v1_task_point_metrics.py,sha256=shKqLFLgNAKua865
|
|
|
174
174
|
hatchet_sdk/clients/rest/models/v1_task_run_metric.py,sha256=8trEgJ_7AHAmUQi2Qty-v5XVjgN3g7VZ6gzMTjeZ1tY,2504
|
|
175
175
|
hatchet_sdk/clients/rest/models/v1_task_run_status.py,sha256=tjipWHHNx7g4lUZBdu_DDZwEqSpxPKv06YiE2Q17cXo,753
|
|
176
176
|
hatchet_sdk/clients/rest/models/v1_task_status.py,sha256=4Hqczjth228k8Y23vIaxAIzTpLaS9mh9I0PrTjY8JRY,742
|
|
177
|
-
hatchet_sdk/clients/rest/models/v1_task_summary.py,sha256=
|
|
177
|
+
hatchet_sdk/clients/rest/models/v1_task_summary.py,sha256=bx4i5YAod1nLJW1g7ETWS712Y9QVZnJ5LGiUA_Uvi-4,9228
|
|
178
178
|
hatchet_sdk/clients/rest/models/v1_task_summary_list.py,sha256=0m-xf_lY9BwwbLky9i6fkTYUwh2K9mADHVZoRyF66o4,3510
|
|
179
179
|
hatchet_sdk/clients/rest/models/v1_task_timing.py,sha256=ygr-r0_Mius0JDSAYIYjsXOvBByG5nxlJ0-cXOoCq7g,5969
|
|
180
180
|
hatchet_sdk/clients/rest/models/v1_task_timing_list.py,sha256=1LFoKqFn11EJ_t7ZeWUFldWOWfG09tN_wTZu3a8e_SM,3509
|
|
@@ -258,13 +258,13 @@ hatchet_sdk/exceptions.py,sha256=DG-mS0wZiB-4Pnyr-BgY-LRrAEAdgP2nqQlIheU99t4,264
|
|
|
258
258
|
hatchet_sdk/features/cron.py,sha256=k6Y-JJBPaf2Dtx-fwvNA2j7lTzHLBZpwVMA_u-p6Lvw,9723
|
|
259
259
|
hatchet_sdk/features/filters.py,sha256=n6PPeRiqd5SOFlcx8V2strUaCGma9JPRAOLx44XpC0o,6443
|
|
260
260
|
hatchet_sdk/features/logs.py,sha256=H_vQnOqiN5q_wQWVoOGAJp7eOPKFYZsLJ1Hb63LriRA,1190
|
|
261
|
-
hatchet_sdk/features/metrics.py,sha256=
|
|
261
|
+
hatchet_sdk/features/metrics.py,sha256=do4kVX6cjDszHocc-IoS8BdT5ChptPc39oElbW6Cd8k,5109
|
|
262
262
|
hatchet_sdk/features/rate_limits.py,sha256=eh55Z3w75cYUthqTyoWmNxj_6tN3rjebMKm3of-vxv0,2155
|
|
263
263
|
hatchet_sdk/features/runs.py,sha256=8geS5l1CU3GCLudFORmCvXyjVVcgNKsNAPV9mLcI8sU,23004
|
|
264
264
|
hatchet_sdk/features/scheduled.py,sha256=t7YA9CoJrzBhH82ChTSFWaTF_dyoC9i1O_wf9ywsphc,8939
|
|
265
265
|
hatchet_sdk/features/tenant.py,sha256=xkhh5mRKCWbunk_S1iBmGR-DYR-F4mjxk8jLyYUyzNE,886
|
|
266
266
|
hatchet_sdk/features/workers.py,sha256=DVdno28RmtlfhMJUkaPcOMHNKXCPV0RFrXtLqV6zWyE,2600
|
|
267
|
-
hatchet_sdk/features/workflows.py,sha256=
|
|
267
|
+
hatchet_sdk/features/workflows.py,sha256=WTt58imAFRrEEB3M5hEEIBwNtrzdWbITFpgtsIqJNSM,4770
|
|
268
268
|
hatchet_sdk/hatchet.py,sha256=rOuE7YPqu4setE_zGbmgvb2WN-q8HNXTDFYcp9N0Wj8,25759
|
|
269
269
|
hatchet_sdk/labels.py,sha256=nATgxWE3lFxRTnfISEpoIRLGbMfAZsHF4lZTuG4Mfic,182
|
|
270
270
|
hatchet_sdk/logger.py,sha256=5uOr52T4mImSQm1QvWT8HvZFK5WfPNh3Y1cBQZRFgUQ,333
|
|
@@ -276,14 +276,14 @@ hatchet_sdk/runnables/action.py,sha256=zrVHpyzIQ9XZgWwY69b_6uhZd53An4trRoLd9b3os
|
|
|
276
276
|
hatchet_sdk/runnables/contextvars.py,sha256=T2LWiXhcSyQYJY_-pfqMjDNjf6PdtDwyXyCZ6zIyWK0,929
|
|
277
277
|
hatchet_sdk/runnables/task.py,sha256=VEYabAl38U9L_igSDgZSzUL7-c-sX6YFRP0wsqGTadU,6714
|
|
278
278
|
hatchet_sdk/runnables/types.py,sha256=QFayOJ_Oi8tOYI6Sjl9bwjftM96QZh9XIlfFnSNgEXI,4359
|
|
279
|
-
hatchet_sdk/runnables/workflow.py,sha256=
|
|
279
|
+
hatchet_sdk/runnables/workflow.py,sha256=9Vq4T0goR4dG_bzarEog9ui-8mef9YmvPICk0CRHf3I,49673
|
|
280
280
|
hatchet_sdk/token.py,sha256=KjIiInwG5Kqd_FO4BSW1x_5Uc7PFbnzIVJqr50-ZldE,779
|
|
281
281
|
hatchet_sdk/utils/aio.py,sha256=cu1rD_UZkShtfzi7iXMYwBBaCRdxJQTdUC0_mf8nU2E,499
|
|
282
282
|
hatchet_sdk/utils/backoff.py,sha256=6B5Rb5nLKw_TqqgpJMYjIBV1PTTtbOMRZCveisVhg_I,353
|
|
283
283
|
hatchet_sdk/utils/datetimes.py,sha256=vIZNEX8tt-bknaIuTmoLEmKVt18dBjClH3urYtCJAys,775
|
|
284
284
|
hatchet_sdk/utils/opentelemetry.py,sha256=64TVwCLrUzEmcL2BUNPV_QubfiR5jajOZtVeGYLnEEA,1226
|
|
285
285
|
hatchet_sdk/utils/proto_enums.py,sha256=v2gp_ZmIhPxURVXwz5lscllXwZXDl5XGXeL6gezw3o0,1241
|
|
286
|
-
hatchet_sdk/utils/serde.py,sha256=
|
|
286
|
+
hatchet_sdk/utils/serde.py,sha256=YbS9rPy_kSom2G9cgYupECJrt3fbBOSbHVx6ihu7fUU,1924
|
|
287
287
|
hatchet_sdk/utils/timedelta_to_expression.py,sha256=YujnBnGn7lxtkUdKIeqmOiN_ZCGBpRPjCCSzcD3jxzA,644
|
|
288
288
|
hatchet_sdk/utils/typing.py,sha256=FgYnZyJSoRjNVFodxlI9gn0X8ST1KFed7xfUynIxa2U,978
|
|
289
289
|
hatchet_sdk/v0/__init__.py,sha256=r3Q7l2RsLgdIkK2jjiz7-JJpD1T_Zy--Oa9MN5n_yEs,9654
|
|
@@ -514,7 +514,7 @@ hatchet_sdk/worker/runner/runner.py,sha256=Btz7wd0DQ-5aPEZLN3T5X5__8DjuxN6H4yQEV
|
|
|
514
514
|
hatchet_sdk/worker/runner/utils/capture_logs.py,sha256=DKw6boqVsSCM1XvBWYuc833MZxCdSpMxg3l4aAqKPyw,3465
|
|
515
515
|
hatchet_sdk/worker/worker.py,sha256=nDuRo_LishRuOCTnDonc7G7qeOoW93nRHGd-fQOE_bs,16541
|
|
516
516
|
hatchet_sdk/workflow_run.py,sha256=KcylcqRwKADtnzOTjoiVr1vdr7qTZFtDeD5aRS6A4Y8,2823
|
|
517
|
-
hatchet_sdk-1.
|
|
518
|
-
hatchet_sdk-1.
|
|
519
|
-
hatchet_sdk-1.
|
|
520
|
-
hatchet_sdk-1.
|
|
517
|
+
hatchet_sdk-1.15.0.dist-info/METADATA,sha256=h9GjdEJsJudw7moBNpVj-uyvJzqlT7aXBcW4NsovLmE,3636
|
|
518
|
+
hatchet_sdk-1.15.0.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
519
|
+
hatchet_sdk-1.15.0.dist-info/entry_points.txt,sha256=Un_76pcLse-ZGBlwebhQpnTPyQrripeHW8J7qmEpGOk,1400
|
|
520
|
+
hatchet_sdk-1.15.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|