1111import requests
1212from aws_lambda_powertools import Tracer
1313from aws_lambda_powertools import Logger
14+ from aws_lambda_powertools import Metrics
15+ from aws_lambda_powertools import single_metric
16+ from aws_lambda_powertools .metrics import MetricUnit
1417from aws_lambda_powertools .utilities import parameters
1518import time
1619
1720tracer = Tracer ()
1821logger = Logger ()
22+ metrics = Metrics ()
23+ metrics .set_default_dimensions (function = os .environ ['AWS_LAMBDA_FUNCTION_NAME' ])
1924config = Config (connect_timeout = 2 , read_timeout = 2 )
2025dynamodb = boto3 .resource ('dynamodb' , config = config )
2126
2530# Steam Web Api key from Secrets manager, cached between requests for 15 minutes
2631steam_web_api_secret_max_age = 15 * 60
2732
33+ def record_success_metric ():
34+ metrics .add_metric (name = "success" , unit = MetricUnit .Count , value = 1 )
35+
36+
37+ def record_failure_metric (reason : str ):
38+ with single_metric (
39+ name = "failure" ,
40+ unit = MetricUnit .Count ,
41+ value = 1 ,
42+ default_dimensions = metrics .default_dimensions
43+ ) as metric :
44+ metric .add_dimension (
45+ name = "reason" , value = reason )
46+
2847# Creates a new user when there's no existing user for the Steam ID
2948@tracer .capture_method
3049def create_user (steam_id ):
@@ -47,6 +66,8 @@ def create_user(steam_id):
4766 logger .info ("User already exists" )
4867 return None
4968
69+ metrics .add_metric (name = "created_user" , unit = MetricUnit .Count , value = 1 )
70+
5071 return user_id
5172
5273@tracer .capture_method
@@ -99,7 +120,7 @@ def get_existing_user(steam_id):
99120@tracer .capture_method
100121def add_new_user_to_steam_table (user_id , steam_id ):
101122 try :
102- steam_id_user_table_name = os .getenv ("STEAM_USER_TABLE" );
123+ steam_id_user_table_name = os .getenv ("STEAM_USER_TABLE" )
103124 steam_id_user_table = dynamodb .Table (steam_id_user_table_name )
104125 steam_id_user_table .put_item (
105126 Item = {
@@ -109,12 +130,14 @@ def add_new_user_to_steam_table(user_id, steam_id):
109130 return True
110131 except Exception as e :
111132 logger .info ("Exception adding user to Steam ID table: " , e )
133+
134+ metrics .add_metric (name = "new_steam_user" , unit = MetricUnit .Count , value = 1 )
112135
113136 return False
114137
115138def link_steam_id_to_existing_user (user_id , steam_id ):
116139 try :
117- user_table_name = os .getenv ("USER_TABLE" );
140+ user_table_name = os .getenv ("USER_TABLE" )
118141 user_table = dynamodb .Table (user_table_name )
119142 # Update existing user
120143 user_table .update_item (
@@ -130,6 +153,8 @@ def link_steam_id_to_existing_user(user_id, steam_id):
130153 return True
131154 except Exception as e :
132155 logger .info ("Exception linking user to existing user: " , e )
156+
157+ metrics .add_metric (name = "linked_user" , unit = MetricUnit .Count , value = 1 )
133158
134159 return False
135160
@@ -143,9 +168,19 @@ def check_steam_token(token: str) -> str:
143168 params = {'key' : steam_web_api_key , 'appid' : os .environ ['STEAM_APP_ID' ], 'ticket' : token })
144169 elapsed_ms = round (((datetime .datetime .utcnow ()- send_time ).microseconds )/ 1000 )
145170 logger .debug (f'Steam response' , elapsed_ms = elapsed_ms , code = response .status_code , headers = response .headers , body = response .text )
171+
172+ with single_metric (
173+ name = "duration" ,
174+ unit = MetricUnit .Milliseconds ,
175+ value = elapsed_ms ,
176+ default_dimensions = metrics .default_dimensions
177+ ) as metric :
178+ metric .add_dimension (name = "partner" , value = 'Steam' )
179+ metric .add_dimension (name = "api" , value = 'ISteamUserAuth/AuthenticateUserTicket/v1' )
146180
147181 if response .status_code != 200 :
148182 logger .error ("Steam returned an error" , response_code = response .status_code )
183+ record_failure_metric (f'Steam returned { response .status_code } ' )
149184 return None
150185
151186 response_body = response .json ()
@@ -155,30 +190,44 @@ def check_steam_token(token: str) -> str:
155190 break
156191
157192 logger .info ("Received 103, retrying after a delay" )
193+ with single_metric (
194+ name = "retry" ,
195+ unit = MetricUnit .Count ,
196+ value = 1 ,
197+ default_dimensions = metrics .default_dimensions
198+ ) as metric :
199+ metric .add_dimension (name = "partner" , value = 'Steam' )
200+ metric .add_dimension (name = "api" , value = 'ISteamUserAuth/AuthenticateUserTicket/v1' )
158201 time .sleep (1 )
159202
160203 response_dict = response_body .get ('response' , {}).get ('params' , {})
161204 if not 'result' in response_dict or response_dict ['result' ] != 'OK' :
162- logger .info ("Result in not OK" , result = response_dict ['result' ])
205+ result = response_dict ['result' ]
206+ logger .info ("Result in not OK" , result = result )
207+ record_failure_metric (f'Steam result { result } ' )
163208 return None
164209
165210 if not 'steamid' in response_dict :
166211 logger .error ("steamid missing" , response = response_dict )
212+ record_failure_metric (f'steamid missing' )
167213 return None
168214 steam_user_id = response_dict ['steamid' ]
169215
170216 if 'vacbanned' in response_dict and response_dict ['publisherbanned' ]:
171217 logger .info ("User is VAC Banned" , steam_user_id = steam_user_id )
218+ record_failure_metric (f'VAC Banned' )
172219 return None
173220
174221 if 'publisherbanned' in response_dict and response_dict ['publisherbanned' ]:
175- logger .info ("User is Published Banned" , steam_user_id = steam_user_id )
222+ logger .info ("User is Publisher Banned" , steam_user_id = steam_user_id )
223+ record_failure_metric (f'Publisher Banned' )
176224 return None
177225
178226 return steam_user_id
179227
180228
181229# define a lambda function that returns a user_id
230+ @metrics .log_metrics
182231@tracer .capture_lambda_handler
183232def lambda_handler (event , context ):
184233
@@ -200,10 +249,12 @@ def lambda_handler(event, context):
200249 if steam_user_id :
201250 logger .info ("Received Steam user ID: " , steam_user_id = steam_user_id )
202251 else :
252+ # failure metrics handled by check_steam_token
203253 return generate_error ('Error: Failed to validate Steam token' )
204254
205255 except Exception as e :
206256 logger .error ("exception in check_steam_token" , error = e )
257+ record_failure_metric (f'exception in check_steam_token { e } ' )
207258 return generate_error ('Error: Token validation error' )
208259
209260 if steam_user_id != None :
@@ -214,6 +265,7 @@ def lambda_handler(event, context):
214265 existing_user_request_success , user_id = get_existing_user (steam_user_id )
215266 # If there was a problem getting existing user, abort as we don't want to create duplicate
216267 if existing_user_request_success is False :
268+ record_failure_metric (f'Failed the try getting existing user' )
217269 return generate_error ('Error: Failed the try getting existing user' )
218270 else :
219271 success = True # Successfully tried getting existing user, might still be None (not found)
@@ -227,12 +279,14 @@ def lambda_handler(event, context):
227279 # Validate the auth_token
228280 decoded_backend_token = decrypt (query_params ['auth_token' ])
229281 if decoded_backend_token is None :
282+ record_failure_metric (f'Failed to authenticate with existing identity' )
230283 return generate_error ('Error: Failed to authenticate with existing identity' )
231284 # Set the user_id
232285 user_id = decoded_backend_token ['sub' ]
233286 # Try to link the new user to an existing user
234287 success = link_steam_id_to_existing_user (user_id , steam_user_id )
235288 if success is False :
289+ record_failure_metric (f'Failed to link new user to existing user' )
236290 return generate_error ('Error: Failed to link new user to existing user' )
237291
238292 # OPTION 3: Else If no user yet and we didn't request linking to an existing user, create one and add to user table
@@ -244,6 +298,7 @@ def lambda_handler(event, context):
244298 user_id = create_user (steam_user_id )
245299 tries += 1
246300 if user_id == None :
301+ record_failure_metric (f'Failed to create user' )
247302 return generate_error ('Error: Failed to create user' )
248303
249304 # Add user to Appe Id User table in both cases (linking and new user)
@@ -257,7 +312,9 @@ def lambda_handler(event, context):
257312 # Create for scope "authenticated" so backend can differentiate from guest users if needed
258313 auth_token , refresh_token , auth_token_expires_in , refresh_token_expires_in = encrypt (payload , "authenticated" )
259314 # NOTE: We might want to send back all attached identities from user table?
315+ record_success_metric ()
260316 return generate_success (user_id , steam_user_id , auth_token , refresh_token , auth_token_expires_in , refresh_token_expires_in )
261317
262318 # Failed to return success, return final error
319+ record_failure_metric (f'Invalid request' )
263320 return generate_error ('Error: Failed to authenticate' )
0 commit comments