@cloud-copilot/iam-collect
Version:
Collect IAM information from AWS Accounts
116 lines • 4.52 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.conductLogAnalysis = conductLogAnalysis;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
function keyToString(k) {
return [k.service, k.accountId, k.region, k.sync].join('|');
}
function stringToKey(s) {
const [service, accountId, region, sync] = s.split('|');
return { service, accountId, region, sync };
}
function parseLogs(filePath) {
const raw = fs.readFileSync(filePath, 'utf8');
return raw
.split('\n')
.filter((line) => line.trim().length > 0)
.map((line) => JSON.parse(line));
}
function analyzeJobs(entries) {
const startTimes = new Map();
const finishTimes = new Map();
const fmt = (ts) => new Date(ts);
for (const e of entries) {
const keyProps = {
service: e.service,
accountId: e.accountId,
region: e.region ?? '', // global jobs will have empty region
sync: e.sync
};
// only consider entries with a full set of job identifiers
if (!keyProps.service || !keyProps.accountId || !keyProps.sync) {
continue;
}
const keyStr = keyToString(keyProps);
const when = fmt(e.timestamp);
if (e.message.includes('Executing') && e.message.includes('sync')) {
// first start time wins
if (!startTimes.has(keyStr)) {
startTimes.set(keyStr, when);
}
}
else if (e.message.includes('Finished') && e.message.includes('sync')) {
finishTimes.set(keyStr, when);
}
}
// 1) Jobs that started but didn't finish
const incomplete = Array.from(startTimes.keys())
.filter((k) => !finishTimes.has(k))
.map(stringToKey);
// 2) Compute durations for completed jobs
const durations = Array.from(startTimes.entries())
.filter(([k]) => finishTimes.has(k))
.map(([k, start]) => {
const finish = finishTimes.get(k);
const deltaSec = (finish.getTime() - start.getTime()) / 1000;
return { ...stringToKey(k), durationSec: deltaSec };
});
return { incomplete, durations };
}
/**
* Analyze the provided log file for job execution times and incomplete jobs.
*
* @param logFilePath the path to the log file to analyze
* @returns true if all jobs completed successfully, false if there are incomplete jobs
*/
async function conductLogAnalysis(logFilePath) {
const logFile = path.resolve(logFilePath);
const entries = parseLogs(logFile);
const { incomplete, durations } = analyzeJobs(entries);
if (incomplete.length > 0) {
console.log('\n🔴 Incomplete Jobs:');
incomplete.forEach((j) => {
console.log(` • ${j.service} | ${j.accountId} | ${j.region} | ${j.sync}`);
});
}
console.log('\n⏱️ Job Durations (seconds):');
durations.forEach((d) => {
console.log(` • ${d.service} | ${d.accountId} | ${d.region} | ${d.sync}: ${d.durationSec.toFixed(3)}s`);
});
return incomplete.length === 0;
}
//# sourceMappingURL=analyze.js.map