4747import google .registry .model .eppinput .EppInput .Services ;
4848import google .registry .model .eppoutput .EppResponse ;
4949import google .registry .model .registrar .Registrar ;
50+ import google .registry .util .StopwatchLogger ;
5051import jakarta .inject .Inject ;
52+ import java .time .Duration ;
5153import java .util .Optional ;
5254import java .util .Set ;
5355
@@ -97,19 +99,25 @@ public final EppResponse run() throws EppException {
9799
98100 /** Run the flow without bothering to log errors. The {@link #run} method will do that for us. */
99101 private EppResponse runWithoutLogging () throws EppException {
102+ final StopwatchLogger stopwatch = new StopwatchLogger (logger , Duration .ofMillis (400 ));
100103 extensionManager .validate (); // There are no legal extensions for this flow.
104+ stopwatch .tick ("LoginFlow extension validate" );
101105 Login login = (Login ) eppInput .getCommandWrapper ().getCommand ();
106+ stopwatch .tick ("LoginFlow getCommand" );
102107 if (!registrarId .isEmpty ()) {
103108 throw new AlreadyLoggedInException ();
104109 }
105110 Options options = login .getOptions ();
111+ stopwatch .tick ("LoginFlow getOptions" );
106112 if (!ProtocolDefinition .LANGUAGE .equals (options .getLanguage ())) {
107113 throw new UnsupportedLanguageException ();
108114 }
109115 Services services = login .getServices ();
116+ stopwatch .tick ("LoginFlow getServices" );
110117 Set <String > unsupportedObjectServices = difference (
111118 nullToEmpty (services .getObjectServices ()),
112119 ProtocolDefinition .SUPPORTED_OBJECT_SERVICES );
120+ stopwatch .tick ("LoginFlow difference unsupportedObjectServices" );
113121 if (!unsupportedObjectServices .isEmpty ()) {
114122 throw new UnimplementedObjectServiceException ();
115123 }
@@ -121,11 +129,12 @@ private EppResponse runWithoutLogging() throws EppException {
121129 }
122130 serviceExtensionUrisBuilder .add (uri );
123131 }
132+ stopwatch .tick ("LoginFlow serviceExtensionUrisBuilder" );
124133 Optional <Registrar > registrar = Registrar .loadByRegistrarIdCached (login .getClientId ());
125134 if (registrar .isEmpty ()) {
126135 throw new BadRegistrarIdException (login .getClientId ());
127136 }
128-
137+ stopwatch . tick ( "LoginFlow loadByRegistrarIdCached" );
129138 // AuthenticationErrorExceptions will propagate up through here.
130139 try {
131140 credentials .validate (registrar .get (), login .getPassword ());
@@ -137,6 +146,7 @@ private EppResponse runWithoutLogging() throws EppException {
137146 throw e ;
138147 }
139148 }
149+ stopwatch .tick ("LoginFlow credentials.validate" );
140150 if (!registrar .get ().isLive ()) {
141151 throw new RegistrarAccountNotActiveException ();
142152 }
@@ -145,17 +155,24 @@ private EppResponse runWithoutLogging() throws EppException {
145155 String newPassword = login .getNewPassword ().get ();
146156 // Load fresh from database (bypassing the cache) to ensure we don't save stale data.
147157 Optional <Registrar > freshRegistrar = Registrar .loadByRegistrarId (login .getClientId ());
158+ stopwatch .tick ("LoginFlow reload freshRegistrar" );
148159 if (freshRegistrar .isEmpty ()) {
149160 throw new BadRegistrarIdException (login .getClientId ());
150161 }
151162 tm ().put (freshRegistrar .get ().asBuilder ().setPassword (newPassword ).build ());
163+ stopwatch .tick ("LoginFlow updated password" );
152164 }
153165
154166 // We are in!
155167 sessionMetadata .resetFailedLoginAttempts ();
168+ stopwatch .tick ("LoginFlow resetFailedLoginAttempts" );
156169 sessionMetadata .setRegistrarId (login .getClientId ());
170+ stopwatch .tick ("LoginFlow setRegistrarId" );
157171 sessionMetadata .setServiceExtensionUris (serviceExtensionUrisBuilder .build ());
158- return responseBuilder .setIsLoginResponse ().build ();
172+ stopwatch .tick ("LoginFlow setServiceExtensionUris" );
173+ EppResponse eppResponse = responseBuilder .setIsLoginResponse ().build ();
174+ stopwatch .tick ("LoginFlow eppResponse build()" );
175+ return eppResponse ;
159176 }
160177
161178 /** Registrar with this ID could not be found. */
0 commit comments