polaris-python 0.0.1.dev3__py3-none-any.whl → 0.0.1.dev4__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.
- polaris/_version.py +1 -1
- polaris/api/log.py +3 -1
- polaris/plugin/server_connector/grpc_connector/connection.py +116 -13
- {polaris_python-0.0.1.dev3.dist-info → polaris_python-0.0.1.dev4.dist-info}/METADATA +23 -11
- {polaris_python-0.0.1.dev3.dist-info → polaris_python-0.0.1.dev4.dist-info}/RECORD +8 -8
- {polaris_python-0.0.1.dev3.dist-info → polaris_python-0.0.1.dev4.dist-info}/WHEEL +0 -0
- {polaris_python-0.0.1.dev3.dist-info → polaris_python-0.0.1.dev4.dist-info}/licenses/LICENSE +0 -0
- {polaris_python-0.0.1.dev3.dist-info → polaris_python-0.0.1.dev4.dist-info}/top_level.txt +0 -0
polaris/_version.py
CHANGED
polaris/api/log.py
CHANGED
|
@@ -97,7 +97,9 @@ def _create_file_logger(name, path, level, max_bytes, backup_count, max_age_days
|
|
|
97
97
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
98
98
|
handler = ExclusiveRotatingFileHandler(path, "a", max_bytes, backup_count,
|
|
99
99
|
encoding="utf-8", max_age_days=max_age_days)
|
|
100
|
-
handler.setFormatter(logging.Formatter(
|
|
100
|
+
handler.setFormatter(logging.Formatter(
|
|
101
|
+
"[%(asctime)s][%(levelname)s][%(process)d][%(filename)s:%(lineno)d]: %(message)s"
|
|
102
|
+
))
|
|
101
103
|
instance = logging.Logger(name, level=level)
|
|
102
104
|
instance.addHandler(handler)
|
|
103
105
|
instance.propagate = False
|
|
@@ -19,12 +19,14 @@ from __future__ import annotations
|
|
|
19
19
|
|
|
20
20
|
import asyncio
|
|
21
21
|
import itertools
|
|
22
|
+
import logging
|
|
22
23
|
import time
|
|
23
24
|
import traceback
|
|
24
25
|
from collections.abc import AsyncIterator, Awaitable, Callable, Sequence
|
|
25
26
|
from dataclasses import dataclass
|
|
26
27
|
|
|
27
28
|
import grpc
|
|
29
|
+
from google.protobuf.json_format import MessageToJson
|
|
28
30
|
from google.protobuf.message import Message
|
|
29
31
|
from polarismesh_specification.api.v1.service_manage import (
|
|
30
32
|
client_pb2,
|
|
@@ -53,6 +55,7 @@ _REQUEST_ID_PREFIX = {
|
|
|
53
55
|
"DownloadSkill": "1",
|
|
54
56
|
}
|
|
55
57
|
_REQUEST_ID_SEEDS = {prefix: itertools.count(1) for prefix in set(_REQUEST_ID_PREFIX.values())}
|
|
58
|
+
REPORT_CLIENT_LOG_INTERVAL_SECONDS = 30 * 60
|
|
56
59
|
|
|
57
60
|
|
|
58
61
|
def _request_id(method: str) -> tuple[tuple[str, str], ...]:
|
|
@@ -72,6 +75,32 @@ def _response_location(response) -> str:
|
|
|
72
75
|
return "-"
|
|
73
76
|
|
|
74
77
|
|
|
78
|
+
def _report_client_request_summary(request) -> str:
|
|
79
|
+
try:
|
|
80
|
+
client_type = client_pb2.Client.ClientType.Name(request.type)
|
|
81
|
+
except ValueError:
|
|
82
|
+
client_type = str(request.type)
|
|
83
|
+
config_metadata = request.config_metadata.value if request.HasField("config_metadata") else ""
|
|
84
|
+
config_enabled = request.config_enabled.value if request.HasField("config_enabled") else False
|
|
85
|
+
stats = [
|
|
86
|
+
(
|
|
87
|
+
f"{stat.protocol.value or '-'}://{stat.target.value or '-'}:"
|
|
88
|
+
f"{stat.port.value}{stat.path.value or '/'}"
|
|
89
|
+
)
|
|
90
|
+
for stat in request.stat
|
|
91
|
+
]
|
|
92
|
+
return (
|
|
93
|
+
f"clientId={request.id.value} host={request.host.value} "
|
|
94
|
+
f"clientType={client_type} clientVersion={request.version.value} "
|
|
95
|
+
f"configEnabled={config_enabled} configMetadataLen={len(config_metadata)} "
|
|
96
|
+
f"stats={','.join(stats) or '-'}"
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _compact_message_json(message: Message) -> str:
|
|
101
|
+
return MessageToJson(message, preserving_proto_field_name=True, indent=None)
|
|
102
|
+
|
|
103
|
+
|
|
75
104
|
@dataclass(frozen=True, slots=True)
|
|
76
105
|
class GrpcSettings:
|
|
77
106
|
"""Values required by the gRPC transport."""
|
|
@@ -115,6 +144,25 @@ class GrpcConnection:
|
|
|
115
144
|
self.address_resolver = None
|
|
116
145
|
self.on_switch = None
|
|
117
146
|
self._switch_task = None
|
|
147
|
+
self._last_report_client_log = None
|
|
148
|
+
self._last_report_client_log_at = None
|
|
149
|
+
|
|
150
|
+
def _should_log_report_client(self, request) -> bool:
|
|
151
|
+
content = request.SerializeToString(deterministic=True)
|
|
152
|
+
now = time.monotonic()
|
|
153
|
+
if (
|
|
154
|
+
content == self._last_report_client_log
|
|
155
|
+
and self._last_report_client_log_at is not None
|
|
156
|
+
and now - self._last_report_client_log_at < REPORT_CLIENT_LOG_INTERVAL_SECONDS
|
|
157
|
+
):
|
|
158
|
+
return False
|
|
159
|
+
self._last_report_client_log = content
|
|
160
|
+
self._last_report_client_log_at = now
|
|
161
|
+
return True
|
|
162
|
+
|
|
163
|
+
def _reset_report_client_log(self) -> None:
|
|
164
|
+
self._last_report_client_log = None
|
|
165
|
+
self._last_report_client_log_at = None
|
|
118
166
|
|
|
119
167
|
def _metadata(self) -> tuple[tuple[str, str], ...]:
|
|
120
168
|
if not self.settings.token:
|
|
@@ -160,29 +208,68 @@ class GrpcConnection:
|
|
|
160
208
|
address = self._addresses[self._address_index % len(self._addresses)]
|
|
161
209
|
started = time.monotonic()
|
|
162
210
|
response = None
|
|
211
|
+
request_metadata = _request_id(method) + extra_metadata + self._metadata()
|
|
212
|
+
request_id = next(
|
|
213
|
+
(value for key, value in request_metadata if key == "request-id"),
|
|
214
|
+
"-",
|
|
215
|
+
)
|
|
163
216
|
try:
|
|
217
|
+
if method == "ReportClient" and self.base_logger.isEnabledFor(logging.DEBUG):
|
|
218
|
+
self.base_logger.debug(
|
|
219
|
+
"reportClient request address=%s requestId=%s request=%s",
|
|
220
|
+
address,
|
|
221
|
+
request_id,
|
|
222
|
+
_compact_message_json(request),
|
|
223
|
+
)
|
|
164
224
|
stub = await self._rpc_stub(method, address)
|
|
165
225
|
rpc: Callable[..., Awaitable[response_pb2.Response]] = getattr(stub, method)
|
|
166
226
|
response = await rpc(
|
|
167
227
|
request,
|
|
168
228
|
timeout=self.settings.timeout_seconds if timeout_seconds is None else timeout_seconds,
|
|
169
|
-
metadata=
|
|
229
|
+
metadata=request_metadata,
|
|
170
230
|
)
|
|
171
231
|
code = response_code(response)
|
|
172
232
|
cost = (time.monotonic() - started) * 1000
|
|
173
233
|
if method == "ReportClient":
|
|
234
|
+
summary = _report_client_request_summary(request)
|
|
174
235
|
if code == ServerCode.ExecuteSuccess:
|
|
175
|
-
self.
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
236
|
+
if self._should_log_report_client(request):
|
|
237
|
+
self.base_logger.info(
|
|
238
|
+
"reportClient success address=%s serverCode=%s cost=%.3fms "
|
|
239
|
+
"location=%s requestId=%s %s",
|
|
240
|
+
address,
|
|
241
|
+
code,
|
|
242
|
+
cost,
|
|
243
|
+
_response_location(response),
|
|
244
|
+
request_id,
|
|
245
|
+
summary,
|
|
246
|
+
)
|
|
179
247
|
else:
|
|
248
|
+
self._reset_report_client_log()
|
|
180
249
|
self.base_logger.warning(
|
|
181
|
-
"reportClient failed address=%s serverCode=%s cost=%.3fms
|
|
182
|
-
|
|
250
|
+
"reportClient failed address=%s serverCode=%s cost=%.3fms "
|
|
251
|
+
"location=%s requestId=%s %s",
|
|
252
|
+
address,
|
|
253
|
+
code,
|
|
254
|
+
cost,
|
|
255
|
+
_response_location(response),
|
|
256
|
+
request_id,
|
|
257
|
+
summary,
|
|
258
|
+
)
|
|
259
|
+
if self.base_logger.isEnabledFor(logging.DEBUG):
|
|
260
|
+
self.base_logger.debug(
|
|
261
|
+
"reportClient response address=%s requestId=%s response=%s",
|
|
262
|
+
address,
|
|
263
|
+
request_id,
|
|
264
|
+
_compact_message_json(response),
|
|
183
265
|
)
|
|
184
|
-
self.logger.debug(
|
|
185
|
-
|
|
266
|
+
self.logger.debug(
|
|
267
|
+
"Polaris ReportClient success address=%s code=%s requestId=%s %s",
|
|
268
|
+
address,
|
|
269
|
+
code,
|
|
270
|
+
request_id,
|
|
271
|
+
summary,
|
|
272
|
+
)
|
|
186
273
|
else:
|
|
187
274
|
# Heartbeats repeat on every TTL; keep them out of the INFO stream like polaris-go.
|
|
188
275
|
quiet_methods = {"Heartbeat", "GetServiceContract"}
|
|
@@ -196,12 +283,28 @@ class GrpcConnection:
|
|
|
196
283
|
last_error = exc
|
|
197
284
|
cost = (time.monotonic() - started) * 1000
|
|
198
285
|
if method == "ReportClient":
|
|
286
|
+
summary = _report_client_request_summary(request)
|
|
287
|
+
self._reset_report_client_log()
|
|
199
288
|
self.base_logger.warning(
|
|
200
|
-
"reportClient failed address=%s code=%s cost=%.3fms
|
|
201
|
-
|
|
289
|
+
"reportClient failed address=%s code=%s cost=%.3fms "
|
|
290
|
+
"requestId=%s %s: %s",
|
|
291
|
+
address,
|
|
292
|
+
exc.code().name,
|
|
293
|
+
cost,
|
|
294
|
+
request_id,
|
|
295
|
+
summary,
|
|
296
|
+
exc.details(),
|
|
297
|
+
)
|
|
298
|
+
self.logger.debug(
|
|
299
|
+
"Polaris ReportClient failed address=%s code=%s cost=%.3fms "
|
|
300
|
+
"requestId=%s %s: %s",
|
|
301
|
+
address,
|
|
302
|
+
exc.code().name,
|
|
303
|
+
cost,
|
|
304
|
+
request_id,
|
|
305
|
+
summary,
|
|
306
|
+
exc.details(),
|
|
202
307
|
)
|
|
203
|
-
self.logger.debug("Polaris ReportClient failed address=%s code=%s cost=%.3fms: %s",
|
|
204
|
-
address, exc.code().name, cost, exc.details())
|
|
205
308
|
else:
|
|
206
309
|
self.logger.error(
|
|
207
310
|
"Polaris %s failed address=%s code=%s cost=%.3fms: %s",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: polaris-python
|
|
3
|
-
Version: 0.0.1.
|
|
3
|
+
Version: 0.0.1.dev4
|
|
4
4
|
Summary: Python SDK for Polaris service governance.
|
|
5
5
|
Author-email: evelynwei <evelynwei@tencent.com>
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -189,24 +189,36 @@ See [TLS](docs/guides/tls.md).
|
|
|
189
189
|
|
|
190
190
|
## Examples
|
|
191
191
|
|
|
192
|
-
|
|
192
|
+
From the repository root, Quickstart reads its adjacent `polaris.yaml`:
|
|
193
193
|
|
|
194
194
|
```bash
|
|
195
|
-
|
|
195
|
+
export POLARIS_SERVER_ADDRESS=127.0.0.1:8091
|
|
196
|
+
export POLARIS_TOKEN=
|
|
197
|
+
make -C examples run DEMO=quickstart/provider ARGS='--service-token "" --port 0'
|
|
198
|
+
# Another terminal with the same environment
|
|
199
|
+
make -C examples run DEMO=quickstart/consumer ARGS='--port 18080'
|
|
196
200
|
```
|
|
197
201
|
|
|
198
|
-
|
|
202
|
+
`--service-token` is required; an empty string works when service authentication is
|
|
203
|
+
disabled. Runs stay in the foreground; use separate terminals or `&`.
|
|
199
204
|
|
|
200
205
|
```bash
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
./logs.sh --latest --tail 30
|
|
205
|
-
./cleanup.sh --force
|
|
206
|
+
make -C examples logs ARGS='--only quickstart --latest --tail 30'
|
|
207
|
+
make -C examples cleanup ARGS='--only quickstart --dry-run'
|
|
208
|
+
make -C examples cleanup ARGS='--only quickstart'
|
|
206
209
|
```
|
|
207
210
|
|
|
208
|
-
|
|
209
|
-
|
|
211
|
+
See [examples/README.md](examples/README.md) for demos, Makefiles and log/cleanup options.
|
|
212
|
+
|
|
213
|
+
Verification and test artifacts belong to `integration/`:
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
./integration/verify.sh --only quickstart
|
|
217
|
+
./integration/verify_e2e.sh --only quickstart
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
See the [integration guide](integration/README.md) and
|
|
221
|
+
[quickstart tests](integration/scenarios/quickstart/test.md) for checks and test artifacts.
|
|
210
222
|
|
|
211
223
|
## License
|
|
212
224
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
polaris/__init__.py,sha256=g0tzWZkbmiA08jI9eamped66UghtWNHP52QNSgPeJ28,2471
|
|
2
|
-
polaris/_version.py,sha256=
|
|
2
|
+
polaris/_version.py,sha256=24cjgsjZ51oQN2WKxw5dhXfg4gHwfuN2ubPhXnYC6W8,710
|
|
3
3
|
polaris/plugin_manager.py,sha256=5hngFEOGMSGTeI0dnk-y4Y4Q4CXttS3fsZyxu-rGELg,5690
|
|
4
4
|
polaris/api/__init__.py,sha256=tOUxtVmMBEdzZUP5YqfIIEWUiu1jtrOXpuSTFTHuOs0,1778
|
|
5
5
|
polaris/api/_log_file.py,sha256=LYd__J8ooAdtONz7Ux7KmEridLpMyzKh0jk82BRsgpU,8729
|
|
6
6
|
polaris/api/config.py,sha256=dFm7wKgbjpzZgLrF6yUQYPHW_kFJBmLXu-80mFF_RHw,6023
|
|
7
7
|
polaris/api/consumer.py,sha256=etibb0SYWeqkVKGb_JDl4yCUxQ2r_AVU6YoB-Wj_S_s,10708
|
|
8
|
-
polaris/api/log.py,sha256=
|
|
8
|
+
polaris/api/log.py,sha256=TDTv08enECNWalRBRErix6KPvKSBcZ4Zhp2UH6__P9M,17535
|
|
9
9
|
polaris/api/lossless.py,sha256=Bg6srjmKU7mUNxlQkE2Ctpu_GyQgNr0Ijd7d-DPAxA0,3393
|
|
10
10
|
polaris/api/provider.py,sha256=wZ8yize1GTuaeXR1WB15-y7OuU-esgKvgw2cXblKekU,6936
|
|
11
11
|
polaris/api/skill.py,sha256=j3lCuU0H9Hhyc6OvA0tU9fE_g4lGmhEna3qUATXmXR0,8352
|
|
@@ -62,7 +62,7 @@ polaris/plugin/server_connector/__init__.py,sha256=vxOLRFc-K6p6WjDZdtNAe95DRDXIg
|
|
|
62
62
|
polaris/plugin/server_connector/base.py,sha256=CbCGkZQP3ZuCw2BFlzOhTgxLACFpl9u4BzzUqb8tn9c,3129
|
|
63
63
|
polaris/plugin/server_connector/convert.py,sha256=xhYAqkl2DpLuAyWYFrS8v6tFjKf0ZE26UXH9d3ghJTA,7506
|
|
64
64
|
polaris/plugin/server_connector/grpc_connector/__init__.py,sha256=grRkHuo-nrdQxpBZyDEsNs8bLOKR0XGQfYTe7_NrQFw,883
|
|
65
|
-
polaris/plugin/server_connector/grpc_connector/connection.py,sha256=
|
|
65
|
+
polaris/plugin/server_connector/grpc_connector/connection.py,sha256=56sOGVKZZy3W1Cr59PJ4K97T2qne_y7ZI1u7PRKca1M,22488
|
|
66
66
|
polaris/plugin/server_connector/grpc_connector/grpc_client.py,sha256=Q_qK2_5mDBXocqsa0MMpkpEZLtHAwUMD4lSnf3w8AG8,18425
|
|
67
67
|
polaris/plugin/server_connector/grpc_connector/tls.py,sha256=iGLyeqAUOKZsltg4IJAxLnnQFDbCfXAwEWVGacK3NWg,1987
|
|
68
68
|
polaris/plugin/service_router/__init__.py,sha256=MdDHSjiSE7gTKPRTNH5JCWI8o5t60oz4u1Zmaf1Re7E,993
|
|
@@ -77,8 +77,8 @@ polaris/plugin/skill/persistence.py,sha256=Lr6D6KbcxHBAkP-vTkMg2sfGMwLhqOxhLyVGL
|
|
|
77
77
|
polaris/plugin/stat_reporter/__init__.py,sha256=dWFnNx7KLGCJoyIBjDDco8xvm_QgAr6RFnVd3IXj6oY,726
|
|
78
78
|
polaris/plugin/stat_reporter/base.py,sha256=egAQK8ZBTXsFpnFK8fW9fgA_2xDq7BeeQah4aio9T0Y,1178
|
|
79
79
|
polaris/plugin/stat_reporter/prometheus.py,sha256=so0H8CyaGsnJpPMsmW57ryqePyWIsLvQZJu-g2cl-c8,17311
|
|
80
|
-
polaris_python-0.0.1.
|
|
81
|
-
polaris_python-0.0.1.
|
|
82
|
-
polaris_python-0.0.1.
|
|
83
|
-
polaris_python-0.0.1.
|
|
84
|
-
polaris_python-0.0.1.
|
|
80
|
+
polaris_python-0.0.1.dev4.dist-info/licenses/LICENSE,sha256=YJW-rt35PlCxHBGzDNLAaMYMaUjgCrrH57V3MJTwpSI,1779
|
|
81
|
+
polaris_python-0.0.1.dev4.dist-info/METADATA,sha256=GAP1ScgF4hBW6XAGvaICkEv14pO1OTpL8k7dBf0ztQc,7710
|
|
82
|
+
polaris_python-0.0.1.dev4.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
|
|
83
|
+
polaris_python-0.0.1.dev4.dist-info/top_level.txt,sha256=w-dcIlTf_g1vjlHs3857yHM0OcmFnk4xJ2LgBYbPI6w,8
|
|
84
|
+
polaris_python-0.0.1.dev4.dist-info/RECORD,,
|
|
File without changes
|
{polaris_python-0.0.1.dev3.dist-info → polaris_python-0.0.1.dev4.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|