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

Add option to change log level for websocket logs #7035

Merged
merged 2 commits into from
Dec 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 13 additions & 0 deletions docs/providers/aws/events/websocket.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,16 @@ provider:
```

The log streams will be generated in a dedicated log group which follows the naming schema `/aws/websocket/{service}-{stage}`.

The default log level will be INFO. You can change this to error with the following:

```yml
# serverless.yml
provider:
name: aws
logs:
websocket:
level: ERROR
```

Valid values are INFO, ERROR.
5 changes: 3 additions & 2 deletions docs/providers/aws/guide/serverless.yml.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,14 +136,15 @@ provider:
apiGateway: true
lambda: true # Optional, can be true (true equals 'Active'), 'Active' or 'PassThrough'
logs:
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.
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.
accessLogging: true # Optional configuration which enables or disables access logging. Defaults to true.
format: 'requestId: $context.requestId' # Optional configuration which specifies the log format to use for access logging.
executionLogging: true # Optional configuration which enables or disables execution logging. Defaults to true.
level: INFO # Optional configuration which specifies the log level to use for execution logging. May be set to either INFO or ERROR.
fullExecutionData: true # Optional configuration which specifies whether or not to log full requests/responses for execution logging. Defaults to true.
role: arn:aws:iam::123456:role # Optional IAM role for ApiGateway to use when managing CloudWatch Logs
websocket: true # Optional configuration which specifies if Websockets logs are used
websocket: # Optional configuration which specifies if Websocket logs are used. This can either be set to `true` to use defaults, or configured via subproperties.
level: INFO # Optional configuration which specifies the log level to use for execution logging. May be set to either INFO or ERROR.
frameworkLambda: true # Optional, whether to write CloudWatch logs for custom resource lambdas as added by the framework

package: # Optional deployment packaging configuration
Expand Down
22 changes: 19 additions & 3 deletions lib/plugins/aws/package/compile/events/websockets/lib/stage.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

const BbPromise = require('bluebird');
const ensureApiGatewayCloudWatchRole = require('../../lib/ensureApiGatewayCloudWatchRole');
const ServerlessError = require('../../../../../../../classes/Error').ServerlessError;

const defaultLogLevel = 'INFO';
const validLogLevels = new Set(['INFO', 'ERROR']);

module.exports = {
compileStage() {
Expand All @@ -15,7 +19,7 @@ module.exports = {
if (provider.apiGateway && provider.apiGateway.websocketApiId) return null;

// logs
const logsEnabled = provider.logs && provider.logs.websocket;
const logs = provider.logs && provider.logs.websocket;

const stageLogicalId = this.provider.naming.getWebsocketsStageLogicalId();
const logGroupLogicalId = this.provider.naming.getWebsocketsLogGroupLogicalId();
Expand All @@ -35,7 +39,19 @@ module.exports = {

Object.assign(cfTemplate.Resources, { [stageLogicalId]: stageResource });

if (!logsEnabled) return null;
if (!logs) return null;

let level = defaultLogLevel;
if (logs.level) {
level = logs.level;
if (!validLogLevels.has(level)) {
throw new ServerlessError(
`provider.logs.websocket.level is set to an invalid value. Support values are ${Array.from(
validLogLevels
).join(', ')}, got ${level}.`
);
}
}

// create log-specific resources
Object.assign(stageResource.Properties, {
Expand All @@ -54,7 +70,7 @@ module.exports = {
},
DefaultRouteSettings: {
DataTraceEnabled: true,
LoggingLevel: 'INFO',
LoggingLevel: level,
},
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
'use strict';

const expect = require('chai').expect;
const chai = require('chai');

const expect = chai.expect;
const sinon = require('sinon');
const BbPromise = require('bluebird');
const _ = require('lodash');
Expand All @@ -9,6 +11,8 @@ const AwsCompileWebsocketsEvents = require('../index');
const Serverless = require('../../../../../../../Serverless');
const AwsProvider = require('../../../../../provider/awsProvider');

chai.use(require('chai-as-promised'));

describe('#compileStage()', () => {
let awsCompileWebsocketsEvents;
let stageLogicalId;
Expand Down Expand Up @@ -151,6 +155,34 @@ describe('#compileStage()', () => {
});
});

it('should use valid logging level', () => {
awsCompileWebsocketsEvents.serverless.service.provider.logs = {
websocket: {
level: 'ERROR',
},
};

return awsCompileWebsocketsEvents.compileStage().then(() => {
const resources =
awsCompileWebsocketsEvents.serverless.service.provider.compiledCloudFormationTemplate
.Resources;

expect(resources[stageLogicalId].Properties.DefaultRouteSettings.LoggingLevel).equal(
'ERROR'
);
});
});

it('should reject invalid logging level', () => {
awsCompileWebsocketsEvents.serverless.service.provider.logs = {
websocket: {
level: 'FOOBAR',
},
};

expect(awsCompileWebsocketsEvents.compileStage()).to.be.rejectedWith('invalid value');
});

it('should ensure ClousWatch role custom resource', () => {
return awsCompileWebsocketsEvents.compileStage().then(() => {
const resources =
Expand Down