diff --git a/spec.bs b/spec.bs
index deb92df0d..79c823d8c 100644
--- a/spec.bs
+++ b/spec.bs
@@ -1779,14 +1779,22 @@ following steps. They return a failure if failing to fetch the script or wasm, o
1. Let |prevWinElement| be the [=sequence=]<{{PreviousWinElement}}>
«|timeDelta|, |prevWinAdIDL|».
1. [=list/Append=] |prevWinElement| to |prevWins|.
1. [=map/Set=] |browserSignals|["{{BiddingBrowserSignals/prevWinsMs}}"] to |prevWins|.
+ 1. Let |metrics| be a new [=execution metrics=].
1. Let |biddingScriptFetcher| be the result of [=creating a new script fetcher=] with
|ig|'s [=interest group/bidding url=], and |settings|.
1. Let |biddingScript| be the result of [=waiting for script body from a fetcher=] given
|biddingScriptFetcher|.
+ 1. [=Add a sample to an averager=] given |metrics|'s [=execution metrics/average code fetch
+ time=] and |biddingScriptFetcher|'s [=script fetcher/fetch duration=].
1. If |biddingScript| is failure, return failure.
1. If |ig|'s [=interest group/bidding wasm helper url=] is not null:
+ 1. Let |wasmFetchStart| be |settings|'s [=environment settings object/current monotonic time=].
1. Let |wasmModuleObject| be the result of [=fetching WebAssembly=] with |ig|'s
[=interest group/bidding wasm helper url=] and |settings|.
+ 1. Let |wasmFetchDuration| be the [=duration from=] |wasmFetchStart| to
+ |settings|'s [=environment settings object/current monotonic time=], in milliseconds.
+ 1. [=Add a sample to an averager=] given |metrics|'s [=execution metrics/average code fetch
+ time=] and |wasmFetchDuration|.
1. If |wasmModuleObject| is not failure, then [=map/set=]
|browserSignals|["{{BiddingBrowserSignals/wasmHelper}}"] to |wasmModuleObject|.
1. Otherwise, return failure.
@@ -1810,7 +1818,7 @@ following steps. They return a failure if failing to fetch the script or wasm, o
|crossOriginTrustedBiddingSignalsOrigin|.
1. [=map/Set=] |crossOriginTrustedBiddingSignalsOrigin|[|originKey|] to |trustedBiddingSignals|.
1. Return the result of [=evaluating a bidding script=] with |biddingScript|, |multiBidLimit|,
- |ig|, |reportingContext|, |expectedCurrency|, |igGenerateBid|, |auctionSignals|,
+ |ig|, |reportingContext|, |metrics|, |expectedCurrency|, |igGenerateBid|, |auctionSignals|,
|perBuyerSignals|, |sameOriginTrustedBiddingSignals|, |crossOriginTrustedBiddingSignals|,
|browserSignals|, |directFromSellerSignalsForBuyer| and |perBuyerTimeout|.
@@ -1964,6 +1972,8 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|:
1. If |perBuyerExperimentGroupIds| is not null and |perBuyerExperimentGroupIds|[|buyer|]
[=map/exists=], then set |buyerExperimentGroupId| to |perBuyerExperimentGroupIds|[|buyer|].
1. Apply interest groups limits to prioritized list:
+ 1. Let |metrics| be the result of [=accessing per-participant metrics=] for |reportingContext|,
+ |buyer|, [=worklet function/generate-bid=].
1. Let |buyerGroupLimit| be |allBuyersGroupLimit|.
1. Let |perBuyerGroupLimits| be |auctionConfig|'s
[=auction config/per buyer group limits=].
@@ -1974,6 +1984,10 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|:
1. [=map/For each=] slotSizeQueryParam → |perSignalsUrlGenerator| of |perSlotSizeQueryParam|:
1. [=map/For each=] joiningOrigin → |groups| of |perSignalsUrlGenerator|:
1. [=list/Extend=] |igs| with |groups|.
+ 1. [=Update storage metrics=] given |metrics| and |igs|.
+
+ Note: This is done before any filtering, since it represents storage resource usage.
+
1. [=list/Sort in descending order=] |igs|, with |a| being less than |b| if |a|'s
[=interest group/priority=] is less than |b|'s [=interest group/priority=].
1. [=list/Remove=] the first |buyerGroupLimit| items from |igs|.
@@ -1981,6 +1995,9 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|:
1. [=map/For each=] slotSizeQueryParam → |perSignalsUrlGenerator| of |perSlotSizeQueryParam|:
1. [=map/For each=] joiningOrigin → |groups| of |perSignalsUrlGenerator|:
1. [=list/Remove=] from |groups| any [=interest group=] [=list/contained=] in |igs|.
+ 1. Set |metrics|'s [=per participant metrics/participating interest group count=] to
+ |metrics|'s [=per participant metrics/participating interest group count=] + [=list/
+ size=] of |groups|.
1. Let |perBuyerSignals| be null.
1. If |auctionConfig|'s [=auction config/per buyer signals=] is not null and
[=auction config/per buyer signals=][|buyer|] [=map/exists=], then set |perBuyerSignals| to
@@ -2057,8 +2074,8 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|:
1. If |optedInForRealTimeReporting| is true, then [=add a platform contribution=] with
[=bidding script failure bucket=], |realTimeContributionsMap| and |buyer|.
1. [=iteration/Continue=].
- 1. Let (|bidsBatch|, |bidDebugReportInfo|, |realTimeContributions|, |paContributions|) be
- |generateBidResult|.
+ 1. Let (|bidsBatch|, |bidDebugReportInfo|, |realTimeContributions|, |paContributions|,
+ |executionMetrics|) be |generateBidResult|.
1. Let |generateBidDuration| be the [=duration from=] |generateBidStartTime| to |settings|'s
[=environment settings object/current monotonic time=], in milliseconds.
1. If |perBuyerCumulativeTimeout| is not null, decrement |perBuyerCumulativeTimeout| by
@@ -2083,8 +2100,8 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|:
1. Let |generateBidStartTime| be |settings|'s
[=environment settings object/current monotonic time=].
1. Set (|generatedBids|, |bidDebugReportInfo|, |realTimeContributions|,
- |paContributions|) to the result of running [=generate potentially multiple bids=]
- with |allTrustedBiddingSignals|,
+ |paContributions|, |executionMetrics|) to the result of running [=generate potentially
+ multiple bids=] with |allTrustedBiddingSignals|,
|crossOriginTrustedBiddingSignalsOrigin|, |auctionSignals|, a [=map/clone=] of |browserSignals|,
|perBuyerSignals|, |directFromSellerSignalsForBuyer|, |perBuyerTimeout|, |expectedCurrency|,
1 (for multiBidLimit), |kAnonRestrictedIG|, |reportingContext|, |auctionStartTime|,
@@ -2102,7 +2119,7 @@ and a [=real time reporting contributions map=] |realTimeContributionsMap|:
1. [=Apply any component ads target to a bid=] given |generatedBid|.
1. [=list/Append=] |generatedBid| to |bidsToScore|.
1. [=Register bids for reporting=] given |bidsToScore|, |ig|, |bidDebugReportInfo|,
- |paContributions|, and |reportingContext|.
+ |paContributions|, |executionMetrics|, and |reportingContext|.
1. If |auctionConfig|'s [=auction config/per buyer real time reporting config=][|buyer|]
is "`default-local-reporting`", then [=insert entries to map=] given
|realTimeContributionsMap|, |buyer|, and |realTimeContributions|.
@@ -2354,11 +2371,21 @@ or "component-auction", a [=currency tag=] |componentAuctionExpectedCurrency|, a
"`default-local-reporting`", then [=add a platform contribution=] with
[=scoring script failure bucket=], |realTimeContributionsMap| and |seller|.
1. Return.
+1. Let |metrics| be the result of [=access per-participant metrics=] given |reportingContext|,
+ |auctionConfig|'s [=auction config/seller=], [=worklet function/score-ad=].
+1. [=Add a sample to an averager=] given |metrics|'s [=per participant metrics/average code fetch
+ time=] and |decisionLogicFetcher|'s [=script fetcher/fetch duration=].
1. Let « |scoreAdResult|, |debugWinReportUrl|, |debugLossReportUrl|, |realTimeContributions|,
- |paContributions| » be the result of [=evaluating a scoring script=] with |decisionLogicScript|,
- |adMetadata|, |bidValue|'s [=bid with currency/value=], |auctionConfig|, |reportingContext|,
- |sameOriginTrustedScoringSignals|, |crossOriginTrustedScoringSignals|, |browserSignals|,
- |directFromSellerSignalsForSeller|, and |auctionConfig|'s [=auction config/seller timeout=].
+ |paContributions|, |executionMetrics| » be the result of [=evaluating a scoring script=] with
+ |decisionLogicScript|, |adMetadata|, |bidValue|'s [=bid with currency/value=], |auctionConfig|,
+ |reportingContext|, |sameOriginTrustedScoringSignals|, |crossOriginTrustedScoringSignals|,
+ |browserSignals|, |directFromSellerSignalsForSeller|, and |auctionConfig|'s [=auction config/
+ seller timeout=].
+1. Set |metrics|'s [=per participant metrics/script executions attempted=] to |metrics|'s [=per
+ participant metrics/script executions attempted=] + 1.
+1. If |executionMetrics|'s [=execution metrics/script timeout occurred=] is true, set |metrics|'s
+ [=per participant metrics/script timeouts occurred=] to |metrics|'s [=per participant metrics/
+ script timeouts occurred=] + 1.
1. If |generatedBid|'s [=generated bid/for k-anon auction=] is true:
Note: Non-k-anonymous bids do not participate in reporting (except for platform real-time
@@ -2893,17 +2920,25 @@ and a [=global object=] |global|:
[=generated bid/interest group=], |igAd|, and null is true:
1. If |igAd|'s [=interest group ad/buyer and seller reporting ID=] is not null, [=map/set=]
|browserSignals|["{{ReportingBrowserSignals/buyerAndSellerReportingId}}"] to it.
+ 1. Let |metrics| be the result of [=access per-participant metrics=] given |reportingContext|,
+ |config|'s [=auction config/seller=], [=worklet function/report-result=].
1. Let |sellerReportingScriptFetcher| be the result of [=creating a new script fetcher=] with
|config|'s [=auction config/decision logic url=] and |global|'s [=relevant settings object=].
1. Let |sellerReportingScript| be the result of [=waiting for script body from a fetcher=] given
|sellerReportingScriptFetcher|.
- 1. Let « |sellerSignals|, |reportUrl|, |reportingBeaconMap|, ignored, |paContributions| » be the
- result of [=evaluating a reporting script=] with |sellerReportingScript|, "`reportResult`",
- |reportingContext|, |config|'s [=auction config/seller=], |config|'s
+ 1. [=Add a sample to an averager=] given |metrics|'s [=per participant metrics/average code fetch
+ time=] and |sellerReportingScriptFetcher|'s [=script fetcher/fetch duration=].
+ 1. Let « |sellerSignals|, |reportUrl|, |reportingBeaconMap|, ignored, |paContributions|,
+ |executionMetrics| » be the result of [=evaluating a reporting script=] with
+ |sellerReportingScript|, "`reportResult`", |reportingContext|,
+ |config|'s [=auction config/seller=], |config|'s
[=auction config/seller Private Aggregation coordinator=], |config|'s [=auction config/
config idl=]'s {{AuctionAdConfig/reportingTimeout}}, and
« |config|'s [=auction config/config idl=], |browserSignals|, |directFromSellerSignals| ».
- 1. Let |reportingResult| be a [=reporting result=] with the following [=struct/items=]:
+ 1. Set |metrics|'s [=per participant metrics/script executions attempted=] to 1.
+ 1. If |executionMetrics|'s [=execution metrics/script timeout occurred=] is true, set |metrics|'s
+ [=per participant metrics/script timeouts occurred=] to 1.
+ 1. Let |reportingResult| be a [=reporting result=] with the following [=struct/items=]:
: [=reporting result/report url=]
:: |reportUrl|
: [=reporting result/reporting beacon map=]
@@ -2958,6 +2993,8 @@ a {{ReportingBrowserSignals}} |browserSignals|, a [=direct from seller signals=]
(TODO: noise and bucket this signal)
1. Let |ig| be |winner|'s [=generated bid/interest group=].
+ 1. Let |metrics| be the result of [=access per-participant metrics=] given |reportingContext|,
+ |ig|'s [=interest group/owner=], [=worklet function/report-win=].
1. Let |igAd| be the [=interest group ad=] from ig's [=interest group/ads=] whose
[=interest group ad/render url=] is |winner|'s
[=generated bid/ad descriptor=]'s [=ad descriptor/url=].
@@ -2993,17 +3030,23 @@ a {{ReportingBrowserSignals}} |browserSignals|, a [=direct from seller signals=]
|winner|'s [=generated bid/interest group=]'s [=interest group/bidding url=] and |settings|.
1. Let |buyerReportingScript| be the result of [=waiting for script body from a fetcher=] given
|buyerReportingScriptFetcher|.
+ 1. [=Add a sample to an averager=] given |metrics|'s [=per participant metrics/average code fetch
+ time=] and |buyerReportingScriptFetcher|'s [=script fetcher/fetch duration=].
1. Let |reportFunctionName| be "`reportWin`".
1. If |winner|'s [=generated bid/provided as additional bid=] is true:
1. Set |reportFunctionName| be "`reportAdditionalBidWin`".
- 1. Let « ignored, |resultUrl|, |reportingBeaconMap|, |reportingMacroMap|, |paContributions| » be
- the result of [=evaluating a reporting script=] with |buyerReportingScript|,
- |reportFunctionName|, |reportingContext|, |ig|'s [=interest group/owner=], |ig|'s [=interest
- group/Private Aggregation coordinator=], |leadingBidInfo|'s [=leading bid info/auction config=]'s
+ 1. Let « ignored, |resultUrl|, |reportingBeaconMap|, |reportingMacroMap|, |paContributions|,
+ |executionMetrics| » be the result of [=evaluating a reporting script=] with
+ |buyerReportingScript|, |reportFunctionName|, |reportingContext|, |ig|'s
+ [=interest group/owner=], |ig|'s [=interest group/
+ Private Aggregation coordinator=], |leadingBidInfo|'s [=leading bid info/auction config=]'s
[=auction config/config idl=]'s {{AuctionAdConfig/reportingTimeout}}, and
« |leadingBidInfo|'s [=leading bid info/auction config=]'s [=auction config/config idl=]'s
{{AuctionAdConfig/auctionSignals}}, |perBuyerSignalsForBuyer|, |sellerSignals|,
|reportWinBrowserSignals|, |directFromSellerSignals| ».
+ 1. Set |metrics|'s [=per participant metrics/script executions attempted=] to 1.
+ 1. If |executionMetrics|'s [=execution metrics/script timeout occurred=] is true, set |metrics|'s
+ [=per participant metrics/script timeouts occurred=] to 1.
1. [=Commit private aggregation contributions=] given |paContributions|, |winner|'s [=generated
bid/reporting id=] and |reportingContext|.
1. Set |leadingBidInfo|'s [=leading bid info/buyer reporting result=] to a [=reporting result=]
@@ -3638,8 +3681,21 @@ A reporting context is a [=struct=] with the following [=struct/items
some of these may be based on bids that started as additional bids or from component auctions
run by Bidding and Auction services, and not interest groups, so this list may be quite
different from [=reporting context/bidder participants=].
+ : participant metrics
+ :: A [=map=] from a pair ([=origin=], [=worklet function=]) to [=per participant metrics=].
+
average-code-fetch-time
"
+:: The numeric value is the average time it took to fetch code resources (JavaScript or WebAssembly)
+ for this particular worklet function, for this participant.
+: "participating-ig-count
"
+:: The numeric value is the number of interest groups for the buyer actually participating in the
+ auction, after considering prioritization and capabilities.
+: "percent-scripts-timeout
"
+:: The numeric value is percentage of executions of this script that hit their individual timeout,
+ out of all executions that were expected to happen.
+: "regular-igs-count
"
+:: Number of [=regular interest groups=] for the given buyer. (0 if this is used by a seller).
+: "percent-regular-ig-count-quota-used
"
+::
+: "negative-igs-count
"
+:: Number of [=negative interest groups=] for the given buyer. (0 if this is used by a seller).
+: "percent-negative-ig-count-quota-used
"
+::
+: "ig-storage-used
"
+:: Bytes of storage used by the given buyer. (0 if this is used by a seller).
+: "percent-ig-storage-quota-used
"
+::
+
[=signal base value/winning-bid=]
":
1. If |leadingBidInfo|'s [=leading bid info/leading bid=] is null, return 0.
1. Otherwise, return |leadingBidInfo|'s [=leading bid info/leading bid=]'s [=generated bid/bid=].
@@ -4446,6 +4623,54 @@ They return a {{double}}.
Issue: Verify handling when the bid was not rejected.
+1. If |signalBaseValue| is "[=signal base value/average-code-fetch-time=]
":
+ 1. Return the result of [=getting the value to report from an averager=] given |metrics|'s [=per
+ participant metrics/average code fetch time=].
+1. If |signalBaseValue| is "[=signal base value/participating-ig-count=]
":
+ 1. Return |bidAndScoreMetrics|'s [=per participant metrics/participating interest group count=].
+1. If |signalBaseValue| is "[=signal base value/percent-scripts-timeout=]
":
+ 1. Return the result of [=computing a percentage metric=] given |metrics|'s [=per participant
+ metrics/script timeouts occurred=] and |metrics|'s [=per participant metrics/script executions
+ attempted=].
+1. If |signalBaseValue| is "[=signal base value/regular-igs-count=]
":
+ 1. Return |bidAndScoreMetrics|'s [=per participant metrics/regular interest group count=].
+1. If |signalBaseValue| is "[=signal base value/percent-regular-ig-count-quota-used=]
":
+ 1. Return the result of [=computing a percentage metric=] given |bidAndScoreMetrics|'s [=per
+ participant metrics/regular interest group count=] and [=Max regular interest groups per owner=].
+1. If |signalBaseValue| is "[=signal base value/negative-igs-count=]
":
+ 1. Return |bidAndScoreMetrics|'s [=per participant metrics/negative interest group count=].
+1. If |signalBaseValue| is "[=signal base value/percent-negative-ig-count-quota-used=]
":
+ 1. Return the result of [=computing a percentage metric=] given |bidAndScoreMetrics|'s [=per
+ participant metrics/negative interest group count=] and [=Max negative interest groups per
+ owner=].
+1. If |signalBaseValue| is "[=signal base value/ig-storage-used=]
":
+ 1. Return |bidAndScoreMetrics|'s [=per participant metrics/storage quota used=].
+1. If |signalBaseValue| is "[=signal base value/percent-ig-storage-quota-used=]
":
+ 1. Return the result of [=computing a percentage metric=] given |bidAndScoreMetrics|'s [=per
+ participant metrics/storage quota used=] and [=Max interest groups total size per owner=].
+
+