Skip to content

Commit e84d016

Browse files
authored
centralized logging (#4)
* log unhandled exceptions so the contain request ID * enable tracing in tests * add terraform to deploy centralized log group * add lock * use centralized log group - set invoke settings to 0 retries and 6 hour max event age - fixed misspellings - removed deployment_name variable * don't use xray_recorder.capture as a decorator * Update README.md
1 parent acb94fe commit e84d016

File tree

28 files changed

+331
-84
lines changed

28 files changed

+331
-84
lines changed

README.md

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -216,18 +216,56 @@ This guide provides a quick way to get started with our project. Please see our
216216

217217
### Setting Up the End-to-End Demo
218218

219-
#### Deploying the Initiator
219+
#### Create the centralized log group
220220

221221
1. Clone repo:
222222

223223
```
224224
git clone https://github.com/unity-sds/unity-initiator.git
225225
```
226226

227+
1. Change directory to the location of the centralized log group terraform:
228+
229+
```
230+
cd unity-initiator/terraform-unity/centralized_log_group/
231+
```
232+
233+
1. Set up environment variables for `project` (by default `uod`) and venue (by default `dev`):
234+
235+
```
236+
export PROJECT=<your project, e.g. uod>
237+
export VENUE=<your venue, e.g. dev>
238+
```
239+
240+
1. Initialize terraform:
241+
242+
```
243+
terraform init
244+
```
245+
246+
1. Run terraform apply:
247+
248+
```
249+
terraform apply \
250+
--var project=${PROJECT} \
251+
--var venue=${VENUE} \
252+
-auto-approve
253+
```
254+
255+
**Take note of the `centralized_log_group_name` that is output by terraform. It will be used when setting up other resources (e.g. initiator, trigger and evaluator lambdas).**
256+
257+
1. Export the `centralized_log_group_name` that was output from the centralized log group terraform deployment:
258+
259+
```
260+
export CENTRALIZED_LOG_GROUP=<your log group name, e.g. /unity/log/uod-dev-initiator-centralized-log-group>
261+
```
262+
263+
#### Deploying the Initiator
264+
227265
1. Change directory to the location of the inititator terraform:
228266

229267
```
230-
cd unity-initiator/terraform-unity/initiator/
268+
cd ../initiator/
231269
```
232270

233271
1. You will need an S3 bucket for terraform to stage the router Lambda zip file and router configuration YAML file during deployment. Create one or reuse an existing one and set an environment variable for it:
@@ -248,12 +286,6 @@ This guide provides a quick way to get started with our project. Please see our
248286
aws s3 cp test_router.yaml s3://${CODE_BUCKET}/test_router.yaml
249287
```
250288

251-
1. Set a project name:
252-
253-
```
254-
export PROJECT=gmanipon-test
255-
```
256-
257289
1. Initialize terraform:
258290

259291
```
@@ -265,13 +297,20 @@ This guide provides a quick way to get started with our project. Please see our
265297
```
266298
terraform apply \
267299
--var project=${PROJECT} \
300+
--var venue=${VENUE} \
268301
--var code_bucket=${CODE_BUCKET} \
269302
--var router_config=s3://${CODE_BUCKET}/test_router.yaml \
270303
-auto-approve
271304
```
272305

273306
**Take note of the `initiator_topic_arn` that is output by terraform. It will be used when setting up any triggers.**
274307

308+
1. Export the `initiator_topic_arn` that was output from the initiator terraform deployment:
309+
310+
```
311+
export INITIATOR_TOPIC_ARN=<initiator topic ARN>
312+
```
313+
275314
#### Deploying Example Evaluators (SNS topic->SQS queue->Lambda)
276315

277316
In this demo we will deploy 2 evaluators:
@@ -320,6 +359,8 @@ In this demo we will deploy 2 evaluators:
320359

321360
```
322361
terraform apply \
362+
--var project=${PROJECT} \
363+
--var venue=${VENUE} \
323364
--var evaluator_name=${EVALUATOR_NAME} \
324365
--var code_bucket=${CODE_BUCKET} \
325366
-auto-approve
@@ -361,6 +402,8 @@ In this demo we will deploy 2 evaluators:
361402
1. Run terraform apply:
362403
```
363404
terraform apply \
405+
--var project=${PROJECT} \
406+
--var venue=${VENUE} \
364407
--var evaluator_name=${EVALUATOR_NAME} \
365408
--var code_bucket=${CODE_BUCKET} \
366409
-auto-approve
@@ -448,11 +491,12 @@ In this demo we will deploy 2 evaluators:
448491
terraform init
449492
```
450493

451-
1. Run terraform apply. Note the PROJECT and INITIATOR_TOPIC_ARN environment variables should have been set in the previous steps. If not set them again:
494+
1. Run terraform apply. Note the PROJECT, VENUE and INITIATOR_TOPIC_ARN environment variables should have been set in the previous steps. If not set them again:
452495

453496
```
454497
terraform apply \
455498
--var project=${PROJECT} \
499+
--var venue=${VENUE} \
456500
--var initiator_topic_arn=${INITIATOR_TOPIC_ARN} \
457501
-auto-approve
458502
```
@@ -505,6 +549,7 @@ In this demo we will deploy 2 evaluators:
505549
```
506550
terraform apply \
507551
--var project=${PROJECT} \
552+
--var venue=${VENUE} \
508553
--var code_bucket=${CODE_BUCKET} \
509554
--var initiator_topic_arn=${INITIATOR_TOPIC_ARN} \
510555
--var provider_id=${PROVIDER_ID} \

src/unity_initiator/cloud/lambda_handler.py

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from aws_xray_sdk.core import patch_all, xray_recorder
88

99
from ..router import Router
10-
from ..utils.logger import logger
10+
from ..utils.logger import log_exceptions, logger
1111

1212
# initialize the AWS X-Ray SDK
1313
patch_all()
@@ -16,33 +16,34 @@
1616
ROUTER = None
1717

1818

19-
@xray_recorder.capture("lambda_handler_base")
19+
@log_exceptions
2020
def lambda_handler_base(event, context):
2121
"""Base lambda handler that instantiates a router, globally, and executes actions for a single payload."""
2222

2323
logger.info("context: %s", context)
2424

25-
# TODO: Should use AppConfig. For now, either reading router config body in ROUTER_CFG env variable
26-
# or from a url in ROUTER_CFG_URL env variable.
27-
global ROUTER
28-
if ROUTER is None:
29-
router_cfg = os.environ.get("ROUTER_CFG", "").strip()
30-
router_cfg_url = os.environ.get("ROUTER_CFG_URL", "").strip()
31-
if router_cfg == "":
32-
if router_cfg_url != "":
33-
with smart_open.open(router_cfg_url, "r") as f:
34-
router_cfg = f.read()
35-
else:
36-
raise RuntimeError(
37-
"No router configuration specified via ROUTER_CFG or ROUTER_CFG_URL env variables."
38-
)
39-
fd, router_file = mkstemp(prefix="router_", suffix=".yaml", text=True)
40-
with os.fdopen(fd, "w") as f:
41-
f.write(router_cfg)
42-
ROUTER = Router(router_file)
43-
os.unlink(router_file)
44-
xray_recorder.put_annotation("payload", event["payload"])
45-
return ROUTER.execute_actions(event["payload"])
25+
with xray_recorder.capture("lambda_handler_base"):
26+
# TODO: Should use AppConfig. For now, either reading router config body in ROUTER_CFG env variable
27+
# or from a url in ROUTER_CFG_URL env variable.
28+
global ROUTER
29+
if ROUTER is None:
30+
router_cfg = os.environ.get("ROUTER_CFG", "").strip()
31+
router_cfg_url = os.environ.get("ROUTER_CFG_URL", "").strip()
32+
if router_cfg == "":
33+
if router_cfg_url != "":
34+
with smart_open.open(router_cfg_url, "r") as f:
35+
router_cfg = f.read()
36+
else:
37+
raise RuntimeError(
38+
"No router configuration specified via ROUTER_CFG or ROUTER_CFG_URL env variables."
39+
)
40+
fd, router_file = mkstemp(prefix="router_", suffix=".yaml", text=True)
41+
with os.fdopen(fd, "w") as f:
42+
f.write(router_cfg)
43+
ROUTER = Router(router_file)
44+
os.unlink(router_file)
45+
xray_recorder.put_annotation("payload", event["payload"])
46+
return ROUTER.execute_actions(event["payload"])
4647

4748

4849
def lambda_handler_multiple_payloads(event, context):

src/unity_initiator/utils/logger.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import logging
2+
import traceback
3+
from functools import wraps
24

35
# set logger and custom filter
46
log_format = "[%(asctime)s: %(levelname)s/%(funcName)s] %(message)s"
@@ -16,3 +18,16 @@ def filter(self, record):
1618
logger = logging.getLogger("unity_initiator")
1719
logger.setLevel(logging.INFO)
1820
logger.addFilter(LogFilter())
21+
22+
23+
def log_exceptions(lambda_handler):
24+
@wraps(lambda_handler)
25+
def wrapper(event, context):
26+
try:
27+
return lambda_handler(event, context)
28+
except Exception as err:
29+
tb = traceback.format_exc()
30+
logger.exception("Got exception: %s\n%s", str(err), tb)
31+
raise
32+
33+
return wrapper

terraform-unity/centralized_log_group/.terraform.lock.hcl

Lines changed: 45 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# terraform-unity
2+
3+
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
4+
## Requirements
5+
6+
| Name | Version |
7+
|------|---------|
8+
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | ~> 1.8.2 |
9+
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >=5.50.0 |
10+
| <a name="requirement_local"></a> [local](#requirement\_local) | >=2.5.1 |
11+
12+
## Providers
13+
14+
| Name | Version |
15+
|------|---------|
16+
| <a name="provider_aws"></a> [aws](#provider\_aws) | 5.65.0 |
17+
18+
## Modules
19+
20+
No modules.
21+
22+
## Resources
23+
24+
| Name | Type |
25+
|------|------|
26+
| [aws_cloudwatch_log_group.centralized_log_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource |
27+
28+
## Inputs
29+
30+
| Name | Description | Type | Default | Required |
31+
|------|-------------|------|---------|:--------:|
32+
| <a name="input_project"></a> [project](#input\_project) | The unity project its installed into | `string` | `"uod"` | no |
33+
| <a name="input_venue"></a> [venue](#input\_venue) | The unity venue its installed into | `string` | `"dev"` | no |
34+
35+
## Outputs
36+
37+
| Name | Description |
38+
|------|-------------|
39+
| <a name="output_centralized_log_group_name"></a> [centralized\_log\_group\_name](#output\_centralized\_log\_group\_name) | The name of the centralized log group |
40+
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
locals {
2+
log_group_name = "${var.project}-${var.venue}-initiator-centralized-log-group"
3+
tags = {
4+
Venue = "dev"
5+
ServiceArea = "cs"
6+
Capability = "initiator"
7+
CapVersion = "0.0.1"
8+
Component = "U-OD"
9+
Name = "${var.project}-${var.venue}-cs-initiator-od"
10+
Proj = var.project
11+
CreatedBy = "cs"
12+
Env = "dev"
13+
Stack = "U-OD"
14+
}
15+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
resource "aws_cloudwatch_log_group" "centralized_log_group" {
2+
name = "/unity/log/${local.log_group_name}"
3+
retention_in_days = 14
4+
tags = local.tags
5+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
output "centralized_log_group_name" {
2+
description = "The name of the centralized log group"
3+
value = aws_cloudwatch_log_group.centralized_log_group.name
4+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
variable "project" {
2+
description = "The unity project its installed into"
3+
type = string
4+
default = "uod"
5+
}
6+
7+
variable "venue" {
8+
description = "The unity venue its installed into"
9+
type = string
10+
default = "dev"
11+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
terraform {
2+
required_version = "~> 1.8.2"
3+
4+
required_providers {
5+
aws = {
6+
source = "hashicorp/aws"
7+
version = ">=5.50.0"
8+
}
9+
local = {
10+
source = "hashicorp/local"
11+
version = ">=2.5.1"
12+
}
13+
}
14+
}

0 commit comments

Comments
 (0)