-
Notifications
You must be signed in to change notification settings - Fork 2
/
splunk.js
100 lines (90 loc) · 3.96 KB
/
splunk.js
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
/**
* Stream events from AWS CloudWatch Logs to Splunk
*
* This function streams AWS CloudWatch Logs to Splunk using
* Splunk's HTTP event collector API.
*
* Define the following Environment Variables in the console below to configure
* this function to stream logs to your Splunk host:
*
* 1. SPLUNK_HEC_URL: URL address for your Splunk HTTP event collector endpoint.
* Default port for event collector is 8088. Example: https://host.com:8088/services/collector
*
* 2. SPLUNK_HEC_TOKEN: Token for your Splunk HTTP event collector.
* To create a new token for this Lambda function, refer to Splunk Docs:
* http://docs.splunk.com/Documentation/Splunk/latest/Data/UsetheHTTPEventCollector#Create_an_Event_Collector_token
*/
'use strict'
const loggerConfig = {
url: process.env.SPLUNK_HEC_URL,
token: process.env.SPLUNK_HEC_TOKEN,
maxBatchCount: 0, // Manually flush events
maxRetries: 3 // Retry 3 times
}
const SplunkLogger = require('splunk-logging').Logger
const zlib = require('zlib')
const logger = new SplunkLogger(loggerConfig)
exports.handler = (event, context, callback) => {
console.log('Received event:', JSON.stringify(event, null, 2))
// First, configure logger to automatically add Lambda metadata and to hook into Lambda callback
configureLogger(context, callback) // eslint-disable-line no-use-before-define
// CloudWatch Logs data is base64 encoded so decode here
const payload = new Buffer(event.awslogs.data, 'base64')
// CloudWatch Logs are gzip compressed so expand here
zlib.gunzip(payload, (error, result) => {
if (error) {
callback(error)
} else {
const parsed = JSON.parse(result.toString('ascii'))
console.log('Decoded payload:', JSON.stringify(parsed, null, 2))
let count = 0
if (parsed.logEvents) {
parsed.logEvents.forEach((item) => {
/* Send item message to Splunk with optional metadata properties such as time, index, source, sourcetype, and host.
- Change "item.timestamp" below if time is specified in another field in the event.
- Set or remove metadata properties as needed. For descripion of each property, refer to:
http://docs.splunk.com/Documentation/Splunk/latest/RESTREF/RESTinput#services.2Fcollector */
logger.send({
message: item.message,
metadata: {
time: item.timestamp ? new Date(item.timestamp).getTime() / 1000 : Date.now(),
host: 'serverless',
source: `lambda:${context.functionName}`,
sourcetype: 'httpevent'
// index: 'main',
}
})
count += 1
})
}
// Send all the events in a single batch to Splunk
logger.flush((err, resp, body) => {
// Request failure or valid response from Splunk with HEC error code
if (err || (body && body.code !== 0)) {
// If failed, error will be handled by pre-configured logger.error() below
} else {
// If succeeded, body will be { text: 'Success', code: 0 }
console.log('Response from Splunk:', body)
console.log(`Successfully processed ${count} log event(s).`)
callback(null, count) // Return number of log events
}
})
}
})
}
const configureLogger = (context, callback) => {
// Override SplunkLogger default formatter
logger.eventFormatter = (event) => {
// Enrich event only if it is an object
if (typeof event === 'object' && !Object.prototype.hasOwnProperty.call(event, 'awsRequestId')) {
// Add awsRequestId from Lambda context for request tracing
event.awsRequestId = context.awsRequestId // eslint-disable-line no-param-reassign
}
return event
}
// Set common error handler for logger.send() and logger.flush()
logger.error = (error, payload) => {
console.log('error', error, 'context', payload)
callback(error)
}
}