velocity-python 0.0.193__tar.gz → 0.0.194__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. {velocity_python-0.0.193 → velocity_python-0.0.194}/PKG-INFO +1 -1
  2. {velocity_python-0.0.193 → velocity_python-0.0.194}/pyproject.toml +1 -1
  3. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/__init__.py +1 -1
  4. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/aws/handlers/base_handler.py +37 -6
  5. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/aws/handlers/lambda_handler.py +16 -9
  6. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/aws/handlers/mixins/web_handler.py +49 -1
  7. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity_python.egg-info/PKG-INFO +1 -1
  8. {velocity_python-0.0.193 → velocity_python-0.0.194}/LICENSE +0 -0
  9. {velocity_python-0.0.193 → velocity_python-0.0.194}/README.md +0 -0
  10. {velocity_python-0.0.193 → velocity_python-0.0.194}/setup.cfg +0 -0
  11. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/app/__init__.py +0 -0
  12. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/app/invoices.py +0 -0
  13. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/app/orders.py +0 -0
  14. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/app/payments.py +0 -0
  15. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/app/purchase_orders.py +0 -0
  16. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/app/tests/__init__.py +0 -0
  17. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/app/tests/test_email_processing.py +0 -0
  18. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/app/tests/test_payment_profile_sorting.py +0 -0
  19. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/app/tests/test_spreadsheet_functions.py +0 -0
  20. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/aws/__init__.py +0 -0
  21. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/aws/amplify.py +0 -0
  22. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/aws/handlers/__init__.py +0 -0
  23. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/aws/handlers/context.py +0 -0
  24. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/aws/handlers/exceptions.py +0 -0
  25. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/aws/handlers/mixins/__init__.py +0 -0
  26. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/aws/handlers/mixins/data_service.py +0 -0
  27. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/aws/handlers/response.py +0 -0
  28. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/aws/handlers/sqs_handler.py +0 -0
  29. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/aws/tests/__init__.py +0 -0
  30. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/aws/tests/test_lambda_handler_json_serialization.py +0 -0
  31. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/aws/tests/test_response.py +0 -0
  32. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/__init__.py +0 -0
  33. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/core/__init__.py +0 -0
  34. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/core/column.py +0 -0
  35. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/core/database.py +0 -0
  36. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/core/decorators.py +0 -0
  37. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/core/engine.py +0 -0
  38. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/core/result.py +0 -0
  39. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/core/row.py +0 -0
  40. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/core/sequence.py +0 -0
  41. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/core/table.py +0 -0
  42. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/core/transaction.py +0 -0
  43. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/exceptions.py +0 -0
  44. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/__init__.py +0 -0
  45. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/base/__init__.py +0 -0
  46. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/base/initializer.py +0 -0
  47. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/base/operators.py +0 -0
  48. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/base/sql.py +0 -0
  49. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/base/types.py +0 -0
  50. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/mysql/__init__.py +0 -0
  51. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/mysql/operators.py +0 -0
  52. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/mysql/reserved.py +0 -0
  53. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/mysql/sql.py +0 -0
  54. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/mysql/types.py +0 -0
  55. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/postgres/__init__.py +0 -0
  56. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/postgres/operators.py +0 -0
  57. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/postgres/reserved.py +0 -0
  58. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/postgres/sql.py +0 -0
  59. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/postgres/types.py +0 -0
  60. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/sqlite/__init__.py +0 -0
  61. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/sqlite/operators.py +0 -0
  62. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/sqlite/reserved.py +0 -0
  63. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/sqlite/sql.py +0 -0
  64. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/sqlite/types.py +0 -0
  65. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/sqlserver/__init__.py +0 -0
  66. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/sqlserver/operators.py +0 -0
  67. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/sqlserver/reserved.py +0 -0
  68. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/sqlserver/sql.py +0 -0
  69. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/sqlserver/types.py +0 -0
  70. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/servers/tablehelper.py +0 -0
  71. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/__init__.py +0 -0
  72. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/common_db_test.py +0 -0
  73. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/postgres/__init__.py +0 -0
  74. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/postgres/common.py +0 -0
  75. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/postgres/test_column.py +0 -0
  76. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/postgres/test_connections.py +0 -0
  77. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/postgres/test_database.py +0 -0
  78. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/postgres/test_engine.py +0 -0
  79. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/postgres/test_general_usage.py +0 -0
  80. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/postgres/test_imports.py +0 -0
  81. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/postgres/test_result.py +0 -0
  82. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/postgres/test_row.py +0 -0
  83. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/postgres/test_row_comprehensive.py +0 -0
  84. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/postgres/test_schema_locking.py +0 -0
  85. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/postgres/test_schema_locking_unit.py +0 -0
  86. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/postgres/test_sequence.py +0 -0
  87. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/postgres/test_sql_comprehensive.py +0 -0
  88. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/postgres/test_table.py +0 -0
  89. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/postgres/test_table_comprehensive.py +0 -0
  90. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/postgres/test_transaction.py +0 -0
  91. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/sql/__init__.py +0 -0
  92. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/sql/common.py +0 -0
  93. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/sql/test_postgres_select_advanced.py +0 -0
  94. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/sql/test_postgres_select_variances.py +0 -0
  95. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/test_cursor_rowcount_fix.py +0 -0
  96. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/test_db_utils.py +0 -0
  97. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/test_postgres.py +0 -0
  98. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/test_postgres_unchanged.py +0 -0
  99. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/test_process_error_robustness.py +0 -0
  100. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/test_result_caching.py +0 -0
  101. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/test_result_sql_aware.py +0 -0
  102. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/test_row_get_missing_column.py +0 -0
  103. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/test_schema_locking_initializers.py +0 -0
  104. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/test_schema_locking_simple.py +0 -0
  105. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/test_sql_builder.py +0 -0
  106. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/tests/test_tablehelper.py +0 -0
  107. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/db/utils.py +0 -0
  108. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/logging.py +0 -0
  109. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/misc/__init__.py +0 -0
  110. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/misc/conv/__init__.py +0 -0
  111. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/misc/conv/iconv.py +0 -0
  112. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/misc/conv/oconv.py +0 -0
  113. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/misc/db.py +0 -0
  114. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/misc/export.py +0 -0
  115. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/misc/format.py +0 -0
  116. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/misc/mail.py +0 -0
  117. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/misc/merge.py +0 -0
  118. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/misc/tests/__init__.py +0 -0
  119. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/misc/tests/test_db.py +0 -0
  120. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/misc/tests/test_fix.py +0 -0
  121. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/misc/tests/test_format.py +0 -0
  122. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/misc/tests/test_iconv.py +0 -0
  123. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/misc/tests/test_merge.py +0 -0
  124. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/misc/tests/test_oconv.py +0 -0
  125. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/misc/tests/test_original_error.py +0 -0
  126. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/misc/tests/test_timer.py +0 -0
  127. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/misc/timer.py +0 -0
  128. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/misc/tools.py +0 -0
  129. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/payment/__init__.py +0 -0
  130. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/payment/base_adapter.py +0 -0
  131. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/payment/braintree_adapter.py +0 -0
  132. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/payment/router.py +0 -0
  133. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity/payment/stripe_adapter.py +0 -0
  134. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity_python.egg-info/SOURCES.txt +0 -0
  135. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity_python.egg-info/dependency_links.txt +0 -0
  136. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity_python.egg-info/requires.txt +0 -0
  137. {velocity_python-0.0.193 → velocity_python-0.0.194}/src/velocity_python.egg-info/top_level.txt +0 -0
  138. {velocity_python-0.0.193 → velocity_python-0.0.194}/tests/test_decorators.py +0 -0
  139. {velocity_python-0.0.193 → velocity_python-0.0.194}/tests/test_lambda_handler.py +0 -0
  140. {velocity_python-0.0.193 → velocity_python-0.0.194}/tests/test_mixins_import.py +0 -0
  141. {velocity_python-0.0.193 → velocity_python-0.0.194}/tests/test_sys_modified_count_postgres_demo.py +0 -0
  142. {velocity_python-0.0.193 → velocity_python-0.0.194}/tests/test_table_alter.py +0 -0
  143. {velocity_python-0.0.193 → velocity_python-0.0.194}/tests/test_where_clause_validation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: velocity-python
3
- Version: 0.0.193
3
+ Version: 0.0.194
4
4
  Summary: A rapid application development library for interfacing with data storage
5
5
  Author-email: Velocity Team <info@codeclubs.org>
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "velocity-python"
7
- version = "0.0.193"
7
+ version = "0.0.194"
8
8
  authors = [
9
9
  { name="Velocity Team", email="info@codeclubs.org" },
10
10
  ]
@@ -1,4 +1,4 @@
1
- __version__ = version = "0.0.193"
1
+ __version__ = version = "0.0.194"
2
2
 
3
3
  from . import aws
4
4
  from . import db
@@ -5,13 +5,15 @@ This module provides a base class for handling AWS Lambda events.
5
5
  It includes common functionality shared between LambdaHandler and SqsHandler.
6
6
  """
7
7
 
8
+ import logging
8
9
  import os
9
10
  import sys
11
+ import time
10
12
  import traceback
11
13
  from typing import Any, Dict, List, Optional
12
14
 
13
15
  from velocity.aws.handlers import context as VelocityContext
14
- from velocity.logging import get_logger
16
+ logger = logging.getLogger(__name__)
15
17
 
16
18
 
17
19
  class BaseHandler:
@@ -22,8 +24,6 @@ class BaseHandler:
22
24
  and error handling hooks that can be shared across different handler types.
23
25
  """
24
26
 
25
- logger = get_logger("velocity.aws.handlers.base")
26
-
27
27
  def __init__(
28
28
  self,
29
29
  aws_event: Dict[str, Any],
@@ -131,9 +131,18 @@ class BaseHandler:
131
131
  Returns:
132
132
  True if an action was executed, False otherwise
133
133
  """
134
+ total_start = time.perf_counter()
135
+
134
136
  # Execute beforeAction hook if available
135
137
  if hasattr(self, "beforeAction"):
138
+ before_start = time.perf_counter()
136
139
  self.beforeAction(tx, local_context)
140
+ before_elapsed = (time.perf_counter() - before_start) * 1000
141
+ logger.info(
142
+ "Timing: beforeAction %.2f ms",
143
+ before_elapsed,
144
+ extra={"action": getattr(local_context, "action", lambda: None)()},
145
+ )
137
146
 
138
147
  action_executed = False
139
148
 
@@ -143,7 +152,15 @@ class BaseHandler:
143
152
  break
144
153
 
145
154
  if hasattr(self, action):
155
+ action_start = time.perf_counter()
146
156
  result = getattr(self, action)(tx, local_context)
157
+ action_elapsed = (time.perf_counter() - action_start) * 1000
158
+ logger.info(
159
+ "Timing: %s %.2f ms",
160
+ action,
161
+ action_elapsed,
162
+ extra={"action": getattr(local_context, "action", lambda: None)()},
163
+ )
147
164
  if result is not None:
148
165
  # Gather diagnostic information
149
166
  diagnostic_info = {
@@ -163,7 +180,7 @@ class BaseHandler:
163
180
  except Exception as e:
164
181
  diagnostic_info["diagnostic_error"] = str(e)
165
182
 
166
- self.logger.warning(
183
+ logger.warning(
167
184
  "Action %s returned an unexpected non-None result (%r).",
168
185
  action,
169
186
  result,
@@ -174,7 +191,21 @@ class BaseHandler:
174
191
 
175
192
  # Execute afterAction hook if available
176
193
  if hasattr(self, "afterAction"):
194
+ after_start = time.perf_counter()
177
195
  self.afterAction(tx, local_context)
196
+ after_elapsed = (time.perf_counter() - after_start) * 1000
197
+ logger.info(
198
+ "Timing: afterAction %.2f ms",
199
+ after_elapsed,
200
+ extra={"action": getattr(local_context, "action", lambda: None)()},
201
+ )
202
+
203
+ total_elapsed = (time.perf_counter() - total_start) * 1000
204
+ logger.info(
205
+ "Timing: execute_actions total %.2f ms",
206
+ total_elapsed,
207
+ extra={"action": getattr(local_context, "action", lambda: None)()},
208
+ )
178
209
 
179
210
  return action_executed
180
211
 
@@ -210,7 +241,7 @@ class BaseHandler:
210
241
  }
211
242
  self._extend_log_data(log_data)
212
243
 
213
- log_method = getattr(self.logger, level, self.logger.info)
244
+ log_method = getattr(logger, level, logger.info)
214
245
  log_method(
215
246
  "%s %s",
216
247
  function,
@@ -249,7 +280,7 @@ class BaseHandler:
249
280
  f" - action: {action}\n"
250
281
  f" - handler: {self.__class__.__name__}"
251
282
  )
252
- self.logger.warning(warning_message)
283
+ logger.warning(warning_message)
253
284
  local_context.response().set_body(
254
285
  {"event": self.aws_event, "postdata": local_context.postdata()}
255
286
  )
@@ -1,5 +1,6 @@
1
1
  import copy
2
2
  import json
3
+ import logging
3
4
  import os
4
5
  import pprint
5
6
  import time
@@ -7,11 +8,11 @@ from typing import Optional, Type
7
8
 
8
9
  from velocity.aws.handlers.base_handler import BaseHandler
9
10
  from velocity.aws.handlers.response import Response
10
- from velocity.logging import configure_logging, get_logger
11
+ from velocity.logging import configure_logging
11
12
  from . import context
12
13
 
13
14
  configure_logging()
14
- logger = get_logger("velocity.aws.handlers.lambda")
15
+ logger = logging.getLogger(__name__)
15
16
 
16
17
 
17
18
  class LambdaHandler(BaseHandler):
@@ -68,7 +69,10 @@ class LambdaHandler(BaseHandler):
68
69
  logger.debug("starting LamdaHandler.beforeAction")
69
70
 
70
71
 
72
+ cognito_start = time.perf_counter()
71
73
  self.cognito_user = context.get_cognito_user(self.aws_event)
74
+ cognito_elapsed = (time.perf_counter() - cognito_start) * 1000
75
+ logger.info("Timing: get_cognito_user %.2f ms", cognito_elapsed)
72
76
  self.current_user = {}
73
77
 
74
78
  logger.debug("DEBUG: !!! cognito_user %s", self.cognito_user)
@@ -76,9 +80,9 @@ class LambdaHandler(BaseHandler):
76
80
  email_address = self.cognito_user["attributes"]["email"]
77
81
  self.session["email_address"] = email_address
78
82
  except Exception:
79
- self.logger.warning("Unable to read email from Cognito user", exc_info=True)
83
+ logger.warning("Unable to read email from Cognito user", exc_info=True)
80
84
 
81
- self.logger.info(
85
+ logger.info(
82
86
  "Starting action",
83
87
  extra={
84
88
  "action": context.action(),
@@ -89,16 +93,19 @@ class LambdaHandler(BaseHandler):
89
93
  )
90
94
 
91
95
  if not self.user_table:
92
- self.logger.warning(
96
+ logger.warning(
93
97
  "user_table not configured; skipping DB lookup for %s",
94
98
  self.session.get("email_address"),
95
99
  )
96
100
  raise Exception(
97
101
  "User table not configured; cannot validate user [Config]"
98
102
  )
103
+ lookup_start = time.perf_counter()
99
104
  row = tx.table(self.user_table).find(
100
105
  {"email_address": self.session.get("email_address")}
101
106
  )
107
+ lookup_elapsed = (time.perf_counter() - lookup_start) * 1000
108
+ logger.info("Timing: user lookup %.2f ms", lookup_elapsed)
102
109
  if not row:
103
110
  raise Exception(
104
111
  "A valid user with permission is required to access this function [DB]"
@@ -107,7 +114,7 @@ class LambdaHandler(BaseHandler):
107
114
 
108
115
  temp = copy.deepcopy(context.postdata())
109
116
  temp["payload"].pop("cognito_user", None)
110
- self.logger.debug(
117
+ logger.debug(
111
118
  "Events.OnAction %s",
112
119
  temp.get("action"),
113
120
  extra={"payload": pprint.pformat(temp)},
@@ -121,7 +128,7 @@ class LambdaHandler(BaseHandler):
121
128
  logger.debug("starting LamdaHandler.afterAction")
122
129
 
123
130
  self.end = time.time()
124
- self.logger.info(
131
+ logger.info(
125
132
  "Completed action",
126
133
  extra={
127
134
  "action": context.action(),
@@ -135,7 +142,7 @@ class LambdaHandler(BaseHandler):
135
142
  return
136
143
  logger.debug("starting LamdaHandler.aws_api_activity")
137
144
  request_id = getattr(self.aws_context, "aws_request_id", None)
138
- self.logger.error(
145
+ logger.error(
139
146
  "Unhandled exception for action %s",
140
147
  context.action(),
141
148
  exc_info=exc,
@@ -147,7 +154,7 @@ class LambdaHandler(BaseHandler):
147
154
  temp = copy.deepcopy(context.postdata())
148
155
  logger.debug("starting BackOfficeEvents.log")
149
156
  temp["payload"].pop("cognito_user", None)
150
- self.logger.error(
157
+ logger.error(
151
158
  "Events.OnError %s",
152
159
  temp.get("action"),
153
160
  extra={"payload": pprint.pformat(temp), "traceback": tb},
@@ -36,6 +36,8 @@ class WebHandler(ABC):
36
36
  self.end_time = None
37
37
  self.activity_log_key = None
38
38
  self.activity_data = {}
39
+ self._perf_timing_enabled = False
40
+ self._perf_timing_start = None
39
41
 
40
42
  # ------------------------------------------------------------------
41
43
  # Activity helpers
@@ -132,6 +134,29 @@ class WebHandler(ABC):
132
134
 
133
135
  return json.dumps(sanitized)
134
136
 
137
+ def _is_performance_timing_enabled(self, context) -> bool:
138
+ """Check postdata/payload for log_performance_timing=true"""
139
+ try:
140
+ postdata = context.postdata() or {}
141
+ except Exception:
142
+ return False
143
+
144
+ def normalize(val):
145
+ if isinstance(val, bool):
146
+ return val
147
+ if val is None:
148
+ return False
149
+ return str(val).strip().lower() in {"true", "1", "yes", "y"}
150
+
151
+ if normalize(postdata.get("log_performance_timing")):
152
+ return True
153
+
154
+ payload = postdata.get("payload") if isinstance(postdata, dict) else None
155
+ if isinstance(payload, dict) and normalize(payload.get("log_performance_timing")):
156
+ return True
157
+
158
+ return False
159
+
135
160
  def _recursive_sanitize(self, data: Any, sensitive_fields: List[str]):
136
161
  """Recursively remove sensitive fields from nested data structures"""
137
162
  if isinstance(data, dict):
@@ -372,15 +397,38 @@ Request Details:
372
397
 
373
398
  def _enhanced_before_action(self, tx, context):
374
399
  """Enhanced beforeAction that adds activity tracking"""
400
+ self._perf_timing_enabled = self._is_performance_timing_enabled(context)
401
+ if self._perf_timing_enabled:
402
+ self._perf_timing_start = time.perf_counter()
403
+ logger.info(
404
+ "Performance timing enabled: start action=%s handler=%s",
405
+ context.action(),
406
+ self.__class__.__name__,
407
+ )
375
408
  self.track_activity_start(tx, context)
376
409
 
377
410
  def _enhanced_after_action(self, tx, context):
378
411
  """Enhanced afterAction that adds activity tracking"""
379
412
  self.track_activity_success(tx, context)
413
+ if self._perf_timing_enabled and self._perf_timing_start is not None:
414
+ elapsed_ms = (time.perf_counter() - self._perf_timing_start) * 1000
415
+ logger.info(
416
+ "Performance timing end: action=%s handler=%s duration=%.2f ms",
417
+ context.action(),
418
+ self.__class__.__name__,
419
+ elapsed_ms,
420
+ )
380
421
 
381
422
  def _enhanced_error_handler(self, tx, context, exc, tb):
382
423
  """Enhanced onError that adds standardized error handling"""
383
-
424
+ if self._perf_timing_enabled and self._perf_timing_start is not None:
425
+ elapsed_ms = (time.perf_counter() - self._perf_timing_start) * 1000
426
+ logger.info(
427
+ "Performance timing error: action=%s handler=%s duration=%.2f ms",
428
+ context.action(),
429
+ self.__class__.__name__,
430
+ elapsed_ms,
431
+ )
384
432
 
385
433
  self.track_activity_error(tx, context, exc, tb)
386
434
  self.log_error_to_system(tx, context, exc, tb)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: velocity-python
3
- Version: 0.0.193
3
+ Version: 0.0.194
4
4
  Summary: A rapid application development library for interfacing with data storage
5
5
  Author-email: Velocity Team <info@codeclubs.org>
6
6
  License-Expression: MIT