Skip to content

Commit f9d9052

Browse files
committed
Fix Python linting issues in Lambda handler
- Fix all PEP 8 style violations (whitespace, blank lines) - Remove emojis from Slack messages for professional appearance - Fix line length issues by breaking long lines - Add proper newline at end of file - Ensure consistent code formatting throughout - All flake8 linting checks now pass
1 parent ba190a5 commit f9d9052

File tree

1 file changed

+38
-30
lines changed

1 file changed

+38
-30
lines changed

lambda/handler.py

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
logger = logging.getLogger()
1616
logger.setLevel(logging.INFO)
1717

18+
1819
def lambda_handler(event, context):
1920
"""
2021
Main Lambda handler function
@@ -24,36 +25,38 @@ def lambda_handler(event, context):
2425
s3_client = boto3.client('s3')
2526
ce_client = boto3.client('ce')
2627
secrets_client = boto3.client('secretsmanager')
27-
28+
2829
# Get environment variables
2930
bucket_name = os.environ['BUCKET_NAME']
3031
cost_threshold = float(os.environ.get('COST_THRESHOLD', 50.0))
3132
slack_secret_name = os.environ['SLACK_SECRET_NAME']
3233
environment = os.environ.get('ENVIRONMENT', 'dev')
33-
34+
3435
logger.info(f"Starting cost collection for environment: {environment}")
3536
logger.info(f"Cost threshold: ${cost_threshold}")
36-
37+
3738
# Get cost data from Cost Explorer
3839
cost_data = get_cost_data(ce_client)
39-
40+
4041
# Store cost data in S3
4142
s3_key = store_cost_data(s3_client, bucket_name, cost_data)
4243
logger.info(f"Cost data stored in S3: {s3_key}")
43-
44+
4445
# Process cost data and check threshold
4546
cost_summary = process_cost_data(cost_data)
4647
logger.info(f"Total daily cost: ${cost_summary['total_cost']:.2f}")
47-
48+
4849
# Send Slack alert if threshold exceeded
4950
if cost_summary['total_cost'] > cost_threshold:
5051
slack_webhook_url = get_slack_webhook(secrets_client, slack_secret_name)
5152
send_slack_alert(slack_webhook_url, cost_summary, cost_threshold, environment)
5253
alert_sent = True
5354
else:
5455
alert_sent = False
55-
logger.info(f"Cost ${cost_summary['total_cost']:.2f} within threshold ${cost_threshold:.2f}")
56-
56+
logger.info(
57+
f"Cost ${cost_summary['total_cost']:.2f} within threshold ${cost_threshold:.2f}"
58+
)
59+
5760
return {
5861
'statusCode': 200,
5962
'body': json.dumps({
@@ -64,7 +67,7 @@ def lambda_handler(event, context):
6467
's3_key': s3_key
6568
})
6669
}
67-
70+
6871
except Exception as e:
6972
logger.error(f"Error in cost collection: {str(e)}")
7073
return {
@@ -74,6 +77,7 @@ def lambda_handler(event, context):
7477
})
7578
}
7679

80+
7781
def get_cost_data(ce_client) -> Dict:
7882
"""
7983
Fetch cost data from AWS Cost Explorer
@@ -82,9 +86,9 @@ def get_cost_data(ce_client) -> Dict:
8286
today = datetime.date.today()
8387
start_date = (today - datetime.timedelta(days=1)).strftime('%Y-%m-%d')
8488
end_date = today.strftime('%Y-%m-%d')
85-
89+
8690
logger.info(f"Fetching cost data for period: {start_date} to {end_date}")
87-
91+
8892
try:
8993
response = ce_client.get_cost_and_usage(
9094
TimePeriod={
@@ -100,69 +104,72 @@ def get_cost_data(ce_client) -> Dict:
100104
}
101105
]
102106
)
103-
107+
104108
return response
105-
109+
106110
except Exception as e:
107111
logger.error(f"Error fetching cost data: {str(e)}")
108112
raise
109113

114+
110115
def store_cost_data(s3_client, bucket_name: str, cost_data: Dict) -> str:
111116
"""
112117
Store cost data in S3 bucket
113118
"""
114119
# Generate S3 key with timestamp
115120
timestamp = datetime.datetime.now().strftime('%Y-%m-%d')
116121
s3_key = f"cost_data/daily/{timestamp}.json"
117-
122+
118123
try:
119124
s3_client.put_object(
120125
Bucket=bucket_name,
121126
Key=s3_key,
122127
Body=json.dumps(cost_data, indent=2, default=str),
123128
ContentType='application/json'
124129
)
125-
130+
126131
return s3_key
127-
132+
128133
except Exception as e:
129134
logger.error(f"Error storing cost data in S3: {str(e)}")
130135
raise
131136

137+
132138
def process_cost_data(cost_data: Dict) -> Dict:
133139
"""
134140
Process cost data and extract key metrics
135141
"""
136142
try:
137143
results = cost_data['ResultsByTime'][0]
138144
total_cost = float(results['Total']['BlendedCost']['Amount'])
139-
145+
140146
# Process service-level costs
141147
services = []
142148
for group in results.get('Groups', []):
143149
service_name = group['Keys'][0]
144150
service_cost = float(group['Metrics']['BlendedCost']['Amount'])
145-
151+
146152
if service_cost > 0: # Only include services with actual costs
147153
services.append({
148154
'name': service_name,
149155
'cost': service_cost
150156
})
151-
157+
152158
# Sort services by cost (highest first)
153159
services.sort(key=lambda x: x['cost'], reverse=True)
154-
160+
155161
return {
156162
'total_cost': total_cost,
157163
'date': results['TimePeriod']['Start'],
158164
'services': services[:10], # Top 10 services
159165
'service_count': len(services)
160166
}
161-
167+
162168
except Exception as e:
163169
logger.error(f"Error processing cost data: {str(e)}")
164170
raise
165171

172+
166173
def get_slack_webhook(secrets_client, secret_name: str) -> str:
167174
"""
168175
Retrieve Slack webhook URL from Secrets Manager
@@ -171,11 +178,12 @@ def get_slack_webhook(secrets_client, secret_name: str) -> str:
171178
response = secrets_client.get_secret_value(SecretId=secret_name)
172179
secret_data = json.loads(response['SecretString'])
173180
return secret_data['SLACK_WEBHOOK_URL']
174-
181+
175182
except Exception as e:
176183
logger.error(f"Error retrieving Slack webhook: {str(e)}")
177184
raise
178185

186+
179187
def send_slack_alert(webhook_url: str, cost_summary: Dict, threshold: float, environment: str):
180188
"""
181189
Send cost alert to Slack
@@ -185,16 +193,16 @@ def send_slack_alert(webhook_url: str, cost_summary: Dict, threshold: float, env
185193
top_services = ""
186194
for i, service in enumerate(cost_summary['services'][:5], 1):
187195
top_services += f"{i}. {service['name']}: ${service['cost']:.2f}\n"
188-
189-
# Create Slack message
196+
197+
# Create Slack message (removed emojis for professional appearance)
190198
message = {
191-
"text": f"🚨 *AWS Cost Alert - {environment.upper()}*",
199+
"text": f"AWS Cost Alert - {environment.upper()}",
192200
"blocks": [
193201
{
194202
"type": "header",
195203
"text": {
196204
"type": "plain_text",
197-
"text": f"🚨 AWS Cost Alert - {environment.upper()}"
205+
"text": f"AWS Cost Alert - {environment.upper()}"
198206
}
199207
},
200208
{
@@ -236,7 +244,7 @@ def send_slack_alert(webhook_url: str, cost_summary: Dict, threshold: float, env
236244
}
237245
]
238246
}
239-
247+
240248
# Send to Slack
241249
http = urllib3.PoolManager()
242250
response = http.request(
@@ -245,12 +253,12 @@ def send_slack_alert(webhook_url: str, cost_summary: Dict, threshold: float, env
245253
body=json.dumps(message),
246254
headers={'Content-Type': 'application/json'}
247255
)
248-
256+
249257
if response.status == 200:
250258
logger.info("Slack alert sent successfully")
251259
else:
252260
logger.error(f"Failed to send Slack alert: {response.status}")
253-
261+
254262
except Exception as e:
255263
logger.error(f"Error sending Slack alert: {str(e)}")
256-
raise
264+
raise

0 commit comments

Comments
 (0)