Kousha
Kousha

Reputation: 36219

Delete AWS Log Groups that haven't been touched in X days

Is there a way to delete all AWS Log Groups that haven't had any writes to them in the past 30 days?

Or conversely, get the list of log groups that haven't had anything written to them in the past 30 days?

Upvotes: 5

Views: 4275

Answers (4)

tarun mittal
tarun mittal

Reputation: 411

I did the same setup, I my case I want to delete log stream older than X days from the Cloudwatch Log Stream.

remove.py

import optparse
import sys
import os
import json
import datetime

def deletefunc(loggroupname,days):
    os.system("aws logs describe-log-streams --log-group-name {} --order-by LastEventTime > test.json".format(loggroupname))
    oldstream=[]
    milli= days * 24 * 60 * 60 * 1000
    with open('test.json') as json_file:
       data = json.load(json_file)
       for p in data['logStreams']:
         subtract=p['creationTime']+milli
         sub1=subtract/1000
         sub2=datetime.datetime.fromtimestamp(sub1).strftime('%Y-%m-%d')
         op=p['creationTime']/1000
         original=datetime.datetime.fromtimestamp(op).strftime('%Y-%m-%d')
         name=p['logStreamName']
         if original < sub2:
             oldstream.append(name)

    for i in oldstream:
       os.system("aws logs delete-log-stream --log-group-name {} --log-stream-name {}".format(loggroupname,i))


parser = optparse.OptionParser()
parser.add_option('--log-group-name', action="store", dest="loggroupname", help="LogGroupName For Eg: testing-vpc-flow-logs",type="string")
parser.add_option('-d','--days', action="store", dest="days", help="Type No.of Days in Integer to Delete Logs other than days provided",type="int")
options, args = parser.parse_args()

if options.loggroupname is None:
        print ("Provide log group name to continue.\n")
        cmd = 'python3 ' + sys.argv[0] + ' -h'
        os.system(cmd)
        sys.exit(0)

if options.days is None:
        print ("Provide date to continue.\n")
        cmd = 'python3 ' + sys.argv[0] + ' -h'
        os.system(cmd)
        sys.exit(0)


elif options.days and options.loggroupname:

    loggroupname = options.loggroupname
    days = options.days
    deletefunc(loggroupname,days)

you can run this file using the command:

python3 remove.py --log-group-name=testing-vpc-flow-logs --days=7

Upvotes: 0

Jordan Stewart
Jordan Stewart

Reputation: 3385

Here is some quick script I wrote:

#!/usr/bin/python3

# describe log groups
# describe log streams
# get log groups with the lastEventTimestamp after some time
# delete those log groups
# have a dry run option
# support profile

# https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/logs.html#CloudWatchLogs.Client.describe_log_streams
# https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/logs.html#CloudWatchLogs.Client.describe_log_groups
# https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/logs.html#CloudWatchLogs.Client.delete_log_group

import boto3
import time
millis = int(round(time.time() * 1000))

delete = False
debug = False
log_group_prefix='/' # NEED TO CHANGE THESE

days = 30
# Create CloudWatchLogs client
cloudwatch_logs = boto3.client('logs')

log_groups=[]
# List log groups through the pagination interface
paginator = cloudwatch_logs.get_paginator('describe_log_groups')
for response in paginator.paginate(logGroupNamePrefix=log_group_prefix):
    for log_group in response['logGroups']:
        log_groups.append(log_group['logGroupName'])

if debug:
    print(log_groups)

old_log_groups=[]
empty_log_groups=[]
for log_group in log_groups:
    response = cloudwatch_logs.describe_log_streams(
        logGroupName=log_group, #logStreamNamePrefix='',
        orderBy='LastEventTime',
        descending=True,
        limit=1
    )
    # The time of the most recent log event in the log stream in CloudWatch Logs. This number is expressed as the number of milliseconds after Jan 1, 1970 00:00:00 UTC.
    if len(response['logStreams']) > 0:
        if debug:
            print("full response is:")
            print(response)
            print("Last event is:")
            print(response['logStreams'][0]['lastEventTimestamp'])
            print("current millis is:")
            print(millis)
        if response['logStreams'][0]['lastEventTimestamp'] < millis - (days * 24 * 60 * 60 * 1000):
            old_log_groups.append(log_group)
    else:
        empty_log_groups.append(log_group)

# delete log group
if delete:
    for log_group in old_log_groups:
        response = cloudwatch_logs.delete_log_group(logGroupName=log_group)
    #for log_group in empty_log_groups:
    #    response = cloudwatch_logs.delete_log_group(logGroupName=log_group)
else:
    print("old log groups are:")
    print(old_log_groups)
    print("Number of log groups:")
    print(len(old_log_groups))
    print("empty log groups are:")
    print(empty_log_groups)

Upvotes: 2

Richard Mathie
Richard Mathie

Reputation: 336

I have been using aws-cloudwatch-log-clean and I can say it works quite well.

you need boto3 installed and then you:

./sweep_log_streams.py [log_group_name]

It has a --dry-run option for you to check it what you expect first.

A note of caution, If you have a long running process in ECS which is quiet on the Logs, and the log has been truncated to empty in CW due to the logs retention period. Deleting its empty log stream can break and hang the service, as it has nowhere to post its logs to...

Upvotes: 2

jarmod
jarmod

Reputation: 78703

I'm not aware of a simple way to do this, but you could use the awscli (or preferably python/boto3) to describe-log-groups, then for each log group invoke describe-log-streams, then for each log group/stream pair, invoke get-log-events with a --start-time of 30 days ago. If the union of all the events arrays for the log group is empty then you know you can delete the log group.

Upvotes: 0

Related Questions