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

[AWS::ApiGatewayV2::CfnStage] logging level ERROR not working #1712

Closed
greg5123334 opened this issue Jun 13, 2023 · 1 comment
Closed

[AWS::ApiGatewayV2::CfnStage] logging level ERROR not working #1712

greg5123334 opened this issue Jun 13, 2023 · 1 comment
Labels

Comments

@greg5123334
Copy link

Name of the resource

AWS::ApiGatewayV2::Stage

Resource Name

No response

Issue Description

Describe the bug

Setting AWS::ApiGatewayV2::CfnStage.loggingLevel is not deploying correct value.

Possible Solution

When setting logging level to "ERROR", set physical resource to "Errors Only" mode.

Expected Behavior

When setting logging level to ERROR, the resulting setting in the physical resource should be set to "Errors Only"

Observed Behavior

Setting logging level to ERROR, results in the physical resource being set to "Full Request and Response Logs".

Test Cases

Reproduction Steps

Just set loggingLevel to FALSE and check the actual value, it's set to "Full Request and Response Logs".

LoggingLevel parameter VS physical resource
OFF: "OFF"
INFO: "Full Request and Response Logs"
ERROR: "Full Request and Response Logs" (WRONG!)

import * as cdk from 'aws-cdk-lib';
import {CfnOutput, CfnParameter} from 'aws-cdk-lib';
import {Construct} from 'constructs';

import {CfnApi, CfnStage} from "aws-cdk-lib/aws-apigatewayv2";

export class ApiGatewayV2Stack extends cdk.Stack {


    constructor(scope: Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);

        const api = new CfnApi(this, `${id}-api`, {
            name: "MockApi",
            protocolType: "WEBSOCKET",
            routeSelectionExpression: "$request.body.action",
        });

        new CfnOutput(this, 'ApiId',
            {
                description: "The API identifier.",
                value: api.attrApiId
            })
        new CfnOutput(this, 'ApiEndpoint',
            {
                description: "The default endpoint for an API.",
                value: api.attrApiEndpoint
            })
        new CfnOutput(this, 'ApiBasePath',
            {
                description: "Specifies how to interpret the base path of the API during import.",
                value: String(api.basePath)
            })
        new CfnOutput(this, 'ApiBodyS3Location',
            {
                description: "The S3 location of an OpenAPI definition.",
                value: String(api.bodyS3Location)
            })
        new CfnOutput(this, 'ApiDescription',
            {
                description: "The description of the API.",
                value: String(api.description)
            })
        new CfnOutput(this, 'ApiName',
            {
                description: "The name of the API.",
                value: String(api.name)
            })
        new CfnOutput(this, 'ApiProtocolType',
            {
                description: "The API protocol.",
                value: String(api.protocolType)
            })
        new CfnOutput(this, 'ApiVersion',
            {
                description: "A version identifier for the API.",
                value: String(api.version)
            })

        const loggingLevel = new CfnParameter(this, "LoggingLevel", {
            type: "String",
            description: "Specifies the logging level for this route.",
            default: 'INFO',
            allowedValues: ['INFO', 'ERROR', 'OFF'],
        });
        new CfnOutput(this, 'LoggingLevelParameter',
            {
                description: "A map that defines the stage variables for a Stage.",
                value: loggingLevel.valueAsString
            })

        const stage = new CfnStage(this, `${id}-stage`, {
            apiId: api.ref,
            stageName: `${id}-stage-${loggingLevel.valueAsString}`,
            autoDeploy: true,
            defaultRouteSettings: {
                dataTraceEnabled: true, // depends on logging role
                detailedMetricsEnabled: true,
                loggingLevel: loggingLevel.valueAsString,
            }
        });
        new CfnOutput(this, 'StageApiId',
            {
                description: "The API identifier.",
                value: String(stage.apiId)
            })
        new CfnOutput(this, 'StageName',
            {
                description: "Stage names can contain only alphanumeric characters, hyphens, and underscores, or be $default . Maximum length is 128 characters.",
                value: String(stage.stageName)
            })
        new CfnOutput(this, 'IsStageAutoDeploy',
            {
                description: "Specifies whether updates to an API automatically trigger a new deployment.",
                value: String(stage.autoDeploy)
            })
        new CfnOutput(this, 'StageClientCertId',
            {
                description: "The identifier of a client certificate for a Stage.",
                value: String(stage.clientCertificateId)
            })
        new CfnOutput(this, 'StageDeploymentIde',
            {
                description: "The deployment identifier for the API stage.",
                value: String(stage.deploymentId)
            })
        new CfnOutput(this, 'StageDescription',
            {
                description: "The description for the API stage.",
                value: String(stage.description)
            })
        new CfnOutput(this, 'StageVariables',
            {
                description: "A map that defines the stage variables for a Stage.",
                value: String(stage.stageVariables)
            })
        new CfnOutput(this, 'StageRouteSettings',
            {
                description: "Route settings for the stage.",
                value: String(stage.routeSettings)
            })

    }
}

Other Details

No response

@BenoitLarouche27
Copy link

Hi,
This is not really a bug, more a slightly confusing relationship between the loggingLevel and dataTraceEnabled.

In short, setting dataTraceEnabled: true will always set the CloudWatch Logs setting on the UI to Full Request and Response Logs

It's only if dataTraceEnabled is not set not true, then the logging level will be applied:

  OFF: "Off",
  ERROR: "Errors Only",
  INFO: "Errors and Info Logs",

The 2 parameters creates the impression that there are 6 different possible combination, but in there are really only 4, with some duplication (dataTraceEnabled: true always yields Full Request and Response Logs, and OFF is always OFF)

This logic can be validated by trying all possible combination:

import * as cdk from 'aws-cdk-lib';
import {CfnOutput, CfnParameter} from 'aws-cdk-lib';
import {Construct} from 'constructs';

import {CfnApi, CfnStage} from "aws-cdk-lib/aws-apigatewayv2";

export class V930147049Stack extends cdk.Stack {


    constructor(scope: Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);

        const api = new CfnApi(this, `${id}-api`, {
            name: "MockApi",
            protocolType: "WEBSOCKET",
            routeSelectionExpression: "$request.body.action",
        });

        const stage1 = new CfnStage(this, `${id}-stage1`, {
            apiId: api.ref,
            stageName: `${id}-stage-INFO-true`,
            autoDeploy: true,
            defaultRouteSettings: {
                dataTraceEnabled: true,
                loggingLevel: "INFO"
            }
        });

        const stage2 = new CfnStage(this, `${id}-stage2`, {
            apiId: api.ref,
            stageName: `${id}-stage-ERROR-true`,
            autoDeploy: true,
            defaultRouteSettings: {
                dataTraceEnabled: true,
                loggingLevel: "ERROR"
            }
        });

        const stage3 = new CfnStage(this, `${id}-stage3`, {
            apiId: api.ref,
            stageName: `${id}-stage-OFF-true`,
            autoDeploy: true,
            defaultRouteSettings: {
                dataTraceEnabled: true,
                loggingLevel: "OFF"
            }
        });

        const stage4 = new CfnStage(this, `${id}-stage4`, {
            apiId: api.ref,
            stageName: `${id}-stage-INFO-false`,
            autoDeploy: true,
            defaultRouteSettings: {
                dataTraceEnabled: false,
                loggingLevel: "INFO"
            }
        });

        const stage5 = new CfnStage(this, `${id}-stage5`, {
            apiId: api.ref,
            stageName: `${id}-stage-ERROR-false`,
            autoDeploy: true,
            defaultRouteSettings: {
                dataTraceEnabled: false,
                detailedMetricsEnabled: true,
                loggingLevel: "ERROR"
            }
        });

        const stage6 = new CfnStage(this, `${id}-stage6`, {
            apiId: api.ref,
            stageName: `${id}-stage-OFF-false`,
            autoDeploy: true,
            defaultRouteSettings: {
                dataTraceEnabled: false,
                loggingLevel: "OFF"
            }
        });
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants