Parameters:
  FastlyCDNLogFilesBucket:
    Description: Name of the S3 bucket where the Fastly CDN log files are stored 
    Type: String
    ConstraintDescription: must be a valid bucket name.
    AllowedPattern: "[a-zA-Z][a-zA-Z0-9_-]*"
    MinLength: 1
  QuicksightUserARN:
    Description: The ARN of the Quicksight user
    Type: String
    MinLength: 1

Resources:
##############################
  ### Glue resources
################################
  FastlyCDNGlueDatabase:
    Type: AWS::Glue::Database
    Properties:
      CatalogId: !Ref AWS::AccountId
      DatabaseInput:
        Description: Glue Database Used for transformed support case
        Name: !Sub "${AWS::StackName}-${AWS::Region}-fastlycdngluedb"
  FastlyCDNGlueCrawler:
    Type: AWS::Glue::Crawler
    Properties:
      DatabaseName: !Ref FastlyCDNGlueDatabase
      Description: Crawler for Transformed Support Case Data
      Name: !Sub "${AWS::StackName}-${AWS::Region}-fastlycdngluecrawler"
      Role: !GetAtt FastlyCDNGlueCrawlerRole.Arn
      SchemaChangePolicy:
        DeleteBehavior: DEPRECATE_IN_DATABASE
        UpdateBehavior: UPDATE_IN_DATABASE
      Targets:
        S3Targets:
          - Path: !Sub 's3://${FastlyCDNLogFilesBucket}/'
  FastlyCDNGlueCrawlerBucketPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action:
              - s3:GetObject
              - s3:PutObject
            Resource:
              - !Sub arn:aws:s3:::${FastlyCDNLogFilesBucket}*
      PolicyName: !Sub "${AWS::StackName}-${AWS::Region}-fastlycdngluebucketpolicy"
      Roles:
        - !Ref FastlyCDNGlueCrawlerRole
  FastlyCDNGlueCrawlerRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service: glue.amazonaws.com
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSGlueServiceRole
      Path: /
  AWSLambdaFunction:
    Type: "AWS::Lambda::Function"
    Properties:
      Description: "Lambda function to start Glue Crawler"
      FunctionName: !Sub "${AWS::StackName}-${AWS::Region}-lambda"
      Handler: index.handler
      Role: !GetAtt AWSLambdaExecutionRole.Arn
      Timeout: 360
      Runtime: python3.11
      Code:
        ZipFile: |
          import boto3
          import os
          import time
          import cfnresponse

          responseData = {}

          def handler(event, context):
            glue_client = boto3.client('glue')
            try:
              gluecrawler = os.environ['gluecrawler']
              response = glue_client.start_crawler(Name=gluecrawler)
              while True:
                time.sleep(30)  # Wait for 30 seconds before checking the status again
                crawler = glue_client.get_crawler(Name=gluecrawler)
                if crawler['Crawler']['State'] == 'READY':
                  cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData)
                      # Crawler has finished
                  break
              print(response)
            except Exception as e:
              print(e)
              cfnresponse.send(event, context, cfnresponse.FAILED, responseData)
              raise e
            lclient = boto3.client ('lambda')
            lclient.delete_function (FunctionName = context.function_name)
      Environment:
        Variables:
          gluecrawler: !Ref FastlyCDNGlueCrawler
  AWSLambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSGlueServiceRole
      AssumeRolePolicyDocument:
        Statement:
          - Action:
              - sts:AssumeRole
            Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
        Version: "2012-10-17"
      Path: "/"
      Policies:
        - PolicyDocument:
            Statement:
              - Action:
                  - lambda:DeleteFunction
                  - lambda:DeleteLayerVersion
                Effect: Allow
                Resource: !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${AWS::StackName}-${AWS::Region}-lambda
            Version: "2012-10-17"
          PolicyName: !Sub ${AWS::StackName}-${AWS::Region}-AWSLambda-DEL
        - PolicyDocument:
            Statement:
              - Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Effect: Allow
                Resource: arn:aws:logs:*:*:*
            Version: "2012-10-17"
          PolicyName: !Sub ${AWS::StackName}-${AWS::Region}-AWSLambda-CW
        - PolicyDocument:
            Statement:
              - Action:
                  - s3:PutObject
                  - s3:DeleteObject
                  - s3:List*
                Effect: Allow
                Resource:
                  - !Sub arn:aws:s3:::${FastlyCDNLogFilesBucket}/*
                  - !Sub arn:aws:s3:::${FastlyCDNLogFilesBucket}
            Version: "2012-10-17"
          PolicyName: !Sub ${AWS::StackName}-${AWS::Region}-AWSLambda-S3
      RoleName: !Sub ${AWS::StackName}-${AWS::Region}-AWSLambdaExecutionRole
  MyWaitHandle:
    Type: AWS::CloudFormation::WaitConditionHandle
  FastlyCDNLambdaResource:
    Type: AWS::CloudFormation::CustomResource
    DependsOn: AWSLambdaFunction
    Properties:
      ServiceToken: !GetAtt AWSLambdaFunction.Arn
      gluecrawler: !Ref FastlyCDNGlueCrawler
  AthenaQSDataSource:
    Type: AWS::QuickSight::DataSource
    DependsOn: FastlyCDNLambdaResource
    Properties: 
      AwsAccountId: !Ref 'AWS::AccountId'
      DataSourceId: !Sub ${AWS::StackName}-${AWS::Region}-athena-datasource
      Name: !Sub ${AWS::StackName}-${AWS::Region}-athena-datasource
      Type: ATHENA
      DataSourceParameters:
        AthenaParameters:
          WorkGroup: 'primary'
      Permissions:
        - Principal: !Ref QuicksightUserARN
          Actions:
            - 'quicksight:DescribeDataSource'
            - 'quicksight:DescribeDataSourcePermissions'
            - 'quicksight:PassDataSource'
            - 'quicksight:UpdateDataSource'
            - 'quicksight:DeleteDataSource'
            - 'quicksight:UpdateDataSourcePermissions'
  AthenaQSDataSet:
    Type: 'AWS::QuickSight::DataSet'
    DependsOn: FastlyCDNLambdaResource
    Properties: 
      AwsAccountId: !Ref 'AWS::AccountId'
      DataSetId: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
      Name: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
      ImportMode: SPICE
      Permissions: 
        - Actions:
            - 'quicksight:UpdateDataSetPermissions'
            - 'quicksight:DescribeDataSet'
            - 'quicksight:DescribeDataSetPermissions'
            - 'quicksight:PassDataSet'
            - 'quicksight:DescribeIngestion'
            - 'quicksight:ListIngestions'
            - 'quicksight:UpdateDataSet'
            - 'quicksight:DeleteDataSet'
            - 'quicksight:CreateIngestion'
            - 'quicksight:CancelIngestion'
          Principal: !Ref QuicksightUserARN
      PhysicalTableMap:
        PhysicalTable1: 
          RelationalTable:
            DataSourceArn: !GetAtt AthenaQSDataSource.Arn
            Schema: !Ref FastlyCDNGlueDatabase
            # Name: !Ref GenerateGlueTableName
            Name: !Join [ "_", !Split [ "-", !Ref FastlyCDNLogFilesBucket ] ]
            InputColumns:
              - Name: timestamp
                Type: STRING
              - Name: client_ip
                Type: STRING
              - Name: geo_country
                Type: STRING
              - Name: geo_city
                Type: STRING
              - Name: host
                Type: STRING
              - Name: url
                Type: STRING
              - Name: request_method
                Type: STRING
              - Name: request_protocol
                Type: STRING
              - Name: request_referer
                Type: STRING
              - Name: request_user_agent
                Type: STRING
              - Name: response_state
                Type: STRING
              - Name: response_status
                Type: INTEGER
              - Name: response_reason
                Type: STRING
              - Name: response_body_size
                Type: INTEGER
              - Name: fastly_server
                Type: STRING
              - Name: fastly_is_edge
                Type: STRING
      LogicalTableMap:
        LogicalTable1:
          Alias: fastlycdntable
          Source:
            PhysicalTableId: PhysicalTable1
          DataTransforms:
          - CastColumnTypeOperation:
              ColumnName: timestamp
              NewColumnType: DATETIME
              Format: yyyy-MM-dd'T'HH:mm:ssZ
          - TagColumnOperation:
              ColumnName: geo_country
              Tags:
                - ColumnGeographicRole: COUNTRY
          - TagColumnOperation:
              ColumnName: geo_city
              Tags:
                - ColumnGeographicRole: CITY
          - ProjectOperation:
              ProjectedColumns:
                - timestamp
                - client_ip
                - geo_country
                - geo_city
                - host
                - url
                - request_method
                - request_protocol
                - request_referer
                - request_user_agent
                - response_state
                - response_status
                - response_reason
                - response_body_size
                - fastly_server
                - fastly_is_edge
      OutputColumns:
          - Name: timestamp
            Type: DATETIME
          - Name: client_ip
            Type: STRING
          - Name: geo_country
            Type: STRING
          - Name: geo_city
            Type: STRING
          - Name: host
            Type: STRING
          - Name: url
            Type: STRING
          - Name: request_method
            Type: STRING
          - Name: request_protocol
            Type: STRING
          - Name: request_referer
            Type: STRING
          - Name: request_user_agent
            Type: STRING
          - Name: response_state
            Type: STRING
          - Name: response_status
            Type: INTEGER
          - Name: response_reason
            Type: STRING
          - Name: response_body_size
            Type: INTEGER
          - Name: fastly_server
            Type: STRING
          - Name: fastly_is_edge
            Type: STRING
  AthenaQSAnalysis:
    Type: AWS::QuickSight::Analysis
    Properties:
      AwsAccountId: !Ref AWS::AccountId
      AnalysisId: FastlyCDNLogsAnalysisCF
      ThemeArn: !Sub arn:aws:quicksight::aws:theme/MIDNIGHT
      Name: FastlyCDNLogsAnalysisCF
      Permissions:
        - Principal: !Ref QuicksightUserARN
          Actions:
          - quicksight:RestoreAnalysis
          - quicksight:UpdateAnalysisPermissions
          - quicksight:DeleteAnalysis
          - quicksight:QueryAnalysis
          - quicksight:DescribeAnalysisPermissions
          - quicksight:DescribeAnalysis
          - quicksight:UpdateAnalysis
      Tags:
        - Key: FastlyCDNLogsAnalysisCF
          Value: FastlyCDNLogsAnalysisCF
      Definition:
        DataSetIdentifierDeclarations:
        - Identifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
          DataSetArn: !GetAtt AthenaQSDataSet.Arn
        Sheets:
        - SheetId: f99e61a5-84cc-48a3-b67d-e45af9aa8a18
          Name: CDN Metrics
          ParameterControls:
          - Dropdown:
              ParameterControlId: ff11cafa-3094-4255-9276-8f1710f3b6ed
              Title: City
              SourceParameterName: City
              DisplayOptions:
                SelectAllOptions:
                  Visibility: VISIBLE
                TitleOptions:
                  Visibility: VISIBLE
                  FontConfiguration:
                    FontSize:
                      Relative: MEDIUM
              Type: MULTI_SELECT
              SelectableValues:
                LinkToDataSetColumn:
                  DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                  ColumnName: geo_city
          - Dropdown:
              ParameterControlId: aca983d2-990a-42c6-aeb6-772471061959
              Title: Domain
              SourceParameterName: Domain
              DisplayOptions:
                SelectAllOptions:
                  Visibility: VISIBLE
                TitleOptions:
                  Visibility: VISIBLE
                  FontConfiguration:
                    FontSize:
                      Relative: MEDIUM
              Type: MULTI_SELECT
              SelectableValues:
                LinkToDataSetColumn:
                  DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                  ColumnName: host
          FilterControls:
          - RelativeDateTime:
              FilterControlId: 66a9a46e-9b65-41b0-8a7d-7371abf53bcd
              Title: timestamp
              SourceFilterId: a4acb795-11c5-44b8-95a5-376112ba9e6b
          Visuals:
          - CustomContentVisual:
              VisualId: 6cef9dc7-9d44-4548-8df5-26753f0125e5
              Title:
                Visibility: HIDDEN
              Subtitle:
                Visibility: VISIBLE
              ChartConfiguration:
                ContentUrl: https://theme.zdassets.com/theme_assets/70773/8e2a2a19e26476f2ada25b517f31f58287fb2552.png
                ContentType: IMAGE
              Actions:
              - CustomActionId: ca606831-def0-493b-80e8-4ceccc45f74f
                Name: Action 1
                Status: ENABLED
                Trigger: DATA_POINT_CLICK
                ActionOperations:
                - URLOperation:
                    URLTemplate: https://www.fastly.com/
                    URLTarget: NEW_TAB
              DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
          - InsightVisual:
              VisualId: c2427ee3-b35a-4b57-a6b1-6c82dce592b6
              Title:
                Visibility: HIDDEN
              Subtitle:
                Visibility: VISIBLE
              InsightConfiguration:
                Computations:
                - TopBottomRanked:
                    ComputationId: b3026f16-5fad-4e48-a203-de4c4d491437
                    Name: Top
                    Category:
                      CategoricalDimensionField:
                        FieldId: s3LogicalTableMap.host.0.1704493436405
                        Column:
                          DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                          ColumnName: host
                    ResultSize: 3
                    Type: TOP
              Actions: []
              DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
          - PieChartVisual:
              VisualId: 0cf808d2-f1eb-45cc-ac99-b80e2cd6ba46
              Title:
                Visibility: VISIBLE
                FormatText:
                  RichText: |-
                    <visual-title>
                      <inline color="#17dfef" font-size="16px">Total Number of Requests by HTTP Status Code</inline>
                    </visual-title>
              Subtitle:
                Visibility: VISIBLE
              ChartConfiguration:
                FieldWells:
                  PieChartAggregatedFieldWells:
                    Category:
                    - NumericalDimensionField:
                        FieldId: s3LogicalTableMap.response_status.0.1704491278514
                        Column:
                          DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                          ColumnName: response_status
                    Values: []
                SortConfiguration:
                  CategoryItemsLimit:
                    OtherCategories: INCLUDE
                  SmallMultiplesLimitConfiguration:
                    OtherCategories: INCLUDE
                DonutOptions:
                  ArcOptions:
                    ArcThickness: MEDIUM
                Legend:
                  Visibility: HIDDEN
                DataLabels:
                  Visibility: VISIBLE
                  Overlap: DISABLE_OVERLAP
                Tooltip:
                  TooltipVisibility: VISIBLE
                  SelectedTooltipType: DETAILED
                  FieldBasedTooltip:
                    AggregationVisibility: HIDDEN
                    TooltipTitleType: PRIMARY_VALUE
                    TooltipFields:
                    - FieldTooltipItem:
                        FieldId: s3LogicalTableMap.response_status.0.1704491278514
                        Visibility: VISIBLE
                VisualPalette:
                  ColorMap:
                  - Element:
                      FieldId: s3LogicalTableMap.response_status.0.1704491278514
                      FieldValue: '200'
                    Color: "#2CAD00"
              Actions: []
              ColumnHierarchies: []
          - PieChartVisual:
              VisualId: 73e3a100-8a47-4adc-93ad-519b03503fc9
              Title:
                Visibility: VISIBLE
                FormatText:
                  RichText: |-
                    <visual-title>
                      <inline color="#17dfef" font-size="16px">Response State - HIT/MISS/PASS</inline>
                    </visual-title>
              Subtitle:
                Visibility: VISIBLE
              ChartConfiguration:
                FieldWells:
                  PieChartAggregatedFieldWells:
                    Category:
                    - CategoricalDimensionField:
                        FieldId: s3LogicalTableMap.response_state.0.1704492135510
                        Column:
                          DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                          ColumnName: response_state
                    Values: []
                SortConfiguration:
                  CategoryItemsLimit:
                    OtherCategories: INCLUDE
                  SmallMultiplesLimitConfiguration:
                    OtherCategories: INCLUDE
                DonutOptions:
                  ArcOptions:
                    ArcThickness: WHOLE
                Legend:
                  Visibility: HIDDEN
                DataLabels:
                  Visibility: VISIBLE
                  MeasureLabelVisibility: VISIBLE
                  Position: INSIDE
                  LabelFontConfiguration:
                    FontSize:
                      Relative: MEDIUM
                  Overlap: DISABLE_OVERLAP
                Tooltip:
                  TooltipVisibility: VISIBLE
                  SelectedTooltipType: DETAILED
                  FieldBasedTooltip:
                    AggregationVisibility: HIDDEN
                    TooltipTitleType: PRIMARY_VALUE
                    TooltipFields:
                    - FieldTooltipItem:
                        FieldId: s3LogicalTableMap.response_state.0.1704492135510
                        Visibility: VISIBLE
                VisualPalette:
                  ColorMap:
                  - Element:
                      FieldId: s3LogicalTableMap.response_state.0.1704492135510
                      FieldValue: PASS
                    Color: "#0251D3"
                  - Element:
                      FieldId: s3LogicalTableMap.response_state.0.1704492135510
                      FieldValue: HIT
                    Color: "#2CAD00"
                  - Element:
                      FieldId: s3LogicalTableMap.response_state.0.1704492135510
                      FieldValue: MISS-CLUSTER
                    Color: "#8B5011"
                  - Element:
                      FieldId: s3LogicalTableMap.response_state.0.1704492135510
                      FieldValue: MISS
                    Color: "#F11835"
                  - Element:
                      FieldId: s3LogicalTableMap.response_state.0.1704492135510
                      FieldValue: HIT-CLUSTER
                    Color: "#863CFF"
              Actions: []
              ColumnHierarchies: []
          - ComboChartVisual:
              VisualId: f7e5636b-8a24-4448-8ed6-336da1e76c32
              Title:
                Visibility: VISIBLE
                FormatText:
                  RichText: |-
                    <visual-title>
                      <inline color="#17dfef" font-size="16px">Response Status - Drill down for specific urls</inline>
                    </visual-title>
              Subtitle:
                Visibility: VISIBLE
              ChartConfiguration:
                FieldWells:
                  ComboChartAggregatedFieldWells:
                    Category:
                    - DateDimensionField:
                        FieldId: s3LogicalTableMap.timestamp.0.1704492354429
                        Column:
                          DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                          ColumnName: timestamp
                        DateGranularity: WEEK
                        HierarchyId: s3LogicalTableMap.timestamp.0.1704492354429
                    BarValues:
                    - CategoricalMeasureField:
                        FieldId: s3LogicalTableMap.response_reason.1.1704493014952
                        Column:
                          DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                          ColumnName: response_reason
                        AggregationFunction: COUNT
                    Colors:
                    - CategoricalDimensionField:
                        FieldId: s3LogicalTableMap.response_reason.2.1704493030383
                        Column:
                          DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                          ColumnName: response_reason
                    LineValues: []
                SortConfiguration:
                  CategorySort:
                  - FieldSort:
                      FieldId: s3LogicalTableMap.timestamp.0.1704492354429
                      Direction: ASC
                  CategoryItemsLimit:
                    OtherCategories: INCLUDE
                  ColorItemsLimit:
                    OtherCategories: INCLUDE
                BarsArrangement: CLUSTERED
                CategoryAxis:
                  AxisOffset: 72px
                Legend:
                  Visibility: VISIBLE
                  Position: TOP
                BarDataLabels:
                  Visibility: HIDDEN
                  Overlap: DISABLE_OVERLAP
                Tooltip:
                  TooltipVisibility: VISIBLE
                  SelectedTooltipType: DETAILED
                  FieldBasedTooltip:
                    AggregationVisibility: HIDDEN
                    TooltipTitleType: PRIMARY_VALUE
                    TooltipFields:
                    - FieldTooltipItem:
                        FieldId: s3LogicalTableMap.timestamp.0.1704492354429
                        Visibility: VISIBLE
                    - FieldTooltipItem:
                        FieldId: s3LogicalTableMap.response_reason.2.1704493030383
                        Visibility: VISIBLE
                    - FieldTooltipItem:
                        FieldId: s3LogicalTableMap.response_reason.2.1704493030383
                        Visibility: VISIBLE
              Actions: []
              ColumnHierarchies:
              - DateTimeHierarchy:
                  HierarchyId: s3LogicalTableMap.timestamp.0.1704492354429
          - LineChartVisual:
              VisualId: 86a160d9-e841-431f-855b-bb2e433831ec
              Title:
                Visibility: VISIBLE
                FormatText:
                  RichText: |-
                    <visual-title>
                      <inline color="#17dfef" font-size="16px">Number of Requests with Time</inline>
                    </visual-title>
              Subtitle:
                Visibility: VISIBLE
              ChartConfiguration:
                FieldWells:
                  LineChartAggregatedFieldWells:
                    Category:
                    - DateDimensionField:
                        FieldId: s3LogicalTableMap.timestamp.0.1704493828270
                        Column:
                          DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                          ColumnName: timestamp
                        DateGranularity: WEEK
                        HierarchyId: s3LogicalTableMap.timestamp.0.1704493828270
                    Values:
                    - CategoricalMeasureField:
                        FieldId: s3LogicalTableMap.request_method.1.1704493846435
                        Column:
                          DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                          ColumnName: request_method
                        AggregationFunction: COUNT
                    Colors: []
                SortConfiguration:
                  CategorySort:
                  - FieldSort:
                      FieldId: s3LogicalTableMap.timestamp.0.1704493828270
                      Direction: DESC
                  CategoryItemsLimitConfiguration:
                    OtherCategories: INCLUDE
                  ColorItemsLimitConfiguration:
                    OtherCategories: INCLUDE
                  SmallMultiplesLimitConfiguration:
                    OtherCategories: INCLUDE
                Type: LINE
                XAxisDisplayOptions:
                  TickLabelOptions:
                    RotationAngle: 0
                  AxisLineVisibility: HIDDEN
                  DataOptions:
                    DateAxisOptions:
                      MissingDateVisibility: HIDDEN
                PrimaryYAxisDisplayOptions:
                  AxisOptions:
                    GridLineVisibility: VISIBLE
                Series:
                - FieldSeriesItem:
                    FieldId: s3LogicalTableMap.request_method.1.1704493846435
                    AxisBinding: PRIMARY_YAXIS
                    Settings:
                      MarkerStyleSettings:
                        MarkerVisibility: VISIBLE
                        MarkerColor: "#FFB500"
                DataLabels:
                  Visibility: VISIBLE
                  Overlap: DISABLE_OVERLAP
                Tooltip:
                  TooltipVisibility: VISIBLE
                  SelectedTooltipType: DETAILED
                  FieldBasedTooltip:
                    AggregationVisibility: HIDDEN
                    TooltipTitleType: PRIMARY_VALUE
                    TooltipFields:
                    - FieldTooltipItem:
                        FieldId: s3LogicalTableMap.timestamp.0.1704493828270
                        Visibility: VISIBLE
                    - FieldTooltipItem:
                        FieldId: s3LogicalTableMap.request_method.1.1704493846435
                        Visibility: VISIBLE
                VisualPalette:
                  ColorMap:
                  - Element:
                      FieldId: s3LogicalTableMap.request_method.1.1704493846435
                      FieldValue: request_method
                    Color: "#0251D3"
              Actions: []
              ColumnHierarchies:
              - DateTimeHierarchy:
                  HierarchyId: s3LogicalTableMap.timestamp.0.1704493828270
          - SankeyDiagramVisual:
              VisualId: c11b51d9-fe74-4f95-ad47-8511fec4a4cf
              Title:
                Visibility: VISIBLE
                FormatText:
                  RichText: |-
                    <visual-title>
                      <inline color="#17dfef" font-size="16px">Fastly Server Mapping with Domain</inline>
                    </visual-title>
              Subtitle:
                Visibility: VISIBLE
              ChartConfiguration:
                FieldWells:
                  SankeyDiagramAggregatedFieldWells:
                    Source:
                    - CategoricalDimensionField:
                        FieldId: s3LogicalTableMap.fastly_server.0.1704495019093
                        Column:
                          DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                          ColumnName: fastly_server
                    Destination:
                    - CategoricalDimensionField:
                        FieldId: s3LogicalTableMap.host.1.1704495055508
                        Column:
                          DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                          ColumnName: host
                    Weight: []
                SortConfiguration:
                  SourceItemsLimit:
                    ItemsLimit: 10
                    OtherCategories: EXCLUDE
                DataLabels:
                  Visibility: VISIBLE
                  Overlap: DISABLE_OVERLAP
              Actions: []
          - TableVisual:
              VisualId: 06ee529a-36af-40bb-bb87-b53e80dfa69e
              Title:
                Visibility: VISIBLE
                FormatText:
                  RichText: |-
                    <visual-title>
                      <inline color="#17dfef" font-size="16px">Top Client IPs by Requests</inline>
                    </visual-title>
              Subtitle:
                Visibility: VISIBLE
              ChartConfiguration:
                FieldWells:
                  TableAggregatedFieldWells:
                    GroupBy:
                    - CategoricalDimensionField:
                        FieldId: s3LogicalTableMap.client_ip.0.1704495343744
                        Column:
                          DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                          ColumnName: client_ip
                    - CategoricalDimensionField:
                        FieldId: s3LogicalTableMap.geo_country.1.1704495351209
                        Column:
                          DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                          ColumnName: geo_country
                    Values:
                    - CategoricalMeasureField:
                        FieldId: s3LogicalTableMap.request_method.2.1704495356758
                        Column:
                          DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                          ColumnName: request_method
                        AggregationFunction: COUNT
                SortConfiguration:
                  RowSort:
                  - FieldSort:
                      FieldId: s3LogicalTableMap.request_method.2.1704495356758
                      Direction: DESC
                TableOptions:
                  HeaderStyle:
                    TextWrap: WRAP
                    Height: 25
                  CellStyle:
                    Height: 25
                FieldOptions:
                  SelectedFieldOptions:
                  - FieldId: s3LogicalTableMap.client_ip.0.1704495343744
                    Width: 149px
                  - FieldId: s3LogicalTableMap.geo_country.1.1704495351209
                    Width: 124px
                  - FieldId: s3LogicalTableMap.request_method.2.1704495356758
                    Width: 235px
                  Order: []
                TableInlineVisualizations:
                - DataBars:
                    FieldId: s3LogicalTableMap.request_method.2.1704495356758
                    PositiveColor: "#2CAD00"
                    NegativeColor: "#DE3B00"
              Actions: []
          - SankeyDiagramVisual:
              VisualId: 9d501730-ddd3-4381-8e1b-2895260b65a9
              Title:
                Visibility: VISIBLE
                FormatText:
                  RichText: |-
                    <visual-title>
                      <inline color="#17dfef" font-size="16px">Client IPs accessing Hosts</inline>
                    </visual-title>
              Subtitle:
                Visibility: VISIBLE
              ChartConfiguration:
                FieldWells:
                  SankeyDiagramAggregatedFieldWells:
                    Source:
                    - CategoricalDimensionField:
                        FieldId: s3LogicalTableMap.client_ip.0.1704496588228
                        Column:
                          DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                          ColumnName: client_ip
                    Destination:
                    - CategoricalDimensionField:
                        FieldId: s3LogicalTableMap.host.1.1704496591322
                        Column:
                          DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                          ColumnName: host
                    Weight: []
                SortConfiguration:
                  SourceItemsLimit:
                    ItemsLimit: 10
                    OtherCategories: EXCLUDE
                DataLabels:
                  Visibility: VISIBLE
                  Overlap: DISABLE_OVERLAP
              Actions: []
          - TreeMapVisual:
              VisualId: 4b2a48e0-d763-4c29-900f-1c90788bec93
              Title:
                Visibility: VISIBLE
                FormatText:
                  RichText: |-
                    <visual-title>
                      <inline color="#17dfef" font-size="16px">Requests by City</inline>
                    </visual-title>
              Subtitle:
                Visibility: VISIBLE
              ChartConfiguration:
                FieldWells:
                  TreeMapAggregatedFieldWells:
                    Groups:
                    - CategoricalDimensionField:
                        FieldId: s3LogicalTableMap.geo_city.1.1704497444589
                        Column:
                          DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                          ColumnName: geo_city
                    Sizes: []
                    Colors:
                    - CategoricalMeasureField:
                        FieldId: s3LogicalTableMap.request_method.1.1704498262804
                        Column:
                          DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                          ColumnName: request_method
                        AggregationFunction: COUNT
                SortConfiguration:
                  TreeMapSort:
                  - FieldSort:
                      FieldId: s3LogicalTableMap.request_method.1.1704498262804
                      Direction: DESC
                  TreeMapGroupItemsLimitConfiguration:
                    ItemsLimit: 5
                    OtherCategories: INCLUDE
                ColorScale:
                  Colors:
                  - Color: "#0251D3"
                  - Color: "#A7DBE2"
                  ColorFillType: GRADIENT
                Legend:
                  Width: 90px
                DataLabels:
                  Visibility: VISIBLE
                  Overlap: DISABLE_OVERLAP
                Tooltip:
                  TooltipVisibility: VISIBLE
                  SelectedTooltipType: DETAILED
                  FieldBasedTooltip:
                    AggregationVisibility: HIDDEN
                    TooltipTitleType: PRIMARY_VALUE
                    TooltipFields:
                    - FieldTooltipItem:
                        FieldId: s3LogicalTableMap.geo_city.1.1704497444589
                        Visibility: VISIBLE
                    - FieldTooltipItem:
                        FieldId: s3LogicalTableMap.request_method.1.1704498262804
                        Visibility: VISIBLE
              Actions: []
              ColumnHierarchies: []
          - BarChartVisual:
              VisualId: c39115cd-3bd3-4b5c-9123-ef0b66c3c9cb
              Title:
                Visibility: VISIBLE
                FormatText:
                  RichText: |-
                    <visual-title>
                      <inline color="#17dfef" font-size="16px">Requests by User Agent</inline>
                    </visual-title>
              Subtitle:
                Visibility: VISIBLE
              ChartConfiguration:
                FieldWells:
                  BarChartAggregatedFieldWells:
                    Category:
                    - CategoricalDimensionField:
                        FieldId: s3LogicalTableMap.request_user_agent.0.1704498353151
                        Column:
                          DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                          ColumnName: request_user_agent
                    Values: []
                    Colors: []
                SortConfiguration:
                  CategoryItemsLimit:
                    OtherCategories: INCLUDE
                  ColorItemsLimit:
                    OtherCategories: INCLUDE
                  SmallMultiplesLimitConfiguration:
                    OtherCategories: INCLUDE
                Orientation: VERTICAL
                BarsArrangement: CLUSTERED
                VisualPalette:
                  ChartColor: "#B9E52F"
                  ColorMap:
                  - Element:
                      FieldId: s3LogicalTableMap.request_user_agent.0.1704498353151
                      FieldValue: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101
                        Firefox/115.0
                    Color: "#B9E52F"
                DataLabels:
                  Visibility: HIDDEN
                  Overlap: DISABLE_OVERLAP
                Tooltip:
                  TooltipVisibility: VISIBLE
                  SelectedTooltipType: DETAILED
                  FieldBasedTooltip:
                    AggregationVisibility: HIDDEN
                    TooltipTitleType: PRIMARY_VALUE
                    TooltipFields:
                    - FieldTooltipItem:
                        FieldId: s3LogicalTableMap.request_user_agent.0.1704498353151
                        Visibility: VISIBLE
              Actions: []
              ColumnHierarchies: []
          Layouts:
          - Configuration:
              FreeFormLayout:
                Elements:
                - ElementId: c2427ee3-b35a-4b57-a6b1-6c82dce592b6
                  ElementType: VISUAL
                  XAxisLocation: 0px
                  YAxisLocation: 144px
                  Width: 320px
                  Height: 128px
                  Visibility: VISIBLE
                  BorderStyle:
                    Visibility: HIDDEN
                - ElementId: 6cef9dc7-9d44-4548-8df5-26753f0125e5
                  ElementType: VISUAL
                  XAxisLocation: 0px
                  YAxisLocation: 0px
                  Width: 320px
                  Height: 144px
                  Visibility: VISIBLE
                  BorderStyle:
                    Visibility: HIDDEN
                - ElementId: 0cf808d2-f1eb-45cc-ac99-b80e2cd6ba46
                  ElementType: VISUAL
                  XAxisLocation: 320px
                  YAxisLocation: 0px
                  Width: 384px
                  Height: 288px
                  Visibility: VISIBLE
                  BorderStyle:
                    Visibility: HIDDEN
                - ElementId: 73e3a100-8a47-4adc-93ad-519b03503fc9
                  ElementType: VISUAL
                  XAxisLocation: 704px
                  YAxisLocation: 0px
                  Width: 432px
                  Height: 432px
                  Visibility: VISIBLE
                  BorderStyle:
                    Visibility: HIDDEN
                - ElementId: f7e5636b-8a24-4448-8ed6-336da1e76c32
                  ElementType: VISUAL
                  XAxisLocation: 1136px
                  YAxisLocation: 0px
                  Width: 464px
                  Height: 432px
                  Visibility: VISIBLE
                  BorderStyle:
                    Visibility: HIDDEN
                - ElementId: 86a160d9-e841-431f-855b-bb2e433831ec
                  ElementType: VISUAL
                  XAxisLocation: 0px
                  YAxisLocation: 256px
                  Width: 704px
                  Height: 176px
                  Visibility: VISIBLE
                  BorderStyle:
                    Visibility: HIDDEN
                - ElementId: c11b51d9-fe74-4f95-ad47-8511fec4a4cf
                  ElementType: VISUAL
                  XAxisLocation: 0px
                  YAxisLocation: 432px
                  Width: 512px
                  Height: 432px
                  Visibility: VISIBLE
                  BorderStyle:
                    Visibility: HIDDEN
                - ElementId: 06ee529a-36af-40bb-bb87-b53e80dfa69e
                  ElementType: VISUAL
                  XAxisLocation: 512px
                  YAxisLocation: 432px
                  Width: 544px
                  Height: 432px
                  Visibility: VISIBLE
                  BorderStyle:
                    Visibility: HIDDEN
                - ElementId: 9d501730-ddd3-4381-8e1b-2895260b65a9
                  ElementType: VISUAL
                  XAxisLocation: 1056px
                  YAxisLocation: 432px
                  Width: 544px
                  Height: 432px
                  Visibility: VISIBLE
                  BorderStyle:
                    Visibility: HIDDEN
                - ElementId: 4b2a48e0-d763-4c29-900f-1c90788bec93
                  ElementType: VISUAL
                  XAxisLocation: 0px
                  YAxisLocation: 864px
                  Width: 798px
                  Height: 532px
                  Visibility: VISIBLE
                  BorderStyle:
                    Visibility: HIDDEN
                - ElementId: c39115cd-3bd3-4b5c-9123-ef0b66c3c9cb
                  ElementType: VISUAL
                  XAxisLocation: 798px
                  YAxisLocation: 864px
                  Width: 798px
                  Height: 532px
                  Visibility: VISIBLE
                  BorderStyle:
                    Visibility: HIDDEN
                CanvasSizeOptions:
                  ScreenCanvasSizeOptions:
                    OptimizedViewPortWidth: 1600px
          SheetControlLayouts:
          - Configuration:
              GridLayout:
                Elements:
                - ElementId: ff11cafa-3094-4255-9276-8f1710f3b6ed
                  ElementType: PARAMETER_CONTROL
                  ColumnSpan: 2
                  RowSpan: 1
                - ElementId: aca983d2-990a-42c6-aeb6-772471061959
                  ElementType: PARAMETER_CONTROL
                  ColumnSpan: 2
                  RowSpan: 1
                - ElementId: 66a9a46e-9b65-41b0-8a7d-7371abf53bcd
                  ElementType: FILTER_CONTROL
                  ColumnSpan: 2
                  RowSpan: 1
          ContentType: INTERACTIVE
        CalculatedFields: []
        ParameterDeclarations:
        - StringParameterDeclaration:
            ParameterValueType: MULTI_VALUED
            Name: City
            DefaultValues: {}
            ValueWhenUnset:
              ValueWhenUnsetOption: RECOMMENDED_VALUE
        - StringParameterDeclaration:
            ParameterValueType: MULTI_VALUED
            Name: Domain
            DefaultValues: {}
            ValueWhenUnset:
              ValueWhenUnsetOption: RECOMMENDED_VALUE
        FilterGroups:
        - FilterGroupId: dcbdd2a2-6a60-4600-b6c6-288f506f3e34
          Filters:
          - TopBottomFilter:
              FilterId: cfdbd746-4f4b-43a8-a1ec-1eb8804a4da0
              Column:
                DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                ColumnName: client_ip
              Limit: 10
              AggregationSortConfigurations:
              - Column:
                  DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                  ColumnName: client_ip
                SortDirection: DESC
                AggregationFunction:
                  CategoricalAggregationFunction: COUNT
          ScopeConfiguration:
            SelectedSheets:
              SheetVisualScopingConfigurations:
              - SheetId: f99e61a5-84cc-48a3-b67d-e45af9aa8a18
                Scope: SELECTED_VISUALS
                VisualIds:
                - 06ee529a-36af-40bb-bb87-b53e80dfa69e
          Status: ENABLED
          CrossDataset: SINGLE_DATASET
        - FilterGroupId: 0ffc106e-4385-46b8-b151-f17c8f312688
          Filters:
          - TopBottomFilter:
              FilterId: f7e1deed-32e5-4b3b-9ec1-848699d17723
              Column:
                DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                ColumnName: request_user_agent
              Limit: 5
              AggregationSortConfigurations:
              - Column:
                  DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                  ColumnName: request_method
                SortDirection: DESC
                AggregationFunction:
                  CategoricalAggregationFunction: COUNT
          ScopeConfiguration:
            SelectedSheets:
              SheetVisualScopingConfigurations:
              - SheetId: f99e61a5-84cc-48a3-b67d-e45af9aa8a18
                Scope: SELECTED_VISUALS
                VisualIds:
                - c39115cd-3bd3-4b5c-9123-ef0b66c3c9cb
          Status: ENABLED
          CrossDataset: SINGLE_DATASET
        - FilterGroupId: '097da406-f0bc-4048-bbdd-cc264802965b'
          Filters:
          - CategoryFilter:
              FilterId: c4d5ccf5-1a35-44ec-b87d-1e298a56a535
              Column:
                DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                ColumnName: geo_city
              Configuration:
                CustomFilterConfiguration:
                  MatchOperator: EQUALS
                  ParameterName: City
                  NullOption: NON_NULLS_ONLY
          ScopeConfiguration:
            SelectedSheets:
              SheetVisualScopingConfigurations:
              - SheetId: f99e61a5-84cc-48a3-b67d-e45af9aa8a18
                Scope: ALL_VISUALS
          Status: ENABLED
          CrossDataset: SINGLE_DATASET
        - FilterGroupId: 72feed16-a306-486d-8a68-ff2482f60bb1
          Filters:
          - CategoryFilter:
              FilterId: f5e33924-0f5d-4413-9de8-a22692956989
              Column:
                DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                ColumnName: host
              Configuration:
                CustomFilterConfiguration:
                  MatchOperator: EQUALS
                  ParameterName: Domain
                  NullOption: NON_NULLS_ONLY
          ScopeConfiguration:
            SelectedSheets:
              SheetVisualScopingConfigurations:
              - SheetId: f99e61a5-84cc-48a3-b67d-e45af9aa8a18
                Scope: ALL_VISUALS
          Status: ENABLED
          CrossDataset: SINGLE_DATASET
        - FilterGroupId: c1bb7446-b574-4cc9-8906-fc7dcd6e243f
          Filters:
          - RelativeDatesFilter:
              FilterId: a4acb795-11c5-44b8-95a5-376112ba9e6b
              Column:
                DataSetIdentifier: !Sub ${AWS::StackName}-${AWS::Region}-athena-dataset
                ColumnName: timestamp
              AnchorDateConfiguration:
                AnchorOption: NOW
              MinimumGranularity: MINUTE
              TimeGranularity: YEAR
              RelativeDateType: PREVIOUS
              NullOption: NON_NULLS_ONLY
          ScopeConfiguration:
            SelectedSheets:
              SheetVisualScopingConfigurations:
              - SheetId: f99e61a5-84cc-48a3-b67d-e45af9aa8a18
                Scope: ALL_VISUALS
          Status: ENABLED
          CrossDataset: SINGLE_DATASET
        AnalysisDefaults:
          DefaultNewSheetConfiguration:
            InteractiveLayoutConfiguration:
              Grid:
                CanvasSizeOptions:
                  ScreenCanvasSizeOptions:
                    ResizeOption: FIXED
                    OptimizedViewPortWidth: 1600px
            SheetContentType: INTERACTIVE