nui-lambda-shared-utils 1.1.1__tar.gz → 1.1.4__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 (65) hide show
  1. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/PKG-INFO +1 -1
  2. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/docs/README.md +8 -3
  3. nui_lambda_shared_utils-1.1.4/docs/guides/elasticsearch-integration.md +375 -0
  4. nui_lambda_shared_utils-1.1.4/docs/guides/lambda-utilities.md +274 -0
  5. nui_lambda_shared_utils-1.1.4/docs/guides/shared-types.md +527 -0
  6. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/nui_lambda_shared_utils/__init__.py +5 -0
  7. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/nui_lambda_shared_utils/cli.py +1 -1
  8. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/nui_lambda_shared_utils/cloudwatch_metrics.py +2 -2
  9. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/nui_lambda_shared_utils/db_client.py +1 -1
  10. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/nui_lambda_shared_utils/error_handler.py +1 -1
  11. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/nui_lambda_shared_utils/es_client.py +82 -4
  12. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/nui_lambda_shared_utils/es_query_builder.py +2 -2
  13. nui_lambda_shared_utils-1.1.4/nui_lambda_shared_utils/lambda_helpers.py +84 -0
  14. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/nui_lambda_shared_utils/powertools_helpers.py +15 -7
  15. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/nui_lambda_shared_utils/slack_client.py +12 -7
  16. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/nui_lambda_shared_utils/slack_setup/channel_creator.py +1 -1
  17. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/nui_lambda_shared_utils.egg-info/SOURCES.txt +5 -0
  18. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/tests/test_aws_utils.py +0 -2
  19. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/tests/test_base_client.py +1 -2
  20. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/tests/test_cloudwatch_metrics.py +3 -2
  21. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/tests/test_config.py +0 -1
  22. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/tests/test_db_client.py +3 -2
  23. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/tests/test_error_handler.py +1 -5
  24. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/tests/test_es_client.py +147 -1
  25. nui_lambda_shared_utils-1.1.4/tests/test_lambda_helpers.py +247 -0
  26. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/tests/test_powertools_helpers.py +2 -4
  27. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/tests/test_slack_client.py +4 -2
  28. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/tests/test_slack_formatter.py +1 -2
  29. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/tests/test_timezone.py +0 -2
  30. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/tests/test_utils.py +1 -1
  31. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/.editorconfig +0 -0
  32. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/.github/workflows/ci.yml +0 -0
  33. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/.github/workflows/publish.yml +0 -0
  34. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/.github/workflows/test.yml +0 -0
  35. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/.markdownlint-cli2.yaml +0 -0
  36. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/CLAUDE.md +0 -0
  37. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/CONTRIBUTING.md +0 -0
  38. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/LICENSE +0 -0
  39. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/MANIFEST.in +0 -0
  40. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/README.md +0 -0
  41. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/docs/development/testing.md +0 -0
  42. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/docs/getting-started/configuration.md +0 -0
  43. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/docs/getting-started/installation.md +0 -0
  44. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/docs/getting-started/quickstart.md +0 -0
  45. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/docs/guides/cli-tools.md +0 -0
  46. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/docs/guides/powertools-integration.md +0 -0
  47. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/docs/guides/slack-integration.md +0 -0
  48. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/mypy.ini +0 -0
  49. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/nui_lambda_shared_utils/base_client.py +0 -0
  50. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/nui_lambda_shared_utils/config.py +0 -0
  51. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/nui_lambda_shared_utils/secrets_helper.py +0 -0
  52. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/nui_lambda_shared_utils/slack_formatter.py +0 -0
  53. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/nui_lambda_shared_utils/slack_setup/__init__.py +0 -0
  54. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/nui_lambda_shared_utils/slack_setup/channel_definitions.py +0 -0
  55. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/nui_lambda_shared_utils/slack_setup/setup_helpers.py +0 -0
  56. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/nui_lambda_shared_utils/timezone.py +0 -0
  57. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/nui_lambda_shared_utils/utils.py +0 -0
  58. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/pyproject.toml +0 -0
  59. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/pytest.ini +0 -0
  60. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/requirements-test.txt +0 -0
  61. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/setup.cfg +0 -0
  62. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/setup.py +0 -0
  63. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/tests/__init__.py +0 -0
  64. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/tests/test_es_query_builder.py +0 -0
  65. {nui_lambda_shared_utils-1.1.1 → nui_lambda_shared_utils-1.1.4}/tests/test_secrets_helper.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nui-lambda-shared-utils
3
- Version: 1.1.1
3
+ Version: 1.1.4
4
4
  Summary: Enterprise-grade utilities for AWS Lambda functions with Slack, Elasticsearch, and monitoring integrations
5
5
  Home-page: https://github.com/nuimarkets/nui-lambda-shared-utils
6
6
  Author: NUI Markets
@@ -17,8 +17,9 @@ Welcome to the comprehensive documentation for `nui-lambda-shared-utils`.
17
17
  Component-specific guides for major features:
18
18
 
19
19
  - **[AWS Powertools Integration](guides/powertools-integration.md)** - Standardized logging, metrics, and error handling
20
+ - **[Lambda Context Helpers](guides/lambda-utilities.md)** - Environment info extraction for logging and metrics
20
21
  - **[Slack Integration](guides/slack-integration.md)** - Messaging, formatting, and file uploads
21
- - Elasticsearch Operations (planned)
22
+ - **[Elasticsearch Integration](guides/elasticsearch-integration.md)** - Search, bulk indexing, health checks
22
23
  - Database Connections (planned)
23
24
  - Error Handling Patterns (planned)
24
25
  - CloudWatch Metrics (planned)
@@ -32,8 +33,9 @@ Command-line utilities included with the package:
32
33
 
33
34
  ### 📋 Reference
34
35
 
35
- API reference and detailed component documentation (planned):
36
+ API reference and detailed component documentation:
36
37
 
38
+ - **[Shared Types & Data Structures](guides/shared-types.md)** - Core types, interfaces, and response structures
37
39
  - Client APIs (planned)
38
40
  - Utility Functions (planned)
39
41
  - Configuration Options (planned)
@@ -117,14 +119,17 @@ When contributing to documentation:
117
119
  - Main documentation (this README)
118
120
  - Getting started guides (installation, configuration, quickstart)
119
121
  - AWS Powertools integration guide (guides/powertools-integration.md)
122
+ - Lambda context helpers guide (guides/lambda-utilities.md)
120
123
  - Slack integration guide (guides/slack-integration.md)
124
+ - Elasticsearch integration guide (guides/elasticsearch-integration.md)
125
+ - Shared types reference (guides/shared-types.md)
121
126
  - CLI tools guide (guides/cli-tools.md)
122
127
  - Testing guide (development/testing.md)
123
128
  - Configuration templates (Slack account names, channel setup)
124
129
 
125
130
  ### 🚧 Planned
126
131
 
127
- - Component-specific guides (Elasticsearch, Database, Metrics, Error Handling)
132
+ - Component-specific guides (Database, Metrics, Error Handling)
128
133
  - API reference documentation
129
134
  - Advanced topics (AWS infrastructure, Lambda integration)
130
135
  - Troubleshooting guide
@@ -0,0 +1,375 @@
1
+ # Elasticsearch Integration Guide
2
+
3
+ Comprehensive guide for using Elasticsearch utilities in `nui-lambda-shared-utils`.
4
+
5
+ **Last Updated**: 2026-01-30
6
+
7
+ ## Overview
8
+
9
+ The package provides Elasticsearch integration through:
10
+
11
+ - **ElasticsearchClient** - Search, aggregations, bulk indexing, health checks
12
+ - **ElasticsearchQueryBuilder** - Fluent query construction
13
+
14
+ ## Quick Start
15
+
16
+ ```python
17
+ import nui_lambda_shared_utils as nui
18
+
19
+ # Configure Elasticsearch credentials
20
+ nui.configure(es_credentials_secret="prod/elasticsearch-credentials")
21
+
22
+ # Create client and search
23
+ es = nui.ElasticsearchClient()
24
+ results = es.search(
25
+ index="logs-*",
26
+ body={"query": {"match": {"level": "error"}}}
27
+ )
28
+ ```
29
+
30
+ ## Installation
31
+
32
+ Install with the elasticsearch extra:
33
+
34
+ ```bash
35
+ pip install nui-lambda-shared-utils[elasticsearch]
36
+ ```
37
+
38
+ ## Configuration
39
+
40
+ ### AWS Secrets Manager Setup
41
+
42
+ Create a secret with your Elasticsearch credentials:
43
+
44
+ ```bash
45
+ aws secretsmanager create-secret \
46
+ --name "elasticsearch-credentials" \
47
+ --description "Elasticsearch credentials" \
48
+ --secret-string '{"username":"elastic","password":"YOUR_PASSWORD"}'
49
+ ```
50
+
51
+ **Secret Format:**
52
+
53
+ ```json
54
+ {
55
+ "username": "elastic",
56
+ "password": "YOUR_PASSWORD"
57
+ }
58
+ ```
59
+
60
+ ### Environment Variables
61
+
62
+ | Variable | Description | Default |
63
+ |----------|-------------|---------|
64
+ | `ES_HOST` | Elasticsearch host | `localhost:9200` |
65
+ | `ES_CREDENTIALS_SECRET` | Secret name for credentials | `elasticsearch-credentials` |
66
+
67
+ ### Programmatic Configuration
68
+
69
+ ```python
70
+ import nui_lambda_shared_utils as nui
71
+
72
+ # Configure at startup
73
+ nui.configure(
74
+ es_host="elasticsearch.example.com:9200",
75
+ es_credentials_secret="prod/es-creds"
76
+ )
77
+
78
+ # Or pass directly to client
79
+ client = nui.ElasticsearchClient(
80
+ host="elasticsearch.example.com:9200",
81
+ secret_name="prod/es-creds"
82
+ )
83
+ ```
84
+
85
+ ## Basic Operations
86
+
87
+ ### Search
88
+
89
+ ```python
90
+ from nui_lambda_shared_utils import ElasticsearchClient
91
+
92
+ es = ElasticsearchClient()
93
+
94
+ # Simple search
95
+ results = es.search(
96
+ index="logs-*",
97
+ body={"query": {"match_all": {}}},
98
+ size=100
99
+ )
100
+
101
+ for doc in results:
102
+ print(doc["message"])
103
+ ```
104
+
105
+ ### Aggregations
106
+
107
+ ```python
108
+ # Get aggregation results
109
+ aggs = es.aggregate(
110
+ index="logs-*",
111
+ body={
112
+ "query": {"range": {"@timestamp": {"gte": "now-1h"}}},
113
+ "aggs": {
114
+ "by_level": {"terms": {"field": "level.keyword"}},
115
+ "avg_duration": {"avg": {"field": "duration"}}
116
+ }
117
+ }
118
+ )
119
+
120
+ print(aggs["by_level"]["buckets"])
121
+ ```
122
+
123
+ ### Count Documents
124
+
125
+ ```python
126
+ # Count all documents
127
+ total = es.count(index="logs-*")
128
+
129
+ # Count with query
130
+ errors = es.count(
131
+ index="logs-*",
132
+ body={"query": {"term": {"level": "error"}}}
133
+ )
134
+ ```
135
+
136
+ ## Bulk Indexing
137
+
138
+ ### streaming_bulk Method
139
+
140
+ For efficient bulk indexing of documents, use the `streaming_bulk` method:
141
+
142
+ ```python
143
+ from nui_lambda_shared_utils import ElasticsearchClient
144
+
145
+ es = ElasticsearchClient()
146
+
147
+ def generate_documents():
148
+ """Yield documents to index."""
149
+ for item in items:
150
+ yield {
151
+ "_index": "my-index",
152
+ "_source": {
153
+ "field1": item.field1,
154
+ "field2": item.field2,
155
+ "@timestamp": item.timestamp.isoformat()
156
+ }
157
+ }
158
+
159
+ # Index documents with automatic error handling
160
+ success, failed = es.streaming_bulk(
161
+ actions=generate_documents(),
162
+ chunk_size=100,
163
+ max_retries=2
164
+ )
165
+
166
+ print(f"Indexed {success} documents, {failed} failures")
167
+ ```
168
+
169
+ ### Parameters
170
+
171
+ | Parameter | Type | Default | Description |
172
+ |-----------|------|---------|-------------|
173
+ | `actions` | Iterator[Dict] | required | Iterator yielding action dictionaries |
174
+ | `chunk_size` | int | 100 | Documents per batch |
175
+ | `max_retries` | int | 2 | Retries for failed documents |
176
+ | `raise_on_error` | bool | False | Raise exception on first error |
177
+
178
+ ### Action Dictionary Format
179
+
180
+ Each yielded action should contain:
181
+
182
+ ```python
183
+ {
184
+ "_index": "target-index-name",
185
+ "_source": {
186
+ # Your document fields
187
+ },
188
+ # Optional fields:
189
+ "_id": "custom-id", # Auto-generated if not provided
190
+ "_op_type": "index" # "index", "create", "update", "delete"
191
+ }
192
+ ```
193
+
194
+ ### Error Handling
195
+
196
+ By default, `streaming_bulk` logs errors but continues processing:
197
+
198
+ ```python
199
+ # Default: log errors, continue processing
200
+ success, failed = es.streaming_bulk(generate_docs())
201
+ if failed > 0:
202
+ logger.warning(f"{failed} documents failed to index")
203
+
204
+ # Strict mode: raise on first error
205
+ try:
206
+ success, failed = es.streaming_bulk(
207
+ generate_docs(),
208
+ raise_on_error=True
209
+ )
210
+ except Exception as e:
211
+ logger.error(f"Bulk indexing failed: {e}")
212
+ ```
213
+
214
+ ### Integration with Log Processors
215
+
216
+ The `streaming_bulk` method pairs well with log extraction utilities:
217
+
218
+ ```python
219
+ from nui_lambda_shared_utils import ElasticsearchClient
220
+
221
+ es = ElasticsearchClient()
222
+
223
+ def extract_logs_from_kinesis(records):
224
+ """Extract logs from Kinesis records."""
225
+ for record in records:
226
+ # Your log extraction logic
227
+ yield {
228
+ "_index": f"logs-{service_name}-{date}",
229
+ "_source": log_data
230
+ }
231
+
232
+ def handler(event, context):
233
+ success, failed = es.streaming_bulk(
234
+ actions=extract_logs_from_kinesis(event["Records"]),
235
+ chunk_size=200
236
+ )
237
+ return {"indexed": success, "failed": failed}
238
+ ```
239
+
240
+ ## Service Statistics
241
+
242
+ Get comprehensive service statistics:
243
+
244
+ ```python
245
+ stats = es.get_service_stats(
246
+ service="order",
247
+ hours=24,
248
+ index_prefix="logs"
249
+ )
250
+
251
+ print(f"Total requests: {stats['total_count']}")
252
+ print(f"Error rate: {stats['error_rate']:.2f}%")
253
+ print(f"P95 latency: {stats['p95_response_time']}ms")
254
+ ```
255
+
256
+ ## Recent Errors
257
+
258
+ Retrieve recent error logs:
259
+
260
+ ```python
261
+ errors = es.get_recent_errors(
262
+ service="auth",
263
+ hours=1,
264
+ limit=10
265
+ )
266
+
267
+ for error in errors:
268
+ print(f"{error['@timestamp']}: {error['message']}")
269
+ ```
270
+
271
+ ## Health Checks
272
+
273
+ ### Cluster Health
274
+
275
+ ```python
276
+ # Get cluster info
277
+ info = es.get_cluster_info()
278
+ print(f"Cluster: {info['cluster_name']}, Status: {info['cluster_status']}")
279
+
280
+ # Check health (raises on failure)
281
+ health = es.check_health()
282
+ ```
283
+
284
+ ### Index Information
285
+
286
+ ```python
287
+ indices = es.get_indices_info(pattern="logs-*")
288
+ for idx in indices:
289
+ print(f"{idx['index']}: {idx['docs.count']} docs, {idx['store.size']}")
290
+ ```
291
+
292
+ ## Query Builder
293
+
294
+ For complex queries, use the query builder:
295
+
296
+ ```python
297
+ from nui_lambda_shared_utils import ElasticsearchQueryBuilder
298
+
299
+ query = (
300
+ ElasticsearchQueryBuilder()
301
+ .must_match("service", "order")
302
+ .must_range("@timestamp", gte="now-1h")
303
+ .filter_term("level", "error")
304
+ .sort("@timestamp", "desc")
305
+ .build()
306
+ )
307
+
308
+ results = es.search(index="logs-*", body=query)
309
+ ```
310
+
311
+ ## Lambda Handler Pattern
312
+
313
+ Recommended pattern for Lambda functions:
314
+
315
+ ```python
316
+ import os
317
+ import nui_lambda_shared_utils as nui
318
+ from nui_lambda_shared_utils import (
319
+ ElasticsearchClient,
320
+ get_powertools_logger,
321
+ powertools_handler
322
+ )
323
+
324
+ # Configure once at module level
325
+ nui.configure(
326
+ es_host=os.environ.get("ES_HOST"),
327
+ es_credentials_secret=os.environ.get("ES_CREDENTIALS_SECRET")
328
+ )
329
+
330
+ logger = get_powertools_logger("my-service")
331
+
332
+
333
+ @powertools_handler(service_name="my-service")
334
+ def handler(event, context):
335
+ es = ElasticsearchClient()
336
+
337
+ # Your indexing logic
338
+ success, failed = es.streaming_bulk(
339
+ actions=process_records(event["Records"])
340
+ )
341
+
342
+ logger.info(f"Indexed {success} documents, {failed} failures")
343
+ return {"statusCode": 200, "body": f"Processed {success} documents"}
344
+ ```
345
+
346
+ ## Troubleshooting
347
+
348
+ ### Connection Issues
349
+
350
+ ```python
351
+ # Test connectivity
352
+ try:
353
+ es = ElasticsearchClient()
354
+ info = es.get_cluster_info()
355
+ print(f"Connected to: {info['cluster_name']}")
356
+ except Exception as e:
357
+ print(f"Connection failed: {e}")
358
+ ```
359
+
360
+ ### Common Errors
361
+
362
+ | Error | Cause | Solution |
363
+ |-------|-------|----------|
364
+ | `AuthenticationException` | Invalid credentials | Check secret values |
365
+ | `ConnectionError` | Host unreachable | Verify `ES_HOST` and network |
366
+ | `TransportError(403)` | Missing permissions | Check index permissions |
367
+
368
+ ### Debug Logging
369
+
370
+ Enable debug logging for troubleshooting:
371
+
372
+ ```python
373
+ import logging
374
+ logging.getLogger("elasticsearch").setLevel(logging.DEBUG)
375
+ ```
@@ -0,0 +1,274 @@
1
+ # Lambda Context Helpers Guide
2
+
3
+ This guide covers the Lambda context helpers provided by `nui-lambda-shared-utils`. These utilities provide standardized environment info extraction for logging context, metric dimensions, and conditional behavior based on execution environment.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Installation](#installation)
8
+ - [Quick Start](#quick-start)
9
+ - [Function Reference](#function-reference)
10
+ - [Usage Patterns](#usage-patterns)
11
+ - [Environment Detection](#environment-detection)
12
+ - [Related Documentation](#related-documentation)
13
+
14
+ ## Installation
15
+
16
+ No additional dependencies required. Lambda helpers use only Python standard library:
17
+
18
+ ```bash
19
+ # Base package includes lambda_helpers
20
+ pip install nui-lambda-shared-utils
21
+ ```
22
+
23
+ ## Quick Start
24
+
25
+ ```python
26
+ from nui_lambda_shared_utils import get_lambda_environment_info
27
+
28
+ def handler(event, context):
29
+ env_info = get_lambda_environment_info()
30
+
31
+ # Use for conditional behavior
32
+ if env_info["is_local"]:
33
+ print("Running locally")
34
+ else:
35
+ print(f"Running in Lambda: {env_info['function_name']}")
36
+
37
+ return {"statusCode": 200}
38
+ ```
39
+
40
+ ## Function Reference
41
+
42
+ ### `get_lambda_environment_info()`
43
+
44
+ Extracts standard Lambda environment info from environment variables.
45
+
46
+ **Signature:**
47
+
48
+ ```python
49
+ def get_lambda_environment_info() -> Dict[str, str | bool]:
50
+ """
51
+ Extract standard Lambda environment info.
52
+
53
+ Returns:
54
+ Dict with keys:
55
+ - environment: "prod" | "dev" | "staging" | "unknown"
56
+ - aws_region: AWS region (e.g., "ap-southeast-2")
57
+ - function_name: Lambda function name
58
+ - function_version: Lambda function version (e.g., "$LATEST")
59
+ - memory_limit: Memory limit in MB (e.g., "512")
60
+ - is_local: True if running outside Lambda environment
61
+ """
62
+ ```
63
+
64
+ **Return Value Example:**
65
+
66
+ ```python
67
+ {
68
+ "environment": "prod",
69
+ "aws_region": "ap-southeast-2",
70
+ "function_name": "order-processor",
71
+ "function_version": "$LATEST",
72
+ "memory_limit": "512",
73
+ "is_local": False
74
+ }
75
+ ```
76
+
77
+ **Environment Variable Sources:**
78
+
79
+ | Return Key | Primary Env Var | Fallback | Default |
80
+ |------------|-----------------|----------|---------|
81
+ | `environment` | `ENVIRONMENT` | `ENV`, `STAGE` | `"unknown"` |
82
+ | `aws_region` | `AWS_REGION` | `AWS_DEFAULT_REGION` | `""` |
83
+ | `function_name` | `AWS_LAMBDA_FUNCTION_NAME` | - | `""` |
84
+ | `function_version` | `AWS_LAMBDA_FUNCTION_VERSION` | - | `""` |
85
+ | `memory_limit` | `AWS_LAMBDA_FUNCTION_MEMORY_SIZE` | - | `""` |
86
+ | `is_local` | (absence of `AWS_LAMBDA_RUNTIME_API`) | - | `True` |
87
+
88
+ **Environment Normalization:**
89
+
90
+ The `environment` value is normalized for consistency:
91
+
92
+ - `"production"`, `"prd"` → `"prod"`
93
+ - `"development"` → `"dev"`
94
+ - All values are lowercased
95
+
96
+ ## Usage Patterns
97
+
98
+ ### With Powertools Logger
99
+
100
+ Add environment context to structured logs:
101
+
102
+ ```python
103
+ from nui_lambda_shared_utils import get_powertools_logger, get_lambda_environment_info
104
+
105
+ logger = get_powertools_logger("my-service")
106
+
107
+ def handler(event, context):
108
+ env_info = get_lambda_environment_info()
109
+
110
+ logger.info(
111
+ "Processing event",
112
+ extra={
113
+ **env_info,
114
+ "event_type": event.get("type")
115
+ }
116
+ )
117
+
118
+ return {"statusCode": 200}
119
+ ```
120
+
121
+ ### With CloudWatch Metrics
122
+
123
+ Add standard dimensions to metrics:
124
+
125
+ ```python
126
+ from nui_lambda_shared_utils import MetricsPublisher, get_lambda_environment_info
127
+
128
+ def handler(event, context):
129
+ env_info = get_lambda_environment_info()
130
+
131
+ metrics = MetricsPublisher(namespace="MyService")
132
+ metrics.add_dimension("Environment", env_info["environment"])
133
+ metrics.add_dimension("FunctionName", env_info["function_name"])
134
+ metrics.add_dimension("Region", env_info["aws_region"])
135
+
136
+ # Publish metrics with consistent dimensions
137
+ metrics.put_metric("ProcessedEvents", 1, "Count")
138
+
139
+ return {"statusCode": 200}
140
+ ```
141
+
142
+ ### Conditional Behavior
143
+
144
+ Execute different code paths based on environment:
145
+
146
+ ```python
147
+ from nui_lambda_shared_utils import get_lambda_environment_info
148
+
149
+ def handler(event, context):
150
+ env_info = get_lambda_environment_info()
151
+
152
+ # Use different configuration for local vs Lambda
153
+ if env_info["is_local"]:
154
+ config = load_local_config()
155
+ else:
156
+ config = load_lambda_config()
157
+
158
+ # Environment-specific behavior
159
+ if env_info["environment"] == "prod":
160
+ send_to_production_queue(event)
161
+ else:
162
+ send_to_dev_queue(event)
163
+
164
+ return {"statusCode": 200}
165
+ ```
166
+
167
+ ### Error Context Enhancement
168
+
169
+ Include environment info in error reports:
170
+
171
+ ```python
172
+ from nui_lambda_shared_utils import (
173
+ get_powertools_logger,
174
+ get_lambda_environment_info,
175
+ SlackClient
176
+ )
177
+
178
+ logger = get_powertools_logger("my-service")
179
+
180
+ def handler(event, context):
181
+ env_info = get_lambda_environment_info()
182
+
183
+ try:
184
+ process_event(event)
185
+ except Exception as e:
186
+ logger.exception(
187
+ "Handler failed",
188
+ extra={
189
+ **env_info,
190
+ "error_type": type(e).__name__,
191
+ "error_message": str(e)
192
+ }
193
+ )
194
+
195
+ # Include environment context in Slack alerts
196
+ slack = SlackClient()
197
+ slack.send_message(
198
+ channel="#errors",
199
+ text=(
200
+ f"*Error in {env_info['function_name']}*\n"
201
+ f"Environment: {env_info['environment']}\n"
202
+ f"Region: {env_info['aws_region']}\n"
203
+ f"Error: {str(e)}"
204
+ )
205
+ )
206
+ raise
207
+
208
+ return {"statusCode": 200}
209
+ ```
210
+
211
+ ## Environment Detection
212
+
213
+ ### How `is_local` Works
214
+
215
+ The `is_local` flag detects whether code is running in a Lambda environment:
216
+
217
+ ```python
218
+ # Detection logic
219
+ is_local = os.getenv("AWS_LAMBDA_RUNTIME_API") is None
220
+ ```
221
+
222
+ **Detection Rules:**
223
+
224
+ | `AWS_LAMBDA_RUNTIME_API` | Result | Scenario |
225
+ |--------------------------|--------|----------|
226
+ | Not set | `is_local = True` | Local dev, unit tests |
227
+ | Set to any value | `is_local = False` | Lambda runtime |
228
+
229
+ **Note:** SAM Local sets `AWS_LAMBDA_RUNTIME_API` during `sam local invoke`. Use `AWS_SAM_LOCAL` to detect SAM specifically if needed.
230
+
231
+ ### Testing Considerations
232
+
233
+ For unit tests, mock environment variables:
234
+
235
+ ```python
236
+ import pytest
237
+
238
+ def test_handler_local_behavior(monkeypatch):
239
+ """Test handler behavior when running locally"""
240
+ monkeypatch.delenv("AWS_LAMBDA_RUNTIME_API", raising=False)
241
+
242
+ from nui_lambda_shared_utils import get_lambda_environment_info
243
+
244
+ env_info = get_lambda_environment_info()
245
+ assert env_info["is_local"] is True
246
+
247
+
248
+ def test_handler_lambda_behavior(monkeypatch):
249
+ """Test handler behavior when running in Lambda"""
250
+ monkeypatch.setenv("AWS_LAMBDA_RUNTIME_API", "127.0.0.1:9001")
251
+ monkeypatch.setenv("ENVIRONMENT", "prod")
252
+ monkeypatch.setenv("AWS_REGION", "ap-southeast-2")
253
+ monkeypatch.setenv("AWS_LAMBDA_FUNCTION_NAME", "my-function")
254
+
255
+ from nui_lambda_shared_utils import get_lambda_environment_info
256
+
257
+ env_info = get_lambda_environment_info()
258
+ assert env_info["is_local"] is False
259
+ assert env_info["environment"] == "prod"
260
+ assert env_info["function_name"] == "my-function"
261
+ ```
262
+
263
+ ## Related Documentation
264
+
265
+ - [Powertools Integration Guide](powertools-integration.md) - Logger and handler decorators
266
+ - [Quick Start Guide](../getting-started/quickstart.md) - Package usage patterns
267
+ - [CloudWatch Metrics](../getting-started/quickstart.md#cloudwatch-metrics) - Metrics publishing
268
+
269
+ ## Support
270
+
271
+ For issues or questions:
272
+
273
+ - [GitHub Issues](https://github.com/nuimarkets/nui-lambda-shared-utils/issues)
274
+ - [Package Documentation](https://github.com/nuimarkets/nui-lambda-shared-utils)