Last active
May 25, 2022 06:53
-
-
Save larenelg/326728ada62742dbd128b5ff202c451e to your computer and use it in GitHub Desktop.
Forward Cloudwatch Logs to Seq Lambda
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
/* | |
Make sure you are logging to Console using the Compact JSON Formatter, e.g. | |
``` | |
public class LambdaEntryPoint : APIGatewayHttpApiV2ProxyFunction | |
{ | |
protected override void Init(IWebHostBuilder builder) | |
{ | |
Log.Logger = new LoggerConfiguration() | |
.MinimumLevel.Override("Microsoft", LogEventLevel.Information) | |
.Enrich.FromLogContext() | |
.WriteTo.Console(new CompactJsonFormatter()) | |
.CreateLogger(); | |
builder.UseStartup<Startup>().UseSerilog(); | |
} | |
} | |
``` | |
*/ | |
const https = require('https'); | |
const zlib = require('zlib'); | |
const loggerConfig = { | |
hostname: process.env.SEQ_SERVER_HOSTNAME, | |
port: process.env.SEQ_SERVER_PORT, | |
apiKey: process.env.SEQ_API_KEY, | |
}; | |
// entry point | |
exports.handler = (event, context, callback) => { | |
const payload = Buffer.from(event.awslogs.data, 'base64'); | |
function postEventsToSeq(parsedEvents) { | |
const payload = parsedEvents.map(JSON.stringify).join('\n'); | |
try { | |
const options = { | |
hostname: loggerConfig.hostname, | |
port: loggerConfig.port, | |
path: '/api/events/raw', | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/vnd.serilog.clef', | |
'Content-Length': payload.length, | |
'X-Seq-ApiKey': loggerConfig.apiKey | |
}, | |
}; | |
const req = https.request(options, (res) => { | |
console.log('Status Code:', res.statusCode); | |
let response = []; | |
res.on('data', (data) => { | |
response.push(data); | |
}); | |
res.on('end', () => { | |
console.log('Response message:', response.join('')); | |
callback(); | |
}); | |
}); | |
req.on('error', (err) => { | |
console.log('Problem with request:', err.toString()); | |
callback(err); | |
}); | |
// write data to request body | |
req.write(payload); | |
req.end(); | |
} catch (ex) { | |
console.log(ex.message); | |
callback(ex.message); | |
} | |
} | |
function checkIfClef(logEvent) { | |
try { | |
const maybeClef = JSON.parse(logEvent.message.trim()); | |
if (maybeClef.hasOwnProperty("@t")) { | |
return maybeClef; | |
} else { | |
throw new Error('Wrong format JSON'); | |
} | |
} catch (ex) { | |
// a text-only log, probably from AWS | |
return { | |
"@t": new Date(logEvent.timestamp).toISOString(), | |
"@m": logEvent.message.trim(), // remove trailing \n | |
}; | |
} | |
} | |
zlib.gunzip(payload, (error, result) => { | |
if (error) { | |
callback(error); | |
} else { | |
const resultParsed = JSON.parse(result.toString('ascii')); | |
const parsedEvents = resultParsed.logEvents.map((logEvent) => checkIfClef(logEvent)); | |
postEventsToSeq(parsedEvents); | |
} | |
}); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment