1
+ #! /bin/bash
2
+
3
+ # This script leverages the AWS CLI to collect Elastic Stack logs for your
4
+ # Buildkite Elastic CI Stack instances.
5
+ #
6
+ # It assumes you have the AWS CLI tool configured, with appropriate credentials
7
+ # so it is recommended to use something like aws-vault: https://github.com/99designs/aws-vault.
8
+ #
9
+ # You will need to know the Instance ID and Stack name of the resources
10
+ # you want to collect logs for.
11
+ #
12
+ # Once you have collected the logs, please send them to [email protected]
13
+ # with a description of the issue you are seeing, and we'll be happy to assist!
14
+
15
+ set -euo pipefail
16
+
17
+ usage () {
18
+ cat << EOF
19
+ Usage: ./bk-log-collector -s <stack-name> -i <instance-id>
20
+ Collect Buildkite Elastic CI stack logs from AWS CloudWatch
21
+ -s Auto Scaling Group Name, can be found at console.aws.amazon.com/ec2autoscaling/
22
+ -i Instance ID, the AWS instance ID for the instance you want to collect logs for
23
+ -o Output format for logs(optional flag), supported values are text (default value), json, table
24
+ EOF
25
+ }
26
+
27
+ while getopts ' hs:i:o:' opt; do
28
+ case ${opt} in
29
+ s )
30
+ stackName=$OPTARG
31
+ ;;
32
+ i )
33
+ instanceId=$OPTARG
34
+ ;;
35
+ o )
36
+ outputFormat=$OPTARG
37
+ ;;
38
+ h )
39
+ usage
40
+ exit 0
41
+ ;;
42
+ \? )
43
+ echo " Invalid Option: -$OPTARG " 1>&2
44
+ exit 1
45
+ ;;
46
+ : )
47
+ echo " Invalid option: $OPTARG requires an arguemnt" 1>&2
48
+ ;;
49
+ esac
50
+ done
51
+ shift $(( OPTIND - 1 ))
52
+
53
+ now=$( date +" %F" )
54
+ outputFormat=" ${outputFormat:= text} "
55
+
56
+ # Create a temporary directory to store our logs
57
+ pwd=$( pwd)
58
+ dir=$( mktemp -d " $pwd " /buildkite-logs-" $now " )
59
+
60
+ echo " Collecting logs for instance $instanceId "
61
+
62
+ # Collect the logs for the instance
63
+ aws logs get-log-events --log-group-name /buildkite/buildkite-agent --log-stream-name " $instanceId " --output " $outputFormat " >> " $dir " /buildkite-agent-" $instanceId " .log
64
+ aws logs get-log-events --log-group-name /buildkite/system --log-stream-name " $instanceId " --output " $outputFormat " >> " $dir " /system-" $instanceId " .log
65
+ aws logs get-log-events --log-group-name /buildkite/lifecycled --log-stream-name " $instanceId " --output " $outputFormat " >> " $dir " /lifecycled-" $instanceId " .log
66
+ aws logs get-log-events --log-group-name /buildkite/docker-daemon --log-stream-name " $instanceId " --output " $outputFormat " >> " $dir " /docker-daemon-" $instanceId " .log
67
+
68
+ # CloudWatch stores the creationTime as milliseconds since epoch UTC.
69
+ # Since macOS doesn't support calculating the time since epoch in milliseconds, we don't have perfect accuracy on this, but it should be as close to 24 hours as possible
70
+ # Currently only collects the last 24h of logs, but it might be good to be able to specify a different value for this.
71
+ logAge=$( date -v-1d " +%s000" )
72
+
73
+ # Collect some information about the Lambda function and associated log groups
74
+ # Change the timeframe to be dynamically set with a default of 24h. Currently collects the last 24 hours of Lambda logs
75
+ lambdaFunction=$( aws cloudformation describe-stack-resources --stack-name " $stackName " --logical-resource-id Autoscaling --query " StackResources[*].PhysicalResourceId" --output text | sed -nr ' s/.*stack\/(.*)\/.*/\1/p' )
76
+ lambdaLogGroup=$( aws cloudformation describe-stack-resources --stack-name " $lambdaFunction " --logical-resource-id LogGroup --query " StackResources[*].PhysicalResourceId" --output text)
77
+ logStreams=$( aws logs describe-log-streams --log-group-name " $lambdaLogGroup " --order-by LastEventTime --query " logStreams[?creationTime > \` $logAge \` ] | [*].logStreamName" --output text | tr -s ' [:space:]' ' \n' )
78
+
79
+ # Iterate through all of the log streams we collected from the lambda log group
80
+
81
+ echo " Collecting Lambda logs for $lambdaFunction "
82
+ for i in $logStreams
83
+ do
84
+ fileName=$( echo " $i " | sed -r ' s/\//-/g' )
85
+ aws logs get-log-events --log-group-name " $lambdaLogGroup " --log-stream-name " $i " --output " $outputFormat " >> " $dir " /lambda-" $fileName " .log
86
+ done
87
+
88
+ # Collect ASG activity for the scaling group
89
+ autoScalingGroup=$( aws cloudformation describe-stack-resources --stack-name " $stackName " --logical-resource-id AgentAutoScaleGroup --query " StackResources[*].PhysicalResourceId" --output text)
90
+ echo " Collecting ASG activity for $autoScalingGroup "
91
+ aws autoscaling describe-scaling-activities --auto-scaling-group-name " $autoScalingGroup " >> " $dir " /asg-activities-" $stackName " .log
92
+
93
+ # Make an archive with the logs
94
+ zip -jq buildkite-logs-" $now " .zip " $dir " /* .log
95
+
96
+ # Clean up the unneeded files
97
+ rm -r " $dir "
98
+
99
+ echo " Finished collecting logs, you can find them here: $pwd /buildkite-logs-$now .zip"
100
+
101
+ exit 0
0 commit comments