Skip to content

Instantly share code, notes, and snippets.

@DV8FromTheWorld
Created January 11, 2021 17:56
Show Gist options
  • Save DV8FromTheWorld/3fa1ea606f5605477f88bbe788f57e6d to your computer and use it in GitHub Desktop.
Save DV8FromTheWorld/3fa1ea606f5605477f88bbe788f57e6d to your computer and use it in GitHub Desktop.
AWS ALB access log file to CSV
const fs = require('fs')
const path = require('path')
const util = require('util')
const { exec } = require('child_process')
const fsPromises = fs.promises
const execPromise = util.promisify(exec)
const columnHeaders = ["type", "time", "elb", "client:port", "target:port", "request_processing_time", "target_processing_time", "response_processing_time", "elb_status_code", "target_status_code", "received_bytes", "sent_bytes", "request", "user_agent", "ssl_cipher", "ssl_protocol", "target_group_arn", "trace_id", "domain_name", "chosen_cert_arn", "matched_rule_priority", "request_creation_time", "actions_executed", "redirect_url", "error_reason", "target:port_list", "target_status_code_list", "classification", "classification_reason"]
;(async () => {
const fileName = process.argv[2]
if (!fileName) {
printUsage()
return
}
const originalFilePath = path.resolve(fileName)
if (!(await fileExists(originalFilePath))) {
console.log(`Provided file doesn't exist!`)
console.log(`Provided: ${fileName}`)
console.log(`Resolved: ${originalFilePath}`)
console.log()
printUsage()
return
}
let filePath = originalFilePath
if (fileName.endsWith('.gz')) {
console.log("Determined that file is gzipped. Unzipping first.")
filePath = await ungzipFile(originalFilePath)
}
const contentRaw = await fsPromises.readFile(filePath)
const content = contentRaw.toString('utf8')
.replace(/ /g, ',')
const colHeaderRow = columnHeaders.join(',')
const newContent = colHeaderRow + '\n' + content
const newFilePath = filePath + '.csv'
await fsPromises.writeFile(newFilePath, newContent)
console.log(`Wrote new CSV file to:\n${newFilePath}`)
})();
function printUsage() {
console.log('node alb-log-to-csv <log-file>')
}
async function ungzipFile(filePath) {
try {
//The new file that gzip command will output (same file name without the .gz attached)
const unzipedFileName = filePath.slice(0, -".gz".length)
//Args:
// -d: unzip the provided file
// -k: keep the original file
await execPromise(`rm -f ${unzipedFileName}`)
await execPromise(`gzip -dk ${filePath}`)
return unzipedFileName
}
catch (err) {
console.log("Failed to unzip the gzip file: " + filePath)
console.log(err)
process.exit(1)
}
}
async function fileExists(path) {
try {
await fsPromises.stat(path)
return true
}
catch {
return false
}
}
@DV8FromTheWorld
Copy link
Author

Utility built for processing AWS ALB access logs into a format that is easier to understand.
Specifically, this script converts the log to a CSV that has column headers explaining each part of each access log entry.

Usage

  1. Enable access logging on your ALB
  2. Download your ALB access logs from S3.
  3. Run this script on the file. It will unzip the file and process it into a CSV.
Example:

Given a log file named:
727591254000_elasticloadbalancing_20210111T1000Z.log.gz

Run command
node alb-log-to-csv.js 727591254000_elasticloadbalancing_20210111T1000Z.log.gz

Produces:
727591254000_elasticloadbalancing_20210111T1000Z.log.csv

@slavking
Copy link

Determined that file is gzipped. Unzipping first.
node:buffer:634
    slice: (buf, start, end) => buf.utf8Slice(start, end),
                                    ^

Error: Cannot create a string longer than 0x1fffffe8 characters
    at Object.slice (node:buffer:634:37)
    at Buffer.toString (node:buffer:853:14)
    at /Users/me/Downloads/alb_logs/prod-public/alb-log-to-csv.js:36:30 {
  code: 'ERR_STRING_TOO_LONG'
}

Node.js v20.6.1

I do have a very large ALB file

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment