---
AWSTemplateFormatVersion: '2010-09-09'
Description: Template to create a demo Custom Widget Lambda functions. Creates a sample dashboard with the custom widgets. Or, once your stack is created, go to the CloudWatch Console Add widget modal to continue with your custom widget creation.

Resources:
  lambdaFunctionDGSummary:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        ZipFile: |
          // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
          // SPDX-License-Identifier: MIT-0
          
          // CloudWatch Custom Widget sample: displays count of Amazon DevOps Guru Insights
          const aws = require('aws-sdk');
          
          const DOCS = `## DevOps Guru Insights Count
          Displays the total counts of Proactive and Reactive Insights in DevOps Guru.
          `;
          
          async function getProactiveInsightsCount(DevOpsGuru, StartTime, EndTime) {
              let NextToken = null;
              let proactivecount=0;
          
              do {
                  const args = { StatusFilter: { Any : { StartTimeRange: { FromTime: StartTime, ToTime: EndTime }, Type: 'PROACTIVE'  }}}
                  const result = await DevOpsGuru.listInsights(args).promise();
                  console.log(result)
                  NextToken = result.NextToken;
                  result.ProactiveInsights.forEach(res => {
                  console.log(result.ProactiveInsights[0].Status)
                  proactivecount++;
                  });
                  } while (NextToken);
              return proactivecount;
          }
          
          async function getReactiveInsightsCount(DevOpsGuru, StartTime, EndTime) {
              let NextToken = null;
              let reactivecount=0;
          
              do {
                  const args = { StatusFilter: { Any : { StartTimeRange: { FromTime: StartTime, ToTime: EndTime }, Type: 'REACTIVE'  }}}
                  const result = await DevOpsGuru.listInsights(args).promise();
                  NextToken = result.NextToken;
                  result.ReactiveInsights.forEach(res => {
                  reactivecount++;
                  });
                  } while (NextToken);
              return reactivecount;
          }
          
          function getHtmlOutput(proactivecount, reactivecount, region, event, context) {
          
              return `DevOps Guru Proactive Insights<br><font size="+10" color="#FF9900">${proactivecount}</font>
              <p>DevOps Guru Reactive Insights</p><font size="+10" color="#FF9900">${reactivecount}`;
          }
          
          exports.handler = async (event, context) => {
              if (event.describe) {
                  return DOCS;
              }
              const widgetContext = event.widgetContext;
              const timeRange = widgetContext.timeRange.zoom || widgetContext.timeRange;
              const StartTime = new Date(timeRange.start);
              const EndTime = new Date(timeRange.end);
              const region = event.region || process.env.AWS_REGION;
              const DevOpsGuru = new aws.DevOpsGuru({ region });
          
              const proactivecount = await getProactiveInsightsCount(DevOpsGuru, StartTime, EndTime);
              const reactivecount = await getReactiveInsightsCount(DevOpsGuru, StartTime, EndTime);
          
              return getHtmlOutput(proactivecount, reactivecount, region, event, context);
              
          };

      Description: "CloudWatch Custom Widget sample: Display DevOps Guru Proactive and Reactive insights count"
      FunctionName: !Sub ${AWS::StackName}-summary
      Handler: index.handler
      MemorySize: 128
      Role: !GetAtt lambdaIAMRole.Arn
      Runtime: nodejs14.x
      Timeout: 60
      Tags:
        - Key: cw-custom-widget
          Value: describe:readOnly
  lambdaFunctionDGProactive:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        ZipFile: |
          // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
          // SPDX-License-Identifier: MIT-0
          
          // CloudWatch Custom Widget sample: displays proactive insights
          const aws = require('aws-sdk');
          
          const DOCS = `## DevOps Guru Insights
          Displays DevOps Guru Proactive Insights.
          `;
          
          async function getInsights(guru, StartTime, EndTime) {
          let NextToken = null;
          let insights = [];

          do {
              const args = { StatusFilter: { Any : { StartTimeRange: { FromTime: StartTime, ToTime: EndTime }, Type: 'PROACTIVE'  }}}
              const result = await guru.listInsights(args).promise();
              NextToken = result.NextToken;
              console.log(result);
              result.ProactiveInsights.forEach(res => {
                  insights = insights.concat(res);
                  console.log(res);
              });
          } while (NextToken);

          return insights;
          }

          function getHtmlOutput(insights, region, event, context) {
              if (insights.length == 0) {
                  return `<p>No proactive insights found for this time period</p>`;
              }
              if (event.Insights) {
                  insights = insights.slice(0, event.Insights);
              }

              const header = '<tr><th>Name</th><th>Severity</th><th>Status</th><th>Time Range</th>'
              const rows = insights.map(i => {
                  return `<tr><td><a href="/devops-guru/insight/proactive/${i.ID}" target=_blank>${i.Name}</a></td>
                              <td>${i.Severity}</td><td>${i.Status}</td>
                              <td>${i.InsightTimeRange.StartTime}</td>`;
              }).join('');

              return `<table>${header}${rows}</table>`;
          }

          exports.handler = async (event, context) => {
              if (event.describe) {
                  return DOCS;
              }
              const widgetContext = event.widgetContext;
              const timeRange = widgetContext.timeRange.zoom || widgetContext.timeRange;
              const StartTime = new Date(timeRange.start);
              const EndTime = new Date(timeRange.end);
              const region = event.region || process.env.AWS_REGION;
              const guru = new aws.DevOpsGuru({ region });
              const cw = new aws.CloudWatch({ region })

              const insights = await getInsights(guru, StartTime, EndTime);
              return getHtmlOutput(insights, region, event, context);
              
          };
      Description: "CloudWatch Custom Widget sample: Display Proactive insights table"
      FunctionName: !Sub ${AWS::StackName}-proactive
      Handler: index.handler
      MemorySize: 128
      Role: !GetAtt lambdaIAMRole.Arn
      Runtime: nodejs14.x
      Timeout: 60
      Tags:
        - Key: cw-custom-widget
          Value: describe:readOnly

  lambdaFunctionDGReactive:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        ZipFile: |
          // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
          // SPDX-License-Identifier: MIT-0
          
          // CloudWatch Custom Widget sample: displays reactive insights
          const aws = require('aws-sdk');
          
          const DOCS = `## DevOps Guru Insights
          Displays DevOps Guru reactive Insights.
          `;
          
          async function getInsights(guru, StartTime, EndTime) {
          let NextToken = null;
          let insights = [];

          do {
              const args = { StatusFilter: { Any : { StartTimeRange: { FromTime: StartTime, ToTime: EndTime }, Type: 'REACTIVE'  }}}
              const result = await guru.listInsights(args).promise();
              NextToken = result.NextToken;
              console.log(result);
              result.ReactiveInsights.forEach(res => {
                  insights = insights.concat(res);
                  console.log(res);
              });
          } while (NextToken);

          return insights;
          }

          function getHtmlOutput(insights, region, event, context) {
              if (insights.length == 0) {
                  return `<p>No reactive insights found for this time period</p>`;
              }
              if (event.Insights) {
                  insights = insights.slice(0, event.Insights);
              }

              const header = '<tr><th>Name</th><th>Severity</th><th>Status</th><th>Time Range</th>'
              const rows = insights.map(i => {
                  return `<tr><td><a href="/devops-guru/insight/reactive/${i.ID}" target=_blank>${i.Name}</a></td>
                              <td>${i.Severity}</td><td>${i.Status}</td>
                              <td>${i.InsightTimeRange.StartTime}</td>`;
              }).join('');

              return `<table>${header}${rows}</table>`;
          }

          exports.handler = async (event, context) => {
              if (event.describe) {
                  return DOCS;
              }
              const widgetContext = event.widgetContext;
              const timeRange = widgetContext.timeRange.zoom || widgetContext.timeRange;
              const StartTime = new Date(timeRange.start);
              const EndTime = new Date(timeRange.end);
              const region = event.region || process.env.AWS_REGION;
              const guru = new aws.DevOpsGuru({ region });
              const cw = new aws.CloudWatch({ region })

              const insights = await getInsights(guru, StartTime, EndTime);
              return getHtmlOutput(insights, region, event, context);
              
          };
      Description: "CloudWatch Custom Widget sample: Display Reactive insights table"
      FunctionName: !Sub ${AWS::StackName}-reactive
      Handler: index.handler
      MemorySize: 128
      Role: !GetAtt lambdaIAMRole.Arn
      Runtime: nodejs14.x
      Timeout: 60
      Tags:
        - Key: cw-custom-widget
          Value: describe:readOnly


  lambdaIAMRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Action:
              - sts:AssumeRole
            Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
      Policies:
        - PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Effect: Allow
                Resource:
                  - !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${AWS::StackName}*:*
          PolicyName: lambda
        - PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Action:
                  - devops-guru:ListInsights
                Effect: Allow
                Resource:
                  - "*"
          PolicyName: getDevOpsGuruInsights

  lambdaSummaryLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub /aws/lambda/${AWS::StackName}-summary
      RetentionInDays: 7

  lambdaReactiveLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub /aws/lambda/${AWS::StackName}-reactive
      RetentionInDays: 7

  lambdaProactiveLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub /aws/lambda/${AWS::StackName}-proactive
      RetentionInDays: 7

  demoDashboard:
    Type: AWS::CloudWatch::Dashboard
    Properties:
      DashboardName: !Sub ${AWS::StackName}-${AWS::Region}
      DashboardBody:
        !Sub
          >
          {
              "start": "-PT1H",
              "widgets": [
                  {
                      "type": "custom",
                      "width": 4,
                      "height": 5,
                      "properties": {
                          "endpoint": "${lambdaFunctionDGSummary.Arn}",
                          "updateOn": {
                              "refresh": true,
                              "timeRange": true
                          },
                          "title": "DevOps Guru Insights Count"
                      }
                  },
                  {
                      "type": "custom",
                      "width": 8,
                      "height": 5,
                      "properties": {
                          "endpoint": "${lambdaFunctionDGProactive.Arn}",
                          "updateOn": {
                              "refresh": true,
                              "timeRange": true
                          },
                          "title": "DevOps Guru Proactive Insights"
                      }
                  },
                  {
                      "type": "custom",
                      "width": 8,
                      "height": 5,
                      "properties": {
                          "endpoint": "${lambdaFunctionDGReactive.Arn}",
                          "updateOn": {
                              "refresh": true,
                              "timeRange": true
                          },
                          "title": "DevOps Guru Reactive Insights"
                      }
                  }
              ]
          }