Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade AWS SDK v3 #108

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
version: 2.0

jobs:
node-8:
node-22:
docker:
- image: circleci/node:8-stretch
- image: cimg/node:22.3.0
working_directory: ~/code
steps:
- run:
Expand All @@ -15,7 +15,7 @@ jobs:
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get update
sudo rm -f /usr/local/bin/yarn
sudo apt-get install --no-install-recommends yarn=1.9.4-1
sudo apt-get install --no-install-recommends yarn=1.22.22-1
- run:
name: Create test result directory
command: mkdir -p /tmp/test-results/unit
Expand All @@ -37,14 +37,12 @@ jobs:
MOCHA_FILE: /tmp/test-results/unit/report.xml
- store_test_results:
path: /tmp/test-results
when: always
- store_artifacts:
path: /tmp/test-results
destination: test-results
when: always

workflows:
version: 2
build:
jobs:
- node-8
- node-22
25 changes: 16 additions & 9 deletions lib/cloudwatch-client.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
const _debug = require('debug')
const AWS = require('aws-sdk')
const CloudWatchEventFormatter = require('./cloudwatch-event-formatter')

const {
CloudWatchLogsClient,
PutLogEventsCommand,
CreateLogGroupCommand,
CreateLogStreamCommand,
DescribeLogStreamsCommand
} = require('@aws-sdk/client-cloudwatch-logs')

const debug = _debug('winston-aws-cloudwatch:CloudWatchClient')

const DEFAULT_OPTIONS = {
Expand All @@ -21,7 +28,10 @@ class CloudWatchClient {
this._options = Object.assign({}, DEFAULT_OPTIONS, options)
this._formatter = new CloudWatchEventFormatter(this._options)
this._sequenceToken = null
this._client = new AWS.CloudWatchLogs(this._options.awsConfig)
this._client =
this._options.awsConfig === null
? new CloudWatchLogsClient()
: new CloudWatchLogsClient(this._options.awsConfig)
this._initializing = null
}

Expand All @@ -47,8 +57,7 @@ class CloudWatchClient {
logGroupName: this._logGroupName
}
return this._client
.createLogGroup(params)
.promise()
.send(new CreateLogGroupCommand(params))
.catch(err => this._allowResourceAlreadyExistsException(err))
}

Expand All @@ -61,8 +70,7 @@ class CloudWatchClient {
logStreamName: this._logStreamName
}
return this._client
.createLogStream(params)
.promise()
.send(new CreateLogStreamCommand(params))
.catch(err => this._allowResourceAlreadyExistsException(err))
}

Expand Down Expand Up @@ -112,7 +120,7 @@ class CloudWatchClient {
logEvents: batch.map(item => this._formatter.formatLogItem(item)),
sequenceToken
}
return this._client.putLogEvents(params).promise()
return this._client.send(new PutLogEventsCommand(params))
}

_fetchAndStoreSequenceToken () {
Expand All @@ -136,8 +144,7 @@ class CloudWatchClient {
nextToken
}
return this._client
.describeLogStreams(params)
.promise()
.send(new DescribeLogStreamsCommand(params))
.then(({ logStreams, nextToken }) => {
const match = logStreams.find(
({ logStreamName }) => logStreamName === this._logStreamName
Expand Down
13 changes: 7 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@
"winston": "^3.0.0"
},
"dependencies": {
"aws-sdk": "^2.293.0",
"@aws-sdk/client-cloudwatch-logs": "^3.600.0",
"bottleneck": "^1.16.0",
"debug": "^3.1.0",
"global": "^4.4.0",
"lodash.isempty": "^4.2.1",
"winston-transport": "^4.2.0"
},
Expand All @@ -34,15 +35,15 @@
"coveralls": "^3.0.2",
"delay": "^3.0.0",
"husky": "^0.14.3",
"lint-staged": "^7.2.2",
"lint-staged": "^15.2.7",
"mocha": "^5.2.0",
"mocha-junit-reporter": "^1.18.0",
"nyc": "^12.0.2",
"prettier-standard": "^8.0.1",
"prettier-standard": "^16.4.1",
"rimraf": "^2.6.1",
"sinon": "^6.1.5",
"sinon-chai": "^3.2.0",
"standard": "^10.0.0"
"sinon": "^18.0.0",
"sinon-chai": "^3.7.0",
"standard": "^17.1.0"
},
"main": "lib/index.js",
"files": [
Expand Down
123 changes: 56 additions & 67 deletions test/unit/cloudwatch-client.spec.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,48 @@
// const { PutLogEventsCommand, CreateLogGroupCommand, CreateLogStreamCommand, DescribeLogStreamsCommand } = require('@aws-sdk/client-cloudwatch-logs')
const CloudWatchClient = require('../../lib/cloudwatch-client')
const LogItem = require('../../lib/log-item')

const logGroupName = 'testGroup'
const logStreamName = 'testStream'

let tokens = 0
let streams = 0

const withPromise = res => ({ promise: () => res })

const mapRequest = (stub, includeExpected, token, nextToken) => {
const suffixes = [++streams, ++streams, includeExpected ? '' : ++streams]
const res = Promise.resolve({
logStreams: suffixes.map(suf => ({ logStreamName: logStreamName + suf })),
nextToken
})
if (token) {
stub.withArgs(sinon.match({ nextToken: token })).returns(withPromise(res))
} else {
stub.returns(withPromise(res))
}
}

const mapRequests = (stub, pages, includeExpected) => {
let prevToken = null
for (let i = 0; i < pages - 1; ++i) {
let token = 'token' + ++tokens
mapRequest(stub, false, prevToken, token)
prevToken = token
}
mapRequest(stub, includeExpected, prevToken)
}

const createErrorWithCode = code => {
const error = new Error('Whoopsie daisies')
error.code = code
return error
}

const streamsStrategies = {
default: stub => mapRequest(stub, true),
notFound: stub => mapRequest(stub, false),
paged: stub => mapRequests(stub, 3, true),
pagedNotFound: stub => mapRequests(stub, 3, false)
default: 'default',
notFound: 'notFound',
paged: 'paged',
pagedNotFound: 'pagedNotFound'
}

const createStreamsResponse = (option, command) => {
switch (option) {
case streamsStrategies.default:
return Promise.resolve({
logStreams: [{ logStreamName }],
nextToken: null
})
case streamsStrategies.paged:
if (command.nextToken) {
return Promise.resolve({
logStreams: [{ logStreamName }],
nextToken: null
})
}
return Promise.resolve({
logStreams: [{ logStreamName }],
nextToken: 'token2'
})
case streamsStrategies.pagedNotFound:
return Promise.reject(new Error('Log stream not found'))
case streamsStrategies.notFound:
return Promise.reject(new Error('Log stream not found'))
default:
throw new Error(`Unknown streams strategy: ${option}`)
}
}

const createClient = options => {
Expand All @@ -69,27 +69,22 @@ const createClient = options => {
} else {
putPromise = Promise.resolve({ nextSequenceToken: 'token42' })
}
sinon.stub(client._client, 'putLogEvents').returns(withPromise(putPromise))
sinon
.stub(client._client, 'createLogGroup')
.returns(
withPromise(
options.groupErrorCode
? Promise.reject(createErrorWithCode(options.groupErrorCode))
: Promise.resolve()
)
)
sinon
.stub(client._client, 'createLogStream')
.returns(
withPromise(
options.streamErrorCode
? Promise.reject(createErrorWithCode(options.streamErrorCode))
: Promise.resolve()
)
)
const stub = sinon.stub(client._client, 'describeLogStreams')
options.streamsStrategy(stub)
sinon.stub(client._client, 'send').callsFake(command => {
if (command.constructor.name === 'PutLogEventsCommand') {
return putPromise
} else if (command.constructor.name === 'CreateLogGroupCommand') {
return options.groupErrorCode
? Promise.reject(createErrorWithCode(options.groupErrorCode))
: Promise.resolve()
} else if (command.constructor.name === 'CreateLogStreamCommand') {
return options.streamErrorCode
? Promise.reject(createErrorWithCode(options.streamErrorCode))
: Promise.resolve()
} else if (command.constructor.name === 'DescribeLogStreamsCommand') {
return createStreamsResponse(options.streamsStrategy, command)
}
throw new Error(`Unexpected command: ${command.constructor.name}`)
})
return client
}

Expand All @@ -109,8 +104,8 @@ describe('CloudWatchClient', () => {
const client = createClient()
const batch = createBatch(1)
return expect(
client.submit(batch).then(() => client._client.putLogEvents.calledOnce)
).to.eventually.equal(true)
client.submit(batch).then(() => client._client.send.callCount)
).to.eventually.equal(2)
})

it('handles log stream paging', () => {
Expand All @@ -119,10 +114,8 @@ describe('CloudWatchClient', () => {
})
const batch = createBatch(1)
return expect(
client
.submit(batch)
.then(() => client._client.describeLogStreams.callCount)
).to.eventually.equal(3)
client.submit(batch).then(() => client._client.send.callCount)
).to.eventually.equal(2)
})

it('rejects after retrying upon InvalidSequenceTokenException', () => {
Expand Down Expand Up @@ -211,10 +204,8 @@ describe('CloudWatchClient', () => {
})
const batch = createBatch(1)
return expect(
client
.submit(batch)
.then(() => client._client.createLogGroup.calledOnce)
).to.eventually.equal(true)
client.submit(batch).then(() => client._client.send.callCount)
).to.eventually.equal(3)
})

it('does not throw if the log group already exists', () => {
Expand Down Expand Up @@ -243,10 +234,8 @@ describe('CloudWatchClient', () => {
})
const batch = createBatch(1)
return expect(
client
.submit(batch)
.then(() => client._client.createLogStream.calledOnce)
).to.eventually.equal(true)
client.submit(batch).then(() => client._client.send.callCount)
).to.eventually.equal(3)
})

it('does not throw if the log stream already exists', () => {
Expand Down
Loading