Repository navigation
Expand file tree
/
Copy pathhandler.js
More file actions
120 lines (93 loc) · 3.7 KB
/
Copy pathhandler.js
File metadata and controls
120 lines (93 loc) · 3.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
const AWS = require("aws-sdk");
const moment = require('moment');
const _ = require('lodash');
const bucketName = process.env.LOGS_BUCKET_NAME;
const maxExportDays = process.env.MAX_RETENTION;
const region = process.env.REGION;
const cwlClient = new AWS.CloudWatchLogs({region: region});
let allLogGroups = [];
let taskResults = {};
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
const listAllCwLogGroups = async (nextToken) => {
let params = {
...(nextToken && {nextToken})
};
const logGroups = await cwlClient.describeLogGroups(params).promise();
if (logGroups.logGroups) {
allLogGroups = allLogGroups.concat(logGroups.logGroups);
}
//describeLogGroups has a max limit of 50 groups, need to use nextToken to get all groups
if (logGroups.nextToken) {
await listAllCwLogGroups(logGroups.nextToken);
}
};
async function checkExportTaskStatus(taskName, taskId) {
const describeTaskResp = await cwlClient.describeExportTasks({taskId: taskId}).promise();
const status = describeTaskResp.exportTasks[0].status.code;
console.log(`${taskName} status is ${status}`);
return status;
}
async function createExportTask(logGroup) {
console.log(`Creating export task for ${logGroup.logGroupName}`);
const timeNow = moment.utc();
const taskName = `exportTaskFor-${logGroup.logGroupName}`;
const fromDays = _.min([logGroup.retentionInDays, maxExportDays]);
let destinationPrefix = logGroup.logGroupName;
// remove first '/' from /aws/lambda/{lambdaName} to keep s3 sane and happy
if (destinationPrefix[0] == '/') {
destinationPrefix = destinationPrefix.substring(1);
}
const createTaskParams = {
taskName: taskName,
to: timeNow.add(1, 'minute').unix() * 1000,
from: timeNow.subtract(fromDays, 'days').unix() * 1000,
logGroupName: logGroup.logGroupName,
destination: bucketName,
destinationPrefix: destinationPrefix
};
const createTaskResp = await cwlClient.createExportTask(createTaskParams).promise();
const taskId = createTaskResp.taskId;
return {taskName, taskId};
}
const exportCwLogGroup = async (logGroup) => {
const {taskName, taskId} = await createExportTask(logGroup);
let exportTaskStatus = await checkExportTaskStatus(taskName, taskId);
while (exportTaskStatus === 'PENDING' || exportTaskStatus === 'RUNNING') {
await sleep(1000);
exportTaskStatus = await checkExportTaskStatus(taskName, taskId);
}
console.log(`${logGroup.logGroupName} is finished with the result ${exportTaskStatus}`);
taskResults[taskId] = {name: logGroup.logGroupName, status: exportTaskStatus};
};
const exportCwLogGroups = async (logGroups) => {
// Each account can only have one active (RUNNING or PENDING) export task at a time.
// need to wait until previous finished before start a new one
// no parallel jobs :(
for (const logGroup in logGroups) {
await exportCwLogGroup(logGroups[logGroup]);
}
};
const main = async () => {
await listAllCwLogGroups();
console.log(`Number of log groups in account is ${allLogGroups.length}`);
await exportCwLogGroups(allLogGroups);
console.log('All export asks are created');
console.log(JSON.stringify(taskResults, null, 2));
const tasksGroupedByStatus = _.groupBy(Object.keys(taskResults).map(key => {
return {...taskResults[key], id: key};
}), 'status');
console.debug(`Extract tasks with statuses are ${JSON.stringify(tasksGroupedByStatus, null, 2)}`);
console.log(`There are ${tasksGroupedByStatus['COMPLETED'].length} COMPLETED tasks out of ${allLogGroups.length}`);
console.log(`Script completed`);
};
module.exports.handle = async event => {
// reset global vars
allLogGroups = [];
taskResults = {};
await main();
return {
statusCode: 200
};
};