|
68 | 68 | public class Main { |
69 | 69 | private static final Logger LOGGER = LoggerFactory.getLogger(Main.class); |
70 | 70 |
|
71 | | - // Startup timing field |
| 71 | + // Startup timing fields |
72 | 72 | private static volatile Instant startupBeginTime; |
| 73 | + private static volatile Instant metadataLoadingBeginTime; |
73 | 74 |
|
74 | 75 | private final JsonObject config; |
75 | 76 | private final Vertx vertx; |
@@ -275,15 +276,69 @@ public static void recordStartupComplete() { |
275 | 276 | .register(globalRegistry); |
276 | 277 |
|
277 | 278 | if (startupDuration != null) { |
278 | | - LOGGER.info("UID2 Operator startup completed in {:.3f} seconds", durationSeconds); |
| 279 | + LOGGER.info("UID2 Operator startup completed in {} seconds", String.format("%.3f", durationSeconds)); |
279 | 280 | } else { |
280 | 281 | LOGGER.warn("UID2 Operator startup completed but timing measurement failed"); |
281 | 282 | } |
282 | 283 | } |
283 | 284 |
|
| 285 | + /** |
| 286 | + * Record timing for individual store loading operations. |
| 287 | + * @param storeName Name of the store that was loaded |
| 288 | + * @param startTime When the store loading started |
| 289 | + */ |
| 290 | + private static void recordStoreLoadingTime(String storeName, Instant startTime) { |
| 291 | + final Duration duration = Duration.between(startTime, Instant.now()); |
| 292 | + final double durationMs = duration.toMillis(); |
| 293 | + |
| 294 | + LOGGER.info("Store '{}' content loading completed in {} ms", storeName, durationMs); |
| 295 | + |
| 296 | + // Register individual store loading time metric |
| 297 | + Gauge.builder("uid2_operator_store_loading_duration_ms", () -> durationMs) |
| 298 | + .description("Time taken to load individual store content during startup") |
| 299 | + .tags("store_name", storeName) |
| 300 | + .register(globalRegistry); |
| 301 | + } |
| 302 | + |
| 303 | + /** |
| 304 | + * Record timing for major startup phases. |
| 305 | + * @param phaseName Name of the startup phase |
| 306 | + * @param duration Duration of the phase |
| 307 | + */ |
| 308 | + private static void recordPhaseTime(String phaseName, Duration duration) { |
| 309 | + final double durationMs = duration.toMillis(); |
| 310 | + |
| 311 | + LOGGER.info("Startup phase '{}' completed in {} ms", phaseName, durationMs); |
| 312 | + |
| 313 | + // Register startup phase timing metric |
| 314 | + Gauge.builder("uid2_operator_startup_phase_duration_ms", () -> durationMs) |
| 315 | + .description("Time taken for major startup phases") |
| 316 | + .tags("phase_name", phaseName) |
| 317 | + .register(globalRegistry); |
| 318 | + } |
| 319 | + |
| 320 | + /** |
| 321 | + * Record timing for individual store metadata loading operations. |
| 322 | + * @param storeName Name of the store that had its metadata loaded |
| 323 | + * @param startTime When the metadata loading started |
| 324 | + */ |
| 325 | + private static void recordMetadataLoadingTime(String storeName, Instant startTime) { |
| 326 | + final Duration duration = Duration.between(startTime, Instant.now()); |
| 327 | + final double durationMs = duration.toMillis(); |
| 328 | + |
| 329 | + LOGGER.info("Store '{}' metadata loading completed in {} ms", storeName, durationMs); |
| 330 | + |
| 331 | + // Register individual store metadata loading time metric |
| 332 | + Gauge.builder("uid2_operator_store_metadata_duration_ms", () -> durationMs) |
| 333 | + .description("Time taken to load individual store metadata during startup") |
| 334 | + .tags("store_name", storeName) |
| 335 | + .register(globalRegistry); |
| 336 | + } |
| 337 | + |
284 | 338 | public static void main(String[] args) throws Exception { |
285 | 339 | // Record startup begin time following established patterns |
286 | 340 | startupBeginTime = Instant.now(); |
| 341 | + LOGGER.info("UID2 Operator startup initiated at {}", startupBeginTime); |
287 | 342 |
|
288 | 343 | java.security.Security.setProperty("networkaddress.cache.ttl" , "60"); |
289 | 344 |
|
@@ -402,30 +457,73 @@ private void run() throws Exception { |
402 | 457 | } |
403 | 458 |
|
404 | 459 | private Future<Void> createStoreVerticles() throws Exception { |
| 460 | + // Time the metadata loading phase - critical S3 operations |
| 461 | + metadataLoadingBeginTime = Instant.now(); |
| 462 | + LOGGER.info("Starting store metadata loading phase"); |
| 463 | + |
405 | 464 | // load metadatas for the first time |
406 | 465 | if (clientSideTokenGenerate) { |
| 466 | + Instant start = Instant.now(); |
407 | 467 | siteProvider.getMetadata(); |
| 468 | + recordMetadataLoadingTime("site", start); |
| 469 | + |
| 470 | + start = Instant.now(); |
408 | 471 | clientSideKeypairProvider.getMetadata(); |
| 472 | + recordMetadataLoadingTime("client_side_keypair", start); |
409 | 473 | } |
410 | 474 |
|
411 | 475 | if (validateServiceLinks) { |
| 476 | + Instant start = Instant.now(); |
412 | 477 | serviceProvider.getMetadata(); |
| 478 | + recordMetadataLoadingTime("service", start); |
| 479 | + |
| 480 | + start = Instant.now(); |
413 | 481 | serviceLinkProvider.getMetadata(); |
| 482 | + recordMetadataLoadingTime("service_link", start); |
414 | 483 | } |
415 | 484 |
|
416 | 485 | if (encryptedCloudFilesEnabled) { |
| 486 | + Instant start = Instant.now(); |
417 | 487 | cloudEncryptionKeyProvider.getMetadata(); |
| 488 | + recordMetadataLoadingTime("cloud_encryption_key", start); |
418 | 489 | } |
419 | 490 |
|
| 491 | + Instant start = Instant.now(); |
420 | 492 | clientKeyProvider.getMetadata(); |
| 493 | + recordMetadataLoadingTime("client_key", start); |
| 494 | + |
| 495 | + start = Instant.now(); |
421 | 496 | keysetKeyStore.getMetadata(); |
| 497 | + recordMetadataLoadingTime("keyset_key", start); |
| 498 | + |
| 499 | + start = Instant.now(); |
422 | 500 | keysetProvider.getMetadata(); |
| 501 | + recordMetadataLoadingTime("keyset", start); |
| 502 | + |
| 503 | + start = Instant.now(); |
423 | 504 | saltProvider.getMetadata(); |
| 505 | + recordMetadataLoadingTime("salt", start); |
| 506 | + |
| 507 | + Duration totalMetadataLoadingTime = Duration.between(metadataLoadingBeginTime, Instant.now()); |
| 508 | + LOGGER.info("Store metadata loading phase completed in {} ms", totalMetadataLoadingTime.toMillis()); |
| 509 | + recordPhaseTime("store_metadata_loading", totalMetadataLoadingTime); |
424 | 510 |
|
| 511 | + // Time the cloud sync setup |
| 512 | + Instant cloudSyncStart = Instant.now(); |
| 513 | + LOGGER.info("Setting up optout cloud sync"); |
| 514 | + |
425 | 515 | // create cloud sync for optout store |
426 | 516 | OptOutCloudSync optOutCloudSync = new OptOutCloudSync(config, false); |
427 | 517 | this.optOutStore.registerCloudSync(optOutCloudSync); |
| 518 | + |
| 519 | + Duration cloudSyncSetupTime = Duration.between(cloudSyncStart, Instant.now()); |
| 520 | + LOGGER.info("OptOut cloud sync setup completed in {} ms", cloudSyncSetupTime.toMillis()); |
| 521 | + recordPhaseTime("optout_cloud_sync_setup", cloudSyncSetupTime); |
428 | 522 |
|
| 523 | + // Time the rotating store verticles deployment |
| 524 | + Instant rotatingStoresStart = Instant.now(); |
| 525 | + LOGGER.info("Starting rotating store verticles deployment"); |
| 526 | + |
429 | 527 | // create rotating store verticles to poll for updates |
430 | 528 | Promise<Void> promise = Promise.promise(); |
431 | 529 | List<Future> fs = new ArrayList<>(); |
@@ -454,7 +552,12 @@ private Future<Void> createStoreVerticles() throws Exception { |
454 | 552 | fs.add(createAndDeployCloudSyncStoreVerticle("optout", fsOptOut, optOutCloudSync)); |
455 | 553 | CompositeFuture.all(fs).onComplete(ar -> { |
456 | 554 | if (ar.failed()) promise.fail(new Exception(ar.cause())); |
457 | | - else promise.complete(); |
| 555 | + else { |
| 556 | + Duration rotatingStoresTime = Duration.between(rotatingStoresStart, Instant.now()); |
| 557 | + LOGGER.info("Rotating store verticles deployment completed in {} ms", rotatingStoresTime.toMillis()); |
| 558 | + recordPhaseTime("rotating_store_verticles_deployment", rotatingStoresTime); |
| 559 | + promise.complete(); |
| 560 | + } |
458 | 561 | }); |
459 | 562 |
|
460 | 563 |
|
|
0 commit comments