Skip to content

Commit

Permalink
feat: added CloudWatchEvents client
Browse files Browse the repository at this point in the history
  • Loading branch information
theburningmonk committed Jan 1, 2020
1 parent 7d27134 commit d573ce5
Show file tree
Hide file tree
Showing 5 changed files with 347 additions and 0 deletions.
40 changes: 40 additions & 0 deletions packages/lambda-powertools-cloudwatchevents-client/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# lambda-powertools-cloudwatchevents-client

CloudWatchEvents client wrapper that knows how to forward correlation IDs (captured via `@dazn/lambda-powertools-correlation-ids`).

Main features:

* auto-injects correlation IDs into the CloudWatchEvents events when you call `putEvents`

* direct replacement for `AWS.CloudWatchEvents` client

## Getting Started

Install from NPM: `npm install @dazn/lambda-powertools-cloudwatchevents-client`

## API

It's exactly the same as the CloudWatchEvents client from the AWS SDK.

```js
const CloudWatchEvents = require('@dazn/lambda-powertools-cloudwatchevents-client')

const publishEvents = async () => {
const putEventsReq = {
Entries: [
{
Source: "my-source",
"Detail-Type": "my-type",
Detail: JSON.stringify({ message: 'hello cloudwatchevents' })
},
{
Source: "my-source",
"Detail-Type": "my-type",
Detail: JSON.stringify({ message: 'hello lambda-powertools' })
}
]
}

await CloudWatchEvents.putEvents(putEventsReq).promise()
}
```
120 changes: 120 additions & 0 deletions packages/lambda-powertools-cloudwatchevents-client/__tests__/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
const AWS = require('aws-sdk')

const mockPutEvents = jest.fn()
AWS.CloudWatchEvents.prototype.putEvents = mockPutEvents

global.console.log = jest.fn()

const CloudWatchEvents = require('../index')
const CorrelationIds = require('@dazn/lambda-powertools-correlation-ids')

beforeEach(() => {
mockPutEvents.mockReturnValueOnce({
promise: async () => Promise.resolve()
})
})

afterEach(() => {
mockPutEvents.mockClear()

CorrelationIds.clearAll()
})

const verifyPutEventsContext = async (f) => {
const eventTypes = [
'wrote_test',
'ran_test',
'pass_test'
]
const entries = eventTypes
.map(eventType => {
const data = { eventType, username: 'theburningmonk' }
return {
Source: 'test',
DetailType: 'test',
Detail: JSON.stringify(data)
}
})
const params = {
Entries: entries
}
await CloudWatchEvents.putEvents(params).promise()

expect(mockPutEvents).toBeCalled()
const actualParams = mockPutEvents.mock.calls[0][0]
actualParams.Entries.forEach(entry => {
const actualDetail = JSON.parse(entry.Detail)
f(actualDetail.__context__)
})
}

const verifyPutEventsWithCorrelationIdsContext = async (correlationIds, f) => {
const eventTypes = [
'wrote_test',
'ran_test',
'pass_test'
]
const entries = eventTypes
.map(eventType => {
const data = { eventType, username: 'theburningmonk' }
return {
Source: 'test',
DetailType: 'test',
Detail: JSON.stringify(data)
}
})
const params = {
Entries: entries
}
await CloudWatchEvents.putEventsWithCorrelationIds(correlationIds, params).promise()

expect(mockPutEvents).toBeCalled()
const actualParams = mockPutEvents.mock.calls[0][0]
actualParams.Entries.forEach(entry => {
const actualDetail = JSON.parse(entry.Detail)
f(actualDetail.__context__)
})
}

describe('CloudWatchEvents client', () => {
describe('.putEvents', () => {
describe('when there are no correlation IDs', () => {
it('sends empty __context__ ', async () => {
await verifyPutEventsContext(x => expect(x).toEqual({}))
})
})

describe('when there are global correlationIds', () => {
it('forwards them in __context__', async () => {
const correlationIds = {
'x-correlation-id': 'id',
'debug-log-enabled': 'true'
}
CorrelationIds.replaceAllWith(correlationIds)

await verifyPutEventsContext(x => {
expect(x).toEqual({
'x-correlation-id': 'id',
'debug-log-enabled': 'true'
})
})
})
})
})

describe('.putEventsWithCorrelationIds', () => {
it('forwards given correlationIds in __context__ field', async () => {
const correlationIds = new CorrelationIds({
'x-correlation-id': 'child-id',
'debug-log-enabled': 'true'
})

await verifyPutEventsWithCorrelationIdsContext(correlationIds, x => {
expect(x).toEqual({
'x-correlation-id': 'child-id',
'debug-log-enabled': 'true'
})
})
})
})
})
58 changes: 58 additions & 0 deletions packages/lambda-powertools-cloudwatchevents-client/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
process.env.AWS_NODEJS_CONNECTION_REUSE_ENABLED = '1'
const CloudWatchEvents = require('aws-sdk/clients/cloudwatchevents')
const client = new CloudWatchEvents()
const Log = require('@dazn/lambda-powertools-logger')
const CorrelationIds = require('@dazn/lambda-powertools-correlation-ids')

function tryJsonParse (data) {
if (typeof data !== 'string') {
return null
}

try {
return JSON.parse(data)
} catch (err) {
Log.warn('only JSON string data can be modified to insert correlation IDs', null, err)
return null
}
}

function addCorrelationIds (correlationIds, data) {
// only do this with JSON string data
const payload = tryJsonParse(data)
if (!payload) {
return data
}

const ids = correlationIds.get()
const newData = {
__context__: ids,
...payload
}
return JSON.stringify(newData)
}

client._putEvents = client.putEvents

client.putEvents = (...args) => {
return client.putEventsWithCorrelationIds(CorrelationIds, ...args)
}

client.putEventsWithCorrelationIds = (correlationIds, params, ...args) => {
const newEntries = params.Entries.map(entry => {
const newDetail = addCorrelationIds(correlationIds, entry.Detail)
return {
...entry,
Detail: newDetail
}
})

const extendedParams = {
...params,
Entries: newEntries
}

return client._putEvents(extendedParams, ...args)
}

module.exports = client
102 changes: 102 additions & 0 deletions packages/lambda-powertools-cloudwatchevents-client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions packages/lambda-powertools-cloudwatchevents-client/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "@dazn/lambda-powertools-cloudwatchevents-client",
"version": "1.15.6",
"description": "CloudWatchEvents client wrapper that knows how to forward correlation IDs (captured via @dazn/lambda-powertools-correlation-ids)",
"main": "index.js",
"scripts": {
"test": "jest"
},
"dependencies": {
"@dazn/lambda-powertools-correlation-ids": "^1.8.2",
"@dazn/lambda-powertools-logger": "^1.15.2",
"aws-sdk": "^2.540.0"
},
"license": "MIT",
"author": "Yan Cui",
"homepage": "https://github.com/getndazn/dazn-lambda-powertools#readme",
"repository": {
"type": "git",
"url": "git+https://github.com/getndazn/dazn-lambda-powertools.git"
},
"bugs": {
"url": "https://github.com/getndazn/dazn-lambda-powertools/issues"
},
"publishConfig": {
"access": "public"
}
}

0 comments on commit d573ce5

Please sign in to comment.