├── .gitignore ├── .vscode ├── launch.json └── tasks.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── PetAdoptions ├── .gitignore ├── .vscode │ ├── launch.json │ └── tasks.json ├── README.md ├── cdk │ ├── .gitkeep │ └── pet_stack │ │ ├── .gitignore │ │ ├── .npmignore │ │ ├── .vscode │ │ └── launch.json │ │ ├── README.md │ │ ├── app │ │ └── pet_stack.ts │ │ ├── cdk.json │ │ ├── jest.config.js │ │ ├── lib │ │ ├── applications.ts │ │ ├── applications │ │ │ ├── eks-application.ts │ │ │ └── pet-adoptions-history-application.ts │ │ ├── common │ │ │ └── container-image-builder.ts │ │ ├── modules │ │ │ └── core │ │ │ │ └── cloud9.ts │ │ ├── services.ts │ │ └── services │ │ │ ├── ecs-service.ts │ │ │ ├── list-adoptions-service.ts │ │ │ ├── pay-for-adoption-service.ts │ │ │ ├── search-service.ts │ │ │ ├── status-updater-service.ts │ │ │ ├── stepfn.ts │ │ │ └── traffic-generator-service.ts │ │ ├── package.json │ │ ├── resources │ │ ├── addons-otel-permissions.yaml │ │ ├── amp-eks-adot-prometheus-daemonset.yaml │ │ ├── amp-setup-irsa-eks.sh │ │ ├── amp_ingest_kubecost_override_values.yaml │ │ ├── amp_ingest_override_values.yaml │ │ ├── application-insights │ │ │ └── dynamodb-query-function.py │ │ ├── build-adot-ecr.sh │ │ ├── bunnies.zip │ │ ├── collector │ │ │ └── ecs-xray-manual.yaml │ │ ├── cw_dashboard_cost_control.json │ │ ├── cw_dashboard_fluent_bit.json │ │ ├── cwagent-ecs-prometheus-metric-for-awsvpc.yaml │ │ ├── cwagent-fluent-bit-quickstart.yaml │ │ ├── dashboard.json │ │ ├── dashboard.yaml │ │ ├── delete-seed-data.json │ │ ├── destroy_stack.sh │ │ ├── detmon-cwagent-cfn.yml │ │ ├── event-demos │ │ │ └── riv-cop301-2022 │ │ │ │ ├── README.md │ │ │ │ ├── amplifyapp │ │ │ │ ├── .gitignore │ │ │ │ ├── README.md │ │ │ │ ├── amplify │ │ │ │ │ ├── .config │ │ │ │ │ │ └── project-config.json │ │ │ │ │ ├── README.md │ │ │ │ │ ├── backend │ │ │ │ │ │ ├── backend-config.json │ │ │ │ │ │ ├── hosting │ │ │ │ │ │ │ └── amplifyhosting │ │ │ │ │ │ │ │ └── amplifyhosting-template.json │ │ │ │ │ │ └── tags.json │ │ │ │ │ ├── cli.json │ │ │ │ │ ├── hooks │ │ │ │ │ │ └── README.md │ │ │ │ │ └── team-provider-info.json │ │ │ │ ├── package.json │ │ │ │ ├── public │ │ │ │ │ ├── favicon.ico │ │ │ │ │ ├── index.html │ │ │ │ │ ├── logo192.png │ │ │ │ │ ├── logo512.png │ │ │ │ │ ├── manifest.json │ │ │ │ │ └── robots.txt │ │ │ │ └── src │ │ │ │ │ ├── App.css │ │ │ │ │ ├── App.js │ │ │ │ │ ├── App.test.js │ │ │ │ │ ├── components │ │ │ │ │ ├── ColorCard.js │ │ │ │ │ └── ProTip.js │ │ │ │ │ ├── index.css │ │ │ │ │ ├── index.js │ │ │ │ │ ├── logo.svg │ │ │ │ │ ├── reportWebVitals.js │ │ │ │ │ ├── setupTests.js │ │ │ │ │ ├── utils │ │ │ │ │ ├── api.js │ │ │ │ │ ├── colors.js │ │ │ │ │ └── theme.js │ │ │ │ │ └── views │ │ │ │ │ ├── Choice.js │ │ │ │ │ └── Colors.js │ │ │ │ ├── ecs-api │ │ │ │ ├── .gitignore │ │ │ │ ├── Dockerfile │ │ │ │ ├── README.md │ │ │ │ ├── copilot │ │ │ │ │ ├── .workspace │ │ │ │ │ ├── cop301-api │ │ │ │ │ │ ├── addons │ │ │ │ │ │ │ └── observability.yaml │ │ │ │ │ │ └── manifest.yml │ │ │ │ │ └── environments │ │ │ │ │ │ └── test │ │ │ │ │ │ └── manifest.yml │ │ │ │ ├── go.mod │ │ │ │ ├── go.sum │ │ │ │ ├── main.go │ │ │ │ ├── utils.go │ │ │ │ └── utils │ │ │ │ │ └── benchmark.yaml │ │ │ │ └── lambda-api │ │ │ │ ├── README.md │ │ │ │ ├── dequeue │ │ │ │ ├── .npmignore │ │ │ │ ├── dequeue.js │ │ │ │ ├── package.json │ │ │ │ └── unit │ │ │ │ │ └── test-handler.js │ │ │ │ ├── events │ │ │ │ └── event.json │ │ │ │ ├── function │ │ │ │ ├── .npmignore │ │ │ │ ├── app.js │ │ │ │ ├── package.json │ │ │ │ └── tests │ │ │ │ │ └── unit │ │ │ │ │ └── test-handler.js │ │ │ │ ├── package.json │ │ │ │ └── template.yaml │ │ ├── extra_scrape_configs.yaml │ │ ├── fargate-resize-dashboard.json │ │ ├── k8s_petsite │ │ │ ├── deployment.yaml │ │ │ └── xray-daemon-config.yaml │ │ ├── kitten.zip │ │ ├── load_balancer │ │ │ ├── crds.yaml │ │ │ ├── iam_policy.json │ │ │ └── service_account.yaml │ │ ├── microservices │ │ │ ├── payforadoption-go │ │ │ ├── petadoptionshistory-py │ │ │ ├── petlistadoptions-go │ │ │ ├── petsearch-java │ │ │ ├── petsite │ │ │ └── trafficgenerator │ │ ├── otel-collector-prometheus.yaml │ │ ├── petadoptions-grafana-dashboard.json │ │ ├── petadoptionshistory-py │ │ │ ├── README.md │ │ │ ├── petadoptionshistory_complete.py │ │ │ └── petadoptionshistory_tracing.py │ │ ├── prometheus-eks.yaml │ │ ├── puppies.zip │ │ ├── rds_sqlserver.sql │ │ ├── resource-controller-widget │ │ │ ├── cloudwatch-custom-widget.py │ │ │ └── petsite-application-resource-controler.py │ │ ├── seed-data.json │ │ ├── setup-ssm-agent.yaml │ │ ├── stepfn_lambdas │ │ │ ├── lambda_step_priceGreaterThan55.py │ │ │ ├── lambda_step_priceLessThan55.py │ │ │ └── lambda_step_readDDB.py │ │ ├── syn-apicanary.js │ │ ├── syn-uicanary.js │ │ ├── use_cases │ │ │ ├── observability-getting-started-ADOT.yml │ │ │ └── observability-getting-started.yml │ │ └── workshop_amg_dashboard.json │ │ └── tsconfig.json ├── getrole.sh ├── keycloak-cleanup.sh ├── keycloak-setup.sh ├── patches │ ├── ddb-billing-mode.patch │ └── sql-connection.patch ├── payforadoption-go │ ├── Dockerfile │ ├── benchmark │ │ ├── Dockerfile │ │ ├── README.md │ │ ├── benchmark.sh │ │ └── benchmark.yaml │ ├── config.go │ ├── go.mod │ ├── go.sum │ ├── main.go │ ├── payforadoption │ │ ├── endpoint.go │ │ ├── middlewares.go │ │ ├── repository.go │ │ ├── service.go │ │ ├── transport.go │ │ └── utils.go │ └── seed.json ├── petadoptionshistory-py │ ├── Dockerfile │ ├── config.py │ ├── deployment.yaml │ ├── otel-collector-config.yaml │ ├── petadoptionshistory.py │ ├── repository.py │ └── requirements.txt ├── petlistadoptions-go │ ├── Dockerfile │ ├── benchmark │ │ ├── Dockerfile │ │ ├── README.md │ │ ├── benchmark.sh │ │ └── benchmark.yaml │ ├── config.go │ ├── go.mod │ ├── go.sum │ ├── main.go │ └── petlistadoptions │ │ ├── endpoint.go │ │ ├── middlewares.go │ │ ├── repository.go │ │ ├── service.go │ │ └── transport.go ├── petsearch-java │ ├── .gitignore │ ├── Dockerfile │ ├── build.gradle │ ├── docker-compose.yml │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── manual-instrumentation-complete │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── ca │ │ │ │ │ └── petsearch │ │ │ │ │ ├── Application.java │ │ │ │ │ ├── ApplicationFilter.java │ │ │ │ │ ├── MetricEmitter.java │ │ │ │ │ ├── PseudoRandomNumberGenerator.java │ │ │ │ │ ├── RandomNumberGenerator.java │ │ │ │ │ ├── TracingLogFilter.java │ │ │ │ │ ├── TracingRequestInterceptor.java │ │ │ │ │ ├── WebConfig.java │ │ │ │ │ └── controllers │ │ │ │ │ ├── HealthController.java │ │ │ │ │ ├── Pet.java │ │ │ │ │ └── SearchController.java │ │ │ └── resources │ │ │ │ ├── application.yml │ │ │ │ └── logback-spring.xml │ │ │ └── test │ │ │ ├── java │ │ │ └── ca │ │ │ │ └── petsearch │ │ │ │ ├── PseudoRandomNumberGeneratorTest.java │ │ │ │ └── controllers │ │ │ │ └── SearchControllerIT.java │ │ │ └── resources │ │ │ └── application-test.yml │ ├── settings.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── ca │ │ │ └── petsearch │ │ │ ├── Application.java │ │ │ ├── ApplicationFilter.java │ │ │ ├── MetricEmitter.java │ │ │ ├── PseudoRandomNumberGenerator.java │ │ │ ├── RandomNumberGenerator.java │ │ │ ├── WebConfig.java │ │ │ └── controllers │ │ │ ├── HealthController.java │ │ │ ├── Pet.java │ │ │ └── SearchController.java │ │ └── resources │ │ ├── application.yml │ │ └── logback-spring.xml ├── petsite │ ├── .dockerignore │ ├── .vscode │ │ ├── launch.json │ │ └── tasks.json │ ├── iam-policy.json │ ├── petsite.sln │ └── petsite │ │ ├── Controllers │ │ ├── AdoptionController.cs │ │ ├── HealthController.cs │ │ ├── HomeController.cs │ │ ├── PaymentController.cs │ │ ├── PetFoodController.cs │ │ ├── PetHistoryController.cs │ │ └── PetListAdoptionsController.cs │ │ ├── Dockerfile │ │ ├── Models │ │ └── ErrorViewModel.cs │ │ ├── PetSite.csproj │ │ ├── Program.cs │ │ ├── Properties │ │ └── launchSettings.json │ │ ├── PutParams.cs │ │ ├── SearchParams.cs │ │ ├── Startup.cs │ │ ├── SystemsManagerConfigurationProviderWithReload.cs │ │ ├── ViewModels │ │ └── Pets.cs │ │ ├── Views │ │ ├── Adoption │ │ │ └── Index.cshtml │ │ ├── Home │ │ │ ├── HouseKeeping.cshtml │ │ │ ├── Index.cshtml │ │ │ └── Privacy.cshtml │ │ ├── Payment │ │ │ └── Index.cshtml │ │ ├── PetHistory │ │ │ └── Index.cshtml │ │ ├── PetListAdoptions │ │ │ └── Index.cshtml │ │ ├── Shared │ │ │ ├── Error.cshtml │ │ │ ├── _AdoptionItem.cshtml │ │ │ ├── _Layout.cshtml │ │ │ ├── _PetItem.cshtml │ │ │ └── _ValidationScriptsPartial.cshtml │ │ ├── _ViewImports.cshtml │ │ └── _ViewStart.cshtml │ │ ├── appsettings.Development.json │ │ ├── appsettings.json │ │ ├── bundleconfig.json │ │ ├── compilerconfig.json │ │ ├── compilerconfig.json.defaults │ │ └── wwwroot │ │ ├── css │ │ ├── petstyles.css │ │ ├── site.css │ │ └── site.min.css │ │ ├── favicon.ico │ │ ├── images │ │ ├── arrow-down.png │ │ ├── arrow-right.svg │ │ ├── brand.png │ │ ├── main_banner.png │ │ └── main_banner_text.png │ │ ├── js │ │ ├── site.js │ │ └── site.min.js │ │ └── lib │ │ ├── bootstrap │ │ ├── LICENSE │ │ └── dist │ │ │ ├── css │ │ │ ├── bootstrap-grid.css │ │ │ ├── bootstrap-grid.css.map │ │ │ ├── bootstrap-grid.min.css │ │ │ ├── bootstrap-grid.min.css.map │ │ │ ├── bootstrap-reboot.css │ │ │ ├── bootstrap-reboot.css.map │ │ │ ├── bootstrap-reboot.min.css │ │ │ ├── bootstrap-reboot.min.css.map │ │ │ ├── bootstrap.css │ │ │ ├── bootstrap.css.map │ │ │ ├── bootstrap.min.css │ │ │ └── bootstrap.min.css.map │ │ │ └── js │ │ │ ├── bootstrap.bundle.js │ │ │ ├── bootstrap.bundle.js.map │ │ │ ├── bootstrap.bundle.min.js │ │ │ ├── bootstrap.bundle.min.js.map │ │ │ ├── bootstrap.js │ │ │ ├── bootstrap.js.map │ │ │ ├── bootstrap.min.js │ │ │ └── bootstrap.min.js.map │ │ ├── jquery-validation-unobtrusive │ │ ├── LICENSE.txt │ │ ├── jquery.validate.unobtrusive.js │ │ └── jquery.validate.unobtrusive.min.js │ │ ├── jquery-validation │ │ ├── LICENSE.md │ │ └── dist │ │ │ ├── additional-methods.js │ │ │ ├── additional-methods.min.js │ │ │ ├── jquery.validate.js │ │ │ └── jquery.validate.min.js │ │ └── jquery │ │ ├── LICENSE.txt │ │ └── dist │ │ ├── jquery.js │ │ ├── jquery.min.js │ │ └── jquery.min.map ├── petstatusupdater │ ├── .gitignore │ ├── index.js │ ├── package-lock.json │ └── package.json └── trafficgenerator │ ├── .idea │ ├── .gitignore │ └── .idea.trafficgenerator │ │ ├── .idea │ │ ├── .gitignore │ │ ├── contentModel.xml │ │ ├── encodings.xml │ │ ├── indexLayout.xml │ │ ├── modules.xml │ │ ├── projectSettingsUpdater.xml │ │ └── vcs.xml │ │ └── riderModule.iml │ ├── trafficgenerator.sln │ └── trafficgenerator │ ├── Dockerfile │ ├── PetData.cs │ ├── Program.cs │ ├── Properties │ └── launchSettings.json │ ├── Startup.cs │ ├── Worker.cs │ ├── appsettings.Development.json │ ├── appsettings.json │ ├── docker-compose.yml │ └── trafficgenerator.csproj ├── README.md ├── buildspec.yml ├── codepipeline-stack.yaml ├── gitops ├── git-repository.yaml └── grafana-kustomization.yaml ├── grafana-dashboards ├── cluster.json ├── kubelet.json ├── namespace-workloads.json ├── nodeexporter-nodes.json ├── nodes.json └── workloads.json ├── grafana-operator-manifests ├── amg_grafana-amp-datasource.yaml ├── amg_grafana-cw-datasource.yaml ├── amg_grafana-dashboard.yaml ├── amg_grafana-identity.yaml ├── amg_grafana-xray-datasource.yaml └── kustomization.yaml ├── pack.sh └── setup-cloudshell.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Go binaries 2 | PetAdoptions/payforadoption-go/petadoptions 3 | **/.DS_Store 4 | **/assets 5 | **/.idea 6 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | // Use IntelliSense to find out which attributes exist for C# debugging 6 | // Use hover for the description of the existing attributes 7 | // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md 8 | "name": ".NET Core Launch (web)", 9 | "type": "coreclr", 10 | "request": "launch", 11 | "preLaunchTask": "build", 12 | // If you have changed target frameworks, make sure to update the program path. 13 | "program": "${workspaceFolder}/PetAdoptions/cdk/pet_stack/resources/microservices/petsite/petsite/bin/Debug/net6.0/PetSite.dll", 14 | "args": [], 15 | "cwd": "${workspaceFolder}/PetAdoptions/cdk/pet_stack/resources/microservices/petsite/petsite", 16 | "stopAtEntry": false, 17 | // Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser 18 | "serverReadyAction": { 19 | "action": "openExternally", 20 | "pattern": "\\bNow listening on:\\s+(https?://\\S+)" 21 | }, 22 | "env": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | }, 25 | "sourceFileMap": { 26 | "/Views": "${workspaceFolder}/Views" 27 | } 28 | }, 29 | { 30 | "name": ".NET Core Attach", 31 | "type": "coreclr", 32 | "request": "attach" 33 | } 34 | ] 35 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "build", 6 | "command": "dotnet", 7 | "type": "process", 8 | "args": [ 9 | "build", 10 | "${workspaceFolder}/PetAdoptions/cdk/pet_stack/resources/microservices/petsite/petsite/PetSite.csproj", 11 | "/property:GenerateFullPaths=true", 12 | "/consoleloggerparameters:NoSummary" 13 | ], 14 | "problemMatcher": "$msCompile" 15 | }, 16 | { 17 | "label": "publish", 18 | "command": "dotnet", 19 | "type": "process", 20 | "args": [ 21 | "publish", 22 | "${workspaceFolder}/PetAdoptions/cdk/pet_stack/resources/microservices/petsite/petsite/PetSite.csproj", 23 | "/property:GenerateFullPaths=true", 24 | "/consoleloggerparameters:NoSummary" 25 | ], 26 | "problemMatcher": "$msCompile" 27 | }, 28 | { 29 | "label": "watch", 30 | "command": "dotnet", 31 | "type": "process", 32 | "args": [ 33 | "watch", 34 | "run", 35 | "--project", 36 | "${workspaceFolder}/PetAdoptions/cdk/pet_stack/resources/microservices/petsite/petsite/PetSite.csproj" 37 | ], 38 | "problemMatcher": "$msCompile" 39 | } 40 | ] 41 | } -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 10 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 11 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 12 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | 16 | -------------------------------------------------------------------------------- /PetAdoptions/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to find out which attributes exist for C# debugging 3 | // Use hover for the description of the existing attributes 4 | // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": ".NET Core Launch (web)", 9 | "type": "coreclr", 10 | "request": "launch", 11 | "preLaunchTask": "build", 12 | // If you have changed target frameworks, make sure to update the program path. 13 | "program": "${workspaceFolder}/payforadoption/PayForAdoption/bin/Debug/netcoreapp3.0/PayForAdoption.dll", 14 | "args": [], 15 | "cwd": "${workspaceFolder}/payforadoption/PayForAdoption", 16 | "stopAtEntry": false, 17 | // Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser 18 | "serverReadyAction": { 19 | "action": "openExternally", 20 | "pattern": "^\\s*Now listening on:\\s+(https?://\\S+)" 21 | }, 22 | "env": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | }, 25 | "sourceFileMap": { 26 | "/Views": "${workspaceFolder}/Views" 27 | } 28 | }, 29 | { 30 | "name": ".NET Core Attach", 31 | "type": "coreclr", 32 | "request": "attach", 33 | "processId": "${command:pickProcess}" 34 | } 35 | ] 36 | } -------------------------------------------------------------------------------- /PetAdoptions/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "build", 6 | "command": "dotnet", 7 | "type": "process", 8 | "args": [ 9 | "build", 10 | "${workspaceFolder}/payforadoption/PayForAdoption/PayForAdoption.csproj", 11 | "/property:GenerateFullPaths=true", 12 | "/consoleloggerparameters:NoSummary" 13 | ], 14 | "problemMatcher": "$msCompile" 15 | }, 16 | { 17 | "label": "publish", 18 | "command": "dotnet", 19 | "type": "process", 20 | "args": [ 21 | "publish", 22 | "${workspaceFolder}/payforadoption/PayForAdoption/PayForAdoption.csproj", 23 | "/property:GenerateFullPaths=true", 24 | "/consoleloggerparameters:NoSummary" 25 | ], 26 | "problemMatcher": "$msCompile" 27 | }, 28 | { 29 | "label": "watch", 30 | "command": "dotnet", 31 | "type": "process", 32 | "args": [ 33 | "watch", 34 | "run", 35 | "${workspaceFolder}/payforadoption/PayForAdoption/PayForAdoption.csproj", 36 | "/property:GenerateFullPaths=true", 37 | "/consoleloggerparameters:NoSummary" 38 | ], 39 | "problemMatcher": "$msCompile" 40 | } 41 | ] 42 | } -------------------------------------------------------------------------------- /PetAdoptions/README.md: -------------------------------------------------------------------------------- 1 | Go to https://observability.workshop.aws/ for install instructions. -------------------------------------------------------------------------------- /PetAdoptions/cdk/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/one-observability-demo/396cb484bde89fbe3581338d9eb33e5769f58f4c/PetAdoptions/cdk/.gitkeep -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/.gitignore: -------------------------------------------------------------------------------- 1 | !jest.config.js 2 | *.d.ts 3 | node_modules 4 | 5 | # CDK asset staging directory 6 | .cdk.staging 7 | cdk.out 8 | 9 | # Parcel build directories 10 | .cache 11 | .build 12 | 13 | **/package-lock.json 14 | 15 | cdk.context.json 16 | 17 | # IDE 18 | .idea 19 | 20 | **/.DS_Store 21 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/.npmignore: -------------------------------------------------------------------------------- 1 | *.ts 2 | !*.d.ts 3 | 4 | # CDK asset staging directory 5 | .cdk.staging 6 | cdk.out 7 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "type": "node", 6 | "request": "launch", 7 | "name": "CDK Debugger", 8 | "skipFiles": ["/**"], 9 | "runtimeArgs": [ 10 | "-r", 11 | "./node_modules/ts-node/register/transpile-only" 12 | ], 13 | // Entry point of your stack 14 | "args": ["${workspaceFolder}/app/pet_stack.ts"] 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/README.md: -------------------------------------------------------------------------------- 1 | # Welcome to your CDK TypeScript project! 2 | 3 | This is a blank project for TypeScript development with CDK. 4 | 5 | The `cdk.json` file tells the CDK Toolkit how to execute your app. 6 | 7 | ## Useful commands 8 | 9 | * `npm run build:sql-seeder` build SqlSeeder lambda package 10 | * `npm run build` compile typescript to js 11 | * `npm run watch` watch for changes and compile 12 | * `npm run test` perform the jest unit tests 13 | * `cdk deploy` deploy this stack to your default AWS account/region 14 | * `cdk diff` compare deployed stack with current state 15 | * `cdk synth` emits the synthesized CloudFormation template 16 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/app/pet_stack.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import 'source-map-support/register'; 3 | import { Services } from '../lib/services'; 4 | import { Applications } from '../lib/applications'; 5 | //import { EKSPetsite } from '../lib/ekspetsite' 6 | import { App, Tags, Aspects } from 'aws-cdk-lib'; 7 | //import { AwsSolutionsChecks } from 'cdk-nag'; 8 | 9 | 10 | const stackName = "Services"; 11 | const app = new App(); 12 | 13 | const stack = new Services(app, stackName, { 14 | env: { 15 | account: process.env.CDK_DEFAULT_ACCOUNT, 16 | region: process.env.CDK_DEFAULT_REGION 17 | }}); 18 | 19 | const applications = new Applications(app, "Applications", { 20 | env: { 21 | account: process.env.CDK_DEFAULT_ACCOUNT, 22 | region: process.env.CDK_DEFAULT_REGION 23 | }}); 24 | 25 | Tags.of(app).add("Workshop","true") 26 | //Aspects.of(stack).add(new AwsSolutionsChecks({verbose: true})); 27 | //Aspects.of(applications).add(new AwsSolutionsChecks({verbose: true})); 28 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node app/pet_stack.ts", 3 | "context": { 4 | "vpc_cidr": "11.0.0.0/16", 5 | "snstopic_email": "someone@example.com", 6 | "rdsusername":"petadmin", 7 | "petsite_on_eks":"true" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | roots: ['/test'], 3 | testMatch: ['**/*.test.ts'], 4 | transform: { 5 | '^.+\\.tsx?$': 'ts-jest' 6 | } 7 | }; 8 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/lib/applications/eks-application.ts: -------------------------------------------------------------------------------- 1 | import * as iam from 'aws-cdk-lib/aws-iam'; 2 | import * as eks from 'aws-cdk-lib/aws-eks'; 3 | import { Construct } from 'constructs' 4 | 5 | export interface EksApplicationProps { 6 | cluster: eks.ICluster, 7 | app_trustRelationship: iam.PolicyStatement, 8 | kubernetesManifestPath: string, 9 | region: string, 10 | imageUri: string, 11 | } 12 | 13 | export abstract class EksApplication extends Construct { 14 | constructor(scope: Construct, id: string, props: EksApplicationProps) { 15 | super(scope, id); 16 | } 17 | } -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/lib/common/container-image-builder.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Create a container image from Dockerfile and make it available 3 | * on a dedicated ECR repository (by default, CDK places all of the 4 | * container images in the same "CDK Assets" ECR repository) 5 | * 6 | * Behind the scenes, this is what happens: 7 | * 1. The container image is built locally and pushed into the "CDK Assets" ECR repository 8 | * 2. A dedicated ECR repository is created 9 | * 3. The container image is copied from "CDK Assets" to the dedicated repository 10 | */ 11 | 12 | import * as cdk from 'aws-cdk-lib'; 13 | import * as ecr from 'aws-cdk-lib/aws-ecr'; 14 | import * as ecrassets from 'aws-cdk-lib/aws-ecr-assets'; 15 | import * as ecrdeploy from 'cdk-ecr-deployment'; 16 | 17 | import { Construct } from 'constructs'; 18 | 19 | export interface ContainerImageBuilderProps { 20 | repositoryName: string, 21 | dockerImageAssetDirectory: string 22 | } 23 | 24 | export class ContainerImageBuilder extends Construct { 25 | public repositoryUri: string; 26 | public imageUri: string; 27 | 28 | constructor(scope: Construct, id: string, props: ContainerImageBuilderProps) { 29 | super(scope, id); 30 | 31 | const repository = new ecr.Repository(this, props.repositoryName + 'Repository', { 32 | repositoryName: props.repositoryName, 33 | imageScanOnPush: true, 34 | removalPolicy: cdk.RemovalPolicy.DESTROY, 35 | emptyOnDelete: true, 36 | }); 37 | const image = new ecrassets.DockerImageAsset(this, props.repositoryName + 'DockerImageAsset', { 38 | directory: props.dockerImageAssetDirectory 39 | }); 40 | new ecrdeploy.ECRDeployment(this, props.repositoryName + 'DeployDockerImage', { 41 | src: new ecrdeploy.DockerImageName(image.imageUri), 42 | dest: new ecrdeploy.DockerImageName(repository.repositoryUri), 43 | }); 44 | 45 | this.repositoryUri = repository.repositoryUri; 46 | this.imageUri = `${repository.repositoryUri}:latest`; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/lib/modules/core/cloud9.ts: -------------------------------------------------------------------------------- 1 | import { Construct } from "constructs"; 2 | import * as cloudformation_include from "aws-cdk-lib/cloudformation-include"; 3 | import { CfnRole } from "aws-cdk-lib/aws-iam"; 4 | 5 | export interface Cloud9EnvironmentProps { 6 | name?: string; 7 | vpcId: string; 8 | subnetId: string; 9 | templateFile: string; 10 | cloud9OwnerArn?: string; 11 | } 12 | 13 | export class Cloud9Environment extends Construct { 14 | public readonly c9Role: CfnRole; 15 | constructor(scope: Construct, id: string, props: Cloud9EnvironmentProps) { 16 | super(scope, id); 17 | 18 | const template = new cloudformation_include.CfnInclude(this, 'Cloud9Template', { 19 | templateFile: props.templateFile, 20 | parameters: { 21 | 'CreateVPC': false, 22 | 'Cloud9VPC': props.vpcId, 23 | 'Cloud9Subnet': props.subnetId 24 | }, 25 | preserveLogicalIds: false 26 | }); 27 | 28 | if (props.name) { 29 | template.getParameter("EnvironmentName").default = props.name; 30 | } 31 | 32 | if (props.cloud9OwnerArn) { 33 | template.getParameter("Cloud9OwnerRole").default = props.cloud9OwnerArn.valueOf(); 34 | } 35 | 36 | this.c9Role = template.getResource("C9Role") as CfnRole; 37 | 38 | } 39 | } -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/lib/services/list-adoptions-service.ts: -------------------------------------------------------------------------------- 1 | import * as ecs from 'aws-cdk-lib/aws-ecs'; 2 | import * as rds from 'aws-cdk-lib/aws-rds'; 3 | import { DockerImageAsset } from 'aws-cdk-lib/aws-ecr-assets'; 4 | import { EcsService, EcsServiceProps } from './ecs-service' 5 | import { Construct } from 'constructs' 6 | 7 | 8 | export interface ListAdoptionServiceProps extends EcsServiceProps { 9 | database: rds.DatabaseCluster 10 | } 11 | 12 | export class ListAdoptionsService extends EcsService { 13 | 14 | constructor(scope: Construct, id: string, props: ListAdoptionServiceProps ) { 15 | super(scope, id, props); 16 | 17 | props.database.secret?.grantRead(this.taskDefinition.taskRole); 18 | } 19 | 20 | containerImageFromRepository(repositoryURI: string) : ecs.ContainerImage { 21 | return ecs.ContainerImage.fromRegistry(`${repositoryURI}/pet-listadoptions:latest`) 22 | } 23 | 24 | createContainerImage() : ecs.ContainerImage { 25 | return ecs.ContainerImage.fromDockerImageAsset(new DockerImageAsset(this,"petlistadoptions-go", 26 | { directory: "./resources/microservices/petlistadoptions-go"} 27 | )) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/lib/services/pay-for-adoption-service.ts: -------------------------------------------------------------------------------- 1 | import * as ecs from 'aws-cdk-lib/aws-ecs'; 2 | import * as rds from 'aws-cdk-lib/aws-rds'; 3 | import { DockerImageAsset } from 'aws-cdk-lib/aws-ecr-assets'; 4 | import { EcsService, EcsServiceProps } from './ecs-service' 5 | import { Construct } from 'constructs' 6 | 7 | export interface PayForAdoptionServiceProps extends EcsServiceProps { 8 | database: rds.DatabaseCluster 9 | } 10 | 11 | export class PayForAdoptionService extends EcsService { 12 | 13 | constructor(scope: Construct, id: string, props: PayForAdoptionServiceProps) { 14 | super(scope, id, props); 15 | 16 | props.database.secret?.grantRead(this.taskDefinition.taskRole); 17 | } 18 | 19 | containerImageFromRepository(repositoryURI: string) : ecs.ContainerImage { 20 | return ecs.ContainerImage.fromRegistry(`${repositoryURI}/pet-payforadoption:latest`) 21 | } 22 | 23 | createContainerImage() : ecs.ContainerImage { 24 | return ecs.ContainerImage.fromDockerImageAsset(new DockerImageAsset(this,"pay-for-adoption", { 25 | directory: "./resources/microservices/payforadoption-go" 26 | })) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/lib/services/search-service.ts: -------------------------------------------------------------------------------- 1 | import * as ecs from 'aws-cdk-lib/aws-ecs'; 2 | import * as iam from 'aws-cdk-lib/aws-iam'; 3 | import { DockerImageAsset } from 'aws-cdk-lib/aws-ecr-assets'; 4 | import { EcsService, EcsServiceProps } from './ecs-service' 5 | import { Construct } from 'constructs' 6 | 7 | export class SearchService extends EcsService { 8 | 9 | constructor(scope: Construct, id: string, props: EcsServiceProps ) { 10 | super(scope, id, props); 11 | 12 | this.taskDefinition.taskRole?.addManagedPolicy(iam.ManagedPolicy.fromManagedPolicyArn(this, 'AmazonDynamoDBReadOnlyAccess', 'arn:aws:iam::aws:policy/AmazonDynamoDBReadOnlyAccess')); 13 | this.taskDefinition.taskRole?.addManagedPolicy(iam.ManagedPolicy.fromManagedPolicyArn(this, 'AmazonS3ReadOnlyAccess', 'arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess')); 14 | } 15 | 16 | containerImageFromRepository(repositoryURI: string) : ecs.ContainerImage { 17 | return ecs.ContainerImage.fromRegistry(`${repositoryURI}/pet-search-java:latest`) 18 | } 19 | 20 | createContainerImage() : ecs.ContainerImage { 21 | return ecs.ContainerImage.fromDockerImageAsset(new DockerImageAsset(this,"search-service", { 22 | directory: "./resources/microservices/petsearch-java" 23 | })) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/lib/services/traffic-generator-service.ts: -------------------------------------------------------------------------------- 1 | import * as ecs from 'aws-cdk-lib/aws-ecs'; 2 | import { DockerImageAsset } from 'aws-cdk-lib/aws-ecr-assets'; 3 | import { EcsService, EcsServiceProps } from './ecs-service' 4 | import { Construct } from 'constructs' 5 | 6 | export class TrafficGeneratorService extends EcsService { 7 | 8 | constructor(scope: Construct, id: string, props: EcsServiceProps ) { 9 | super(scope, id, props); 10 | } 11 | 12 | containerImageFromRepository(repositoryURI: string) : ecs.ContainerImage { 13 | return ecs.ContainerImage.fromRegistry(`${repositoryURI}/pet-trafficgenerator:latest`) 14 | } 15 | 16 | createContainerImage() : ecs.ContainerImage { 17 | return ecs.ContainerImage.fromDockerImageAsset(new DockerImageAsset(this, "traffic-generator", { 18 | directory: "./resources/microservices/trafficgenerator/trafficgenerator" 19 | })) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pet_stack", 3 | "version": "0.2.0", 4 | "bin": { 5 | "pet_stack": "bin/pet_stack.js" 6 | }, 7 | "scripts": { 8 | "build:status-updater": "(cd ../../petstatusupdater && npm i)", 9 | "build": "tsc", 10 | "watch": "tsc -w", 11 | "test": "jest", 12 | "cdk": "cdk" 13 | }, 14 | "dependencies": { 15 | "@aws-cdk/aws-lambda-python-alpha": "^2.179.0-alpha.0", 16 | "@aws-cdk/lambda-layer-kubectl-v31": "^2.0.3", 17 | "@types/js-yaml": "^4.0.9", 18 | "aws-cdk-lib": "^2.179.0", 19 | "cdk-ecr-deployment": "^3.1.9", 20 | "jest": "^29.7.0", 21 | "js-yaml": "^4.1.0", 22 | "source-map-support": "^0.5.21" 23 | }, 24 | "devDependencies": { 25 | "@types/jest": "^29.5.14", 26 | "@types/node": "^22.13.4", 27 | "aws-cdk": "^2.1000.2", 28 | "cdk-nag": "^2.35.24", 29 | "constructs": "^10.4.2", 30 | "ts-jest": "^29.2.5", 31 | "ts-node": "^10.9.2", 32 | "ts-replace-all": "^1.0.0", 33 | "typescript": "^5.7.3" 34 | } 35 | } -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/amp_ingest_override_values.yaml: -------------------------------------------------------------------------------- 1 | ## The following is a set of default values for prometheus server helm chart which enable remoteWrite to AMP 2 | ## For the rest of prometheus helm chart values see: https://github.com/prometheus-community/helm-charts/blob/main/charts/prometheus/values.yaml 3 | ## 4 | serviceAccounts: 5 | ## Disable alert manager roles 6 | ## 7 | server: 8 | name: "amp-iamproxy-ingest-role" 9 | create: false 10 | 11 | alertmanager: 12 | create: false 13 | 14 | ## Disable pushgateway 15 | ## 16 | pushgateway: 17 | create: false 18 | 19 | server: 20 | remoteWrite: 21 | - 22 | queue_config: 23 | max_samples_per_send: 1000 24 | max_shards: 200 25 | capacity: 2500 26 | 27 | ## Use a statefulset instead of a deployment for resiliency 28 | ## 29 | statefulSet: 30 | enabled: true 31 | 32 | ## Store blocks locally for short time period only 33 | ## 34 | retention: 1h 35 | 36 | ## Disable alert manager 37 | ## 38 | alertmanager: 39 | enabled: false 40 | 41 | ## Disable pushgateway 42 | ## 43 | prometheus-pushgateway: 44 | enabled: false -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/application-insights/dynamodb-query-function.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | import boto3 4 | from boto3.dynamodb.conditions import Key 5 | 6 | dynamodb = boto3.resource('dynamodb') 7 | DYNAMODB_TABLE_NAME = os.environ['DYNAMODB_TABLE_NAME'] 8 | 9 | def lambda_handler(event, context): 10 | table = dynamodb.Table(DYNAMODB_TABLE_NAME) 11 | error_mode = event.get('error_mode') 12 | if error_mode == 'true': 13 | query_key = 'wrongKey' 14 | else: 15 | query_key = 'pettype' 16 | t_end = time.time() + 60 * 13 17 | while time.time() < t_end: 18 | try: 19 | response = table.query( 20 | KeyConditionExpression=Key(query_key).eq('puppy') 21 | ) 22 | items = response['Items'] 23 | except Exception as e: 24 | print("An exception occurred, but still continuing. The error is: ",e) 25 | items = "FunctionError" 26 | time.sleep(30) 27 | return { 28 | 'statusCode': 200, 29 | 'body': items 30 | } -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/bunnies.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/one-observability-demo/396cb484bde89fbe3581338d9eb33e5769f58f4c/PetAdoptions/cdk/pet_stack/resources/bunnies.zip -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/collector/ecs-xray-manual.yaml: -------------------------------------------------------------------------------- 1 | extensions: 2 | health_check: 3 | 4 | receivers: 5 | otlp: 6 | protocols: 7 | grpc: 8 | endpoint: 0.0.0.0:4317 9 | http: 10 | endpoint: 0.0.0.0:4318 11 | 12 | processors: 13 | batch/traces: 14 | timeout: 1s 15 | send_batch_size: 50 16 | 17 | exporters: 18 | awsxray: 19 | 20 | service: 21 | pipelines: 22 | traces: 23 | receivers: [otlp] 24 | processors: [batch/traces] 25 | exporters: [awsxray] 26 | 27 | extensions: [health_check] 28 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/cw_dashboard_cost_control.json: -------------------------------------------------------------------------------- 1 | { 2 | "widgets": [ 3 | { 4 | "height": 3, 5 | "width": 18, 6 | "y": 0, 7 | "x": 0, 8 | "type": "custom", 9 | "properties": { 10 | "endpoint": "{{YOUR_LAMBDA_ARN}}", 11 | "updateOn": { 12 | "refresh": true, 13 | "resize": true, 14 | "timeRange": true 15 | }, 16 | "title": "Petsite Resource Controller" 17 | } 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/dashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "apiVersion": "v1", 3 | "kind": "List", 4 | "items": [ 5 | { 6 | "apiVersion": "rbac.authorization.k8s.io/v1", 7 | "kind": "ClusterRole", 8 | "metadata": { 9 | "name": "dashboard-viewer" 10 | }, 11 | "rules": [ 12 | { 13 | "apiGroups": [ 14 | "" 15 | ], 16 | "resources": [ 17 | "nodes", 18 | "namespaces", 19 | "pods" 20 | ], 21 | "verbs": [ 22 | "get", 23 | "list" 24 | ] 25 | }, 26 | { 27 | "apiGroups": [ 28 | "apps" 29 | ], 30 | "resources": [ 31 | "deployments", 32 | "pods", 33 | "daemonsets", 34 | "statefulsets", 35 | "replicasets" 36 | ], 37 | "verbs": [ 38 | "get", 39 | "list" 40 | ] 41 | }, 42 | { 43 | "apiGroups": [ 44 | "batch" 45 | ], 46 | "resources": [ 47 | "jobs" 48 | ], 49 | "verbs": [ 50 | "get", 51 | "list" 52 | ] 53 | } 54 | ] 55 | }, 56 | { 57 | "apiVersion": "rbac.authorization.k8s.io/v1", 58 | "kind": "ClusterRoleBinding", 59 | "metadata": { 60 | "name": "dashboard-viewer" 61 | }, 62 | "roleRef": { 63 | "apiGroup": "rbac.authorization.k8s.io", 64 | "kind": "ClusterRole", 65 | "name": "dashboard-viewer" 66 | }, 67 | "subjects": [ 68 | { 69 | "apiGroup": "rbac.authorization.k8s.io", 70 | "kind": "Group", 71 | "name": "dashboard-view" 72 | } 73 | ] 74 | } 75 | ] 76 | } -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/dashboard.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: dashboard-viewer 6 | rules: 7 | - apiGroups: 8 | - '' 9 | resources: 10 | - nodes 11 | - namespaces 12 | - pods 13 | verbs: 14 | - get 15 | - list 16 | - apiGroups: 17 | - apps 18 | resources: 19 | - deployments 20 | - pods 21 | - daemonsets 22 | - statefulsets 23 | - replicasets 24 | verbs: 25 | - get 26 | - list 27 | - apiGroups: 28 | - batch 29 | resources: 30 | - jobs 31 | verbs: 32 | - get 33 | - list 34 | --- 35 | apiVersion: rbac.authorization.k8s.io/v1 36 | kind: ClusterRoleBinding 37 | metadata: 38 | name: dashboard-viewer 39 | roleRef: 40 | apiGroup: rbac.authorization.k8s.io 41 | kind: ClusterRole 42 | name: dashboard-viewer 43 | subjects: 44 | - apiGroup: rbac.authorization.k8s.io 45 | kind: Group 46 | name: dashboard-view 47 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/delete-seed-data.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "petid": "01" 4 | }, 5 | { 6 | "petid": "02" 7 | }, 8 | { 9 | "petid": "03" 10 | }, 11 | { 12 | "petid": "04" 13 | }, 14 | { 15 | "petid": "05" 16 | }, 17 | { 18 | "petid": "06" 19 | }, 20 | { 21 | "petid": "07" 22 | }, 23 | { 24 | "petid": "08" 25 | }, 26 | { 27 | "petid": "09" 28 | }, 29 | { 30 | "petid": "10" 31 | }, 32 | { 33 | "petid": "11" 34 | }, 35 | { 36 | "petid": "12" 37 | }, 38 | { 39 | "petid": "13" 40 | }, 41 | { 42 | "petid": "14" 43 | }, 44 | { 45 | "petid": "15" 46 | }, 47 | { 48 | "petid": "16" 49 | }, 50 | { 51 | "petid": "17" 52 | }, 53 | { 54 | "petid": "18" 55 | }, 56 | { 57 | "petid": "19" 58 | }, 59 | { 60 | "petid": "20" 61 | }, 62 | { 63 | "petid": "21" 64 | }, 65 | { 66 | "petid": "22" 67 | }, 68 | { 69 | "petid": "23" 70 | }, 71 | { 72 | "petid": "24" 73 | }, 74 | { 75 | "petid": "25" 76 | }, 77 | { 78 | "petid": "26" 79 | } 80 | ] -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/destroy_stack.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo --------------------------------------------------------------------------------------------- 4 | echo This script destroys the resources created in the workshop 5 | echo --------------------------------------------------------------------------------------------- 6 | 7 | if [ -z "$AWS_REGION" ]; then 8 | echo "Fatal: environment variable AWS_REGION not set. Aborting." 9 | exit 1 10 | fi 11 | 12 | # Disable Contributor Insights 13 | DDB_CONTRIB=$(aws ssm get-parameter --name '/petstore/dynamodbtablename' | jq .Parameter.Value -r) 14 | aws dynamodb update-contributor-insights --table-name $DDB_CONTRIB --contributor-insights-action DISABLE 15 | 16 | # Delete Network Flow Monitor 17 | if aws networkflowmonitor get-monitor --monitor-name network-flow-monitor-demo >/dev/null 2>&1; then 18 | echo "Deleting network flow monitor..." 19 | aws networkflowmonitor delete-monitor --monitor-name network-flow-monitor-demo 20 | else 21 | echo "Network flow monitor not found, skipping delete." 22 | fi 23 | 24 | echo STARTING SERVICES CLEANUP 25 | echo ----------------------------- 26 | 27 | # Get the main stack name 28 | STACK_NAME=$(aws ssm get-parameter --name '/petstore/stackname' --region $AWS_REGION | jq .Parameter.Value -r) 29 | STACK_NAME_APP=$(aws ssm get-parameter --name '/eks/petsite/stackname' --region $AWS_REGION | jq .Parameter.Value -r) 30 | 31 | # Set default name in case Parameters are gone (partial deletion) 32 | if [ -z $STACK_NAME ]; then STACK_NAME="Services"; fi 33 | if [ -z $STACK_NAME_APP ]; then STACK_NAME_APP="Applications"; fi 34 | if [ -z $STACK_NAME_CODEPIPELINE ]; then STACK_NAME_CODEPIPELINE="Observability-Workshop"; fi 35 | 36 | # Fix for CDK teardown issues 37 | aws eks update-kubeconfig --name PetSite 38 | kubectl delete -f https://raw.githubusercontent.com/aws-samples/one-observability-demo/main/PetAdoptions/cdk/pet_stack/resources/load_balancer/crds.yaml 39 | 40 | #Deleting keycloak 41 | kubectl delete namespace keycloak --force 42 | 43 | # Sometimes the SqlSeeder doesn't get deleted cleanly. This helps clean up the environment completely including Sqlseeder 44 | aws cloudformation delete-stack --stack-name $STACK_NAME_APP 45 | aws cloudformation wait stack-delete-complete --stack-name $STACK_NAME_APP 46 | aws cloudformation delete-stack --stack-name $STACK_NAME 47 | aws cloudformation wait stack-delete-complete --stack-name $STACK_NAME 48 | 49 | aws cloudwatch delete-dashboards --dashboard-names "EKS_FluentBit_Dashboard" 50 | 51 | # delete the code pipeline stack 52 | aws cloudformation delete-stack --stack-name $STACK_NAME_CODEPIPELINE 53 | aws cloudformation wait stack-delete-complete --stack-name $STACK_NAME_CODEPIPELINE 54 | 55 | echo CDK BOOTSTRAP WAS NOT DELETED 56 | 57 | echo ----- ✅ DONE -------- -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/README.md: -------------------------------------------------------------------------------- 1 | # AWS re:Invent 2022 COP301 demo 2 | 3 | This contains the sources artifacts to deploy the COP301 session. 4 | 5 | ### Architecture diagram 6 | 7 | image 8 | 9 | ### Deployment 10 | 11 | #### AWS Lambda API 12 | 13 | Make sure to have [AWS SAM CLI](https://aws.amazon.com/serverless/sam/) installed to run these commands. 14 | 15 | ``` 16 | cd lambda-api 17 | npm install 18 | sam sync --stack-name cop301-data 19 | ``` 20 | 21 | #### Amazon ECS API 22 | 23 | Visit [the documentation](./ecs-api/README.md) to deploy the Amazon ECS backend API. 24 | 25 | #### Webapp (with AWS Amplify) 26 | 27 | Screenshot 2022-11-27 at 11 31 31 28 | 29 | Visit [the documentation](./amplifyapp/README.md) to deploy the web app with AWS Amplify. 30 | 31 | ### Visualization with Amazon Managed Grafana 32 | 33 | Visit the [getting started page](https://docs.aws.amazon.com/grafana/latest/userguide/getting-started-with-AMG.html) to create an Amazon Managed Grafana workspace and create your dashboard. 34 | 35 | image 36 | 37 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | #amplify-do-not-edit-begin 26 | amplify/\#current-cloud-backend 27 | amplify/.config/local-* 28 | amplify/logs 29 | amplify/mock-data 30 | amplify/backend/amplify-meta.json 31 | amplify/backend/.temp 32 | build/ 33 | dist/ 34 | node_modules/ 35 | aws-exports.js 36 | awsconfiguration.json 37 | amplifyconfiguration.json 38 | amplifyconfiguration.dart 39 | amplify-build-config.json 40 | amplify-gradle-config.json 41 | amplifytools.xcconfig 42 | .secret-* 43 | **.sample 44 | #amplify-do-not-edit-end 45 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/README.md: -------------------------------------------------------------------------------- 1 | # Web application with AWS Amplify 2 | 3 | This project was bootstrapped with AWS Amplify. 4 | 5 | ## Pre-requisites 6 | 7 | 1. Install [AWS Amplify CLI](https://docs.amplify.aws/cli/start/install/) 8 | 2. Edit `amplifyapp/src/index.js` and replace `endpoint: $ECS_API_URL` with the Amazon ECS deployment URL 9 | 10 | ## Run locally 11 | 12 | In the project directory, you can run: 13 | 14 | ```console 15 | npm install 16 | npm start 17 | ``` 18 | 19 | Runs the app in the development mode.\ 20 | Open [http://localhost:3000](http://localhost:3000) to view it in your browser. 21 | 22 | The page will reload when you make changes.\ 23 | You may also see any lint errors in the console. 24 | 25 | 26 | ## Deployment 27 | 28 | Install [AWS Amplify CLI](https://docs.amplify.aws/cli/start/install/) 29 | 30 | ```console 31 | npm install 32 | amplify publish 33 | ``` 34 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/amplify/.config/project-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "cop301", 3 | "version": "3.1", 4 | "frontend": "javascript", 5 | "javascript": { 6 | "framework": "react", 7 | "config": { 8 | "SourceDir": "src", 9 | "DistributionDir": "build", 10 | "BuildCommand": "npm run-script build", 11 | "StartCommand": "npm run-script start" 12 | } 13 | }, 14 | "providers": [ 15 | "awscloudformation" 16 | ] 17 | } -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/amplify/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Amplify CLI 2 | This directory was generated by [Amplify CLI](https://docs.amplify.aws/cli). 3 | 4 | Helpful resources: 5 | - Amplify documentation: https://docs.amplify.aws 6 | - Amplify CLI documentation: https://docs.amplify.aws/cli 7 | - More details on this folder & generated files: https://docs.amplify.aws/cli/reference/files 8 | - Join Amplify's community: https://amplify.aws/community/ 9 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/amplify/backend/backend-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "amplifyhosting": { 4 | "service": "amplifyhosting", 5 | "providerPlugin": "awscloudformation", 6 | "type": "manual" 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/amplify/backend/hosting/amplifyhosting/amplifyhosting-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "AWSTemplateFormatVersion": "2010-09-09", 3 | "Description": "{\"createdOn\":\"Mac\",\"createdBy\":\"Amplify\",\"createdWith\":\"10.4.0\",\"stackType\":\"hosting-amplifyhosting\",\"metadata\":{}}", 4 | "Parameters": { 5 | "env": { 6 | "Type": "String" 7 | }, 8 | "appId": { 9 | "Type": "String" 10 | }, 11 | "type": { 12 | "Type": "String" 13 | } 14 | }, 15 | "Conditions": { 16 | "isManual": { 17 | "Fn::Equals": [ 18 | { 19 | "Ref": "type" 20 | }, 21 | "manual" 22 | ] 23 | } 24 | }, 25 | "Resources": { 26 | "AmplifyBranch": { 27 | "Condition": "isManual", 28 | "Type": "AWS::Amplify::Branch", 29 | "Properties": { 30 | "BranchName": { 31 | "Ref": "env" 32 | }, 33 | "AppId": { 34 | "Ref": "appId" 35 | } 36 | } 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/amplify/backend/tags.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Key": "user:Stack", 4 | "Value": "{project-env}" 5 | }, 6 | { 7 | "Key": "user:Application", 8 | "Value": "{project-name}" 9 | } 10 | ] -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/amplify/cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "features": { 3 | "graphqltransformer": { 4 | "addmissingownerfields": true, 5 | "improvepluralization": false, 6 | "validatetypenamereservedwords": true, 7 | "useexperimentalpipelinedtransformer": true, 8 | "enableiterativegsiupdates": true, 9 | "secondarykeyasgsi": true, 10 | "skipoverridemutationinputtypes": true, 11 | "transformerversion": 2, 12 | "suppressschemamigrationprompt": true, 13 | "securityenhancementnotification": false, 14 | "showfieldauthnotification": false, 15 | "usesubusernamefordefaultidentityclaim": true, 16 | "usefieldnameforprimarykeyconnectionfield": false, 17 | "enableautoindexquerynames": false, 18 | "respectprimarykeyattributesonconnectionfield": false, 19 | "shoulddeepmergedirectiveconfigdefaults": false, 20 | "populateownerfieldforstaticgroupauth": false 21 | }, 22 | "frontend-ios": { 23 | "enablexcodeintegration": true 24 | }, 25 | "auth": { 26 | "enablecaseinsensitivity": true, 27 | "useinclusiveterminology": true, 28 | "breakcirculardependency": true, 29 | "forcealiasattributes": false, 30 | "useenabledmfas": true 31 | }, 32 | "codegen": { 33 | "useappsyncmodelgenplugin": true, 34 | "usedocsgeneratorplugin": true, 35 | "usetypesgeneratorplugin": true, 36 | "cleangeneratedmodelsdirectory": true, 37 | "retaincasestyle": true, 38 | "addtimestampfields": true, 39 | "handlelistnullabilitytransparently": true, 40 | "emitauthprovider": true, 41 | "generateindexrules": true, 42 | "enabledartnullsafety": true 43 | }, 44 | "appsync": { 45 | "generategraphqlpermissions": true 46 | }, 47 | "latestregionsupport": { 48 | "pinpoint": 1, 49 | "translate": 1, 50 | "transcribe": 1, 51 | "rekognition": 1, 52 | "textract": 1, 53 | "comprehend": 1 54 | }, 55 | "project": { 56 | "overrides": true 57 | } 58 | }, 59 | "debug": { 60 | "shareProjectConfig": true 61 | } 62 | } -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/amplify/hooks/README.md: -------------------------------------------------------------------------------- 1 | # Command Hooks 2 | 3 | Command hooks can be used to run custom scripts upon Amplify CLI lifecycle events like pre-push, post-add-function, etc. 4 | 5 | To get started, add your script files based on the expected naming convention in this directory. 6 | 7 | Learn more about the script file naming convention, hook parameters, third party dependencies, and advanced configurations at https://docs.amplify.aws/cli/usage/command-hooks 8 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/amplify/team-provider-info.json: -------------------------------------------------------------------------------- 1 | { 2 | "dev": { 3 | "awscloudformation": { 4 | "AuthRoleName": "amplify-cop301-dev-232621-authRole", 5 | "UnauthRoleArn": "arn:aws:iam::339743103717:role/amplify-cop301-dev-232621-unauthRole", 6 | "AuthRoleArn": "arn:aws:iam::339743103717:role/amplify-cop301-dev-232621-authRole", 7 | "Region": "us-west-2", 8 | "DeploymentBucketName": "amplify-cop301-dev-232621-deployment", 9 | "UnauthRoleName": "amplify-cop301-dev-232621-unauthRole", 10 | "StackName": "amplify-cop301-dev-232621", 11 | "StackId": "arn:aws:cloudformation:us-west-2:339743103717:stack/amplify-cop301-dev-232621/19498120-5e22-11ed-8d38-021c0ddc0de5", 12 | "AmplifyAppId": "d24q83cq1bplkg" 13 | }, 14 | "categories": { 15 | "hosting": { 16 | "amplifyhosting": { 17 | "appId": "d24q83cq1bplkg", 18 | "type": "manual" 19 | } 20 | } 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cop301", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@emotion/react": "^11.10.5", 7 | "@emotion/styled": "^11.10.5", 8 | "@mui/material": "^5.10.12", 9 | "@testing-library/jest-dom": "^5.16.5", 10 | "@testing-library/react": "^13.4.0", 11 | "@testing-library/user-event": "^13.5.0", 12 | "aws-amplify": "^4.3.43", 13 | "history": "^5.3.0", 14 | "react": "^18.2.0", 15 | "react-bootstrap": "^2.5.0", 16 | "react-dom": "^18.2.0", 17 | "react-router-dom": "^6.4.3", 18 | "react-scripts": "5.0.1", 19 | "react-spinners": "^0.13.6", 20 | "web-vitals": "^2.1.4" 21 | }, 22 | "scripts": { 23 | "start": "react-scripts start", 24 | "build": "react-scripts build", 25 | "test": "react-scripts test", 26 | "eject": "react-scripts eject" 27 | }, 28 | "eslintConfig": { 29 | "extends": [ 30 | "react-app", 31 | "react-app/jest" 32 | ] 33 | }, 34 | "browserslist": { 35 | "production": [ 36 | ">0.2%", 37 | "not dead", 38 | "not op_mini all" 39 | ], 40 | "development": [ 41 | "last 1 chrome version", 42 | "last 1 firefox version", 43 | "last 1 safari version" 44 | ] 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/one-observability-demo/396cb484bde89fbe3581338d9eb33e5769f58f4c/PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/public/favicon.ico -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | AWS re:Invent COP301 17 | 18 | 19 | 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/one-observability-demo/396cb484bde89fbe3581338d9eb33e5769f58f4c/PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/public/logo192.png -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/one-observability-demo/396cb484bde89fbe3581338d9eb33e5769f58f4c/PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/public/logo512.png -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Veggy", 3 | "name": "React Shopping Cart", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#077915", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { useState, createContext } from "react"; 2 | import Container from '@mui/material/Container'; 3 | import Typography from '@mui/material/Typography'; 4 | import Box from '@mui/material/Box'; 5 | import theme from './utils/theme'; 6 | import { ThemeProvider } from '@mui/material/styles'; 7 | import CssBaseline from '@mui/material/CssBaseline'; 8 | import Colors from "./views/Colors"; 9 | import Choice from "./views/Choice"; 10 | 11 | export const VoteStatusContext = createContext(); 12 | 13 | export default function App() { 14 | 15 | const [voted, setVoted] = useState(false); 16 | const [color, setColor] = useState(undefined); 17 | const [colorCode, setColorCode] = useState(undefined); 18 | 19 | return ( 20 | 21 | 22 | 23 | 24 | 25 | 26 | re:Invent COP301 - Observability the Open Source Way 27 | 28 | {!voted && 29 | 30 | } 31 | {voted && 32 | < Choice /> 33 | } 34 | 35 | 36 | 37 | 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/src/components/ColorCard.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useContext } from "react"; 2 | import Card from '@mui/material/Card'; 3 | import CardActions from '@mui/material/CardActions'; 4 | import CardContent from '@mui/material/CardContent'; 5 | import CardActionArea from '@mui/material/CardActionArea'; 6 | import Button from '@mui/material/Button'; 7 | import Typography from '@mui/material/Typography'; 8 | import { vote } from "../utils/api"; 9 | import { VoteStatusContext } from "../App"; 10 | import { SyncLoader } from "react-spinners"; 11 | 12 | const ColorCard = ({ colorName, colorCode }) => { 13 | 14 | const { setVoted, setColor, setColorCode } = useContext(VoteStatusContext) 15 | const [loading, setLoading] = useState(false); 16 | 17 | const styles = { 18 | minWidth: 27, 19 | background: colorCode, 20 | }; 21 | 22 | const handleUpdateVote = async () => { 23 | setLoading(true) 24 | const response = await vote( 25 | colorName 26 | ); 27 | setVoted(true) 28 | setColor(colorName) 29 | setColorCode(colorCode) 30 | console.log(response); 31 | setLoading(false) 32 | }; 33 | 34 | 35 | return ( 36 | 37 | 38 | 39 | 40 | {colorName} 41 | 42 | 47 | 48 | 49 | 50 | ); 51 | } 52 | 53 | export default ColorCard; -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/src/components/ProTip.js: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import SvgIcon from '@mui/material/SvgIcon'; 3 | import Typography from '@mui/material/Typography'; 4 | 5 | function LightBulbIcon(props) { 6 | return ( 7 | 8 | 9 | 10 | ); 11 | } 12 | 13 | export default function ProTip() { 14 | return ( 15 | 16 | 17 | Click on your favorite color to vote! 18 | 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/src/index.js: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { createRoot } from 'react-dom/client'; 3 | import App from './App'; 4 | import { Amplify, API } from 'aws-amplify'; 5 | import awsExports from './aws-exports'; 6 | import { 7 | BrowserRouter as Router, 8 | } from "react-router-dom"; 9 | 10 | Amplify.configure(awsExports); 11 | 12 | const rootElement = document.getElementById('root'); 13 | const root = createRoot(rootElement); 14 | 15 | Amplify.configure({ 16 | API: { 17 | endpoints: [ 18 | { 19 | name: "voteapi", 20 | endpoint: $ECS_API_URL 21 | } 22 | ] 23 | }, 24 | ...awsExports 25 | }) 26 | API.configure(); 27 | 28 | root.render( 29 | 30 | 31 | 32 | ); 33 | 34 | 35 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/src/utils/api.js: -------------------------------------------------------------------------------- 1 | import { Amplify } from "aws-amplify"; 2 | 3 | const apiName = "voteapi"; 4 | 5 | export async function vote( 6 | colorName, 7 | ) { 8 | const path = `/votes`; 9 | const reqBody = { 10 | body: { 11 | color: colorName, 12 | }, 13 | }; 14 | return await Amplify.API.post(apiName, path, reqBody); 15 | // await new Promise(r => setTimeout(r, 1000)); 16 | } -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/src/utils/colors.js: -------------------------------------------------------------------------------- 1 | const colors = [ 2 | { code: "#dc3220", size: 8, name: "red orange" }, 3 | { code: "#d41159", size: 4, name: "pink" }, 4 | { code: "#d35fb7", size: 4, name: "purple" }, 5 | { code: "#5d3a9b", size: 8, name: "deep purple" }, 6 | { code: "#005ab5", size: 8, name: "indigo" }, 7 | { code: "#1a85ff", size: 4, name: "blue" }, 8 | { code: "#00bcd4", size: 4, name: "cyan" }, 9 | { code: "#40b0a6", size: 8, name: "teal" }, 10 | { code: "#994f00", size: 8, name: "brown" }, 11 | { code: "#e66100", size: 4, name: "orange" }, 12 | { code: "#000000", size: 12, name: "black" }, 13 | ] 14 | 15 | export default colors; -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/src/utils/theme.js: -------------------------------------------------------------------------------- 1 | import { red } from '@mui/material/colors'; 2 | import { createTheme } from '@mui/material/styles'; 3 | 4 | // A custom theme for this app 5 | const theme = createTheme({ 6 | palette: { 7 | primary: { 8 | main: '#556cd6', 9 | }, 10 | secondary: { 11 | main: '#19857b', 12 | }, 13 | error: { 14 | main: red.A400, 15 | }, 16 | }, 17 | }); 18 | 19 | export default theme; 20 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/src/views/Choice.js: -------------------------------------------------------------------------------- 1 | import React, { useContext } from "react"; 2 | import Typography from '@mui/material/Typography'; 3 | import Grid from '@mui/material/Grid'; 4 | import Card from '@mui/material/Card'; 5 | import CardContent from '@mui/material/CardContent'; 6 | import { VoteStatusContext } from "../App"; 7 | import { PacmanLoader } from "react-spinners"; 8 | 9 | 10 | export default function Choice() { 11 | 12 | const { color, colorCode } = useContext(VoteStatusContext) 13 | const styles = { 14 | minWidth: 27, 15 | background: colorCode, 16 | minHeight: 500 17 | }; 18 | 19 | return ( 20 | 21 | 22 | 23 | 24 | 25 | Thank you for voting {color}! 26 | 27 | 31 | 32 | 33 | 34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/amplifyapp/src/views/Colors.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ProTip from '../components/ProTip'; 3 | import ColorCard from '../components/ColorCard'; 4 | import Grid from '@mui/material/Grid'; 5 | import colors from "../utils/colors"; 6 | 7 | export default function Colors() { 8 | return ( 9 | <> 10 | 11 | 12 | {colors.map((c, i) => ( 13 | 14 | 15 | 16 | ))} 17 | 18 | 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/ecs-api/.gitignore: -------------------------------------------------------------------------------- 1 | api 2 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/ecs-api/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.18 as builder 2 | ENV GOPROXY=https://goproxy.io,direct 3 | WORKDIR /go/src/app 4 | COPY . . 5 | RUN go get . 6 | RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . 7 | 8 | FROM alpine:latest 9 | WORKDIR /app 10 | RUN apk --no-cache add ca-certificates 11 | COPY --from=builder /go/src/app/app . 12 | EXPOSE 8000 13 | CMD ["./app"] 14 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/ecs-api/README.md: -------------------------------------------------------------------------------- 1 | # COP301 Backend API on Amazon ECS 2 | 3 | ```console 4 | ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) 5 | ``` 6 | 7 | ## Create ECR repository 8 | 9 | Skip this step if you already have a repository 10 | 11 | ```console 12 | ECR_REPOSITORY_URI=$(aws ecr create-repository --repository cop301-api --query repository.repositoryUri --output text) 13 | ``` 14 | 15 | ```console 16 | ECR_REPOSITORY_URI=$(aws ecr describe-repositories --repository-names cop301-api --query 'repositories[0].repositoryUri' --output text) 17 | ``` 18 | 19 | 20 | ## Build image 21 | 22 | ```console 23 | docker buildx build . -t cop301-api --platform=linux/amd64 24 | aws ecr get-login-password | docker login --username AWS --password-stdin $ECR_REPOSITORY_URI 25 | docker tag cop301-api:latest $ECR_REPOSITORY_URI 26 | docker push $ECR_REPOSITORY_URI 27 | ``` 28 | 29 | ## Deploy application (on Amazon ECS) 30 | 31 | ```console 32 | copilot svc init --name cop301-api 33 | copilot svc deploy --name cop301-api --env test 34 | ``` 35 | 36 | ## Benchmark (optional) 37 | 38 | Drill is a HTTP load testing application written in Rust. Follow this link [to install](https://github.com/fcsonline/drill#install). 39 | If you have [Cargo](https://github.com/fcsonline/drill#install), run: 40 | 41 | ```console 42 | cargo install drill 43 | ``` 44 | 45 | Running the benchmark scenario 46 | 47 | ```console 48 | drill -s --benchmark utils/benchmark.yaml 49 | ``` 50 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/ecs-api/copilot/.workspace: -------------------------------------------------------------------------------- 1 | application: cop301-api 2 | path: "" 3 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/ecs-api/copilot/cop301-api/addons/observability.yaml: -------------------------------------------------------------------------------- 1 | Parameters: 2 | App: 3 | Type: String 4 | Description: Your application's name. 5 | Env: 6 | Type: String 7 | Description: The environment name your service, job, or workflow is being deployed to. 8 | Name: 9 | Type: String 10 | Description: The name of the service, job, or workflow being deployed. 11 | 12 | Resources: 13 | SSM: 14 | Type: AWS::IAM::ManagedPolicy 15 | Properties: 16 | PolicyDocument: 17 | Version: "2012-10-17" 18 | Statement: 19 | - Sid: SSMActions 20 | Effect: Allow 21 | Action: 22 | - ssm:Get* 23 | - ssm:List* 24 | Resource: "*" 25 | Observability: 26 | Type: AWS::IAM::ManagedPolicy 27 | Properties: 28 | PolicyDocument: 29 | Version: "2012-10-17" 30 | Statement: 31 | - Sid: Xray 32 | Effect: Allow 33 | Action: 34 | - xray:PutTraceSegments 35 | - xray:PutTelemetryRecords 36 | - xray:GetSamplingRules 37 | - xray:GetSamplingTargets 38 | - xray:GetSamplingStatisticSummaries 39 | Resource: "*" 40 | - Sid: AMP 41 | Effect: Allow 42 | Action: 43 | - aps:RemoteWrite 44 | Resource: "*" 45 | 46 | Outputs: 47 | # 1. You need to output the IAM ManagedPolicy so that Copilot can add it as a managed policy to your ECS task role. 48 | SSMAccessPolicyArn: 49 | Description: "The ARN of the ManagedPolicy to attach to the task role." 50 | Value: !Ref SSM 51 | ObservabilityAccessPolicyArn: 52 | Description: "The ARN of the ManagedPolicy to attach to the task role." 53 | Value: !Ref Observability 54 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/ecs-api/copilot/cop301-api/manifest.yml: -------------------------------------------------------------------------------- 1 | # The manifest for the "cop301-api" service. 2 | # Read the full specification for the "Load Balanced Web Service" type at: 3 | # https://aws.github.io/copilot-cli/docs/manifest/lb-web-service/ 4 | 5 | # Your service name will be used in naming your resources like log groups, ECS services, etc. 6 | name: cop301-api 7 | type: Load Balanced Web Service 8 | 9 | # Distribute traffic to your service. 10 | http: 11 | # Requests to this path will be forwarded to your service. 12 | # To match all requests you can use the "/" path. 13 | path: "/" 14 | # You can specify a custom health check path. The default is "/". 15 | healthcheck: "/health" 16 | 17 | # Configuration for your containers and service. 18 | image: 19 | # replace this field with the value of $ECR_REPOSITORY_URI 20 | location: $ECR_REPOSITORY_URI 21 | # Docker build arguments. For additional overrides: https://aws.github.io/copilot-cli/docs/manifest/lb-web-service/#image-build 22 | # build: Dockerfile 23 | # Port exposed through your container to route traffic to it. 24 | port: 8000 25 | platform: linux/arm64 26 | 27 | cpu: 256 # Number of CPU units for the task. 28 | memory: 512 # Amount of memory in MiB used by the task. 29 | count: 2 # Number of tasks that should be running in your service. 30 | exec: true # Enable running commands in your container. 31 | 32 | # Optional fields for more advanced use-cases. 33 | # 34 | variables: # Pass environment variables as key value pairs. 35 | LOG_LEVEL: info 36 | # Deploy /data module to have the lambda URL 37 | DATA_API_URL: $DATA_API_URL 38 | 39 | sidecars: 40 | otel_sidecar: 41 | image: "public.ecr.aws/aws-observability/aws-otel-collector:latest" 42 | secrets: 43 | AOT_CONFIG_CONTENT: /copilot/${COPILOT_APPLICATION_NAME}/${COPILOT_ENVIRONMENT_NAME}/secrets/otel_config 44 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/ecs-api/copilot/environments/test/manifest.yml: -------------------------------------------------------------------------------- 1 | # The manifest for the "test" environment. 2 | # Read the full specification for the "Environment" type at: 3 | # https://aws.github.io/copilot-cli/docs/manifest/environment/ 4 | 5 | # Your environment name will be used in naming your resources like VPC, cluster, etc. 6 | name: test 7 | type: Environment 8 | 9 | # Import your own VPC and subnets or configure how they should be created. 10 | # network: 11 | # vpc: 12 | # id: 13 | 14 | # Configure the load balancers in your environment, once created. 15 | # http: 16 | # public: 17 | # private: 18 | 19 | # Configure observability for your environment resources. 20 | observability: 21 | container_insights: false 22 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/ecs-api/go.mod: -------------------------------------------------------------------------------- 1 | module api 2 | 3 | go 1.20 4 | 5 | require ( 6 | github.com/aws/aws-sdk-go v1.44.276 7 | github.com/gorilla/mux v1.8.0 8 | github.com/prometheus/client_golang v1.15.1 9 | github.com/rs/cors v1.9.0 10 | go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.42.0 11 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0 12 | go.opentelemetry.io/contrib/propagators/aws v1.17.0 13 | go.opentelemetry.io/otel v1.16.0 14 | go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0 15 | go.opentelemetry.io/otel/sdk v1.16.0 16 | go.opentelemetry.io/otel/trace v1.16.0 17 | go.uber.org/zap v1.24.0 18 | ) 19 | 20 | require ( 21 | github.com/beorn7/perks v1.0.1 // indirect 22 | github.com/cenkalti/backoff/v4 v4.2.1 // indirect 23 | github.com/cespare/xxhash/v2 v2.2.0 // indirect 24 | github.com/felixge/httpsnoop v1.0.3 // indirect 25 | github.com/go-logr/logr v1.2.4 // indirect 26 | github.com/go-logr/stdr v1.2.2 // indirect 27 | github.com/golang/protobuf v1.5.3 // indirect 28 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect 29 | github.com/jmespath/go-jmespath v0.4.0 // indirect 30 | github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect 31 | github.com/prometheus/client_model v0.4.0 // indirect 32 | github.com/prometheus/common v0.44.0 // indirect 33 | github.com/prometheus/procfs v0.10.1 // indirect 34 | go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 // indirect 35 | go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 // indirect 36 | go.opentelemetry.io/otel/metric v1.16.0 // indirect 37 | go.opentelemetry.io/proto/otlp v0.19.0 // indirect 38 | go.uber.org/atomic v1.11.0 // indirect 39 | go.uber.org/multierr v1.11.0 // indirect 40 | golang.org/x/net v0.10.0 // indirect 41 | golang.org/x/sys v0.8.0 // indirect 42 | golang.org/x/text v0.9.0 // indirect 43 | google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc // indirect 44 | google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect 45 | google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect 46 | google.golang.org/grpc v1.55.0 // indirect 47 | google.golang.org/protobuf v1.30.0 // indirect 48 | ) 49 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/ecs-api/utils/benchmark.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | concurrency: 60 3 | base: "https://dopi6gkpn7o94.cloudfront.net" 4 | iterations: 200 5 | rampup: 4 6 | 7 | plan: 8 | - name: Vote {{ item.color }} 9 | shuffle: true 10 | request: 11 | url: /votes 12 | method: POST 13 | body: '{"color":"{{ item.color }}"}' 14 | headers: 15 | Content-Type: "application/json" 16 | with_items: 17 | - { color: "teal" } 18 | - { color: "black" } 19 | - { color: "orange" } 20 | - { color: "red orange" } 21 | - { color: "pink" } 22 | - { color: "purple" } 23 | - { color: "deep purple" } 24 | - { color: "indigo" } 25 | - { color: "blue" } 26 | - { color: "cyan" } 27 | - { color: "teal" } 28 | - { color: "yellow" } 29 | - { color: "orange" } 30 | - { color: "black" } 31 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/lambda-api/dequeue/.npmignore: -------------------------------------------------------------------------------- 1 | tests/* 2 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/lambda-api/dequeue/dequeue.js: -------------------------------------------------------------------------------- 1 | const AWSXRay = require('aws-xray-sdk-core') 2 | const AWS = AWSXRay.captureAWS(require('aws-sdk')) 3 | 4 | const dynamodb = new AWS.DynamoDB() 5 | const tableName = process.env.TABLE_NAME 6 | 7 | /** 8 | * Lambda Function URL 9 | * https://docs.aws.amazon.com/lambda/latest/dg/urls-invocation.html 10 | */ 11 | exports.lambdaHandler = async (event, context) => { 12 | 13 | let votes = {} 14 | 15 | event.Records.forEach(record => { 16 | const { body } = record; 17 | const vote = JSON.parse(body) 18 | if (votes[vote.color] === undefined) { 19 | votes[vote.color] = 1 20 | } else { 21 | votes[vote.color] += 1 22 | } 23 | }); 24 | 25 | console.log(votes) 26 | 27 | return this.updateVotesDDB(votes) 28 | }; 29 | 30 | exports.updateVotesDDB = async (votes) => { 31 | 32 | const colors = Object.keys(votes) 33 | console.log(colors) 34 | 35 | const bulkUpdatePromises = colors.map(async (c) => { 36 | const count = `${votes[c]}` 37 | console.log(count) 38 | await dynamodb.updateItem({ 39 | TableName: tableName, 40 | Key: { 41 | "color": { 42 | S: c, 43 | } 44 | }, 45 | UpdateExpression: "ADD votes :inc", 46 | ExpressionAttributeValues: { 47 | ":inc": { N: count } 48 | }, 49 | ReturnValues: "ALL_NEW" 50 | }, 51 | (err, data) => { 52 | if (err) throw err 53 | else console.log(JSON.stringify(data)) 54 | } 55 | ).promise() 56 | }); 57 | 58 | return await Promise.all(bulkUpdatePromises); 59 | } 60 | 61 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/lambda-api/dequeue/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cop301_dequeue", 3 | "version": "1.0.0", 4 | "description": "reInvent cop301 demo", 5 | "main": "dequeue.js", 6 | "repository": "https://github.com/awslabs/aws-sam-cli/tree/develop/samcli/local/init/templates/cookiecutter-aws-sam-hello-nodejs", 7 | "author": "SAM CLI", 8 | "license": "MIT", 9 | "dependencies": { 10 | "axios": ">=0.21.1", 11 | "aws-sdk": "^2.1247.0", 12 | "aws-xray-sdk-core": "^3.3.8" 13 | }, 14 | "scripts": { 15 | "test": "mocha tests/unit/" 16 | }, 17 | "devDependencies": { 18 | "chai": "^4.2.0", 19 | "mocha": "^9.1.4" 20 | } 21 | } -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/lambda-api/dequeue/unit/test-handler.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const app = require('../../app.js'); 4 | const chai = require('chai'); 5 | const expect = chai.expect; 6 | var event, context; 7 | 8 | describe('Tests index', function () { 9 | it('verifies successful response', async () => { 10 | const result = await app.lambdaHandler(event, context) 11 | 12 | expect(result).to.be.an('object'); 13 | expect(result.statusCode).to.equal(200); 14 | expect(result.body).to.be.an('string'); 15 | 16 | let response = JSON.parse(result.body); 17 | 18 | expect(response).to.be.an('object'); 19 | expect(response.message).to.be.equal("hello world"); 20 | // expect(response.location).to.be.an("string"); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/lambda-api/events/event.json: -------------------------------------------------------------------------------- 1 | { 2 | "body": "{\"message\": \"hello world\"}", 3 | "resource": "/{proxy+}", 4 | "path": "/path/to/resource", 5 | "httpMethod": "POST", 6 | "isBase64Encoded": false, 7 | "queryStringParameters": { 8 | "foo": "bar" 9 | }, 10 | "pathParameters": { 11 | "proxy": "/path/to/resource" 12 | }, 13 | "stageVariables": { 14 | "baz": "qux" 15 | }, 16 | "headers": { 17 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", 18 | "Accept-Encoding": "gzip, deflate, sdch", 19 | "Accept-Language": "en-US,en;q=0.8", 20 | "Cache-Control": "max-age=0", 21 | "CloudFront-Forwarded-Proto": "https", 22 | "CloudFront-Is-Desktop-Viewer": "true", 23 | "CloudFront-Is-Mobile-Viewer": "false", 24 | "CloudFront-Is-SmartTV-Viewer": "false", 25 | "CloudFront-Is-Tablet-Viewer": "false", 26 | "CloudFront-Viewer-Country": "US", 27 | "Host": "1234567890.execute-api.us-east-1.amazonaws.com", 28 | "Upgrade-Insecure-Requests": "1", 29 | "User-Agent": "Custom User Agent String", 30 | "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", 31 | "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", 32 | "X-Forwarded-For": "127.0.0.1, 127.0.0.2", 33 | "X-Forwarded-Port": "443", 34 | "X-Forwarded-Proto": "https" 35 | }, 36 | "requestContext": { 37 | "accountId": "123456789012", 38 | "resourceId": "123456", 39 | "stage": "prod", 40 | "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", 41 | "requestTime": "09/Apr/2015:12:34:56 +0000", 42 | "requestTimeEpoch": 1428582896000, 43 | "identity": { 44 | "cognitoIdentityPoolId": null, 45 | "accountId": null, 46 | "cognitoIdentityId": null, 47 | "caller": null, 48 | "accessKey": null, 49 | "sourceIp": "127.0.0.1", 50 | "cognitoAuthenticationType": null, 51 | "cognitoAuthenticationProvider": null, 52 | "userArn": null, 53 | "userAgent": "Custom User Agent String", 54 | "user": null 55 | }, 56 | "path": "/prod/path/to/resource", 57 | "resourcePath": "/{proxy+}", 58 | "httpMethod": "POST", 59 | "apiId": "1234567890", 60 | "protocol": "HTTP/1.1" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/lambda-api/function/.npmignore: -------------------------------------------------------------------------------- 1 | tests/* 2 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/lambda-api/function/app.js: -------------------------------------------------------------------------------- 1 | const AWSXRay = require('aws-xray-sdk-core') 2 | const AWS = AWSXRay.captureAWS(require('aws-sdk')) 3 | 4 | const sqs = new AWS.SQS() 5 | const queueURL = process.env.QUEUE_URL 6 | let response; 7 | 8 | /** 9 | * Lambda Function URL 10 | * https://docs.aws.amazon.com/lambda/latest/dg/urls-invocation.html 11 | */ 12 | exports.lambdaHandler = async (event, context) => { 13 | 14 | console.info(event) 15 | //let body = Buffer.from(event.body, 'base64') 16 | let body = atob(event.body) 17 | //let parsedVote = JSON.parse(body) 18 | 19 | console.log( 20 | event.requestContext.http.method, 21 | event.requestContext.http.path, 22 | event.requestContext.http.protocol, 23 | event.requestContext.http.userAgent, 24 | event.requestContext.http.sourceIp, 25 | body 26 | ) 27 | 28 | if (event.requestContext.http.method == "POST" && event.requestContext.http.path == "/votes") { 29 | 30 | return this.enqueueVote(body, event.requestContext.http.sourceIp) 31 | } 32 | 33 | return { statusCode: 404 } 34 | }; 35 | 36 | exports.enqueueVote = async (body, sourceIP) => { 37 | const params = { 38 | MessageBody: body, 39 | QueueUrl: queueURL, 40 | } 41 | 42 | let parsedVote = JSON.parse(body) 43 | 44 | return new Promise((resolve, reject) => { 45 | sqs.sendMessage(params, (err, data) => { 46 | if (err) 47 | throw err 48 | else { 49 | console.info(data) 50 | response = { 51 | statusCode: 200, 52 | headers: { 53 | "Access-Control-Allow-Headers": "Content-Type", 54 | "Access-Control-Allow-Origin": "*", 55 | "Access-Control-Allow-Methods": "OPTIONS,POST,GET" 56 | }, 57 | body: { 58 | color: parsedVote.color.trim(), 59 | source: sourceIP 60 | } 61 | } 62 | resolve(response) 63 | } 64 | }).promise() 65 | }) 66 | } -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/lambda-api/function/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cop301_data", 3 | "version": "1.0.0", 4 | "description": "reInvent cop301 demo", 5 | "main": "app.js", 6 | "repository": "https://github.com/awslabs/aws-sam-cli/tree/develop/samcli/local/init/templates/cookiecutter-aws-sam-hello-nodejs", 7 | "author": "SAM CLI", 8 | "license": "MIT", 9 | "dependencies": { 10 | "axios": ">=0.21.1", 11 | "aws-sdk": "^2.1247.0", 12 | "aws-xray-sdk-core": "^3.3.8" 13 | }, 14 | "scripts": { 15 | "test": "mocha tests/unit/" 16 | }, 17 | "devDependencies": { 18 | "chai": "^4.2.0", 19 | "mocha": "^9.1.4" 20 | } 21 | } -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/lambda-api/function/tests/unit/test-handler.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const app = require('../../app.js'); 4 | const chai = require('chai'); 5 | const expect = chai.expect; 6 | var event, context; 7 | 8 | describe('Tests index', function () { 9 | it('verifies successful response', async () => { 10 | const result = await app.lambdaHandler(event, context) 11 | 12 | expect(result).to.be.an('object'); 13 | expect(result.statusCode).to.equal(200); 14 | expect(result.body).to.be.an('string'); 15 | 16 | let response = JSON.parse(result.body); 17 | 18 | expect(response).to.be.an('object'); 19 | expect(response.message).to.be.equal("hello world"); 20 | // expect(response.location).to.be.an("string"); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/event-demos/riv-cop301-2022/lambda-api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "aws-sdk": "^2.1247.0", 4 | "aws-xray-sdk-core": "^3.3.8" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/extra_scrape_configs.yaml: -------------------------------------------------------------------------------- 1 | - job_name: kubecost 2 | honor_labels: true 3 | scrape_interval: 1m 4 | scrape_timeout: 10s 5 | metrics_path: /metrics 6 | scheme: http 7 | dns_sd_configs: 8 | - names: 9 | - kubecost-cost-analyzer # Note: this is the URL of the kube-cost-analyzer. 10 | type: "A" 11 | port: 9003 -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/k8s_petsite/deployment.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | annotations: 6 | eks.amazonaws.com/role-arn: "{{PETSITE_SA_ROLE}}" 7 | name: petsite-sa 8 | namespace: default 9 | --- 10 | apiVersion: v1 11 | kind: Service 12 | metadata: 13 | name: service-petsite 14 | namespace: default 15 | annotations: 16 | scrape: "true" 17 | prometheus.io/scrape: "true" 18 | spec: 19 | ports: 20 | - port: 80 21 | nodePort: 30300 22 | targetPort: 80 23 | protocol: TCP 24 | type: NodePort 25 | selector: 26 | app: petsite 27 | --- 28 | apiVersion: apps/v1 29 | kind: Deployment 30 | metadata: 31 | name: petsite-deployment 32 | namespace: default 33 | spec: 34 | selector: 35 | matchLabels: 36 | app: petsite 37 | replicas: 2 38 | template: 39 | metadata: 40 | labels: 41 | app: petsite 42 | spec: 43 | serviceAccountName: petsite-sa 44 | containers: 45 | - image: "{{ECR_IMAGE_URL}}" 46 | imagePullPolicy: Always 47 | name: petsite 48 | ports: 49 | - containerPort: 80 50 | protocol: TCP 51 | env: 52 | - name: AWS_XRAY_DAEMON_ADDRESS 53 | value: xray-service.default:2000 54 | --- 55 | apiVersion: elbv2.k8s.aws/v1beta1 56 | kind: TargetGroupBinding 57 | metadata: 58 | name: petsite-tgb 59 | spec: 60 | serviceRef: 61 | name: service-petsite 62 | port: 80 63 | targetGroupARN: "" 64 | targetType: ip 65 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/kitten.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/one-observability-demo/396cb484bde89fbe3581338d9eb33e5769f58f4c/PetAdoptions/cdk/pet_stack/resources/kitten.zip -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/load_balancer/service_account.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: alb-ingress-controller 7 | name: alb-ingress-controller 8 | namespace: kube-system 9 | annotations: 10 | eks.amazonaws.com/role-arn: "<>" -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/microservices/payforadoption-go: -------------------------------------------------------------------------------- 1 | ../../../../payforadoption-go/ -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/microservices/petadoptionshistory-py: -------------------------------------------------------------------------------- 1 | ../../../../petadoptionshistory-py/ -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/microservices/petlistadoptions-go: -------------------------------------------------------------------------------- 1 | ../../../../petlistadoptions-go/ -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/microservices/petsearch-java: -------------------------------------------------------------------------------- 1 | ../../../../petsearch-java/ -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/microservices/petsite: -------------------------------------------------------------------------------- 1 | ../../../../petsite/ -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/microservices/trafficgenerator: -------------------------------------------------------------------------------- 1 | ../../../../trafficgenerator/ -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/petadoptionshistory-py/README.md: -------------------------------------------------------------------------------- 1 | # PetAdoptionsHistory with full OTEL instrumentation applied 2 | 3 | See PetAdoptions/petadoptionshistory-py/ for the complete source code of the service. 4 | 5 | * `petadoptionshistory_tracing.py`: tracing applied 6 | * `petadoptionshistory_complete.py`: tracing and metrics applied -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/puppies.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/one-observability-demo/396cb484bde89fbe3581338d9eb33e5769f58f4c/PetAdoptions/cdk/pet_stack/resources/puppies.zip -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/rds_sqlserver.sql: -------------------------------------------------------------------------------- 1 | USE [master] 2 | GO 3 | 4 | /****** Object: Database [adoptions] Script Date: 4/24/2020 2:02:30 PM ******/ 5 | CREATE DATABASE [adoptions] 6 | CONTAINMENT = NONE 7 | ON PRIMARY 8 | ( NAME = N'adoptions', FILENAME = N'D:\rdsdbdata\DATA\adoptions.mdf' , SIZE = 8192KB , MAXSIZE = UNLIMITED, FILEGROWTH = 10%) 9 | LOG ON 10 | ( NAME = N'adoptions_log', FILENAME = N'D:\rdsdbdata\DATA\adoptions_log.ldf' , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%) 11 | GO 12 | 13 | 14 | 15 | USE [adoptions] 16 | GO 17 | 18 | /****** Object: Table [dbo].[Transactions] Script Date: 4/23/2020 10:07:28 PM ******/ 19 | SET ANSI_NULLS ON 20 | GO 21 | 22 | SET QUOTED_IDENTIFIER ON 23 | GO 24 | 25 | CREATE TABLE [dbo].[Transactions]( 26 | [Id] [int] IDENTITY(1,1) NOT NULL, 27 | [PetId] [nvarchar](50) NULL, 28 | [Adoption_Date] [datetime] NULL, 29 | [Transaction_Id] [nvarchar](50) NULL, 30 | PRIMARY KEY CLUSTERED 31 | ( 32 | [Id] ASC 33 | )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 34 | ) ON [PRIMARY] 35 | GO 36 | 37 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/setup-ssm-agent.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: node-configuration-daemonset 5 | --- 6 | apiVersion: rbac.authorization.k8s.io/v1 7 | kind: ClusterRole 8 | metadata: 9 | name: ssm-agent-installer 10 | rules: 11 | - apiGroups: ['policy'] 12 | resources: ['podsecuritypolicies'] 13 | verbs: ['use'] 14 | resourceNames: 15 | - ssm-agent-installer 16 | --- 17 | apiVersion: v1 18 | kind: ServiceAccount 19 | metadata: 20 | name: ssm-agent-installer 21 | namespace: node-configuration-daemonset 22 | --- 23 | apiVersion: rbac.authorization.k8s.io/v1 24 | kind: RoleBinding 25 | metadata: 26 | name: ssm-agent-installer 27 | namespace: node-configuration-daemonset 28 | roleRef: 29 | kind: ClusterRole 30 | name: ssm-agent-installer 31 | apiGroup: rbac.authorization.k8s.io 32 | subjects: 33 | - kind: ServiceAccount 34 | name: ssm-agent-installer 35 | namespace: node-configuration-daemonset 36 | --- 37 | apiVersion: v1 38 | kind: ConfigMap 39 | metadata: 40 | name: ssm-installer-script 41 | namespace: node-configuration-daemonset 42 | data: 43 | install.sh: | 44 | #!/bin/bash 45 | # Update and install packages 46 | sudo yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm 47 | STATUS=$(sudo systemctl status amazon-ssm-agent) 48 | if echo $STATUS | grep -q "running"; then 49 | echo "Success" 50 | else 51 | echo "Fail" >&2 52 | fi 53 | --- 54 | apiVersion: apps/v1 55 | kind: DaemonSet 56 | metadata: 57 | name: ssm-agent-installer 58 | namespace: node-configuration-daemonset 59 | spec: 60 | selector: 61 | matchLabels: 62 | job: ssm-agent-installer 63 | template: 64 | metadata: 65 | labels: 66 | job: ssm-agent-installer 67 | spec: 68 | hostPID: true 69 | restartPolicy: Always 70 | initContainers: 71 | - image: jicowan/ssm-agent-installer:1.2 72 | name: ssm-agent-installer 73 | securityContext: 74 | privileged: true 75 | volumeMounts: 76 | - name: install-script 77 | mountPath: /tmp 78 | - name: host-mount 79 | mountPath: /host 80 | volumes: 81 | - name: install-script 82 | configMap: 83 | name: ssm-installer-script 84 | - name: host-mount 85 | hostPath: 86 | path: /tmp/install 87 | serviceAccount: ssm-agent-installer 88 | containers: 89 | - image: "gcr.io/google-containers/pause:2.0" 90 | name: pause 91 | securityContext: 92 | allowPrivilegeEscalation: false 93 | runAsUser: 1000 94 | readOnlyRootFilesystem: true 95 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/stepfn_lambdas/lambda_step_priceGreaterThan55.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | def lambda_handler(event, context): 4 | # TODO implement 5 | print(event) 6 | 7 | print('ProcessGreaterThan55 - Execution complete') 8 | return { 9 | 'statusCode': 200, 10 | 'body': json.dumps('ProcessGreaterThan55 - Execution complete') 11 | } 12 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/stepfn_lambdas/lambda_step_priceLessThan55.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | def lambda_handler(event, context): 4 | # TODO implement 5 | print(event) 6 | print('ProcessLessthan55 - Execution complete') 7 | return { 8 | 'statusCode': 200, 9 | 'body': json.dumps('ProcessLessthan55 - Execution complete') 10 | } 11 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/stepfn_lambdas/lambda_step_readDDB.py: -------------------------------------------------------------------------------- 1 | import json 2 | import boto3 3 | from boto3.dynamodb.conditions import Key 4 | 5 | ssm = boto3.client('ssm') 6 | dynamodb = boto3.resource('dynamodb') 7 | 8 | def lambda_handler(event, context): 9 | 10 | dynamodb_tablename = ssm.get_parameter(Name='/petstore/dynamodbtablename', WithDecryption=False) 11 | 12 | table = dynamodb.Table(dynamodb_tablename['Parameter']['Value']) 13 | 14 | response = table.query( 15 | KeyConditionExpression=Key('petid').eq(event['petid']) & Key('pettype').eq(event['pettype']) 16 | ) 17 | 18 | response['Items'][0]['price'] = int(response['Items'][0]['price']) 19 | 20 | return { 21 | 'statusCode': 200, 22 | 'body': response['Items'][0] 23 | } 24 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/syn-apicanary.js: -------------------------------------------------------------------------------- 1 | var synthetics = require('Synthetics'); 2 | const log = require('SyntheticsLogger'); 3 | const https = require('https'); 4 | const http = require('http'); 5 | 6 | const apiCanaryBlueprint = async function () { 7 | const postData = ""; 8 | 9 | const verifyRequest = async function (requestOption) { 10 | return new Promise((resolve, reject) => { 11 | log.info("Making request with options: " + JSON.stringify(requestOption)); 12 | let req 13 | if (requestOption.port === 443) { 14 | req = https.request(requestOption); 15 | } else { 16 | req = http.request(requestOption); 17 | } 18 | req.on('response', (res) => { 19 | log.info(`Status Code: ${res.statusCode}`) 20 | log.info(`Response Headers: ${JSON.stringify(res.headers)}`) 21 | if (res.statusCode !== 200) { 22 | reject("Failed: " + requestOption.path); 23 | } 24 | res.on('data', (d) => { 25 | log.info("Response: " + d.length); 26 | if(d.length <= 2) 27 | { 28 | reject("PetType Invalid - : "+requestOption.path ); 29 | } 30 | }); 31 | res.on('end', () => { 32 | resolve(); 33 | }) 34 | }); 35 | 36 | req.on('error', (error) => { 37 | reject(error); 38 | }); 39 | 40 | if (postData) { 41 | req.write(postData); 42 | } 43 | req.end(); 44 | }); 45 | } 46 | 47 | const headers = {} 48 | headers['User-Agent'] = [synthetics.getCanaryUserAgentString(), headers['User-Agent']].join(' '); 49 | 50 | const pettypes = ["fish", "bunny", "puppy", "kitten"]; 51 | const position = Math.floor(Math.random() * Math.floor(4)); 52 | 53 | const requestOptions = { 54 | hostname: '', 55 | // Example- hostname: 'petsearch-live.us-east-1.elasticbeanstalk.com', 56 | port: 80, 57 | path: '/api/search?pettype='+pettypes[position], 58 | method: 'GET' 59 | } 60 | 61 | requestOptions['headers'] = headers; 62 | await verifyRequest(requestOptions); 63 | }; 64 | 65 | exports.handler = async () => { 66 | return await apiCanaryBlueprint(); 67 | }; 68 | 69 | 70 | -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/resources/syn-uicanary.js: -------------------------------------------------------------------------------- 1 | var synthetics = require('Synthetics'); 2 | const log = require('SyntheticsLogger'); 3 | 4 | const flowBuilderBlueprint = async function () { 5 | // INSERT URL here 6 | //let url = "http://petsite-1081345346.us-east-1.elb.amazonaws.com/"; 7 | let url = ""; 8 | 9 | let page = await synthetics.getPage(); 10 | 11 | // Navigate to the initial url 12 | await synthetics.executeStep('navigateToUrl', async function (timeoutInMillis = 30000) { 13 | await page.goto(url, {waitUntil: ['load', 'networkidle0'], timeout: timeoutInMillis}); 14 | }); 15 | 16 | // Execute customer steps 17 | await synthetics.executeStep('customerActions', async function () { 18 | await page.waitForSelector("[id='searchpets']", { timeout: 30000 }); 19 | await page.click("[id='searchpets']"); 20 | try { 21 | await synthetics.takeScreenshot("click", 'result'); 22 | } catch(ex) { 23 | synthetics.addExecutionError('Unable to capture screenshot.', ex); 24 | } 25 | 26 | await page.waitForSelector("[id='seeadoptionlist']", { timeout: 30000 }); 27 | await page.click("[id='seeadoptionlist']"); 28 | try { 29 | await synthetics.takeScreenshot("click", 'result'); 30 | } catch(ex) { 31 | synthetics.addExecutionError('Unable to capture screenshot.', ex); 32 | } 33 | 34 | await page.waitForSelector("[id='performhousekeeping']", { timeout: 30000 }); 35 | await page.click("[id='performhousekeeping']"); 36 | try { 37 | await synthetics.takeScreenshot("click", 'result'); 38 | } catch(ex) { 39 | synthetics.addExecutionError('Unable to capture screenshot.', ex); 40 | } 41 | }); 42 | }; 43 | 44 | exports.handler = async () => { 45 | return await flowBuilderBlueprint(); 46 | }; -------------------------------------------------------------------------------- /PetAdoptions/cdk/pet_stack/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target":"ES2021", 4 | "module": "commonjs", 5 | "lib": ["es2021"], 6 | "declaration": true, 7 | "strict": true, 8 | "noImplicitAny": true, 9 | "strictNullChecks": true, 10 | "noImplicitThis": true, 11 | "alwaysStrict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": false, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": false, 16 | "inlineSourceMap": true, 17 | "inlineSources": true, 18 | "experimentalDecorators": true, 19 | "strictPropertyInitialization":false, 20 | "typeRoots": ["./node_modules/@types"] 21 | }, 22 | "exclude": ["cdk.out"] 23 | } 24 | -------------------------------------------------------------------------------- /PetAdoptions/getrole.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | currentRole=$(aws sts get-caller-identity --query Arn --output text) 4 | 5 | if echo ${currentRole} | grep -q assumed-role; then 6 | assumedrolename=$(echo ${currentRole} | awk -F/ '{print $(NF-1)}') 7 | rolearn=$(aws iam get-role --role-name ${assumedrolename} --query Role.Arn --output text) 8 | echo ${rolearn} 9 | exit 0 10 | elif echo ${currentRole} | grep -q user; then 11 | echo ${currentRole} 12 | exit 0 13 | fi 14 | 15 | exit 1 -------------------------------------------------------------------------------- /PetAdoptions/patches/ddb-billing-mode.patch: -------------------------------------------------------------------------------- 1 | diff --git cdk/pet_stack/lib/services.ts cdk/pet_stack/lib/services.ts 2 | index d469bbd..dc4a15a 100644 3 | --- cdk/pet_stack/lib/services.ts 4 | +++ cdk/pet_stack/lib/services.ts 5 | @@ -55,21 +55,8 @@ export class Services extends cdk.Stack { 6 | name: 'petid', 7 | type: ddb.AttributeType.STRING 8 | }, 9 | - removalPolicy: RemovalPolicy.DESTROY 10 | - }); 11 | - 12 | - dynamodb_petadoption.metricConsumedReadCapacityUnits().createAlarm(this, 'ReadCapacityUnitsLimit-BasicAlarm', { 13 | - threshold: 240, 14 | - evaluationPeriods: 2, 15 | - period: cdk.Duration.minutes(1), 16 | - alarmName: `${dynamodb_petadoption.tableName}-ReadCapacityUnitsLimit-BasicAlarm`, 17 | - }); 18 | - 19 | - dynamodb_petadoption.metricConsumedReadCapacityUnits().createAlarm(this, 'WriteCapacityUnitsLimit-BasicAlarm', { 20 | - threshold: 240, 21 | - evaluationPeriods: 2, 22 | - period: cdk.Duration.minutes(1), 23 | - alarmName: `${dynamodb_petadoption.tableName}-WriteCapacityUnitsLimit-BasicAlarm`, 24 | + removalPolicy: RemovalPolicy.DESTROY, 25 | + billingMode: ddb.BillingMode.PAY_PER_REQUEST 26 | }); 27 | 28 | // Seeds the petadoptions dynamodb table with all data required 29 | -------------------------------------------------------------------------------- /PetAdoptions/patches/sql-connection.patch: -------------------------------------------------------------------------------- 1 | diff --git payforadoption/PayForAdoption/Controllers/HomeController.cs payforadoption/PayForAdoption/Controllers/HomeController.cs 2 | index d801a84..f2eb9d0 100644 3 | --- payforadoption/PayForAdoption/Controllers/HomeController.cs 4 | +++ payforadoption/PayForAdoption/Controllers/HomeController.cs 5 | @@ -1,4 +1,5 @@ 6 | -using System; 7 | +using System; 8 | +using System.Data; 9 | using System.Collections.Generic; 10 | using System.Linq; 11 | using System.Net.Http; 12 | @@ -19,7 +20,6 @@ namespace PayForAdoption.Controllers 13 | [ApiController] 14 | public class HomeController : ControllerBase 15 | { 16 | - private static SqlConnection _sqlConnection = new SqlConnection(); 17 | private static HttpClient _httpClient = new HttpClient(new HttpClientXRayTracingHandler(new HttpClientHandler())); 18 | private static IConfiguration _configuration; 19 | public HomeController(IConfiguration configuration) 20 | @@ -37,13 +37,11 @@ namespace PayForAdoption.Controllers 21 | AWSXRayRecorder.Instance.AddAnnotation("PetId", petId); 22 | AWSXRayRecorder.Instance.AddAnnotation("PetType", pettype); 23 | 24 | - _sqlConnection.ConnectionString = await GetConnectionString(); 25 | - 26 | var sqlCommandText = $"INSERT INTO [dbo].[transactions] ([PetId], [Transaction_Id], [Adoption_Date]) VALUES ('{petId}', '{Guid.NewGuid().ToString()}', '{DateTime.Now.ToString()}')"; 27 | 28 | AWSXRayRecorder.Instance.AddMetadata("Query",sqlCommandText); 29 | 30 | - using (_sqlConnection) 31 | + using (SqlConnection _sqlConnection = new SqlConnection(await GetConnectionString())) 32 | { 33 | using var command = new TraceableSqlCommand(sqlCommandText, _sqlConnection); 34 | command.Connection.Open(); 35 | @@ -63,13 +61,12 @@ namespace PayForAdoption.Controllers 36 | [HttpPost("CleanUpAdoptions")] 37 | public async Task CleanupAdoptions() 38 | { 39 | - _sqlConnection.ConnectionString = await GetConnectionString(); 40 | 41 | var sqlCommandText = $"DELETE FROM [dbo].[transactions]"; 42 | 43 | AWSXRayRecorder.Instance.AddMetadata("Query",sqlCommandText); 44 | 45 | - using (_sqlConnection) 46 | + using (SqlConnection _sqlConnection = new SqlConnection(await GetConnectionString())) 47 | { 48 | using var command = new TraceableSqlCommand(sqlCommandText, _sqlConnection); 49 | command.Connection.Open(); 50 | -------------------------------------------------------------------------------- /PetAdoptions/payforadoption-go/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.23 as builder 2 | WORKDIR /go/src/app 3 | COPY . . 4 | ENV GOPROXY=https://goproxy.io,direct 5 | RUN go get . 6 | RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . 7 | 8 | FROM alpine:latest 9 | WORKDIR /app 10 | RUN apk --no-cache add ca-certificates 11 | COPY --from=builder /go/src/app/app . 12 | COPY --from=builder /go/src/app/seed.json . 13 | EXPOSE 80 14 | CMD ["./app"] 15 | -------------------------------------------------------------------------------- /PetAdoptions/payforadoption-go/benchmark/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rust:latest as builder 2 | WORKDIR /app 3 | RUN 4 | COPY . . 5 | RUN cargo install drill 6 | CMD ["./benchmark.sh"] 7 | -------------------------------------------------------------------------------- /PetAdoptions/payforadoption-go/benchmark/README.md: -------------------------------------------------------------------------------- 1 | ## Drill for PayForAdoption 2 | 3 | Using [drill](https://github.com/fcsonline/drill), this allows to generate 4 | traffic in the PetSite EKS cluster or locally in dev, without spinning ECS 5 | traffic generator. 6 | 7 | This can be useful to test all APIs or boost traffic for Application Signals. 8 | 9 | ### (Optional) Pick your benchmark environment 10 | 11 | In the `benchmark.yaml` file, change the base URL to your PayForAdoption ALB 12 | endpoint if you are not testing it locally as the default is local. 13 | 14 | ```yaml 15 | concurrency: 4 16 | base: "http://Servic-payfo-[.....].eu-central-1.elb.amazonaws.com" 17 | ``` 18 | 19 | ### Running locally 20 | 21 | [Install drill](https://github.com/fcsonline/drill?tab=readme-ov-file#install) 22 | and run 23 | 24 | ```bash 25 | drill --benchmark benchmark.yaml 26 | ``` 27 | 28 | ### Running in EKS 29 | 30 | 1. Authenticate against your EKS cluster 31 | 32 | ```bash 33 | aws eks update-kubeconfig --name PetSite --region 34 | ``` 35 | 36 | 2. Create an ECR image `drill-payforadoption` 37 | 38 | 3. Build and push 39 | 40 | ```bash 41 | aws ecr get-login-password --region | docker login --username AWS --password-stdin .dkr.ecr..amazonaws.com 42 | docker buildx build -t drill-payforadoption . --platform=linux/amd64 43 | docker tag drill-payforadoption:latest .dkr.ecr..amazonaws.com/drill-payforadoption:latest 44 | docker push .dkr.ecr..amazonaws.com/drill-payforadoption:latest 45 | ``` 46 | 47 | 4. Run in EKS 48 | 49 | ```bash 50 | kubectl run -it drill-payforadoption --image .dkr.ecr..amazonaws.com/drill-payforadoption:latest 51 | ``` 52 | 53 | -------------------------------------------------------------------------------- /PetAdoptions/payforadoption-go/benchmark/benchmark.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | while true 4 | do 5 | drill -s --benchmark benchmark.yaml 6 | sleep 1 7 | done 8 | -------------------------------------------------------------------------------- /PetAdoptions/payforadoption-go/benchmark/benchmark.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | concurrency: 4 3 | base: "http://localhost:80" 4 | iterations: 4 5 | rampup: 2 6 | 7 | plan: 8 | - name: Health check 9 | request: 10 | url: /health/status 11 | method: GET 12 | 13 | - name: Adopt Bunnies 14 | request: 15 | url: /api/home/completeadoption?petId={{ item }}&petType=bunny 16 | method: POST 17 | body: "" 18 | with_items: 19 | - "023" 20 | - "024" 21 | - "025" 22 | - "026" 23 | - "invalid_bunny_id" 24 | 25 | - name: Adopt Kittens 26 | request: 27 | url: /api/home/completeadoption?petId={{ item }}&petType=kitten 28 | method: POST 29 | body: "" 30 | with_items: 31 | - "016" 32 | - "017" 33 | - "018" 34 | - "019" 35 | - "020" 36 | - "021" 37 | - "022" 38 | - "invalid_kitten_id" 39 | 40 | - name: Adopt Puppies 41 | request: 42 | url: /api/home/completeadoption?petId={{ item }}&petType=puppy 43 | method: POST 44 | body: "" 45 | with_items: 46 | - "001" 47 | - "002" 48 | - "003" 49 | - "004" 50 | - "005" 51 | - "006" 52 | - "007" 53 | - "008" 54 | - "009" 55 | - "010" 56 | - "011" 57 | - "012" 58 | - "013" 59 | - "014" 60 | - "015" 61 | - "invalid_puppy_id" 62 | 63 | - name: Cleanup Adoptions 64 | request: 65 | url: /api/home/cleanupadoptions 66 | method: POST 67 | body: "" 68 | -------------------------------------------------------------------------------- /PetAdoptions/payforadoption-go/payforadoption/endpoint.go: -------------------------------------------------------------------------------- 1 | package payforadoption 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/go-kit/kit/endpoint" 7 | ) 8 | 9 | type Endpoints struct { 10 | HealthCheckEndpoint endpoint.Endpoint 11 | CompleteAdoptionEndpoint endpoint.Endpoint 12 | CleanupAdoptionsEndpoint endpoint.Endpoint 13 | TriggerSeedingEndpoint endpoint.Endpoint 14 | } 15 | 16 | func MakeEndpoints(s Service) Endpoints { 17 | return Endpoints{ 18 | HealthCheckEndpoint: makeHealthCheckEndpoint(s), 19 | CompleteAdoptionEndpoint: makeCompleteAdoptionEndpoint(s), 20 | CleanupAdoptionsEndpoint: makeCleanupAdoptionsEndpoint(s), 21 | TriggerSeedingEndpoint: makeTriggerSeedingEndpoint(s), 22 | } 23 | } 24 | 25 | func makeHealthCheckEndpoint(s Service) endpoint.Endpoint { 26 | return func(ctx context.Context, _ interface{}) (interface{}, error) { 27 | return nil, s.HealthCheck(ctx) 28 | } 29 | } 30 | 31 | func makeCompleteAdoptionEndpoint(s Service) endpoint.Endpoint { 32 | return func(ctx context.Context, request interface{}) (interface{}, error) { 33 | req := request.(completeAdoptionRequest) 34 | return s.CompleteAdoption(ctx, req.PetId, req.PetType) 35 | } 36 | } 37 | 38 | func makeCleanupAdoptionsEndpoint(s Service) endpoint.Endpoint { 39 | return func(ctx context.Context, _ interface{}) (interface{}, error) { 40 | return nil, s.CleanupAdoptions(ctx) 41 | } 42 | } 43 | 44 | func makeTriggerSeedingEndpoint(s Service) endpoint.Endpoint { 45 | return func(ctx context.Context, _ interface{}) (interface{}, error) { 46 | return nil, s.TriggerSeeding(ctx) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /PetAdoptions/payforadoption-go/payforadoption/utils.go: -------------------------------------------------------------------------------- 1 | package payforadoption 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "strings" 7 | "time" 8 | ) 9 | 10 | type CustomerInfo struct { 11 | ID int64 12 | FullName string 13 | Address string 14 | CreditCard string 15 | Email string 16 | } 17 | 18 | func getFakeCustomer() CustomerInfo { 19 | now := time.Now().UnixNano() 20 | r := rand.New(rand.NewSource(now)) 21 | fullname := fmt.Sprintf("%s %s", getFirstName(r), getLastName(r)) 22 | 23 | return CustomerInfo{ 24 | ID: time.Now().UnixNano(), 25 | FullName: fullname, 26 | Email: strings.ToLower(fmt.Sprintf("%s.com", strings.ReplaceAll(fullname, " ", "@"))), 27 | CreditCard: getFakeCreditCard(r), 28 | Address: getAddresses(r), 29 | } 30 | } 31 | 32 | func getFakeCreditCard(r *rand.Rand) string { 33 | 34 | //not real cards 35 | //from https://developer.paypal.com/braintree/docs/guides/credit-cards/testing-go-live/node 36 | seed := []string{ 37 | "4217651111111119", 38 | "4500600000000061", 39 | "4005519200000004", 40 | "4012000077777777", 41 | "4012000033330026", 42 | "2223000048400011", 43 | "6304000000000000", 44 | } 45 | 46 | return seed[r.Intn(len(seed))] 47 | } 48 | 49 | func getFirstName(r *rand.Rand) string { 50 | seed := []string{ 51 | "Catherine", 52 | "Javier", 53 | "Alex", 54 | "Frank", 55 | "Mark", 56 | "Fatiha", 57 | "Purva", 58 | "Selim", 59 | "Jane", 60 | "Alan", 61 | "Mohamed", 62 | } 63 | return seed[r.Intn(len(seed))] 64 | } 65 | 66 | func getLastName(r *rand.Rand) string { 67 | seed := []string{ 68 | "Banks", 69 | "Marley", 70 | "Konan", 71 | "Lopez", 72 | "Gonzales", 73 | "Levine", 74 | "Fofana", 75 | "Hernan", 76 | "Zheng", 77 | "Chergui", 78 | "Mousli", 79 | } 80 | return seed[r.Intn(len(seed))] 81 | } 82 | 83 | func getAddresses(r *rand.Rand) string { 84 | 85 | // Random addresses 86 | seed := []string{ 87 | "8 Rue de la Pompe, 75116 Paris", 88 | "174 Quai de Jemmapes, 75010 Paris, France", 89 | "60 Holborn Viaduct, London, EC1A 2FD", 90 | "3333 Piedmont Road NE, Atlanta, GA 30305", 91 | "2121 7th Ave, Seattle WA, 98121", 92 | "2021 7th Ave, Seattle WA, 98121", 93 | "31 place des Corolles, 92400 Courbevoie", 94 | "120 Avenue de Versailles, 75016 Paris", 95 | } 96 | return seed[r.Intn(len(seed))] 97 | } 98 | -------------------------------------------------------------------------------- /PetAdoptions/petadoptionshistory-py/Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | 3 | FROM python:3.8 4 | 5 | WORKDIR /app 6 | 7 | # prerequisites for building psycopg2 8 | RUN apt-get update && apt-get install -y build-essential python3-dev libpq-dev 9 | 10 | COPY requirements.txt requirements.txt 11 | RUN pip3 install -r requirements.txt 12 | 13 | COPY . . 14 | ENV FLASK_APP=petadoptionshistory 15 | ENV PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python 16 | 17 | CMD [ "flask", "run" , "--host=0.0.0.0", "--port=8080"] 18 | 19 | EXPOSE 8080/tcp -------------------------------------------------------------------------------- /PetAdoptions/petadoptionshistory-py/config.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | import boto3 4 | 5 | def fetch_config(): 6 | cfg = { 7 | 'update_adoption_url': os.getenv("UPDATE_ADOPTION_URL"), 8 | 'rds_secret_arn': os.getenv("RDS_SECRET_ARN"), 9 | 'region': os.getenv("AWS_REGION") 10 | } 11 | 12 | if cfg['update_adoption_url'] == None or cfg['rds_secret_arn'] == None: 13 | return fetch_config_from_parameter_store(cfg['region']) 14 | 15 | return cfg 16 | 17 | def fetch_config_from_parameter_store(region): 18 | client = boto3.client('ssm', region_name=region) 19 | 20 | result = client.get_parameters( 21 | Names=[ 22 | '/petstore/updateadoptionstatusurl', 23 | '/petstore/rdssecretarn', 24 | '/petstore/s3bucketname', 25 | '/petstore/dynamodbtablename' 26 | ] 27 | ) 28 | 29 | cfg = { 30 | 'region': region 31 | } 32 | 33 | for p in result['Parameters']: 34 | if p['Name'] == '/petstore/updateadoptionstatusurl': 35 | cfg['update_adoption_url'] = p['Value'] 36 | elif p['Name'] == '/petstore/rdssecretarn': 37 | cfg['rds_secret_arn'] = p['Value'] 38 | elif p['Name'] == '/petstore/s3bucketname': 39 | cfg['s3_bucket_name'] = p['Value'] 40 | elif p['Name'] == '/petstore/dynamodbtablename': 41 | cfg['dynamodb_tablename'] = p['Value'] 42 | 43 | return cfg 44 | 45 | def get_secret_value(secret_id, region): 46 | client = boto3.client('secretsmanager', region_name=region) 47 | 48 | response = client.get_secret_value( 49 | SecretId=secret_id 50 | ) 51 | 52 | return response['SecretString'] 53 | 54 | def get_rds_connection_parameters(secret_id, region): 55 | jsonstr = get_secret_value(secret_id, region) 56 | 57 | c = json.loads(jsonstr) 58 | 59 | u = { 60 | 'database': c['dbname'], 61 | 'user': c['username'], 62 | 'password': c['password'], 63 | 'host': c['host'] 64 | } 65 | 66 | return u -------------------------------------------------------------------------------- /PetAdoptions/petadoptionshistory-py/petadoptionshistory.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import os 3 | import psycopg 4 | import config 5 | import repository 6 | from flask import Flask, jsonify 7 | 8 | # Setup flask app 9 | app = Flask(__name__) 10 | 11 | logging.basicConfig(level=os.getenv('LOG_LEVEL', 20), format='%(message)s') 12 | logger = logging.getLogger() 13 | cfg = config.fetch_config() 14 | conn_params = config.get_rds_connection_parameters(cfg['rds_secret_arn'], cfg['region']) 15 | db = psycopg.connect(**conn_params) 16 | 17 | @app.route('/petadoptionshistory/api/home/transactions', methods=['GET']) 18 | def transactions_get(): 19 | transactions = repository.list_transaction_history(db) 20 | return jsonify(transactions) 21 | 22 | @app.route('/petadoptionshistory/api/home/transactions', methods=['DELETE']) 23 | def transactions_delete(): 24 | repository.delete_transaction_history(db) 25 | return jsonify(success=True) 26 | 27 | @app.route('/health/status') 28 | def status_path(): 29 | repository.check_alive(db) 30 | return jsonify(success=True) -------------------------------------------------------------------------------- /PetAdoptions/petadoptionshistory-py/repository.py: -------------------------------------------------------------------------------- 1 | def list_transaction_history(db): 2 | sql = 'SELECT * FROM transactions_history' 3 | 4 | cur = db.cursor() 5 | cur.execute(sql) 6 | result = cur.fetchall() 7 | db.commit() 8 | 9 | return result 10 | 11 | def delete_transaction_history(db): 12 | sql = 'DELETE FROM transactions_history' 13 | 14 | cur = db.cursor() 15 | result = cur.execute(sql) 16 | db.commit() 17 | 18 | return result 19 | 20 | def count_transaction_history(db): 21 | sql = 'SELECT count(*) FROM transactions_history' 22 | 23 | cur = db.cursor() 24 | cur.execute(sql) 25 | result = cur.fetchone() 26 | db.commit() 27 | 28 | return result[0] 29 | 30 | def check_alive(db): 31 | sql = 'SELECT NULL' # do nothing 32 | 33 | cur = db.cursor() 34 | cur.execute(sql) 35 | db.commit() -------------------------------------------------------------------------------- /PetAdoptions/petadoptionshistory-py/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask==2.0.2 2 | boto3==1.37.10 3 | psycopg==3.2.5 4 | opentelemetry-distro==0.32b0 5 | opentelemetry-exporter-otlp==1.11.1 6 | opentelemetry-exporter-otlp-proto-grpc==1.11.1 7 | opentelemetry-exporter-otlp-proto-http==1.11.1 8 | opentelemetry-exporter-prometheus==1.12.0rc1 9 | opentelemetry-instrumentation==0.32b0 10 | opentelemetry-instrumentation-botocore==0.32b0 11 | opentelemetry-instrumentation-dbapi==0.32b0 12 | opentelemetry-instrumentation-flask==0.32b0 13 | opentelemetry-instrumentation-psycopg2==0.32b0 14 | opentelemetry-instrumentation-wsgi==0.32b0 15 | opentelemetry-propagator-aws-xray==1.0.1 16 | opentelemetry-proto==1.11.1 17 | opentelemetry-sdk==1.12.0rc2 18 | opentelemetry-sdk-extension-aws==2.0.1 19 | opentelemetry-semantic-conventions==0.32b0 20 | opentelemetry-util-http==0.32b0 21 | prometheus-flask-exporter==0.20.2 22 | Werkzeug==2.2.2 23 | -------------------------------------------------------------------------------- /PetAdoptions/petlistadoptions-go/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.23 as builder 2 | WORKDIR /go/src/app 3 | COPY . . 4 | ENV GOPROXY=https://goproxy.io,direct 5 | RUN go get . 6 | RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . 7 | 8 | FROM alpine:latest 9 | WORKDIR /app 10 | RUN apk --no-cache add ca-certificates 11 | COPY --from=builder /go/src/app/app . 12 | EXPOSE 80 13 | CMD ["./app"] 14 | -------------------------------------------------------------------------------- /PetAdoptions/petlistadoptions-go/benchmark/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rust:latest as builder 2 | WORKDIR /app 3 | RUN 4 | COPY . . 5 | RUN cargo install drill 6 | CMD ["./benchmark.sh"] 7 | -------------------------------------------------------------------------------- /PetAdoptions/petlistadoptions-go/benchmark/README.md: -------------------------------------------------------------------------------- 1 | ## Drill for PetListAdoptions 2 | 3 | Using [drill](https://github.com/fcsonline/drill), this allows to generate 4 | traffic in the PetSite EKS cluster or locally in dev, without spinning ECS 5 | traffic generator. 6 | 7 | This can be useful to test all APIs or boost traffic for Application Signals. 8 | 9 | ### (Optional) Pick your benchmark environment 10 | 11 | In the `benchmark.yaml` file, change the base URL to your PetListAdoptions ALB 12 | endpoint if you are not testing it locally as the default is local. 13 | 14 | ```yaml 15 | concurrency: 4 16 | base: "http://Servic-lista-[...].eu-central-1.elb.amazonaws.com" 17 | ``` 18 | 19 | ### Running locally 20 | 21 | [Install drill](https://github.com/fcsonline/drill?tab=readme-ov-file#install) 22 | and run 23 | 24 | ```bash 25 | drill --benchmark benchmark.yaml 26 | ``` 27 | 28 | ### Running in EKS 29 | 30 | 1. Authenticate against your EKS cluster 31 | 32 | ```bash 33 | aws eks update-kubeconfig --name PetSite --region 34 | ``` 35 | 36 | 2. Create an ECR image `drill-petlistadoptions` 37 | 38 | 3. Build and push 39 | 40 | ```bash 41 | aws ecr get-login-password --region | docker login --username AWS --password-stdin .dkr.ecr..amazonaws.com 42 | docker buildx build -t drill-petlistadoptions . --platform=linux/amd64 43 | docker tag drill-petlistadoptions:latest .dkr.ecr..amazonaws.com/drill-petlistadoptions:latest 44 | docker push .dkr.ecr..amazonaws.com/drill-petlistadoptions:latest 45 | ``` 46 | 47 | 4. Run in EKS 48 | 49 | ```bash 50 | kubectl run -it drill-petlistadoptions --image .dkr.ecr..amazonaws.com/drill-petlistadoptions:latest 51 | ``` 52 | 53 | -------------------------------------------------------------------------------- /PetAdoptions/petlistadoptions-go/benchmark/benchmark.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | while true 4 | do 5 | drill -s --benchmark benchmark.yaml 6 | sleep 1 7 | done 8 | -------------------------------------------------------------------------------- /PetAdoptions/petlistadoptions-go/benchmark/benchmark.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | concurrency: 5 3 | base: "http://localhost:80" 4 | iterations: 100 5 | rampup: 2 6 | 7 | plan: 8 | - name: Health check 9 | request: 10 | url: /health/status 11 | method: GET 12 | 13 | - name: List adoptions 14 | request: 15 | url: /api/adoptionlist/ 16 | method: GET 17 | 18 | - name: Get Prometheus metrics 19 | request: 20 | url: /metrics 21 | method: GET 22 | 23 | - name: List adoptions 24 | request: 25 | url: /api/adoptionlist/ 26 | method: GET 27 | -------------------------------------------------------------------------------- /PetAdoptions/petlistadoptions-go/petlistadoptions/endpoint.go: -------------------------------------------------------------------------------- 1 | package petlistadoptions 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/go-kit/kit/endpoint" 7 | ) 8 | 9 | type Endpoints struct { 10 | HealthCheckEndpoint endpoint.Endpoint 11 | ListAdoptionsEndpoint endpoint.Endpoint 12 | } 13 | 14 | func MakeEndpoints(s Service) Endpoints { 15 | return Endpoints{ 16 | HealthCheckEndpoint: makeHealthCheckEndpoint(s), 17 | ListAdoptionsEndpoint: makeListAdoptionsEndpoint(s), 18 | } 19 | } 20 | 21 | func makeHealthCheckEndpoint(s Service) endpoint.Endpoint { 22 | return func(ctx context.Context, _ interface{}) (interface{}, error) { 23 | return s.HealthCheck(ctx) 24 | } 25 | } 26 | 27 | func makeListAdoptionsEndpoint(s Service) endpoint.Endpoint { 28 | return func(ctx context.Context, request interface{}) (interface{}, error) { 29 | return s.ListAdoptions(ctx) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /PetAdoptions/petlistadoptions-go/petlistadoptions/service.go: -------------------------------------------------------------------------------- 1 | package petlistadoptions 2 | 3 | import ( 4 | "context" 5 | "time" 6 | 7 | "github.com/go-kit/log" 8 | "github.com/go-kit/log/level" 9 | ) 10 | 11 | type Adoption struct { 12 | TransactionID string `json:"transactionid,omitempty"` 13 | AdoptionDate time.Time `json:"adoptiondate,omitempty"` 14 | Availability string `json:"availability,omitempty"` 15 | CutenessRate string `json:"cuteness_rate,omitempty"` 16 | PetColor string `json:"petcolor,omitempty"` 17 | PetID string `json:"petid,omitempty"` 18 | PetType string `json:"pettype,omitempty"` 19 | PetURL string `json:"peturl,omitempty"` 20 | Price string `json:"price,omitempty"` 21 | } 22 | 23 | // links endpoints to transport 24 | type Service interface { 25 | HealthCheck(ctx context.Context) (string, error) 26 | ListAdoptions(ctx context.Context) ([]Adoption, error) 27 | } 28 | 29 | // object that handles the logic and complies with interface 30 | type service struct { 31 | logger log.Logger 32 | repository Repository 33 | petSearchURL string 34 | } 35 | 36 | // inject dependencies into core logic 37 | func NewService(logger log.Logger, rep Repository, petSearchURL string) Service { 38 | return &service{ 39 | logger: logger, 40 | repository: rep, 41 | petSearchURL: petSearchURL, 42 | } 43 | } 44 | 45 | func (s service) HealthCheck(ctx context.Context) (string, error) { 46 | return "alive", nil 47 | } 48 | 49 | func (s service) ListAdoptions(ctx context.Context) ([]Adoption, error) { 50 | 51 | res, err := s.repository.GetLatestAdoptions(ctx, s.petSearchURL) 52 | 53 | if err != nil { 54 | logger := log.With(s.logger, "method", "ListAdoptions") 55 | level.Error(logger).Log("err", err) 56 | } 57 | 58 | return res, err 59 | } 60 | -------------------------------------------------------------------------------- /PetAdoptions/petsearch-java/.gitignore: -------------------------------------------------------------------------------- 1 | /.gradle/ 2 | /.idea/ 3 | /build/ 4 | -------------------------------------------------------------------------------- /PetAdoptions/petsearch-java/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gradle:7.3-jdk17 as build 2 | 3 | WORKDIR /app 4 | COPY ./build.gradle ./build.gradle 5 | COPY ./src ./src 6 | COPY ./settings.gradle ./settings.gradle 7 | 8 | ENV GRADLE_OPTS "-Dorg.gradle.daemon=false" 9 | RUN gradle build -DexcludeTags='integration' 10 | 11 | FROM amazoncorretto:17-alpine 12 | WORKDIR /app 13 | 14 | ADD https://github.com/aws-observability/aws-otel-java-instrumentation/releases/download/v1.21.1/aws-opentelemetry-agent.jar /app/aws-opentelemetry-agent.jar 15 | ENV JAVA_TOOL_OPTIONS "-javaagent:/app/aws-opentelemetry-agent.jar" 16 | 17 | ARG JAR_FILE=build/libs/\*.jar 18 | COPY --from=build /app/${JAR_FILE} ./app.jar 19 | 20 | # OpenTelemetry agent configuration 21 | ENV OTEL_TRACES_SAMPLER "always_on" 22 | ENV OTEL_PROPAGATORS "tracecontext,baggage,xray" 23 | ENV OTEL_RESOURCE_ATTRIBUTES "service.name=PetSearch" 24 | ENV OTEL_IMR_EXPORT_INTERVAL "10000" 25 | ENV OTEL_EXPORTER_OTLP_ENDPOINT "http://localhost:4317" 26 | 27 | ENTRYPOINT ["java","-jar","/app/app.jar"] 28 | -------------------------------------------------------------------------------- /PetAdoptions/petsearch-java/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/one-observability-demo/396cb484bde89fbe3581338d9eb33e5769f58f4c/PetAdoptions/petsearch-java/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /PetAdoptions/petsearch-java/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /PetAdoptions/petsearch-java/manual-instrumentation-complete/src/main/java/ca/petsearch/Application.java: -------------------------------------------------------------------------------- 1 | package ca.petsearch; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Application { 8 | public static void main(String[] args) { 9 | SpringApplication.run(Application.class, args); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /PetAdoptions/petsearch-java/manual-instrumentation-complete/src/main/java/ca/petsearch/ApplicationFilter.java: -------------------------------------------------------------------------------- 1 | package ca.petsearch; 2 | 3 | import org.springframework.web.util.ContentCachingResponseWrapper; 4 | 5 | import javax.servlet.*; 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | import java.io.IOException; 9 | 10 | public class ApplicationFilter implements Filter { 11 | 12 | private final MetricEmitter metricEmitter; 13 | 14 | public ApplicationFilter(MetricEmitter metricEmitter) { 15 | this.metricEmitter = metricEmitter; 16 | } 17 | 18 | @Override 19 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 20 | 21 | long requestStartTime = System.currentTimeMillis(); 22 | 23 | ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper((HttpServletResponse) response); 24 | 25 | chain.doFilter(request, responseWrapper); 26 | 27 | int loadSize = responseWrapper.getContentSize(); 28 | 29 | responseWrapper.copyBodyToResponse(); 30 | 31 | String statusCode = String.valueOf(((HttpServletResponse)response).getStatus()); 32 | 33 | metricEmitter.emitReturnTimeMetric( 34 | System.currentTimeMillis() - requestStartTime, ((HttpServletRequest)request).getServletPath(), statusCode); 35 | 36 | 37 | metricEmitter.emitBytesSentMetric(loadSize, ((HttpServletRequest)request).getServletPath(), statusCode); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /PetAdoptions/petsearch-java/manual-instrumentation-complete/src/main/java/ca/petsearch/PseudoRandomNumberGenerator.java: -------------------------------------------------------------------------------- 1 | package ca.petsearch; 2 | 3 | public class PseudoRandomNumberGenerator implements RandomNumberGenerator { 4 | 5 | @Override 6 | public int nextNonNegativeInt(int max) { 7 | if (max < 0) throw new RuntimeException("Wrong parameter value"); 8 | return (int) (Math.random() * max); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /PetAdoptions/petsearch-java/manual-instrumentation-complete/src/main/java/ca/petsearch/RandomNumberGenerator.java: -------------------------------------------------------------------------------- 1 | package ca.petsearch; 2 | 3 | public interface RandomNumberGenerator { 4 | int nextNonNegativeInt(int max); 5 | } 6 | -------------------------------------------------------------------------------- /PetAdoptions/petsearch-java/manual-instrumentation-complete/src/main/java/ca/petsearch/TracingLogFilter.java: -------------------------------------------------------------------------------- 1 | package ca.petsearch; 2 | 3 | import ch.qos.logback.classic.spi.ILoggingEvent; 4 | import ch.qos.logback.core.filter.Filter; 5 | import ch.qos.logback.core.spi.FilterReply; 6 | import io.opentelemetry.api.trace.Span; 7 | import org.slf4j.MDC; 8 | 9 | public class TracingLogFilter extends Filter { 10 | @Override 11 | public FilterReply decide(ILoggingEvent event) { 12 | Span span = Span.current(); 13 | 14 | if (span == Span.getInvalid()) { 15 | MDC.remove("AWS-XRAY-TRACE-ID"); 16 | return FilterReply.ACCEPT; 17 | } 18 | 19 | String traceId = span.getSpanContext().getTraceId(); 20 | String entityId = span.getSpanContext().getSpanId(); 21 | 22 | String traceLog = "1-" 23 | + traceId.substring(0, 8) 24 | + "-" 25 | + traceId.substring(8) 26 | + "@" 27 | + entityId; 28 | MDC.put("AWS-XRAY-TRACE-ID", traceLog); 29 | 30 | return FilterReply.ACCEPT; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /PetAdoptions/petsearch-java/manual-instrumentation-complete/src/main/java/ca/petsearch/controllers/HealthController.java: -------------------------------------------------------------------------------- 1 | package ca.petsearch.controllers; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RestController 9 | public class HealthController { 10 | 11 | Logger logger = LoggerFactory.getLogger(HealthController.class); 12 | 13 | @GetMapping("/health/status") 14 | public String status(){ 15 | logger.info("Testing"); 16 | return "Alive"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /PetAdoptions/petsearch-java/manual-instrumentation-complete/src/main/java/ca/petsearch/controllers/Pet.java: -------------------------------------------------------------------------------- 1 | package ca.petsearch.controllers; 2 | 3 | public class Pet { 4 | 5 | private final String petid; 6 | private final String availability; 7 | private final String cuteness_rate; 8 | private final String petcolor; 9 | private final String pettype; 10 | private final String price; 11 | private final String peturl; 12 | 13 | public Pet( 14 | String petid, 15 | String availability, 16 | String cuteness_rate, 17 | String petcolor, 18 | String pettype, 19 | String price, 20 | String peturl 21 | ) { 22 | this.petid = petid; 23 | this.availability = availability; 24 | this.cuteness_rate = cuteness_rate; 25 | this.petcolor = petcolor; 26 | this.pettype = pettype; 27 | this.price = price; 28 | this.peturl = peturl; 29 | } 30 | 31 | public String getPetid() { 32 | return petid; 33 | } 34 | public String getAvailability() { 35 | return availability; 36 | } 37 | public String getCuteness_rate() { 38 | return cuteness_rate; 39 | } 40 | public String getPetcolor() { 41 | return petcolor; 42 | } 43 | public String getPettype() { 44 | return pettype; 45 | } 46 | public String getPrice() { 47 | return price; 48 | } 49 | public String getPeturl() { 50 | return peturl; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /PetAdoptions/petsearch-java/manual-instrumentation-complete/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: petstore 4 | cloud: 5 | aws: 6 | region: 7 | static: eu-west-1 8 | auto: false 9 | server: 10 | port: 80 -------------------------------------------------------------------------------- /PetAdoptions/petsearch-java/manual-instrumentation-complete/src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | yyyy-MM-dd' 'HH:mm:ss.SSS 9 | true 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /PetAdoptions/petsearch-java/manual-instrumentation-complete/src/test/java/ca/petsearch/PseudoRandomNumberGeneratorTest.java: -------------------------------------------------------------------------------- 1 | package ca.petsearch; 2 | 3 | import io.vavr.CheckedFunction1; 4 | import io.vavr.test.Arbitrary; 5 | import io.vavr.test.CheckResult; 6 | import io.vavr.test.Property; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | import static org.assertj.core.api.Assertions.assertThat; 12 | 13 | public class PseudoRandomNumberGeneratorTest { 14 | 15 | @Test 16 | public void testNonNegativeNumber() { 17 | PseudoRandomNumberGenerator generator = new PseudoRandomNumberGenerator(); 18 | 19 | Arbitrary nonNegative = Arbitrary.integer() 20 | .filter(i -> i >= 0); 21 | 22 | CheckedFunction1 mustBeNonNegative 23 | = i -> { 24 | int n = generator.nextNonNegativeInt(i); 25 | return n < i && n >= 0; 26 | }; 27 | 28 | CheckResult result = Property 29 | .def("Every random number need to be non-negative and smaller than the given parameter") 30 | .forAll(nonNegative) 31 | .suchThat(mustBeNonNegative) 32 | .check(10_000, 100); 33 | 34 | result.assertIsSatisfied(); 35 | } 36 | 37 | @Test 38 | public void testRandomDistribution() { 39 | PseudoRandomNumberGenerator generator = new PseudoRandomNumberGenerator(); 40 | Map distribution = new HashMap<>(); 41 | 42 | for (int i = 0; i < 10000; i++) { 43 | int generated = generator.nextNonNegativeInt(10); 44 | if (distribution.containsKey(generated)) { 45 | distribution.put(generated, distribution.get(generated) + 1); 46 | } else { 47 | distribution.put(generated, 1); 48 | } 49 | } 50 | 51 | assertThat(distribution.keySet().size()).isGreaterThanOrEqualTo(5).isLessThanOrEqualTo(10); 52 | assertThat(distribution.get(3)).isGreaterThanOrEqualTo(900).isLessThanOrEqualTo(1100); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /PetAdoptions/petsearch-java/manual-instrumentation-complete/src/test/resources/application-test.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | profiles: test, default 3 | main: 4 | allow-bean-definition-overriding: true 5 | cloud: 6 | aws: 7 | region: 8 | static: eu-central-1 9 | auto: false 10 | stack: 11 | auto: false 12 | credentials: 13 | accessKey: ABC 14 | secretKey: XYZ -------------------------------------------------------------------------------- /PetAdoptions/petsearch-java/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'pet-search' 2 | 3 | -------------------------------------------------------------------------------- /PetAdoptions/petsearch-java/src/main/java/ca/petsearch/Application.java: -------------------------------------------------------------------------------- 1 | package ca.petsearch; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Application { 8 | public static void main(String[] args) { 9 | SpringApplication.run(Application.class, args); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /PetAdoptions/petsearch-java/src/main/java/ca/petsearch/ApplicationFilter.java: -------------------------------------------------------------------------------- 1 | package ca.petsearch; 2 | 3 | import org.springframework.web.util.ContentCachingResponseWrapper; 4 | 5 | import javax.servlet.*; 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | import java.io.IOException; 9 | 10 | public class ApplicationFilter implements Filter { 11 | 12 | private final MetricEmitter metricEmitter; 13 | 14 | public ApplicationFilter(MetricEmitter metricEmitter) { 15 | this.metricEmitter = metricEmitter; 16 | } 17 | 18 | @Override 19 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 20 | 21 | long requestStartTime = System.currentTimeMillis(); 22 | 23 | ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper((HttpServletResponse) response); 24 | 25 | chain.doFilter(request, responseWrapper); 26 | 27 | int loadSize = responseWrapper.getContentSize(); 28 | 29 | responseWrapper.copyBodyToResponse(); 30 | 31 | String statusCode = String.valueOf(((HttpServletResponse)response).getStatus()); 32 | 33 | metricEmitter.emitReturnTimeMetric( 34 | System.currentTimeMillis() - requestStartTime, ((HttpServletRequest)request).getServletPath(), statusCode); 35 | 36 | 37 | metricEmitter.emitBytesSentMetric(loadSize, ((HttpServletRequest)request).getServletPath(), statusCode); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /PetAdoptions/petsearch-java/src/main/java/ca/petsearch/PseudoRandomNumberGenerator.java: -------------------------------------------------------------------------------- 1 | package ca.petsearch; 2 | 3 | public class PseudoRandomNumberGenerator implements RandomNumberGenerator { 4 | 5 | @Override 6 | public int nextNonNegativeInt(int max) { 7 | if (max < 0) throw new RuntimeException("Wrong parameter value"); 8 | return (int) (Math.random() * max); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /PetAdoptions/petsearch-java/src/main/java/ca/petsearch/RandomNumberGenerator.java: -------------------------------------------------------------------------------- 1 | package ca.petsearch; 2 | 3 | public interface RandomNumberGenerator { 4 | int nextNonNegativeInt(int max); 5 | } 6 | -------------------------------------------------------------------------------- /PetAdoptions/petsearch-java/src/main/java/ca/petsearch/controllers/HealthController.java: -------------------------------------------------------------------------------- 1 | package ca.petsearch.controllers; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | @RestController 7 | public class HealthController { 8 | @GetMapping("/health/status") 9 | public String status(){ 10 | return "Alive"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /PetAdoptions/petsearch-java/src/main/java/ca/petsearch/controllers/Pet.java: -------------------------------------------------------------------------------- 1 | package ca.petsearch.controllers; 2 | 3 | public class Pet { 4 | 5 | private final String petid; 6 | private final String availability; 7 | private final String cuteness_rate; 8 | private final String petcolor; 9 | private final String pettype; 10 | private final String price; 11 | private final String peturl; 12 | 13 | public Pet( 14 | String petid, 15 | String availability, 16 | String cuteness_rate, 17 | String petcolor, 18 | String pettype, 19 | String price, 20 | String peturl 21 | ) { 22 | this.petid = petid; 23 | this.availability = availability; 24 | this.cuteness_rate = cuteness_rate; 25 | this.petcolor = petcolor; 26 | this.pettype = pettype; 27 | this.price = price; 28 | this.peturl = peturl; 29 | } 30 | 31 | public String getPetid() { 32 | return petid; 33 | } 34 | public String getAvailability() { 35 | return availability; 36 | } 37 | public String getCuteness_rate() { 38 | return cuteness_rate; 39 | } 40 | public String getPetcolor() { 41 | return petcolor; 42 | } 43 | public String getPettype() { 44 | return pettype; 45 | } 46 | public String getPrice() { 47 | return price; 48 | } 49 | public String getPeturl() { 50 | return peturl; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /PetAdoptions/petsearch-java/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: petstore 4 | cloud: 5 | aws: 6 | region: 7 | static: eu-west-1 8 | auto: false 9 | server: 10 | port: 80 -------------------------------------------------------------------------------- /PetAdoptions/petsearch-java/src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | yyyy-MM-dd' 'HH:mm:ss.SSS 8 | true 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /PetAdoptions/petsite/.dockerignore: -------------------------------------------------------------------------------- 1 | **/.classpath 2 | **/.dockerignore 3 | **/.env 4 | **/.git 5 | **/.gitignore 6 | **/.project 7 | **/.settings 8 | **/.toolstarget 9 | **/.vs 10 | **/.vscode 11 | **/*.*proj.user 12 | **/*.dbmdl 13 | **/*.jfm 14 | **/azds.yaml 15 | **/bin 16 | **/charts 17 | **/docker-compose* 18 | **/Dockerfile* 19 | **/node_modules 20 | **/npm-debug.log 21 | **/obj 22 | **/secrets.dev.yaml 23 | **/values.dev.yaml 24 | LICENSE 25 | README.md -------------------------------------------------------------------------------- /PetAdoptions/petsite/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to find out which attributes exist for C# debugging 3 | // Use hover for the description of the existing attributes 4 | // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": ".NET Core Launch (web)", 9 | "type": "coreclr", 10 | "request": "launch", 11 | "preLaunchTask": "build", 12 | // If you have changed target frameworks, make sure to update the program path. 13 | "program": "${workspaceFolder}/petsite/bin/Debug/netcoreapp3.0/PetSite.dll", 14 | "args": [], 15 | "cwd": "${workspaceFolder}/petsite", 16 | "stopAtEntry": false, 17 | // Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser 18 | "serverReadyAction": { 19 | "action": "openExternally", 20 | "pattern": "^\\s*Now listening on:\\s+(https?://\\S+)" 21 | }, 22 | "env": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | }, 25 | "sourceFileMap": { 26 | "/Views": "${workspaceFolder}/Views" 27 | } 28 | }, 29 | { 30 | "name": ".NET Core Attach", 31 | "type": "coreclr", 32 | "request": "attach", 33 | "processId": "${command:pickProcess}" 34 | } 35 | ] 36 | } -------------------------------------------------------------------------------- /PetAdoptions/petsite/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "build", 6 | "command": "dotnet", 7 | "type": "process", 8 | "args": [ 9 | "build", 10 | "${workspaceFolder}/petsite/PetSite.csproj", 11 | "/property:GenerateFullPaths=true", 12 | "/consoleloggerparameters:NoSummary" 13 | ], 14 | "problemMatcher": "$msCompile" 15 | }, 16 | { 17 | "label": "publish", 18 | "command": "dotnet", 19 | "type": "process", 20 | "args": [ 21 | "publish", 22 | "${workspaceFolder}/petsite/PetSite.csproj", 23 | "/property:GenerateFullPaths=true", 24 | "/consoleloggerparameters:NoSummary" 25 | ], 26 | "problemMatcher": "$msCompile" 27 | }, 28 | { 29 | "label": "watch", 30 | "command": "dotnet", 31 | "type": "process", 32 | "args": [ 33 | "watch", 34 | "run", 35 | "${workspaceFolder}/petsite/PetSite.csproj", 36 | "/property:GenerateFullPaths=true", 37 | "/consoleloggerparameters:NoSummary" 38 | ], 39 | "problemMatcher": "$msCompile" 40 | } 41 | ] 42 | } -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29503.13 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PetSite", "petsite\PetSite.csproj", "{3CF15FF6-D1C6-42EC-84E7-082FA8E5339F}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3CF15FF6-D1C6-42EC-84E7-082FA8E5339F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {3CF15FF6-D1C6-42EC-84E7-082FA8E5339F}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {3CF15FF6-D1C6-42EC-84E7-082FA8E5339F}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {3CF15FF6-D1C6-42EC-84E7-082FA8E5339F}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {45D80372-F05E-421A-BEDF-01DE6C4F969E} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/Controllers/HealthController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace PetSite.Controllers 4 | { 5 | public class HealthController : Controller 6 | { 7 | // GET 8 | [HttpGet("/health/status")] 9 | public string Status() 10 | { 11 | return "Alive"; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/Controllers/PetFoodController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.Extensions.Configuration; 3 | using System; 4 | using System.Net.Http; 5 | using System.Threading.Tasks; 6 | using Amazon.XRay.Recorder.Core; 7 | using Amazon.XRay.Recorder.Handlers.System.Net; 8 | using Amazon.XRay.Recorder.Handlers.AwsSdk; 9 | 10 | 11 | namespace PetSite.Controllers 12 | { 13 | public class PetFoodController : Controller 14 | { 15 | 16 | private static HttpClient httpClient; 17 | private IConfiguration _configuration; 18 | 19 | public PetFoodController(IConfiguration configuration) 20 | 21 | { 22 | AWSSDKHandler.RegisterXRayForAllServices(); 23 | } 24 | 25 | [HttpGet("/petfood")] 26 | public async Task Index() 27 | { 28 | // X-Ray FTW 29 | AWSXRayRecorder.Instance.BeginSubsegment("Calling PetFood"); 30 | Console.WriteLine($"[{AWSXRayRecorder.Instance.GetEntity().TraceId}][{AWSXRayRecorder.Instance.TraceContext.GetEntity().RootSegment.TraceId}] - Calling PetFood"); 31 | 32 | // Get our data from petfood 33 | var httpClient = new HttpClient(new HttpClientXRayTracingHandler(new HttpClientHandler())); 34 | string result = await httpClient.GetStringAsync("http://petfood"); 35 | 36 | // Close the segment 37 | AWSXRayRecorder.Instance.EndSubsegment(); 38 | 39 | // Return the result! 40 | return result; 41 | } 42 | 43 | [HttpGet("/petfood-metric/{entityId}/{value}")] 44 | public async Task PetFoodMetric(string entityId, float value) 45 | { 46 | // X-Ray FTW 47 | AWSXRayRecorder.Instance.BeginSubsegment("Calling PetFood metric"); 48 | Console.WriteLine("Calling: " + "http://petfood-metric/metric/" + entityId + "/" + value.ToString()); 49 | Console.WriteLine($"[{AWSXRayRecorder.Instance.GetEntity().TraceId}][{AWSXRayRecorder.Instance.TraceContext.GetEntity().RootSegment.TraceId}] - Calling PetFood metric"); 50 | 51 | var httpClient = new HttpClient(new HttpClientXRayTracingHandler(new HttpClientHandler())); 52 | string result = await httpClient.GetStringAsync("http://petfood-metric/metric/" + entityId + "/" + value.ToString()); 53 | 54 | AWSXRayRecorder.Instance.AddAnnotation("entityId", entityId); 55 | AWSXRayRecorder.Instance.AddAnnotation("value", value.ToString()); 56 | AWSXRayRecorder.Instance.EndSubsegment(); 57 | 58 | return result; 59 | } 60 | 61 | } 62 | } -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/Controllers/PetHistoryController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.Extensions.Configuration; 3 | using System; 4 | using System.Net.Http; 5 | using System.Threading.Tasks; 6 | using Amazon.XRay.Recorder.Core; 7 | using Amazon.XRay.Recorder.Handlers.System.Net; 8 | using Amazon.XRay.Recorder.Handlers.AwsSdk; 9 | using Microsoft.Extensions.Logging; 10 | 11 | namespace PetSite.Controllers; 12 | 13 | public class PetHistoryController : Controller 14 | { 15 | private IConfiguration _configuration; 16 | private readonly ILogger _logger; 17 | private static HttpClient _httpClient; 18 | private static string _pethistoryurl; 19 | 20 | public PetHistoryController(IConfiguration configuration) 21 | { 22 | AWSSDKHandler.RegisterXRayForAllServices(); 23 | _configuration = configuration; 24 | _httpClient = new HttpClient(new HttpClientXRayTracingHandler(new HttpClientHandler())); 25 | 26 | _pethistoryurl = _configuration["pethistoryurl"]; 27 | //string _pethistoryurl = SystemsManagerConfigurationProviderWithReloadExtensions.GetConfiguration(_configuration,"pethistoryurl"); 28 | 29 | } 30 | 31 | /// 32 | /// GET:/pethistory 33 | /// 34 | /// 35 | [HttpGet] 36 | public async Task Index() 37 | { 38 | AWSXRayRecorder.Instance.BeginSubsegment("Calling GetPetAdoptionsHistory"); 39 | ViewData["pethistory"] = await _httpClient.GetStringAsync($"{_pethistoryurl}/api/home/transactions"); 40 | AWSXRayRecorder.Instance.EndSubsegment(); 41 | return View(); 42 | } 43 | 44 | /// 45 | /// DELETE:/deletepetadoptionshistory 46 | /// 47 | /// 48 | [HttpDelete] 49 | public async Task DeletePetAdoptionsHistory() 50 | { 51 | AWSXRayRecorder.Instance.BeginSubsegment("Calling DeletePetAdoptionsHistory"); 52 | ViewData["pethistory"] = await _httpClient.DeleteAsync($"{_pethistoryurl}/api/home/transactions"); 53 | AWSXRayRecorder.Instance.EndSubsegment(); 54 | return View("Index"); 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/Controllers/PetListAdoptionsController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.Extensions.Logging; 7 | using PetSite.Models; 8 | using Amazon.XRay.Recorder.Handlers.AwsSdk; 9 | using System.Net.Http; 10 | using Amazon.XRay.Recorder.Handlers.System.Net; 11 | using Amazon.XRay.Recorder.Core; 12 | using System.Text.Json; 13 | using PetSite.ViewModels; 14 | using Microsoft.AspNetCore.Mvc.Rendering; 15 | using Microsoft.Extensions.Configuration; 16 | 17 | namespace PetSite.Controllers 18 | { 19 | public class PetListAdoptionsController : Controller 20 | { 21 | private static HttpClient _httpClient; 22 | private IConfiguration _configuration; 23 | 24 | public PetListAdoptionsController(IConfiguration configuration) 25 | { 26 | _configuration = configuration; 27 | AWSSDKHandler.RegisterXRayForAllServices(); 28 | 29 | _httpClient = new HttpClient(new HttpClientXRayTracingHandler(new HttpClientHandler())); 30 | } 31 | 32 | // GET 33 | public async Task Index() 34 | { 35 | AWSXRayRecorder.Instance.BeginSubsegment("Calling PetListAdoptions"); 36 | 37 | Console.WriteLine($"[{AWSXRayRecorder.Instance.GetEntity().TraceId}][{AWSXRayRecorder.Instance.TraceContext.GetEntity().RootSegment.TraceId}] - Calling PetListAdoptions API"); 38 | 39 | string result; 40 | 41 | List Pets = new List(); 42 | 43 | try 44 | { 45 | //string petlistadoptionsurl = _configuration["petlistadoptionsurl"]; 46 | string petlistadoptionsurl = SystemsManagerConfigurationProviderWithReloadExtensions.GetConfiguration(_configuration,"petlistadoptionsurl"); 47 | 48 | 49 | result = await _httpClient.GetStringAsync($"{petlistadoptionsurl}"); 50 | Pets = JsonSerializer.Deserialize>(result); 51 | } 52 | catch (Exception e) 53 | { 54 | AWSXRayRecorder.Instance.AddException(e); 55 | throw e; 56 | } 57 | finally 58 | { 59 | AWSXRayRecorder.Instance.EndSubsegment(); 60 | } 61 | 62 | return View(Pets); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/aspnet:7.0-bullseye-slim-amd64 AS base 2 | WORKDIR /app 3 | EXPOSE 80 4 | EXPOSE 443 5 | 6 | FROM mcr.microsoft.com/dotnet/sdk:7.0-bullseye-slim-amd64 AS build 7 | WORKDIR /src 8 | COPY . . 9 | RUN dotnet restore "PetSite.csproj" 10 | RUN dotnet build "PetSite.csproj" -c Release -o /app/build 11 | 12 | FROM build AS publish 13 | RUN dotnet publish "PetSite.csproj" -c Release -o /app/publish 14 | 15 | FROM base AS final 16 | WORKDIR /app 17 | #ENV AWS_XRAY_DAEMON_ADDRESS=xray-service.default 18 | COPY --from=publish /app/publish . 19 | ENTRYPOINT ["dotnet", "PetSite.dll"] 20 | -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/Models/ErrorViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PetSite.Models 4 | { 5 | public class ErrorViewModel 6 | { 7 | public string RequestId { get; set; } 8 | 9 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Amazon.Extensions.NETCore.Setup; 3 | using Microsoft.AspNetCore.Hosting; 4 | using Microsoft.Extensions.Configuration; 5 | using Microsoft.Extensions.Hosting; 6 | using Prometheus.DotNetRuntime; 7 | 8 | namespace PetSite 9 | { 10 | public class Program 11 | { 12 | public static void Main(string[] args) 13 | { 14 | // Sets default settings to collect dotnet runtime specific metrics 15 | DotNetRuntimeStatsBuilder.Default().StartCollecting(); 16 | 17 | //You can also set the specifics on what metrics you want to collect as below 18 | // DotNetRuntimeStatsBuilder.Customize() 19 | // .WithThreadPoolSchedulingStats() 20 | // .WithContentionStats() 21 | // .WithGcStats() 22 | // .WithJitStats() 23 | // .WithThreadPoolStats() 24 | // .WithErrorHandler(ex => Console.WriteLine("ERROR: " + ex.ToString())) 25 | // //.WithDebuggingMetrics(true); 26 | // .StartCollecting(); 27 | 28 | CreateHostBuilder(args).Build().Run(); 29 | } 30 | 31 | public static IHostBuilder CreateHostBuilder(string[] args) => 32 | Host.CreateDefaultBuilder(args) 33 | .ConfigureAppConfiguration((hostingContext, config) => 34 | { 35 | var env = hostingContext.HostingEnvironment; 36 | Console.WriteLine($"ENVIRONMENT NAME IS: {env.EnvironmentName}"); 37 | if (env.EnvironmentName.ToLower() == "development") 38 | config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) 39 | .AddJsonFile($"appsettings.{env.EnvironmentName}.json", 40 | optional: true, reloadOnChange: true); 41 | else 42 | config.AddSystemsManagerWithReload(configureSource => 43 | { 44 | configureSource.Path = "/petstore"; 45 | configureSource.Optional = true; 46 | configureSource.ReloadAfter = TimeSpan.FromMinutes(5); 47 | }); 48 | }) 49 | .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }); 50 | } 51 | } -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:55730", 7 | "sslPort": 44347 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "PetSite": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "http://localhost:5000" 25 | }, 26 | "Docker": { 27 | "commandName": "Docker", 28 | "launchBrowser": true, 29 | "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}", 30 | "environmentVariables": { 31 | "ASPNETCORE_URLS": "https://+:443;http://+:80", 32 | "ASPNETCORE_HTTPS_PORT": "44348", 33 | "AWS_XRAY_DAEMON_ADDRESS":"xray-service:default" 34 | }, 35 | "httpPort": 55731, 36 | "useSSL": true, 37 | "sslPort": 44348 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/PutParams.cs: -------------------------------------------------------------------------------- 1 | namespace PetSite 2 | { 3 | public class PutParams 4 | { 5 | public string petid { get; set; } 6 | public string pettype { get; set; } 7 | } 8 | } -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/SearchParams.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace PetSite 7 | { 8 | public class SearchParams 9 | { 10 | public string pettype { get; set; } 11 | public string petid { get; set; } 12 | public string petcolor { get; set; } 13 | 14 | public string petavailability { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Builder; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Microsoft.AspNetCore.HttpsPolicy; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.DependencyInjection; 10 | using Microsoft.Extensions.Hosting; 11 | using Prometheus; 12 | 13 | namespace PetSite 14 | { 15 | public class Startup 16 | { 17 | public Startup(IConfiguration configuration) 18 | { 19 | Configuration = configuration; 20 | new ConfigurationBuilder() 21 | .AddEnvironmentVariables() 22 | .Build(); 23 | } 24 | 25 | public IConfiguration Configuration { get; } 26 | 27 | // This method gets called by the runtime. Use this method to add services to the container. 28 | public void ConfigureServices(IServiceCollection services) 29 | { 30 | services.AddControllersWithViews(); 31 | } 32 | 33 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 34 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 35 | { 36 | app.UseXRay("PetSite", Configuration); 37 | 38 | if (env.IsDevelopment()) 39 | { 40 | app.UseDeveloperExceptionPage(); 41 | } 42 | else 43 | { 44 | app.UseExceptionHandler("/Home/Error"); 45 | app.UseHsts(); 46 | } 47 | 48 | app.UseHttpsRedirection(); 49 | app.UseStaticFiles(); 50 | 51 | app.UseRouting(); 52 | app.UseHttpMetrics(); 53 | 54 | app.UseAuthorization(); 55 | 56 | app.UseEndpoints(endpoints => 57 | { 58 | endpoints.MapControllerRoute( 59 | name: "default", 60 | pattern: "{controller=Home}/{action=Index}/{id?}"); 61 | endpoints.MapMetrics(); 62 | }); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/ViewModels/Pets.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc.Rendering; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace PetSite.ViewModels 8 | { 9 | public class Pet 10 | { 11 | public string pettype { get; set; } 12 | public string petid { get; set; } 13 | public string price { get; set; } 14 | public string petcolor { get; set; } 15 | public string cuteness_rate { get; set; } 16 | public string availability { get; set; } 17 | public string image { get; set; } 18 | public string peturl { get; set; } 19 | 20 | public string transactionid { get; set; } 21 | public string adoptiondate { get; set; } 22 | } 23 | 24 | public class Variety 25 | { 26 | public IEnumerable PetTypes; 27 | public IEnumerable PetColors; 28 | 29 | public string SelectedPetType { get; set; } 30 | public string SelectedPetColor { get; set; } 31 | } 32 | 33 | public class PetDetails 34 | { 35 | public List Pets { get; set; } 36 | public Variety Varieties { get; set; } 37 | } 38 | 39 | public class PetFood 40 | { 41 | public string EntityId { get; set; } 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/Views/Home/HouseKeeping.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "House Keeping"; 3 | } 4 | 5 |
6 |
7 | 8 |
9 |
10 | 11 |
12 | 17 |
-------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @using PetSite.ViewModels; 2 | 3 | @{ 4 | ViewData["Title"] = "Home Page"; 5 | @model PetDetails; 6 | } 7 | 8 |
9 |
10 | 11 |
12 |
13 | 14 |
15 |
16 |
17 | 20 | 23 | 24 | 25 |
26 |
27 |
28 | 29 | 30 |
31 | @if (Model.Pets.Any()) 32 | { 33 |
34 | @foreach (var pet in Model.Pets) 35 | { 36 |
37 | 38 |
39 | } 40 |
41 | } 42 | else 43 | { 44 |
45 | NO PETS AVAILABLE WITH THAT SEARCH CONDITION 46 |
47 | } 48 |
-------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/Views/Home/Privacy.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewData["Title"] = "Privacy Policy"; 3 | } 4 |

@ViewData["Title"]

5 | 6 |

Use this page to detail your site's privacy policy.

7 | -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/Views/Payment/Index.cshtml: -------------------------------------------------------------------------------- 1 | 
2 |
3 | 4 |
5 |
6 | 7 |
8 | @if (ViewData["txStatus"].ToString() == "success") 9 | { 10 | 15 | } 16 | else 17 | { 18 | 23 |

Error @ViewData["error"]

24 | } 25 |
-------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/Views/PetHistory/Index.cshtml: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
6 | 7 | @ViewData["pethistory"].ToString() -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/Views/PetListAdoptions/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model List 2 | 3 | @{ 4 | ViewData["Title"] = "Pet Adoption List"; 5 | } 6 | 7 |
8 |
9 | 10 |
11 |
12 | 13 | 14 |
15 | @if (Model.Any()) 16 | { 17 |
18 | @foreach (var pet in Model) 19 | { 20 |
21 | 22 |
23 | } 24 |
25 | } 26 | else 27 | { 28 |
29 | No adoption data retreived 30 |
31 | } 32 |
33 | -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @model ErrorViewModel 2 | @{ 3 | ViewData["Title"] = "Error"; 4 | } 5 | 6 |

Error.

7 |

An error occurred while processing your request.

8 | 9 | @if (Model.ShowRequestId) 10 | { 11 |

12 | Request ID: @Model.RequestId 13 |

14 | } 15 | 16 |

Development Mode

17 |

18 | Swapping to Development environment will display more detailed information about the error that occurred. 19 |

20 |

21 | The Development environment shouldn't be enabled for deployed applications. 22 | It can result in displaying sensitive information from exceptions to end users. 23 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 24 | and restarting the app. 25 |

26 | -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/Views/Shared/_AdoptionItem.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.CodeAnalysis.CSharp.Syntax 2 | @model Pet; 3 | 4 | 5 | 6 |
7 | @Model.pettype-@Model.petcolor 8 |
9 |
10 | @Model.price 11 |
12 |
13 | Adoption Id-@Model.transactionid 14 |
15 |
16 | Adopted on-@Model.adoptiondate 17 |
-------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Html 2 | @using Amazon.SimpleSystemsManagement 3 | @using Amazon.SimpleSystemsManagement.Model 4 | 5 | 6 | 7 | 8 | 9 | @(new HtmlString(new AmazonSimpleSystemsManagementClient().GetParameterAsync(new GetParameterRequest() { Name = "/petstore/rumscript" }).Result.Parameter.Value)) 10 | 11 | 12 | @ViewData["Title"] - Observability PetAdoptions 13 | 14 | 15 | 16 | 17 | 18 |
19 |
20 | 21 |
22 | 41 | 42 |
43 |
44 | @RenderBody() 45 | 46 | 47 |
48 | 49 | 50 | 51 | @RenderSection("Scripts", required: false) 52 | 53 | -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/Views/Shared/_PetItem.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.CodeAnalysis.CSharp.Syntax 2 | @model Pet; 3 | 4 |
5 | 6 | @if (Model.availability == "yes") 7 | { 8 | 9 | } 10 | else 11 | { 12 | Not available 13 | } 14 | 15 |
16 | @Model.pettype-@Model.petcolor 17 |
18 |
19 | @Model.price 20 |
21 | 22 | @for (int i = 0; i < Int32.Parse(Model.cuteness_rate); i++) 23 | { 24 | 25 | } 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
34 | -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/Views/Shared/_ValidationScriptsPartial.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using PetSite 2 | @using PetSite.Models 3 | @using PetSite.ViewModels; 4 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 5 | -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*", 10 | "XRay": { 11 | "AWSXRayPlugins": "EC2Plugin" } 12 | } 13 | -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/bundleconfig.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "outputFileName": "wwwroot/css/site.min.css", 4 | "inputFiles": [ 5 | "wwwroot/css/petstyles.css", 6 | "wwwroot/css/site.css" 7 | ] 8 | }, 9 | { 10 | "outputFileName": "wwwroot/js/site.min.js", 11 | "inputFiles": [ 12 | "wwwroot/js/site.js" 13 | ], 14 | "minify": { 15 | "enabled": true, 16 | "renameLocals": true 17 | }, 18 | "sourceMap": false 19 | } 20 | ] -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/compilerconfig.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "outputFile": "wwwroot/css/shared/components/header/header.css", 4 | "inputFile": "wwwroot/css/shared/components/header/header.scss" 5 | }, 6 | { 7 | "outputFile": "wwwroot/css/orders/orders.component.css", 8 | "inputFile": "wwwroot/css/orders/orders.component.scss" 9 | }, 10 | { 11 | "outputFile": "wwwroot/css/catalog/catalog.component.css", 12 | "inputFile": "wwwroot/css/catalog/catalog.component.scss" 13 | }, 14 | { 15 | "outputFile": "wwwroot/css/basket/basket.component.css", 16 | "inputFile": "wwwroot/css/basket/basket.component.scss" 17 | }, 18 | { 19 | "outputFile": "wwwroot/css/basket/basket-status/basket-status.component.css", 20 | "inputFile": "wwwroot/css/basket/basket-status/basket-status.component.scss" 21 | }, 22 | { 23 | "outputFile": "wwwroot/css/app.component.css", 24 | "inputFile": "wwwroot/css/app.component.scss" 25 | }, 26 | { 27 | "outputFile": "wwwroot/css/_variables.css", 28 | "inputFile": "wwwroot/css/_variables.scss" 29 | }, 30 | { 31 | "outputFile": "wwwroot/css/shared/components/pager/pager.css", 32 | "inputFile": "wwwroot/css/shared/components/pager/pager.scss" 33 | } 34 | ] -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/compilerconfig.json.defaults: -------------------------------------------------------------------------------- 1 | { 2 | "compilers": { 3 | "less": { 4 | "autoPrefix": "", 5 | "cssComb": "none", 6 | "ieCompat": true, 7 | "strictMath": false, 8 | "strictUnits": false, 9 | "relativeUrls": true, 10 | "rootPath": "", 11 | "sourceMapRoot": "", 12 | "sourceMapBasePath": "", 13 | "sourceMap": false 14 | }, 15 | "sass": { 16 | "autoPrefix": "", 17 | "includePath": "", 18 | "indentType": "space", 19 | "indentWidth": 2, 20 | "outputStyle": "nested", 21 | "Precision": 5, 22 | "relativeUrls": true, 23 | "sourceMapRoot": "", 24 | "lineFeed": "", 25 | "sourceMap": false 26 | }, 27 | "stylus": { 28 | "sourceMap": false 29 | }, 30 | "babel": { 31 | "sourceMap": false 32 | }, 33 | "coffeescript": { 34 | "bare": false, 35 | "runtimeMode": "node", 36 | "sourceMap": false 37 | }, 38 | "handlebars": { 39 | "root": "", 40 | "noBOM": false, 41 | "name": "", 42 | "namespace": "", 43 | "knownHelpersOnly": false, 44 | "forcePartial": false, 45 | "knownHelpers": [], 46 | "commonjs": "", 47 | "amd": false, 48 | "sourceMap": false 49 | } 50 | }, 51 | "minifiers": { 52 | "css": { 53 | "enabled": true, 54 | "termSemicolons": true, 55 | "gzip": false 56 | }, 57 | "javascript": { 58 | "enabled": true, 59 | "termSemicolons": true, 60 | "gzip": false 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | /* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification 2 | for details on configuring this project to bundle and minify static web assets. */ 3 | 4 | a.navbar-brand { 5 | white-space: normal; 6 | text-align: center; 7 | word-break: break-all; 8 | } 9 | 10 | /* Provide sufficient contrast against white background */ 11 | a { 12 | color: #19dc91; 13 | } 14 | 15 | .btn-primary { 16 | color: #fff; 17 | background-color: #19dc91; 18 | border-color: #19dc91; 19 | } 20 | 21 | .nav-pills .nav-link.active, .nav-pills .show > .nav-link { 22 | color: #fff; 23 | background-color: #19dc91; 24 | border-color: #19dc91; 25 | } 26 | 27 | /* Sticky footer styles 28 | -------------------------------------------------- */ 29 | html { 30 | font-size: 14px; 31 | } 32 | @media (min-width: 768px) { 33 | html { 34 | font-size: 16px; 35 | } 36 | } 37 | 38 | .border-top { 39 | border-top: 1px solid #e5e5e5; 40 | } 41 | .border-bottom { 42 | border-bottom: 1px solid #e5e5e5; 43 | } 44 | 45 | .box-shadow { 46 | box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05); 47 | } 48 | 49 | button.accept-policy { 50 | font-size: 1rem; 51 | line-height: inherit; 52 | } 53 | 54 | /* Sticky footer styles 55 | -------------------------------------------------- */ 56 | html { 57 | position: relative; 58 | min-height: 100%; 59 | } 60 | 61 | body { 62 | /* Margin bottom by footer height */ 63 | margin-bottom: 60px; 64 | } 65 | .footer { 66 | position: absolute; 67 | bottom: 0; 68 | width: 100%; 69 | white-space: nowrap; 70 | line-height: 60px; /* Vertically center the text there */ 71 | } 72 | -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/one-observability-demo/396cb484bde89fbe3581338d9eb33e5769f58f4c/PetAdoptions/petsite/petsite/wwwroot/favicon.ico -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/wwwroot/images/arrow-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/one-observability-demo/396cb484bde89fbe3581338d9eb33e5769f58f4c/PetAdoptions/petsite/petsite/wwwroot/images/arrow-down.png -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/wwwroot/images/arrow-right.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/wwwroot/images/brand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/one-observability-demo/396cb484bde89fbe3581338d9eb33e5769f58f4c/PetAdoptions/petsite/petsite/wwwroot/images/brand.png -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/wwwroot/images/main_banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/one-observability-demo/396cb484bde89fbe3581338d9eb33e5769f58f4c/PetAdoptions/petsite/petsite/wwwroot/images/main_banner.png -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/wwwroot/images/main_banner_text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/one-observability-demo/396cb484bde89fbe3581338d9eb33e5769f58f4c/PetAdoptions/petsite/petsite/wwwroot/images/main_banner_text.png -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/wwwroot/js/site.js: -------------------------------------------------------------------------------- 1 | // Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification 2 | // for details on configuring this project to bundle and minify static web assets. 3 | 4 | // Write your JavaScript code. 5 | -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/wwwroot/js/site.min.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/one-observability-demo/396cb484bde89fbe3581338d9eb33e5769f58f4c/PetAdoptions/petsite/petsite/wwwroot/js/site.min.js -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/wwwroot/lib/bootstrap/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2018 Twitter, Inc. 4 | Copyright (c) 2011-2018 The Bootstrap Authors 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) .NET Foundation. All rights reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use 4 | these files except in compliance with the License. You may obtain a copy of the 5 | License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software distributed 10 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 11 | CONDITIONS OF ANY KIND, either express or implied. See the License for the 12 | specific language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/wwwroot/lib/jquery-validation/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright Jörn Zaefferer 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /PetAdoptions/petsite/petsite/wwwroot/lib/jquery/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright JS Foundation and other contributors, https://js.foundation/ 2 | 3 | This software consists of voluntary contributions made by many 4 | individuals. For exact contribution history, see the revision history 5 | available at https://github.com/jquery/jquery 6 | 7 | The following license applies to all parts of this software except as 8 | documented below: 9 | 10 | ==== 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining 13 | a copy of this software and associated documentation files (the 14 | "Software"), to deal in the Software without restriction, including 15 | without limitation the rights to use, copy, modify, merge, publish, 16 | distribute, sublicense, and/or sell copies of the Software, and to 17 | permit persons to whom the Software is furnished to do so, subject to 18 | the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be 21 | included in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | ==== 32 | 33 | All files located in the node_modules and external directories are 34 | externally maintained libraries used by this software which have their 35 | own licenses; we recommend you read them, as their terms may differ from 36 | the terms above. 37 | -------------------------------------------------------------------------------- /PetAdoptions/petstatusupdater/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /PetAdoptions/petstatusupdater/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var AWSXRay = require('aws-xray-sdk'); 4 | var AWS = AWSXRay.captureAWS(require('aws-sdk')); 5 | var documentClient = new AWS.DynamoDB.DocumentClient(); 6 | 7 | exports.handler = async function (event, context, callback) { 8 | var payload = JSON.parse(event.body); 9 | 10 | var availability = "yes"; 11 | if (payload.petavailability === undefined) { 12 | availability = "no"; 13 | } 14 | var params = { 15 | TableName: process.env.TABLE_NAME, 16 | Key: { 17 | "pettype": payload.pettype, 18 | "petid": payload.petid 19 | }, 20 | UpdateExpression: "set availability = :r", 21 | ExpressionAttributeValues: { 22 | ":r": availability 23 | }, ReturnValues: "UPDATED_NEW" 24 | }; 25 | 26 | await updatePetadoptionsTable(params); 27 | 28 | console.log("Updated petid: " + payload.petid + ", pettype: " + payload.pettype + ", to availability: " + availability); 29 | return { "statusCode": 200, "body": "success" }; 30 | }; 31 | 32 | async function updatePetadoptionsTable(params) { 33 | await documentClient.update(params, function (err, data) { 34 | if (err) { 35 | console.log(JSON.stringify(err, null, 2)); 36 | } else { 37 | console.log(JSON.stringify(data, null, 2)); 38 | // console.log("Updated petid: "+payload.petid +", pettype: "+payload.pettype+ " to availability: "+availability); 39 | } 40 | }).promise(); 41 | } 42 | -------------------------------------------------------------------------------- /PetAdoptions/petstatusupdater/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "petstatusupdater", 3 | "version": "1.0.0", 4 | "description": "Updates pet availability", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "aws-xray-sdk": "^3.3.3" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /PetAdoptions/trafficgenerator/.idea/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/one-observability-demo/396cb484bde89fbe3581338d9eb33e5769f58f4c/PetAdoptions/trafficgenerator/.idea/.gitignore -------------------------------------------------------------------------------- /PetAdoptions/trafficgenerator/.idea/.idea.trafficgenerator/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /workspace.xml -------------------------------------------------------------------------------- /PetAdoptions/trafficgenerator/.idea/.idea.trafficgenerator/.idea/contentModel.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /PetAdoptions/trafficgenerator/.idea/.idea.trafficgenerator/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /PetAdoptions/trafficgenerator/.idea/.idea.trafficgenerator/.idea/indexLayout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PetAdoptions/trafficgenerator/.idea/.idea.trafficgenerator/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PetAdoptions/trafficgenerator/.idea/.idea.trafficgenerator/.idea/projectSettingsUpdater.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /PetAdoptions/trafficgenerator/.idea/.idea.trafficgenerator/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /PetAdoptions/trafficgenerator/.idea/.idea.trafficgenerator/riderModule.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /PetAdoptions/trafficgenerator/trafficgenerator.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "trafficgenerator", "trafficgenerator\trafficgenerator.csproj", "{C872A202-C201-46EC-AA25-C5FB9EF5AD4A}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Any CPU = Debug|Any CPU 8 | Release|Any CPU = Release|Any CPU 9 | EndGlobalSection 10 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 11 | {C872A202-C201-46EC-AA25-C5FB9EF5AD4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 12 | {C872A202-C201-46EC-AA25-C5FB9EF5AD4A}.Debug|Any CPU.Build.0 = Debug|Any CPU 13 | {C872A202-C201-46EC-AA25-C5FB9EF5AD4A}.Release|Any CPU.ActiveCfg = Release|Any CPU 14 | {C872A202-C201-46EC-AA25-C5FB9EF5AD4A}.Release|Any CPU.Build.0 = Release|Any CPU 15 | EndGlobalSection 16 | EndGlobal 17 | -------------------------------------------------------------------------------- /PetAdoptions/trafficgenerator/trafficgenerator/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/aspnet:6.0-bullseye-slim AS base 2 | WORKDIR /app 3 | EXPOSE 80 4 | EXPOSE 443 5 | 6 | FROM mcr.microsoft.com/dotnet/sdk:6.0-bullseye-slim AS build 7 | WORKDIR /src 8 | COPY . . 9 | RUN dotnet restore "trafficgenerator.csproj" 10 | RUN dotnet build "trafficgenerator.csproj" -c Release -o /app/build 11 | 12 | FROM build AS publish 13 | RUN dotnet publish "trafficgenerator.csproj" -c Release -o /app/publish 14 | 15 | FROM base AS final 16 | WORKDIR /app 17 | #ENV DOTNET_ENVIRONMENT=Development 18 | COPY --from=publish /app/publish . 19 | ENTRYPOINT ["dotnet", "trafficgenerator.dll"] 20 | -------------------------------------------------------------------------------- /PetAdoptions/trafficgenerator/trafficgenerator/PetData.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Diagnostics; 3 | 4 | namespace trafficgenerator 5 | { 6 | public class Pet 7 | { 8 | public string pettype { get; set; } 9 | public string petid { get; set; } 10 | public string petcolor { get; set; } 11 | public string availability { get; set; } 12 | public bool IsProcessed { get; set; } 13 | } 14 | 15 | public class Pets 16 | { 17 | public List AllPets { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /PetAdoptions/trafficgenerator/trafficgenerator/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using Microsoft.Extensions.Hosting; 8 | using Microsoft.AspNetCore.Hosting; 9 | 10 | namespace trafficgenerator 11 | { 12 | public class Program 13 | { 14 | public static void Main(string[] args) 15 | { 16 | CreateWebBuilder(args).Build().RunAsync(); 17 | CreateHostBuilder(args).Build().Run(); 18 | } 19 | 20 | public static IHostBuilder CreateHostBuilder(string[] args) => 21 | Host.CreateDefaultBuilder(args) 22 | .ConfigureServices((hostContext, services) => 23 | { 24 | services.AddHostedService(); 25 | 26 | }) 27 | .ConfigureAppConfiguration((hostingContext, config) => 28 | { 29 | var env = hostingContext.HostingEnvironment; 30 | Console.WriteLine($"ENVIRONMENT NAME IS: {env.EnvironmentName}"); 31 | if (env.EnvironmentName.ToLower() == "development") 32 | config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) 33 | .AddJsonFile($"appsettings.{env.EnvironmentName}.json", 34 | optional: true, reloadOnChange: true); 35 | else 36 | config.AddSystemsManager(configureSource => 37 | { 38 | configureSource.Path = "/petstore"; 39 | configureSource.Optional = true; 40 | configureSource.ReloadAfter = TimeSpan.FromMinutes(5); 41 | }); 42 | 43 | 44 | }); 45 | 46 | public static IHostBuilder CreateWebBuilder(string[] args) => 47 | Host.CreateDefaultBuilder(args) 48 | .ConfigureWebHostDefaults(web => 49 | { 50 | web.UseStartup(); 51 | }); 52 | 53 | } 54 | } -------------------------------------------------------------------------------- /PetAdoptions/trafficgenerator/trafficgenerator/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "trafficgenerator": { 4 | "commandName": "Project", 5 | "environmentVariables": { 6 | "DOTNET_ENVIRONMENT": "Development" 7 | } 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /PetAdoptions/trafficgenerator/trafficgenerator/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Hosting; 6 | using Microsoft.Extensions.Diagnostics.HealthChecks; 7 | 8 | namespace trafficgenerator 9 | { 10 | public class Startup 11 | { 12 | public Startup(IConfiguration configuration) 13 | { 14 | Configuration = configuration; 15 | } 16 | 17 | public IConfiguration Configuration { get; } 18 | 19 | // This method gets called by the runtime. Use this method to add services to the container. 20 | public void ConfigureServices(IServiceCollection services) 21 | { 22 | services.AddHealthChecks().AddCheck("AlwaysGood",()=> HealthCheckResult.Healthy("All Good!")); 23 | } 24 | 25 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 26 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 27 | { 28 | 29 | if (env.IsDevelopment()) 30 | { 31 | app.UseDeveloperExceptionPage(); 32 | } 33 | 34 | app.UseHealthChecks("/health"); 35 | app.UseHealthChecks("/"); 36 | 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /PetAdoptions/trafficgenerator/trafficgenerator/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "petsiteurl":"petsite-1088770206.us-east-1.elb.amazonaws.com", 10 | "searchapiurl":"petsearch-live.us-east-1.elasticbeanstalk.com/api/search" 11 | } 12 | -------------------------------------------------------------------------------- /PetAdoptions/trafficgenerator/trafficgenerator/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /PetAdoptions/trafficgenerator/trafficgenerator/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | trafficgenerator: 4 | build: . 5 | -------------------------------------------------------------------------------- /PetAdoptions/trafficgenerator/trafficgenerator/trafficgenerator.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | netcoreapp6.0 4 | dotnet-trafficgenerator-24A0A2C8-664C-4353-AA89-98AB3F5B653C 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## One Observability Demo 2 | 3 | This repo contains a sample application which is used in the One Observability Demo workshop here - https://observability.workshop.aws/ 4 | 5 | ## Security 6 | 7 | See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information. 8 | 9 | ## Instructions 10 | 11 | To deploy this workshop on your own account you need to have an IAM role with elevated priviliges and the `aws-cli` installed. Then, from the root 12 | of the repository run the following command: 13 | 14 | ``` 15 | aws cloudformation create-stack --stack-name Observability-Workshop --template-body file://codepipeline-stack.yaml --capabilities CAPABILITY_NAMED_IAM --parameters ParameterKey=UserRoleArn,ParameterValue=$(aws iam get-role --role-name $(aws sts get-caller-identity --query Arn --output text | awk -F/ '{print $(NF-1)}') --query Role.Arn --output text) 16 | ``` 17 | 18 | You can replace the role specified in the paramter `UserRoleArn` with any other role with access to AWS CloudShell if you need so. 19 | 20 | ## License 21 | 22 | This library is licensed under the MIT-0 License. See the LICENSE file. 23 | 24 | -------------------------------------------------------------------------------- /buildspec.yml: -------------------------------------------------------------------------------- 1 | version: 0.2 2 | env: 3 | variables: 4 | # https://github.com/cdklabs/cdk-ecr-deployment/issues/478#issuecomment-1938020710 5 | NO_PREBUILT_LAMBDA: "1" 6 | phases: 7 | install: 8 | commands: 9 | - nohup /usr/local/bin/dockerd --host=unix:///var/run/docker.sock --host=tcp://127.0.0.1:2375 --storage-driver=overlay2 & 10 | - timeout 15 sh -c "until docker info; do echo .; sleep 1; done" 11 | - npm install aws-cdk -g 12 | - CDK_STACK=$(aws cloudformation list-stacks --query 'StackSummaries[?(StackName==`CDKToolkit` && StackStatus==`CREATE_COMPLETE`)].StackId' --output text) 13 | build: 14 | commands: 15 | - cd ./PetAdoptions/cdk/pet_stack/ 16 | - npm install 17 | - if [ -z "$CDK_STACK" ] ; then cdk bootstrap ; else echo "Already bootstrapped" ; fi 18 | - npm run build 19 | - cdk deploy Services --context admin_role=${EE_TEAM_ROLE_ARN} --require-approval=never --verbose -O ./out/out.json 20 | - cdk deploy Applications --require-approval=never --verbose -O ./out/out.json 21 | artifacts: 22 | files: "./PetAdoptions/cdk/pet_stack/out/out.json" 23 | -------------------------------------------------------------------------------- /gitops/git-repository.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: source.toolkit.fluxcd.io/v1beta2 2 | kind: GitRepository 3 | metadata: 4 | name: grafana-repo 5 | namespace: flux-system 6 | spec: 7 | interval: 5m0s 8 | url: https://github.com/aws-samples/one-observability-demo 9 | ref: 10 | branch: main -------------------------------------------------------------------------------- /gitops/grafana-kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.toolkit.fluxcd.io/v1beta2 2 | kind: Kustomization 3 | metadata: 4 | name: grafana-kustomization 5 | namespace: flux-system 6 | spec: 7 | interval: 1m0s 8 | path: ./grafana-operator-manifests 9 | prune: true 10 | sourceRef: 11 | kind: GitRepository 12 | name: grafana-repo 13 | postBuild: 14 | substituteFrom: 15 | - kind: ConfigMap 16 | name: cluster-vars -------------------------------------------------------------------------------- /grafana-operator-manifests/amg_grafana-amp-datasource.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: grafana.integreatly.org/v1beta1 2 | kind: GrafanaDatasource 3 | metadata: 4 | name: grafanadatasource-sample-amp 5 | namespace: grafana-operator 6 | spec: 7 | instanceSelector: 8 | matchLabels: 9 | dashboards: "external-grafana" 10 | datasource: 11 | name: grafana-operator-amp-datasource 12 | type: prometheus 13 | access: proxy 14 | url: ${AMP_ENDPOINT_URL} 15 | isDefault: true 16 | jsonData: 17 | 'tlsSkipVerify': false 18 | 'timeInterval': "5s" 19 | 'sigV4Auth': true 20 | 'sigV4AuthType': "ec2_iam_role" 21 | 'sigV4Region': ${AMG_AWS_REGION} 22 | editable: true 23 | -------------------------------------------------------------------------------- /grafana-operator-manifests/amg_grafana-cw-datasource.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: grafana.integreatly.org/v1beta1 2 | kind: GrafanaDatasource 3 | metadata: 4 | name: grafanadatasource-sample-cw 5 | spec: 6 | instanceSelector: 7 | matchLabels: 8 | dashboards: "external-grafana" 9 | datasource: 10 | name: cloud-watch 11 | type: cloudwatch 12 | access: server 13 | isDefault: false 14 | jsonData: 15 | 'tlsSkipVerify': false 16 | 'timeInterval': "5s" 17 | "sigV4Auth": true, 18 | "sigV4AuthType": "ec2_iam_role" 19 | "sigV4Region": ${AMG_AWS_REGION} 20 | "customMetricsNamespaces": "ContainerInsights/Prometheus" 21 | "defaultRegion": ${AMG_AWS_REGION} 22 | "provisionedBy": "aws-datasource-provisioner-app" 23 | editable: true -------------------------------------------------------------------------------- /grafana-operator-manifests/amg_grafana-dashboard.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: grafana.integreatly.org/v1beta1 2 | kind: GrafanaDashboard 3 | metadata: 4 | name: external-grafanadashboard-url 5 | namespace: grafana-operator 6 | spec: 7 | instanceSelector: 8 | matchLabels: 9 | dashboards: "external-grafana" 10 | url: ${GRAFANA_NODEEXP_DASH_URL} 11 | -------------------------------------------------------------------------------- /grafana-operator-manifests/amg_grafana-identity.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: grafana.integreatly.org/v1beta1 2 | kind: Grafana 3 | metadata: 4 | name: external-grafana 5 | namespace: grafana-operator 6 | labels: 7 | dashboards: "external-grafana" 8 | spec: 9 | external: 10 | url: ${AMG_ENDPOINT_URL} 11 | apiKey: 12 | name: grafana-admin-credentials 13 | key: GF_SECURITY_ADMIN_APIKEY 14 | -------------------------------------------------------------------------------- /grafana-operator-manifests/amg_grafana-xray-datasource.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: grafana.integreatly.org/v1beta1 2 | kind: GrafanaDatasource 3 | metadata: 4 | name: grafanadatasource-sample-xray 5 | spec: 6 | instanceSelector: 7 | matchLabels: 8 | dashboards: "external-grafana" 9 | datasource: 10 | name: X-Ray 11 | type: grafana-x-ray-datasource 12 | access: server 13 | isDefault: false 14 | jsonData: 15 | "authType": "ec2_iam_role" 16 | "defaultRegion": ${AMG_AWS_REGION} 17 | "provisionedBy": "aws-datasource-provisioner-app" 18 | editable: true -------------------------------------------------------------------------------- /grafana-operator-manifests/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | resources: 4 | - amg_grafana-identity.yaml 5 | - amg_grafana-amp-datasource.yaml 6 | - amg_grafana-dashboard.yaml -------------------------------------------------------------------------------- /pack.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | 5 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" 6 | 7 | rm -rf ./assets 8 | mkdir -p assets 9 | 10 | zip -r ./assets/SourceCode.zip . -x ".*" "*/.*" "*/obj/**" ".git/**" "*/node_modules/**" "*/cdk.out/*" "*/out/**" -------------------------------------------------------------------------------- /setup-cloudshell.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ -z "$AWS_REGION" ]; then 4 | echo "error: environment variable AWS_REGION not set. Aborting." 5 | exit 1 6 | fi 7 | 8 | function install_helm(){ 9 | echo "Installing helm" 10 | curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 11 | chmod 700 get_helm.sh 12 | ./get_helm.sh 13 | sudo mv $(which helm) $HOME/.local/bin/ 14 | rm get_helm.sh 15 | } 16 | 17 | function install_eksctl(){ 18 | echo "Installing eksctl" 19 | ARCH=amd64 20 | PLATFORM=$(uname -s)_$ARCH 21 | curl -sLO "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_$PLATFORM.tar.gz" 22 | curl -sL "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_checksums.txt" | grep $PLATFORM | sha256sum --check 23 | tar -xzf eksctl_$PLATFORM.tar.gz -C /tmp && rm eksctl_$PLATFORM.tar.gz 24 | sudo mv /tmp/eksctl $HOME/.local/bin/ 25 | } 26 | 27 | function install_awscurl(){ 28 | echo "Installing awscurl" 29 | pip install awscurl 30 | } 31 | 32 | mkdir -p $HOME/.local/bin 33 | cd /tmp 34 | 35 | # install helm 36 | command -v helm >/dev/null 2>&1 || 37 | { install_helm; } 38 | 39 | # install awscurl 40 | command -v awscurl >/dev/null 2>&1 || 41 | { install_awscurl; } 42 | 43 | # install eksctl 44 | command -v eksctl >/dev/null 2>&1 || 45 | { install_eksctl; } 46 | 47 | echo "All dependencies installed!" 48 | 49 | cd - 50 | --------------------------------------------------------------------------------