Merge pull request #6542 from ktardif/apigw-customize-log-level

AWS API Gateway customize log level
This commit is contained in:
Mariusz Nowak 2019-08-16 10:38:07 +02:00 committed by GitHub
commit 78a703a2eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 81 additions and 3 deletions

View File

@ -1507,3 +1507,16 @@ provider:
restApi:
format: '{ "requestId":"$context.requestId", "ip": "$context.identity.sourceIp" }'
```
The default API Gateway log level will be INFO. You can change this to error with the following:
```yml
# serverless.yml
provider:
name: aws
logs:
restApi:
level: ERROR
```
Valid values are INFO, ERROR.

View File

@ -130,7 +130,9 @@ provider:
apiGateway: true
lambda: true # Optional, can be true (true equals 'Active'), 'Active' or 'PassThrough'
logs:
restApi: true # Optional configuration which specifies if API Gateway logs are used
restApi: # Optional configuration which specifies if API Gateway logs are used. This can either be set to true to use defaults, or configured via subproperties.
format: 'requestId: $context.requestId' # Optional configuration which specifies the log format to use.
level: INFO # Optional configuration which specifies the log level to use. May be either INFO or ERROR.
websocket: true # Optional configuration which specifies if Websockets logs are used
package: # Optional deployment packaging configuration

View File

@ -2,6 +2,7 @@
const _ = require('lodash');
const BbPromise = require('bluebird');
const ServerlessError = require('../../../../../../../../classes/Error').ServerlessError;
const isRestApiId = RegExp.prototype.test.bind(/^[a-z0-9]{3,}$/);
const defaultApiGatewayLogFormat = [
@ -16,6 +17,8 @@ const defaultApiGatewayLogFormat = [
'protocol: $context.protocol',
'responseLength: $context.responseLength',
].join(', ');
const defaultApiGatewayLogLevel = 'INFO';
const apiGatewayValidLogLevels = new Set(['INFO', 'ERROR']);
// NOTE --> Keep this file in sync with ../stage.js
@ -23,6 +26,8 @@ const defaultApiGatewayLogFormat = [
// Stage resource (see https://github.com/serverless/serverless/pull/5692#issuecomment-467849311 for more information).
module.exports = {
defaultApiGatewayLogLevel,
apiGatewayValidLogLevels,
updateStage() {
// this array is used to gather all the patch operations we need to
// perform on the stage
@ -191,6 +196,18 @@ function handleLogs() {
logFormat = logs.format;
}
let level = defaultApiGatewayLogLevel;
if (logs.level) {
level = logs.level;
if (!apiGatewayValidLogLevels.has(level)) {
throw new ServerlessError(
`provider.logs.restApi.level is set to an invalid value. Support values are ${Array.from(
apiGatewayValidLogLevels
).join(', ')}, got ${level}.`
);
}
}
const destinationArn = {
op: 'replace',
path: '/accessLogSettings/destinationArn',
@ -202,7 +219,7 @@ function handleLogs() {
value: logFormat,
};
dataTrace = { op: 'replace', path: '/*/*/logging/dataTrace', value: 'true' };
logLevel = { op: 'replace', path: '/*/*/logging/loglevel', value: 'INFO' };
logLevel = { op: 'replace', path: '/*/*/logging/loglevel', value: level };
operations = [destinationArn, format, dataTrace, logLevel];
}

View File

@ -8,9 +8,14 @@ const sinon = require('sinon');
const _ = require('lodash');
const Serverless = require('../../../../../../../../Serverless');
const AwsProvider = require('../../../../../../provider/awsProvider');
const updateStage = require('./updateStage').updateStage;
const {
updateStage,
apiGatewayValidLogLevels,
defaultApiGatewayLogLevel,
} = require('./updateStage');
chai.use(require('sinon-chai'));
chai.use(require('chai-as-promised'));
const { expect } = chai;
@ -389,4 +394,45 @@ describe('#updateStage()', () => {
});
});
});
function checkLogLevel(setLevel, expectedLevel) {
if (setLevel) {
context.state.service.provider.logs = {
restApi: {
level: setLevel,
},
};
} else {
context.state.service.provider.logs = {
restApi: true,
};
}
return updateStage.call(context).then(() => {
const patchOperation = { op: 'replace', path: '/*/*/logging/loglevel', value: expectedLevel };
const patchOperations = providerRequestStub.args[2][2].patchOperations;
expect(patchOperations).to.include.deep.members([patchOperation]);
});
}
it('should use the default log level if no log level is given', () => {
return checkLogLevel(null, defaultApiGatewayLogLevel);
});
apiGatewayValidLogLevels.forEach(logLevel => {
it(`should update the stage with a custom APIGW log level if given ${logLevel}`, () => {
return checkLogLevel(logLevel, logLevel);
});
});
it('should reject a custom APIGW log level if value is invalid', () => {
context.state.service.provider.logs = {
restApi: {
level: 'INVALID',
},
};
return expect(updateStage.call(context)).to.be.rejectedWith('invalid value');
});
});