From 290329503f5f5b57acb3ddc3b0fe79502cd7da05 Mon Sep 17 00:00:00 2001 From: Xing Gao Date: Thu, 2 May 2024 09:37:12 -0400 Subject: [PATCH] Release 3.6.0 (2024-05-01) ### Features * [Debug Reporting] Enable debug reporting by default * [DebugReporting] Add a log to get the libcurl queue time * add ability to tag AMIs * Add markdown-link-check to pre-commit * add support for AWS CodeBuild * add support for GCP Cloud Build * API Updates for Bid Currency Support for Top-Level Seller in Server-Orchestrated Multi-Seller Auctions * Enable TCMalloc for all B&A servers * support sending Nitro Enclave logs to AWS CloudWatch for debugging ### Bug Fixes * [Temp] Adds buyer bid to top level auctions for Chrome < v125 * Adjust ps_vlog pre-commit hook to avoid recursing symlinks * clean up log verbosity 2 * **deps:** Upgrade clang-format to v18 * **deps:** Upgrade pre-commit hooks * Ensure that the debug url length is capped Bug: 338216564 GitOrigin-RevId: 80d679ed731179f7041dd54ab336c2ec119923e4 Change-Id: I778be44f30e098d8ddc75399b0da797e5933f508 --- .bazelrc | 6 + .markdown-link-check.json | 21 + .pre-commit-config.yaml | 23 +- CHANGELOG.md | 26 + WORKSPACE | 12 + api/bidding_auction_servers.proto | 14 + builders/.github/workflows/scorecard.yaml | 12 +- builders/CHANGELOG.md | 14 + builders/images/build-debian/Dockerfile | 2 +- .../images/build-debian/compile_libprofiler | 1 + builders/tests/data/hashes/build-debian | 2 +- builders/tools/builder.sh | 1 + builders/version.txt | 2 +- .../terraform/environment/demo/buyer/buyer.tf | 9 +- .../environment/demo/seller/seller.tf | 9 +- .../autoscaling/instance_init_script.tftpl | 68 +- .../terraform/services/autoscaling/main.tf | 4 +- .../services/autoscaling/variables.tf | 8 +- .../services/iam_role_policies/main.tf | 14 + .../terraform/environment/demo/buyer/buyer.tf | 9 +- .../environment/demo/seller/seller.tf | 9 +- production/packaging/aws/build_and_test | 17 +- production/packaging/aws/codebuild/README.md | 199 +++++ .../packaging/aws/codebuild/buildspec.yaml | 46 ++ .../packaging/aws/common/ami/image.pkr.hcl | 14 +- production/packaging/aws/common/ami/setup.sh | 4 +- .../packaging/build_and_test_all_in_docker | 11 +- .../packaging/gcp/cloud_build/Dockerfile | 21 + .../packaging/gcp/cloud_build/README.md | 74 ++ .../packaging/gcp/cloud_build/cloudbuild.yaml | 50 ++ services/auction_service/BUILD | 2 + services/auction_service/auction_main.cc | 21 +- .../reporting/reporting_helper.cc | 11 +- services/auction_service/runtime_flags.h | 45 +- services/auction_service/score_ads_reactor.cc | 50 +- services/auction_service/utils/BUILD | 1 + services/auction_service/utils/proto_utils.cc | 95 ++- services/auction_service/utils/proto_utils.h | 4 +- .../auction_service/utils/proto_utils_test.cc | 31 + services/bidding_service/BUILD | 2 + services/bidding_service/bidding_main.cc | 21 +- .../bidding_service/bidding_service_test.cc | 17 +- .../bidding_service/generate_bids_reactor.cc | 20 +- .../generate_bids_reactor_test_utils.cc | 31 +- .../inference/inference_utils.cc | 2 +- ...ected_app_signals_generate_bids_reactor.cc | 19 +- ...tected_app_signals_generate_bids_reactor.h | 9 +- ..._app_signals_generate_bids_reactor_test.cc | 317 ++++---- services/bidding_service/runtime_flags.h | 44 +- services/buyer_frontend_service/BUILD | 2 + .../buyer_frontend_main.cc | 20 + .../get_bids_unary_reactor.cc | 14 +- ...ttp_bidding_signals_async_provider_test.cc | 108 +-- .../buyer_frontend_service/runtime_flags.h | 49 +- .../util/buyer_frontend_test_utils.cc | 5 +- services/common/clients/client_params.h | 4 +- services/common/clients/client_params_test.cc | 14 +- .../config/trusted_server_config_client.cc | 6 + .../config/trusted_server_config_client.h | 3 + services/common/clients/http/BUILD | 3 + .../http/multi_curl_http_fetcher_async.cc | 102 ++- .../http/multi_curl_http_fetcher_async.h | 58 +- .../multi_curl_http_fetcher_async_test.cc | 2 + .../http/multi_curl_request_manager.cc | 154 +++- .../clients/http/multi_curl_request_manager.h | 39 +- .../common/clients/http_kv_server/buyer/BUILD | 1 + .../buyer_key_value_async_http_client.cc | 13 +- .../buyer_key_value_async_http_client_test.cc | 46 +- .../fake_buyer_key_value_async_http_client.cc | 6 +- .../clients/http_kv_server/seller/BUILD | 1 + ...fake_seller_key_value_async_http_client.cc | 10 +- .../seller_key_value_async_http_client.cc | 15 +- ...seller_key_value_async_http_client_test.cc | 20 +- .../code_dispatch/code_dispatch_reactor.h | 4 +- .../code_fetch/periodic_bucket_fetcher.cc | 2 +- .../code_fetch/periodic_code_fetcher.cc | 8 +- .../code_fetch/periodic_code_fetcher_test.cc | 16 +- .../common/loggers/benchmarking_logger.cc | 6 +- services/common/loggers/no_ops_logger.h | 4 +- services/common/util/BUILD | 12 + services/common/util/binary_http_utils.h | 5 +- services/common/util/reporting_util.cc | 2 +- .../common/util/request_response_constants.h | 13 +- services/common/util/tcmalloc_utils.h | 59 ++ .../inference_sidecar/common/benchmark/BUILD | 17 +- .../common/benchmark/module_benchmark.cc | 27 +- .../common/benchmark/request_utils.cc | 49 ++ .../common/benchmark/request_utils.h | 31 + .../common/benchmark/sandbox_benchmark.cc | 37 +- .../inference_sidecar/common/modules/BUILD | 1 + .../common/modules/module_concurrency_test.cc | 29 +- .../modules/pytorch_v2_1_1/BUILD | 1 + .../modules/pytorch_v2_1_1/benchmark/BUILD | 1 + .../modules/tensorflow_v2_14_0/BUILD | 1 + .../tensorflow_v2_14_0/benchmark/BUILD | 26 + services/seller_frontend_service/BUILD | 2 + .../select_ad_reactor_benchmarks.cc | 6 +- ...ttp_scoring_signals_async_provider_test.cc | 83 +- .../seller_frontend_service/runtime_flags.h | 62 +- .../select_ad_reactor.cc | 67 +- .../select_ad_reactor.h | 3 +- .../select_ad_reactor_test.cc | 7 +- .../select_auction_result_reactor.cc | 11 +- .../select_auction_result_reactor_test.cc | 92 +-- .../seller_frontend_main.cc | 20 +- services/seller_frontend_service/util/BUILD | 1 + .../util/encryption_util.cc | 15 +- .../util/proto_mapping_util.cc | 36 +- .../util/proto_mapping_util_test.cc | 3 - .../seller_frontend_service/util/web_utils.cc | 2 + .../util/web_utils_test.cc | 63 +- third_party/libevent-evconfig.patch | 64 ++ third_party/libevent.BUILD | 45 ++ third_party/libevent.patch | 713 ++++++++++++++++++ tools/debug/start_auction | 4 +- tools/debug/start_bfe | 2 + tools/debug/start_bidding | 2 + tools/debug/start_sfe | 2 + version.txt | 2 +- 119 files changed, 2961 insertions(+), 836 deletions(-) create mode 100644 .markdown-link-check.json create mode 100644 production/packaging/aws/codebuild/README.md create mode 100644 production/packaging/aws/codebuild/buildspec.yaml create mode 100644 production/packaging/gcp/cloud_build/Dockerfile create mode 100644 production/packaging/gcp/cloud_build/README.md create mode 100644 production/packaging/gcp/cloud_build/cloudbuild.yaml create mode 100644 services/common/util/tcmalloc_utils.h create mode 100644 services/inference_sidecar/common/benchmark/request_utils.cc create mode 100644 services/inference_sidecar/common/benchmark/request_utils.h create mode 100644 third_party/libevent-evconfig.patch create mode 100644 third_party/libevent.BUILD create mode 100644 third_party/libevent.patch diff --git a/.bazelrc b/.bazelrc index fd120bcc..76541859 100644 --- a/.bazelrc +++ b/.bazelrc @@ -27,6 +27,11 @@ build:clang --client_env=BAZEL_CXXOPTS=-std=c++17 build:clang --copt=-Werror=thread-safety #disable the "int conversion" warning for external/nitrokmscli_aws_c_http/source/websocket_decoder.c build:clang --per_file_copt=external/nitrokmscli_.*\.c@-Wno-int-conversion +# https://github.com/google/tcmalloc/blob/master/docs/tuning.md#build-time-optimizations +build:clang --cxxopt=-fsized-deallocation +build:clang --host_cxxopt=-fsized-deallocation +build:clang --cxxopt=-fnew-alignment=8 +build:clang --host_cxxopt=-fnew-alignment=8 # Flag compiler warnings as errors. build:cpp_no_warn --copt=-Werror @@ -101,6 +106,7 @@ build:asan --copt=-fno-omit-frame-pointer build:asan --linkopt=-fsanitize=address build:asan --linkopt=-fuse-ld=lld build:asan --action_env=ASAN_OPTIONS=detect_leaks=1:color=always +build:asan --custom_malloc=@bazel_tools//tools/cpp:malloc # Memory sanitizer, set action_env to segregate cache entries build:msan --action_env=PRIVACY_SANDBOX_SERVERS_MSAN=1 diff --git a/.markdown-link-check.json b/.markdown-link-check.json new file mode 100644 index 00000000..e1a9603e --- /dev/null +++ b/.markdown-link-check.json @@ -0,0 +1,21 @@ +{ + "ignorePatterns": [ + { + "pattern": "^tg/" + }, + { + "pattern": "^http://go/" + } + ], + "replacementPatterns": [ + { + "pattern": "^/", + "replacement": "{{BASEURL}}/" + } + ], + "timeout": "20s", + "retryOn429": true, + "retryCount": 5, + "fallbackRetryDelay": "30s", + "aliveStatusCodes": [200, 206] +} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 83fd8f4e..4e42bbf6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -29,7 +29,7 @@ exclude: (?x)^( fail_fast: false repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.6.0 hooks: - id: end-of-file-fixer - id: fix-byte-order-marker @@ -63,7 +63,7 @@ repos: files: ^$ - repo: https://github.com/bufbuild/buf - rev: v1.26.1 + rev: v1.31.0 hooks: - id: buf-format args: @@ -72,7 +72,7 @@ repos: - api/ - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v16.0.6 + rev: v18.1.4 hooks: - id: clang-format types_or: @@ -121,7 +121,7 @@ repos: - id: ps_vlog_123 name: Don't use PS_VLOG(0/1/2/3) - entry: sh -c '! grep -RE "PS_VLOG[(][01][,)]" services/' + entry: sh -c '! grep --files-with-matches --recursive -E "PS_VLOG[(][012][,)]" services/' language: system types_or: - c++ @@ -129,10 +129,9 @@ repos: pass_filenames: false always_run: false fail_fast: false - verbose: true - repo: https://github.com/pre-commit/mirrors-prettier - rev: v3.0.3 + rev: v3.1.0 hooks: - id: prettier types_or: @@ -146,11 +145,19 @@ repos: )$ - repo: https://github.com/DavidAnson/markdownlint-cli2 - rev: v0.10.0 + rev: v0.13.0 hooks: - id: markdownlint-cli2 name: lint markdown +- repo: https://github.com/tcort/markdown-link-check + rev: v3.11.2 + hooks: + - id: markdown-link-check + args: + - -c + - .markdown-link-check.json + - repo: local hooks: - id: buildifier @@ -181,7 +188,7 @@ repos: - --quiet - repo: https://github.com/psf/black - rev: 23.9.1 + rev: 24.4.1 hooks: - id: black name: black python formatter diff --git a/CHANGELOG.md b/CHANGELOG.md index 13f71458..bbf7eae3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,32 @@ All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines. +## 3.6.0 (2024-05-01) + + +### Features + +* [Debug Reporting] Enable debug reporting by default +* [DebugReporting] Add a log to get the libcurl queue time +* add ability to tag AMIs +* Add kv e2e tests environment +* Add markdown-link-check to pre-commit +* add support for AWS CodeBuild +* add support for GCP Cloud Build +* API Updates for Bid Currency Support for Top-Level Seller in Server-Orchestrated Multi-Seller Auctions +* Enable TCMalloc for all B&A servers +* support sending Nitro Enclave logs to AWS CloudWatch for debugging + + +### Bug Fixes + +* [Temp] Adds buyer bid to top level auctions for Chrome < v125 +* Adjust ps_vlog pre-commit hook to avoid recursing symlinks +* clean up log verbosity 2 +* **deps:** Upgrade clang-format to v18 +* **deps:** Upgrade pre-commit hooks +* Ensure that the debug url length is capped + ## 3.5.0 (2024-04-24) diff --git a/WORKSPACE b/WORKSPACE index 7f7d1772..ff8a21e8 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -126,3 +126,15 @@ local_repository( name = "tensorflow_v2_14_0", path = "services/inference_sidecar/modules/tensorflow_v2_14_0", ) + +http_archive( + name = "libevent", + build_file = "//third_party:libevent.BUILD", + patch_args = ["-p1"], + patches = [ + "//third_party:libevent.patch", + ], + sha256 = "8836ad722ab211de41cb82fe098911986604f6286f67d10dfb2b6787bf418f49", + strip_prefix = "libevent-release-2.1.12-stable", + urls = ["https://github.com/libevent/libevent/archive/refs/tags/release-2.1.12-stable.zip"], +) diff --git a/api/bidding_auction_servers.proto b/api/bidding_auction_servers.proto index d7b4ca36..834d1464 100644 --- a/api/bidding_auction_servers.proto +++ b/api/bidding_auction_servers.proto @@ -542,6 +542,20 @@ message SelectAdRequest { // object in SelectAdResponse will be encrypted with a public key // of the specified cloud platform instead of the shared encryption context. EncryptionCloudPlatform top_level_cloud_platform = 11; + + // Optional. For use by the top-level seller in a server-orchestrated + // multiseller auction only. Specifies configuration information about the + // component sellers. + message PerComponentSellerConfig { + // The currency in which the top-level seller expects this component seller + // to submit bids. Expressed as three capital letters, ISO 4217 suggested. + string expected_currency = 1; + } + + // Optional. For use by the top-level seller in a server-orchestrated + // multiseller auction only. The key in the map corresponds to the seller + // identifier in AuctionResult.auction_params.component_seller. + map per_component_seller_config = 12; } message ComponentAuctionResult { // AuctionResult from a server component auction. diff --git a/builders/.github/workflows/scorecard.yaml b/builders/.github/workflows/scorecard.yaml index dbcb6200..22bd7f8e 100644 --- a/builders/.github/workflows/scorecard.yaml +++ b/builders/.github/workflows/scorecard.yaml @@ -26,14 +26,14 @@ on: - cron: '35 10 * * 4' push: branches: - - main + - main # Declare default permissions as read only. permissions: read-all jobs: analysis: - name: Scorecard analysis + name: OpenSSF Scorecard analysis runs-on: ubuntu-latest permissions: # Needed to upload the results to code-scanning dashboard. @@ -46,12 +46,12 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0 + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 with: persist-credentials: false - name: Run analysis - uses: ossf/scorecard-action@e38b1902ae4f44df626f11ba0734b14fb91f8f86 # v2.1.2 + uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 with: results_file: results.sarif results_format: sarif @@ -73,7 +73,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: Upload artifact - uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: SARIF file path: results.sarif @@ -81,6 +81,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: Upload to code-scanning - uses: github/codeql-action/upload-sarif@17573ee1cc1b9d061760f3a006fc4aac4f944fd5 # v2.2.4 + uses: github/codeql-action/upload-sarif@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9 with: sarif_file: results.sarif diff --git a/builders/CHANGELOG.md b/builders/CHANGELOG.md index e323d8a3..10be7b47 100644 --- a/builders/CHANGELOG.md +++ b/builders/CHANGELOG.md @@ -2,6 +2,20 @@ All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines. +## 0.58.0 (2024-04-26) + + +### Features + +* add missing AWS env variable for CodeBuild + +## 0.57.1 (2024-03-28) + + +### Bug Fixes + +* Upgrade OpenSSF scorecard GitHub Action + ## 0.57.0 (2024-03-10) diff --git a/builders/images/build-debian/Dockerfile b/builders/images/build-debian/Dockerfile index eb370730..735d9b66 100644 --- a/builders/images/build-debian/Dockerfile +++ b/builders/images/build-debian/Dockerfile @@ -18,7 +18,7 @@ ARG BASE_IMAGE=ubuntu:20.04 # hadolint ignore=DL3006 FROM ${BASE_IMAGE} as libprofiler-builder ENV CC=clang \ - CXX=clang + CXX=clang++ ADD https://github.com/gperftools/gperftools/releases/download/gperftools-2.13/gperftools-2.13.tar.gz /build/gperftools.tar.gz ADD https://apt.llvm.org/llvm.sh /build/llvm.sh COPY compile_libprofiler /scripts/ diff --git a/builders/images/build-debian/compile_libprofiler b/builders/images/build-debian/compile_libprofiler index f05397fb..bcc15a68 100755 --- a/builders/images/build-debian/compile_libprofiler +++ b/builders/images/build-debian/compile_libprofiler @@ -24,6 +24,7 @@ function install_clang() { /build/llvm.sh ${CLANG_VER} apt-get --quiet install -y --no-install-recommends libc++-${CLANG_VER}-dev update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${CLANG_VER} 100 + update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-${CLANG_VER} 100 rm -f llvm.sh clang --version diff --git a/builders/tests/data/hashes/build-debian b/builders/tests/data/hashes/build-debian index c89114f2..8836d286 100644 --- a/builders/tests/data/hashes/build-debian +++ b/builders/tests/data/hashes/build-debian @@ -1 +1 @@ -38cc8a23a6a56eb6567bef3685100cd3be1c0491dcc8b953993c42182da3fa40 +35e001149b0e33cba53e9a393c157ef920b3ab2adabcebd07eee0e3d4d9fccf3 diff --git a/builders/tools/builder.sh b/builders/tools/builder.sh index 77317aae..d2ca2f98 100644 --- a/builders/tools/builder.sh +++ b/builders/tools/builder.sh @@ -112,6 +112,7 @@ function builder::add_aws_env_vars() { "AWS_REGION" "AWS_DEFAULT_REGION" "AWS_PROFILE" + "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" ) } diff --git a/builders/version.txt b/builders/version.txt index 78756de3..e8f304f8 100644 --- a/builders/version.txt +++ b/builders/version.txt @@ -1 +1 @@ -0.57.0 \ No newline at end of file +0.58.0 \ No newline at end of file diff --git a/production/deploy/aws/terraform/environment/demo/buyer/buyer.tf b/production/deploy/aws/terraform/environment/demo/buyer/buyer.tf index fda0d10e..2b2eb6d8 100644 --- a/production/deploy/aws/terraform/environment/demo/buyer/buyer.tf +++ b/production/deploy/aws/terraform/environment/demo/buyer/buyer.tf @@ -85,7 +85,7 @@ module "buyer" { # "protectedAppSignalsBiddingWasmHelperUrl": "", # "urlFetchPeriodMs": 13000000, # "urlFetchTimeoutMs": 30000, - # "enableBuyerDebugUrlGeneration": false, + # "enableBuyerDebugUrlGeneration": true, # "enableAdtechCodeLogging": false, # "prepareDataForAdsRetrievalJsUrl": "", # "prepareDataForAdsRetrievalWasmHelperUrl": "", @@ -115,5 +115,12 @@ module "buyer" { INFERENCE_SIDECAR_BINARY_PATH = "" # Example: "/server/bin/inference_sidecar" INFERENCE_MODEL_BUCKET_NAME = "" # Example: "" INFERENCE_MODEL_BUCKET_PATHS = "" # Example: "," + + # TCMalloc related config parameters. + # See: https://github.com/google/tcmalloc/blob/master/docs/tuning.md + BIDDING_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND = "4096" + BIDDING_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES = "10737418240" + BFE_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND = "4096" + BFE_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES = "10737418240" } } diff --git a/production/deploy/aws/terraform/environment/demo/seller/seller.tf b/production/deploy/aws/terraform/environment/demo/seller/seller.tf index 135d7347..7c5f4546 100644 --- a/production/deploy/aws/terraform/environment/demo/seller/seller.tf +++ b/production/deploy/aws/terraform/environment/demo/seller/seller.tf @@ -82,7 +82,7 @@ module "seller" { # "auctionJsUrl": "https://example.com/scoreAd.js", # "urlFetchPeriodMs": 13000000, # "urlFetchTimeoutMs": 30000, - # "enableSellerDebugUrlGeneration": false, + # "enableSellerDebugUrlGeneration": true, # This flag should only be set if console.logs from the AdTech code(Ex:scoreAd(), reportResult(), reportWin()) # execution need to be exported as VLOG. # Note: turning on this flag will lead to higher memory consumption for AdTech code execution @@ -119,5 +119,12 @@ module "seller" { KEY_REFRESH_FLOW_RUN_FREQUENCY_SECONDS = "" # Example: "10800" MAX_ALLOWED_SIZE_DEBUG_URL_BYTES = "" # Example: "65536" MAX_ALLOWED_SIZE_ALL_DEBUG_URLS_KB = "" # Example: "3000" + + # TCMalloc related config parameters. + # See: https://github.com/google/tcmalloc/blob/master/docs/tuning.md + AUCTION_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND = "4096" + AUCTION_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES = "10737418240" + SFE_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND = "4096" + SFE_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES = "10737418240" } } diff --git a/production/deploy/aws/terraform/services/autoscaling/instance_init_script.tftpl b/production/deploy/aws/terraform/services/autoscaling/instance_init_script.tftpl index 863b2a0a..b30db2ee 100644 --- a/production/deploy/aws/terraform/services/autoscaling/instance_init_script.tftpl +++ b/production/deploy/aws/terraform/services/autoscaling/instance_init_script.tftpl @@ -1,15 +1,21 @@ #!/bin/bash +# Having issues with servers failing init? On the EC2 instance, +# you can find log outputs for this script via: +# sudo cat /var/log/cloud-init-output.log + +set -x + # Start Envoy before the nitro allocator service. # Otherwise, Envoy segfaults. # See b/276754615 for more detail. # TODO(b/276754615): Update after envoy fixes its bug. docker run --rm \ ---network host \ --v /etc/envoy:/etc/envoy \ -envoyproxy/envoy-distroless-dev:e0cc4306253f0318f9dcbc77cf32feb6245c378f \ ---config-path /etc/envoy/envoy.yaml \ --l info & + --network host \ + -v /etc/envoy:/etc/envoy \ + envoyproxy/envoy-distroless-dev:e0cc4306253f0318f9dcbc77cf32feb6245c378f \ + --config-path /etc/envoy/envoy.yaml \ + -l info & # Ping Envoy until it's ready. Silent fail otherwise -- # load balancer health checks will eventually kill this instance. curl --retry 6 --retry-all-errors localhost:9902/ready @@ -18,7 +24,7 @@ curl --retry 6 --retry-all-errors localhost:9902/ready systemctl stop nitro-enclaves-allocator.service # Allocate resources available to enclave -export ALLOCATOR_YAML=/etc/nitro_enclaves/allocator.yaml +declare -r -x ALLOCATOR_YAML=/etc/nitro_enclaves/allocator.yaml cat >"$${ALLOCATOR_YAML}" < "/amazon-cloudwatch-agent.json" +{ + "agent": { + "metrics_collection_interval": 10 + }, + "logs": { + "logs_collected": { + "files": { + "collect_list": [ + { + "file_path": "${enclave_log_path}", + "log_group_name": "${service}-tee-logs", + "log_stream_name": "${environment}-{instance_id}", + "timestamp_format": "%Y-%m-%d %H:%M:%S" + } + ] + } + } + } +} +EOF + + # Start cloudwatch + sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \ + -a fetch-config -m ec2 \ + -c file:/amazon-cloudwatch-agent.json -s + + nitro-cli run-enclave \ + --cpu-count ${enclave_cpu_count} --memory ${enclave_memory_mib} \ + --eif-path /opt/privacysandbox/server_enclave_image.eif \ + --enclave-cid 16 --attach-console > ${enclave_log_path} +else + nitro-cli run-enclave \ + --cpu-count ${enclave_cpu_count} --memory ${enclave_memory_mib} \ + --eif-path /opt/privacysandbox/server_enclave_image.eif \ + --enclave-cid 16 +fi diff --git a/production/deploy/aws/terraform/services/autoscaling/main.tf b/production/deploy/aws/terraform/services/autoscaling/main.tf index bc61bc56..74fbdbd9 100644 --- a/production/deploy/aws/terraform/services/autoscaling/main.tf +++ b/production/deploy/aws/terraform/services/autoscaling/main.tf @@ -37,7 +37,9 @@ resource "aws_launch_template" "instance_launch_template" { enclave_memory_mib = var.enclave_memory_mib, enclave_cpu_count = var.enclave_cpu_count, service = var.service, - debug_mode = "${var.enclave_debug_mode ? "--attach-console > output.log" : ""}" + environment = var.environment, + enclave_log_path = var.enclave_log_path, + enclave_debug_mode = var.enclave_debug_mode })) metadata_options { diff --git a/production/deploy/aws/terraform/services/autoscaling/variables.tf b/production/deploy/aws/terraform/services/autoscaling/variables.tf index 394e30ee..c765af79 100644 --- a/production/deploy/aws/terraform/services/autoscaling/variables.tf +++ b/production/deploy/aws/terraform/services/autoscaling/variables.tf @@ -78,7 +78,13 @@ variable "service" { } variable "enclave_debug_mode" { - description = "If true, strats the Nitro enclave with --debug-mode." + description = "If true, starts the Nitro enclave with --debug-mode." type = bool default = false } + +variable "enclave_log_path" { + description = "Absolute path to where nitro enclave logs will be written. Only used if enclave_debug_mode = true." + type = string + default = "/output.log" +} diff --git a/production/deploy/aws/terraform/services/iam_role_policies/main.tf b/production/deploy/aws/terraform/services/iam_role_policies/main.tf index 6d36829a..048cfcf3 100644 --- a/production/deploy/aws/terraform/services/iam_role_policies/main.tf +++ b/production/deploy/aws/terraform/services/iam_role_policies/main.tf @@ -82,6 +82,15 @@ data "aws_iam_policy_document" "instance_policy_doc" { effect = "Allow" resources = ["*"] } + statement { + actions = [ + "s3:ListBucket", + "s3:GetBucketLocation", + "s3:GetObject", + ] + effect = "Allow" + resources = ["*"] + } } resource "aws_iam_policy" "instance_policy" { @@ -99,6 +108,11 @@ resource "aws_iam_role_policy_attachment" "ssm_instance_role_attachment" { policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" } +resource "aws_iam_role_policy_attachment" "cloudwatch_instance_role_attachment" { + role = var.server_instance_role_name + policy_arn = "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy" +} + # Set up policies for using EC2 instance connect. data "aws_iam_policy_document" "ssh_instance_policy_doc" { statement { diff --git a/production/deploy/gcp/terraform/environment/demo/buyer/buyer.tf b/production/deploy/gcp/terraform/environment/demo/buyer/buyer.tf index f4cd5a34..e5dc94f8 100644 --- a/production/deploy/gcp/terraform/environment/demo/buyer/buyer.tf +++ b/production/deploy/gcp/terraform/environment/demo/buyer/buyer.tf @@ -83,7 +83,7 @@ module "buyer" { # "protectedAppSignalsBiddingWasmHelperUrl": "", # "urlFetchPeriodMs": 13000000, # "urlFetchTimeoutMs": 30000, - # "enableBuyerDebugUrlGeneration": false, + # "enableBuyerDebugUrlGeneration": true, # "enableAdtechCodeLogging": false, # "prepareDataForAdsRetrievalJsUrl": "", # "prepareDataForAdsRetrievalWasmHelperUrl": "", @@ -122,6 +122,13 @@ module "buyer" { INFERENCE_SIDECAR_BINARY_PATH = "" # Example: "/server/bin/inference_sidecar" INFERENCE_MODEL_BUCKET_NAME = "" # Example: "" INFERENCE_MODEL_BUCKET_PATHS = "" # Example: "," + + # TCMalloc related config parameters. + # See: https://github.com/google/tcmalloc/blob/master/docs/tuning.md + BIDDING_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND = "4096" # Example: 4096 + BIDDING_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES = "10737418240" # Example: 10737418240 + BFE_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND = "4096" + BFE_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES = "10737418240" } # Please manually create a Google Cloud domain name, dns zone, and SSL certificate. diff --git a/production/deploy/gcp/terraform/environment/demo/seller/seller.tf b/production/deploy/gcp/terraform/environment/demo/seller/seller.tf index fab9eb2c..8f8cd2c7 100644 --- a/production/deploy/gcp/terraform/environment/demo/seller/seller.tf +++ b/production/deploy/gcp/terraform/environment/demo/seller/seller.tf @@ -79,7 +79,7 @@ module "seller" { # "auctionJsUrl": "https://example.com/scoreAd.js", # "urlFetchPeriodMs": 13000000, # "urlFetchTimeoutMs": 30000, - # "enableSellerDebugUrlGeneration": false, + # "enableSellerDebugUrlGeneration": true, # "enableAdtechCodeLogging": false, # "enableReportResultUrlGeneration": true, # "enableReportWinUrlGeneration": true, @@ -124,6 +124,13 @@ module "seller" { SFE_TLS_CERT = module.secrets.tls_cert # You may remove the secrets module and instead either inline or use an auto.tfvars for this variable. MAX_ALLOWED_SIZE_DEBUG_URL_BYTES = "" # Example: "65536" MAX_ALLOWED_SIZE_ALL_DEBUG_URLS_KB = "" # Example: "3000" + + # TCMalloc related config parameters. + # See: https://github.com/google/tcmalloc/blob/master/docs/tuning.md + AUCTION_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND = "4096" + AUCTION_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES = "10737418240" + SFE_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND = "4096" + SFE_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES = "10737418240" } # Please manually create a Google Cloud domain name, dns zone, and SSL certificate. diff --git a/production/packaging/aws/build_and_test b/production/packaging/aws/build_and_test index a0c38ca9..c2503136 100755 --- a/production/packaging/aws/build_and_test +++ b/production/packaging/aws/build_and_test @@ -39,6 +39,7 @@ usage: --server-image Server docker image tarfile --service-path [REQUIRED] One of: auction_service, bidding_service, buyer_frontend_service, seller_frontend_service --with-ami AMI region in which to build and store AWS AMIs. Use multiple times to specify more than one region + --aws-image-tag Custom image tag for AMI image. Applied to AMI as tag value for key 'build_env'. environment variables (all optional): WORKSPACE Set the path to the workspace (repo root) @@ -52,6 +53,7 @@ USAGE declare -a AMI_REGIONS declare BUILD_FLAVOR=prod +declare AWS_IMAGE_TAG="" while [[ $# -gt 0 ]]; do case "$1" in @@ -70,6 +72,10 @@ while [[ $# -gt 0 ]]; do shift shift ;; + --aws-image-tag) + AWS_IMAGE_TAG="$2" + shift 2 + ;; --verbose) set -o xtrace shift @@ -158,8 +164,17 @@ if [[ -n ${AMI_REGIONS[0]} ]]; then unzip -o -d "${DIST}"/aws "${DIST}"/aws/artifacts_proto.zip printf "==== build AWS AMI (using packer) =====\n" regions="$(arr_to_string_list AMI_REGIONS)" + build_version="$(git -C ${WORKSPACE} describe --tags --always || echo no-git-version)-${BUILD_FLAVOR}" builder::cbuild_al2 " set -o errexit -packer build -var=regions='${regions}' -var=service=${SERVICE} -var=commit_version=$(git rev-parse HEAD) -var=distribution_dir=dist/aws -var=workspace=/src/workspace production/packaging/aws/common/ami/image.pkr.hcl +packer build \ + -var=regions='${regions}' \ + -var=service=${SERVICE} \ + -var=git_commit=$(git rev-parse HEAD) \ + -var=build_version=${build_version} \ + -var=build_env=${AWS_IMAGE_TAG} \ + -var=distribution_dir=dist/aws \ + -var=workspace=/src/workspace \ + production/packaging/aws/common/ami/image.pkr.hcl " fi diff --git a/production/packaging/aws/codebuild/README.md b/production/packaging/aws/codebuild/README.md new file mode 100644 index 00000000..5e96ffdb --- /dev/null +++ b/production/packaging/aws/codebuild/README.md @@ -0,0 +1,199 @@ +# AWS CodeBuild for Bidding and Auction Services + +## Overview + +This README contains instructions on how to setup [AWS CodeBuild](https://aws.amazon.com/codebuild/) +to build the Bidding and Auction service +[AMIs](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html). These AMIs can then be +directly used for the +[deployment process](https://github.com/privacysandbox/protected-auction-services-docs/blob/main/bidding_auction_services_aws_guide.md#step-2-deployment). + +### Why do this? + +The Bidding and Auction services can take around 2 hours (with 72 cores) to build. If you create an +automated build pipeline that builds new Bidding and Auction service releases, you can avoid manual +labor and increase operational efficiency. Binaries and docker images will be provided directly in +the future. + +## CodeBuild Configuration + +### Prerequisites + +#### Choose an AWS Region + +Setup will be simplest if you do everything in a single region. Verify that AWS CodeBuild is +available in your chosen region via the +[Global Infrastructure page](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/). + +#### Service Role + +You must first create a role via [IAM](https://aws.amazon.com/iam). This service role will need to +be able to build and upload AMIs, so we will need to modify its permission policies. Attach the +following policy (you can add it as an inline policy via the Role Permissions -> Add permissions +feature in IAM): + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ecr-public:GetAuthorizationToken", + "sts:GetServiceBearerToken", + "ec2:AttachVolume", + "ec2:AuthorizeSecurityGroupIngress", + "ec2:CopyImage", + "ec2:CreateImage", + "ec2:CreateKeyPair", + "ec2:CreateSecurityGroup", + "ec2:CreateSnapshot", + "ec2:CreateTags", + "ec2:CreateVolume", + "ec2:DeleteKeyPair", + "ec2:DeleteSecurityGroup", + "ec2:DeleteSnapshot", + "ec2:DeleteVolume", + "ec2:DeregisterImage", + "ec2:DescribeImageAttribute", + "ec2:DescribeImages", + "ec2:DescribeInstances", + "ec2:DescribeInstanceStatus", + "ec2:DescribeRegions", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSnapshots", + "ec2:DescribeSubnets", + "ec2:DescribeTags", + "ec2:DescribeVolumes", + "ec2:DetachVolume", + "ec2:GetPasswordData", + "ec2:ModifyImageAttribute", + "ec2:ModifyInstanceAttribute", + "ec2:ModifySnapshotAttribute", + "ec2:RegisterImage", + "ec2:RunInstances", + "ec2:StopInstances", + "ec2:TerminateInstances" + ], + "Resource": "*" + } + ] +} +``` + +Additionally, increase the `Maximum session duration` to 4 hours by editing the Role Summary. This +is necessary because the build uses the role's session token and we want to avoid the token expiring +while the build is still running. + +#### Docker Login Credentials + +You will need a [Docker Hub](https://hub.docker.com/) account because the images we use to run the +build are, by default, sourced from Docker Hub. + +Create an AWS Secret (via [Secret Manager](https://aws.amazon.com/secrets-manager/)) to store your +Docker Hub password. When creating the secret, choose secret type 'Other' and make sure to store the +password as plaintext (not as a key/value pair). Add the following permissions to your secret: + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam:::role/" + }, + "Action": "secretsmanager:GetSecretValue", + "Resource": "*" + } + ] +} +``` + +The build process will login to the provided Docker Hub account at build time. + +### Project + +Create a build project in your preferred AWS Region. The following sections will guide you through +the build project configuration. + +### Source Repo + +Set Github as your source provider, and use the public repository: +`https://github.com/privacysandbox/bidding-auction-servers.git`. No other source repo config is +necessary. + +However, if you want to enable webhook events (after selecting 'Repository in my GitHub account', +webhook events are not available for the 'Public repository' option) and run an automatic build for +every release, you will have to clone the public repo into a Github repo under your ownership and +keep your clone up to date with the public repo. If you prefer to avoid cloning the public +repository, any time you want a new build for Bidding and Auction serivces you must follow the steps +[here](#start-build). + +### Environment + +Use the following configuration: + +1. Provisioning model: On-Demand +1. Environment image: Managed image +1. Compute: EC2 +1. Operating system: Ubuntu +1. Runtime: Standard +1. Image: `aws/codebuild/standard:7.0` +1. Image version: Always use latest +1. Service role: see the [service role section](#service-role-permissions). +1. Report auto-discover: disable + +Additional configuration: + +1. Timeout: 4 Hours +1. Queued timeout: 8 Hours +1. Privileged: Enable +1. Certificate: Do not install +1. Compute: `145 GB memory, 72 vCPUs` +1. Environment variables: + + ```plaintext + key: AMI_REGION value: + key: DOCKERHUB_USERNAME value: + key: DOCKERHUB_PASSWORD_SECRET_NAME value: + ``` + +### Buildspec + +Select `Use a buildspec file`. Enter the following: +`production/packaging/aws/codebuild/buildspec.yaml`. + +### Batch configuration + +Leave blank. + +### Artifacts + +Type: No artifacts + +Additional configuration: + +Encryption key: use default + +### Logs + +Enable CloudWatch logs. + +### Service role permissions + +Choose the service role you created in the [prerequisites](#service-role) and enable allowing AWS +CodeBuild to modify the role so it can be used with this build project. + +### Start Build + +Save the changes and create/update the project. Then, click `Start build with overrides` from the +Build projects directory and try building the project with the latest Bidding and Auction release +(specify a tag, such as `v3.5.0`, in the Source version config field). + +If the build succeeds, you should have 4 AMIs in your region: + +1. auction-service +1. bidding-service +1. buyer-frontend-service +1. seller-frontend-service diff --git a/production/packaging/aws/codebuild/buildspec.yaml b/production/packaging/aws/codebuild/buildspec.yaml new file mode 100644 index 00000000..94efbaca --- /dev/null +++ b/production/packaging/aws/codebuild/buildspec.yaml @@ -0,0 +1,46 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: 0.2 + +env: + variables: + # CODEBUILD_SRC_DIR is a CodeBuild-provided env variable. + # Other variables can be provided by the CodeBuild project GUI or AWS CLI. + # Check the README and the following link for more information about + # env vars required by this script: + # https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-env-vars.html + AMI_REGION: us-east-1 # Default. Region where to upload the final AMIs. + DOCKERHUB_USERNAME: YOUR_USERNAME # Default. Used to login to Docker with DOCKERHUB_PASSWORD_SECRET_NAME. + DOCKERHUB_PASSWORD_SECRET_NAME: codebuild-dockerhub-password # Default. Name of AWS Secret resource. + +phases: + build: + commands: + - | + aws secretsmanager get-secret-value \ + --secret-id ${DOCKERHUB_PASSWORD_SECRET_NAME} \ + --query SecretString --output text \ + | docker login -u ${DOCKERHUB_USERNAME} --password-stdin + - | + WORKSPACE_MOUNT=${CODEBUILD_SRC_DIR} \ + production/packaging/build_and_test_all_in_docker \ + --service-path buyer_frontend_service \ + --service-path seller_frontend_service \ + --service-path bidding_service \ + --service-path auction_service \ + --instance aws --platform aws \ + --with-ami ${AMI_REGION} \ + --build-flavor prod \ + --no-tests --no-precommit diff --git a/production/packaging/aws/common/ami/image.pkr.hcl b/production/packaging/aws/common/ami/image.pkr.hcl index 4953e770..74414753 100644 --- a/production/packaging/aws/common/ami/image.pkr.hcl +++ b/production/packaging/aws/common/ami/image.pkr.hcl @@ -22,7 +22,15 @@ EOF } } -variable "commit_version" { +variable "git_commit" { + type = string +} + +variable "build_version" { + type = string +} + +variable "build_env" { type = string } @@ -84,7 +92,9 @@ source "amazon-ebs" "dataserver" { owners = ["137112412989"] } tags = { - commit_version = var.commit_version + git_commit = var.git_commit + build_version = var.build_version + build_env = var.build_env } ssh_username = "ec2-user" } diff --git a/production/packaging/aws/common/ami/setup.sh b/production/packaging/aws/common/ami/setup.sh index 76a96a11..fa309a14 100644 --- a/production/packaging/aws/common/ami/setup.sh +++ b/production/packaging/aws/common/ami/setup.sh @@ -18,7 +18,9 @@ set -o pipefail # Install necessary dependencies sudo yum update -y -sudo yum install -y docker +sudo yum install -y \ + amazon-cloudwatch-agent \ + docker wget -O /tmp/aws-otel-collector.rpm https://aws-otel-collector.s3.amazonaws.com/amazon_linux/amd64/latest/aws-otel-collector.rpm sudo yum localinstall -y /tmp/aws-otel-collector.rpm sudo amazon-linux-extras install -y aws-nitro-enclaves-cli diff --git a/production/packaging/build_and_test_all_in_docker b/production/packaging/build_and_test_all_in_docker index 22aa484e..e0b67b89 100755 --- a/production/packaging/build_and_test_all_in_docker +++ b/production/packaging/build_and_test_all_in_docker @@ -48,6 +48,7 @@ declare -i SKIP_PRECOMMIT=0 declare -i NO_TESTS=0 declare -i NO_PLATFORM_BUILD=0 declare -a AMI_REGIONS +declare AWS_IMAGE_TAG declare GCP_IMAGE_TAG declare GCP_IMAGE_REPO declare -i GCP_SKIP_IMAGE_UPLOAD=0 @@ -75,10 +76,13 @@ usage: --no-precommit Skip precommit checks --no-tests Skip tests --no-platform-build Skip platform-specific building and testing + --verbose Enable verbose output + +If platform is aws: --with-ami AMI region in which to build and store AWS AMIs. Use multiple times to specify more than one region. If empty or not specified, none will be built. - --verbose Enable verbose output + --aws-image-tag Custom image tag for AMI image. Applied to AMI as tag value for key 'build_env'. If platform is gcp: --gcp-skip-image-upload Skip GCP image upload (and sha256 recording). @@ -124,6 +128,10 @@ while [[ $# -gt 0 ]]; do AMI_REGIONS+=("$2") shift 2 || usage ;; + --aws-image-tag) + AWS_IMAGE_TAG+=("$2") + shift 2 || usage + ;; --service-path) SERVICES+=("$2") shift 2 || usage @@ -310,6 +318,7 @@ if [[ ${NO_PLATFORM_BUILD} -eq 0 ]]; then for region in "${AMI_REGIONS[@]}"; do EXTRA_ARGS+=(--with-ami "${region}") done + EXTRA_ARGS+=(--aws-image-tag ${AWS_IMAGE_TAG}) if [[ ${VERBOSE} -eq 1 ]]; then EXTRA_ARGS+=("--verbose") fi diff --git a/production/packaging/gcp/cloud_build/Dockerfile b/production/packaging/gcp/cloud_build/Dockerfile new file mode 100644 index 00000000..f6cb3ddc --- /dev/null +++ b/production/packaging/gcp/cloud_build/Dockerfile @@ -0,0 +1,21 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Use a debian-based image with gcloud and docker installed: +FROM google/cloud-sdk:473.0.0 + +# Install additional dependencies +RUN apt-get update && apt-get install -y \ + git \ + gettext-base # Package for envsubst diff --git a/production/packaging/gcp/cloud_build/README.md b/production/packaging/gcp/cloud_build/README.md new file mode 100644 index 00000000..a9258aa2 --- /dev/null +++ b/production/packaging/gcp/cloud_build/README.md @@ -0,0 +1,74 @@ +# GCP Code Build for Bidding and Auction Services + +## Overview + +This README contains instructions on how to setup [GCP Cloud Build](https://cloud.google.com/build) +to build the Bidding and Auction service Docker Images for use in +[Confidential Spaces](https://cloud.google.com/docs/security/confidential-space). These images can +be directly used for the +[deployment process](https://github.com/privacysandbox/protected-auction-services-docs/blob/main/bidding_auction_services_gcp_guide.md#guide-package-deploy-and-run-a-service). + +### Why do this? + +The Bidding and Auction services can take around 2 hours (with 32 cores) to build. If you create an +automated build pipeline that builds new Bidding and Auction service releases, you can avoid manual +labor and increase operational efficiency. Binaries and docker images will be provided directly in +the future. + +## Cloud Build Configuration + +### Prerequisites + +#### Connecting to Github + +First, follow the steps to +[connect a Github repository](https://cloud.google.com/build/docs/automating-builds/github/connect-repo-github?generation=2nd-gen) +and create a host connection. You will need to clone the +[Bidding and Auction repo](https://github.com/privacysandbox/bidding-auction-servers) to your own +Github account before you can connect it to your GCP project's Cloud Build. + +#### Configuring an Image Repo + +Please create an [Artifact Registry](https://cloud.google.com/artifact-registry) repo to hold all of +the Bidding and Auction service images that will be created. Four directories will be created in the +repo (`auction_serivce`, `bidding_service`, `seller_frontend_service`, and +`buyer_frontend_service`). We suggest a default repo name of +`us-docker.pkg.dev/${PROJECT_ID}/services`. + +#### Service Account Permissions + +Navigate to the Cloud Build page in the GCP GUI and click on Settings. Make sure the service account +permissions have 'Service Account User' enabled. Then, in IAM, additionally make sure that the +service account has Artifact Registry Writer permissions. The build script will attempt to push +images to the image repo specified using the service account for permissions. + +### Create a Trigger + +#### Source + +You must create a build trigger. Starting with a +[manual](https://cloud.google.com/build/docs/triggers#manual) or +[Github](https://cloud.google.com/build/docs/triggers#github) trigger is recommended. Please make +sure to use a '2nd gen' repository source type. + +#### Configuration + +1. Type: Cloud Build configuration file (yaml or json) +1. Location: Repository + + ```plaintext + production/packaging/gcp/cloud_build/cloudbuild.yaml + ``` + +1. Substitution Variables + + Note: these will override variables in the cloudbuild.yaml. + + ```plaintext + key: _GCP_IMAGE_REPO value: service images repo URI from prerequisites (default: us-docker.pkg.dev/${PROJECT_ID}/services) + key: _GCP_IMAGE_TAG value: any tag (default: from-cloudbuild) + ``` + +1. Service account: Use the account created [previously](#service-account-permissions). + +After configuring your Trigger, click Save. You may manually run it from the Triggers page. diff --git a/production/packaging/gcp/cloud_build/cloudbuild.yaml b/production/packaging/gcp/cloud_build/cloudbuild.yaml new file mode 100644 index 00000000..030f9b16 --- /dev/null +++ b/production/packaging/gcp/cloud_build/cloudbuild.yaml @@ -0,0 +1,50 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +steps: + - name: gcr.io/cloud-builders/docker + args: + - build + - -t + - service-builder + - -f + - production/packaging/gcp/cloud_build/Dockerfile + - . + - name: service-builder + env: + - WORKSPACE_MOUNT=/workspace + script: | + #!/usr/bin/env bash + production/packaging/build_and_test_all_in_docker \ + --service-path buyer_frontend_service \ + --service-path bidding_service \ + --service-path seller_frontend_service \ + --service-path auction_service \ + --instance gcp --platform gcp \ + --build-flavor prod \ + --gcp-image-tag ${_GCP_IMAGE_TAG} \ + --gcp-image-repo ${_GCP_IMAGE_REPO} \ + --no-tests --no-precommit +substitutions: + # The following variables may be overridden via the gcloud CLI or the + # CloudBuild Trigger GUI. + # See https://cloud.google.com/build/docs/configuring-builds/substitute-variable-values + # for more information. + _GCP_IMAGE_TAG: from-cloudbuild # Default. Useful for organization. The build already tags the images with verison information. + _GCP_IMAGE_REPO: us-docker.pkg.dev/${PROJECT_ID}/services # Default. Artifact Registry repo to house images for each service. +timeout: 10800s +options: + machineType: E2_HIGHCPU_32 + automapSubstitutions: true + logging: CLOUD_LOGGING_ONLY diff --git a/services/auction_service/BUILD b/services/auction_service/BUILD index d58f45a6..bae60e26 100644 --- a/services/auction_service/BUILD +++ b/services/auction_service/BUILD @@ -278,6 +278,7 @@ cc_binary( "-Wl,-rpath,\\$$ORIGIN/../lib", ], local_defines = ENABLE_CORE_DUMPS_DEFINES, + malloc = "@com_google_tcmalloc//tcmalloc", visibility = ["//visibility:public"], deps = [ ":auction_code_fetch_config_cc_proto", @@ -294,6 +295,7 @@ cc_binary( "//services/common/encryption:crypto_client_factory", "//services/common/encryption:key_fetcher_factory", "//services/common/telemetry:configure_telemetry", + "//services/common/util:tcmalloc_utils", "@com_github_grpc_grpc//:grpc++", "@com_github_grpc_grpc//:grpc++_reflection", # for grpc_cli "@com_google_absl//absl/debugging:failure_signal_handler", diff --git a/services/auction_service/auction_main.cc b/services/auction_service/auction_main.cc index 51527c2a..ae861683 100644 --- a/services/auction_service/auction_main.cc +++ b/services/auction_service/auction_main.cc @@ -47,6 +47,7 @@ #include "services/common/encryption/crypto_client_factory.h" #include "services/common/encryption/key_fetcher_factory.h" #include "services/common/telemetry/configure_telemetry.h" +#include "services/common/util/tcmalloc_utils.h" #include "src/concurrent/event_engine_executor.h" #include "src/core/lib/event_engine/default_event_engine.h" #include "src/encryption/key_fetcher/key_fetcher_manager.h" @@ -75,6 +76,15 @@ ABSL_FLAG(std::optional, js_worker_queue_len, std::nullopt, "The length of queue size for a single JS execution worker."); ABSL_FLAG(std::optional, enable_report_win_input_noising, std::nullopt, "Enables noising and bucketing of the inputs to reportWin"); +ABSL_FLAG(std::optional, + auction_tcmalloc_background_release_rate_bytes_per_second, + std::nullopt, + "Amount of cached memory in bytes that is returned back to the " + "system per second"); +ABSL_FLAG(std::optional, auction_tcmalloc_max_total_thread_cache_bytes, + std::nullopt, + "Maximum amount of cached memory in bytes across all threads (or " + "logical CPUs)"); namespace privacy_sandbox::bidding_auction_servers { @@ -137,7 +147,11 @@ absl::StatusOr GetConfigClient( MAX_ALLOWED_SIZE_DEBUG_URL_BYTES); config_client.SetFlag(FLAGS_max_allowed_size_all_debug_urls_kb, MAX_ALLOWED_SIZE_ALL_DEBUG_URLS_KB); - + config_client.SetFlag( + FLAGS_auction_tcmalloc_background_release_rate_bytes_per_second, + AUCTION_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND); + config_client.SetFlag(FLAGS_auction_tcmalloc_max_total_thread_cache_bytes, + AUCTION_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES); if (absl::GetFlag(FLAGS_init_config_client)) { PS_RETURN_IF_ERROR(config_client.Init(config_param_prefix)).LogError() << "Config client failed to initialize."; @@ -159,6 +173,11 @@ absl::Status RunServer() { PS_ASSIGN_OR_RETURN(TrustedServersConfigClient config_client, GetConfigClient(config_util.GetConfigParameterPrefix())); + MaySetBackgroundReleaseRate(config_client.GetInt64Parameter( + AUCTION_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND)); + MaySetMaxTotalThreadCacheBytes(config_client.GetInt64Parameter( + AUCTION_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES)); + std::string_view port = config_client.GetStringParameter(PORT); std::string server_address = absl::StrCat("0.0.0.0:", port); diff --git a/services/auction_service/reporting/reporting_helper.cc b/services/auction_service/reporting/reporting_helper.cc index 0d43362d..7619587a 100644 --- a/services/auction_service/reporting/reporting_helper.cc +++ b/services/auction_service/reporting/reporting_helper.cc @@ -282,7 +282,7 @@ std::string GetBuyerMetadataJson( kJoinCount, join_count, buyer_reporting_signals_obj.GetAllocator()); } if (dispatch_request_data.buyer_reporting_metadata.recency.has_value()) { - PS_VLOG(kInfoMsg, dispatch_request_data.log_context) + PS_VLOG(kNoisyInfo, dispatch_request_data.log_context) << "BuyerReportingMetadata: Recency:" << dispatch_request_data.buyer_reporting_metadata.recency.value(); long recency = @@ -353,7 +353,7 @@ std::string GetBuyerMetadataJson( absl::StatusOr buyer_reporting_metadata_json = SerializeJsonDoc(buyer_reporting_signals_obj); if (!buyer_reporting_metadata_json.ok()) { - PS_VLOG(2, dispatch_request_data.log_context) + PS_VLOG(kNoisyWarn, dispatch_request_data.log_context) << "Error constructing buyer_reporting_metadata_input for " "reportingEntryFunction"; return kDefaultBuyerReportingMetadata; @@ -367,7 +367,7 @@ std::vector> GetReportingInput( absl::StatusOr seller_reporting_signals = GetSellerReportingSignals(dispatch_request_data, dispatch_request_config); if (!seller_reporting_signals.ok()) { - PS_VLOG(2, dispatch_request_data.log_context) + PS_VLOG(kNoisyWarn, dispatch_request_data.log_context) << "Error generating Seller Reporting Signals for Reporting input"; return {}; } @@ -404,9 +404,8 @@ std::vector> GetReportingInput( } } - PS_VLOG(2, dispatch_request_data.log_context) - << "\n\nReporting Input Args:" - << "\nAuction Config:\n" + PS_VLOG(kDispatch, dispatch_request_data.log_context) + << "\n\nReporting Input Args:" << "\nAuction Config:\n" << *(input[ReportingArgIndex(ReportingArgs::kAuctionConfig)]) << "\nSeller Reporting Signals:\n" << *(input[ReportingArgIndex(ReportingArgs::kSellerReportingSignals)]) diff --git a/services/auction_service/runtime_flags.h b/services/auction_service/runtime_flags.h index 5473d634..10448b3f 100644 --- a/services/auction_service/runtime_flags.h +++ b/services/auction_service/runtime_flags.h @@ -23,27 +23,40 @@ namespace privacy_sandbox::bidding_auction_servers { // Define runtime flag names. -inline constexpr char PORT[] = "AUCTION_PORT"; -inline constexpr char HEALTHCHECK_PORT[] = "AUCTION_HEALTHCHECK_PORT"; -inline constexpr char ENABLE_AUCTION_SERVICE_BENCHMARK[] = +inline constexpr absl::string_view PORT = "AUCTION_PORT"; +inline constexpr absl::string_view HEALTHCHECK_PORT = + "AUCTION_HEALTHCHECK_PORT"; +inline constexpr absl::string_view ENABLE_AUCTION_SERVICE_BENCHMARK = "ENABLE_AUCTION_SERVICE_BENCHMARK"; -inline constexpr char SELLER_CODE_FETCH_CONFIG[] = "SELLER_CODE_FETCH_CONFIG"; -inline constexpr char JS_NUM_WORKERS[] = "JS_NUM_WORKERS"; -inline constexpr char JS_WORKER_QUEUE_LEN[] = "JS_WORKER_QUEUE_LEN"; -inline constexpr char ENABLE_REPORT_WIN_INPUT_NOISING[] = +inline constexpr absl::string_view SELLER_CODE_FETCH_CONFIG = + "SELLER_CODE_FETCH_CONFIG"; +inline constexpr absl::string_view JS_NUM_WORKERS = "JS_NUM_WORKERS"; +inline constexpr absl::string_view JS_WORKER_QUEUE_LEN = "JS_WORKER_QUEUE_LEN"; +inline constexpr absl::string_view ENABLE_REPORT_WIN_INPUT_NOISING = "ENABLE_REPORT_WIN_INPUT_NOISING"; +inline constexpr char + AUCTION_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND[] = + "AUCTION_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND"; +inline constexpr absl::string_view + AUCTION_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES = + "AUCTION_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES"; -inline constexpr absl::string_view kFlags[] = {PORT, - HEALTHCHECK_PORT, - ENABLE_AUCTION_SERVICE_BENCHMARK, - SELLER_CODE_FETCH_CONFIG, - JS_NUM_WORKERS, - JS_WORKER_QUEUE_LEN, - ENABLE_REPORT_WIN_INPUT_NOISING}; +inline constexpr int kNumRuntimeFlags = 9; +inline constexpr std::array kFlags = { + PORT, + HEALTHCHECK_PORT, + ENABLE_AUCTION_SERVICE_BENCHMARK, + SELLER_CODE_FETCH_CONFIG, + JS_NUM_WORKERS, + JS_WORKER_QUEUE_LEN, + ENABLE_REPORT_WIN_INPUT_NOISING, + AUCTION_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND, + AUCTION_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES, +}; inline std::vector GetServiceFlags() { - int size = sizeof(kFlags) / sizeof(kFlags[0]); - std::vector flags(kFlags, kFlags + size); + std::vector flags(kFlags.begin(), + kFlags.begin() + kNumRuntimeFlags); for (absl::string_view flag : kCommonServiceFlags) { flags.push_back(flag); diff --git a/services/auction_service/score_ads_reactor.cc b/services/auction_service/score_ads_reactor.cc index aef1ecf1..9dd90a3f 100644 --- a/services/auction_service/score_ads_reactor.cc +++ b/services/auction_service/score_ads_reactor.cc @@ -58,10 +58,10 @@ inline void MayVlogRomaResponses( ContextImpl& log_context) { if (PS_VLOG_IS_ON(2)) { for (const auto& dispatch_response : responses) { - PS_VLOG(2, log_context) + PS_VLOG(kDispatch, log_context) << "ScoreAds V8 Response: " << dispatch_response.status(); if (dispatch_response.ok()) { - PS_VLOG(2, log_context) << dispatch_response->resp; + PS_VLOG(kDispatch, log_context) << dispatch_response->resp; } } } @@ -252,7 +252,7 @@ absl::Status ScoreAdsReactor::PopulateTopLevelAuctionDispatchRequests( log_context_, enable_adtech_code_logging_, enable_debug_reporting, code_version_); if (!dispatch_request.ok()) { - PS_VLOG(2, log_context_) + PS_VLOG(kDispatch, log_context_) << "Failed to create scoring request for protected audience: " << dispatch_request.status(); continue; @@ -266,9 +266,10 @@ absl::Status ScoreAdsReactor::PopulateTopLevelAuctionDispatchRequests( ad_data_.emplace(dispatch_request->id, MapAuctionResultToAdWithBidMetadata(auction_result)); if (!inserted) { - PS_VLOG(2, log_context_) << "Protected Audience ScoreAd Request id " - "conflict detected: " - << dispatch_request->id; + PS_VLOG(kNoisyWarn, log_context_) + << "Protected Audience ScoreAd Request id " + "conflict detected: " + << dispatch_request->id; continue; } @@ -296,7 +297,7 @@ void ScoreAdsReactor::PopulateProtectedAudienceDispatchRequests( ad->bid_currency()), code_version_); if (!dispatch_request.ok()) { - PS_VLOG(2, log_context_) + PS_VLOG(kNoisyWarn, log_context_) << "Failed to create scoring request for protected audience: " << dispatch_request.status(); continue; @@ -304,9 +305,10 @@ void ScoreAdsReactor::PopulateProtectedAudienceDispatchRequests( auto [unused_it, inserted] = ad_data_.emplace(dispatch_request->id, std::move(ad)); if (!inserted) { - PS_VLOG(2, log_context_) << "Protected Audience ScoreAd Request id " - "conflict detected: " - << dispatch_request->id; + PS_VLOG(kNoisyWarn, log_context_) + << "Protected Audience ScoreAd Request id " + "conflict detected: " + << dispatch_request->id; continue; } @@ -344,7 +346,7 @@ void ScoreAdsReactor::MayPopulateProtectedAppSignalsDispatchRequests( raw_request_.top_level_seller(), pas_ad_with_bid->bid_currency()), code_version_); if (!dispatch_request.ok()) { - PS_VLOG(2, log_context_) + PS_VLOG(kNoisyWarn, log_context_) << "Failed to create scoring request for protected app signals ad: " << dispatch_request.status(); continue; @@ -353,7 +355,7 @@ void ScoreAdsReactor::MayPopulateProtectedAppSignalsDispatchRequests( auto [unused_it, inserted] = protected_app_signals_ad_data_.emplace( dispatch_request->id, std::move(pas_ad_with_bid)); if (!inserted) { - PS_VLOG(2, log_context_) + PS_VLOG(kNoisyWarn, log_context_) << "ProtectedAppSignals ScoreAd Request id conflict detected: " << dispatch_request->id; continue; @@ -562,7 +564,7 @@ void ScoreAdsReactor::HandleScoredAd(int index, float buyer_bid, if (CheckAndUpdateModifiedBid(auction_scope_, buyer_bid, ad_with_bid_currency, &ad_score)) { - PS_VLOG(kInfoMsg, log_context_) + PS_VLOG(kNoisyInfo, log_context_) << "Setting modified bid value to original buyer bid value (and " "currency) as the " "modified bid is not set. For interest group: " @@ -578,7 +580,7 @@ void ScoreAdsReactor::HandleScoredAd(int index, float buyer_bid, ad_score.interest_group_owner()); ad_rejection_reason->set_rejection_reason( SellerRejectionReason::BID_FROM_SCORE_AD_FAILED_CURRENCY_CHECK); - PS_VLOG(kInfoMsg, log_context_) + PS_VLOG(kNoisyInfo, log_context_) << "Skipping component bid as it does not match seller_currency: " << interest_group_name << ": " << ad_score.DebugString(); } @@ -593,7 +595,7 @@ void ScoreAdsReactor::HandleScoredAd(int index, float buyer_bid, ad_score.interest_group_owner()); ad_rejection_reason->set_rejection_reason( SellerRejectionReason::INVALID_BID); - PS_VLOG(kInfoMsg, log_context_) + PS_VLOG(kNoisyInfo, log_context_) << "Skipping ad_score as its incomingBidInSellerCurrency was " "modified " "when it should not have been: " @@ -614,7 +616,7 @@ void ScoreAdsReactor::HandleScoredAd(int index, float buyer_bid, // Ignore component level winner if it is not allowed to // participate in the top level auction. // TODO(b/311234165): Add metric for rejected component ads. - PS_VLOG(kInfoMsg, log_context_) + PS_VLOG(kNoisyInfo, log_context_) << "Skipping component bid as it is not allowed for " << interest_group_name << ": " << ad_score.DebugString(); return; @@ -712,11 +714,12 @@ ScoringData ScoreAdsReactor::FindWinningAd( long current_all_debug_urls_chars = 0; auto ad_score = ParseScoreAdResponse( *response_json, max_allowed_size_debug_url_chars_, - max_allowed_size_all_debug_urls_chars_, current_all_debug_urls_chars, + max_allowed_size_all_debug_urls_chars_, (auction_scope_ == AuctionScope::AUCTION_SCOPE_DEVICE_COMPONENT_MULTI_SELLER || auction_scope_ == - AuctionScope::AUCTION_SCOPE_SERVER_COMPONENT_MULTI_SELLER)); + AuctionScope::AUCTION_SCOPE_SERVER_COMPONENT_MULTI_SELLER), + current_all_debug_urls_chars); if (!ad_score.ok()) { LogWarningForBadResponse(ad_score.status(), *response, ad, log_context_); continue; @@ -874,9 +877,6 @@ void ScoreAdsReactor::ScoreAdsCallback( PerformDebugReporting(winning_ad); } *raw_response_.mutable_ad_score() = *winning_ad; - - PS_VLOG(2, log_context_) << "ScoreAdsRawResponse:\n" - << raw_response_.DebugString(); if (!enable_report_result_url_generation_) { benchmarking_logger_->HandleResponseEnd(); EncryptAndFinishOK(); @@ -889,10 +889,10 @@ void ScoreAdsReactor::ReportingCallback( const std::vector>& responses) { if (PS_VLOG_IS_ON(2)) { for (const auto& dispatch_response : responses) { - PS_VLOG(2, log_context_) + PS_VLOG(kDispatch, log_context_) << "Reporting V8 Response: " << dispatch_response.status(); if (dispatch_response.ok()) { - PS_VLOG(2, log_context_) << dispatch_response.value().resp; + PS_VLOG(kDispatch, log_context_) << dispatch_response.value().resp; } } } @@ -909,7 +909,7 @@ void ScoreAdsReactor::ReportingCallback( } if (PS_VLOG_IS_ON(1) && enable_adtech_code_logging_) { for (std::string& log : reporting_response.value().seller_logs) { - PS_VLOG(kInfoMsg, log_context_) + PS_VLOG(kNoisyInfo, log_context_) << "Log from Seller's execution script:" << log; } for (std::string& log : reporting_response.value().seller_error_logs) { @@ -922,7 +922,7 @@ void ScoreAdsReactor::ReportingCallback( << "Warning Log from Seller's execution script:" << log; } for (std::string& log : reporting_response.value().buyer_logs) { - PS_VLOG(kInfoMsg, log_context_) + PS_VLOG(kNoisyInfo, log_context_) << "Log from Buyer's execution script:" << log; } for (std::string& log : reporting_response.value().buyer_error_logs) { diff --git a/services/auction_service/utils/BUILD b/services/auction_service/utils/BUILD index fe1bcda7..79fdf25e 100644 --- a/services/auction_service/utils/BUILD +++ b/services/auction_service/utils/BUILD @@ -51,6 +51,7 @@ cc_test( "//services/auction_service:auction_constants", "//services/auction_service:score_ads_reactor_test_util", "//services/common/test:random", + "//services/common/util:json_util", "@com_google_googletest//:gtest_main", "@google_privacysandbox_servers_common//src/core/test/utils", ], diff --git a/services/auction_service/utils/proto_utils.cc b/services/auction_service/utils/proto_utils.cc index b13e8e35..8c7b8880 100644 --- a/services/auction_service/utils/proto_utils.cc +++ b/services/auction_service/utils/proto_utils.cc @@ -20,6 +20,7 @@ #include "rapidjson/writer.h" #include "services/common/util/json_util.h" #include "services/common/util/reporting_util.h" +#include "services/common/util/request_response_constants.h" namespace privacy_sandbox::bidding_auction_servers { @@ -189,13 +190,46 @@ std::string MakeOpenBidMetadataJson( return bid_metadata; } +// Gets the debug reporting URL (either win or loss URL) if the URL will not +// exceed the caps set within here. +inline absl::string_view GetDebugUrlIfInLimit( + const std::string& url_type, const rapidjson::Value& debug_reporting_urls, + int max_allowed_size_debug_url_chars, + int max_allowed_size_all_debug_urls_chars, + int current_all_debug_urls_chars) { + auto debug_url_it = debug_reporting_urls.FindMember(url_type.c_str()); + if (debug_url_it == debug_reporting_urls.MemberEnd() || + !debug_url_it->value.IsString()) { + return ""; + } + + absl::string_view debug_url = debug_url_it->value.GetString(); + int url_length = debug_url.length(); + if (url_length <= max_allowed_size_debug_url_chars && + url_length + current_all_debug_urls_chars <= + max_allowed_size_all_debug_urls_chars) { + PS_VLOG(8) << "Included the " << url_type << ": " << debug_url + << " with length: " << url_length + << ", previous total length: " << current_all_debug_urls_chars + << ", new total length: " + << current_all_debug_urls_chars + url_length; + return debug_url; + } else { + PS_VLOG(8) << "Skipping " << url_type << " of length: " << url_length + << ", since it will cause the new running total to become: " + << current_all_debug_urls_chars + url_length + << "(which surpasses the limit: " + << max_allowed_size_all_debug_urls_chars << ")"; + } + return ""; +} + } // namespace void MayLogScoreAdsInput(const std::vector>& input, ContextImpl& log_context) { - PS_VLOG(2, log_context) - << "\n\nScore Ad Input Args:" - << "\nAdMetadata:\n" + PS_VLOG(kDispatch, log_context) + << "\n\nScore Ad Input Args:" << "\nAdMetadata:\n" << *(input[ScoreArgIndex(ScoreAdArgs::kAdMetadata)]) << "\nBid:\n" << *(input[ScoreArgIndex(ScoreAdArgs::kBid)]) << "\nAuction Config:\n" << *(input[ScoreArgIndex(ScoreAdArgs::kAuctionConfig)]) @@ -270,7 +304,7 @@ BuildTrustedScoringSignals( raw_request.scoring_signals().data()); if (parse_result.IsError()) { // TODO (b/285215004): Print offset to ease debugging. - PS_VLOG(2, log_context) + PS_VLOG(kNoisyWarn, log_context) << "Trusted scoring signals JSON parse error: " << rapidjson::GetParseError_En(parse_result.Code()) << ", trusted signals were: " << raw_request.scoring_signals(); @@ -342,7 +376,7 @@ BuildTrustedScoringSignals( combined_formatted_ad_signals.try_emplace(render_url, std::move(buffer)); } - PS_VLOG(2, log_context) + PS_VLOG(kStats, log_context) << "\nTrusted Scoring Signals Deserialize Time: " << ToInt64Microseconds((absl::Now() - start_parse_time)) << " microseconds for " << combined_formatted_ad_signals.size() @@ -426,8 +460,8 @@ ParseAdRejectionReason(const rapidjson::Document& score_ad_resp, absl::StatusOr ParseScoreAdResponse( const rapidjson::Document& score_ad_resp, int max_allowed_size_debug_url_chars, - long max_allowed_size_all_debug_urls_chars, - long current_all_debug_urls_chars, bool device_component_auction) { + int64_t max_allowed_size_all_debug_urls_chars, + bool device_component_auction, int64_t& current_all_debug_urls_chars) { ScoreAdsResponse::AdScore score_ads_response; // Default value. score_ads_response.set_allow_component_auction(false); @@ -511,37 +545,28 @@ absl::StatusOr ParseScoreAdResponse( if (debug_report_urls_itr == score_ad_resp.MemberEnd()) { return score_ads_response; } + DebugReportUrls debug_report_urls; - if (debug_report_urls_itr->value.HasMember( - kAuctionDebugWinUrlPropertyForScoreAd) && - debug_report_urls_itr->value[kAuctionDebugWinUrlPropertyForScoreAd] - .IsString()) { - absl::string_view win_debug_url = - debug_report_urls_itr->value[kAuctionDebugWinUrlPropertyForScoreAd] - .GetString(); - int win_url_length = win_debug_url.length(); - if (win_url_length <= max_allowed_size_debug_url_chars && - win_url_length + current_all_debug_urls_chars <= - max_allowed_size_all_debug_urls_chars) { - debug_report_urls.set_auction_debug_win_url(win_debug_url); - current_all_debug_urls_chars += win_url_length; - } + const auto& debug_reporting_urls = debug_report_urls_itr->value; + + absl::string_view win_debug_url = GetDebugUrlIfInLimit( + kAuctionDebugWinUrlPropertyForScoreAd, debug_reporting_urls, + max_allowed_size_debug_url_chars, max_allowed_size_all_debug_urls_chars, + current_all_debug_urls_chars); + if (!win_debug_url.empty()) { + debug_report_urls.set_auction_debug_win_url(win_debug_url); + current_all_debug_urls_chars += win_debug_url.size(); } - if (debug_report_urls_itr->value.HasMember( - kAuctionDebugLossUrlPropertyForScoreAd) && - debug_report_urls_itr->value[kAuctionDebugLossUrlPropertyForScoreAd] - .IsString()) { - absl::string_view loss_debug_url = - debug_report_urls_itr->value[kAuctionDebugLossUrlPropertyForScoreAd] - .GetString(); - int loss_url_length = loss_debug_url.length(); - if (loss_url_length <= max_allowed_size_debug_url_chars && - loss_url_length + current_all_debug_urls_chars <= - max_allowed_size_all_debug_urls_chars) { - debug_report_urls.set_auction_debug_loss_url(loss_debug_url); - } + absl::string_view loss_debug_url = GetDebugUrlIfInLimit( + kAuctionDebugLossUrlPropertyForScoreAd, debug_reporting_urls, + max_allowed_size_debug_url_chars, max_allowed_size_all_debug_urls_chars, + current_all_debug_urls_chars); + if (!loss_debug_url.empty()) { + debug_report_urls.set_auction_debug_loss_url(loss_debug_url); + current_all_debug_urls_chars += loss_debug_url.size(); } - *score_ads_response.mutable_debug_report_urls() = debug_report_urls; + *score_ads_response.mutable_debug_report_urls() = + std::move(debug_report_urls); return score_ads_response; } diff --git a/services/auction_service/utils/proto_utils.h b/services/auction_service/utils/proto_utils.h index 52936aee..da9cc69a 100644 --- a/services/auction_service/utils/proto_utils.h +++ b/services/auction_service/utils/proto_utils.h @@ -81,8 +81,8 @@ ParseAdRejectionReason(const rapidjson::Document& score_ad_resp, absl::StatusOr ParseScoreAdResponse( const rapidjson::Document& score_ad_resp, int max_allowed_size_debug_url_chars, - long max_allowed_size_all_debug_urls_chars, - long current_all_debug_urls_chars, bool device_component_auction); + int64_t max_allowed_size_all_debug_urls_chars, + bool device_component_auction, int64_t& current_all_debug_urls_chars); constexpr int ScoreArgIndex(ScoreAdArgs arg) { return static_cast>(arg); diff --git a/services/auction_service/utils/proto_utils_test.cc b/services/auction_service/utils/proto_utils_test.cc index d394bede..c20eaca6 100644 --- a/services/auction_service/utils/proto_utils_test.cc +++ b/services/auction_service/utils/proto_utils_test.cc @@ -25,6 +25,7 @@ #include "services/auction_service/auction_constants.h" #include "services/auction_service/score_ads_reactor_test_util.h" #include "services/common/test/random.h" +#include "services/common/util/json_util.h" #include "services/common/util/proto_util.h" #include "src/core/test/utils/proto_test_utils.h" @@ -365,5 +366,35 @@ TEST(BuildScoreAdRequestTest, PopulatesFeatureFlagsForPASAdWithBidMetadata) { } } +TEST(ScoreAdsTest, ParsesScoreAdResponseRespectsDebugUrlLimits) { + std::string long_win_url(1024, 'A'); + std::string long_loss_url(1025, 'B'); + auto scored_ad = ParseJsonString(absl::Substitute( + R"({ + "desirability" : 10, + "allowComponentAuction" : false, + "debugReportUrls": { + "auctionDebugLossUrl": "$0", + "auctionDebugWinUrl": "$1" + } + })", + long_loss_url, long_win_url)); + CHECK_OK(scored_ad); + int64_t current_all_debug_urls_chars = 0; + auto parsed_response = ParseScoreAdResponse( + *scored_ad, /*max_allowed_size_debug_url_chars=*/65536, + /*max_allowed_size_all_debug_urls_chars=*/1024, + /*device_component_auction=*/false, current_all_debug_urls_chars); + CHECK_OK(parsed_response); + std::cerr << " parsed response: \n" << parsed_response->DebugString() << "\n"; + EXPECT_TRUE(parsed_response->has_debug_report_urls()); + EXPECT_FALSE( + parsed_response->debug_report_urls().auction_debug_win_url().empty()); + EXPECT_EQ(parsed_response->debug_report_urls().auction_debug_win_url().size(), + 1024); + EXPECT_TRUE( + parsed_response->debug_report_urls().auction_debug_loss_url().empty()); +} + } // namespace } // namespace privacy_sandbox::bidding_auction_servers diff --git a/services/bidding_service/BUILD b/services/bidding_service/BUILD index 6dcc044d..e37212ac 100644 --- a/services/bidding_service/BUILD +++ b/services/bidding_service/BUILD @@ -237,6 +237,7 @@ cc_binary( "-Wl,-rpath,\\$$ORIGIN/../lib", ], local_defines = ENABLE_CORE_DUMPS_DEFINES, + malloc = "@com_google_tcmalloc//tcmalloc", visibility = ["//visibility:public"], deps = [ ":bidding_code_fetch_config_cc_proto", @@ -259,6 +260,7 @@ cc_binary( "//services/common/telemetry:configure_telemetry", "//services/common/util:file_util", "//services/common/util:request_response_constants", + "//services/common/util:tcmalloc_utils", "@com_github_grpc_grpc//:grpc++", "@com_github_grpc_grpc//:grpc++_reflection", # for grpc_cli "@com_google_absl//absl/debugging:failure_signal_handler", diff --git a/services/bidding_service/bidding_main.cc b/services/bidding_service/bidding_main.cc index a56cd733..6c0c65b6 100644 --- a/services/bidding_service/bidding_main.cc +++ b/services/bidding_service/bidding_main.cc @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include #include #include #include @@ -54,6 +55,7 @@ #include "services/common/telemetry/configure_telemetry.h" #include "services/common/util/file_util.h" #include "services/common/util/request_response_constants.h" +#include "services/common/util/tcmalloc_utils.h" #include "src/concurrent/event_engine_executor.h" #include "src/encryption/key_fetcher/key_fetcher_manager.h" #include "src/public/cpio/interface/blob_storage_client/blob_storage_client_interface.h" @@ -90,6 +92,15 @@ ABSL_FLAG(std::optional, ad_retrieval_kv_server_egress_tls, std::nullopt, "If true, ad retrieval service gRPC client uses TLS."); ABSL_FLAG(std::optional, kv_server_egress_tls, std::nullopt, "If true, KV service gRPC client uses TLS."); +ABSL_FLAG(std::optional, + bidding_tcmalloc_background_release_rate_bytes_per_second, + std::nullopt, + "Amount of cached memory in bytes that is returned back to the " + "system per second"); +ABSL_FLAG(std::optional, bidding_tcmalloc_max_total_thread_cache_bytes, + std::nullopt, + "Maximum amount of cached memory in bytes across all threads (or " + "logical CPUs)"); namespace privacy_sandbox::bidding_auction_servers { @@ -170,7 +181,11 @@ absl::StatusOr GetConfigClient( INFERENCE_MODEL_BUCKET_PATHS); config_client.SetFlag(FLAGS_inference_sidecar_runtime_config, INFERENCE_SIDECAR_RUNTIME_CONFIG); - + config_client.SetFlag( + FLAGS_bidding_tcmalloc_background_release_rate_bytes_per_second, + BIDDING_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND); + config_client.SetFlag(FLAGS_bidding_tcmalloc_max_total_thread_cache_bytes, + BIDDING_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES); if (absl::GetFlag(FLAGS_init_config_client)) { PS_RETURN_IF_ERROR(config_client.Init(config_param_prefix)).LogError() << "Config client failed to initialize."; @@ -210,6 +225,10 @@ absl::Status RunServer() { PS_ASSIGN_OR_RETURN(TrustedServersConfigClient config_client, GetConfigClient(config_util.GetConfigParameterPrefix())); + MaySetBackgroundReleaseRate(config_client.GetInt64Parameter( + BIDDING_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND)); + MaySetMaxTotalThreadCacheBytes(config_client.GetInt64Parameter( + BIDDING_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES)); std::string_view port = config_client.GetStringParameter(PORT); std::string server_address = absl::StrCat("0.0.0.0:", port); diff --git a/services/bidding_service/bidding_service_test.cc b/services/bidding_service/bidding_service_test.cc index 637a89e7..003d832c 100644 --- a/services/bidding_service/bidding_service_test.cc +++ b/services/bidding_service/bidding_service_test.cc @@ -273,15 +273,14 @@ TEST_F(BiddingProtectedAppSignalsTest, BadAdRetrievalResponseFinishesRpc) { CreatePrepareDataForAdsRetrievalResponse()); }); EXPECT_CALL(*ad_retrieval_client_, ExecuteInternal) - .WillOnce( - [](std::unique_ptr raw_request, - const RequestMetadata& metadata, - absl::AnyInvocable< - void(absl::StatusOr>) &&> - on_done, - absl::Duration timeout) { - return absl::InternalError(kInternalServerError); - }); + .WillOnce([](std::unique_ptr raw_request, + const RequestMetadata& metadata, + absl::AnyInvocable>)&&> + on_done, + absl::Duration timeout) { + return absl::InternalError(kInternalServerError); + }); auto bidding_service = CreateBiddingService(); LocalServiceStartResult start_service_result = StartLocalService(&bidding_service); diff --git a/services/bidding_service/generate_bids_reactor.cc b/services/bidding_service/generate_bids_reactor.cc index 5444dc30..ecb66e57 100644 --- a/services/bidding_service/generate_bids_reactor.cc +++ b/services/bidding_service/generate_bids_reactor.cc @@ -218,15 +218,15 @@ absl::StatusOr SerializeTrustedBiddingSignalsPerIG( auto start_parse_time = absl::Now(); PS_ASSIGN_OR_RETURN((rapidjson::Document parsed_signals), ParseJsonString(raw_request.bidding_signals())); - PS_VLOG(2, log_context) << "\nTrusted Bidding Signals Deserialize Time: " - << ToInt64Microseconds( - (absl::Now() - start_parse_time)) - << " microseconds for " - << raw_request.bidding_signals().size() << " bytes."; + PS_VLOG(kStats, log_context) + << "\nTrusted Bidding Signals Deserialize Time: " + << ToInt64Microseconds((absl::Now() - start_parse_time)) + << " microseconds for " << raw_request.bidding_signals().size() + << " bytes."; // Select root key. if (!parsed_signals.HasMember("keys")) { - PS_VLOG(2, log_context) + PS_VLOG(kNoisyWarn, log_context) << "Trusted bidding signals JSON validate error (Missing property " "\"keys\")"; @@ -520,10 +520,10 @@ void GenerateBidsReactor::GenerateBidsCallback( const std::vector>& output) { if (server_common::log::PS_VLOG_IS_ON(2)) { for (const auto& dispatch_response : output) { - PS_VLOG(2, log_context_) + PS_VLOG(kDispatch, log_context_) << "Generate Bids V8 Response: " << dispatch_response.status(); if (dispatch_response.ok()) { - PS_VLOG(2, log_context_) << dispatch_response.value().resp; + PS_VLOG(kDispatch, log_context_) << dispatch_response.value().resp; } } } @@ -564,7 +564,7 @@ void GenerateBidsReactor::GenerateBidsCallback( current_all_debug_urls_chars); } if (!IsValidBid(bid)) { - PS_VLOG(2, log_context_) + PS_VLOG(kNoisyWarn, log_context_) << "Skipping 0 bid for " << interest_group_name << ": " << bid.DebugString(); } else if ( @@ -604,7 +604,7 @@ void GenerateBidsReactor::GenerateBidsCallback( LogIfError(metric_context_->LogHistogram( (static_cast(zero_bid_count)) / total_bid_count)); - PS_VLOG(kInfoMsg, log_context_) + PS_VLOG(kNoisyInfo, log_context_) << "\n\nFailed of total: " << failed_requests << "/" << output.size(); benchmarking_logger_->HandleResponseEnd(); } diff --git a/services/bidding_service/generate_bids_reactor_test_utils.cc b/services/bidding_service/generate_bids_reactor_test_utils.cc index c5950f8f..4b49a425 100644 --- a/services/bidding_service/generate_bids_reactor_test_utils.cc +++ b/services/bidding_service/generate_bids_reactor_test_utils.cc @@ -245,22 +245,21 @@ void SetupAdRetrievalClientExpectations( KVAsyncClientMock& ad_retrieval_client, absl::optional> ads_retrieval_response) { EXPECT_CALL(ad_retrieval_client, ExecuteInternal) - .WillOnce( - [&ads_retrieval_response]( - std::unique_ptr raw_request, - const RequestMetadata& metadata, - absl::AnyInvocable< - void(absl::StatusOr>) &&> - on_done, - absl::Duration timeout) { - auto response = ads_retrieval_response.has_value() - ? *ads_retrieval_response - : CreateAdsRetrievalOrKvLookupResponse(); - EXPECT_TRUE(response.ok()) << response.status(); - std::move(on_done)( - std::make_unique(*std::move(response))); - return absl::OkStatus(); - }); + .WillOnce([&ads_retrieval_response]( + std::unique_ptr raw_request, + const RequestMetadata& metadata, + absl::AnyInvocable>)&&> + on_done, + absl::Duration timeout) { + auto response = ads_retrieval_response.has_value() + ? *ads_retrieval_response + : CreateAdsRetrievalOrKvLookupResponse(); + EXPECT_TRUE(response.ok()) << response.status(); + std::move(on_done)( + std::make_unique(*std::move(response))); + return absl::OkStatus(); + }); } } // namespace privacy_sandbox::bidding_auction_servers diff --git a/services/bidding_service/inference/inference_utils.cc b/services/bidding_service/inference/inference_utils.cc index e7bc4ef8..3f3affc4 100644 --- a/services/bidding_service/inference/inference_utils.cc +++ b/services/bidding_service/inference/inference_utils.cc @@ -137,7 +137,7 @@ void RunInference(google::scp::roma::FunctionBindingPayload<>& wrapper) { std::unique_ptr stub = InferenceService::NewStub(InferenceChannel(executor)); - PS_VLOG(kInfoMsg) << "RunInference input: " << payload; + PS_VLOG(kNoisyInfo) << "RunInference input: " << payload; PredictRequest predict_request; predict_request.set_input(payload); diff --git a/services/bidding_service/protected_app_signals_generate_bids_reactor.cc b/services/bidding_service/protected_app_signals_generate_bids_reactor.cc index 9f2d6346..a93eb8c3 100644 --- a/services/bidding_service/protected_app_signals_generate_bids_reactor.cc +++ b/services/bidding_service/protected_app_signals_generate_bids_reactor.cc @@ -161,8 +161,8 @@ void ProtectedAppSignalsGenerateBidsReactor::FetchAds( [this, prepare_data_for_ads_retrieval_response]( KVLookUpResult ad_retrieval_result) { if (!ad_retrieval_result.ok()) { - PS_VLOG(2, log_context_) << "Ad retrieval request failed: " - << ad_retrieval_result.status(); + PS_VLOG(kNoisyWarn, log_context_) << "Ad retrieval request failed: " + << ad_retrieval_result.status(); EncryptResponseAndFinish(grpc::Status( grpc::INTERNAL, ad_retrieval_result.status().ToString())); return; @@ -174,7 +174,7 @@ void ProtectedAppSignalsGenerateBidsReactor::FetchAds( absl::Milliseconds(ad_bids_retrieval_timeout_ms_)); if (!status.ok()) { - PS_VLOG(2, log_context_) + PS_VLOG(kNoisyWarn, log_context_) << "Failed to execute ad retrieval request: " << status; EncryptResponseAndFinish(grpc::Status(grpc::INTERNAL, status.ToString())); } @@ -263,8 +263,9 @@ void ProtectedAppSignalsGenerateBidsReactor::OnFetchAdsDataDone( }, [this](const ProtectedAppSignalsAdWithBid& bid) { if (!IsValidBid(bid)) { - PS_VLOG(2, log_context_) << "Skipping protected app signals bid (" - << GetBidDebugInfo(bid) << ")"; + PS_VLOG(kNoisyWarn, log_context_) + << "Skipping protected app signals bid (" << GetBidDebugInfo(bid) + << ")"; } else { PS_VLOG(3, log_context_) << "Successful non-zero protected app signals bid received"; @@ -381,7 +382,7 @@ void ProtectedAppSignalsGenerateBidsReactor::FetchAdsMetadata( KVLookUpResult kv_look_up_result) { PS_VLOG(8) << "On KV response"; if (!kv_look_up_result.ok()) { - PS_VLOG(2, log_context_) + PS_VLOG(kNoisyWarn, log_context_) << "KV metadata request failed: " << kv_look_up_result.status(); EncryptResponseAndFinish(grpc::Status( grpc::INTERNAL, kv_look_up_result.status().ToString())); @@ -394,7 +395,7 @@ void ProtectedAppSignalsGenerateBidsReactor::FetchAdsMetadata( absl::Milliseconds(ad_bids_retrieval_timeout_ms_)); if (!status.ok()) { - PS_VLOG(2, log_context_) + PS_VLOG(kNoisyWarn, log_context_) << "Failed to execute ads metadata KV lookup request: " << status; EncryptResponseAndFinish(grpc::Status(grpc::INTERNAL, status.ToString())); } @@ -408,8 +409,8 @@ void ProtectedAppSignalsGenerateBidsReactor::StartContextualAdsRetrieval() { void ProtectedAppSignalsGenerateBidsReactor::Execute() { PS_VLOG(8, log_context_) << __func__; - PS_VLOG(2, log_context_) << "GenerateBidsRequest:\n" - << request_->DebugString(); + PS_VLOG(kEncrypted, log_context_) << "GenerateBidsRequest:\n" + << request_->ShortDebugString(); PS_VLOG(kPlain, log_context_) << "GenerateBidsRawRequest:\n" << raw_request_.ShortDebugString(); diff --git a/services/bidding_service/protected_app_signals_generate_bids_reactor.h b/services/bidding_service/protected_app_signals_generate_bids_reactor.h index 13245fd4..559afe56 100644 --- a/services/bidding_service/protected_app_signals_generate_bids_reactor.h +++ b/services/bidding_service/protected_app_signals_generate_bids_reactor.h @@ -112,7 +112,7 @@ class ProtectedAppSignalsGenerateBidsReactor on_successful_response = std::move(on_successful_response), requests]( const std::vector>& result) { if (auto status = ValidateRomaResponse(result); !status.ok()) { - PS_VLOG(2, log_context_) + PS_VLOG(kNoisyWarn, log_context_) << "Failed to run UDF: " << roma_entry_function << ". Error: " << status; EncryptResponseAndFinish( @@ -124,7 +124,7 @@ class ProtectedAppSignalsGenerateBidsReactor << ": " << result[0]->resp; auto parsed_response = std::move(parse_response)(result[0]->resp); if (!parsed_response.ok()) { - PS_VLOG(2, log_context_) + PS_VLOG(kNoisyWarn, log_context_) << "Failed to parse the response from: " << roma_entry_function << ". Error: " << parsed_response.status(); EncryptResponseAndFinish( @@ -140,8 +140,9 @@ class ProtectedAppSignalsGenerateBidsReactor }); if (!status.ok()) { - PS_VLOG(2, log_context_) << "Failed to execute " << roma_entry_function - << " in Roma. Error: " << status.ToString(); + PS_VLOG(kNoisyWarn, log_context_) + << "Failed to execute " << roma_entry_function + << " in Roma. Error: " << status.ToString(); EncryptResponseAndFinish( grpc::Status(grpc::StatusCode::INTERNAL, status.ToString())); } diff --git a/services/bidding_service/protected_app_signals_generate_bids_reactor_test.cc b/services/bidding_service/protected_app_signals_generate_bids_reactor_test.cc index 81e5dac5..fcdf92f1 100644 --- a/services/bidding_service/protected_app_signals_generate_bids_reactor_test.cc +++ b/services/bidding_service/protected_app_signals_generate_bids_reactor_test.cc @@ -114,19 +114,18 @@ TEST_F(GenerateBidsReactorTest, WinningBidIsGenerated) { SetupProtectedAppSignalsRomaExpectations(dispatcher_, num_roma_dispatches); EXPECT_CALL(ad_retrieval_client_, ExecuteInternal) - .WillOnce( - [](std::unique_ptr raw_request, - const RequestMetadata& metadata, - absl::AnyInvocable< - void(absl::StatusOr>) &&> - on_done, - absl::Duration timeout) { - auto response = CreateAdsRetrievalOrKvLookupResponse(); - EXPECT_TRUE(response.ok()) << response.status(); - std::move(on_done)( - std::make_unique(*std::move(response))); - return absl::OkStatus(); - }); + .WillOnce([](std::unique_ptr raw_request, + const RequestMetadata& metadata, + absl::AnyInvocable>)&&> + on_done, + absl::Duration timeout) { + auto response = CreateAdsRetrievalOrKvLookupResponse(); + EXPECT_TRUE(response.ok()) << response.status(); + std::move(on_done)( + std::make_unique(*std::move(response))); + return absl::OkStatus(); + }); auto raw_request = CreateRawProtectedAppSignalsRequest( kTestAuctionSignals, kTestBuyerSignals, @@ -151,16 +150,15 @@ TEST_F(GenerateBidsReactorTest, AdsRetrievalTimeoutIsUsed) { SetupProtectedAppSignalsRomaExpectations(dispatcher_, num_roma_dispatches); EXPECT_CALL(ad_retrieval_client_, ExecuteInternal) - .WillOnce( - [](std::unique_ptr raw_request, - const RequestMetadata& metadata, - absl::AnyInvocable< - void(absl::StatusOr>) &&> - on_done, - absl::Duration timeout) { - EXPECT_EQ(timeout, absl::Milliseconds(kTestAdRetrievalTimeoutMs)); - return absl::OkStatus(); - }); + .WillOnce([](std::unique_ptr raw_request, + const RequestMetadata& metadata, + absl::AnyInvocable>)&&> + on_done, + absl::Duration timeout) { + EXPECT_EQ(timeout, absl::Milliseconds(kTestAdRetrievalTimeoutMs)); + return absl::OkStatus(); + }); auto raw_request = CreateRawProtectedAppSignalsRequest( kTestAuctionSignals, kTestBuyerSignals, @@ -225,8 +223,8 @@ TEST_F(GenerateBidsReactorTest, AdRetrievalClientInputIsCorrect) { EXPECT_CALL(ad_retrieval_client_, ExecuteInternal) .WillOnce([](std::unique_ptr raw_request, const RequestMetadata& metadata, - absl::AnyInvocable>) &&> + absl::AnyInvocable>)&&> on_done, absl::Duration timeout) { EXPECT_EQ(raw_request->partitions().size(), 1); @@ -316,19 +314,18 @@ TEST_F(GenerateBidsReactorTest, GenerateBidsInputIsCorrect) { }); EXPECT_CALL(ad_retrieval_client_, ExecuteInternal) - .WillOnce( - [](std::unique_ptr raw_request, - const RequestMetadata& metadata, - absl::AnyInvocable< - void(absl::StatusOr>) &&> - on_done, - absl::Duration timeout) { - auto response = CreateAdsRetrievalOrKvLookupResponse(); - EXPECT_TRUE(response.ok()) << response.status(); - std::move(on_done)( - std::make_unique(*std::move(response))); - return absl::OkStatus(); - }); + .WillOnce([](std::unique_ptr raw_request, + const RequestMetadata& metadata, + absl::AnyInvocable>)&&> + on_done, + absl::Duration timeout) { + auto response = CreateAdsRetrievalOrKvLookupResponse(); + EXPECT_TRUE(response.ok()) << response.status(); + std::move(on_done)( + std::make_unique(*std::move(response))); + return absl::OkStatus(); + }); auto raw_request = CreateRawProtectedAppSignalsRequest( kTestAuctionSignals, kTestBuyerSignals, @@ -346,19 +343,18 @@ TEST_F(GenerateBidsReactorTest, egressPayloadAreNotPopulated) { SetupProtectedAppSignalsRomaExpectations(dispatcher_, num_roma_dispatches); EXPECT_CALL(ad_retrieval_client_, ExecuteInternal) - .WillOnce( - [](std::unique_ptr raw_request, - const RequestMetadata& metadata, - absl::AnyInvocable< - void(absl::StatusOr>) &&> - on_done, - absl::Duration timeout) { - auto response = CreateAdsRetrievalOrKvLookupResponse(); - EXPECT_TRUE(response.ok()) << response.status(); - std::move(on_done)( - std::make_unique(*std::move(response))); - return absl::OkStatus(); - }); + .WillOnce([](std::unique_ptr raw_request, + const RequestMetadata& metadata, + absl::AnyInvocable>)&&> + on_done, + absl::Duration timeout) { + auto response = CreateAdsRetrievalOrKvLookupResponse(); + EXPECT_TRUE(response.ok()) << response.status(); + std::move(on_done)( + std::make_unique(*std::move(response))); + return absl::OkStatus(); + }); auto raw_request = CreateRawProtectedAppSignalsRequest( kTestAuctionSignals, kTestBuyerSignals, @@ -405,19 +401,18 @@ TEST_F(GenerateBidsReactorTest, ZeroBidsAreFiltered) { }); EXPECT_CALL(ad_retrieval_client_, ExecuteInternal) - .WillOnce( - [](std::unique_ptr raw_request, - const RequestMetadata& metadata, - absl::AnyInvocable< - void(absl::StatusOr>) &&> - on_done, - absl::Duration timeout) { - auto response = CreateAdsRetrievalOrKvLookupResponse(); - EXPECT_TRUE(response.ok()) << response.status(); - std::move(on_done)( - std::make_unique(*std::move(response))); - return absl::OkStatus(); - }); + .WillOnce([](std::unique_ptr raw_request, + const RequestMetadata& metadata, + absl::AnyInvocable>)&&> + on_done, + absl::Duration timeout) { + auto response = CreateAdsRetrievalOrKvLookupResponse(); + EXPECT_TRUE(response.ok()) << response.status(); + std::move(on_done)( + std::make_unique(*std::move(response))); + return absl::OkStatus(); + }); auto raw_request = CreateRawProtectedAppSignalsRequest( kTestAuctionSignals, kTestBuyerSignals, @@ -452,19 +447,18 @@ TEST_F(GenerateBidsReactorTest, }); EXPECT_CALL(ad_retrieval_client_, ExecuteInternal) - .WillOnce( - [](std::unique_ptr raw_request, - const RequestMetadata& metadata, - absl::AnyInvocable< - void(absl::StatusOr>) &&> - on_done, - absl::Duration timeout) { - auto response = CreateAdsRetrievalOrKvLookupResponse(""); - EXPECT_TRUE(response.ok()) << response.status(); - std::move(on_done)( - std::make_unique(*std::move(response))); - return absl::OkStatus(); - }); + .WillOnce([](std::unique_ptr raw_request, + const RequestMetadata& metadata, + absl::AnyInvocable>)&&> + on_done, + absl::Duration timeout) { + auto response = CreateAdsRetrievalOrKvLookupResponse(""); + EXPECT_TRUE(response.ok()) << response.status(); + std::move(on_done)( + std::make_unique(*std::move(response))); + return absl::OkStatus(); + }); auto raw_request = CreateRawProtectedAppSignalsRequest( kTestAuctionSignals, kTestBuyerSignals, @@ -481,19 +475,18 @@ TEST_F(GenerateBidsReactorTest, NoContextualAdsMeansAdRetrievalServiceInvoked) { int num_roma_dispatches = 0; SetupProtectedAppSignalsRomaExpectations(dispatcher_, num_roma_dispatches); EXPECT_CALL(ad_retrieval_client_, ExecuteInternal) - .WillOnce( - [](std::unique_ptr raw_request, - const RequestMetadata& metadata, - absl::AnyInvocable< - void(absl::StatusOr>) &&> - on_done, - absl::Duration timeout) { - auto response = CreateAdsRetrievalOrKvLookupResponse(); - EXPECT_TRUE(response.ok()) << response.status(); - std::move(on_done)( - std::make_unique(*std::move(response))); - return absl::OkStatus(); - }); + .WillOnce([](std::unique_ptr raw_request, + const RequestMetadata& metadata, + absl::AnyInvocable>)&&> + on_done, + absl::Duration timeout) { + auto response = CreateAdsRetrievalOrKvLookupResponse(); + EXPECT_TRUE(response.ok()) << response.status(); + std::move(on_done)( + std::make_unique(*std::move(response))); + return absl::OkStatus(); + }); EXPECT_CALL(kv_async_client_, ExecuteInternal).Times(0); ContextualProtectedAppSignalsData contextual_pas_data; EXPECT_TRUE(contextual_pas_data.ad_render_ids().empty()); @@ -521,19 +514,18 @@ TEST_F(GenerateBidsReactorTest, ContextualAdsMeansKVServiceInvoked) { num_roma_dispatches); EXPECT_CALL(ad_retrieval_client_, ExecuteInternal).Times(0); EXPECT_CALL(kv_async_client_, ExecuteInternal) - .WillOnce( - [](std::unique_ptr raw_request, - const RequestMetadata& metadata, - absl::AnyInvocable< - void(absl::StatusOr>) &&> - on_done, - absl::Duration timeout) { - auto response = CreateAdsRetrievalOrKvLookupResponse(); - EXPECT_TRUE(response.ok()) << response.status(); - std::move(on_done)( - std::make_unique(*std::move(response))); - return absl::OkStatus(); - }); + .WillOnce([](std::unique_ptr raw_request, + const RequestMetadata& metadata, + absl::AnyInvocable>)&&> + on_done, + absl::Duration timeout) { + auto response = CreateAdsRetrievalOrKvLookupResponse(); + EXPECT_TRUE(response.ok()) << response.status(); + std::move(on_done)( + std::make_unique(*std::move(response))); + return absl::OkStatus(); + }); ContextualProtectedAppSignalsData contextual_pas_data; *contextual_pas_data.mutable_ad_render_ids()->Add() = kTestAdRenderId; auto raw_request = CreateRawProtectedAppSignalsRequest( @@ -558,29 +550,27 @@ TEST_F(GenerateBidsReactorTest, KvInputIsCorrect) { SetupContextualProtectedAppSignalsRomaExpectations(dispatcher_, num_roma_dispatches); EXPECT_CALL(kv_async_client_, ExecuteInternal) - .WillOnce( - [](std::unique_ptr raw_request, - const RequestMetadata& metadata, - absl::AnyInvocable< - void(absl::StatusOr>) &&> - on_done, - absl::Duration timeout) { - EXPECT_EQ(raw_request->partitions().size(), 1); - const auto& udf_arguments = - raw_request->partitions()[0].arguments(); - EXPECT_EQ(udf_arguments.size(), kNumKVLookupUdfArguments); - - const auto& ad_render_ids = - udf_arguments[kAdRenderIdsIndex].data().list_value().values(); - - EXPECT_EQ(ad_render_ids.size(), 1); - EXPECT_EQ(ad_render_ids[0].string_value(), kTestAdRenderId); - auto response = CreateAdsRetrievalOrKvLookupResponse(); - EXPECT_TRUE(response.ok()) << response.status(); - std::move(on_done)( - std::make_unique(*std::move(response))); - return absl::OkStatus(); - }); + .WillOnce([](std::unique_ptr raw_request, + const RequestMetadata& metadata, + absl::AnyInvocable>)&&> + on_done, + absl::Duration timeout) { + EXPECT_EQ(raw_request->partitions().size(), 1); + const auto& udf_arguments = raw_request->partitions()[0].arguments(); + EXPECT_EQ(udf_arguments.size(), kNumKVLookupUdfArguments); + + const auto& ad_render_ids = + udf_arguments[kAdRenderIdsIndex].data().list_value().values(); + + EXPECT_EQ(ad_render_ids.size(), 1); + EXPECT_EQ(ad_render_ids[0].string_value(), kTestAdRenderId); + auto response = CreateAdsRetrievalOrKvLookupResponse(); + EXPECT_TRUE(response.ok()) << response.status(); + std::move(on_done)( + std::make_unique(*std::move(response))); + return absl::OkStatus(); + }); ContextualProtectedAppSignalsData contextual_pas_data; *contextual_pas_data.mutable_ad_render_ids()->Add() = kTestAdRenderId; @@ -607,19 +597,18 @@ TEST_F(GenerateBidsReactorTest, TemporaryEgressVectorGetsPopulated) { SetupProtectedAppSignalsRomaExpectations(dispatcher_, num_roma_dispatches); EXPECT_CALL(ad_retrieval_client_, ExecuteInternal) - .WillOnce( - [](std::unique_ptr raw_request, - const RequestMetadata& metadata, - absl::AnyInvocable< - void(absl::StatusOr>) &&> - on_done, - absl::Duration timeout) { - auto response = CreateAdsRetrievalOrKvLookupResponse(); - EXPECT_TRUE(response.ok()) << response.status(); - std::move(on_done)( - std::make_unique(*std::move(response))); - return absl::OkStatus(); - }); + .WillOnce([](std::unique_ptr raw_request, + const RequestMetadata& metadata, + absl::AnyInvocable>)&&> + on_done, + absl::Duration timeout) { + auto response = CreateAdsRetrievalOrKvLookupResponse(); + EXPECT_TRUE(response.ok()) << response.status(); + std::move(on_done)( + std::make_unique(*std::move(response))); + return absl::OkStatus(); + }); auto raw_request = CreateRawProtectedAppSignalsRequest( kTestAuctionSignals, kTestBuyerSignals, @@ -647,19 +636,18 @@ TEST_F(GenerateBidsReactorTest, SetupProtectedAppSignalsRomaExpectations(dispatcher_, num_roma_dispatches); EXPECT_CALL(ad_retrieval_client_, ExecuteInternal) - .WillOnce( - [](std::unique_ptr raw_request, - const RequestMetadata& metadata, - absl::AnyInvocable< - void(absl::StatusOr>) &&> - on_done, - absl::Duration timeout) { - auto response = CreateAdsRetrievalOrKvLookupResponse(); - EXPECT_TRUE(response.ok()) << response.status(); - std::move(on_done)( - std::make_unique(*std::move(response))); - return absl::OkStatus(); - }); + .WillOnce([](std::unique_ptr raw_request, + const RequestMetadata& metadata, + absl::AnyInvocable>)&&> + on_done, + absl::Duration timeout) { + auto response = CreateAdsRetrievalOrKvLookupResponse(); + EXPECT_TRUE(response.ok()) << response.status(); + std::move(on_done)( + std::make_unique(*std::move(response))); + return absl::OkStatus(); + }); auto raw_request = CreateRawProtectedAppSignalsRequest( kTestAuctionSignals, kTestBuyerSignals, @@ -687,19 +675,18 @@ TEST_F(GenerateBidsReactorTest, SetupProtectedAppSignalsRomaExpectations(dispatcher_, num_roma_dispatches); EXPECT_CALL(ad_retrieval_client_, ExecuteInternal) - .WillOnce( - [](std::unique_ptr raw_request, - const RequestMetadata& metadata, - absl::AnyInvocable< - void(absl::StatusOr>) &&> - on_done, - absl::Duration timeout) { - auto response = CreateAdsRetrievalOrKvLookupResponse(); - EXPECT_TRUE(response.ok()) << response.status(); - std::move(on_done)( - std::make_unique(*std::move(response))); - return absl::OkStatus(); - }); + .WillOnce([](std::unique_ptr raw_request, + const RequestMetadata& metadata, + absl::AnyInvocable>)&&> + on_done, + absl::Duration timeout) { + auto response = CreateAdsRetrievalOrKvLookupResponse(); + EXPECT_TRUE(response.ok()) << response.status(); + std::move(on_done)( + std::make_unique(*std::move(response))); + return absl::OkStatus(); + }); auto raw_request = CreateRawProtectedAppSignalsRequest( kTestAuctionSignals, kTestBuyerSignals, diff --git a/services/bidding_service/runtime_flags.h b/services/bidding_service/runtime_flags.h index 783f281f..08080f05 100644 --- a/services/bidding_service/runtime_flags.h +++ b/services/bidding_service/runtime_flags.h @@ -24,22 +24,33 @@ namespace privacy_sandbox::bidding_auction_servers { // Define runtime flag names. -inline constexpr char PORT[] = "BIDDING_PORT"; -inline constexpr char HEALTHCHECK_PORT[] = "BIDDING_HEALTHCHECK_PORT"; -inline constexpr char ENABLE_BIDDING_SERVICE_BENCHMARK[] = +inline constexpr absl::string_view PORT = "BIDDING_PORT"; +inline constexpr absl::string_view HEALTHCHECK_PORT = + "BIDDING_HEALTHCHECK_PORT"; +inline constexpr absl::string_view ENABLE_BIDDING_SERVICE_BENCHMARK = "ENABLE_BIDDING_SERVICE_BENCHMARK"; -inline constexpr char BUYER_CODE_FETCH_CONFIG[] = "BUYER_CODE_FETCH_CONFIG"; -inline constexpr char JS_NUM_WORKERS[] = "JS_NUM_WORKERS"; -inline constexpr char JS_WORKER_QUEUE_LEN[] = "JS_WORKER_QUEUE_LEN"; -inline constexpr char TEE_AD_RETRIEVAL_KV_SERVER_ADDR[] = +inline constexpr absl::string_view BUYER_CODE_FETCH_CONFIG = + "BUYER_CODE_FETCH_CONFIG"; +inline constexpr absl::string_view JS_NUM_WORKERS = "JS_NUM_WORKERS"; +inline constexpr absl::string_view JS_WORKER_QUEUE_LEN = "JS_WORKER_QUEUE_LEN"; +inline constexpr absl::string_view TEE_AD_RETRIEVAL_KV_SERVER_ADDR = "TEE_AD_RETRIEVAL_KV_SERVER_ADDR"; -inline constexpr char TEE_KV_SERVER_ADDR[] = "TEE_KV_SERVER_ADDR"; -inline constexpr char AD_RETRIEVAL_TIMEOUT_MS[] = "AD_RETRIEVAL_TIMEOUT_MS"; -inline constexpr char AD_RETRIEVAL_KV_SERVER_EGRESS_TLS[] = +inline constexpr absl::string_view TEE_KV_SERVER_ADDR = "TEE_KV_SERVER_ADDR"; +inline constexpr absl::string_view AD_RETRIEVAL_TIMEOUT_MS = + "AD_RETRIEVAL_TIMEOUT_MS"; +inline constexpr absl::string_view AD_RETRIEVAL_KV_SERVER_EGRESS_TLS = "AD_RETRIEVAL_KV_SERVER_EGRESS_TLS"; -inline constexpr char KV_SERVER_EGRESS_TLS[] = "KV_SERVER_EGRESS_TLS"; +inline constexpr absl::string_view KV_SERVER_EGRESS_TLS = + "KV_SERVER_EGRESS_TLS"; +inline constexpr char + BIDDING_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND[] = + "BIDDING_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND"; +inline constexpr absl::string_view + BIDDING_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES = + "BIDDING_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES"; -inline constexpr absl::string_view kFlags[] = { +inline constexpr int kNumRuntimeFlags = 13; +inline constexpr std::array kFlags = { PORT, HEALTHCHECK_PORT, ENABLE_BIDDING_SERVICE_BENCHMARK, @@ -50,11 +61,14 @@ inline constexpr absl::string_view kFlags[] = { TEE_KV_SERVER_ADDR, AD_RETRIEVAL_KV_SERVER_EGRESS_TLS, KV_SERVER_EGRESS_TLS, - AD_RETRIEVAL_TIMEOUT_MS}; + AD_RETRIEVAL_TIMEOUT_MS, + BIDDING_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND, + BIDDING_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES, +}; inline std::vector GetServiceFlags() { - int size = sizeof(kFlags) / sizeof(kFlags[0]); - std::vector flags(kFlags, kFlags + size); + std::vector flags(kFlags.begin(), + kFlags.begin() + kNumRuntimeFlags); for (absl::string_view flag : kCommonServiceFlags) { flags.push_back(flag); diff --git a/services/buyer_frontend_service/BUILD b/services/buyer_frontend_service/BUILD index 56a2d05f..2f4f257f 100644 --- a/services/buyer_frontend_service/BUILD +++ b/services/buyer_frontend_service/BUILD @@ -109,6 +109,7 @@ cc_binary( "-Wl,-rpath,\\$$ORIGIN/../lib", ], local_defines = ENABLE_CORE_DUMPS_DEFINES, + malloc = "@com_google_tcmalloc//tcmalloc", visibility = ["//visibility:public"], deps = [ ":buyer_frontend_service", @@ -122,6 +123,7 @@ cc_binary( "//services/common/encryption:crypto_client_factory", "//services/common/encryption:key_fetcher_factory", "//services/common/telemetry:configure_telemetry", + "//services/common/util:tcmalloc_utils", "@aws_sdk_cpp//:core", "@com_github_grpc_grpc//:grpc++", "@com_github_grpc_grpc//:grpc++_reflection", # for grpc_cli diff --git a/services/buyer_frontend_service/buyer_frontend_main.cc b/services/buyer_frontend_service/buyer_frontend_main.cc index 469506ce..1e20d9ee 100644 --- a/services/buyer_frontend_service/buyer_frontend_main.cc +++ b/services/buyer_frontend_service/buyer_frontend_main.cc @@ -40,6 +40,7 @@ #include "services/common/encryption/crypto_client_factory.h" #include "services/common/encryption/key_fetcher_factory.h" #include "services/common/telemetry/configure_telemetry.h" +#include "services/common/util/tcmalloc_utils.h" #include "src/concurrent/event_engine_executor.h" #include "src/core/lib/event_engine/default_event_engine.h" #include "src/encryption/key_fetcher/key_fetcher_manager.h" @@ -84,6 +85,15 @@ ABSL_FLAG( bool, init_config_client, false, "Initialize config client to fetch any runtime flags not supplied from" " command line from cloud metadata store. False by default."); +ABSL_FLAG(std::optional, + bfe_tcmalloc_background_release_rate_bytes_per_second, std::nullopt, + "Amount of cached memory in bytes that is returned back to the " + "system per second"); +ABSL_FLAG(std::optional, bfe_tcmalloc_max_total_thread_cache_bytes, + std::nullopt, + "Maximum amount of cached memory in bytes across all threads (or " + "logical CPUs)"); + namespace privacy_sandbox::bidding_auction_servers { using ::google::scp::cpio::Cpio; @@ -148,6 +158,11 @@ absl::StatusOr GetConfigClient( config_client.SetFlag(FLAGS_enable_protected_audience, ENABLE_PROTECTED_AUDIENCE); config_client.SetFlag(FLAGS_ps_verbosity, PS_VERBOSITY); + config_client.SetFlag( + FLAGS_bfe_tcmalloc_background_release_rate_bytes_per_second, + BFE_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND); + config_client.SetFlag(FLAGS_bfe_tcmalloc_max_total_thread_cache_bytes, + BFE_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES); if (absl::GetFlag(FLAGS_init_config_client)) { PS_RETURN_IF_ERROR(config_client.Init(config_param_prefix)).LogError() @@ -180,6 +195,11 @@ absl::Status RunServer() { PS_ASSIGN_OR_RETURN(TrustedServersConfigClient config_client, GetConfigClient(config_util.GetConfigParameterPrefix())); + MaySetBackgroundReleaseRate(config_client.GetInt64Parameter( + BFE_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND)); + MaySetMaxTotalThreadCacheBytes(config_client.GetInt64Parameter( + BFE_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES)); + int port = config_client.GetIntParameter(PORT); std::string bidding_server_addr = std::string(config_client.GetStringParameter(BIDDING_SERVER_ADDR)); diff --git a/services/buyer_frontend_service/get_bids_unary_reactor.cc b/services/buyer_frontend_service/get_bids_unary_reactor.cc index b6dcc064..d10deb62 100644 --- a/services/buyer_frontend_service/get_bids_unary_reactor.cc +++ b/services/buyer_frontend_service/get_bids_unary_reactor.cc @@ -224,11 +224,11 @@ void GetBidsUnaryReactor::Execute() { benchmarking_logger_->Begin(); PS_VLOG(kEncrypted, log_context_) << "Encrypted GetBidsRequest:\n" << request_->ShortDebugString(); - PS_VLOG(2, log_context_) << "Headers:\n" - << absl::StrJoin(context_->client_metadata(), "\n", - absl::PairFormatter( - absl::StreamFormatter(), " : ", - absl::StreamFormatter())); + PS_VLOG(kPlain, log_context_) + << "Headers:\n" + << absl::StrJoin(context_->client_metadata(), "\n", + absl::PairFormatter(absl::StreamFormatter(), " : ", + absl::StreamFormatter())); if (!decrypt_status_.ok()) { PS_LOG(ERROR, log_context_) << "Decrypting the request failed:" @@ -419,8 +419,8 @@ void GetBidsUnaryReactor::PrepareAndGenerateProtectedAudienceBid( CreateGenerateBidsRawRequest(raw_request_, raw_request_.buyer_input(), std::move(bidding_signals), log_context); - PS_VLOG(2, log_context_) << "GenerateBidsRequest:\n" - << raw_bidding_input->ShortDebugString(); + PS_VLOG(kOriginated, log_context_) << "GenerateBidsRequest:\n" + << raw_bidding_input->ShortDebugString(); auto bidding_request = metric::MakeInitiatedRequest(metric::kBs, metric_context_.get()); bidding_request->SetRequestSize((int)raw_bidding_input->ByteSizeLong()); diff --git a/services/buyer_frontend_service/providers/http_bidding_signals_async_provider_test.cc b/services/buyer_frontend_service/providers/http_bidding_signals_async_provider_test.cc index c989fff8..2a798043 100644 --- a/services/buyer_frontend_service/providers/http_bidding_signals_async_provider_test.cc +++ b/services/buyer_frontend_service/providers/http_bidding_signals_async_provider_test.cc @@ -61,9 +61,8 @@ TEST(HttpBiddingSignalsAsyncProviderTest, MapsMissingClientTypeToUnknown) { [&request, ¬ification]( std::unique_ptr input, const RequestMetadata& metadata, - absl::AnyInvocable< - void( - absl::StatusOr>) &&> + absl::AnyInvocable>)&&> callback, absl::Duration timeout) { EXPECT_EQ(input->client_type, ClientType::CLIENT_TYPE_UNKNOWN); @@ -101,44 +100,47 @@ TEST(HttpBiddingSignalsAsyncProviderTest, MapsGetBidKeysToBuyerValuesInput) { An>) &&>>(), An())) - .WillOnce([&request, ¬ification]( - std::unique_ptr input, - const RequestMetadata& metadata, - absl::AnyInvocable>) &&> - callback, - absl::Duration timeout) { - // Check that keys received in input are from buyer_input - EXPECT_EQ(input->hostname, request.publisher_name()); - EXPECT_EQ(input->client_type, ClientType::CLIENT_TYPE_BROWSER); - - EXPECT_FALSE(request.has_buyer_kv_experiment_group_id()); - EXPECT_EQ(request.buyer_kv_experiment_group_id(), 0); - EXPECT_EQ(input->buyer_kv_experiment_group_id, ""); - - // Collect all expected keys - UrlKeysSet expected_keys; - UrlKeysSet expected_ig_names; - for (const auto& interest_group : - request.buyer_input().interest_groups()) { - expected_ig_names.emplace(interest_group.name()); - expected_keys.insert(interest_group.bidding_signals_keys().begin(), - interest_group.bidding_signals_keys().end()); - } - - // All expected keys in received keys and vice versa - std::vector keys_diff; - absl::c_set_difference(input->keys, expected_keys, - std::back_inserter(keys_diff)); - EXPECT_TRUE(keys_diff.empty()); - // All expected IG names in received names and vice versa - std::vector ig_names_diff; - absl::c_set_difference(input->interest_group_names, expected_ig_names, - std::back_inserter(ig_names_diff)); - EXPECT_TRUE(ig_names_diff.empty()); - notification.Notify(); - return absl::OkStatus(); - }); + .WillOnce( + [&request, ¬ification]( + std::unique_ptr input, + const RequestMetadata& metadata, + absl::AnyInvocable>)&&> + callback, + absl::Duration timeout) { + // Check that keys received in input are from buyer_input + EXPECT_EQ(input->hostname, request.publisher_name()); + EXPECT_EQ(input->client_type, ClientType::CLIENT_TYPE_BROWSER); + + EXPECT_FALSE(request.has_buyer_kv_experiment_group_id()); + EXPECT_EQ(request.buyer_kv_experiment_group_id(), 0); + EXPECT_EQ(input->buyer_kv_experiment_group_id, ""); + + // Collect all expected keys + UrlKeysSet expected_keys; + UrlKeysSet expected_ig_names; + for (const auto& interest_group : + request.buyer_input().interest_groups()) { + expected_ig_names.emplace(interest_group.name()); + expected_keys.insert( + interest_group.bidding_signals_keys().begin(), + interest_group.bidding_signals_keys().end()); + } + + // All expected keys in received keys and vice versa + std::vector keys_diff; + absl::c_set_difference(input->keys, expected_keys, + std::back_inserter(keys_diff)); + EXPECT_TRUE(keys_diff.empty()); + // All expected IG names in received names and vice versa + std::vector ig_names_diff; + absl::c_set_difference(input->interest_group_names, + expected_ig_names, + std::back_inserter(ig_names_diff)); + EXPECT_TRUE(ig_names_diff.empty()); + notification.Notify(); + return absl::OkStatus(); + }); HttpBiddingSignalsAsyncProvider class_under_test(std::move(mock_client)); @@ -164,16 +166,15 @@ TEST(HttpBiddingSignalsAsyncProviderTest, MapsBuyerValuesAsyncClientError) { An>) &&>>(), An())) - .WillOnce( - [](std::unique_ptr input, - const RequestMetadata& metadata, - absl::AnyInvocable< - void(absl::StatusOr>) &&> - callback, - absl::Duration timeout) { - (std::move(callback))(absl::InternalError("")); - return absl::OkStatus(); - }); + .WillOnce([](std::unique_ptr input, + const RequestMetadata& metadata, + absl::AnyInvocable>)&&> + callback, + absl::Duration timeout) { + (std::move(callback))(absl::InternalError("")); + return absl::OkStatus(); + }); HttpBiddingSignalsAsyncProvider class_under_test(std::move(mock_client)); @@ -210,9 +211,8 @@ TEST(HttpBiddingSignalsAsyncProviderTest, [&expected_output]( std::unique_ptr input, const RequestMetadata& metadata, - absl::AnyInvocable< - void( - absl::StatusOr>) &&> + absl::AnyInvocable>)&&> callback, absl::Duration timeout) { auto output = std::make_unique(); diff --git a/services/buyer_frontend_service/runtime_flags.h b/services/buyer_frontend_service/runtime_flags.h index aff6e484..d29ff736 100644 --- a/services/buyer_frontend_service/runtime_flags.h +++ b/services/buyer_frontend_service/runtime_flags.h @@ -23,26 +23,37 @@ namespace privacy_sandbox::bidding_auction_servers { // Define runtime flag names. -inline constexpr char PORT[] = "BUYER_FRONTEND_PORT"; -inline constexpr char HEALTHCHECK_PORT[] = "BUYER_FRONTEND_HEALTHCHECK_PORT"; -inline constexpr char BIDDING_SERVER_ADDR[] = "BIDDING_SERVER_ADDR"; -inline constexpr char BUYER_KV_SERVER_ADDR[] = "BUYER_KV_SERVER_ADDR"; -inline constexpr char GENERATE_BID_TIMEOUT_MS[] = "GENERATE_BID_TIMEOUT_MS"; -inline constexpr char PROTECTED_APP_SIGNALS_GENERATE_BID_TIMEOUT_MS[] = - "PROTECTED_APP_SIGNALS_GENERATE_BID_TIMEOUT_MS"; -inline constexpr char BIDDING_SIGNALS_LOAD_TIMEOUT_MS[] = +inline constexpr absl::string_view PORT = "BUYER_FRONTEND_PORT"; +inline constexpr absl::string_view HEALTHCHECK_PORT = + "BUYER_FRONTEND_HEALTHCHECK_PORT"; +inline constexpr absl::string_view BIDDING_SERVER_ADDR = "BIDDING_SERVER_ADDR"; +inline constexpr absl::string_view BUYER_KV_SERVER_ADDR = + "BUYER_KV_SERVER_ADDR"; +inline constexpr absl::string_view GENERATE_BID_TIMEOUT_MS = + "GENERATE_BID_TIMEOUT_MS"; +inline constexpr absl::string_view + PROTECTED_APP_SIGNALS_GENERATE_BID_TIMEOUT_MS = + "PROTECTED_APP_SIGNALS_GENERATE_BID_TIMEOUT_MS"; +inline constexpr absl::string_view BIDDING_SIGNALS_LOAD_TIMEOUT_MS = "BIDDING_SIGNALS_LOAD_TIMEOUT_MS"; -inline constexpr char ENABLE_BUYER_FRONTEND_BENCHMARKING[] = +inline constexpr absl::string_view ENABLE_BUYER_FRONTEND_BENCHMARKING = "ENABLE_BUYER_FRONTEND_BENCHMARKING"; -inline constexpr char CREATE_NEW_EVENT_ENGINE[] = "CREATE_NEW_EVENT_ENGINE"; -inline constexpr char ENABLE_BIDDING_COMPRESSION[] = +inline constexpr absl::string_view CREATE_NEW_EVENT_ENGINE = + "CREATE_NEW_EVENT_ENGINE"; +inline constexpr absl::string_view ENABLE_BIDDING_COMPRESSION = "ENABLE_BIDDING_COMPRESSION"; -inline constexpr char BFE_INGRESS_TLS[] = "BFE_INGRESS_TLS"; -inline constexpr char BFE_TLS_KEY[] = "BFE_TLS_KEY"; -inline constexpr char BFE_TLS_CERT[] = "BFE_TLS_CERT"; -inline constexpr char BIDDING_EGRESS_TLS[] = "BIDDING_EGRESS_TLS"; +inline constexpr absl::string_view BFE_INGRESS_TLS = "BFE_INGRESS_TLS"; +inline constexpr absl::string_view BFE_TLS_KEY = "BFE_TLS_KEY"; +inline constexpr absl::string_view BFE_TLS_CERT = "BFE_TLS_CERT"; +inline constexpr absl::string_view BIDDING_EGRESS_TLS = "BIDDING_EGRESS_TLS"; +inline constexpr absl::string_view + BFE_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND = + "BFE_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND"; +inline constexpr absl::string_view BFE_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES = + "BFE_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES"; -inline constexpr absl::string_view kFlags[] = { +inline constexpr int kNumRuntimeFlags = 16; +inline constexpr std::array kFlags = { PORT, HEALTHCHECK_PORT, BIDDING_SERVER_ADDR, @@ -57,11 +68,13 @@ inline constexpr absl::string_view kFlags[] = { BFE_TLS_KEY, BFE_TLS_CERT, BIDDING_EGRESS_TLS, + BFE_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND, + BFE_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES, }; inline std::vector GetServiceFlags() { - int size = sizeof(kFlags) / sizeof(kFlags[0]); - std::vector flags(kFlags, kFlags + size); + std::vector flags(kFlags.begin(), + kFlags.begin() + kNumRuntimeFlags); for (absl::string_view flag : kCommonServiceFlags) { flags.push_back(flag); diff --git a/services/buyer_frontend_service/util/buyer_frontend_test_utils.cc b/services/buyer_frontend_service/util/buyer_frontend_test_utils.cc index dd3c8869..fa5e633b 100644 --- a/services/buyer_frontend_service/util/buyer_frontend_test_utils.cc +++ b/services/buyer_frontend_service/util/buyer_frontend_test_utils.cc @@ -48,9 +48,8 @@ void SetupBiddingProviderMock( auto MockBiddingSignalsProvider = [bidding_signals_value, server_error_to_return]( const BiddingSignalsRequest& bidding_signals_request, - absl::AnyInvocable< - void(absl::StatusOr>, - GetByteSize) &&> + absl::AnyInvocable>, GetByteSize)&&> on_done, absl::Duration timeout) { GetByteSize get_byte_size; diff --git a/services/common/clients/client_params.h b/services/common/clients/client_params.h index 06771278..04b73635 100644 --- a/services/common/clients/client_params.h +++ b/services/common/clients/client_params.h @@ -102,7 +102,7 @@ class ClientParams { std::unique_ptr response_; // callback will only run once for a single gRPC call - absl::AnyInvocable>)&&> + absl::AnyInvocable>) &&> callback_ = nullptr; }; @@ -170,7 +170,7 @@ class RawClientParams { std::unique_ptr raw_response_; // callback will only run once for a single gRPC call - absl::AnyInvocable>)&&> + absl::AnyInvocable>) &&> raw_callback_ = nullptr; }; diff --git a/services/common/clients/client_params_test.cc b/services/common/clients/client_params_test.cc index 15af2020..4fcaccaa 100644 --- a/services/common/clients/client_params_test.cc +++ b/services/common/clients/client_params_test.cc @@ -37,7 +37,7 @@ class MockResponse { TEST(ClientParamsTest, RequestRefProvidesRequestObject) { std::unique_ptr input_request = std::make_unique(); int input_int = input_request->req_int; - absl::AnyInvocable>)&&> + absl::AnyInvocable>) &&> callback = [](absl::StatusOr> response) {}; ClientParams class_under_test( @@ -49,7 +49,7 @@ TEST(ClientParamsTest, RequestRefProvidesRequestObject) { TEST(ClientParamsTest, ResponseRefProvidesNonNullResponseObject) { std::unique_ptr input_request = std::make_unique(); - absl::AnyInvocable>)&&> + absl::AnyInvocable>) &&> callback = [](absl::StatusOr> response) {}; ClientParams class_under_test( @@ -61,7 +61,7 @@ TEST(ClientParamsTest, ResponseRefProvidesNonNullResponseObject) { TEST(ClientParamsTest, ContextRefProvidesNonNullContextObject) { std::unique_ptr input_request = std::make_unique(); - absl::AnyInvocable>)&&> + absl::AnyInvocable>) &&> callback = [](absl::StatusOr> response) {}; ClientParams class_under_test( @@ -73,7 +73,7 @@ TEST(ClientParamsTest, ContextRefProvidesNonNullContextObject) { TEST(ClientParamsTest, SetDeadlineSetsDeadlineValueInContext) { std::unique_ptr input_request = std::make_unique(); - absl::AnyInvocable>)&&> + absl::AnyInvocable>) &&> callback = [](absl::StatusOr> response) {}; absl::Duration timeout = absl::Microseconds(MakeARandomInt(1, 999)); auto expected_timeout = absl::Now() + timeout; @@ -93,7 +93,7 @@ TEST(ClientParamsTest, SetDeadlineSetsDeadlineValueInContext) { TEST(ClientParamsTest, OnDoneExecutesCallback) { std::unique_ptr input_request = std::make_unique(); int output_value = MakeARandomInt(INT16_MIN, INT16_MAX - 1); - absl::AnyInvocable>)&&> + absl::AnyInvocable>) &&> callback = [&output_value]( absl::StatusOr> response) { ASSERT_TRUE(response.ok()); @@ -111,7 +111,7 @@ TEST(ClientParamsTest, OnDoneExecutesCallback) { TEST(ClientParamsTest, OnDoneDeletesInstance) { std::unique_ptr input_request = std::make_unique(); - absl::AnyInvocable>)&&> + absl::AnyInvocable>) &&> callback = [](absl::StatusOr> response) {}; auto class_under_test = new ClientParams( @@ -126,7 +126,7 @@ TEST(ClientParamsTest, ReceivesMetadataObject) { std::unique_ptr input_request = std::make_unique(); absl::flat_hash_map metadata = MakeARandomMap(); - absl::AnyInvocable>)&&> + absl::AnyInvocable>) &&> callback = [](absl::StatusOr> response) {}; // Cannot test the values get set in the client context here because diff --git a/services/common/clients/config/trusted_server_config_client.cc b/services/common/clients/config/trusted_server_config_client.cc index dbc4f38c..9984b1ff 100644 --- a/services/common/clients/config/trusted_server_config_client.cc +++ b/services/common/clients/config/trusted_server_config_client.cc @@ -132,6 +132,12 @@ int TrustedServersConfigClient::GetIntParameter( return std::stoi(config_entries_map_.at(name)); } +int64_t TrustedServersConfigClient::GetInt64Parameter( + absl::string_view name) const noexcept { + DCHECK(HasParameter(name)) << "Flag " << name << " not found"; + return std::stol(config_entries_map_.at(name)); +} + absl::Status TrustedServersConfigClient::InitAndRunConfigClient() noexcept { PS_RETURN_IF_ERROR(config_client_->Init()).SetPrepend() << "Cannot init config client: "; diff --git a/services/common/clients/config/trusted_server_config_client.h b/services/common/clients/config/trusted_server_config_client.h index 725180af..62c7566d 100644 --- a/services/common/clients/config/trusted_server_config_client.h +++ b/services/common/clients/config/trusted_server_config_client.h @@ -81,6 +81,9 @@ class TrustedServersConfigClient { // Fetches the int value for the specified config parameter. int GetIntParameter(absl::string_view name) const noexcept; + // Fetches the int64 value for the specified config parameter. + int64_t GetInt64Parameter(absl::string_view name) const noexcept; + // Fetches custom flag value for the specified config parameter. template T GetCustomParameter(absl::string_view name) const noexcept { diff --git a/services/common/clients/http/BUILD b/services/common/clients/http/BUILD index 28eee87e..1ba1a403 100644 --- a/services/common/clients/http/BUILD +++ b/services/common/clients/http/BUILD @@ -42,12 +42,14 @@ cc_library( ], deps = [ "@com_google_absl//absl/container:flat_hash_map", + "@com_google_absl//absl/log:check", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/time", "@curl", "@google_privacysandbox_servers_common//src/concurrent:executor", "@google_privacysandbox_servers_common//src/logger:request_context_logger", + "@libevent//:event", ], ) @@ -67,6 +69,7 @@ cc_test( "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", "@google_privacysandbox_servers_common//src/concurrent:executor", + "@google_privacysandbox_servers_common//src/logger:request_context_logger", "@rapidjson", ], ) diff --git a/services/common/clients/http/multi_curl_http_fetcher_async.cc b/services/common/clients/http/multi_curl_http_fetcher_async.cc index 0e80fc4c..f71230cc 100644 --- a/services/common/clients/http/multi_curl_http_fetcher_async.cc +++ b/services/common/clients/http/multi_curl_http_fetcher_async.cc @@ -15,6 +15,7 @@ #include "services/common/clients/http/multi_curl_http_fetcher_async.h" #include +#include #include #include @@ -23,6 +24,7 @@ #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/time/time.h" +#include "event2/thread.h" #include "src/logger/request_context_logger.h" namespace privacy_sandbox::bidding_auction_servers { @@ -44,6 +46,7 @@ struct CurlTimeStats { curl_off_t download_speed = -1; curl_off_t upload_speed = -1; curl_off_t new_conns = -1; + curl_off_t queue_time_us = -1; }; void GetTraceFromCurl(CURL* handle) { if (server_common::log::PS_VLOG_IS_ON(log_level)) { @@ -74,6 +77,8 @@ void GetTraceFromCurl(CURL* handle) { &curl_time_stats.upload_speed); curl_easy_getinfo(handle, CURLINFO_NUM_CONNECTS, &curl_time_stats.new_conns); + curl_easy_getinfo(handle, CURLINFO_QUEUE_TIME_T, + &curl_time_stats.queue_time_us); PS_VLOG(log_level) << "Curl request " << absl::StrCat(request_url) << " stats: \n" @@ -90,20 +95,91 @@ void GetTraceFromCurl(CURL* handle) { << " bytes/second\n" << "upload_speed: " << curl_time_stats.upload_speed << " bytes/second\n" - << "new_conns: " << curl_time_stats.new_conns << "\n"; + << "new_conns: " << curl_time_stats.new_conns << "\n" + << "queue duration: " + << absl::ToDoubleMilliseconds( + absl::Microseconds(curl_time_stats.queue_time_us)) + << " ms\n"; } } } // namespace +EventBase::EventBase(int num_priorities) { + evthread_use_pthreads(); + event_base_ = event_base_new(); + event_base_priority_init(event_base_, num_priorities); + if (server_common::log::PS_VLOG_IS_ON(10)) { + event_enable_debug_mode(); + } +} + +EventBase::~EventBase() { + if (event_base_ != nullptr) { + event_base_free(event_base_); + } +} + +struct event_base* EventBase::get() { return event_base_; } + +Event::Event(struct event_base* base, evutil_socket_t fd, short event_type, + EventCallback event_callback, void* arg, int priority, + struct timeval* event_timeout) + : priority_(priority), + event_(event_new(base, fd, event_type, event_callback, arg)) { + event_priority_set(event_, priority_); + event_add(event_, event_timeout); +} + +struct event* Event::get() { return event_; } +Event::~Event() { + if (event_) { + event_del(event_); + event_free(event_); + } +} + +static struct timeval OneSecond = {1, 0}; + MultiCurlHttpFetcherAsync::MultiCurlHttpFetcherAsync( server_common::Executor* executor, int64_t keepalive_interval_sec, int64_t keepalive_idle_sec) : executor_(executor), keepalive_idle_sec_(keepalive_idle_sec), - keepalive_interval_sec_(keepalive_interval_sec) { + keepalive_interval_sec_(keepalive_interval_sec), + // Shutdown timer event is persistent because we don't want to remove + // it from the event loop the first time it fires. With this timer, we + // periodically check for fetcher shutdown and terminate the event loop + // if fetcher has been shutdown. + shutdown_timer_event_(Event(event_base_.get(), /*fd=*/-1, + /*event_type=*/EV_PERSIST, + /*event_callback=*/ShutdownEventLoop, + /*arg=*/this, + /*priority=*/0, &OneSecond)), + multi_curl_request_manager_(event_base_.get()), + multi_timer_event_(Event( + event_base_.get(), /*fd=*/-1, /*event_type=*/0, + /*event_callback=*/multi_curl_request_manager_.MultiTimerCallback, + /*arg=*/&multi_curl_request_manager_)) { + multi_curl_request_manager_.Configure([this]() { PerformCurlUpdate(); }, + multi_timer_event_.get()); // Start execution loop. - executor_->Run([this]() { ExecuteLoop(); }); + executor_->Run([this]() { + PS_VLOG(5) << "libevent scheduled the event loop"; + event_base_dispatch(event_base_.get()); + }); +} + +void MultiCurlHttpFetcherAsync::ShutdownEventLoop(int fd, short event_type, + void* arg) { + auto* self = reinterpret_cast(arg); + if (!self->shutdown_requested_.HasBeenNotified()) { + return; + } + + PS_VLOG(5) << "Shutting down the event loop"; + event_base_loopbreak(self->event_base_.get()); + self->shutdown_complete_.Notify(); } MultiCurlHttpFetcherAsync::~MultiCurlHttpFetcherAsync() @@ -114,8 +190,7 @@ MultiCurlHttpFetcherAsync::~MultiCurlHttpFetcherAsync() // We ensure that no other thread will lock callback_map_lock_ and in_loop_mu_ // here since no new requests are being accepted, or processed through // the execution loop. - absl::MutexLock l1(&in_loop_mu_); - absl::MutexLock l2(&curl_handle_set_lock_); + absl::MutexLock lock(&curl_handle_set_lock_); // Execute all callbacks and clean up handles for (auto& handle : curl_handle_set_) { @@ -316,18 +391,6 @@ void MultiCurlHttpFetcherAsync::PutUrl(const HTTPRequest& http_request, ExecuteCurlRequest(std::move(request)); } -void MultiCurlHttpFetcherAsync::ExecuteLoop() ABSL_LOCKS_EXCLUDED(in_loop_mu_) { - if (in_loop_mu_.TryLock()) { - while (!shutdown_requested_.HasBeenNotified()) { - PerformCurlUpdate(); - } - // Shut down has been requested so exit. - shutdown_complete_.Notify(); - in_loop_mu_.Unlock(); - } - // Another ExecuteLoop is already running. -} - std::pair MultiCurlHttpFetcherAsync::GetResultFromMsg( CURLMsg* msg) { void* output; @@ -370,11 +433,11 @@ std::pair MultiCurlHttpFetcherAsync::GetResultFromMsg( } void MultiCurlHttpFetcherAsync::PerformCurlUpdate() - ABSL_EXCLUSIVE_LOCKS_REQUIRED(in_loop_mu_) - ABSL_LOCKS_EXCLUDED(curl_handle_set_lock_) { + ABSL_LOCKS_EXCLUDED(curl_handle_set_lock_) { // Check for updates (provide computation for Libcurl to perform I/O). int msgs_left = -1; while (CURLMsg* msg = multi_curl_request_manager_.GetUpdate(&msgs_left)) { + PS_VLOG(10) << __func__ << ": A curl handle completed transfer"; // Get data for completed message. auto [status, data_ptr] = GetResultFromMsg(msg); multi_curl_request_manager_.Remove(msg->easy_handle); @@ -397,6 +460,7 @@ void MultiCurlHttpFetcherAsync::PerformCurlUpdate() static_cast(data_ptr)); // invoke callback for handle. if (status.ok()) { + PS_VLOG(10) << "Invoking callback for successful curl operation"; std::move(curl_request_data_ptr->done_callback)( *curl_request_data_ptr->output); } else { diff --git a/services/common/clients/http/multi_curl_http_fetcher_async.h b/services/common/clients/http/multi_curl_http_fetcher_async.h index 2077c552..fad37629 100644 --- a/services/common/clients/http/multi_curl_http_fetcher_async.h +++ b/services/common/clients/http/multi_curl_http_fetcher_async.h @@ -21,6 +21,7 @@ #include #include +#include #include #include "absl/container/flat_hash_set.h" @@ -40,6 +41,46 @@ struct DataToUpload { int offset = 0; }; +// Libevent uses default priority as half of the number of priorities. +// We needed 2 priorities to begin with (high and default) but configured 3 +// here for future use if we have to configure a low priority event. +inline constexpr int kNumEventPriorities = 3; + +// Wrapper for the libevent structure to hold information and state for a +// libevent dispatch loop. +class EventBase { + public: + explicit EventBase(int num_priorities = kNumEventPriorities); + virtual ~EventBase(); + + // Gets the underlying event base data type. + struct event_base* get(); + + private: + struct event_base* event_base_ = nullptr; +}; + +// Arguments are documented here: +// https://libevent.org/doc/event_8h.html#aed2307f3d9b38e07cc10c2607322d758 +using EventCallback = void (*)(/*fd or signal=*/int, /*events=*/short, + /*pointer to user provided data=*/void*); + +// Wraps the event used by libevent. This wrapper makes it easier to manage +// lifecycle of the underlying event. +class Event { + public: + explicit Event(struct event_base* base, evutil_socket_t fd, short event_type, + EventCallback event_callback, void* arg, + int priority = kNumEventPriorities / 2, + struct timeval* event_timeout = nullptr); + struct event* get(); + virtual ~Event(); + + private: + int priority_; + struct event* event_ = nullptr; +}; + // MultiCurlHttpFetcherAsync provides a thread-safe libcurl wrapper to perform // asynchronous HTTP invocations with client caching(connection pooling), and // TLS session sharing. It uses a single curl multi handle to perform @@ -165,8 +206,11 @@ class MultiCurlHttpFetcherAsync final : public HttpFetcherAsync { // available, it schedules the callback on the executor_. // Only a single thread can execute this function at a time since it requires // the acquisition of the in_loop_mu_ mutex. - void PerformCurlUpdate() ABSL_EXCLUSIVE_LOCKS_REQUIRED(in_loop_mu_) - ABSL_LOCKS_EXCLUDED(curl_handle_set_lock_); + void PerformCurlUpdate() ABSL_LOCKS_EXCLUDED(curl_handle_set_lock_); + + // Shuts down the event loop. This is a callback registered with an event + // that fires every second to see if the event loop should be shutdown. + static void ShutdownEventLoop(int fd, short event_type, void* arg); // Parses curl message to result string or an error message for the callback. std::pair GetResultFromMsg(CURLMsg* msg); @@ -193,8 +237,18 @@ class MultiCurlHttpFetcherAsync final : public HttpFetcherAsync { // Interval time between keep-alive probes in case of no response. int64_t keepalive_interval_sec_; + // All events in the loop are associated with this event base. Note: There can + // be a single event base for a single thread. + // Documentation: https://libevent.org/libevent-book/Ref2_eventbase.html + EventBase event_base_; + // This event is registered with the event loop and fires every second to + // check if the fetcher has been stopped and if so, the callback registered + // for this event will also stop the event loop. + Event shutdown_timer_event_; + // The multi session used for performing HTTP calls. MultiCurlRequestManager multi_curl_request_manager_; + Event multi_timer_event_; // Controlled by multi libcurl stack. // Makes sure only one execution loop runs at a time. absl::Mutex in_loop_mu_; diff --git a/services/common/clients/http/multi_curl_http_fetcher_async_test.cc b/services/common/clients/http/multi_curl_http_fetcher_async_test.cc index 2badab6d..4571bcd9 100644 --- a/services/common/clients/http/multi_curl_http_fetcher_async_test.cc +++ b/services/common/clients/http/multi_curl_http_fetcher_async_test.cc @@ -27,6 +27,7 @@ #include "include/gmock/gmock.h" #include "include/gtest/gtest.h" #include "rapidjson/document.h" +#include "src/logger/request_context_logger.h" namespace privacy_sandbox::bidding_auction_servers { namespace { @@ -41,6 +42,7 @@ constexpr int kNormalTimeoutMs = 5000; class MultiCurlHttpFetcherAsyncTest : public ::testing::Test { protected: MultiCurlHttpFetcherAsyncTest() { + server_common::log::PS_VLOG_IS_ON(0, 10); executor_ = std::make_unique( grpc_event_engine::experimental::CreateEventEngine()); fetcher_ = std::make_unique(executor_.get()); diff --git a/services/common/clients/http/multi_curl_request_manager.cc b/services/common/clients/http/multi_curl_request_manager.cc index e991cc9d..f9244198 100644 --- a/services/common/clients/http/multi_curl_request_manager.cc +++ b/services/common/clients/http/multi_curl_request_manager.cc @@ -14,12 +14,135 @@ #include "services/common/clients/http/multi_curl_request_manager.h" +#include +#include +#include +#include + +#include +#include + +#include "absl/log/check.h" +#include "src/logger/request_context_logger.h" + namespace privacy_sandbox::bidding_auction_servers { -MultiCurlRequestManager::MultiCurlRequestManager() { +namespace { + +using EventCallback = void (*)(int, short, void*); + +std::string GetLogSocketActivityType(int what) { + static std::vector ret = {"none", "IN", "OUT", "INOUT", + "REMOVE"}; + return ret[what]; +} + +} // namespace + +void RemoveSocketFromLibevent(std::unique_ptr socket_info) { + PS_VLOG(10) << __func__ + << "Removing socket and cleaning associated socket info"; + if (!socket_info) return; + + if (event_initialized(&socket_info->tracked_event)) { + // Make the event non-pending and non-active i.e. + // remove the registered event from the libevent's monitoring. + event_del(&socket_info->tracked_event); + } +} + +void MultiCurlRequestManager::OnLibeventSocketActivity(int fd, short kind, + void* data) { + PS_VLOG(8) << __func__; + int action = ((kind & EV_READ) ? CURL_CSELECT_IN : 0) | + ((kind & EV_WRITE) ? CURL_CSELECT_OUT : 0); + + auto* self = reinterpret_cast(data); + { + absl::MutexLock l(&self->request_manager_mu_); + curl_multi_socket_action(self->request_manager_, fd, action, + &self->running_handles_); + } + self->update_easy_handles_callback_(); +} + +void MultiCurlRequestManager::UpsertSocketInLibevent(curl_socket_t sock_fd, + int activity, + SocketInfo* socket_info) { + PS_VLOG(8) << __func__ << ": Relaying insert/update socket event to libevent"; + int kind = ((activity & CURL_POLL_IN) ? EV_READ : 0) | + ((activity & CURL_POLL_OUT) ? EV_WRITE : 0) | EV_PERSIST; + + socket_info->sock_fd = sock_fd; + socket_info->activity = activity; + + if (event_initialized(&socket_info->tracked_event)) { + event_del(&socket_info->tracked_event); + } + + event_assign(&socket_info->tracked_event, event_base_, sock_fd, kind, + OnLibeventSocketActivity, this); + event_add(&socket_info->tracked_event, /*timeout=*/nullptr); +} + +void MultiCurlRequestManager::AddSocketToLibevent(curl_socket_t sock, + int activity, void* data) { + PS_VLOG(8) << __func__ << ": Adding new socket event to libevent"; + + auto socket_info = std::make_unique(); + auto* self = reinterpret_cast(data); + self->UpsertSocketInLibevent(sock, activity, socket_info.get()); + curl_multi_assign(self->request_manager_, sock, socket_info.release()); +} + +int MultiCurlRequestManager::OnLibcurlSocketUpdate(CURL* easy_handle, + curl_socket_t sock_fd, + int activity, void* data, + void* socket_info_pointer) { + PS_VLOG(10) << __func__ << ": sock_fd=" << sock_fd + << ", easy_handle=" << easy_handle + << ", activity=" << GetLogSocketActivityType(activity); + + struct SocketInfo* socket_info = + reinterpret_cast(socket_info_pointer); + auto* self = reinterpret_cast(data); + // See activity details here: + // https://curl.se/libcurl/c/CURLMOPT_SOCKETFUNCTION.html + if (activity == CURL_POLL_REMOVE) { + RemoveSocketFromLibevent(std::unique_ptr(socket_info)); + } else if (!socket_info) { + self->AddSocketToLibevent(sock_fd, activity, data); + } else { + self->UpsertSocketInLibevent(sock_fd, activity, socket_info); + } + return 0; +} + +int OnLibcurlTimerUpdate(CURLM* multi, long timeout_ms, void* timer_event_arg) { + PS_VLOG(10) << __func__ << ": New Timeout value (ms): " << timeout_ms; + DCHECK_NE(timer_event_arg, nullptr) << "Timer event not found"; + struct event* timer_event = reinterpret_cast(timer_event_arg); + if (timeout_ms == -1) { + evtimer_del(timer_event); + } else { + struct timeval timeout = {.tv_sec = timeout_ms / 1000, + .tv_usec = (timeout_ms % 1000) * 1000}; + evtimer_add(timer_event, &timeout); + } + return 0; +} + +MultiCurlRequestManager::MultiCurlRequestManager() + : MultiCurlRequestManager(/*event_base=*/nullptr) {} + +MultiCurlRequestManager::MultiCurlRequestManager(struct event_base* event_base) + : event_base_(event_base) { running_handles_ = 0; curl_global_init(CURL_GLOBAL_ALL); request_manager_ = curl_multi_init(); + curl_multi_setopt(request_manager_, CURLMOPT_SOCKETDATA, this); + curl_multi_setopt(request_manager_, CURLMOPT_SOCKETFUNCTION, + OnLibcurlSocketUpdate); } MultiCurlRequestManager::~MultiCurlRequestManager() { @@ -28,12 +151,34 @@ MultiCurlRequestManager::~MultiCurlRequestManager() { curl_global_cleanup(); } +// static +void MultiCurlRequestManager::MultiTimerCallback(int fd, short what, + void* arg) { + PS_VLOG(9) << "Multi timeout event callback called"; + auto* self = reinterpret_cast(arg); + { + absl::MutexLock l(&self->request_manager_mu_); + curl_multi_socket_action(self->request_manager_, CURL_SOCKET_TIMEOUT, 0, + &self->running_handles_); + } + PS_VLOG(9) << "Updating easy handles callback to be called"; + self->update_easy_handles_callback_(); +} + +void MultiCurlRequestManager::Configure( + absl::AnyInvocable update_easy_handles_callback, + struct event* timer_event) { + update_easy_handles_callback_ = std::move(update_easy_handles_callback); + curl_multi_setopt(request_manager_, CURLMOPT_TIMERDATA, timer_event); + curl_multi_setopt(request_manager_, CURLMOPT_TIMERFUNCTION, + OnLibcurlTimerUpdate); +} + CURLMcode MultiCurlRequestManager::Add(CURL* curl_handle) ABSL_LOCKS_EXCLUDED(request_manager_mu_) { absl::MutexLock l(&request_manager_mu_); - curl_multi_add_handle(request_manager_, curl_handle); - CURLMcode mc = curl_multi_perform(request_manager_, &running_handles_); - return mc; + PS_VLOG(8) << "Adding easy curl handle to multi handle"; + return curl_multi_add_handle(request_manager_, curl_handle); } CURLMsg* MultiCurlRequestManager::GetUpdate(int* msgs_left) @@ -43,6 +188,7 @@ CURLMsg* MultiCurlRequestManager::GetUpdate(int* msgs_left) CURLMsg* msg = curl_multi_info_read(request_manager_, msgs_left); return msg; } + CURLMcode MultiCurlRequestManager::Remove(CURL* curl_handle) ABSL_LOCKS_EXCLUDED(request_manager_mu_) { absl::MutexLock l(&request_manager_mu_); diff --git a/services/common/clients/http/multi_curl_request_manager.h b/services/common/clients/http/multi_curl_request_manager.h index 7ec28a67..276af886 100644 --- a/services/common/clients/http/multi_curl_request_manager.h +++ b/services/common/clients/http/multi_curl_request_manager.h @@ -15,11 +15,24 @@ #ifndef SERVICES_COMMON_CLIENTS_HTTP_MULTI_CURL_REQUEST_MANAGER_H_ #define SERVICES_COMMON_CLIENTS_HTTP_MULTI_CURL_REQUEST_MANAGER_H_ +#include +#include + +#include "absl/functional/any_invocable.h" #include "absl/synchronization/mutex.h" #include "curl/multi.h" namespace privacy_sandbox::bidding_auction_servers { +struct SocketInfo { + // Socket file descriptor. + curl_socket_t sock_fd; + // Last activity recorded on the descriptor. + int activity; + // Event type monitored by libevent's event loop. + struct event tracked_event; +}; + // This class provides a thread-safe interface around the Curl Multi Interface // for sharing HTTP resources (connections and TLS session) across // all HTTP invocations for a client. @@ -28,6 +41,25 @@ class MultiCurlRequestManager final { public: // Initializes the Curl Multi session. MultiCurlRequestManager(); + explicit MultiCurlRequestManager(struct event_base* event_base); + + // Configures the request manager with the callback to invoke upon updates + // to easy handle as well as the timer event to use to trigger transfer on + // handles. + void Configure(absl::AnyInvocable update_easy_handles_callback, + struct event* timer_event); + // This is the callback associated with the timer event which is an input + // to `Configure` method above. + static void MultiTimerCallback(int fd, short what, void* arg); + // This callback is invoked by libcurl when it wants to notify B&A about + // sockets that B&A should monitor for activity. + static int OnLibcurlSocketUpdate(CURL* easy_handle, curl_socket_t sock_fd, + int activity, void* data, + void* socket_info_pointer); + // This callback is invoked by libevent when it detects transfer (read/write) + // on sockets that libevent was monitoring on behalf of B&A. + static void OnLibeventSocketActivity(int fd, short kind, void* data); + // Cleans up the curl mutli session. Please make sure all easy handles // related to this multi session are manually cleaned up before this runs. ~MultiCurlRequestManager(); @@ -53,6 +85,9 @@ class MultiCurlRequestManager final { MultiCurlRequestManager& operator=(const MultiCurlRequestManager&) = delete; private: + void UpsertSocketInLibevent(curl_socket_t sock_fd, int activity, + SocketInfo* socket_info); + void AddSocketToLibevent(curl_socket_t sock, int activity, void* data); // No. of handles still running updated by curl_multi_perform. // This can be used to delay destruction till all easy handles related to this // multi have completed running. @@ -60,7 +95,9 @@ class MultiCurlRequestManager final { // Mutex for ensuring thread safe access of curl multi session. absl::Mutex request_manager_mu_; // Actual curl multi session pointer. - CURLM* request_manager_ ABSL_GUARDED_BY(request_manager_mu_); + CURLM* request_manager_; + absl::AnyInvocable update_easy_handles_callback_; + struct event_base* event_base_ = nullptr; }; } // namespace privacy_sandbox::bidding_auction_servers diff --git a/services/common/clients/http_kv_server/buyer/BUILD b/services/common/clients/http_kv_server/buyer/BUILD index 0cd2cf55..2408ad79 100644 --- a/services/common/clients/http_kv_server/buyer/BUILD +++ b/services/common/clients/http_kv_server/buyer/BUILD @@ -32,6 +32,7 @@ cc_library( "//services/common/clients/http:http_fetcher_async", "//services/common/clients/http_kv_server/util:http_kv_server_gen_url_utils", "//services/common/util:request_metadata", + "//services/common/util:request_response_constants", "@com_google_absl//absl/strings", ], ) diff --git a/services/common/clients/http_kv_server/buyer/buyer_key_value_async_http_client.cc b/services/common/clients/http_kv_server/buyer/buyer_key_value_async_http_client.cc index 587fbeec..4a46321f 100644 --- a/services/common/clients/http_kv_server/buyer/buyer_key_value_async_http_client.cc +++ b/services/common/clients/http_kv_server/buyer/buyer_key_value_async_http_client.cc @@ -18,6 +18,7 @@ #include "api/bidding_auction_servers.grpc.pb.h" #include "services/common/clients/http_kv_server/util/generate_url.h" #include "services/common/util/request_metadata.h" +#include "services/common/util/request_response_constants.h" namespace privacy_sandbox::bidding_auction_servers { namespace { @@ -81,22 +82,22 @@ absl::Status BuyerKeyValueAsyncHttpClient::Execute( auto done_callback = [on_done = std::move(on_done), request_size]( absl::StatusOr resultStr) mutable { if (resultStr.ok()) { - PS_VLOG(2) << "BuyerKeyValueAsyncHttpClient Success Response:\n" - << resultStr.value() << "\n"; + PS_VLOG(kKVLog) << "BuyerKeyValueAsyncHttpClient Success Response:\n" + << resultStr.value() << "\n"; size_t response_size = resultStr->size(); std::unique_ptr resultUPtr = std::make_unique(GetBuyerValuesOutput( {std::move(resultStr.value()), request_size, response_size})); std::move(on_done)(std::move(resultUPtr)); } else { - PS_VLOG(2) << "BuyerKeyValueAsyncHttpClient Failure Response: " - << resultStr.status(); + PS_VLOG(kNoisyWarn) << "BuyerKeyValueAsyncHttpClient Failure Response: " + << resultStr.status(); std::move(on_done)(resultStr.status()); } }; - PS_VLOG(2) << "BTS Request Url:\n" << request.url << "\nHeaders:\n"; + PS_VLOG(kKVLog) << "BTS Request Url:\n" << request.url << "\nHeaders:\n"; for (const auto& header : request.headers) { - PS_VLOG(2) << header; + PS_VLOG(kKVLog) << header; } http_fetcher_async_->FetchUrl( request, static_cast(absl::ToInt64Milliseconds(timeout)), diff --git a/services/common/clients/http_kv_server/buyer/buyer_key_value_async_http_client_test.cc b/services/common/clients/http_kv_server/buyer/buyer_key_value_async_http_client_test.cc index 1d21b884..6ac5be25 100644 --- a/services/common/clients/http_kv_server/buyer/buyer_key_value_async_http_client_test.cc +++ b/services/common/clients/http_kv_server/buyer/buyer_key_value_async_http_client_test.cc @@ -144,8 +144,8 @@ TEST_F(KeyValueAsyncHttpClientTest, // Inside this callback, we will actually check that the client correctly // parses what it gets back from the "server" (mocked below). absl::Notification callback_invoked; - absl::AnyInvocable>)&&> + absl::AnyInvocable< + void(absl::StatusOr>) &&> done_callback_to_check_val = // Capture the expected output struct for comparison [&callback_invoked, @@ -168,7 +168,7 @@ TEST_F(KeyValueAsyncHttpClientTest, // defining what it shall be) .WillOnce([actual_result = expected_result, &expected_urls]( const HTTPRequest& request, int timeout_ms, - absl::AnyInvocable) &&> + absl::AnyInvocable)&&> done_callback) { EXPECT_TRUE(expected_urls.contains(request.url)); // Pack said string into a statusOr @@ -281,8 +281,8 @@ TEST_F(KeyValueAsyncHttpClientTest, // Define the lambda function which is the callback. // Inside this callback, we will actually check that the client correctly // parses what it gets back from the "server" (mocked below). - absl::AnyInvocable>)&&> + absl::AnyInvocable< + void(absl::StatusOr>) &&> done_callback_to_check_val = // Capture the expected output struct for comparison [&callback_invoked, @@ -305,7 +305,7 @@ TEST_F(KeyValueAsyncHttpClientTest, // defining what it shall be) .WillOnce([actualResult, &expected_urls]( const HTTPRequest& request, int timeout_ms, - absl::AnyInvocable) &&> + absl::AnyInvocable)&&> done_callback) { EXPECT_TRUE(expected_urls.contains(request.url)) << request.url; // Pack said string into a statusOr @@ -331,10 +331,11 @@ TEST_F(KeyValueAsyncHttpClientTest, MakesDSPUrlCorrectlyWithDuplicateKey) { absl::StrCat(hostname_, "?hostname=www.usatoday.com&keys=url1"); EXPECT_CALL(*mock_http_fetcher_async_, FetchUrl) .WillOnce( - [expected_url]( - const HTTPRequest& request, int timeout_ms, - absl::AnyInvocable) &&> - done_callback) { EXPECT_EQ(expected_url, request.url); }); + [expected_url](const HTTPRequest& request, int timeout_ms, + absl::AnyInvocable)&&> + done_callback) { + EXPECT_EQ(expected_url, request.url); + }); CheckGetValuesFromKeysViaHttpClient(std::move(input)); } @@ -346,10 +347,11 @@ TEST_F(KeyValueAsyncHttpClientTest, MakesDSPUrlCorrectlyWithNoKeys) { absl::StrCat(hostname_, "?hostname=www.usatoday.com"); EXPECT_CALL(*mock_http_fetcher_async_, FetchUrl) .WillOnce( - [expected_url]( - const HTTPRequest& request, int timeout_ms, - absl::AnyInvocable) &&> - done_callback) { EXPECT_EQ(expected_url, request.url); }); + [expected_url](const HTTPRequest& request, int timeout_ms, + absl::AnyInvocable)&&> + done_callback) { + EXPECT_EQ(expected_url, request.url); + }); CheckGetValuesFromKeysViaHttpClient(std::move(input)); } @@ -362,7 +364,7 @@ TEST_F(KeyValueAsyncHttpClientTest, EXPECT_CALL(*mock_http_fetcher_async_, FetchUrl) .WillOnce([expected_urls_1 = &(expected_urls_1)]( const HTTPRequest& request, int timeout_ms, - absl::AnyInvocable) &&> + absl::AnyInvocable)&&> done_callback) { EXPECT_TRUE(expected_urls_1->contains(request.url)); }); @@ -384,7 +386,7 @@ TEST_F(KeyValueAsyncHttpClientTest, EXPECT_CALL(*mock_http_fetcher_async_, FetchUrl) .WillOnce([expected_urls_1 = &(expected_urls_1)]( const HTTPRequest& request, int timeout_ms, - absl::AnyInvocable) &&> + absl::AnyInvocable)&&> done_callback) { EXPECT_TRUE(expected_urls_1->contains(request.url)); }); @@ -415,7 +417,7 @@ TEST_F(KeyValueAsyncHttpClientTest, MakesDSPUrlCorrectlyWithClientTypeAndroid) { EXPECT_CALL(*mock_http_fetcher_async_, FetchUrl) .WillOnce([&expected_urls]( const HTTPRequest& request, int timeout_ms, - absl::AnyInvocable) &&> + absl::AnyInvocable)&&> done_callback) { EXPECT_TRUE(expected_urls.contains(request.url)); }); @@ -444,7 +446,7 @@ TEST_F(KeyValueAsyncHttpClientTest, AddsMetadataToHeaders) { EXPECT_CALL(*mock_http_fetcher_async_, FetchUrl) .WillOnce([&expectedHeaders]( HTTPRequest request, int timeout_ms, - absl::AnyInvocable) &&> + absl::AnyInvocable)&&> done_callback) { std::sort(expectedHeaders.begin(), expectedHeaders.end()); std::sort(request.headers.begin(), request.headers.end()); @@ -475,7 +477,7 @@ TEST_F(KeyValueAsyncHttpClientTest, AddsMandatoryHeaders) { EXPECT_CALL(*mock_http_fetcher_async_, FetchUrl) .WillOnce([&expected_headers]( HTTPRequest request, int timeout_ms, - absl::AnyInvocable) &&> + absl::AnyInvocable)&&> done_callback) { std::sort(expected_headers.begin(), expected_headers.end()); std::sort(request.headers.begin(), request.headers.end()); @@ -534,8 +536,8 @@ TEST_F(KeyValueAsyncHttpClientTest, SpacesInKeysGetEncoded) { // Inside this callback, we will actually check that the client correctly // parses what it gets back from the "server" (mocked below). absl::Notification callback_invoked; - absl::AnyInvocable>)&&> + absl::AnyInvocable< + void(absl::StatusOr>) &&> done_callback_to_check_val = // Capture the expected output struct for comparison [&callback_invoked, @@ -558,7 +560,7 @@ TEST_F(KeyValueAsyncHttpClientTest, SpacesInKeysGetEncoded) { // defining what it shall be) .WillOnce([actual_result = expected_result, &expectedUrl]( const HTTPRequest& request, int timeout_ms, - absl::AnyInvocable) &&> + absl::AnyInvocable)&&> done_callback) { EXPECT_EQ(request.url, expectedUrl); // Pack said string into a statusOr diff --git a/services/common/clients/http_kv_server/buyer/fake_buyer_key_value_async_http_client.cc b/services/common/clients/http_kv_server/buyer/fake_buyer_key_value_async_http_client.cc index 11a4a23e..a35d3492 100644 --- a/services/common/clients/http_kv_server/buyer/fake_buyer_key_value_async_http_client.cc +++ b/services/common/clients/http_kv_server/buyer/fake_buyer_key_value_async_http_client.cc @@ -18,6 +18,7 @@ #include #include "absl/strings/match.h" +#include "services/common/util/request_response_constants.h" namespace privacy_sandbox::bidding_auction_servers { @@ -52,7 +53,8 @@ absl::Status FakeBuyerKeyValueAsyncHttpClient::Execute( absl::Duration timeout) const { HTTPRequest request = BuyerKeyValueAsyncHttpClient::BuildBuyerKeyValueRequest( kv_server_base_address_, metadata, std::move(keys)); - PS_VLOG(2) << "FakeBuyerKeyValueAsyncHttpClient Request: " << request.url; + PS_VLOG(kKVLog) << "FakeBuyerKeyValueAsyncHttpClient Request: " + << request.url; // Below was faked @@ -67,7 +69,7 @@ absl::Status FakeBuyerKeyValueAsyncHttpClient::Execute( GetBuyerValuesOutput{std::move(kv_response), 0, 0}); std::move(on_done)(std::move(resultUPtr)); - PS_VLOG(2) << "E2E testing received hard coded buyer kv request"; + PS_VLOG(kKVLog) << "E2E testing received hard coded buyer kv request"; return absl::OkStatus(); } diff --git a/services/common/clients/http_kv_server/seller/BUILD b/services/common/clients/http_kv_server/seller/BUILD index 79753688..77be7a44 100644 --- a/services/common/clients/http_kv_server/seller/BUILD +++ b/services/common/clients/http_kv_server/seller/BUILD @@ -32,6 +32,7 @@ cc_library( "//services/common/clients/http:http_fetcher_async", "//services/common/clients/http_kv_server/util:http_kv_server_gen_url_utils", "//services/common/util:request_metadata", + "//services/common/util:request_response_constants", "@com_google_absl//absl/strings", ], ) diff --git a/services/common/clients/http_kv_server/seller/fake_seller_key_value_async_http_client.cc b/services/common/clients/http_kv_server/seller/fake_seller_key_value_async_http_client.cc index 23d94b56..f1c42edc 100644 --- a/services/common/clients/http_kv_server/seller/fake_seller_key_value_async_http_client.cc +++ b/services/common/clients/http_kv_server/seller/fake_seller_key_value_async_http_client.cc @@ -18,6 +18,7 @@ #include #include "absl/strings/match.h" +#include "services/common/util/request_response_constants.h" namespace privacy_sandbox::bidding_auction_servers { namespace { @@ -52,10 +53,11 @@ absl::Status FakeSellerKeyValueAsyncHttpClient::Execute( HTTPRequest request = SellerKeyValueAsyncHttpClient::BuildSellerKeyValueRequest( kv_server_base_address_, metadata, std::move(keys)); - PS_VLOG(2) << "FakeSellerKeyValueAsyncHttpClient Request: " << request.url; - PS_VLOG(2) << "\nFakeSellerKeyValueAsyncHttpClient Headers:\n"; + PS_VLOG(kKVLog) << "FakeSellerKeyValueAsyncHttpClient Request: " + << request.url; + PS_VLOG(kKVLog) << "\nFakeSellerKeyValueAsyncHttpClient Headers:\n"; for (const auto& header : request.headers) { - PS_VLOG(2) << header; + PS_VLOG(kKVLog) << header; } // Below are faked @@ -70,7 +72,7 @@ absl::Status FakeSellerKeyValueAsyncHttpClient::Execute( std::make_unique( GetSellerValuesOutput{std::move(kv_response), 0, 0}); std::move(on_done)(std::move(resultUPtr)); - PS_VLOG(2) << "E2E testing received hard coded seller kv request"; + PS_VLOG(kKVLog) << "E2E testing received hard coded seller kv request"; return absl::OkStatus(); } diff --git a/services/common/clients/http_kv_server/seller/seller_key_value_async_http_client.cc b/services/common/clients/http_kv_server/seller/seller_key_value_async_http_client.cc index 57ccfe2d..881f8ce1 100644 --- a/services/common/clients/http_kv_server/seller/seller_key_value_async_http_client.cc +++ b/services/common/clients/http_kv_server/seller/seller_key_value_async_http_client.cc @@ -18,6 +18,7 @@ #include "api/bidding_auction_servers.grpc.pb.h" #include "services/common/clients/http_kv_server/util/generate_url.h" #include "services/common/util/request_metadata.h" +#include "services/common/util/request_response_constants.h" namespace privacy_sandbox::bidding_auction_servers { @@ -63,10 +64,10 @@ absl::Status SellerKeyValueAsyncHttpClient::Execute( absl::Duration timeout) const { HTTPRequest request = BuildSellerKeyValueRequest(kv_server_base_address_, metadata, std::move(keys)); - PS_VLOG(2) << "SellerKeyValueAsyncHttpClient Request: " << request.url; - PS_VLOG(2) << "\nSellerKeyValueAsyncHttpClient Headers:\n"; + PS_VLOG(kKVLog) << "SellerKeyValueAsyncHttpClient Request: " << request.url; + PS_VLOG(kKVLog) << "\nSellerKeyValueAsyncHttpClient Headers:\n"; for (const auto& header : request.headers) { - PS_VLOG(2) << header; + PS_VLOG(kKVLog) << header; } size_t request_size = 0; for (std::string& header : request.headers) { @@ -76,16 +77,16 @@ absl::Status SellerKeyValueAsyncHttpClient::Execute( auto done_callback = [on_done = std::move(on_done), request_size]( absl::StatusOr resultStr) mutable { if (resultStr.ok()) { - PS_VLOG(2) << "SellerKeyValueAsyncHttpClient Response: " - << resultStr.value(); + PS_VLOG(kKVLog) << "SellerKeyValueAsyncHttpClient Response: " + << resultStr.value(); size_t response_size = resultStr->size(); std::unique_ptr resultUPtr = std::make_unique(GetSellerValuesOutput( {std::move(resultStr.value()), request_size, response_size})); std::move(on_done)(std::move(resultUPtr)); } else { - PS_VLOG(2) << "SellerKeyValueAsyncHttpClients Response: " - << resultStr.status(); + PS_VLOG(kNoisyWarn) << "SellerKeyValueAsyncHttpClients Response fail: " + << resultStr.status(); std::move(on_done)(resultStr.status()); } }; diff --git a/services/common/clients/http_kv_server/seller/seller_key_value_async_http_client_test.cc b/services/common/clients/http_kv_server/seller/seller_key_value_async_http_client_test.cc index 6ddeefb6..a73791e0 100644 --- a/services/common/clients/http_kv_server/seller/seller_key_value_async_http_client_test.cc +++ b/services/common/clients/http_kv_server/seller/seller_key_value_async_http_client_test.cc @@ -203,8 +203,8 @@ TEST_F(KeyValueAsyncHttpClientTest, // Inside this callback, we will actually check that the client correctly // parses what it gets back from the "server" (mocked below). absl::Notification callback_invoked; - absl::AnyInvocable>)&&> + absl::AnyInvocable< + void(absl::StatusOr>) &&> done_callback_to_check_val = // Capture the expected output struct for comparison [&callback_invoked, @@ -228,7 +228,7 @@ TEST_F(KeyValueAsyncHttpClientTest, .WillOnce([actual_result = expected_result, expected_urls = &(expected_urls_with_egid_)]( const HTTPRequest& request, int timeout_ms, - absl::AnyInvocable) &&> + absl::AnyInvocable)&&> done_callback) { EXPECT_TRUE(expected_urls->contains(request.url)); // Pack said string into a statusOr @@ -311,8 +311,8 @@ TEST_F(KeyValueAsyncHttpClientTest, // Define the lambda function which is the callback. // Inside this callback, we will actually check that the client correctly // parses what it gets back from the "server" (mocked below). - absl::AnyInvocable>)&&> + absl::AnyInvocable< + void(absl::StatusOr>) &&> done_callback_to_check_val = // Capture the expected output struct for comparison [&callback_invoked, @@ -335,7 +335,7 @@ TEST_F(KeyValueAsyncHttpClientTest, // defining what it shall be) .WillOnce([actual_result, expected_urls = &(expected_urls_)]( const HTTPRequest& request, int timeout_ms, - absl::AnyInvocable) &&> + absl::AnyInvocable)&&> done_callback) { EXPECT_TRUE(expected_urls->contains(request.url)); // Pack said string into a statusOr @@ -391,7 +391,7 @@ TEST_F(KeyValueAsyncHttpClientTest, MakesSSPUrlCorrectlyWithNoClientType) { .WillOnce( [&expected_url]( const HTTPRequest& request, int timeout_ms, - absl::AnyInvocable) &&> + absl::AnyInvocable)&&> done_callback) { EXPECT_EQ(request.url, expected_url); }); CheckGetValuesFromKeysViaHttpClient(std::move(input)); } @@ -419,7 +419,7 @@ TEST_F(KeyValueAsyncHttpClientTest, MakesSSPUrlCorrectlyWithClientTypeBrowser) { .WillOnce( [&expected_url]( const HTTPRequest& request, int timeout_ms, - absl::AnyInvocable) &&> + absl::AnyInvocable)&&> done_callback) { EXPECT_EQ(request.url, expected_url); }); CheckGetValuesFromKeysViaHttpClient(std::move(input)); } @@ -443,7 +443,7 @@ TEST_F(KeyValueAsyncHttpClientTest, MakesSSPUrlCorrectlyWithClientTypeAndroid) { .WillOnce( [&expected_url]( const HTTPRequest& request, int timeout_ms, - absl::AnyInvocable) &&> + absl::AnyInvocable)&&> done_callback) { EXPECT_EQ(request.url, expected_url); }); CheckGetValuesFromKeysViaHttpClient(std::move(input)); } @@ -487,7 +487,7 @@ TEST_F(KeyValueAsyncHttpClientTest, AddsMetadataToHeaders) { EXPECT_CALL(*mock_http_fetcher_async_, FetchUrl) .WillOnce([&expectedHeaders]( const HTTPRequest& request, int timeout_ms, - absl::AnyInvocable) &&> + absl::AnyInvocable)&&> done_callback) { EXPECT_EQ(expectedHeaders, request.headers); }); diff --git a/services/common/code_dispatch/code_dispatch_reactor.h b/services/common/code_dispatch/code_dispatch_reactor.h index 06a60ffe..6d046788 100644 --- a/services/common/code_dispatch/code_dispatch_reactor.h +++ b/services/common/code_dispatch/code_dispatch_reactor.h @@ -74,8 +74,8 @@ class CodeDispatchReactor : public grpc::ServerUnaryReactor { void OnDone() override { delete this; }; // Handles early-cancellation by the client. - void OnCancel() override{ - // TODO(b/245982466): error handling design + void OnCancel() override { + // TODO(b/245982466): error handling design }; // Decrypts the request ciphertext in and returns whether decryption was diff --git a/services/common/code_fetch/periodic_bucket_fetcher.cc b/services/common/code_fetch/periodic_bucket_fetcher.cc index 4d54dea4..dcac8a63 100644 --- a/services/common/code_fetch/periodic_bucket_fetcher.cc +++ b/services/common/code_fetch/periodic_bucket_fetcher.cc @@ -134,7 +134,7 @@ void PeriodicBucketFetcher::HandleBlobFetchResult( PS_LOG(ERROR) << "Roma failed to load blob: " << roma_result; return; } - PS_VLOG(kInfoMsg) << "Current code loaded into Roma for version " << version + PS_VLOG(kSuccess) << "Current code loaded into Roma for version " << version << ":\n" << wrapped_code; absl::MutexLock lock(&some_load_success_mu_); diff --git a/services/common/code_fetch/periodic_code_fetcher.cc b/services/common/code_fetch/periodic_code_fetcher.cc index 35ad77fd..8aec8854 100644 --- a/services/common/code_fetch/periodic_code_fetcher.cc +++ b/services/common/code_fetch/periodic_code_fetcher.cc @@ -96,11 +96,13 @@ void PeriodicCodeFetcher::PeriodicCodeFetchSync() { std::string wrapped_code = wrap_code_(cb_results_value_); absl::Status syncResult = dispatcher_.LoadSync(version_string_, wrapped_code); - PS_VLOG(kInfoMsg) << "Roma Client Response: " << syncResult; if (syncResult.ok()) { - PS_VLOG(2) << "Current code loaded into Roma:\n" << wrapped_code; + PS_VLOG(kSuccess) << "Current code loaded into Roma:\n" + << wrapped_code; absl::MutexLock lock(&some_load_success_mu_); some_load_success_ = true; + } else { + PS_LOG(ERROR) << "Roma LoadSync fail: " << syncResult; } } } @@ -110,7 +112,7 @@ void PeriodicCodeFetcher::PeriodicCodeFetchSync() { // Create a HTTPRequest object from the url_endpoint_ std::vector requests; for (const std::string& endpoint : url_endpoints_) { - PS_VLOG(kInfoMsg) << "Requesting UDF from: " << endpoint; + PS_VLOG(5) << "Requesting UDF from: " << endpoint; requests.push_back( {.url = endpoint, .headers = {"Cache-Control: no-cache"}}); } diff --git a/services/common/code_fetch/periodic_code_fetcher_test.cc b/services/common/code_fetch/periodic_code_fetcher_test.cc index b070044e..7d55b846 100644 --- a/services/common/code_fetch/periodic_code_fetcher_test.cc +++ b/services/common/code_fetch/periodic_code_fetcher_test.cc @@ -51,8 +51,8 @@ TEST(PeriodicCodeFetcherTest, LoadsHttpFetcherResultIntoV8Dispatcher) { .WillOnce([&js_url, &wasm_helper_url, &url_response]( const std::vector& requests, absl::Duration timeout, - absl::AnyInvocable< - void(std::vector>) &&> + absl::AnyInvocable>)&&> done_callback) { EXPECT_EQ(js_url, requests.at(0).url); EXPECT_EQ(wasm_helper_url, requests.at(1).url); @@ -96,8 +96,8 @@ TEST(PeriodicCodeFetcherTest, PeriodicallyFetchesCode) { .WillOnce([&url_response, &done_fetch_url]( const std::vector& requests, absl::Duration timeout, - absl::AnyInvocable< - void(std::vector>) &&> + absl::AnyInvocable>)&&> done_callback) { done_fetch_url.DecrementCount(); std::move(done_callback)(url_response); @@ -141,8 +141,8 @@ TEST(PeriodicCodeFetcherTest, LoadsOnlyDifferentHttpFetcherResult) { .WillRepeatedly([&url_response, &done_fetch_url]( const std::vector& requests, absl::Duration timeout, - absl::AnyInvocable< - void(std::vector>) &&> + absl::AnyInvocable>)&&> done_callback) { done_fetch_url.DecrementCount(); std::move(done_callback)(url_response); @@ -188,8 +188,8 @@ TEST(PeriodicCodeFetcherTest, LoadsCodeWithTheCorrectVersion) { EXPECT_CALL(*curl_http_fetcher, FetchUrls) .WillOnce([](const std::vector& requests, absl::Duration timeout, - absl::AnyInvocable< - void(std::vector>) &&> + absl::AnyInvocable>)&&> done_callback) { std::move(done_callback)({""}); }); constexpr char kTestVersion[] = "v10"; diff --git a/services/common/loggers/benchmarking_logger.cc b/services/common/loggers/benchmarking_logger.cc index 1359c3a3..67534aa6 100644 --- a/services/common/loggers/benchmarking_logger.cc +++ b/services/common/loggers/benchmarking_logger.cc @@ -40,9 +40,9 @@ void BenchmarkingLogger::End() { BenchmarkingLogger::~BenchmarkingLogger() { for (const std::string& log_record : log_store_) { - PS_VLOG(kInfoMsg) << absl::StrCat("\nBenchmarking for request ID [", - request_id_, "]: ", log_record); + PS_VLOG(kNoisyInfo) << absl::StrCat("\nBenchmarking for request ID [", + request_id_, "]: ", log_record); } - PS_VLOG(kInfoMsg) << "\n\n"; + PS_VLOG(kNoisyInfo) << "\n\n"; } } // namespace privacy_sandbox::bidding_auction_servers diff --git a/services/common/loggers/no_ops_logger.h b/services/common/loggers/no_ops_logger.h index 21bfd008..f9eda53a 100644 --- a/services/common/loggers/no_ops_logger.h +++ b/services/common/loggers/no_ops_logger.h @@ -25,8 +25,8 @@ class NoOpsLogger final : public BenchmarkingLogger { NoOpsLogger() = default; virtual ~NoOpsLogger() = default; - void Begin() override{}; - void End() override{}; + void Begin() override {}; + void End() override {}; // NoOpsLogger is neither copyable nor movable. NoOpsLogger(const NoOpsLogger&) = delete; diff --git a/services/common/util/BUILD b/services/common/util/BUILD index 48b188a8..04ff037f 100644 --- a/services/common/util/BUILD +++ b/services/common/util/BUILD @@ -305,6 +305,7 @@ cc_library( "binary_http_utils.h", ], deps = [ + "//services/common/util:request_response_constants", "@com_github_google_quiche//quiche:binary_http_unstable_api", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", @@ -445,3 +446,14 @@ cc_library( visibility = ["//services:__subpackages__"], deps = ["@com_google_absl//absl/strings"], ) + +cc_library( + name = "tcmalloc_utils", + hdrs = [ + "tcmalloc_utils.h", + ], + deps = [ + "@com_google_tcmalloc//tcmalloc:malloc_extension", + "@google_privacysandbox_servers_common//src/logger:request_context_impl", + ], +) diff --git a/services/common/util/binary_http_utils.h b/services/common/util/binary_http_utils.h index db6d6773..df0f10a2 100644 --- a/services/common/util/binary_http_utils.h +++ b/services/common/util/binary_http_utils.h @@ -23,6 +23,7 @@ #include "absl/status/statusor.h" #include "google/protobuf/util/json_util.h" #include "quiche/binary_http/binary_http_message.h" +#include "services/common/util/request_response_constants.h" #include "src/logger/request_context_logger.h" #include "src/util/status_macro/status_macros.h" @@ -84,8 +85,8 @@ absl::StatusOr FromBinaryHTTP( return absl::InvalidArgumentError( "Unable to convert the Binary HTTP response to proto"); } - PS_VLOG(2) << "Converted the http request to proto: " - << response_proto.DebugString(); + PS_VLOG(kSuccess) << "Converted the http request to proto: " + << response_proto.DebugString(); } return response_proto; } diff --git a/services/common/util/reporting_util.cc b/services/common/util/reporting_util.cc index 817e631e..a08e8704 100644 --- a/services/common/util/reporting_util.cc +++ b/services/common/util/reporting_util.cc @@ -45,7 +45,7 @@ void MayVlogAdTechCodeLogs(const rapidjson::Document& document, auto logs_it = document.FindMember(log_type.c_str()); if (logs_it != document.MemberEnd()) { for (const auto& log : logs_it->value.GetArray()) { - PS_VLOG(kInfoMsg, log_context) << log_type << ": " << log.GetString(); + PS_VLOG(kNoisyInfo, log_context) << log_type << ": " << log.GetString(); } } } diff --git a/services/common/util/request_response_constants.h b/services/common/util/request_response_constants.h index 14004854..42671962 100644 --- a/services/common/util/request_response_constants.h +++ b/services/common/util/request_response_constants.h @@ -141,11 +141,18 @@ inline constexpr std::array enum class AuctionType : int { kProtectedAudience, kProtectedAppSignals }; // log verbosity -inline constexpr int kPlain = 1; + +inline constexpr int kPlain = 1; // plaintext B&A request and response served +inline constexpr int kNoisyWarn = + 2; // non-critical error, use PS_LOG(ERROR, *) for critical error +inline constexpr int kOriginated = + 3; // plaintext B&A request and response originated from server +inline constexpr int kKVLog = 3; // KV request response +inline constexpr int kDispatch = 4; // UDF dispatch request and response inline constexpr int kSuccess = 3; -inline constexpr int kInfoMsg = 3; +inline constexpr int kNoisyInfo = 3; inline constexpr int kEncrypted = 4; - +inline constexpr int kStats = 5; // Stats log like time , byte size, etc. } // namespace privacy_sandbox::bidding_auction_servers #endif // SERVICES_COMMON_UTIL_REQUEST_RESPONSE_CONSTANTS_H_ diff --git a/services/common/util/tcmalloc_utils.h b/services/common/util/tcmalloc_utils.h new file mode 100644 index 00000000..0273a201 --- /dev/null +++ b/services/common/util/tcmalloc_utils.h @@ -0,0 +1,59 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SERVICES_COMMON_UTIL_TCMALLOC_UTILS_H_ +#define SERVICES_COMMON_UTIL_TCMALLOC_UTILS_H_ + +#include +#include + +#include "src/logger/request_context_logger.h" +#include "tcmalloc/malloc_extension.h" + +namespace privacy_sandbox::bidding_auction_servers { + +inline void MaySetBackgroundReleaseRate( + std::optional release_rate_bytes_per_second) { + if (!release_rate_bytes_per_second.has_value()) { + PS_VLOG(4) << "No release_rate_bytes_per_second for TCMalloc " + "specified, will use default"; + return; + } + + PS_VLOG(4) << "Using release_rate_bytes_per_second for TCMalloc: " + << *release_rate_bytes_per_second; + tcmalloc::MallocExtension::SetBackgroundReleaseRate( + static_cast( + *release_rate_bytes_per_second)); +} + +inline void MaySetMaxTotalThreadCacheBytes( + std::optional max_total_thread_cache_bytes) { + if (!max_total_thread_cache_bytes.has_value()) { + PS_VLOG(4) << "No max_total_thread_cache_bytes for TCMalloc specified, " + "will use default"; + return; + } + + PS_VLOG(4) << "Using max_total_thread_cache_bytes for TCMalloc: " + << *max_total_thread_cache_bytes; + tcmalloc::MallocExtension::SetMaxTotalThreadCacheBytes( + *max_total_thread_cache_bytes); +} + +} // namespace privacy_sandbox::bidding_auction_servers + +#endif // SERVICES_COMMON_UTIL_TCMALLOC_UTILS_H_ diff --git a/services/inference_sidecar/common/benchmark/BUILD b/services/inference_sidecar/common/benchmark/BUILD index 7e3106ac..a4b322ce 100644 --- a/services/inference_sidecar/common/benchmark/BUILD +++ b/services/inference_sidecar/common/benchmark/BUILD @@ -12,12 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. -load("@rules_cc//cc:defs.bzl", "cc_binary") +load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library") + +package(default_visibility = ["//visibility:public"]) # We export some benchmark files. # The benchmark can run in the workspace of each inference backend. exports_files([ "module_benchmark.cc", + "sandbox_benchmark.cc", ]) cc_binary( @@ -31,6 +34,7 @@ cc_binary( "//:inference_sidecar_test_target", ], deps = [ + ":request_utils", "//proto:inference_sidecar_cc_grpc_proto", "//proto:inference_sidecar_cc_proto", "//sandbox:sandbox_executor", @@ -54,6 +58,7 @@ cc_binary( "//:gen_test_model", ], deps = [ + ":request_utils", "//modules:module_interface", "//modules:test_module", "//proto:inference_sidecar_cc_proto", @@ -83,6 +88,16 @@ cc_binary( ], ) +cc_library( + name = "request_utils", + srcs = ["request_utils.cc"], + hdrs = ["request_utils.h"], + deps = [ + "//proto:inference_sidecar_cc_proto", + "@com_google_absl//absl/strings", + ], +) + # Builds the IPC inference sidecar for testing. cc_binary( name = "ipc_inference_sidecar_test_bin", diff --git a/services/inference_sidecar/common/benchmark/module_benchmark.cc b/services/inference_sidecar/common/benchmark/module_benchmark.cc index 35025bc3..9b0c1a2a 100644 --- a/services/inference_sidecar/common/benchmark/module_benchmark.cc +++ b/services/inference_sidecar/common/benchmark/module_benchmark.cc @@ -40,6 +40,7 @@ #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "benchmark/benchmark.h" +#include "benchmark/request_utils.h" #include "modules/module_interface.h" #include "proto/inference_sidecar.pb.h" #include "utils/file_util.h" @@ -77,30 +78,6 @@ static void ExportMetrics(benchmark::State& state) { benchmark::Counter::kInvert); } -// Creates a new request with model files in the new model path -RegisterModelRequest CreateNewRegisterRequest( - const RegisterModelRequest& register_request, - const std::string& new_model_path) { - RegisterModelRequest new_register_request = register_request; - new_register_request.mutable_model_spec()->set_model_path(new_model_path); - - std::map new_model_files; - - absl::string_view request_model_path = - register_request.model_spec().model_path(); - for (const auto& [relative_path, file_content] : - register_request.model_files()) { - std::string new_file_path = absl::StrCat( - new_model_path, relative_path.substr(request_model_path.length())); - new_model_files[new_file_path] = file_content; - } - new_register_request.clear_model_files(); - for (const auto& [new_file_path, file_content] : new_model_files) { - (*new_register_request.mutable_model_files())[new_file_path] = file_content; - } - return new_register_request; -} - class ModuleFixture : public benchmark::Fixture { public: void SetUp(::benchmark::State& state) { @@ -144,7 +121,7 @@ BENCHMARK_DEFINE_F(ModuleFixture, BM_Register)(benchmark::State& state) { absl::StrCat(register_model_request_.model_spec().model_path(), state.thread_index(), iter++); RegisterModelRequest new_register_model_request = - CreateNewRegisterRequest(register_model_request_, new_model_path); + CreateRegisterModelRequest(register_model_request_, new_model_path); state.ResumeTiming(); absl::StatusOr response = diff --git a/services/inference_sidecar/common/benchmark/request_utils.cc b/services/inference_sidecar/common/benchmark/request_utils.cc new file mode 100644 index 00000000..844e63df --- /dev/null +++ b/services/inference_sidecar/common/benchmark/request_utils.cc @@ -0,0 +1,49 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "benchmark/request_utils.h" + +#include +#include + +#include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" +#include "proto/inference_sidecar.pb.h" + +namespace privacy_sandbox::bidding_auction_servers::inference { + +RegisterModelRequest CreateRegisterModelRequest( + const RegisterModelRequest& register_request, + const std::string& new_model_path) { + RegisterModelRequest new_register_request = register_request; + new_register_request.mutable_model_spec()->set_model_path(new_model_path); + + std::unordered_map new_model_files; + + absl::string_view request_model_path = + register_request.model_spec().model_path(); + for (const auto& [relative_path, file_content] : + register_request.model_files()) { + std::string new_file_path = absl::StrCat( + new_model_path, relative_path.substr(request_model_path.length())); + new_model_files[new_file_path] = file_content; + } + new_register_request.clear_model_files(); + for (const auto& [new_file_path, file_content] : new_model_files) { + (*new_register_request.mutable_model_files())[new_file_path] = file_content; + } + return new_register_request; +} + +} // namespace privacy_sandbox::bidding_auction_servers::inference diff --git a/services/inference_sidecar/common/benchmark/request_utils.h b/services/inference_sidecar/common/benchmark/request_utils.h new file mode 100644 index 00000000..a6a1e66c --- /dev/null +++ b/services/inference_sidecar/common/benchmark/request_utils.h @@ -0,0 +1,31 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SERVICES_INFERENCE_SIDECAR_COMMON_BENCHMARK_REQUEST_UTILS_H_ +#define SERVICES_INFERENCE_SIDECAR_COMMON_BENCHMARK_REQUEST_UTILS_H_ + +#include + +#include "proto/inference_sidecar.pb.h" + +namespace privacy_sandbox::bidding_auction_servers::inference { + +// Creates a new RegisterModelRequest with the given model path. +RegisterModelRequest CreateRegisterModelRequest( + const RegisterModelRequest& register_request, + const std::string& new_model_path); + +} // namespace privacy_sandbox::bidding_auction_servers::inference + +#endif // SERVICES_INFERENCE_SIDECAR_COMMON_BENCHMARK_REQUEST_UTILS_H_ diff --git a/services/inference_sidecar/common/benchmark/sandbox_benchmark.cc b/services/inference_sidecar/common/benchmark/sandbox_benchmark.cc index 8dafb9c5..8eae5a9d 100644 --- a/services/inference_sidecar/common/benchmark/sandbox_benchmark.cc +++ b/services/inference_sidecar/common/benchmark/sandbox_benchmark.cc @@ -46,9 +46,11 @@ #include "absl/log/check.h" #include "absl/status/status.h" +#include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/synchronization/mutex.h" #include "benchmark/benchmark.h" +#include "benchmark/request_utils.h" #include "proto/inference_sidecar.grpc.pb.h" #include "proto/inference_sidecar.pb.h" #include "sandbox/sandbox_executor.h" @@ -63,9 +65,10 @@ constexpr absl::string_view kIpcInferenceSidecarBinary = constexpr absl::string_view kTestModelPath = "test_model"; constexpr char kJsonString[] = R"json({ "request" : [{ - "model_path" : "my_bucket/models/pcvr_models/1/", + "model_path" : "test_model", "tensors" : [ { + "tensor_name": "serving_default_double1:0", "data_type": "DOUBLE", "tensor_shape": [ 1, @@ -270,17 +273,29 @@ static void BM_Register_GRPC(benchmark::State& state) { std::unique_ptr stub = InferenceService::NewStub(client_channel); + RegisterModelRequest register_model_request; + CHECK(PopulateRegisterModelRequest(kTestModelPath, register_model_request) + .ok()); + + int iter = 0; for (auto _ : state) { - RegisterModelRequest register_model_request; - RegisterModelResponse register_model_response; - CHECK(PopulateRegisterModelRequest(kTestModelPath, register_model_request) - .ok()); + state.PauseTiming(); + std::string new_model_path = + absl::StrCat(register_model_request.model_spec().model_path(), + state.thread_index(), iter++); + RegisterModelRequest new_register_model_request = + CreateRegisterModelRequest(register_model_request, new_model_path); + state.ResumeTiming(); + grpc::ClientContext context; - grpc::Status status = stub->RegisterModel(&context, register_model_request, - ®ister_model_response); + RegisterModelResponse register_model_response; + grpc::Status status = stub->RegisterModel( + &context, new_register_model_request, ®ister_model_response); CHECK(status.ok()) << status.error_message(); } + ExportMetrics(state); + absl::StatusOr result = executor.StopSandboxee(); CHECK(result.ok()); CHECK_EQ(result->final_status(), sandbox2::Result::EXTERNAL_KILL); @@ -295,10 +310,6 @@ BENCHMARK(BM_Register_GRPC)->MeasureProcessCPUTime()->UseRealTime(); // Use a single sandbox worker (or, inference sidecar) to run the execution in // parallel. -BENCHMARK(BM_Predict_IPC) - ->ThreadRange(1, kMaxThreads) - ->MeasureProcessCPUTime() - ->UseRealTime(); BENCHMARK(BM_Predict_GRPC) ->ThreadRange(1, kMaxThreads) ->MeasureProcessCPUTime() @@ -307,10 +318,6 @@ BENCHMARK(BM_Predict_GRPC) // BM_Multiworker benchmarks trigger one sandbox worker (or, inference // sidecar) per Thread. NumWorkers counter is the number of the running // sandbox workers in the benchmark. -BENCHMARK(BM_Multiworker_Predict_IPC) - ->ThreadRange(1, kMaxThreads) - ->MeasureProcessCPUTime() - ->UseRealTime(); BENCHMARK(BM_Multiworker_Predict_GRPC) ->ThreadRange(1, kMaxThreads) ->MeasureProcessCPUTime() diff --git a/services/inference_sidecar/common/modules/BUILD b/services/inference_sidecar/common/modules/BUILD index 933b2f5a..d36eda89 100644 --- a/services/inference_sidecar/common/modules/BUILD +++ b/services/inference_sidecar/common/modules/BUILD @@ -74,6 +74,7 @@ cc_test( ], deps = [ ":test_module", + "//benchmark:request_utils", "//proto:inference_sidecar_cc_proto", "//utils:file_util", "@com_google_absl//absl/status", diff --git a/services/inference_sidecar/common/modules/module_concurrency_test.cc b/services/inference_sidecar/common/modules/module_concurrency_test.cc index 475042bd..2176a2a4 100644 --- a/services/inference_sidecar/common/modules/module_concurrency_test.cc +++ b/services/inference_sidecar/common/modules/module_concurrency_test.cc @@ -21,6 +21,7 @@ #include "absl/strings/str_cat.h" #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" +#include "benchmark/request_utils.h" #include "gtest/gtest.h" #include "modules/module_interface.h" #include "proto/inference_sidecar.pb.h" @@ -49,30 +50,6 @@ constexpr char kJsonString[] = R"json({ }] })json"; -// Create a new request with model files in the new model path -RegisterModelRequest CreateNewRegisterRequest( - const RegisterModelRequest& register_request, - const std::string& new_model_path) { - RegisterModelRequest new_register_request = register_request; - new_register_request.mutable_model_spec()->set_model_path(new_model_path); - - std::map new_model_files; - - absl::string_view request_model_path = - register_request.model_spec().model_path(); - for (const auto& [relative_path, file_content] : - register_request.model_files()) { - std::string new_file_path = absl::StrCat( - new_model_path, relative_path.substr(request_model_path.length())); - new_model_files[new_file_path] = file_content; - } - new_register_request.clear_model_files(); - for (const auto& [new_file_path, file_content] : new_model_files) { - (*new_register_request.mutable_model_files())[new_file_path] = file_content; - } - return new_register_request; -} - TEST(ModuleConcurrencyTest, RegisterModel_Success) { InferenceSidecarRuntimeConfig config; std::unique_ptr module = ModuleInterface::Create(config); @@ -88,7 +65,7 @@ TEST(ModuleConcurrencyTest, RegisterModel_Success) { std::string new_model_path = absl::StrCat(register_request.model_spec().model_path(), i); RegisterModelRequest new_register_request = - CreateNewRegisterRequest(register_request, new_model_path); + CreateRegisterModelRequest(register_request, new_model_path); EXPECT_TRUE(module->RegisterModel(new_register_request).ok()); })); @@ -137,7 +114,7 @@ TEST(ModuleConcurrencyTest, RegisterModel_Predict_Success) { std::string new_model_path = absl::StrCat(register_request.model_spec().model_path(), i); RegisterModelRequest new_register_request = - CreateNewRegisterRequest(register_request, new_model_path); + CreateRegisterModelRequest(register_request, new_model_path); EXPECT_TRUE(module->RegisterModel(new_register_request).ok()); })); diff --git a/services/inference_sidecar/modules/pytorch_v2_1_1/BUILD b/services/inference_sidecar/modules/pytorch_v2_1_1/BUILD index 55c60dff..ea6daf4a 100644 --- a/services/inference_sidecar/modules/pytorch_v2_1_1/BUILD +++ b/services/inference_sidecar/modules/pytorch_v2_1_1/BUILD @@ -193,6 +193,7 @@ cc_test( "@com_google_absl//absl/strings", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", + "@inference_common//benchmark:request_utils", "@inference_common//proto:inference_sidecar_cc_proto", "@inference_common//utils:file_util", ], diff --git a/services/inference_sidecar/modules/pytorch_v2_1_1/benchmark/BUILD b/services/inference_sidecar/modules/pytorch_v2_1_1/benchmark/BUILD index e3a138ac..f92810a1 100644 --- a/services/inference_sidecar/modules/pytorch_v2_1_1/benchmark/BUILD +++ b/services/inference_sidecar/modules/pytorch_v2_1_1/benchmark/BUILD @@ -27,6 +27,7 @@ cc_binary( "@com_google_absl//absl/strings", "@com_google_benchmark//:benchmark", "@com_google_benchmark//:benchmark_main", + "@inference_common//benchmark:request_utils", "@inference_common//modules:module_interface", "@inference_common//proto:inference_sidecar_cc_proto", "@inference_common//utils:file_util", diff --git a/services/inference_sidecar/modules/tensorflow_v2_14_0/BUILD b/services/inference_sidecar/modules/tensorflow_v2_14_0/BUILD index 1668224b..32e9d49c 100644 --- a/services/inference_sidecar/modules/tensorflow_v2_14_0/BUILD +++ b/services/inference_sidecar/modules/tensorflow_v2_14_0/BUILD @@ -220,6 +220,7 @@ cc_test( "@com_google_absl//absl/strings", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", + "@inference_common//benchmark:request_utils", "@inference_common//proto:inference_sidecar_cc_proto", "@inference_common//utils:file_util", ], diff --git a/services/inference_sidecar/modules/tensorflow_v2_14_0/benchmark/BUILD b/services/inference_sidecar/modules/tensorflow_v2_14_0/benchmark/BUILD index ceb88edd..c2d512a9 100644 --- a/services/inference_sidecar/modules/tensorflow_v2_14_0/benchmark/BUILD +++ b/services/inference_sidecar/modules/tensorflow_v2_14_0/benchmark/BUILD @@ -27,8 +27,34 @@ cc_binary( "@com_google_absl//absl/strings", "@com_google_benchmark//:benchmark", "@com_google_benchmark//:benchmark_main", + "@inference_common//benchmark:request_utils", "@inference_common//modules:module_interface", "@inference_common//proto:inference_sidecar_cc_proto", "@inference_common//utils:file_util", ], ) + +cc_binary( + name = "sandbox_benchmark", + srcs = ["@inference_common//benchmark:sandbox_benchmark.cc"], + data = [ + "//:inference_sidecar_test_target", + "//:test_model_target", + ], + deps = [ + "//:tensorflow", + "@com_github_grpc_grpc//:grpc++", + "@com_google_absl//absl/log:check", + "@com_google_absl//absl/status", + "@com_google_absl//absl/strings", + "@com_google_absl//absl/synchronization", + "@com_google_benchmark//:benchmark", + "@com_google_benchmark//:benchmark_main", + "@inference_common//benchmark:request_utils", + "@inference_common//modules:module_interface", + "@inference_common//proto:inference_sidecar_cc_grpc_proto", + "@inference_common//proto:inference_sidecar_cc_proto", + "@inference_common//sandbox:sandbox_executor", + "@inference_common//utils:file_util", + ], +) diff --git a/services/seller_frontend_service/BUILD b/services/seller_frontend_service/BUILD index 809f073c..9aac67d5 100644 --- a/services/seller_frontend_service/BUILD +++ b/services/seller_frontend_service/BUILD @@ -103,12 +103,14 @@ cc_binary( "-Wl,-rpath,\\$$ORIGIN/../lib", ], local_defines = ENABLE_CORE_DUMPS_DEFINES, + malloc = "@com_google_tcmalloc//tcmalloc", deps = [ ":seller_frontend_service", "//services/common/clients/config:config_client_util", "//services/common/encryption:crypto_client_factory", "//services/common/encryption:key_fetcher_factory", "//services/common/telemetry:configure_telemetry", + "//services/common/util:tcmalloc_utils", "//services/seller_frontend_service/util:key_fetcher_utils", "@com_github_grpc_grpc//:grpc++", "@com_github_grpc_grpc//:grpc++_reflection", # for grpc_cli diff --git a/services/seller_frontend_service/benchmarking/select_ad_reactor_benchmarks.cc b/services/seller_frontend_service/benchmarking/select_ad_reactor_benchmarks.cc index 6cc9da99..0d6dbe2c 100644 --- a/services/seller_frontend_service/benchmarking/select_ad_reactor_benchmarks.cc +++ b/services/seller_frontend_service/benchmarking/select_ad_reactor_benchmarks.cc @@ -50,9 +50,9 @@ void AsyncReporterStub::DoReport( const HTTPRequest& reporting_request, absl::AnyInvocable) &&> done_callback) const { - PS_VLOG(kInfoMsg) << "Mocking success for reporting to URL: " - << reporting_request.url - << ", body: " << reporting_request.body; + PS_VLOG(kNoisyInfo) << "Mocking success for reporting to URL: " + << reporting_request.url + << ", body: " << reporting_request.body; std::move(done_callback)("success"); } diff --git a/services/seller_frontend_service/providers/http_scoring_signals_async_provider_test.cc b/services/seller_frontend_service/providers/http_scoring_signals_async_provider_test.cc index e379bc24..a0722f8f 100644 --- a/services/seller_frontend_service/providers/http_scoring_signals_async_provider_test.cc +++ b/services/seller_frontend_service/providers/http_scoring_signals_async_provider_test.cc @@ -46,17 +46,18 @@ TEST(HttpScoringSignalsAsyncProviderTest, IncludesClientTypeInRequest) { An>) &&>>(), An())) - .WillOnce([¬ification, &test_client_type]( - std::unique_ptr input, - const RequestMetadata& metadata, - absl::AnyInvocable>) &&> - callback, - absl::Duration timeout) { - EXPECT_EQ(input->client_type, test_client_type); - notification.Notify(); - return absl::OkStatus(); - }); + .WillOnce( + [¬ification, &test_client_type]( + std::unique_ptr input, + const RequestMetadata& metadata, + absl::AnyInvocable>)&&> + callback, + absl::Duration timeout) { + EXPECT_EQ(input->client_type, test_client_type); + notification.Notify(); + return absl::OkStatus(); + }); HttpScoringSignalsAsyncProvider class_under_test(std::move(mock_client)); @@ -123,20 +124,22 @@ TEST(HttpScoringSignalsAsyncProviderTest, MapsAdKeysToSellerValuesInput) { An>) &&>>(), An())) - .WillOnce([&ad_render_urls, &ad_component_render_urls, ¬ification]( - std::unique_ptr input, - const RequestMetadata& metadata, - absl::AnyInvocable>) &&> - callback, - absl::Duration timeout) { - // All ads from all responses were sent to KV client. - EXPECT_EQ(input->render_urls, ad_render_urls); - EXPECT_EQ(input->ad_component_render_urls, ad_component_render_urls); - EXPECT_EQ(input->seller_kv_experiment_group_id, kSellerEgId); - notification.Notify(); - return absl::OkStatus(); - }); + .WillOnce( + [&ad_render_urls, &ad_component_render_urls, ¬ification]( + std::unique_ptr input, + const RequestMetadata& metadata, + absl::AnyInvocable>)&&> + callback, + absl::Duration timeout) { + // All ads from all responses were sent to KV client. + EXPECT_EQ(input->render_urls, ad_render_urls); + EXPECT_EQ(input->ad_component_render_urls, + ad_component_render_urls); + EXPECT_EQ(input->seller_kv_experiment_group_id, kSellerEgId); + notification.Notify(); + return absl::OkStatus(); + }); HttpScoringSignalsAsyncProvider class_under_test(std::move(mock_client)); @@ -166,9 +169,8 @@ TEST(HttpScoringSignalsAsyncProviderTest, MapsAsyncClientError) { .WillOnce( [](std::unique_ptr input, const RequestMetadata& metadata, - absl::AnyInvocable< - void( - absl::StatusOr>) &&> + absl::AnyInvocable>)&&> callback, absl::Duration timeout) { EXPECT_EQ(input->seller_kv_experiment_group_id, ""); @@ -206,18 +208,19 @@ TEST(HttpScoringSignalsAsyncProviderTest, MapsResponseToScoringSignals) { An>) &&>>(), An())) - .WillOnce([&expected_output]( - std::unique_ptr input, - const RequestMetadata& metadata, - absl::AnyInvocable>) &&> - callback, - absl::Duration timeout) { - auto output = std::make_unique(); - output->result = expected_output; - (std::move(callback))(std::move(output)); - return absl::OkStatus(); - }); + .WillOnce( + [&expected_output]( + std::unique_ptr input, + const RequestMetadata& metadata, + absl::AnyInvocable>)&&> + callback, + absl::Duration timeout) { + auto output = std::make_unique(); + output->result = expected_output; + (std::move(callback))(std::move(output)); + return absl::OkStatus(); + }); HttpScoringSignalsAsyncProvider class_under_test(std::move(mock_client)); diff --git a/services/seller_frontend_service/runtime_flags.h b/services/seller_frontend_service/runtime_flags.h index 61911629..aad34287 100644 --- a/services/seller_frontend_service/runtime_flags.h +++ b/services/seller_frontend_service/runtime_flags.h @@ -23,32 +23,46 @@ namespace privacy_sandbox::bidding_auction_servers { // Define runtime flag names. -inline constexpr char PORT[] = "SELLER_FRONTEND_PORT"; -inline constexpr char HEALTHCHECK_PORT[] = "SELLER_FRONTEND_HEALTHCHECK_PORT"; -inline constexpr char GET_BID_RPC_TIMEOUT_MS[] = "GET_BID_RPC_TIMEOUT_MS"; -inline constexpr char KEY_VALUE_SIGNALS_FETCH_RPC_TIMEOUT_MS[] = +inline constexpr absl::string_view PORT = "SELLER_FRONTEND_PORT"; +inline constexpr absl::string_view HEALTHCHECK_PORT = + "SELLER_FRONTEND_HEALTHCHECK_PORT"; +inline constexpr absl::string_view GET_BID_RPC_TIMEOUT_MS = + "GET_BID_RPC_TIMEOUT_MS"; +inline constexpr absl::string_view KEY_VALUE_SIGNALS_FETCH_RPC_TIMEOUT_MS = "KEY_VALUE_SIGNALS_FETCH_RPC_TIMEOUT_MS"; -inline constexpr char SCORE_ADS_RPC_TIMEOUT_MS[] = "SCORE_ADS_RPC_TIMEOUT_MS"; -inline constexpr char SELLER_ORIGIN_DOMAIN[] = "SELLER_ORIGIN_DOMAIN"; -inline constexpr char AUCTION_SERVER_HOST[] = "AUCTION_SERVER_HOST"; -inline constexpr char KEY_VALUE_SIGNALS_HOST[] = "KEY_VALUE_SIGNALS_HOST"; -inline constexpr char BUYER_SERVER_HOSTS[] = "BUYER_SERVER_HOSTS"; -inline constexpr char ENABLE_BUYER_COMPRESSION[] = "ENABLE_BUYER_COMPRESSION"; -inline constexpr char ENABLE_AUCTION_COMPRESSION[] = +inline constexpr absl::string_view SCORE_ADS_RPC_TIMEOUT_MS = + "SCORE_ADS_RPC_TIMEOUT_MS"; +inline constexpr absl::string_view SELLER_ORIGIN_DOMAIN = + "SELLER_ORIGIN_DOMAIN"; +inline constexpr absl::string_view AUCTION_SERVER_HOST = "AUCTION_SERVER_HOST"; +inline constexpr absl::string_view KEY_VALUE_SIGNALS_HOST = + "KEY_VALUE_SIGNALS_HOST"; +inline constexpr absl::string_view BUYER_SERVER_HOSTS = "BUYER_SERVER_HOSTS"; +inline constexpr absl::string_view ENABLE_BUYER_COMPRESSION = + "ENABLE_BUYER_COMPRESSION"; +inline constexpr absl::string_view ENABLE_AUCTION_COMPRESSION = "ENABLE_AUCTION_COMPRESSION"; -inline constexpr char ENABLE_SELLER_FRONTEND_BENCHMARKING[] = +inline constexpr absl::string_view ENABLE_SELLER_FRONTEND_BENCHMARKING = "ENABLE_SELLER_FRONTEND_BENCHMARKING"; -inline constexpr char CREATE_NEW_EVENT_ENGINE[] = "CREATE_NEW_EVENT_ENGINE"; -inline constexpr char SFE_INGRESS_TLS[] = "SFE_INGRESS_TLS"; -inline constexpr char SFE_TLS_KEY[] = "SFE_TLS_KEY"; -inline constexpr char SFE_TLS_CERT[] = "SFE_TLS_CERT"; -inline constexpr char AUCTION_EGRESS_TLS[] = "AUCTION_EGRESS_TLS"; -inline constexpr char BUYER_EGRESS_TLS[] = "BUYER_EGRESS_TLS"; -inline constexpr char SFE_PUBLIC_KEYS_ENDPOINTS[] = "SFE_PUBLIC_KEYS_ENDPOINTS"; -inline constexpr char SELLER_CLOUD_PLATFORMS_MAP[] = +inline constexpr absl::string_view CREATE_NEW_EVENT_ENGINE = + "CREATE_NEW_EVENT_ENGINE"; +inline constexpr absl::string_view SFE_INGRESS_TLS = "SFE_INGRESS_TLS"; +inline constexpr absl::string_view SFE_TLS_KEY = "SFE_TLS_KEY"; +inline constexpr absl::string_view SFE_TLS_CERT = "SFE_TLS_CERT"; +inline constexpr absl::string_view AUCTION_EGRESS_TLS = "AUCTION_EGRESS_TLS"; +inline constexpr absl::string_view BUYER_EGRESS_TLS = "BUYER_EGRESS_TLS"; +inline constexpr absl::string_view SFE_PUBLIC_KEYS_ENDPOINTS = + "SFE_PUBLIC_KEYS_ENDPOINTS"; +inline constexpr absl::string_view SELLER_CLOUD_PLATFORMS_MAP = "SELLER_CLOUD_PLATFORMS_MAP"; +inline constexpr absl::string_view + SFE_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND = + "SFE_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND"; +inline constexpr absl::string_view SFE_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES = + "SFE_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES"; -inline constexpr absl::string_view kFlags[] = { +inline constexpr int kNumRuntimeFlags = 22; +inline constexpr std::array kFlags = { PORT, HEALTHCHECK_PORT, GET_BID_RPC_TIMEOUT_MS, @@ -69,11 +83,13 @@ inline constexpr absl::string_view kFlags[] = { BUYER_EGRESS_TLS, SFE_PUBLIC_KEYS_ENDPOINTS, SELLER_CLOUD_PLATFORMS_MAP, + SFE_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND, + SFE_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES, }; inline std::vector GetServiceFlags() { - int size = sizeof(kFlags) / sizeof(kFlags[0]); - std::vector flags(kFlags, kFlags + size); + std::vector flags(kFlags.begin(), + kFlags.begin() + kNumRuntimeFlags); for (absl::string_view flag : kCommonServiceFlags) { flags.push_back(flag); diff --git a/services/seller_frontend_service/select_ad_reactor.cc b/services/seller_frontend_service/select_ad_reactor.cc index 7d96b0dd..9f326064 100644 --- a/services/seller_frontend_service/select_ad_reactor.cc +++ b/services/seller_frontend_service/select_ad_reactor.cc @@ -121,7 +121,7 @@ AdWithBidMetadata SelectAdReactor::BuildAdWithBidMetadata( result.set_interest_group_origin(interest_group.origin()); if (request_->client_type() == CLIENT_TYPE_BROWSER) { result.set_join_count(interest_group.browser_signals().join_count()); - PS_VLOG(kInfoMsg, log_context_) + PS_VLOG(kNoisyInfo, log_context_) << "BrowserSignal: Recency:" << interest_group.browser_signals().recency(); @@ -179,9 +179,10 @@ grpc::Status SelectAdReactor::DecryptRequest() { auto decrypted_hpke_req = DecryptOHTTPEncapsulatedHpkeCiphertext( encapsulated_req, clients_.key_fetcher_manager_); if (!decrypted_hpke_req.ok()) { - PS_VLOG(2) << "Error decrypting the protected " - << (is_protected_auction_request_ ? "auction" : "audience") - << " input ciphertext" << decrypted_hpke_req.status(); + PS_VLOG(kNoisyWarn) << "Error decrypting the protected " + << (is_protected_auction_request_ ? "auction" + : "audience") + << " input ciphertext" << decrypted_hpke_req.status(); return {grpc::StatusCode::INVALID_ARGUMENT, absl::StrFormat(kErrorDecryptingCiphertextError, decrypted_hpke_req.status().message())}; @@ -336,11 +337,11 @@ void SelectAdReactor::Execute() { PS_VLOG(kEncrypted, log_context_) << "Encrypted SelectAdRequest:\n" << request_->ShortDebugString(); - PS_VLOG(2, log_context_) << "Headers:\n" - << absl::StrJoin(context_->client_metadata(), "\n", - absl::PairFormatter( - absl::StreamFormatter(), " : ", - absl::StreamFormatter())); + PS_VLOG(kPlain, log_context_) + << "Headers:\n" + << absl::StrJoin(context_->client_metadata(), "\n", + absl::PairFormatter(absl::StreamFormatter(), " : ", + absl::StreamFormatter())); if (!decrypt_status.ok()) { FinishWithStatus(decrypt_status); PS_LOG(ERROR, log_context_) << "SelectAdRequest decryption failed:" @@ -408,7 +409,7 @@ void SelectAdReactor::Execute() { for (const auto& buyer_ig_owner : request_->auction_config().buyer_list()) { if (buyer_set.erase(buyer_ig_owner) == 0) { - PS_VLOG(2, log_context_) + PS_VLOG(kNoisyWarn, log_context_) << "Duplicate buyer found " << buyer_ig_owner << ", skipping buyer"; async_task_tracker_.TaskCompleted(TaskStatus::SKIPPED); continue; @@ -417,14 +418,15 @@ void SelectAdReactor::Execute() { if (num_buyers_solicited >= max_buyers_solicited_) { // Skipped buyers should not be left pending. async_task_tracker_.TaskCompleted(TaskStatus::SKIPPED); - PS_VLOG(2, log_context_) << "Exceeded cap of " << max_buyers_solicited_ - << " buyers called. Skipping buyer"; + PS_VLOG(kNoisyWarn, log_context_) + << "Exceeded cap of " << max_buyers_solicited_ + << " buyers called. Skipping buyer"; continue; } const auto& buyer_input_iterator = buyer_inputs_->find(buyer_ig_owner); if (buyer_input_iterator == buyer_inputs_->end()) { - PS_VLOG(2, log_context_) + PS_VLOG(kNoisyWarn, log_context_) << "No buyer input found for buyer: " << buyer_ig_owner << ", skipping buyer"; @@ -501,7 +503,7 @@ void SelectAdReactor::FetchBid(const std::string& buyer_ig_owner, const BuyerInput& buyer_input) { auto buyer_client = clients_.buyer_factory.Get(buyer_ig_owner); if (buyer_client == nullptr) { - PS_VLOG(2, log_context_) + PS_VLOG(kNoisyWarn, log_context_) << "No buyer client found for buyer: " << buyer_ig_owner; async_task_tracker_.TaskCompleted(TaskStatus::SKIPPED); @@ -583,8 +585,8 @@ void SelectAdReactor::OnFetchBidsDone( PS_VLOG(5, log_context_) << "Received response from a BFE ... "; if (response.ok()) { auto& found_response = *response; - PS_VLOG(2, log_context_) << "\nGetBidsResponse:\n" - << found_response->DebugString(); + PS_VLOG(kOriginated, log_context_) << "\nGetBidsResponse:\n" + << found_response->DebugString(); if (found_response->has_debug_info()) { server_common::DebugInfo& bfe_log = *response_->mutable_debug_info()->add_downstream_servers(); @@ -594,8 +596,8 @@ void SelectAdReactor::OnFetchBidsDone( if ((!is_protected_audience_enabled_ || found_response->bids().empty()) && (!is_pas_enabled_ || found_response->protected_app_signals_bids().empty())) { - PS_VLOG(2, log_context_) << "Skipping buyer " << buyer_ig_owner - << " due to empty GetBidsResponse."; + PS_VLOG(kNoisyWarn, log_context_) << "Skipping buyer " << buyer_ig_owner + << " due to empty GetBidsResponse."; async_task_tracker_.TaskCompleted(TaskStatus::EMPTY_RESPONSE); } else { @@ -629,7 +631,7 @@ void SelectAdReactor::OnAllBidsDone(bool any_successful_bids) { // No successful bids received. if (shared_buyer_bids_map_.empty()) { - PS_VLOG(2, log_context_) << kNoBidsReceived; + PS_VLOG(kNoisyWarn, log_context_) << kNoBidsReceived; if (!any_successful_bids) { LogIfError( @@ -652,7 +654,7 @@ void SelectAdReactor::OnAllBidsDone(bool any_successful_bids) { // That each buyer has bids was checked in OnFetchBidsDone(). // Thus the preconditions of the following method are satisfied. if (!FilterBidsWithMismatchingCurrency()) { - PS_VLOG(2, log_context_) << kAllBidsRejectedBuyerCurrencyMismatch; + PS_VLOG(kNoisyWarn, log_context_) << kAllBidsRejectedBuyerCurrencyMismatch; FinishWithStatus(grpc::Status(grpc::INVALID_ARGUMENT, kAllBidsRejectedBuyerCurrencyMismatch)); } else { @@ -814,8 +816,9 @@ void SelectAdReactor::OnFetchScoringSignalsDone( scoring_signals_ = std::move(result).value(); // If signals are empty, return chaff. if (scoring_signals_->scoring_signals->empty()) { - PS_VLOG(2, log_context_) << "Scoring signals fetch from key-value server " - "succeeded but were empty."; + PS_VLOG(kNoisyWarn, log_context_) + << "Scoring signals fetch from key-value server " + "succeeded but were empty."; OnScoreAdsDone(std::make_unique()); return; @@ -881,21 +884,14 @@ void SelectAdReactor::ScoreAds() { auto raw_request = CreateScoreAdsRequest(); if (raw_request->ad_bids().empty() && raw_request->protected_app_signals_ad_bids().empty()) { - PS_VLOG(2, log_context_) << "No Protected Audience or Protected App " - "Signals ads to score, sending chaff response"; - OnScoreAdsDone(std::make_unique()); - return; - } - - PS_VLOG(2, log_context_) << "\nScoreAdsRawRequest:\n" - << raw_request->DebugString(); - if (raw_request->ad_bids().empty() && - raw_request->protected_app_signals_ad_bids().empty()) { - PS_VLOG(2, log_context_) << "No Protected Audience or Protected App " - "Signals ads to score, sending chaff response"; + PS_VLOG(kNoisyWarn, log_context_) + << "No Protected Audience or Protected App " + "Signals ads to score, sending chaff response"; OnScoreAdsDone(std::make_unique()); return; } + PS_VLOG(kOriginated, log_context_) << "\nScoreAdsRawRequest:\n" + << raw_request->DebugString(); auto auction_request = metric::MakeInitiatedRequest(metric::kAs, metric_context_.get()); @@ -955,7 +951,8 @@ void SelectAdReactor::OnScoreAdsDone( return; } - PS_VLOG(2, log_context_) << "ScoreAdsResponse status:" << response.status(); + PS_VLOG(kOriginated, log_context_) + << "ScoreAdsResponse status:" << response.status(); auto scoring_return_code = static_cast(response.status().code()); if (!response.ok()) { diff --git a/services/seller_frontend_service/select_ad_reactor.h b/services/seller_frontend_service/select_ad_reactor.h index 6dd71ef0..e9cf6f47 100644 --- a/services/seller_frontend_service/select_ad_reactor.h +++ b/services/seller_frontend_service/select_ad_reactor.h @@ -39,6 +39,7 @@ #include "services/common/util/error_accumulator.h" #include "services/common/util/error_reporter.h" #include "services/common/util/request_metadata.h" +#include "services/common/util/request_response_constants.h" #include "services/seller_frontend_service/data/scoring_signals.h" #include "services/seller_frontend_service/seller_frontend_service.h" #include "services/seller_frontend_service/util/encryption_util.h" @@ -179,7 +180,7 @@ class SelectAdReactor : public grpc::ServerUnaryReactor { // Log but don't report the errors for malformed buyer inputs because we // have found at least one buyer input that is well formed. for (const auto& observed_error : observed_errors) { - PS_VLOG(2, log_context_) << observed_error; + PS_VLOG(kNoisyWarn, log_context_) << observed_error; } } } diff --git a/services/seller_frontend_service/select_ad_reactor_test.cc b/services/seller_frontend_service/select_ad_reactor_test.cc index b6c5bb2d..547ce4ac 100644 --- a/services/seller_frontend_service/select_ad_reactor_test.cc +++ b/services/seller_frontend_service/select_ad_reactor_test.cc @@ -837,8 +837,7 @@ TYPED_TEST(SellerFrontEndServiceTest, ReturnsWinningAdAfterScoring) { EXPECT_EQ(auction_result.ad_component_render_urls().size(), winner.mutable_component_renders()->size()); EXPECT_EQ(auction_result.ad_render_url(), winner.render()); - // No modified bid set, so bid should be empty. - EXPECT_EQ(auction_result.bid(), 0.0f); + EXPECT_EQ(auction_result.bid(), winner.buyer_bid()); EXPECT_EQ(auction_result.interest_group_name(), winner.interest_group_name()); EXPECT_EQ(auction_result.interest_group_owner(), winner.interest_group_owner()); @@ -1109,7 +1108,7 @@ TYPED_TEST(SellerFrontEndServiceTest, winner.mutable_component_renders()->size()); EXPECT_EQ(auction_result.ad_render_url(), winner.render()); // No modified bid set, so bid should be empty. - EXPECT_EQ(auction_result.bid(), 0.0f); + EXPECT_EQ(auction_result.bid(), winner.buyer_bid()); EXPECT_EQ(auction_result.interest_group_name(), winner.interest_group_name()); EXPECT_EQ(auction_result.interest_group_owner(), winner.interest_group_owner()); @@ -1335,7 +1334,7 @@ TYPED_TEST(SellerFrontEndServiceTest, PerformsDebugReportingAfterScoring) { .WillRepeatedly( [&reporting_count]( const HTTPRequest& reporting_request, - absl::AnyInvocable) &&> + absl::AnyInvocable)&&> done_callback) { EXPECT_FALSE(reporting_request.url.empty()); reporting_count.DecrementCount(); diff --git a/services/seller_frontend_service/select_auction_result_reactor.cc b/services/seller_frontend_service/select_auction_result_reactor.cc index 676a9f07..99f90cab 100644 --- a/services/seller_frontend_service/select_auction_result_reactor.cc +++ b/services/seller_frontend_service/select_auction_result_reactor.cc @@ -72,8 +72,8 @@ void SelectAuctionResultReactor::ScoreAds( auto raw_request = CreateTopLevelScoreAdsRawRequest( request_->auction_config(), protected_auction_input_, component_auction_results); - PS_VLOG(2, log_context_) << "\nScoreAdsRawRequest:\n" - << raw_request->DebugString(); + PS_VLOG(kOriginated, log_context_) << "\nScoreAdsRawRequest:\n" + << raw_request->DebugString(); auto auction_request_metric = metric::MakeInitiatedRequest(metric::kAs, metric_context_.get()); auction_request_metric->SetRequestSize((int)raw_request->ByteSizeLong()); @@ -108,7 +108,8 @@ void SelectAuctionResultReactor::ScoreAds( void SelectAuctionResultReactor::OnScoreAdsDone( absl::StatusOr> response) { - PS_VLOG(2, log_context_) << "ScoreAdsResponse status:" << response.status(); + PS_VLOG(kOriginated, log_context_) + << "ScoreAdsResponse status:" << response.status(); auto scoring_return_status = server_common::FromAbslStatus(response.status()); if (!response.ok()) { LogIfError( @@ -182,7 +183,7 @@ void SelectAuctionResultReactor::FinishWithResponse( void SelectAuctionResultReactor::FinishWithClientVisibleErrors( absl::string_view message) { - PS_VLOG(2, log_context_) + PS_LOG(ERROR, log_context_) << "Finishing the SelectAdRequest RPC with client visible error: " << message; AuctionResult::Error auction_error; @@ -195,7 +196,7 @@ void SelectAuctionResultReactor::FinishWithClientVisibleErrors( void SelectAuctionResultReactor::FinishWithServerVisibleErrors( absl::string_view message) { - PS_VLOG(2, log_context_) + PS_LOG(ERROR, log_context_) << "Finishing the SelectAdRequest RPC with ad server visible error"; FinishWithStatus( grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, message.data())); diff --git a/services/seller_frontend_service/select_auction_result_reactor_test.cc b/services/seller_frontend_service/select_auction_result_reactor_test.cc index 8305e013..7663a491 100644 --- a/services/seller_frontend_service/select_auction_result_reactor_test.cc +++ b/services/seller_frontend_service/select_auction_result_reactor_test.cc @@ -122,9 +122,9 @@ TYPED_TEST(SelectAuctionResultReactorTest, CallsScoringWithComponentAuctions) { std::unique_ptr score_ads_request, const RequestMetadata& metadata, - absl::AnyInvocable< - void(absl::StatusOr>) &&> + absl::AnyInvocable>)&&> on_done, absl::Duration timeout) { EXPECT_EQ(score_ads_request->auction_signals(), @@ -215,9 +215,9 @@ TYPED_TEST(SelectAuctionResultReactorTest, std::unique_ptr score_ads_request, const RequestMetadata& metadata, - absl::AnyInvocable< - void(absl::StatusOr>) &&> + absl::AnyInvocable>)&&> on_done, absl::Duration timeout) { auto response = @@ -248,18 +248,18 @@ TYPED_TEST(SelectAuctionResultReactorTest, this->SetupComponentAuctionResults(2); EXPECT_CALL(this->scoring_client_, ExecuteInternal) .Times(1) - .WillOnce([&scoring_done]( - std::unique_ptr - score_ads_request, - const RequestMetadata& metadata, - absl::AnyInvocable< - void(absl::StatusOr>) &&> - on_done, - absl::Duration timeout) { - scoring_done.Notify(); - return absl::Status(absl::StatusCode::kInternal, "test msg"); - }); + .WillOnce( + [&scoring_done](std::unique_ptr + score_ads_request, + const RequestMetadata& metadata, + absl::AnyInvocable>)&&> + on_done, + absl::Duration timeout) { + scoring_done.Notify(); + return absl::Status(absl::StatusCode::kInternal, "test msg"); + }); ClientRegistry clients = { MockAsyncProvider(), this->scoring_client_, @@ -301,20 +301,20 @@ TYPED_TEST(SelectAuctionResultReactorTest, this->SetupComponentAuctionResults(2); EXPECT_CALL(this->scoring_client_, ExecuteInternal) .Times(1) - .WillOnce([&scoring_done]( - std::unique_ptr - score_ads_request, - const RequestMetadata& metadata, - absl::AnyInvocable< - void(absl::StatusOr>) &&> - on_done, - absl::Duration timeout) { - std::move(on_done)( - absl::Status(absl::StatusCode::kInvalidArgument, "test msg")); - scoring_done.Notify(); - return absl::OkStatus(); - }); + .WillOnce( + [&scoring_done](std::unique_ptr + score_ads_request, + const RequestMetadata& metadata, + absl::AnyInvocable>)&&> + on_done, + absl::Duration timeout) { + std::move(on_done)( + absl::Status(absl::StatusCode::kInvalidArgument, "test msg")); + scoring_done.Notify(); + return absl::OkStatus(); + }); ClientRegistry clients = { MockAsyncProvider(), this->scoring_client_, @@ -334,20 +334,20 @@ TYPED_TEST(SelectAuctionResultReactorTest, this->SetupComponentAuctionResults(2); EXPECT_CALL(this->scoring_client_, ExecuteInternal) .Times(1) - .WillOnce([&scoring_done]( - std::unique_ptr - score_ads_request, - const RequestMetadata& metadata, - absl::AnyInvocable< - void(absl::StatusOr>) &&> - on_done, - absl::Duration timeout) { - std::move(on_done)( - absl::Status(absl::StatusCode::kInternal, "test msg")); - scoring_done.Notify(); - return absl::OkStatus(); - }); + .WillOnce( + [&scoring_done](std::unique_ptr + score_ads_request, + const RequestMetadata& metadata, + absl::AnyInvocable>)&&> + on_done, + absl::Duration timeout) { + std::move(on_done)( + absl::Status(absl::StatusCode::kInternal, "test msg")); + scoring_done.Notify(); + return absl::OkStatus(); + }); ClientRegistry clients = { MockAsyncProvider(), this->scoring_client_, diff --git a/services/seller_frontend_service/seller_frontend_main.cc b/services/seller_frontend_service/seller_frontend_main.cc index 479430c5..1208c95d 100644 --- a/services/seller_frontend_service/seller_frontend_main.cc +++ b/services/seller_frontend_service/seller_frontend_main.cc @@ -35,6 +35,7 @@ #include "services/common/encryption/crypto_client_factory.h" #include "services/common/encryption/key_fetcher_factory.h" #include "services/common/telemetry/configure_telemetry.h" +#include "services/common/util/tcmalloc_utils.h" #include "services/seller_frontend_service/runtime_flags.h" #include "services/seller_frontend_service/seller_frontend_service.h" #include "services/seller_frontend_service/util/key_fetcher_utils.h" @@ -91,6 +92,14 @@ ABSL_FLAG(std::optional, sfe_public_keys_endpoints, std::nullopt, ABSL_FLAG(std::optional, seller_cloud_platforms_map, std::nullopt, "Seller partner cloud platforms. Can be empty." "Enables requests to the getComponentAuctionCiphertexts RPC."); +ABSL_FLAG(std::optional, + sfe_tcmalloc_background_release_rate_bytes_per_second, std::nullopt, + "Amount of cached memory in bytes that is returned back to the " + "system per second"); +ABSL_FLAG(std::optional, sfe_tcmalloc_max_total_thread_cache_bytes, + std::nullopt, + "Maximum amount of cached memory in bytes across all threads (or " + "logical CPUs)"); namespace privacy_sandbox::bidding_auction_servers { @@ -163,7 +172,11 @@ absl::StatusOr GetConfigClient( config_client.SetFlag(FLAGS_ps_verbosity, PS_VERBOSITY); config_client.SetFlag(FLAGS_seller_cloud_platforms_map, SELLER_CLOUD_PLATFORMS_MAP); - + config_client.SetFlag( + FLAGS_sfe_tcmalloc_background_release_rate_bytes_per_second, + SFE_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND); + config_client.SetFlag(FLAGS_sfe_tcmalloc_max_total_thread_cache_bytes, + SFE_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES); if (absl::GetFlag(FLAGS_init_config_client)) { PS_RETURN_IF_ERROR(config_client.Init(config_param_prefix)).LogError() << "Config client failed to initialize."; @@ -194,6 +207,11 @@ absl::Status RunServer() { PS_ASSIGN_OR_RETURN(TrustedServersConfigClient config_client, GetConfigClient(config_util.GetConfigParameterPrefix())); + MaySetBackgroundReleaseRate(config_client.GetInt64Parameter( + SFE_TCMALLOC_BACKGROUND_RELEASE_RATE_BYTES_PER_SECOND)); + MaySetMaxTotalThreadCacheBytes(config_client.GetInt64Parameter( + SFE_TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES)); + InitTelemetry( config_util, config_client, metric::kSfe, FetchIgOwnerList(ParseIgOwnerToBfeDomainMap( diff --git a/services/seller_frontend_service/util/BUILD b/services/seller_frontend_service/util/BUILD index 51ba2022..4dd08a26 100644 --- a/services/seller_frontend_service/util/BUILD +++ b/services/seller_frontend_service/util/BUILD @@ -190,6 +190,7 @@ cc_library( "//api:bidding_auction_servers_cc_proto", "//services/common/encryption:key_fetcher_factory", "//services/common/util:oblivious_http_utils", + "//services/common/util:request_response_constants", "@com_google_absl//absl/status", "@google_privacysandbox_servers_common//src/communication:ohttp_utils", "@google_privacysandbox_servers_common//src/encryption/key_fetcher:key_fetcher_manager", diff --git a/services/seller_frontend_service/util/encryption_util.cc b/services/seller_frontend_service/util/encryption_util.cc index 283095eb..236f912e 100644 --- a/services/seller_frontend_service/util/encryption_util.cc +++ b/services/seller_frontend_service/util/encryption_util.cc @@ -20,6 +20,7 @@ #include "absl/strings/escaping.h" #include "services/common/util/oblivious_http_utils.h" +#include "services/common/util/request_response_constants.h" #include "src/include/openssl/hpke.h" namespace privacy_sandbox::bidding_auction_servers { @@ -32,8 +33,8 @@ DecryptOHTTPEncapsulatedHpkeCiphertext( parsed_encapsulated_request = server_common::ParseEncapsulatedRequest(ciphertext); if (!parsed_encapsulated_request.ok()) { - PS_VLOG(2) << "Error while parsing encapsulated ciphertext: " - << parsed_encapsulated_request.status(); + PS_VLOG(kNoisyWarn) << "Error while parsing encapsulated ciphertext: " + << parsed_encapsulated_request.status(); return absl::Status( absl::StatusCode::kInvalidArgument, absl::StrCat("Error while parsing encapsulated ciphertext: ", @@ -45,7 +46,8 @@ DecryptOHTTPEncapsulatedHpkeCiphertext( ParseKeyIdFromObliviousHttpRequestPayload( parsed_encapsulated_request->request_payload); if (!key_id.ok()) { - PS_VLOG(2) << "Parsed key id error status: " << key_id.status().message(); + PS_VLOG(kNoisyWarn) << "Parsed key id error status: " + << key_id.status().message(); return absl::Status(absl::StatusCode::kInvalidArgument, kInvalidOhttpKeyIdError); } @@ -56,7 +58,8 @@ DecryptOHTTPEncapsulatedHpkeCiphertext( key_fetcher_manager.GetPrivateKey(str_key_id); if (!private_key.has_value()) { - PS_VLOG(2) << "Unable to retrieve private key for key ID: " << str_key_id; + PS_VLOG(kNoisyWarn) << "Unable to retrieve private key for key ID: " + << str_key_id; return absl::Status(absl::StatusCode::kNotFound, absl::StrFormat(kMissingPrivateKey, str_key_id)); } @@ -68,8 +71,8 @@ DecryptOHTTPEncapsulatedHpkeCiphertext( server_common::DecryptEncapsulatedRequest(*private_key, *parsed_encapsulated_request); if (!ohttp_request.ok()) { - PS_VLOG(2) << "Unable to decrypt the ciphertext. Reason: " - << ohttp_request.status().message(); + PS_VLOG(kNoisyWarn) << "Unable to decrypt the ciphertext. Reason: " + << ohttp_request.status().message(); return absl::Status(absl::StatusCode::kInvalidArgument, absl::StrFormat(kMalformedEncapsulatedRequest, ohttp_request.status().message())); diff --git a/services/seller_frontend_service/util/proto_mapping_util.cc b/services/seller_frontend_service/util/proto_mapping_util.cc index b238986a..3af0f108 100644 --- a/services/seller_frontend_service/util/proto_mapping_util.cc +++ b/services/seller_frontend_service/util/proto_mapping_util.cc @@ -120,7 +120,7 @@ absl::StatusOr PackageAuctionResultForWeb( error_msg = status.error_message(); wait_for_error_callback.Notify(); }; - PS_VLOG(2, log_context) + PS_VLOG(kNoisyInfo, log_context) << "IG bids map size:" << (maybe_bidding_group_map.has_value() ? absl::StrCat("found: ", maybe_bidding_group_map->size()) @@ -297,15 +297,15 @@ IgsWithBidsMap GetBuyerIgsWithBidsMap( IgsWithBidsMap buyer_to_ig_idx_map; for (IgsWithBidsMap& component_auction_ig_group : component_auction_bidding_groups) { - PS_VLOG(kInfoMsg) << "Size of input buyer bids map " - << component_auction_ig_group.size(); + PS_VLOG(kNoisyInfo) << "Size of input buyer bids map " + << component_auction_ig_group.size(); for (auto& [buyer, ig_idx] : component_auction_ig_group) { // Check if the key already exists in the output map const auto& it = buyer_to_ig_idx_map.find(buyer); if (it == buyer_to_ig_idx_map.end()) { // Insert the entire entry buyer_to_ig_idx_map.insert({buyer, std::move(ig_idx)}); - PS_VLOG(kInfoMsg) << "Inserted for " << buyer; + PS_VLOG(kNoisyInfo) << "Inserted for " << buyer; continue; } else if (auto buyer_ig_set = colliding_buyer_sets.find(buyer); buyer_ig_set == colliding_buyer_sets.end()) { @@ -313,13 +313,13 @@ IgsWithBidsMap GetBuyerIgsWithBidsMap( // Add values from previous CARs. absl::flat_hash_set ig_set(it->second.index().begin(), it->second.index().end()); - PS_VLOG(kInfoMsg) << "Inserted in colliding for" << buyer - << ig_set.size(); + PS_VLOG(kNoisyInfo) + << "Inserted in colliding for" << buyer << ig_set.size(); colliding_buyer_sets.insert({buyer, std::move(ig_set)}); } // Already in colliding buyer set. Add all values from current CAR. - PS_VLOG(kInfoMsg) << "Inserted in colliding for" << buyer - << ig_idx.index().size(); + PS_VLOG(kNoisyInfo) << "Inserted in colliding for" << buyer + << ig_idx.index().size(); colliding_buyer_sets.at(buyer).insert(ig_idx.index().begin(), ig_idx.index().end()); } @@ -330,8 +330,8 @@ IgsWithBidsMap GetBuyerIgsWithBidsMap( buyer_to_ig_idx_map.at(buyer).mutable_index()->Assign(ig_idx_set.begin(), ig_idx_set.end()); } - PS_VLOG(kInfoMsg) << "Size of output buyer bids map " - << buyer_to_ig_idx_map.size(); + PS_VLOG(kNoisyInfo) << "Size of output buyer bids map " + << buyer_to_ig_idx_map.size(); return buyer_to_ig_idx_map; } @@ -350,7 +350,7 @@ absl::StatusOr UnpackageServerAuctionComponentResult( PS_ASSIGN_OR_RETURN(std::string payload, GzipDecompress(decoded_request.compressed_data)); - PS_VLOG(2) << "Parsing Auction Result: " << payload; + PS_VLOG(kNoisyInfo) << "Parsing Auction Result: " << payload; if (!proto.ParseFromArray(payload.data(), payload.size())) { return absl::Status(absl::StatusCode::kInvalidArgument, kBadBinaryProto); } @@ -374,7 +374,7 @@ std::vector DecryptAndValidateComponentAuctionResults( std::string error_msg = absl::StrFormat(kErrorDecryptingAuctionResultError, auction_result.status().message()); - PS_VLOG(2, log_context) << error_msg; + PS_VLOG(kNoisyWarn, log_context) << error_msg; // Report error. This will be later returned to client in case // none of the auction results could be decoded. error_accumulator.ReportError(ErrorVisibility::AD_SERVER_VISIBLE, @@ -382,10 +382,10 @@ std::vector DecryptAndValidateComponentAuctionResults( ErrorCode::CLIENT_SIDE); continue; } - PS_VLOG(2, log_context) + PS_VLOG(kSuccess, log_context) << "Successfully decrypted auction result ciphertext for: " << auction_result->auction_params().component_seller(); - PS_VLOG(kInfoMsg, log_context) + PS_VLOG(kNoisyInfo, log_context) << "Bidding group size: " << auction_result->bidding_groups().size(); // Add errors from AuctionResult to error_accumulator in // ValidateComponentAuctionResult. @@ -412,7 +412,7 @@ std::vector DecryptAndValidateComponentAuctionResults( // Return empty vector to abort auction. return std::vector(); } - PS_VLOG(2, log_context) + PS_VLOG(kSuccess, log_context) << "Successfully validated auction result for: " << auction_result->auction_params().component_seller(); component_auction_results.push_back(*std::move(auction_result)); @@ -439,7 +439,8 @@ ProtectedAudienceInput DecryptProtectedAudienceInput( default: break; } - PS_VLOG(2) << "Successfully decrypted protected audience input ciphertext"; + PS_VLOG(kSuccess) + << "Successfully decrypted protected audience input ciphertext"; return protected_auction_input; } @@ -462,7 +463,8 @@ ProtectedAuctionInput DecryptProtectedAuctionInput( default: break; } - PS_VLOG(2) << "Successfully decrypted protected audience input ciphertext"; + PS_VLOG(kSuccess) + << "Successfully decrypted protected audience input ciphertext"; return protected_auction_input; } diff --git a/services/seller_frontend_service/util/proto_mapping_util_test.cc b/services/seller_frontend_service/util/proto_mapping_util_test.cc index d705189a..73e46daf 100644 --- a/services/seller_frontend_service/util/proto_mapping_util_test.cc +++ b/services/seller_frontend_service/util/proto_mapping_util_test.cc @@ -437,9 +437,6 @@ TEST_F(CreateAuctionResultCiphertextTest, ConvertsAdScoreForAndroid) { TEST_F(CreateAuctionResultCiphertextTest, ConvertsAdScoreForWeb) { AuctionResult expected = MapBasicScoreFieldsToAuctionResult(this->valid_score_); - // bid val is only for component and auction and will not be parsed or encoded - // for single seller auction. - expected.clear_bid(); // IG Origin is Android exclusive and will not be parsed or encoded for web. expected.clear_interest_group_origin(); expected.mutable_bidding_groups()->insert(this->bidding_group_map_.begin(), diff --git a/services/seller_frontend_service/util/web_utils.cc b/services/seller_frontend_service/util/web_utils.cc index 9e4b2b02..29838f4f 100644 --- a/services/seller_frontend_service/util/web_utils.cc +++ b/services/seller_frontend_service/util/web_utils.cc @@ -310,6 +310,8 @@ absl::Status CborSerializeScoreAdResponse( const ScoreAdsResponse::AdScore& ad_score, const BiddingGroupMap& bidding_group_map, ErrorHandler error_handler, cbor_item_t& root) { + PS_RETURN_IF_ERROR( + CborSerializeFloat(kBid, ad_score.buyer_bid(), error_handler, root)); PS_RETURN_IF_ERROR( CborSerializeFloat(kScore, ad_score.desirability(), error_handler, root)); PS_RETURN_IF_ERROR(CborSerializeBool(kChaff, false, error_handler, root)); diff --git a/services/seller_frontend_service/util/web_utils_test.cc b/services/seller_frontend_service/util/web_utils_test.cc index a2642ab8..8623fa03 100644 --- a/services/seller_frontend_service/util/web_utils_test.cc +++ b/services/seller_frontend_service/util/web_utils_test.cc @@ -745,9 +745,8 @@ TEST(ChromeResponseUtils, VerifyCborEncodingWithWinReportingUrls) { // Verify that the decoded result has the winning ad correctly set. EXPECT_EQ(decoded_result->ad_render_url(), ad_render_url); - // The modified bid should not be set unless we have a component auction. - EXPECT_TRUE(AreFloatsEqual(decoded_result->bid(), 0.0f)) - << " Actual: " << decoded_result->bid() << ", Expected: " << 0.0f; + EXPECT_TRUE(AreFloatsEqual(decoded_result->bid(), buyer_bid)) + << " Actual: " << decoded_result->bid() << ", Expected: " << buyer_bid; EXPECT_TRUE(AreFloatsEqual(decoded_result->score(), desirability)) << " Actual: " << decoded_result->score() << ", Expected: " << desirability; @@ -825,9 +824,8 @@ TEST(ChromeResponseUtils, VerifyCborEncoding) { // Verify that the decoded result has the winning ad correctly set. EXPECT_EQ(decoded_result->ad_render_url(), ad_render_url); - // Modified bid should not have been set at all. - EXPECT_TRUE(AreFloatsEqual(decoded_result->bid(), 0.0f)) - << " Actual: " << decoded_result->bid() << ", Expected: " << 0.0f; + EXPECT_TRUE(AreFloatsEqual(decoded_result->bid(), buyer_bid)) + << " Actual: " << decoded_result->bid() << ", Expected: " << buyer_bid; EXPECT_TRUE(AreFloatsEqual(decoded_result->score(), desirability)) << " Actual: " << decoded_result->score() << ", Expected: " << desirability; @@ -1187,17 +1185,18 @@ TEST(ChromeResponseUtils, VerifyMinimalResponseEncoding) { // Conversion can be verified at: https://cbor.me/ EXPECT_EQ( absl::BytesToHexString(*ret), - "a86573636f7265fa4818fff26769734368616666f46a636f6d706f6e656e7473806b6164" - "52656e64657255524c606d62696464696e6747726f757073a4627a698207026369673182" - "070263696831820702666f776e6572318207027077696e5265706f7274696e6755524c73" - "a27262757965725265706f7274696e6755524c73a26c7265706f7274696e6755524c7468" - "7474703a2f2f7265706f727457696e2e636f6d7818696e746572616374696f6e5265706f" - "7274696e6755524c73a165636c69636b70687474703a2f2f636c69636b2e636f6d781b74" - "6f704c6576656c53656c6c65725265706f7274696e6755524c73a26c7265706f7274696e" - "6755524c77687474703a2f2f7265706f7274526573756c742e636f6d7818696e74657261" + "a963626964fa3e488a0d6573636f7265fa4818fff26769734368616666f46a636f6d706f" + "6e656e7473806b616452656e64657255524c606d62696464696e6747726f757073a4627a" + "698207026369673182070263696831820702666f776e6572318207027077696e5265706f" + "7274696e6755524c73a27262757965725265706f7274696e6755524c73a26c7265706f72" + "74696e6755524c74687474703a2f2f7265706f727457696e2e636f6d7818696e74657261" "6374696f6e5265706f7274696e6755524c73a165636c69636b70687474703a2f2f636c69" - "636b2e636f6d71696e74657265737447726f75704e616d656369673172696e7465726573" - "7447726f75704f776e65727268747470733a2f2f6164746563682e636f6d"); + "636b2e636f6d781b746f704c6576656c53656c6c65725265706f7274696e6755524c73a2" + "6c7265706f7274696e6755524c77687474703a2f2f7265706f7274526573756c742e636f" + "6d7818696e746572616374696f6e5265706f7274696e6755524c73a165636c69636b7068" + "7474703a2f2f636c69636b2e636f6d71696e74657265737447726f75704e616d65636967" + "3172696e74657265737447726f75704f776e65727268747470733a2f2f6164746563682e" + "636f6d"); } TEST(ChromeResponseUtils, VerifyMinimalComponentResponseEncoding) { @@ -1322,8 +1321,6 @@ TEST(ChromeResponseUtils, VerifyMinimalEncodingWithBuyerReportingId) { winner.set_interest_group_owner("https://adtech.com"); winner.set_interest_group_name("ig1"); winner.set_desirability(156671.781); - // Should accomplish nothing as bid should not be included in the response for - // non-component auction. winner.set_buyer_bid(0.195839122); winner.mutable_win_reporting_urls() ->mutable_buyer_reporting_urls() @@ -1357,21 +1354,21 @@ TEST(ChromeResponseUtils, VerifyMinimalEncodingWithBuyerReportingId) { [](auto error) {}); ASSERT_TRUE(ret.ok()) << ret.status(); // Conversion can be verified at: https://cbor.me/ - EXPECT_EQ(absl::BytesToHexString(*ret), - "a96573636f7265fa4818fff26769734368616666f46a636f6d706f6e656e747" - "3806b616452656e64657255524c606d62696464696e6747726f757073a4627a6" - "98207026369673182070263696831820702666f776e657231820702706275796" - "5725265706f7274696e674964747465737442757965725265706f7274696e674" - "9647077696e5265706f7274696e6755524c73a27262757965725265706f72746" - "96e6755524c73a26c7265706f7274696e6755524c74687474703a2f2f7265706" - "f727457696e2e636f6d7818696e746572616374696f6e5265706f7274696e675" - "5524c73a165636c69636b70687474703a2f2f636c69636b2e636f6d781b746f7" - "04c6576656c53656c6c65725265706f7274696e6755524c73a26c7265706f727" - "4696e6755524c77687474703a2f2f7265706f7274526573756c742e636f6d781" - "8696e746572616374696f6e5265706f7274696e6755524c73a165636c69636b7" - "0687474703a2f2f636c69636b2e636f6d71696e74657265737447726f75704e6" - "16d656369673172696e74657265737447726f75704f776e65727268747470733" - "a2f2f6164746563682e636f6d"); + EXPECT_EQ( + absl::BytesToHexString(*ret), + "aa63626964fa3e488a0d6573636f7265fa4818fff26769734368616666f46a636f6d706f" + "6e656e7473806b616452656e64657255524c606d62696464696e6747726f757073a4627a" + "698207026369673182070263696831820702666f776e6572318207027062757965725265" + "706f7274696e674964747465737442757965725265706f7274696e6749647077696e5265" + "706f7274696e6755524c73a27262757965725265706f7274696e6755524c73a26c726570" + "6f7274696e6755524c74687474703a2f2f7265706f727457696e2e636f6d7818696e7465" + "72616374696f6e5265706f7274696e6755524c73a165636c69636b70687474703a2f2f63" + "6c69636b2e636f6d781b746f704c6576656c53656c6c65725265706f7274696e6755524c" + "73a26c7265706f7274696e6755524c77687474703a2f2f7265706f7274526573756c742e" + "636f6d7818696e746572616374696f6e5265706f7274696e6755524c73a165636c69636b" + "70687474703a2f2f636c69636b2e636f6d71696e74657265737447726f75704e616d6563" + "69673172696e74657265737447726f75704f776e65727268747470733a2f2f6164746563" + "682e636f6d"); } MATCHER_P(ProtoEq, value, "") { diff --git a/third_party/libevent-evconfig.patch b/third_party/libevent-evconfig.patch new file mode 100644 index 00000000..1382fabd --- /dev/null +++ b/third_party/libevent-evconfig.patch @@ -0,0 +1,64 @@ +diff --git a/evconfig-private.h b/evconfig-private.h +new file mode 100644 +index 0000000..31e6100 +--- /dev/null ++++ b/evconfig-private.h +@@ -0,0 +1,56 @@ ++/* evconfig-private.h. Generated from evconfig-private.h.in by configure. */ ++/* evconfig-private.h template - see "Configuration Header Templates" */ ++/* in AC manual. Kevin Bowling +Date: Mon, 29 Apr 2024 21:00:34 +0000 +Subject: [PATCH] patch + +--- + evconfig-private.h | 56 ++++ + event2/event-config.h | 630 ++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 686 insertions(+) + create mode 100644 evconfig-private.h + create mode 100644 event2/event-config.h + +diff --git a/evconfig-private.h b/evconfig-private.h +new file mode 100644 +index 0000000..31e6100 +--- /dev/null ++++ b/evconfig-private.h +@@ -0,0 +1,56 @@ ++/* evconfig-private.h. Generated from evconfig-private.h.in by configure. */ ++/* evconfig-private.h template - see "Configuration Header Templates" */ ++/* in AC manual. Kevin Bowling header file. */ ++/* #undef EVENT__HAVE_AFUNIX_H */ ++ ++/* Define to 1 if you have the `arc4random' function. */ ++/* #define EVENT__HAVE_ARC4RANDOM 1 ++ ++/* Define to 1 if you have the `arc4random_addrandom' function. */ ++/* #undef EVENT__HAVE_ARC4RANDOM_ADDRANDOM */ ++ ++/* Define to 1 if you have the `arc4random_buf' function. */ ++#define EVENT__HAVE_ARC4RANDOM_BUF 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_ARPA_INET_H 1 ++ ++/* Define to 1 if you have the `clock_gettime' function. */ ++#define EVENT__HAVE_CLOCK_GETTIME 1 ++ ++/* Define to 1 if you have the declaration of `CTL_KERN', and to 0 if you ++ don't. */ ++/* #undef EVENT__HAVE_DECL_CTL_KERN */ ++ ++/* Define to 1 if you have the declaration of `KERN_ARND', and to 0 if you ++ don't. */ ++/* #undef EVENT__HAVE_DECL_KERN_ARND */ ++ ++/* Define if /dev/poll is available */ ++/* #undef EVENT__HAVE_DEVPOLL */ ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_DLFCN_H 1 ++ ++/* Define if your system supports the epoll system calls */ ++#define EVENT__HAVE_EPOLL 1 ++ ++/* Define to 1 if you have the `epoll_create1' function. */ ++#define EVENT__HAVE_EPOLL_CREATE1 1 ++ ++/* Define to 1 if you have the `epoll_ctl' function. */ ++#define EVENT__HAVE_EPOLL_CTL 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_ERRNO_H 1 ++ ++/* Define to 1 if you have the `eventfd' function. */ ++#define EVENT__HAVE_EVENTFD 1 ++ ++/* Define if your system supports event ports */ ++/* #undef EVENT__HAVE_EVENT_PORTS */ ++ ++/* Define to 1 if you have the `fcntl' function. */ ++#define EVENT__HAVE_FCNTL 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_FCNTL_H 1 ++ ++/* Define to 1 if the system has the type `fd_mask'. */ ++#define EVENT__HAVE_FD_MASK 1 ++ ++/* Do we have getaddrinfo()? */ ++#define EVENT__HAVE_GETADDRINFO 1 ++ ++/* Define to 1 if you have the `getegid' function. */ ++#define EVENT__HAVE_GETEGID 1 ++ ++/* Define to 1 if you have the `geteuid' function. */ ++#define EVENT__HAVE_GETEUID 1 ++ ++/* Define this if you have any gethostbyname_r() */ ++/* #undef EVENT__HAVE_GETHOSTBYNAME_R */ ++ ++/* Define this if gethostbyname_r takes 3 arguments */ ++/* #undef EVENT__HAVE_GETHOSTBYNAME_R_3_ARG */ ++ ++/* Define this if gethostbyname_r takes 5 arguments */ ++/* #undef EVENT__HAVE_GETHOSTBYNAME_R_5_ARG */ ++ ++/* Define this if gethostbyname_r takes 6 arguments */ ++/* #undef EVENT__HAVE_GETHOSTBYNAME_R_6_ARG */ ++ ++/* Define to 1 if you have the `getifaddrs' function. */ ++#define EVENT__HAVE_GETIFADDRS 1 ++ ++/* Define to 1 if you have the `getnameinfo' function. */ ++#define EVENT__HAVE_GETNAMEINFO 1 ++ ++/* Define to 1 if you have the `getprotobynumber' function. */ ++#define EVENT__HAVE_GETPROTOBYNUMBER 1 ++ ++/* Define to 1 if you have the `getrandom' function. */ ++#define EVENT__HAVE_GETRANDOM 1 ++ ++/* Define to 1 if you have the `getservbyname' function. */ ++#define EVENT__HAVE_GETSERVBYNAME 1 ++ ++/* Define to 1 if you have the `gettimeofday' function. */ ++#define EVENT__HAVE_GETTIMEOFDAY 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_IFADDRS_H 1 ++ ++/* Define to 1 if you have the `inet_ntop' function. */ ++#define EVENT__HAVE_INET_NTOP 1 ++ ++/* Define to 1 if you have the `inet_pton' function. */ ++#define EVENT__HAVE_INET_PTON 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_INTTYPES_H 1 ++ ++/* Define to 1 if you have the `issetugid' function. */ ++/* #undef EVENT__HAVE_ISSETUGID */ ++ ++/* Define to 1 if you have the `kqueue' function. */ ++/* #undef EVENT__HAVE_KQUEUE */ ++ ++/* Define to 1 if you have the `ws2_32' library (-lws2_32). */ ++/* #undef EVENT__HAVE_LIBWS2_32 */ ++ ++/* Define if the system has zlib */ ++#define EVENT__HAVE_LIBZ 1 ++ ++/* Define to 1 if you have the `mach_absolute_time' function. */ ++/* #undef EVENT__HAVE_MACH_ABSOLUTE_TIME */ ++ ++/* Define to 1 if you have the header file. */ ++/* #undef EVENT__HAVE_MACH_MACH_H */ ++ ++/* Define to 1 if you have the header file. */ ++/* #undef EVENT__HAVE_MACH_MACH_TIME_H */ ++ ++/* Define to 1 if you have the header file. */ ++/* #undef EVENT__HAVE_MINIX_CONFIG_H */ ++ ++/* Define to 1 if you have the `mmap' function. */ ++#define EVENT__HAVE_MMAP 1 ++ ++/* Define to 1 if you have the `nanosleep' function. */ ++#define EVENT__HAVE_NANOSLEEP 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_NETDB_H 1 ++ ++/* Define to 1 if you have the header file. */ ++/* #undef EVENT__HAVE_NETINET_IN6_H */ ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_NETINET_IN_H 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_NETINET_TCP_H 1 ++ ++/* Define if the system has openssl */ ++#define EVENT__HAVE_OPENSSL 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_OPENSSL_SSL_H 1 ++ ++/* Define to 1 if you have the `pipe' function. */ ++#define EVENT__HAVE_PIPE 1 ++ ++/* Define to 1 if you have the `pipe2' function. */ ++#define EVENT__HAVE_PIPE2 1 ++ ++/* Define to 1 if you have the `poll' function. */ ++#define EVENT__HAVE_POLL 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_POLL_H 1 ++ ++/* Define to 1 if you have the `port_create' function. */ ++/* #undef EVENT__HAVE_PORT_CREATE */ ++ ++/* Define to 1 if you have the header file. */ ++/* #undef EVENT__HAVE_PORT_H */ ++ ++/* Define if you have POSIX threads libraries and header files. */ ++/* #undef EVENT__HAVE_PTHREAD */ ++ ++/* Define if we have pthreads on this system */ ++#define EVENT__HAVE_PTHREADS 1 ++ ++/* Define to 1 if you have the `putenv' function. */ ++#define EVENT__HAVE_PUTENV 1 ++ ++/* Define to 1 if the system has the type `sa_family_t'. */ ++#define EVENT__HAVE_SA_FAMILY_T 1 ++ ++/* Define to 1 if you have the `select' function. */ ++#define EVENT__HAVE_SELECT 1 ++ ++/* Define to 1 if you have the `sendfile' function. */ ++#define EVENT__HAVE_SENDFILE 1 ++ ++/* Define to 1 if you have the `setenv' function. */ ++#define EVENT__HAVE_SETENV 1 ++ ++/* Define if F_SETFD is defined in */ ++#define EVENT__HAVE_SETFD 1 ++ ++/* Define to 1 if you have the `setrlimit' function. */ ++#define EVENT__HAVE_SETRLIMIT 1 ++ ++/* Define to 1 if you have the `sigaction' function. */ ++#define EVENT__HAVE_SIGACTION 1 ++ ++/* Define to 1 if you have the `signal' function. */ ++#define EVENT__HAVE_SIGNAL 1 ++ ++/* Define to 1 if you have the `splice' function. */ ++#define EVENT__HAVE_SPLICE 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_STDARG_H 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_STDDEF_H 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_STDINT_H 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_STDIO_H 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_STDLIB_H 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_STRINGS_H 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_STRING_H 1 ++ ++/* Define to 1 if you have the `strlcpy' function. */ ++/* #undef EVENT__HAVE_STRLCPY */ ++ ++/* Define to 1 if you have the `strsep' function. */ ++#define EVENT__HAVE_STRSEP 1 ++ ++/* Define to 1 if you have the `strtok_r' function. */ ++#define EVENT__HAVE_STRTOK_R 1 ++ ++/* Define to 1 if you have the `strtoll' function. */ ++#define EVENT__HAVE_STRTOLL 1 ++ ++/* Define to 1 if the system has the type `struct addrinfo'. */ ++#define EVENT__HAVE_STRUCT_ADDRINFO 1 ++ ++/* Define to 1 if the system has the type `struct in6_addr'. */ ++#define EVENT__HAVE_STRUCT_IN6_ADDR 1 ++ ++/* Define to 1 if `s6_addr16' is a member of `struct in6_addr'. */ ++#define EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR16 1 ++ ++/* Define to 1 if `s6_addr32' is a member of `struct in6_addr'. */ ++#define EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR32 1 ++ ++/* Define to 1 if the system has the type `struct linger'. */ ++#define EVENT__HAVE_STRUCT_LINGER 1 ++ ++/* Define to 1 if the system has the type `struct sockaddr_in6'. */ ++#define EVENT__HAVE_STRUCT_SOCKADDR_IN6 1 ++ ++/* Define to 1 if `sin6_len' is a member of `struct sockaddr_in6'. */ ++/* #undef EVENT__HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN */ ++ ++/* Define to 1 if `sin_len' is a member of `struct sockaddr_in'. */ ++/* #undef EVENT__HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ ++ ++/* Define to 1 if the system has the type `struct sockaddr_storage'. */ ++#define EVENT__HAVE_STRUCT_SOCKADDR_STORAGE 1 ++ ++/* Define to 1 if `ss_family' is a member of `struct sockaddr_storage'. */ ++#define EVENT__HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY 1 ++ ++/* Define to 1 if `__ss_family' is a member of `struct sockaddr_storage'. */ ++/* #undef EVENT__HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY */ ++ ++/* Define to 1 if the system has the type `struct sockaddr_un'. */ ++#define EVENT__HAVE_STRUCT_SOCKADDR_UN 1 ++ ++/* Define to 1 if you have the `sysctl' function. */ ++/* #undef EVENT__HAVE_SYSCTL */ ++ ++/* Define to 1 if you have the header file. */ ++/* #undef EVENT__HAVE_SYS_DEVPOLL_H */ ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_SYS_EPOLL_H 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_SYS_EVENTFD_H 1 ++ ++/* Define to 1 if you have the header file. */ ++/* #undef EVENT__HAVE_SYS_EVENT_H */ ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_SYS_IOCTL_H 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_SYS_MMAN_H 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_SYS_PARAM_H 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_SYS_QUEUE_H 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_SYS_RANDOM_H 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_SYS_RESOURCE_H 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_SYS_SELECT_H 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_SYS_SENDFILE_H 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_SYS_SOCKET_H 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_SYS_STAT_H 1 ++ ++/* Define to 1 if you have the header file. */ ++/* #undef EVENT__HAVE_SYS_SYSCTL_H */ ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_SYS_TIMERFD_H 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_SYS_TIME_H 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_SYS_TYPES_H 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_SYS_UIO_H 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_SYS_UN_H 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_SYS_WAIT_H 1 ++ ++/* Define if TAILQ_FOREACH is defined in */ ++#define EVENT__HAVE_TAILQFOREACH 1 ++ ++/* Define if timeradd is defined in */ ++#define EVENT__HAVE_TIMERADD 1 ++ ++/* Define if timerclear is defined in */ ++#define EVENT__HAVE_TIMERCLEAR 1 ++ ++/* Define if timercmp is defined in */ ++#define EVENT__HAVE_TIMERCMP 1 ++ ++/* Define to 1 if you have the `timerfd_create' function. */ ++#define EVENT__HAVE_TIMERFD_CREATE 1 ++ ++/* Define if timerisset is defined in */ ++#define EVENT__HAVE_TIMERISSET 1 ++ ++/* Define to 1 if the system has the type `uint16_t'. */ ++#define EVENT__HAVE_UINT16_T 1 ++ ++/* Define to 1 if the system has the type `uint32_t'. */ ++#define EVENT__HAVE_UINT32_T 1 ++ ++/* Define to 1 if the system has the type `uint64_t'. */ ++#define EVENT__HAVE_UINT64_T 1 ++ ++/* Define to 1 if the system has the type `uint8_t'. */ ++#define EVENT__HAVE_UINT8_T 1 ++ ++/* Define to 1 if the system has the type `uintptr_t'. */ ++#define EVENT__HAVE_UINTPTR_T 1 ++ ++/* Define to 1 if you have the `umask' function. */ ++#define EVENT__HAVE_UMASK 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_UNISTD_H 1 ++ ++/* Define to 1 if you have the `unsetenv' function. */ ++#define EVENT__HAVE_UNSETENV 1 ++ ++/* Define to 1 if you have the `usleep' function. */ ++#define EVENT__HAVE_USLEEP 1 ++ ++/* Define to 1 if you have the `vasprintf' function. */ ++#define EVENT__HAVE_VASPRINTF 1 ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_WCHAR_H 1 ++ ++/* Define if kqueue works correctly with pipes */ ++/* #undef EVENT__HAVE_WORKING_KQUEUE */ ++ ++/* Define to 1 if you have the header file. */ ++#define EVENT__HAVE_ZLIB_H 1 ++ ++/* Define to 1 if you have the `_gmtime64' function. */ ++/* #undef EVENT__HAVE__GMTIME64 */ ++ ++/* Define to 1 if you have the `_gmtime64_s' function. */ ++/* #undef EVENT__HAVE__GMTIME64_S */ ++ ++/* Define to 1 if compiler have __FUNCTION__ */ ++#define EVENT__HAVE___FUNCTION__ 1 ++ ++/* Define to 1 if compiler have __func__ */ ++#define EVENT__HAVE___func__ 1 ++ ++/* Define to the sub-directory where libtool stores uninstalled libraries. */ ++#define EVENT__LT_OBJDIR ".libs/" ++ ++/* Numeric representation of the version */ ++#define EVENT__NUMERIC_VERSION 0x02010c00 ++ ++/* Name of package */ ++#define EVENT__PACKAGE "libevent" ++ ++/* Define to the address where bug reports for this package should be sent. */ ++#define EVENT__PACKAGE_BUGREPORT "" ++ ++/* Define to the full name of this package. */ ++#define EVENT__PACKAGE_NAME "libevent" ++ ++/* Define to the full name and version of this package. */ ++#define EVENT__PACKAGE_STRING "libevent 2.1.12-stable" ++ ++/* Define to the one symbol short name of this package. */ ++#define EVENT__PACKAGE_TARNAME "libevent" ++ ++/* Define to the home page for this package. */ ++#define EVENT__PACKAGE_URL "" ++ ++/* Define to the version of this package. */ ++#define EVENT__PACKAGE_VERSION "2.1.12-stable" ++ ++/* Define to necessary symbol if this constant uses a non-standard name on ++ your system. */ ++/* #undef EVENT__PTHREAD_CREATE_JOINABLE */ ++ ++/* The size of `int', as computed by sizeof. */ ++#define EVENT__SIZEOF_INT 4 ++ ++/* The size of `long', as computed by sizeof. */ ++#define EVENT__SIZEOF_LONG 8 ++ ++/* The size of `long long', as computed by sizeof. */ ++#define EVENT__SIZEOF_LONG_LONG 8 ++ ++/* The size of `off_t', as computed by sizeof. */ ++#define EVENT__SIZEOF_OFF_T 8 ++ ++/* The size of `pthread_t', as computed by sizeof. */ ++#define EVENT__SIZEOF_PTHREAD_T 8 ++ ++/* The size of `short', as computed by sizeof. */ ++#define EVENT__SIZEOF_SHORT 2 ++ ++/* The size of `size_t', as computed by sizeof. */ ++#define EVENT__SIZEOF_SIZE_T 8 ++ ++/* The size of `time_t', as computed by sizeof. */ ++#define EVENT__SIZEOF_TIME_T 8 ++ ++/* The size of `void *', as computed by sizeof. */ ++#define EVENT__SIZEOF_VOID_P 8 ++ ++/* Define to 1 if all of the C90 standard headers exist (not just the ones ++ required in a freestanding environment). This macro is provided for ++ backward compatibility; new code need not use it. */ ++#define STDC_HEADERS 1 ++ ++/* Define to 1 if you can safely include both and . This ++ macro is obsolete. */ ++#define EVENT__TIME_WITH_SYS_TIME 1 ++ ++/* Enable extensions on AIX 3, Interix. */ ++#ifndef _ALL_SOURCE ++# define _ALL_SOURCE 1 ++#endif ++/* Enable general extensions on macOS. */ ++#ifndef _DARWIN_C_SOURCE ++# define _DARWIN_C_SOURCE 1 ++#endif ++/* Enable general extensions on Solaris. */ ++#ifndef __EXTENSIONS__ ++# define __EXTENSIONS__ 1 ++#endif ++/* Enable GNU extensions on systems that have them. */ ++#ifndef _GNU_SOURCE ++# define _GNU_SOURCE 1 ++#endif ++/* Enable X/Open compliant socket functions that do not require linking ++ with -lxnet on HP-UX 11.11. */ ++#ifndef _HPUX_ALT_XOPEN_SOCKET_API ++# define _HPUX_ALT_XOPEN_SOCKET_API 1 ++#endif ++/* Identify the host operating system as Minix. ++ This macro does not affect the system headers' behavior. ++ A future release of Autoconf may stop defining this macro. */ ++#ifndef _MINIX ++/* # undef _MINIX */ ++#endif ++/* Enable general extensions on NetBSD. ++ Enable NetBSD compatibility extensions on Minix. */ ++#ifndef _NETBSD_SOURCE ++# define _NETBSD_SOURCE 1 ++#endif ++/* Enable OpenBSD compatibility extensions on NetBSD. ++ Oddly enough, this does nothing on OpenBSD. */ ++#ifndef _OPENBSD_SOURCE ++# define _OPENBSD_SOURCE 1 ++#endif ++/* Define to 1 if needed for POSIX-compatible behavior. */ ++#ifndef _POSIX_SOURCE ++/* # undef _POSIX_SOURCE */ ++#endif ++/* Define to 2 if needed for POSIX-compatible behavior. */ ++#ifndef _POSIX_1_SOURCE ++/* # undef _POSIX_1_SOURCE */ ++#endif ++/* Enable POSIX-compatible threading on Solaris. */ ++#ifndef _POSIX_PTHREAD_SEMANTICS ++# define _POSIX_PTHREAD_SEMANTICS 1 ++#endif ++/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */ ++#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__ ++# define __STDC_WANT_IEC_60559_ATTRIBS_EXT__ 1 ++#endif ++/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */ ++#ifndef __STDC_WANT_IEC_60559_BFP_EXT__ ++# define __STDC_WANT_IEC_60559_BFP_EXT__ 1 ++#endif ++/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */ ++#ifndef __STDC_WANT_IEC_60559_DFP_EXT__ ++# define __STDC_WANT_IEC_60559_DFP_EXT__ 1 ++#endif ++/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */ ++#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__ ++# define __STDC_WANT_IEC_60559_FUNCS_EXT__ 1 ++#endif ++/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */ ++#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__ ++# define __STDC_WANT_IEC_60559_TYPES_EXT__ 1 ++#endif ++/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */ ++#ifndef __STDC_WANT_LIB_EXT2__ ++# define __STDC_WANT_LIB_EXT2__ 1 ++#endif ++/* Enable extensions specified by ISO/IEC 24747:2009. */ ++#ifndef __STDC_WANT_MATH_SPEC_FUNCS__ ++# define __STDC_WANT_MATH_SPEC_FUNCS__ 1 ++#endif ++/* Enable extensions on HP NonStop. */ ++#ifndef _TANDEM_SOURCE ++# define _TANDEM_SOURCE 1 ++#endif ++/* Enable X/Open extensions. Define to 500 only if necessary ++ to make mbstate_t available. */ ++#ifndef _XOPEN_SOURCE ++/* # undef _XOPEN_SOURCE */ ++#endif ++ ++ ++/* Version number of package */ ++#define EVENT__VERSION "2.1.12-stable" ++ ++/* Number of bits in a file offset, on hosts where this is settable. */ ++/* #undef _FILE_OFFSET_BITS */ ++ ++/* Define for large files, on AIX-style hosts. */ ++/* #undef _LARGE_FILES */ ++ ++/* Define to empty if `const' does not conform to ANSI C. */ ++/* #undef const */ ++ ++/* Define to `__inline__' or `__inline' if that's what the C compiler ++ calls it, or to nothing if 'inline' is not supported under any name. */ ++#ifndef __cplusplus ++/* #undef inline */ ++#endif ++ ++/* Define as a signed integer type capable of holding a process identifier. */ ++/* #undef pid_t */ ++ ++/* Define to `unsigned int' if does not define. */ ++/* #undef size_t */ ++ ++/* Define to unsigned int if you dont have it */ ++/* #undef socklen_t */ ++ ++/* Define to `int' if does not define. */ ++/* #undef ssize_t */ ++ ++#endif /* event2/event-config.h */ +-- +2.44.0.769.g3c40516874-goog + diff --git a/tools/debug/start_auction b/tools/debug/start_auction index d1505b4e..1830a2e7 100755 --- a/tools/debug/start_auction +++ b/tools/debug/start_auction @@ -37,7 +37,7 @@ export SERVER_START_CMD=$(cat << END "auctionJsUrl": "https://pubads.g.doubleclick.net/td/sjs", "urlFetchPeriodMs": 13000000, "urlFetchTimeoutMs": 30000, - "enableSellerDebugUrlGeneration": false, + "enableSellerDebugUrlGeneration": true, "enableAdtechCodeLogging": false, "enableReportResultUrlGeneration": true, "enableReportWinUrlGeneration": true, @@ -48,6 +48,8 @@ export SERVER_START_CMD=$(cat << END --consented_debug_token="" \ --ps_verbosity=2 \ --enable_protected_audience="true" \ +--auction_tcmalloc_background_release_rate_bytes_per_second=4096 \ +--auction_tcmalloc_max_total_thread_cache_bytes=10737418240 \ --enable_protected_app_signals="false" && exit END ) diff --git a/tools/debug/start_bfe b/tools/debug/start_bfe index eefaf3d5..54dd13b6 100755 --- a/tools/debug/start_bfe +++ b/tools/debug/start_bfe @@ -35,6 +35,8 @@ export SERVER_START_CMD=$(cat << END --consented_debug_token="" \ --ps_verbosity=2 \ --enable_protected_audience="true" \ +--bfe_tcmalloc_background_release_rate_bytes_per_second=4096 \ +--bfe_tcmalloc_max_total_thread_cache_bytes=10737418240 \ --enable_protected_app_signals="false" && exit END ) diff --git a/tools/debug/start_bidding b/tools/debug/start_bidding index d19e3c93..d5525d46 100755 --- a/tools/debug/start_bidding +++ b/tools/debug/start_bidding @@ -52,6 +52,8 @@ export SERVER_START_CMD=$(cat << END --enable_protected_audience="true" \ --tee_ad_retrieval_kv_server_addr="localhost:50057" \ --ps_verbosity=2 \ +--bidding_tcmalloc_background_release_rate_bytes_per_second=4096 \ +--bidding_tcmalloc_max_total_thread_cache_bytes=10737418240 \ --ad_retrieval_timeout_ms="60000" && exit END ) diff --git a/tools/debug/start_sfe b/tools/debug/start_sfe index 9127cf71..cae62a45 100755 --- a/tools/debug/start_sfe +++ b/tools/debug/start_sfe @@ -44,6 +44,8 @@ export SERVER_START_CMD=$(cat << END --consented_debug_token="" \ --ps_verbosity=2 \ --enable_protected_audience="true" \ +--sfe_tcmalloc_background_release_rate_bytes_per_second=4096 \ +--sfe_tcmalloc_max_total_thread_cache_bytes=10737418240 \ --enable_protected_app_signals="false" && exit END ) diff --git a/version.txt b/version.txt index e5b82034..084e244c 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -3.5.0 \ No newline at end of file +3.6.0 \ No newline at end of file