2121import org .prebid .server .log .ConditionalLogger ;
2222import org .prebid .server .log .Logger ;
2323import org .prebid .server .log .LoggerFactory ;
24- import org .prebid .server .metric .MetricName ;
25- import org .prebid .server .metric .Metrics ;
2624import org .prebid .server .proto .openrtb .ext .request .ExtImpPrebidFloors ;
2725import org .prebid .server .proto .openrtb .ext .request .ExtRequest ;
2826import org .prebid .server .proto .openrtb .ext .request .ExtRequestPrebid ;
@@ -54,23 +52,17 @@ public class BasicPriceFloorProcessor implements PriceFloorProcessor {
5452
5553 private final PriceFloorFetcher floorFetcher ;
5654 private final PriceFloorResolver floorResolver ;
57- private final Metrics metrics ;
5855 private final JacksonMapper mapper ;
59- private final double logSamplingRate ;
6056
6157 private final RandomWeightedEntrySupplier <PriceFloorModelGroup > modelPicker ;
6258
6359 public BasicPriceFloorProcessor (PriceFloorFetcher floorFetcher ,
6460 PriceFloorResolver floorResolver ,
65- Metrics metrics ,
66- JacksonMapper mapper ,
67- double logSamplingRate ) {
61+ JacksonMapper mapper ) {
6862
6963 this .floorFetcher = Objects .requireNonNull (floorFetcher );
7064 this .floorResolver = Objects .requireNonNull (floorResolver );
71- this .metrics = Objects .requireNonNull (metrics );
7265 this .mapper = Objects .requireNonNull (mapper );
73- this .logSamplingRate = logSamplingRate ;
7466
7567 modelPicker = new RandomPositiveWeightedEntrySupplier <>(BasicPriceFloorProcessor ::resolveModelGroupWeight );
7668 }
@@ -90,7 +82,7 @@ public BidRequest enrichWithPriceFloors(BidRequest bidRequest,
9082 return disableFloorsForRequest (bidRequest );
9183 }
9284
93- final PriceFloorRules floors = resolveFloors (account , bidRequest , warnings );
85+ final PriceFloorRules floors = resolveFloors (account , bidRequest , errors );
9486 return updateBidRequestWithFloors (bidRequest , bidder , floors , errors , warnings );
9587 }
9688
@@ -130,13 +122,49 @@ private static PriceFloorRules extractRequestFloors(BidRequest bidRequest) {
130122 return ObjectUtil .getIfNotNull (prebid , ExtRequestPrebid ::getFloors );
131123 }
132124
133- private PriceFloorRules resolveFloors (Account account , BidRequest bidRequest , List <String > warnings ) {
125+ private PriceFloorRules resolveFloors (Account account , BidRequest bidRequest , List <String > errors ) {
134126 final PriceFloorRules requestFloors = extractRequestFloors (bidRequest );
135127
136128 final FetchResult fetchResult = floorFetcher .fetch (account );
137- final FetchStatus fetchStatus = fetchResult . getFetchStatus ( );
129+ final FetchStatus fetchStatus = ObjectUtil . getIfNotNull ( fetchResult , FetchResult :: getFetchStatus );
138130
139- final boolean isUsingDynamicDataAllowed = Optional .ofNullable (account .getAuction ())
131+ if (fetchResult != null && fetchStatus == FetchStatus .success && shouldUseDynamicData (account , fetchResult )) {
132+ final PriceFloorRules mergedFloors = mergeFloors (requestFloors , fetchResult .getRulesData ());
133+ return createFloorsFrom (mergedFloors , fetchStatus , PriceFloorLocation .fetch );
134+ }
135+
136+ if (requestFloors != null ) {
137+ try {
138+ final Optional <AccountPriceFloorsConfig > priceFloorsConfig = Optional .of (account )
139+ .map (Account ::getAuction )
140+ .map (AccountAuctionConfig ::getPriceFloors );
141+
142+ final Long maxRules = priceFloorsConfig .map (AccountPriceFloorsConfig ::getMaxRules )
143+ .orElse (null );
144+ final Long maxDimensions = priceFloorsConfig .map (AccountPriceFloorsConfig ::getMaxSchemaDims )
145+ .orElse (null );
146+
147+ PriceFloorRulesValidator .validateRules (
148+ requestFloors ,
149+ PriceFloorsConfigResolver .resolveMaxValue (maxRules ),
150+ PriceFloorsConfigResolver .resolveMaxValue (maxDimensions ));
151+
152+ return createFloorsFrom (requestFloors , fetchStatus , PriceFloorLocation .request );
153+ } catch (PreBidException e ) {
154+ errors .add ("Failed to parse price floors from request, with a reason: %s" .formatted (e .getMessage ()));
155+ conditionalLogger .error (
156+ "Failed to parse price floors from request with id: '%s', with a reason: %s"
157+ .formatted (bidRequest .getId (), e .getMessage ()),
158+ 0.01d );
159+ }
160+ }
161+
162+ return createFloorsFrom (null , fetchStatus , PriceFloorLocation .noData );
163+ }
164+
165+ private static boolean shouldUseDynamicData (Account account , FetchResult fetchResult ) {
166+ final boolean isUsingDynamicDataAllowed = Optional .of (account )
167+ .map (Account ::getAuction )
140168 .map (AccountAuctionConfig ::getPriceFloors )
141169 .map (AccountPriceFloorsConfig ::getUseDynamicData )
142170 .map (BooleanUtils ::isNotFalse )
@@ -147,73 +175,12 @@ private PriceFloorRules resolveFloors(Account account, BidRequest bidRequest, Li
147175 .map (rate -> ThreadLocalRandom .current ().nextInt (USE_FETCH_DATA_RATE_MAX ) < rate )
148176 .orElse (true );
149177
150- if (fetchStatus == FetchStatus .success && isUsingDynamicDataAllowed && shouldUseDynamicData ) {
151- final PriceFloorRules mergedFloors = mergeFloors (requestFloors , fetchResult .getRulesData ());
152- return createFloorsFrom (mergedFloors , fetchStatus , PriceFloorLocation .fetch );
153- }
154-
155- final String fetchErrorMessage = resolveFetchErrorMessage (fetchResult , isUsingDynamicDataAllowed );
156- return requestFloors == null
157- ? noPriceFloorData (fetchStatus , account .getId (), bidRequest .getId (), fetchErrorMessage , warnings )
158- : getPriceFloorRules (bidRequest , account , requestFloors , fetchStatus , fetchErrorMessage , warnings );
159- }
160-
161- private static String resolveFetchErrorMessage (FetchResult fetchResult , boolean isUsingDynamicDataAllowed ) {
162- return switch (fetchResult .getFetchStatus ()) {
163- case inprogress -> null ;
164- case error , timeout , none -> fetchResult .getErrorMessage ();
165- case success -> isUsingDynamicDataAllowed ? null : "Using dynamic data is not allowed" ;
166- };
167- }
168-
169- private PriceFloorRules noPriceFloorData (FetchStatus fetchStatus ,
170- String accountId ,
171- String requestId ,
172- String errorMessage ,
173- List <String > warnings ) {
174-
175- if (errorMessage != null ) {
176- warnings .add (errorMessage );
177- conditionalLogger .error ("No price floor data for account %s and request %s, reason: %s"
178- .formatted (accountId , requestId , errorMessage ), logSamplingRate );
179- metrics .updateAlertsMetrics (MetricName .general );
180- }
181-
182- return createFloorsFrom (null , fetchStatus , PriceFloorLocation .noData );
178+ return isUsingDynamicDataAllowed && shouldUseDynamicData ;
183179 }
184180
185- private PriceFloorRules getPriceFloorRules (BidRequest bidRequest ,
186- Account account ,
187- PriceFloorRules requestFloors ,
188- FetchStatus fetchStatus ,
189- String fetchErrorMessage ,
190- List <String > warnings ) {
191-
192- try {
193- final Optional <AccountPriceFloorsConfig > priceFloorsConfig = Optional .of (account .getAuction ())
194- .map (AccountAuctionConfig ::getPriceFloors );
195-
196- final Long maxRules = priceFloorsConfig .map (AccountPriceFloorsConfig ::getMaxRules )
197- .orElse (null );
198- final Long maxDimensions = priceFloorsConfig .map (AccountPriceFloorsConfig ::getMaxSchemaDims )
199- .orElse (null );
200-
201- PriceFloorRulesValidator .validateRules (
202- requestFloors ,
203- PriceFloorsConfigResolver .resolveMaxValue (maxRules ),
204- PriceFloorsConfigResolver .resolveMaxValue (maxDimensions ));
205-
206- return createFloorsFrom (requestFloors , fetchStatus , PriceFloorLocation .request );
207- } catch (PreBidException e ) {
208- final String errorMessage = fetchErrorMessage == null
209- ? null
210- : "%s. Following parsing of request price floors is failed: %s"
211- .formatted (fetchErrorMessage , e .getMessage ());
212- return noPriceFloorData (fetchStatus , account .getId (), bidRequest .getId (), errorMessage , warnings );
213- }
214- }
181+ private PriceFloorRules mergeFloors (PriceFloorRules requestFloors ,
182+ PriceFloorData providerRulesData ) {
215183
216- private PriceFloorRules mergeFloors (PriceFloorRules requestFloors , PriceFloorData providerRulesData ) {
217184 final Price floorMinPrice = resolveFloorMinPrice (requestFloors );
218185
219186 return (requestFloors != null ? requestFloors .toBuilder () : PriceFloorRules .builder ())
0 commit comments