@@ -1113,17 +1113,18 @@ private boolean isTokenInputValid(InputUtil.InputVal input, RoutingContext rc) {
11131113 return true ;
11141114 }
11151115
1116- private JsonObject processIdentityMapV2Response (RoutingContext rc , InputUtil . InputVal [] inputList ) {
1116+ private JsonObject processIdentityMapV2Response (RoutingContext rc , IdentityMapV2Input v2Input ) {
11171117 RuntimeConfig config = getConfigFromRc (rc );
11181118 IdentityEnvironment env = config .getIdentityEnvironment ();
1119+ InputUtil .InputVal [] inputList = v2Input .inputList ();
11191120
11201121 final Instant now = Instant .now ();
11211122 final JsonArray mapped = new JsonArray ();
11221123 final JsonArray unmapped = new JsonArray ();
1123- final int count = inputList .length ;
1124+ final int inputCount = inputList .length ;
11241125 int invalidCount = 0 ;
11251126 int optoutCount = 0 ;
1126- for (int i = 0 ; i < count ; ++i ) {
1127+ for (int i = 0 ; i < inputCount ; ++i ) {
11271128 final InputUtil .InputVal input = inputList [i ];
11281129 if (input != null && input .isValid ()) {
11291130 final MappedIdentity mappedIdentity = idService .mapIdentity (
@@ -1154,7 +1155,7 @@ private JsonObject processIdentityMapV2Response(RoutingContext rc, InputUtil.Inp
11541155 }
11551156 }
11561157
1157- recordIdentityMapStats (rc , inputList . length , invalidCount , optoutCount );
1158+ recordIdentityMapStats (rc , Map . of ( v2Input . diiType (), inputCount ) , invalidCount , optoutCount );
11581159
11591160 final JsonObject resp = new JsonObject ();
11601161 resp .put ("mapped" , mapped );
@@ -1170,12 +1171,12 @@ private JsonObject processIdentityMapV3Response(RoutingContext rc, Map<String, I
11701171 final JsonObject mappedResponse = new JsonObject ();
11711172 int invalidCount = 0 ;
11721173 int optoutCount = 0 ;
1173- int inputTotalCount = 0 ;
1174+ Map < String , Integer > diiTypeCounts = new HashMap <>() ;
11741175
11751176 for (Map .Entry <String , InputUtil .InputVal []> identityType : input .entrySet ()) {
11761177 JsonArray mappedIdentityList = new JsonArray ();
11771178 final InputUtil .InputVal [] rawIdentityList = identityType .getValue ();
1178- inputTotalCount += rawIdentityList .length ;
1179+ diiTypeCounts . put ( identityType . getKey (), rawIdentityList .length ) ;
11791180
11801181 for (final InputUtil .InputVal rawId : rawIdentityList ) {
11811182 final JsonObject resp = new JsonObject ();
@@ -1203,7 +1204,7 @@ private JsonObject processIdentityMapV3Response(RoutingContext rc, Map<String, I
12031204 mappedResponse .put (identityType .getKey (), mappedIdentityList );
12041205 }
12051206
1206- recordIdentityMapStats (rc , inputTotalCount , invalidCount , optoutCount );
1207+ recordIdentityMapStats (rc , diiTypeCounts , invalidCount , optoutCount );
12071208
12081209 return mappedResponse ;
12091210 }
@@ -1223,61 +1224,61 @@ private void handleIdentityMapV2(RoutingContext rc) {
12231224 final String apiContact = RoutingContextUtil .getApiContact (rc , clientKeyProvider );
12241225 recordOperatorServedSdkUsage (rc , siteId , apiContact , rc .request ().headers ().get (Const .Http .ClientVersionHeader ));
12251226
1226- final InputUtil . InputVal [] inputList = getIdentityMapV2Input (rc );
1227- if (inputList == null ) {
1227+ final IdentityMapV2Input v2Input = getIdentityMapV2Input (rc );
1228+ if (v2Input == null ) {
12281229 ResponseUtil .LogInfoAndSend400Response (rc , this .phoneSupport ? ERROR_INVALID_INPUT_WITH_PHONE_SUPPORT : ERROR_INVALID_INPUT_EMAIL_MISSING );
12291230 return ;
12301231 }
12311232
12321233 if (!validateServiceLink (rc )) { return ; }
12331234
1234- final JsonObject resp = processIdentityMapV2Response (rc , inputList );
1235+ final JsonObject resp = processIdentityMapV2Response (rc , v2Input );
12351236 ResponseUtil .SuccessV2 (rc , resp );
12361237 } catch (Exception e ) {
12371238 ResponseUtil .LogErrorAndSendResponse (ResponseStatus .UnknownError , 500 , rc , "Unknown error while mapping identity v2" , e );
12381239 }
12391240 }
12401241
1241- private InputUtil . InputVal [] getIdentityMapV2Input (RoutingContext rc ) {
1242+ private IdentityMapV2Input getIdentityMapV2Input (RoutingContext rc ) {
12421243 final JsonObject obj = (JsonObject ) rc .data ().get ("request" );
12431244
1244- Supplier <InputUtil . InputVal []> getInputList = null ;
1245+ Supplier <IdentityMapV2Input > getV2Request = null ;
12451246 final JsonArray emails = JsonParseUtils .parseArray (obj , "email" , rc );
12461247 if (emails != null && !emails .isEmpty ()) {
1247- getInputList = () -> createInputList (emails , IdentityType .Email , InputUtil .IdentityInputType .Raw );
1248+ getV2Request = () -> new IdentityMapV2Input ( "email" , createInputList (emails , IdentityType .Email , InputUtil .IdentityInputType .Raw ) );
12481249 }
12491250
12501251 final JsonArray emailHashes = JsonParseUtils .parseArray (obj , "email_hash" , rc );
12511252 if (emailHashes != null && !emailHashes .isEmpty ()) {
1252- if (getInputList != null ) {
1253+ if (getV2Request != null ) {
12531254 return null ; // only one type of input is allowed
12541255 }
1255- getInputList = () -> createInputList (emailHashes , IdentityType .Email , InputUtil .IdentityInputType .Hash );
1256+ getV2Request = () -> new IdentityMapV2Input ( "email_hash" , createInputList (emailHashes , IdentityType .Email , InputUtil .IdentityInputType .Hash ) );
12561257 }
12571258
12581259 final JsonArray phones = this .phoneSupport ? JsonParseUtils .parseArray (obj ,"phone" , rc ) : null ;
12591260 if (phones != null && !phones .isEmpty ()) {
1260- if (getInputList != null ) {
1261+ if (getV2Request != null ) {
12611262 return null ; // only one type of input is allowed
12621263 }
1263- getInputList = () -> createInputList (phones , IdentityType .Phone , InputUtil .IdentityInputType .Raw );
1264+ getV2Request = () -> new IdentityMapV2Input ( "phone" , createInputList (phones , IdentityType .Phone , InputUtil .IdentityInputType .Raw ) );
12641265 }
12651266
12661267 final JsonArray phoneHashes = this .phoneSupport ? JsonParseUtils .parseArray (obj ,"phone_hash" , rc ) : null ;
12671268 if (phoneHashes != null && !phoneHashes .isEmpty ()) {
1268- if (getInputList != null ) {
1269+ if (getV2Request != null ) {
12691270 return null ; // only one type of input is allowed
12701271 }
1271- getInputList = () -> createInputList (phoneHashes , IdentityType .Phone , InputUtil .IdentityInputType .Hash );
1272+ getV2Request = () -> new IdentityMapV2Input ( "phone_hash" , createInputList (phoneHashes , IdentityType .Phone , InputUtil .IdentityInputType .Hash ) );
12721273 }
12731274
12741275 if (emails == null && emailHashes == null && phones == null && phoneHashes == null ) {
12751276 return null ;
12761277 }
12771278
1278- return getInputList == null ?
1279- createInputList (null , IdentityType .Email , InputUtil .IdentityInputType .Raw ) : // handle empty array
1280- getInputList .get ();
1279+ return getV2Request == null ?
1280+ new IdentityMapV2Input ( "email" , createInputList (null , IdentityType .Email , InputUtil .IdentityInputType .Raw ) ) : // handle empty array
1281+ getV2Request .get ();
12811282 }
12821283
12831284 private void handleIdentityMapV3 (RoutingContext rc ) {
@@ -1333,18 +1334,25 @@ private static String getApiContact(RoutingContext rc) {
13331334 return apiContact ;
13341335 }
13351336
1336- private void recordIdentityMapStats (RoutingContext rc , int inputCount , int invalidCount , int optoutCount ) {
1337+ private void recordIdentityMapStats (RoutingContext rc , Map < String , Integer > diiTypeCounts , int invalidCount , int optoutCount ) {
13371338 String apiContact = getApiContact (rc );
13381339 String path = rc .request ().path ();
1339- String cacheKey = apiContact + "|" + path ;
13401340
1341- DistributionSummary ds = _identityMapMetricSummaries .computeIfAbsent (cacheKey , k -> DistributionSummary
1342- .builder ("uid2_operator_identity_map_inputs" )
1343- .description ("number of emails or email hashes passed to identity map batch endpoint" )
1344- .tags ("api_contact" , apiContact , "path" , path )
1345- .register (Metrics .globalRegistry ));
1346- ds .record (inputCount );
1341+ for (Map .Entry <String , Integer > entry : diiTypeCounts .entrySet ()) {
1342+ String diiType = entry .getKey ();
1343+ int count = entry .getValue ();
1344+ if (count > 0 ) {
1345+ String cacheKey = apiContact + "|" + path + "|" + diiType ;
1346+ DistributionSummary ds = _identityMapMetricSummaries .computeIfAbsent (cacheKey , k -> DistributionSummary
1347+ .builder ("uid2_operator_identity_map_inputs" )
1348+ .description ("number of identifiers passed to identity map endpoint" )
1349+ .tags ("api_contact" , apiContact , "path" , path , "dii_type" , diiType )
1350+ .register (Metrics .globalRegistry ));
1351+ ds .record (count );
1352+ }
1353+ }
13471354
1355+ String cacheKey = apiContact + "|" + path ;
13481356 Tuple .Tuple2 <Counter , Counter > ids = _identityMapUnmappedIdentifiers .computeIfAbsent (cacheKey , k -> new Tuple .Tuple2 <>(
13491357 Counter .builder ("uid2_operator_identity_map_unmapped_total" )
13501358 .description ("invalid identifiers" )
@@ -1365,27 +1373,36 @@ private void recordIdentityMapStats(RoutingContext rc, int inputCount, int inval
13651373 if (invalidCount > 0 || optoutCount > 0 ) {
13661374 rs .increment ();
13671375 }
1368- recordIdentityMapStatsForServiceLinks (rc , apiContact , path , inputCount , invalidCount , optoutCount );
1376+ recordIdentityMapStatsForServiceLinks (rc , apiContact , path , diiTypeCounts , invalidCount , optoutCount );
13691377 }
13701378
13711379 private void recordIdentityMapStatsForServiceLinks (RoutingContext rc , String apiContact , String path ,
1372- int inputCount , int invalidCount , int optOutCount ) {
1380+ Map < String , Integer > diiTypeCounts , int invalidCount , int optOutCount ) {
13731381 // If request is from a service, break it down further by link_id
13741382 String serviceLinkName = rc .get (SecureLinkValidatorService .SERVICE_LINK_NAME , "" );
13751383 if (!serviceLinkName .isBlank ()) {
13761384 // serviceName will be non-empty as it will be inserted during validation
13771385 final String serviceName = rc .get (SecureLinkValidatorService .SERVICE_NAME );
1378- final String cacheKey = serviceName + serviceLinkName + "|" + path ;
1379- DistributionSummary ds = _identityMapServicesMetricSummaries .computeIfAbsent (cacheKey ,
1380- k -> DistributionSummary .builder ("uid2_operator_identity_map_services_inputs" )
1381- .description ("number of emails or phone numbers passed to identity map batch endpoint by services" )
1382- .tags (Arrays .asList (Tag .of ("api_contact" , apiContact ),
1383- Tag .of ("service_name" , serviceName ),
1384- Tag .of ("service_link_name" , serviceLinkName ),
1385- Tag .of ("path" , path )))
1386- .register (Metrics .globalRegistry ));
1387- ds .record (inputCount );
13881386
1387+ for (Map .Entry <String , Integer > entry : diiTypeCounts .entrySet ()) {
1388+ String diiType = entry .getKey ();
1389+ int count = entry .getValue ();
1390+ if (count > 0 ) {
1391+ final String cacheKey = serviceName + serviceLinkName + "|" + path + "|" + diiType ;
1392+ DistributionSummary ds = _identityMapServicesMetricSummaries .computeIfAbsent (cacheKey ,
1393+ k -> DistributionSummary .builder ("uid2_operator_identity_map_services_inputs" )
1394+ .description ("number of identifiers passed to identity map endpoint by services" )
1395+ .tags (Arrays .asList (Tag .of ("api_contact" , apiContact ),
1396+ Tag .of ("service_name" , serviceName ),
1397+ Tag .of ("service_link_name" , serviceLinkName ),
1398+ Tag .of ("path" , path ),
1399+ Tag .of ("dii_type" , diiType )))
1400+ .register (Metrics .globalRegistry ));
1401+ ds .record (count );
1402+ }
1403+ }
1404+
1405+ final String cacheKey = serviceName + serviceLinkName + "|" + path ;
13891406 Tuple .Tuple2 <Counter , Counter > counterTuple = _identityMapServicesUnmappedIdentifiers .computeIfAbsent (cacheKey ,
13901407 k -> new Tuple .Tuple2 <>(
13911408 Counter .builder ("uid2_operator_identity_map_services_unmapped_total" )
0 commit comments