|
23 | 23 |
|
24 | 24 |
|
25 | 25 | def get_db_counters(mon_port, service):
|
26 |
| - counters_url = f"http://localhost:{mon_port}/counters/counters%3D{service}/json" |
| 26 | + counters_url = f"http://localhost:{mon_port}/counters/counters={service}/json" |
27 | 27 | reply = requests.get(counters_url)
|
28 | 28 | if reply.status_code == 204:
|
29 | 29 | return None
|
@@ -144,7 +144,7 @@ def get_default_feature_flag_value(feature_flag_camel_case) -> bool:
|
144 | 144 | ids=["enable_separate_quotas", "disable_separate_quotas"],
|
145 | 145 | )
|
146 | 146 | def ydb_cluster_configuration(request):
|
147 |
| - extra_feature_flags = [] |
| 147 | + extra_feature_flags = ['enable_db_counters'] |
148 | 148 | if request.param:
|
149 | 149 | extra_feature_flags.append("enable_separate_disk_space_quotas")
|
150 | 150 | else:
|
@@ -275,22 +275,37 @@ def wait_for_stats(client, table, retries=10, sleep_duration=5):
|
275 | 275 |
|
276 | 276 |
|
277 | 277 | # Note: the default total sleep time is 300 seconds, because 200 seconds can sometimes be not enough
|
278 |
| -def check_counters(mon_port, sensors_to_check, retries=60, sleep_duration=5): |
| 278 | +def check_counters(mon_port, sensors_to_check, service="ydb", retries=60, sleep_duration=5): |
| 279 | + sensor_count = 0 |
| 280 | + for _, expected_value in sensors_to_check.items(): |
| 281 | + if isinstance(expected_value, list): |
| 282 | + sensor_count += len(expected_value) |
| 283 | + else: |
| 284 | + sensor_count += 1 |
| 285 | + |
279 | 286 | for attempt in range(retries + 1):
|
280 |
| - counters = get_db_counters(mon_port, "ydb") |
| 287 | + counters = get_db_counters(mon_port, service) |
281 | 288 | correct_sensors = 0
|
282 | 289 | if counters:
|
283 | 290 | for sensor in counters["sensors"]:
|
| 291 | + labels = sensor["labels"] |
284 | 292 | for target_name, expected_value in sensors_to_check.items():
|
285 |
| - if sensor["labels"]["name"] == target_name: |
286 |
| - logger.debug( |
287 |
| - f"sensor {target_name}: expected {expected_value}, " |
288 |
| - f'got {sensor["value"]} in {sleep_duration * attempt} seconds' |
289 |
| - ) |
290 |
| - if sensor["value"] == expected_value: |
291 |
| - correct_sensors += 1 |
292 |
| - if correct_sensors == len(sensors_to_check): |
293 |
| - return |
| 293 | + if isinstance(expected_value, list): |
| 294 | + if labels.get("api_service", "") != target_name: |
| 295 | + continue |
| 296 | + for x in expected_value: |
| 297 | + if len(x) == [labels.get(k, "") == v if k != "value" else sensor[k] == v for k, v in x.items()].count(True): |
| 298 | + correct_sensors += 1 |
| 299 | + else: |
| 300 | + if labels["name"] == target_name: |
| 301 | + logger.debug( |
| 302 | + f"sensor {target_name}: expected {expected_value}, " |
| 303 | + f'got {sensor["value"]} in {sleep_duration * attempt} seconds' |
| 304 | + ) |
| 305 | + if sensor["value"] == expected_value: |
| 306 | + correct_sensors += 1 |
| 307 | + if correct_sensors == sensor_count: |
| 308 | + return |
294 | 309 |
|
295 | 310 | logger.debug(
|
296 | 311 | f"got {correct_sensors} out of {len(sensors_to_check)} correct sensors "
|
@@ -403,3 +418,85 @@ def test_storage_counters(self, ydb_cluster_configuration, ydb_cluster, ydb_data
|
403 | 418 | "resources.storage.table.used_bytes.hdd": 0,
|
404 | 419 | },
|
405 | 420 | )
|
| 421 | + |
| 422 | + |
| 423 | +def test_serverless_counters(ydb_cluster, ydb_endpoint, ydb_root, ydb_safe_test_name): |
| 424 | + hostel_db = os.path.join(ydb_root, "hostel_db", ydb_safe_test_name) |
| 425 | + ydb_cluster.create_hostel_database( |
| 426 | + hostel_db, |
| 427 | + storage_pool_units_count={ |
| 428 | + 'hdd': 1, |
| 429 | + }, |
| 430 | + ) |
| 431 | + |
| 432 | + ydb_cluster.register_and_start_slots(hostel_db, count=1) |
| 433 | + ydb_cluster.wait_tenant_up(hostel_db) |
| 434 | + |
| 435 | + serverless_db = os.path.join(ydb_root, "serverless", ydb_safe_test_name) |
| 436 | + ydb_cluster.create_serverless_database( |
| 437 | + serverless_db, |
| 438 | + hostel_db=hostel_db, |
| 439 | + attributes={ |
| 440 | + "cloud_id": "CLOUD_ID_VAL", |
| 441 | + "folder_id": "FOLDER_ID_VAL", |
| 442 | + "database_id": "DATABASE_ID_VAL", |
| 443 | + }, |
| 444 | + ) |
| 445 | + |
| 446 | + driver_config = ydb.DriverConfig(ydb_endpoint, serverless_db, auth_token='root@builtin') |
| 447 | + driver = ydb.Driver(driver_config) |
| 448 | + driver.wait(120) |
| 449 | + |
| 450 | + session = driver.table_client.session().create() |
| 451 | + |
| 452 | + session.create_table( |
| 453 | + os.path.join(serverless_db, "table") , |
| 454 | + ydb.TableDescription() |
| 455 | + .with_column(ydb.Column("id", ydb.OptionalType(ydb.DataType.Uint64))) |
| 456 | + .with_primary_key("id") |
| 457 | + ) |
| 458 | + |
| 459 | + try: |
| 460 | + session.create_table( |
| 461 | + os.path.join(serverless_db, "invalid_table") , |
| 462 | + ydb.TableDescription() |
| 463 | + .with_column(ydb.Column("id", ydb.OptionalType(ydb.DataType.Float))) |
| 464 | + .with_primary_key("id") |
| 465 | + ) |
| 466 | + except ydb.issues.SchemeError: |
| 467 | + pass |
| 468 | + |
| 469 | + slot_mon_port = ydb_cluster.slots[1].mon_port |
| 470 | + expected_counters = { |
| 471 | + "table": [ |
| 472 | + { |
| 473 | + "method": "CreateSession", |
| 474 | + "name": "api.grpc.request.count", |
| 475 | + "value": 1, |
| 476 | + }, |
| 477 | + { |
| 478 | + "method": "CreateSession", |
| 479 | + "name": "api.grpc.response.count", |
| 480 | + "status": "SUCCESS", |
| 481 | + "value": 1, |
| 482 | + }, |
| 483 | + { |
| 484 | + "method": "CreateTable", |
| 485 | + "name": "api.grpc.request.count", |
| 486 | + "value": 2, |
| 487 | + }, |
| 488 | + { |
| 489 | + "method": "CreateTable", |
| 490 | + "name": "api.grpc.response.count", |
| 491 | + "status": "SUCCESS", |
| 492 | + "value": 1, |
| 493 | + }, |
| 494 | + { |
| 495 | + "method": "CreateTable", |
| 496 | + "name": "api.grpc.response.count", |
| 497 | + "status": "SCHEME_ERROR", |
| 498 | + "value": 1, |
| 499 | + }, |
| 500 | + ], |
| 501 | + } |
| 502 | + check_counters(slot_mon_port, expected_counters, "ydb_serverless") |
0 commit comments