├── .autover └── autover.json ├── .github ├── ISSUE_TEMPLATE │ ├── bug-report.yml │ ├── config.yml │ ├── documentation.yml │ └── feature-request.yml ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── aws-ci.yml │ ├── change-file-in-pr.yml │ ├── closed-issue-message.yml │ ├── create-release-pr.yml │ ├── handle-stale-discussions.yml │ ├── issue-regression-labeler.yml │ ├── stale_issues.yml │ └── sync-main-dev.yml ├── .gitignore ├── .nuget └── NuGet.Config ├── AWS.Logger.sln ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── build.proj ├── buildtools └── ci.buildspec.yml ├── icon.png ├── public.snk ├── samples ├── AspNetCore │ ├── ConsoleSample │ │ ├── ConsoleSample.csproj │ │ ├── Program.cs │ │ └── Properties │ │ │ └── AssemblyInfo.cs │ └── WebSample │ │ ├── Pages │ │ ├── Index.cshtml │ │ ├── Index.cshtml.cs │ │ ├── Shared │ │ │ ├── _CookieConsentPartial.cshtml │ │ │ ├── _Layout.cshtml │ │ │ └── _ValidationScriptsPartial.cshtml │ │ ├── _ViewImports.cshtml │ │ └── _ViewStart.cshtml │ │ ├── Program.cs │ │ ├── Properties │ │ └── launchSettings.json │ │ ├── Startup.cs │ │ ├── WebSample.csproj │ │ ├── appsettings.Development.json │ │ ├── appsettings.json │ │ └── wwwroot │ │ ├── css │ │ └── site.css │ │ ├── favicon.ico │ │ ├── js │ │ └── site.js │ │ └── lib │ │ ├── bootstrap │ │ ├── LICENSE │ │ └── dist │ │ │ ├── css │ │ │ ├── bootstrap-grid.css │ │ │ ├── bootstrap-grid.css.map │ │ │ ├── bootstrap-grid.min.css │ │ │ ├── bootstrap-grid.min.css.map │ │ │ ├── bootstrap-grid.rtl.css │ │ │ ├── bootstrap-grid.rtl.css.map │ │ │ ├── bootstrap-grid.rtl.min.css │ │ │ ├── bootstrap-grid.rtl.min.css.map │ │ │ ├── bootstrap-reboot.css │ │ │ ├── bootstrap-reboot.css.map │ │ │ ├── bootstrap-reboot.min.css │ │ │ ├── bootstrap-reboot.min.css.map │ │ │ ├── bootstrap-reboot.rtl.css │ │ │ ├── bootstrap-reboot.rtl.css.map │ │ │ ├── bootstrap-reboot.rtl.min.css │ │ │ ├── bootstrap-reboot.rtl.min.css.map │ │ │ ├── bootstrap-utilities.css │ │ │ ├── bootstrap-utilities.css.map │ │ │ ├── bootstrap-utilities.min.css │ │ │ ├── bootstrap-utilities.min.css.map │ │ │ ├── bootstrap-utilities.rtl.css │ │ │ ├── bootstrap-utilities.rtl.css.map │ │ │ ├── bootstrap-utilities.rtl.min.css │ │ │ ├── bootstrap-utilities.rtl.min.css.map │ │ │ ├── bootstrap.css │ │ │ ├── bootstrap.css.map │ │ │ ├── bootstrap.min.css │ │ │ ├── bootstrap.min.css.map │ │ │ ├── bootstrap.rtl.css │ │ │ ├── bootstrap.rtl.css.map │ │ │ ├── bootstrap.rtl.min.css │ │ │ └── bootstrap.rtl.min.css.map │ │ │ └── js │ │ │ ├── bootstrap.bundle.js │ │ │ ├── bootstrap.bundle.js.map │ │ │ ├── bootstrap.bundle.min.js │ │ │ ├── bootstrap.bundle.min.js.map │ │ │ ├── bootstrap.esm.js │ │ │ ├── bootstrap.esm.js.map │ │ │ ├── bootstrap.esm.min.js │ │ │ ├── bootstrap.esm.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 ├── Log4net │ ├── BasicAWSCredentialsConfigurationExample │ │ ├── App.config │ │ ├── BasicAWSCredentialsConfigurationExample.csproj │ │ ├── Program.cs │ │ ├── README.md │ │ ├── log4net.config │ │ └── packages.config │ ├── ConfigExample │ │ ├── App.config │ │ ├── ConfigExample.csproj │ │ ├── Program.cs │ │ ├── log4net.config │ │ └── packages.config │ └── ProgrammaticConfigurationExample │ │ ├── App.config │ │ ├── Program.cs │ │ ├── ProgrammaticConfigurationExample.csproj │ │ └── packages.config ├── NLog │ ├── ConfigExample │ │ ├── App.config │ │ ├── ConfigExample.csproj │ │ ├── NLog.config │ │ ├── Program.cs │ │ └── packages.config │ └── ProgrammaticConfigurationExample │ │ ├── App.config │ │ ├── Program.cs │ │ ├── ProgrammaticConfigurationExample.csproj │ │ └── packages.config └── Serilog │ ├── SerilogTestCode │ ├── Program.cs │ └── SerilogTestCode.csproj │ ├── SerilogTestCodeFromConfig │ ├── Program.cs │ ├── SerilogTestCodeFromConfig.csproj │ └── appsettings.json │ └── SerilogTestCodeFromConfigRestrictedToMinimumLevel │ ├── Program.cs │ ├── SerilogTestCodeFromConfigRestrictedToMinimumLevel.csproj │ └── appsettings.json ├── src ├── AWS.Logger.AspNetCore │ ├── AWS.Logger.AspNetCore.csproj │ ├── AWSLogger.cs │ ├── AWSLoggerBuilderExtensions.cs │ ├── AWSLoggerConfigSection.cs │ ├── AWSLoggerFactoryExtensions.cs │ ├── AWSLoggerProvider.cs │ ├── Constants.cs │ ├── NullExternalScopeProvider.cs │ ├── NullScope.cs │ └── Properties │ │ └── AssemblyInfo.cs ├── AWS.Logger.Core │ ├── AWS.Logger.Core.csproj │ ├── AWSLoggerConfig.cs │ ├── Core │ │ ├── AWSLoggerCore.cs │ │ └── IAWSLoggerCore.cs │ ├── IAWSLoggerConfig.cs │ └── Properties │ │ └── AssemblyInfo.cs ├── AWS.Logger.Log4net │ ├── AWS.Logger.Log4net.csproj │ ├── AWSAppender.cs │ └── Properties │ │ └── AssemblyInfo.cs ├── AWS.Logger.SeriLog │ ├── AWS.Logger.SeriLog.csproj │ ├── AWSLoggerSeriLogExtension.cs │ ├── AWSSink.cs │ └── Properties │ │ └── AssemblyInfo.cs └── NLog.AWS.Logger │ ├── AWSTarget.cs │ ├── NLog.AWS.Logger.csproj │ └── Properties │ └── AssemblyInfo.cs └── test ├── AWS.Logger.AspNetCore.Tests ├── AWS.Logger.AspNetCore.Tests.csproj ├── DefaultFilterCheck.json ├── FakeCoreLogger.cs ├── InValidAppsettingsFilter.json ├── MissingLogLevelCheck.json ├── Properties │ └── AssemblyInfo.cs ├── TestClass.cs ├── TestConfigurationBase.cs ├── TestDisableLogGroupCreation.cs ├── TestFilter.cs ├── TestFormatter.cs ├── TestScope.cs ├── ValidAppsettingsFilter.json ├── appsettings.json ├── disableLogGroupCreationMissing.json ├── disableLogGroupCreationTrue.json ├── multiThreadBufferFullTest.json ├── multiThreadTest.json └── overrideLogStreamName.json ├── AWS.Logger.Log4Net.FilterTests ├── AWS.Logger.Log4Net.FilterTests.csproj ├── FakeAWSAppender.cs ├── FakeCoreLogger.cs ├── Properties │ └── AssemblyInfo.cs └── TestFilter.cs ├── AWS.Logger.Log4Net.Tests ├── AWS.Logger.Log4Net.Tests.csproj ├── App.config ├── MultiThreadBufferFullTest.config ├── MultiThreadTest.config ├── OverrideLogStreamName.config ├── Properties │ └── AssemblyInfo.cs ├── TestClass.cs ├── log4net.config └── packages.config ├── AWS.Logger.NLog.FilterTests ├── AWS.Logger.NLog.FilterTests.csproj ├── FakeAWSTarget.cs ├── FakeCoreLogger.cs ├── Properties │ └── AssemblyInfo.cs └── TestFilter.cs ├── AWS.Logger.NLog.Tests ├── AWS.Logger.NLog.Tests.csproj ├── AWSNLogGroupEventSizeExceededTest.config ├── AWSNLogGroupMultiThreadBufferFullTest.config ├── AWSNLogGroupMultiThreadTest.config ├── AWSNLogOverrideLogStreamName.config ├── Properties │ └── AssemblyInfo.cs ├── Regular.config └── TestClass.cs ├── AWS.Logger.SeriLog.Tests ├── AWS.Logger.SeriLog.Tests.csproj ├── AWSSeriLogGroup.json ├── AWSSeriLogGroupMultiThreadBufferFullTest.json ├── AWSSeriLogGroupMultiThreadTest.json ├── AWSSeriLogGroupOverrideLogStreamName.json ├── AWSSeriLogGroupRestrictedToMinimumLevel.json ├── Properties │ └── AssemblyInfo.cs └── SeriLoggerTestClass.cs ├── AWS.Logger.TestUtils ├── AWS.Logger.TestUtils.csproj ├── BaseTestClass.cs ├── Properties │ └── AssemblyInfo.cs └── TestFixture.cs └── AWS.Logger.UnitTests ├── AWS.Logger.UnitTests.csproj ├── AWSLoggerConfigTests.cs ├── DisableLogGroupCreationTests.cs ├── GenerateStreamNameTests.cs ├── MessageSizeBreakupTests.cs └── Properties └── AssemblyInfo.cs /.autover/autover.json: -------------------------------------------------------------------------------- 1 | { 2 | "Projects": [ 3 | { 4 | "Name": "AWS.Logger.AspNetCore", 5 | "Path": "src/AWS.Logger.AspNetCore/AWS.Logger.AspNetCore.csproj" 6 | }, 7 | { 8 | "Name": "AWS.Logger.Core", 9 | "Path": "src/AWS.Logger.Core/AWS.Logger.Core.csproj" 10 | }, 11 | { 12 | "Name": "AWS.Logger.Log4net", 13 | "Path": "src/AWS.Logger.Log4net/AWS.Logger.Log4net.csproj" 14 | }, 15 | { 16 | "Name": "AWS.Logger.SeriLog", 17 | "Path": "src/AWS.Logger.SeriLog/AWS.Logger.SeriLog.csproj" 18 | }, 19 | { 20 | "Name": "NLog.AWS.Logger", 21 | "Path": "src/NLog.AWS.Logger/NLog.AWS.Logger.csproj" 22 | } 23 | ], 24 | "UseCommitsForChangelog": false, 25 | "UseSameVersionForAllProjects": false, 26 | "DefaultIncrementType": "Patch", 27 | "ChangeFilesDetermineIncrementType": true 28 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: "🐛 Bug Report" 3 | description: Report a bug 4 | title: "(short issue description)" 5 | labels: [bug, needs-triage] 6 | assignees: [] 7 | body: 8 | - type: textarea 9 | id: description 10 | attributes: 11 | label: Describe the bug 12 | description: What is the problem? A clear and concise description of the bug. 13 | validations: 14 | required: true 15 | - type: checkboxes 16 | id: regression 17 | attributes: 18 | label: Regression Issue 19 | description: What is a regression? If it worked in a previous version but doesn't in the latest version, it's considered a regression. In this case, please provide specific version number in the report. 20 | options: 21 | - label: Select this option if this issue appears to be a regression. 22 | required: false 23 | - type: textarea 24 | id: expected 25 | attributes: 26 | label: Expected Behavior 27 | description: | 28 | What did you expect to happen? 29 | validations: 30 | required: true 31 | - type: textarea 32 | id: current 33 | attributes: 34 | label: Current Behavior 35 | description: | 36 | What actually happened? 37 | 38 | Please include full errors, uncaught exceptions, stack traces, and relevant logs. 39 | If service responses are relevant, please include wire logs. 40 | validations: 41 | required: true 42 | - type: textarea 43 | id: reproduction 44 | attributes: 45 | label: Reproduction Steps 46 | description: | 47 | Provide a self-contained, concise snippet of code that can be used to reproduce the issue. 48 | For more complex issues provide a repo with the smallest sample that reproduces the bug. 49 | 50 | Avoid including business logic or unrelated code, it makes diagnosis more difficult. 51 | The code sample should be an SSCCE. See http://sscce.org/ for details. In short, please provide a code sample that we can copy/paste, run and reproduce. 52 | validations: 53 | required: true 54 | - type: textarea 55 | id: solution 56 | attributes: 57 | label: Possible Solution 58 | description: | 59 | Suggest a fix/reason for the bug 60 | validations: 61 | required: false 62 | - type: textarea 63 | id: context 64 | attributes: 65 | label: Additional Information/Context 66 | description: | 67 | Anything else that might be relevant for troubleshooting this bug. Providing context helps us come up with a solution that is most useful in the real world. 68 | validations: 69 | required: false 70 | 71 | - type: textarea 72 | id: dotnet-sdk-version 73 | attributes: 74 | label: AWS .NET SDK and/or Package version used 75 | description: NuGet Packages used 76 | placeholder: AWSSDK.S3 3.7.8.13 77 | validations: 78 | required: true 79 | 80 | - type: input 81 | id: platform-used 82 | attributes: 83 | label: Targeted .NET Platform 84 | description: "Example: .NET Framework 4.7, .NET Core 3.1, .NET 6, etc." 85 | placeholder: .NET Framework 4.7, .NET Core 3.1, .NET 6, etc. 86 | validations: 87 | required: true 88 | 89 | - type: input 90 | id: operating-system 91 | attributes: 92 | label: Operating System and version 93 | description: "Example: Windows 10, OSX Mojave, Ubuntu, AmazonLinux, etc." 94 | placeholder: Windows 10, OSX Mojave, Ubuntu, AmazonLinux, etc. 95 | validations: 96 | required: true 97 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | blank_issues_enabled: false 3 | contact_links: 4 | - name: 💬 General Question 5 | url: https://github.com/aws/aws-logging-dotnet/discussions/categories/q-a 6 | about: Please ask and answer questions as a discussion thread -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/documentation.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: "📕 Documentation Issue" 3 | description: Report an issue in the API Reference documentation or Developer Guide 4 | title: "(short issue description)" 5 | labels: [documentation, needs-triage] 6 | assignees: [] 7 | body: 8 | - type: textarea 9 | id: description 10 | attributes: 11 | label: Describe the issue 12 | description: A clear and concise description of the issue. 13 | validations: 14 | required: true 15 | 16 | - type: textarea 17 | id: links 18 | attributes: 19 | label: Links 20 | description: | 21 | Include links to affected documentation page(s). 22 | validations: 23 | required: true 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🚀 Feature Request 3 | description: Suggest an idea for this project 4 | title: "(short issue description)" 5 | labels: [feature-request, needs-triage] 6 | assignees: [] 7 | body: 8 | - type: textarea 9 | id: description 10 | attributes: 11 | label: Describe the feature 12 | description: A clear and concise description of the feature you are proposing. 13 | validations: 14 | required: true 15 | - type: textarea 16 | id: use-case 17 | attributes: 18 | label: Use Case 19 | description: | 20 | Why do you need this feature? For example: "I'm always frustrated when..." 21 | validations: 22 | required: true 23 | - type: textarea 24 | id: solution 25 | attributes: 26 | label: Proposed Solution 27 | description: | 28 | Suggest how to implement the addition or change. Please include prototype/workaround/sketch/reference implementation. 29 | validations: 30 | required: false 31 | - type: textarea 32 | id: other 33 | attributes: 34 | label: Other Information 35 | description: | 36 | Any alternative solutions or features you considered, a more detailed explanation, stack traces, related issues, links for context, etc. 37 | validations: 38 | required: false 39 | - type: checkboxes 40 | id: ack 41 | attributes: 42 | label: Acknowledgements 43 | options: 44 | - label: I may be able to implement this feature request 45 | required: false 46 | - label: This feature might incur a breaking change 47 | required: false 48 | 49 | - type: textarea 50 | id: dotnet-sdk-version 51 | attributes: 52 | label: AWS .NET SDK and/or Package version used 53 | description: NuGet Packages used 54 | placeholder: AWSSDK.S3 3.7.8.13 55 | validations: 56 | required: true 57 | 58 | - type: input 59 | id: platform-used 60 | attributes: 61 | label: Targeted .NET Platform 62 | description: "Example: .NET Framework 4.7, .NET Core 3.1, .NET 6, etc." 63 | placeholder: .NET Framework 4.7, .NET Core 3.1, .NET 6, etc. 64 | validations: 65 | required: true 66 | 67 | - type: input 68 | id: operating-system 69 | attributes: 70 | label: Operating System and version 71 | description: "Example: Windows 10, OSX Mojave, Ubuntu, AmazonLinux, etc." 72 | placeholder: Windows 10, OSX Mojave, Ubuntu, AmazonLinux, etc. 73 | validations: 74 | required: true 75 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | *Issue #, if available:* 2 | 3 | *Description of changes:* 4 | 5 | 6 | By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. 7 | -------------------------------------------------------------------------------- /.github/workflows/aws-ci.yml: -------------------------------------------------------------------------------- 1 | name: AWS CI 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | branches: 7 | - main 8 | - dev 9 | - 'feature/**' 10 | 11 | permissions: 12 | id-token: write 13 | 14 | jobs: 15 | run-ci: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - name: Configure AWS Credentials 19 | uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 #v4 20 | with: 21 | role-to-assume: ${{ secrets.CI_MAIN_TESTING_ACCOUNT_ROLE_ARN }} 22 | role-duration-seconds: 7200 23 | aws-region: us-west-2 24 | - name: Invoke Load Balancer Lambda 25 | id: lambda 26 | shell: pwsh 27 | run: | 28 | aws lambda invoke response.json --function-name "${{ secrets.CI_TESTING_LOAD_BALANCER_LAMBDA_NAME }}" --cli-binary-format raw-in-base64-out --payload '{"Roles": "${{ secrets.CI_TEST_RUNNER_ACCOUNT_ROLES }}", "ProjectName": "${{ secrets.CI_TESTING_CODE_BUILD_PROJECT_NAME }}", "Branch": "${{ github.sha }}"}' 29 | $roleArn=$(cat ./response.json) 30 | "roleArn=$($roleArn -replace '"', '')" >> $env:GITHUB_OUTPUT 31 | - name: Configure Test Runner Credentials 32 | uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 #v4 33 | with: 34 | role-to-assume: ${{ steps.lambda.outputs.roleArn }} 35 | role-duration-seconds: 7200 36 | aws-region: us-west-2 37 | - name: Run Tests on AWS 38 | id: codebuild 39 | uses: aws-actions/aws-codebuild-run-build@4d15a47425739ac2296ba5e7eee3bdd4bfbdd767 #v1.0.18 40 | with: 41 | project-name: ${{ secrets.CI_TESTING_CODE_BUILD_PROJECT_NAME }} 42 | - name: CodeBuild Link 43 | shell: pwsh 44 | run: | 45 | $buildId = "${{ steps.codebuild.outputs.aws-build-id }}" 46 | echo $buildId 47 | -------------------------------------------------------------------------------- /.github/workflows/change-file-in-pr.yml: -------------------------------------------------------------------------------- 1 | name: Change File Included in PR 2 | 3 | on: 4 | pull_request: 5 | types: [opened, synchronize, reopened, labeled] 6 | 7 | jobs: 8 | check-files-in-directory: 9 | if: ${{ !contains(github.event.pull_request.labels.*.name, 'Release Not Needed') && !contains(github.event.pull_request.labels.*.name, 'Release PR') }} 10 | name: Change File Included in PR 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - name: Checkout PR code 15 | uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 #v3.6.0 16 | 17 | - name: Get List of Changed Files 18 | id: changed-files 19 | uses: tj-actions/changed-files@4edd678ac3f81e2dc578756871e4d00c19191daf #v45 20 | 21 | - name: Check for Change File(s) in .autover/changes/ 22 | run: | 23 | DIRECTORY=".autover/changes/" 24 | if echo "${{ steps.changed-files.outputs.all_changed_files }}" | grep -q "$DIRECTORY"; then 25 | echo "✅ One or more change files in '$DIRECTORY' are included in this PR." 26 | else 27 | echo "❌ No change files in '$DIRECTORY' are included in this PR." 28 | echo "Refer to the 'Adding a change file to your contribution branch' section of https://github.com/aws/aws-logging-dotnet/blob/master/CONTRIBUTING.md" 29 | exit 1 30 | fi 31 | -------------------------------------------------------------------------------- /.github/workflows/closed-issue-message.yml: -------------------------------------------------------------------------------- 1 | name: Closed Issue Message 2 | on: 3 | issues: 4 | types: [closed] 5 | jobs: 6 | auto_comment: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: aws-actions/closed-issue-message@10aaf6366131b673a7c8b7742f8b3849f1d44f18 #v2 10 | with: 11 | # These inputs are both required 12 | repo-token: "${{ secrets.GITHUB_TOKEN }}" 13 | message: | 14 | Comments on closed issues are hard for our team to see. 15 | If you need more assistance, please either tag a team member or open a new issue that references this one. 16 | If you wish to keep having a conversation with other community members under this issue feel free to do so. 17 | -------------------------------------------------------------------------------- /.github/workflows/create-release-pr.yml: -------------------------------------------------------------------------------- 1 | # This GitHub Workflow will create a new release branch that contains the updated C# project versions and changelog. 2 | # The workflow will also create a PR that targets `dev` from the release branch. 3 | name: Create Release PR 4 | 5 | # This workflow is manually triggered when in preparation for a release. The workflow should be dispatched from the `dev` branch. 6 | on: 7 | workflow_dispatch: 8 | inputs: 9 | OVERRIDE_VERSION: 10 | description: "Override Version" 11 | type: string 12 | required: false 13 | 14 | permissions: 15 | id-token: write 16 | 17 | jobs: 18 | release-pr: 19 | name: Release PR 20 | runs-on: ubuntu-latest 21 | 22 | env: 23 | INPUT_OVERRIDE_VERSION: ${{ github.event.inputs.OVERRIDE_VERSION }} 24 | 25 | steps: 26 | # Assume an AWS Role that provides access to the Access Token 27 | - name: Configure AWS Credentials 28 | uses: aws-actions/configure-aws-credentials@8c3f20df09ac63af7b3ae3d7c91f105f857d8497 #v4 29 | with: 30 | role-to-assume: ${{ secrets.RELEASE_WORKFLOW_ACCESS_TOKEN_ROLE_ARN }} 31 | aws-region: us-west-2 32 | # Retrieve the Access Token from Secrets Manager 33 | - name: Retrieve secret from AWS Secrets Manager 34 | uses: aws-actions/aws-secretsmanager-get-secrets@fbd65ea98e018858715f591f03b251f02b2316cb #v2.0.8 35 | with: 36 | secret-ids: | 37 | AWS_SECRET, ${{ secrets.RELEASE_WORKFLOW_ACCESS_TOKEN_NAME }} 38 | parse-json-secrets: true 39 | # Checkout a full clone of the repo 40 | - name: Checkout 41 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2 42 | with: 43 | fetch-depth: '0' 44 | token: ${{ env.AWS_SECRET_TOKEN }} 45 | # Install .NET8 which is needed for AutoVer 46 | - name: Setup .NET 8.0 47 | uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 #v4.3.1 48 | with: 49 | dotnet-version: 8.0.x 50 | # Install AutoVer to automate versioning and changelog creation 51 | - name: Install AutoVer 52 | run: dotnet tool install --global AutoVer --version 0.0.25 53 | # Set up a git user to be able to run git commands later on 54 | - name: Setup Git User 55 | run: | 56 | git config --global user.email "github-aws-sdk-dotnet-automation@amazon.com" 57 | git config --global user.name "aws-sdk-dotnet-automation" 58 | # Create the release branch which will contain the version changes and updated changelog 59 | - name: Create Release Branch 60 | id: create-release-branch 61 | run: | 62 | branch=releases/next-release 63 | git checkout -b $branch 64 | echo "BRANCH=$branch" >> $GITHUB_OUTPUT 65 | # Update the version of projects based on the change files 66 | - name: Increment Version 67 | run: autover version 68 | if: env.INPUT_OVERRIDE_VERSION == '' 69 | # Update the version of projects based on the override version 70 | - name: Increment Version 71 | run: autover version --use-version "$INPUT_OVERRIDE_VERSION" 72 | if: env.INPUT_OVERRIDE_VERSION != '' 73 | # Update the changelog based on the change files 74 | - name: Update Changelog 75 | run: autover changelog 76 | # Push the release branch up as well as the created tag 77 | - name: Push Changes 78 | run: | 79 | branch=${{ steps.create-release-branch.outputs.BRANCH }} 80 | git push origin $branch 81 | git push origin $branch --tags 82 | # Get the release name that will be used to create a PR 83 | - name: Read Release Name 84 | id: read-release-name 85 | run: | 86 | version=$(autover changelog --release-name) 87 | echo "VERSION=$version" >> $GITHUB_OUTPUT 88 | # Get the changelog that will be used to create a PR 89 | - name: Read Changelog 90 | id: read-changelog 91 | run: | 92 | changelog=$(autover changelog --output-to-console) 93 | echo "CHANGELOG<> "$GITHUB_OUTPUT" 94 | # Create the Release PR and label it 95 | - name: Create Pull Request 96 | env: 97 | GITHUB_TOKEN: ${{ env.AWS_SECRET_TOKEN }} 98 | run: | 99 | pr_url="$(gh pr create --title "${{ steps.read-release-name.outputs.VERSION }}" --body "${{ steps.read-changelog.outputs.CHANGELOG }}" --base dev --head ${{ steps.create-release-branch.outputs.BRANCH }})" 100 | gh label create "Release PR" --description "A Release PR that includes versioning and changelog changes" -c "#FF0000" -f 101 | gh pr edit $pr_url --add-label "Release PR" 102 | -------------------------------------------------------------------------------- /.github/workflows/handle-stale-discussions.yml: -------------------------------------------------------------------------------- 1 | name: HandleStaleDiscussions 2 | on: 3 | schedule: 4 | - cron: '0 */4 * * *' 5 | discussion_comment: 6 | types: [created] 7 | 8 | jobs: 9 | handle-stale-discussions: 10 | name: Handle stale discussions 11 | runs-on: ubuntu-latest 12 | permissions: 13 | discussions: write 14 | steps: 15 | - name: Stale discussions action 16 | uses: aws-github-ops/handle-stale-discussions@711a9813957be17629fc6933afcd8bd132c57254 #v1.6 17 | env: 18 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} 19 | -------------------------------------------------------------------------------- /.github/workflows/issue-regression-labeler.yml: -------------------------------------------------------------------------------- 1 | # Apply potential regression label on issues 2 | name: issue-regression-label 3 | on: 4 | issues: 5 | types: [opened, edited] 6 | jobs: 7 | add-regression-label: 8 | runs-on: ubuntu-latest 9 | permissions: 10 | issues: write 11 | steps: 12 | - name: Fetch template body 13 | id: check_regression 14 | uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea #v7.0.1 15 | env: 16 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 17 | TEMPLATE_BODY: ${{ github.event.issue.body }} 18 | with: 19 | script: | 20 | const regressionPattern = /\[x\] Select this option if this issue appears to be a regression\./i; 21 | const template = `${process.env.TEMPLATE_BODY}` 22 | const match = regressionPattern.test(template); 23 | core.setOutput('is_regression', match); 24 | - name: Manage regression label 25 | env: 26 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 27 | run: | 28 | if [ "${{ steps.check_regression.outputs.is_regression }}" == "true" ]; then 29 | gh issue edit ${{ github.event.issue.number }} --add-label "potential-regression" -R ${{ github.repository }} 30 | else 31 | gh issue edit ${{ github.event.issue.number }} --remove-label "potential-regression" -R ${{ github.repository }} 32 | fi 33 | -------------------------------------------------------------------------------- /.github/workflows/stale_issues.yml: -------------------------------------------------------------------------------- 1 | name: "Close stale issues" 2 | 3 | # Controls when the action will run. 4 | on: 5 | schedule: 6 | - cron: "0 0 * * *" 7 | 8 | jobs: 9 | cleanup: 10 | runs-on: ubuntu-latest 11 | name: Stale issue job 12 | steps: 13 | - uses: aws-actions/stale-issue-cleanup@5650b49bcd757a078f6ca06c373d7807b773f9bc #v7.1.0 14 | with: 15 | # Setting messages to an empty string will cause the automation to skip 16 | # that category 17 | ancient-issue-message: We have noticed this issue has not received attention in over a year. We will close this issue for now. If you think this is in error, please feel free to comment and reopen the issue. 18 | stale-issue-message: This issue has not received a response in 5 days. If you want to keep this issue open, please just leave a comment below and auto-close will be canceled. 19 | 20 | # These labels are required 21 | stale-issue-label: closing-soon 22 | exempt-issue-labels: no-autoclose 23 | stale-pr-label: no-pr-activity 24 | exempt-pr-labels: awaiting-approval 25 | response-requested-label: response-requested 26 | 27 | # Don't set closed-for-staleness label to skip closing very old issues 28 | # regardless of label 29 | closed-for-staleness-label: closed-for-staleness 30 | 31 | # Issue timing 32 | days-before-stale: 10 33 | days-before-close: 4 34 | days-before-ancient: 36500 35 | 36 | # If you don't want to mark a issue as being ancient based on a 37 | # threshold of "upvotes", you can set this here. An "upvote" is 38 | # the total number of +1, heart, hooray, and rocket reactions 39 | # on an issue. 40 | minimum-upvotes-to-exempt: 10 41 | 42 | repo-token: ${{ secrets.GITHUB_TOKEN }} 43 | #loglevel: DEBUG 44 | # Set dry-run to true to not perform label or close actions. 45 | #dry-run: true 46 | 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ###################################### 2 | # Visual Studio per-user settings data 3 | ###################################### 4 | *.suo 5 | *.user 6 | *.xproj.user 7 | 8 | #################### 9 | # Build/Test folders 10 | #################### 11 | 12 | **/bin/ 13 | **/obj/ 14 | **/TestResults/ 15 | **/Temp/ 16 | **/buildlogs/ 17 | **/packages/ 18 | **/*project.lock.json 19 | 20 | **/.vs/ 21 | 22 | **/Deployment/ 23 | /src/AWS.Logger.Core/AWS.Logger.Core45.nuget.props 24 | *.props 25 | 26 | # JetBrains Rider 27 | .idea/ 28 | *.sln.iml -------------------------------------------------------------------------------- /.nuget/NuGet.Config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check [existing open](https://github.com/aws/aws-logging-dotnet/issues), or [recently closed](https://github.com/aws/aws-logging-dotnet/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *master* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | ## Adding a `change file` to your contribution branch 43 | 44 | Each contribution branch should include a `change file` that contains a changelog message for each project that has been updated, as well as the type of increment to perform for those changes when versioning the project. 45 | 46 | A `change file` looks like the following example: 47 | ```json 48 | { 49 | "Projects": [ 50 | { 51 | "Name": "AWS.Logger.Core", 52 | "Type": "Patch", 53 | "ChangelogMessages": [ 54 | "Fixed an issue causing a failure somewhere" 55 | ] 56 | } 57 | ] 58 | } 59 | ``` 60 | The `change file` lists all the modified projects, the changelog message for each project as well as the increment type. 61 | 62 | These files are located in the repo at .autover/changes/ 63 | 64 | You can use the `AutoVer` tool to create the change file. You can install it using the following command: 65 | ``` 66 | dotnet tool install -g AutoVer 67 | ``` 68 | 69 | You can create the `change file` using the following command: 70 | ``` 71 | autover change --project-name "AWS.Logger.Core" -m "Fixed an issue causing a failure somewhere 72 | ``` 73 | Note: Make sure to run the command from the root of the repository. 74 | 75 | You can update the command to specify which project you are updating. 76 | The available projects are: 77 | * AWS.Logger.AspNetCore 78 | * AWS.Logger.Core 79 | * AWS.Logger.Log4net 80 | * AWS.Logger.SeriLog 81 | * NLog.AWS.Logger 82 | 83 | The possible increment types are: 84 | * Patch 85 | * Minor 86 | * Major 87 | 88 | Note: You do not need to create a new `change file` for every changelog message or project within your branch. You can create one `change file` that contains all the modified projects and the changelog messages. 89 | 90 | ## Finding contributions to work on 91 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels ((enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/aws/aws-logging-dotnet/labels/help%20wanted) issues is a great place to start. 92 | 93 | 94 | ## Code of Conduct 95 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 96 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 97 | opensource-codeofconduct@amazon.com with any additional questions or comments. 98 | 99 | 100 | ## Security issue notifications 101 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 102 | 103 | 104 | ## Licensing 105 | 106 | See the [LICENSE](https://github.com/aws/aws-logging-dotnet/blob/master/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 107 | 108 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. 109 | -------------------------------------------------------------------------------- /build.proj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /buildtools/ci.buildspec.yml: -------------------------------------------------------------------------------- 1 | version: 0.2 2 | 3 | phases: 4 | install: 5 | runtime-versions: 6 | dotnet: 8.x 7 | commands: 8 | # Mono is needed to run the tests on Linux 9 | - curl https://download.mono-project.com/repo/centos8-stable.repo | tee /etc/yum.repos.d/mono-stable.repo 10 | - dnf install -y mono-complete mono-devel 11 | build: 12 | commands: 13 | - dotnet test --verbosity normal test/AWS.Logger.AspNetCore.Tests/AWS.Logger.AspNetCore.Tests.csproj --configuration Release --logger trx --results-directory ./testresults 14 | - dotnet test --verbosity normal test/AWS.Logger.Log4Net.FilterTests/AWS.Logger.Log4Net.FilterTests.csproj --configuration Release --logger trx --results-directory ./testresults 15 | - dotnet test --verbosity normal test/AWS.Logger.Log4Net.Tests/AWS.Logger.Log4Net.Tests.csproj --configuration Release --logger trx --results-directory ./testresults 16 | - dotnet test --verbosity normal test/AWS.Logger.NLog.FilterTests/AWS.Logger.NLog.FilterTests.csproj --configuration Release --logger trx --results-directory ./testresults 17 | - dotnet test --verbosity normal test/AWS.Logger.NLog.Tests/AWS.Logger.NLog.Tests.csproj --configuration Release --logger trx --results-directory ./testresults 18 | - dotnet test --verbosity normal test/AWS.Logger.SeriLog.Tests/AWS.Logger.SeriLog.Tests.csproj --configuration Release --logger trx --results-directory ./testresults 19 | - dotnet test --verbosity normal test/AWS.Logger.UnitTests/AWS.Logger.UnitTests.csproj --configuration Release --logger trx --results-directory ./testresults 20 | reports: 21 | aws-dotnet-messaging-tests: 22 | file-format: VisualStudioTrx 23 | files: 24 | - '**/*' 25 | base-directory: './testresults' -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws/aws-logging-dotnet/03bb4dc1e84495a318812ac683c338c05e9aa494/icon.png -------------------------------------------------------------------------------- /public.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws/aws-logging-dotnet/03bb4dc1e84495a318812ac683c338c05e9aa494/public.snk -------------------------------------------------------------------------------- /samples/AspNetCore/ConsoleSample/ConsoleSample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | ConsoleSample 6 | Exe 7 | false 8 | false 9 | false 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /samples/AspNetCore/ConsoleSample/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | using Microsoft.Extensions.Logging; 7 | 8 | namespace ConsoleSample 9 | { 10 | public class Program 11 | { 12 | public static void Main(string[] args) 13 | { 14 | var config = new AWS.Logger.AWSLoggerConfig("AspNetCore.ConsoleSample"); 15 | config.Region = "us-east-1"; 16 | 17 | LoggerFactory logFactory = new LoggerFactory(); 18 | 19 | logFactory.AddAWSProvider(config); 20 | var logger = logFactory.CreateLogger(); 21 | 22 | logger.LogInformation("Check the AWS Console CloudWatch Logs console in us-east-1"); 23 | logger.LogInformation("to see messages in the log streams for the"); 24 | logger.LogInformation("log group AspNetCore.ConsoleSample"); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /samples/AspNetCore/ConsoleSample/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyConfiguration("")] 9 | [assembly: AssemblyCompany("")] 10 | [assembly: AssemblyProduct("ConsoleSample")] 11 | [assembly: AssemblyTrademark("")] 12 | 13 | // Setting ComVisible to false makes the types in this assembly not visible 14 | // to COM components. If you need to access a type in this assembly from 15 | // COM, set the ComVisible attribute to true on that type. 16 | [assembly: ComVisible(false)] 17 | 18 | // The following GUID is for the ID of the typelib if this project is exposed to COM 19 | [assembly: Guid("49860ddf-0a02-4d51-bf75-15b336455661")] 20 | -------------------------------------------------------------------------------- /samples/AspNetCore/WebSample/Pages/Index.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model IndexModel 3 | @{ 4 | ViewData["Title"] = "Home page"; 5 | } 6 | 7 |

Congrats on using the AWS Logging library for ASP.NET Core

8 |

9 | To see the log messages log onto the AWS Console and view the Cloud Watch Logs console. The log messages will be under the log group AspNetCore.WebSample. 10 |

-------------------------------------------------------------------------------- /samples/AspNetCore/WebSample/Pages/Index.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.AspNetCore.Mvc.RazorPages; 7 | using Microsoft.Extensions.Logging; 8 | 9 | namespace WebSample.Pages 10 | { 11 | public class IndexModel : PageModel 12 | { 13 | ILogger Logger { get; set; } 14 | 15 | public IndexModel(ILogger logger) 16 | { 17 | Logger = logger; 18 | } 19 | 20 | public void OnGet() 21 | { 22 | Logger.LogInformation("Welcome to the AWS Logger. You are viewing the home page"); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /samples/AspNetCore/WebSample/Pages/Shared/_CookieConsentPartial.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Http.Features 2 | 3 | @{ 4 | var consentFeature = Context.Features.Get(); 5 | var showBanner = !consentFeature?.CanTrack ?? false; 6 | var cookieString = consentFeature?.CreateConsentCookie(); 7 | } 8 | 9 | @if (showBanner) 10 | { 11 | 33 | 41 | } -------------------------------------------------------------------------------- /samples/AspNetCore/WebSample/Pages/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | @ViewData["Title"] - WebSample 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | @RenderBody() 25 |
26 |
27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 40 | 46 | 47 | 48 | 49 | @RenderSection("Scripts", required: false) 50 | 51 | 52 | -------------------------------------------------------------------------------- /samples/AspNetCore/WebSample/Pages/Shared/_ValidationScriptsPartial.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 12 | 18 | 19 | -------------------------------------------------------------------------------- /samples/AspNetCore/WebSample/Pages/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using WebSample 2 | @namespace WebSample.Pages 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | -------------------------------------------------------------------------------- /samples/AspNetCore/WebSample/Pages/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /samples/AspNetCore/WebSample/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.Logging; 10 | 11 | namespace WebSample 12 | { 13 | public class Program 14 | { 15 | public static void Main(string[] args) 16 | { 17 | CreateWebHostBuilder(args).Build().Run(); 18 | } 19 | 20 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 21 | WebHost.CreateDefaultBuilder(args) 22 | .ConfigureLogging(logging => 23 | { 24 | logging.AddAWSProvider(); 25 | 26 | // When you need logging below set the minimum level. Otherwise the logging framework will default to Informational for external providers. 27 | logging.SetMinimumLevel(LogLevel.Debug); 28 | }) 29 | .UseStartup(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /samples/AspNetCore/WebSample/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:53139", 7 | "sslPort": 44395 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "WebSample": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "applicationUrl": "https://localhost:5001;http://localhost:5000", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /samples/AspNetCore/WebSample/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.Http; 8 | using Microsoft.AspNetCore.HttpsPolicy; 9 | using Microsoft.AspNetCore.Mvc; 10 | using Microsoft.Extensions.Configuration; 11 | using Microsoft.Extensions.DependencyInjection; 12 | using Microsoft.Extensions.Hosting; 13 | using Microsoft.Extensions.Logging; 14 | 15 | namespace WebSample 16 | { 17 | public class Startup 18 | { 19 | public Startup(IConfiguration configuration, ILogger logger) 20 | { 21 | Configuration = configuration; 22 | this._logger = logger; 23 | } 24 | 25 | public IConfiguration Configuration { get; } 26 | 27 | private ILogger _logger; 28 | 29 | // This method gets called by the runtime. Use this method to add services to the container. 30 | public void ConfigureServices(IServiceCollection services) 31 | { 32 | services.AddRazorPages(); 33 | } 34 | 35 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 36 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 37 | { 38 | // Example Logging 39 | _logger.LogInformation("Check the AWS Console CloudWatch Logs console in us-east-1"); 40 | _logger.LogInformation("to see messages in the log streams for the"); 41 | _logger.LogInformation("log group AspNetCore.WebSample"); 42 | 43 | if (env.IsDevelopment()) 44 | { 45 | app.UseDeveloperExceptionPage(); 46 | } 47 | else 48 | { 49 | app.UseExceptionHandler("/Error"); 50 | app.UseHsts(); 51 | } 52 | 53 | app.UseHttpsRedirection(); 54 | app.UseStaticFiles(); 55 | app.UseCookiePolicy(); 56 | 57 | app.UseRouting(); 58 | 59 | app.UseAuthorization(); 60 | 61 | app.UseEndpoints(endpoints => 62 | { 63 | endpoints.MapRazorPages(); 64 | }); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /samples/AspNetCore/WebSample/WebSample.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /samples/AspNetCore/WebSample/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /samples/AspNetCore/WebSample/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "Region": "us-east-1", 4 | "LogGroup": "AspNetCore.WebSample", 5 | "LogLevel": { 6 | "Default": "Debug", 7 | "System": "Information", 8 | "Microsoft": "Information" 9 | } 10 | }, 11 | "AllowedHosts": "*" 12 | } 13 | -------------------------------------------------------------------------------- /samples/AspNetCore/WebSample/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | html { 2 | font-size: 14px; 3 | } 4 | 5 | @media (min-width: 768px) { 6 | html { 7 | font-size: 16px; 8 | } 9 | } 10 | 11 | html { 12 | position: relative; 13 | min-height: 100%; 14 | } 15 | 16 | body { 17 | margin-bottom: 60px; 18 | } -------------------------------------------------------------------------------- /samples/AspNetCore/WebSample/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws/aws-logging-dotnet/03bb4dc1e84495a318812ac683c338c05e9aa494/samples/AspNetCore/WebSample/wwwroot/favicon.ico -------------------------------------------------------------------------------- /samples/AspNetCore/WebSample/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 | -------------------------------------------------------------------------------- /samples/AspNetCore/WebSample/wwwroot/lib/bootstrap/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2021 Twitter, Inc. 4 | Copyright (c) 2011-2021 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 | -------------------------------------------------------------------------------- /samples/AspNetCore/WebSample/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Reboot v5.1.0 (https://getbootstrap.com/) 3 | * Copyright 2011-2021 The Bootstrap Authors 4 | * Copyright 2011-2021 Twitter, Inc. 5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) 7 | */*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important} 8 | /*# sourceMappingURL=bootstrap-reboot.min.css.map */ -------------------------------------------------------------------------------- /samples/AspNetCore/WebSample/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Reboot v5.1.0 (https://getbootstrap.com/) 3 | * Copyright 2011-2021 The Bootstrap Authors 4 | * Copyright 2011-2021 Twitter, Inc. 5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) 6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) 7 | */*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-right:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-right:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:right}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:right;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:right}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}[type=email],[type=number],[type=tel],[type=url]{direction:ltr}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important} 8 | /*# sourceMappingURL=bootstrap-reboot.rtl.min.css.map */ -------------------------------------------------------------------------------- /samples/AspNetCore/WebSample/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 | -------------------------------------------------------------------------------- /samples/AspNetCore/WebSample/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js: -------------------------------------------------------------------------------- 1 | // Unobtrusive validation support library for jQuery and jQuery Validate 2 | // Copyright (c) .NET Foundation. All rights reserved. 3 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 4 | // @version v3.2.11 5 | !function(a){"function"==typeof define&&define.amd?define("jquery.validate.unobtrusive",["jquery-validation"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery-validation")):jQuery.validator.unobtrusive=a(jQuery)}(function(a){function e(a,e,n){a.rules[e]=n,a.message&&(a.messages[e]=a.message)}function n(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function t(a){return a.replace(/([!"#$%&'()*+,.\/:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function r(a){return a.substr(0,a.lastIndexOf(".")+1)}function i(a,e){return 0===a.indexOf("*.")&&(a=a.replace("*.",e)),a}function o(e,n){var r=a(this).find("[data-valmsg-for='"+t(n[0].name)+"']"),i=r.attr("data-valmsg-replace"),o=i?a.parseJSON(i)!==!1:null;r.removeClass("field-validation-valid").addClass("field-validation-error"),e.data("unobtrusiveContainer",r),o?(r.empty(),e.removeClass("input-validation-error").appendTo(r)):e.hide()}function d(e,n){var t=a(this).find("[data-valmsg-summary=true]"),r=t.find("ul");r&&r.length&&n.errorList.length&&(r.empty(),t.addClass("validation-summary-errors").removeClass("validation-summary-valid"),a.each(n.errorList,function(){a("
  • ").html(this.message).appendTo(r)}))}function s(e){var n=e.data("unobtrusiveContainer");if(n){var t=n.attr("data-valmsg-replace"),r=t?a.parseJSON(t):null;n.addClass("field-validation-valid").removeClass("field-validation-error"),e.removeData("unobtrusiveContainer"),r&&n.empty()}}function l(e){var n=a(this),t="__jquery_unobtrusive_validation_form_reset";if(!n.data(t)){n.data(t,!0);try{n.data("validator").resetForm()}finally{n.removeData(t)}n.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors"),n.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}}function u(e){var n=a(e),t=n.data(v),r=a.proxy(l,e),i=f.unobtrusive.options||{},u=function(n,t){var r=i[n];r&&a.isFunction(r)&&r.apply(e,t)};return t||(t={options:{errorClass:i.errorClass||"input-validation-error",errorElement:i.errorElement||"span",errorPlacement:function(){o.apply(e,arguments),u("errorPlacement",arguments)},invalidHandler:function(){d.apply(e,arguments),u("invalidHandler",arguments)},messages:{},rules:{},success:function(){s.apply(e,arguments),u("success",arguments)}},attachValidation:function(){n.off("reset."+v,r).on("reset."+v,r).validate(this.options)},validate:function(){return n.validate(),n.valid()}},n.data(v,t)),t}var m,f=a.validator,v="unobtrusiveValidation";return f.unobtrusive={adapters:[],parseElement:function(e,n){var t,r,i,o=a(e),d=o.parents("form")[0];d&&(t=u(d),t.options.rules[e.name]=r={},t.options.messages[e.name]=i={},a.each(this.adapters,function(){var n="data-val-"+this.name,t=o.attr(n),s={};void 0!==t&&(n+="-",a.each(this.params,function(){s[this]=o.attr(n+this)}),this.adapt({element:e,form:d,message:t,params:s,rules:r,messages:i}))}),a.extend(r,{__dummy__:!0}),n||t.attachValidation())},parse:function(e){var n=a(e),t=n.parents().addBack().filter("form").add(n.find("form")).has("[data-val=true]");n.find("[data-val=true]").each(function(){f.unobtrusive.parseElement(this,!0)}),t.each(function(){var a=u(this);a&&a.attachValidation()})}},m=f.unobtrusive.adapters,m.add=function(a,e,n){return n||(n=e,e=[]),this.push({name:a,params:e,adapt:n}),this},m.addBool=function(a,n){return this.add(a,function(t){e(t,n||a,!0)})},m.addMinMax=function(a,n,t,r,i,o){return this.add(a,[i||"min",o||"max"],function(a){var i=a.params.min,o=a.params.max;i&&o?e(a,r,[i,o]):i?e(a,n,i):o&&e(a,t,o)})},m.addSingleVal=function(a,n,t){return this.add(a,[n||"val"],function(r){e(r,t||a,r.params[n])})},f.addMethod("__dummy__",function(a,e,n){return!0}),f.addMethod("regex",function(a,e,n){var t;return!!this.optional(e)||(t=new RegExp(n).exec(a),t&&0===t.index&&t[0].length===a.length)}),f.addMethod("nonalphamin",function(a,e,n){var t;return n&&(t=a.match(/\W/g),t=t&&t.length>=n),t}),f.methods.extension?(m.addSingleVal("accept","mimtype"),m.addSingleVal("extension","extension")):m.addSingleVal("extension","extension","accept"),m.addSingleVal("regex","pattern"),m.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"),m.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range"),m.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength"),m.add("equalto",["other"],function(n){var o=r(n.element.name),d=n.params.other,s=i(d,o),l=a(n.form).find(":input").filter("[name='"+t(s)+"']")[0];e(n,"equalTo",l)}),m.add("required",function(a){"INPUT"===a.element.tagName.toUpperCase()&&"CHECKBOX"===a.element.type.toUpperCase()||e(a,"required",!0)}),m.add("remote",["url","type","additionalfields"],function(o){var d={url:o.params.url,type:o.params.type||"GET",data:{}},s=r(o.element.name);a.each(n(o.params.additionalfields||o.element.name),function(e,n){var r=i(n,s);d.data[r]=function(){var e=a(o.form).find(":input").filter("[name='"+t(r)+"']");return e.is(":checkbox")?e.filter(":checked").val()||e.filter(":hidden").val()||"":e.is(":radio")?e.filter(":checked").val()||"":e.val()}}),e(o,"remote",d)}),m.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&e(a,"minlength",a.params.min),a.params.nonalphamin&&e(a,"nonalphamin",a.params.nonalphamin),a.params.regex&&e(a,"regex",a.params.regex)}),m.add("fileextensions",["extensions"],function(a){e(a,"extension",a.params.extensions)}),a(function(){f.unobtrusive.parse(document)}),f.unobtrusive}); 6 | -------------------------------------------------------------------------------- /samples/AspNetCore/WebSample/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 | -------------------------------------------------------------------------------- /samples/AspNetCore/WebSample/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 | -------------------------------------------------------------------------------- /samples/Log4net/BasicAWSCredentialsConfigurationExample/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /samples/Log4net/BasicAWSCredentialsConfigurationExample/BasicAWSCredentialsConfigurationExample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net472 5 | BasicAWSCredentialsConfigurationExample 6 | BasicAWSCredentialsConfigurationExample 7 | Exe 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | PreserveNewest 24 | Designer 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /samples/Log4net/BasicAWSCredentialsConfigurationExample/Program.cs: -------------------------------------------------------------------------------- 1 | using Amazon.Runtime; 2 | using AWS.Logger.Log4net; 3 | using log4net; 4 | using log4net.Layout; 5 | using log4net.Repository.Hierarchy; 6 | using System; 7 | using System.Linq; 8 | 9 | namespace BasicAWSCredentialsConfigurationExample 10 | { 11 | public class Program 12 | { 13 | private static readonly ILog log = LogManager.GetLogger(nameof(Program)); 14 | 15 | private const string logLayoutPattern = "%utcdate{yyyy-MM-ddTHH:mm:ss.fffZ} [%-5level] %logger - %message%newline"; 16 | private const string logGroup = "Log4net.BasicAWSCredentialsConfigurationExample"; 17 | private const string awsRegion = "ap-southeast-1"; 18 | 19 | public static void Main(string[] args) 20 | { 21 | var credentials = CreateCredentials(args); 22 | var appender = CreateAppender(credentials); 23 | 24 | //Get a reference to an existing logger name "Program" in log4net.config 25 | var hierarchy = (Hierarchy)log.Logger.Repository; 26 | var logger = hierarchy.GetLogger(nameof(Program)) as Logger; 27 | 28 | //Attach the CloudWatch Logs appender 29 | logger.AddAppender(appender); 30 | 31 | //Start writing log to CloudWatch Logs 32 | log.Info($"Check the AWS Console CloudWatch Logs console in {awsRegion} region"); 33 | log.Info("to see messages in the log streams for the"); 34 | log.Info($"log group {logGroup}"); 35 | } 36 | 37 | private static BasicAWSCredentials CreateCredentials(string[] args) 38 | { 39 | if (args == null || !args.Any()) 40 | { 41 | throw new ArgumentNullException( 42 | "args", 43 | "Please pass AWS API key and secret key as command line arguments" 44 | ); 45 | } 46 | 47 | //Warning!!! This is only a simple example, not for a production code. 48 | var awsApiKey = args[0]; 49 | var awsSecretKey = args[1]; 50 | 51 | //Output values to verify that we have pass a values from command line arguments 52 | Console.WriteLine( 53 | $"{nameof(awsApiKey)}: {awsApiKey.Substring(0, 8)}, " + 54 | $"{nameof(awsSecretKey)}: {awsSecretKey.Substring(0, 8)}" 55 | ); 56 | 57 | return new BasicAWSCredentials(awsApiKey, awsSecretKey); 58 | } 59 | 60 | private static AWSAppender CreateAppender(AWSCredentials credentials) 61 | { 62 | var patternLayout = new PatternLayout 63 | { 64 | ConversionPattern = logLayoutPattern 65 | }; 66 | patternLayout.ActivateOptions(); 67 | 68 | var appender = new AWSAppender 69 | { 70 | Layout = patternLayout, 71 | Credentials =credentials, 72 | LogGroup = logGroup, 73 | Region = awsRegion 74 | }; 75 | 76 | appender.ActivateOptions(); 77 | return appender; 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /samples/Log4net/BasicAWSCredentialsConfigurationExample/README.md: -------------------------------------------------------------------------------- 1 | #Introduction 2 | This project shows you how to configure AWS CloudWatch Logs with basic AWS credentials. 3 | 4 | It is useful for a project that is not hosted on an AWS environment, e.g. 5 | other dedicated servers, on-premise server. 6 | 7 | #How to run a project 8 | - Open a project with Visual Studio 9 | - In the Solution Explorer window, right click on the project name node. 10 | Select `Set as Startup Project` 11 | - Go to the project properties window 12 | - Select the Debug tab and then add your AWS API key and secret key to Command line arguments text box as 13 | the following pattern: `YouAwsApiKey YourAwsSecretKey` 14 | - Run a project with debugging by pressing `F5` 15 | - Log in to your AWS console, go to CloudWatch Logs. You should see a new log message in 16 | `Log4net.BasicAWSCredentialsConfigurationExample` group. -------------------------------------------------------------------------------- /samples/Log4net/BasicAWSCredentialsConfigurationExample/log4net.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /samples/Log4net/BasicAWSCredentialsConfigurationExample/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /samples/Log4net/ConfigExample/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /samples/Log4net/ConfigExample/ConfigExample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net472 5 | Log4netConfigExample 6 | Log4netConfigExample 7 | Exe 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | PreserveNewest 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /samples/Log4net/ConfigExample/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using log4net; 8 | using log4net.Config; 9 | 10 | namespace ConfigExample 11 | { 12 | class Program 13 | { 14 | static void Main(string[] args) 15 | { 16 | // Log4net is configured in the log4net.config which adds the AWS appender. 17 | XmlConfigurator.Configure(new System.IO.FileInfo("log4net.config")); 18 | 19 | ILog log = LogManager.GetLogger(typeof(Program)); 20 | log.Info("Check the AWS Console CloudWatch Logs console in us-east-1"); 21 | log.Info("to see messages in the log streams for the"); 22 | log.Info("log group Log4net.ConfigExample"); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /samples/Log4net/ConfigExample/log4net.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Log4net.ConfigExample 7 | us-east-1 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /samples/Log4net/ConfigExample/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /samples/Log4net/ProgrammaticConfigurationExample/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /samples/Log4net/ProgrammaticConfigurationExample/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using log4net; 8 | using log4net.Repository.Hierarchy; 9 | using log4net.Core; 10 | using log4net.Appender; 11 | using log4net.Layout; 12 | 13 | using AWS.Logger.Log4net; 14 | 15 | namespace ProgrammaticConfigurationExample 16 | { 17 | class Program 18 | { 19 | static void Main(string[] args) 20 | { 21 | ConfigureLog4net(); 22 | 23 | ILog log = LogManager.GetLogger(typeof(Program)); 24 | log.Info("Check the AWS Console CloudWatch Logs console in us-east-1"); 25 | log.Info("to see messages in the log streams for the"); 26 | log.Info("log group Log4net.ProgrammaticConfigurationExample"); 27 | } 28 | 29 | static void ConfigureLog4net() 30 | { 31 | Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository(); 32 | PatternLayout patternLayout = new PatternLayout(); 33 | 34 | patternLayout.ConversionPattern = "%-4timestamp [%thread] %-5level %logger %ndc - %message%newline"; 35 | patternLayout.ActivateOptions(); 36 | 37 | AWSAppender appender = new AWSAppender(); 38 | appender.Layout = patternLayout; 39 | 40 | // Set log group and region. Assume credentials will be found using the default profile or IAM credentials. 41 | appender.LogGroup = "Log4net.ProgrammaticConfigurationExample"; 42 | appender.Region = "us-east-1"; 43 | 44 | appender.ActivateOptions(); 45 | hierarchy.Root.AddAppender(appender); 46 | 47 | hierarchy.Root.Level = Level.All; 48 | hierarchy.Configured = true; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /samples/Log4net/ProgrammaticConfigurationExample/ProgrammaticConfigurationExample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net472 5 | ProgrammaticConfigurationExample 6 | ProgrammaticConfigurationExample 7 | Exe 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /samples/Log4net/ProgrammaticConfigurationExample/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /samples/NLog/ConfigExample/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /samples/NLog/ConfigExample/ConfigExample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net472 5 | NLogConfigExample 6 | NLogConfigExample 7 | Exe 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | Always 22 | Designer 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /samples/NLog/ConfigExample/NLog.config: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /samples/NLog/ConfigExample/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | using NLog; 9 | 10 | namespace NLog.ConfigExample 11 | { 12 | class Program 13 | { 14 | static void Main(string[] args) 15 | { 16 | // NLog is configured in the NLog.config 17 | Logger logger = LogManager.GetCurrentClassLogger(); 18 | logger.Info("Check the AWS Console CloudWatch Logs console in us-east-1"); 19 | logger.Info("to see messages in the log streams for the"); 20 | logger.Info("log group NLog.ConfigExample"); 21 | 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /samples/NLog/ConfigExample/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /samples/NLog/ProgrammaticConfigurationExample/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /samples/NLog/ProgrammaticConfigurationExample/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using NLog; 8 | using NLog.Targets; 9 | using NLog.Config; 10 | 11 | using NLog.AWS.Logger; 12 | 13 | namespace ProgrammaticConfigurationExample 14 | { 15 | class Program 16 | { 17 | static void Main(string[] args) 18 | { 19 | ConfigureNLog(); 20 | 21 | Logger logger = LogManager.GetCurrentClassLogger(); 22 | logger.Info("Check the AWS Console CloudWatch Logs console in us-east-1"); 23 | logger.Info("to see messages in the log streams for the"); 24 | logger.Info("log group NLog.ProgrammaticConfigurationExample"); 25 | } 26 | 27 | static void ConfigureNLog() 28 | { 29 | var config = new LoggingConfiguration(); 30 | 31 | var consoleTarget = new ColoredConsoleTarget(); 32 | config.AddTarget("console", consoleTarget); 33 | 34 | var awsTarget = new AWSTarget() 35 | { 36 | LogGroup = "NLog.ProgrammaticConfigurationExample", 37 | Region = "us-east-1" 38 | }; 39 | config.AddTarget("aws", awsTarget); 40 | 41 | config.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, consoleTarget)); 42 | config.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, awsTarget)); 43 | 44 | LogManager.Configuration = config; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /samples/NLog/ProgrammaticConfigurationExample/ProgrammaticConfigurationExample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net472 5 | ProgrammaticConfigurationExample 6 | ProgrammaticConfigurationExample 7 | Exe 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /samples/NLog/ProgrammaticConfigurationExample/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /samples/Serilog/SerilogTestCode/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Serilog; 3 | using AWS.Logger.SeriLog; 4 | using AWS.Logger; 5 | 6 | namespace SerilogTestCode 7 | { 8 | class Program 9 | { 10 | static void Main(string[] args) 11 | { 12 | AWSLoggerConfig configuration = new AWSLoggerConfig("Serilog.ConfigExample") 13 | { 14 | Region = "us-east-1" 15 | }; 16 | 17 | var logger = new LoggerConfiguration() 18 | .WriteTo.AWSSeriLog(configuration) 19 | .CreateLogger(); 20 | 21 | logger.Information("Hello!"); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /samples/Serilog/SerilogTestCode/SerilogTestCode.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /samples/Serilog/SerilogTestCodeFromConfig/Program.cs: -------------------------------------------------------------------------------- 1 | using Serilog; 2 | using Microsoft.Extensions.Configuration; 3 | 4 | namespace SerilogTestCodeFromConfig 5 | { 6 | class Program 7 | { 8 | static void Main(string[] args) 9 | { 10 | // logger configuration reads from appsettings.json 11 | var configuration = new ConfigurationBuilder() 12 | .AddJsonFile("appsettings.json") 13 | .Build(); 14 | 15 | var logger = new LoggerConfiguration() 16 | .ReadFrom.Configuration(configuration) 17 | .CreateLogger(); 18 | 19 | logger.Information("Hello!"); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /samples/Serilog/SerilogTestCodeFromConfig/SerilogTestCodeFromConfig.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | PreserveNewest 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /samples/Serilog/SerilogTestCodeFromConfig/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Serilog": { 3 | "Using": [ 4 | "AWS.Logger.SeriLog" 5 | ], 6 | "LogGroup": "Serilog.ConfigExample", 7 | "Region": "us-east-1", 8 | "MinimumLevel": "Information", 9 | "WriteTo": [ 10 | { 11 | "Name": "AWSSeriLog" 12 | } 13 | ] 14 | } 15 | } -------------------------------------------------------------------------------- /samples/Serilog/SerilogTestCodeFromConfigRestrictedToMinimumLevel/Program.cs: -------------------------------------------------------------------------------- 1 | using Serilog; 2 | using Microsoft.Extensions.Configuration; 3 | 4 | namespace SerilogTestCodeFromConfigRestrictedToMinimumLevel 5 | { 6 | class Program 7 | { 8 | static void Main(string[] args) 9 | { 10 | // logger configuration reads from appsettings.json 11 | var configuration = new ConfigurationBuilder() 12 | .AddJsonFile("appsettings.json") 13 | .Build(); 14 | 15 | var logger = new LoggerConfiguration() 16 | .ReadFrom.Configuration(configuration) 17 | .CreateLogger(); 18 | 19 | logger.Information("This should not log since restrictedToMinimumLevel is Error in appsettings.json!"); 20 | logger.Error("Hello!"); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /samples/Serilog/SerilogTestCodeFromConfigRestrictedToMinimumLevel/SerilogTestCodeFromConfigRestrictedToMinimumLevel.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net8.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | PreserveNewest 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /samples/Serilog/SerilogTestCodeFromConfigRestrictedToMinimumLevel/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Serilog": { 3 | "Using": [ 4 | "AWS.Logger.SeriLog" 5 | ], 6 | "LogGroup": "Serilog.ConfigExample", 7 | "Region": "us-east-1", 8 | "MinimumLevel": "Information", 9 | "WriteTo": [ 10 | { 11 | "Name": "AWSSeriLog", 12 | "Args": { 13 | "restrictedToMinimumLevel": "Error" 14 | } 15 | } 16 | ] 17 | } 18 | } -------------------------------------------------------------------------------- /src/AWS.Logger.AspNetCore/AWS.Logger.AspNetCore.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0;net8.0 5 | 6 | An AWS implementation of ASP.NET Core ILogger that records logging messages to Amazon CloudWatch Logs. 7 | Amazon Web Services 8 | Amazon Web Services 9 | AWS;Cloudwatch;Logger 10 | icon.png 11 | https://github.com/aws/aws-logging-dotnet 12 | LICENSE 13 | git 14 | https://github.com/aws/aws-logging-dotnet.git 15 | README.md 16 | 17 | $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb 18 | true 19 | true 20 | 21 | True 22 | ..\..\public.snk 23 | 24 | true 25 | true 26 | true 27 | snupkg 28 | 29 | 4.0.0 30 | 31 | 32 | 33 | true 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /src/AWS.Logger.AspNetCore/AWSLoggerFactoryExtensions.cs: -------------------------------------------------------------------------------- 1 | using AWS.Logger; 2 | using AWS.Logger.AspNetCore; 3 | using Microsoft.Extensions.Configuration; 4 | using System; 5 | 6 | namespace Microsoft.Extensions.Logging 7 | { 8 | /// 9 | /// Extensions methods for ILoggerFactory to add the AWS logging provider 10 | /// 11 | public static class AWSLoggerFactoryExtensions 12 | { 13 | /// 14 | /// Adds the AWS logging provider to the log factory using the configuration specified in the AWSLoggerConfig 15 | /// 16 | /// 17 | /// Configuration on how to connect to AWS and how the log messages should be sent. 18 | /// A custom formatter which accepts a LogLevel, a state, and an exception and returns the formatted log message. 19 | /// 20 | public static ILoggerFactory AddAWSProvider(this ILoggerFactory factory, AWSLoggerConfig config, Func formatter = null) 21 | { 22 | // If config is null. Assuming the logger is being activated in a debug environment 23 | // and skip adding the provider. We don't want to prevent developers running their application 24 | // locally because they don't have access or want to use AWS for their local development. 25 | if (config == null) 26 | { 27 | factory.CreateLogger("AWS.Logging.AspNetCore").LogWarning("AWSLoggerConfig is null, skipping adding AWS Logging provider."); 28 | return factory; 29 | } 30 | 31 | var provider = new AWSLoggerProvider(config, formatter); 32 | factory.AddProvider(provider); 33 | return factory; 34 | } 35 | 36 | /// 37 | /// Adds the AWS logging provider to the log factory using the configuration specified in the AWSLoggerConfig 38 | /// 39 | /// 40 | /// Configuration and loglevels on how to connect to AWS and how the log messages should be sent. 41 | /// A custom formatter which accepts a LogLevel, a state, and an exception and returns the formatted log message. 42 | /// 43 | public static ILoggerFactory AddAWSProvider(this ILoggerFactory factory, AWSLoggerConfigSection configSection, Func formatter = null) 44 | { 45 | // If configSection is null. Assuming the logger is being activated in a debug environment 46 | // and skip adding the provider. We don't want to prevent developers running their application 47 | // locally because they don't have access or want to use AWS for their local development. 48 | if (configSection == null) 49 | { 50 | factory.CreateLogger("AWS.Logging.AspNetCore").LogWarning("AWSLoggerConfigSection is null. LogGroup is likely not configured in config files. Skipping adding AWS Logging provider."); 51 | return factory; 52 | } 53 | 54 | var provider = new AWSLoggerProvider(configSection, formatter); 55 | factory.AddProvider(provider); 56 | return factory; 57 | } 58 | 59 | /// 60 | /// Adds the AWS logging provider to the log factory using the configuration specified in the AWSLoggerConfig 61 | /// 62 | /// 63 | /// Configuration on how to connect to AWS and how the log messages should be sent. 64 | /// The minimum log level for messages to be written. 65 | /// 66 | public static ILoggerFactory AddAWSProvider(this ILoggerFactory factory, AWSLoggerConfig config, LogLevel minLevel) 67 | { 68 | var provider = new AWSLoggerProvider(config, minLevel); 69 | factory.AddProvider(provider); 70 | return factory; 71 | } 72 | 73 | /// 74 | /// Adds the AWS logging provider to the log factory using the configuration specified in the AWSLoggerConfig 75 | /// 76 | /// 77 | /// Configuration on how to connect to AWS and how the log messages should be sent. 78 | /// A filter function that has the logger category name and log level which can be used to filter messages being sent to AWS. 79 | /// 80 | public static ILoggerFactory AddAWSProvider(this ILoggerFactory factory, AWSLoggerConfig config, Func filter) 81 | { 82 | var provider = new AWSLoggerProvider(config, filter); 83 | factory.AddProvider(provider); 84 | return factory; 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/AWS.Logger.AspNetCore/Constants.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace AWS.Logger.AspNetCore 6 | { 7 | internal class Constants 8 | { 9 | internal const bool IncludeScopesDefault = false; 10 | internal const bool IncludeLogLevelDefault = true; 11 | internal const bool IncludeCategoryDefault = true; 12 | internal const bool IncludeEventIdDefault = false; 13 | internal const bool IncludeNewlineDefault = true; 14 | internal const bool IncludeExceptionDefault = true; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/AWS.Logger.AspNetCore/NullExternalScopeProvider.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | using System; 3 | 4 | namespace AWS.Logger.AspNetCore 5 | { 6 | /// 7 | /// Scope provider that does nothing. 8 | /// 9 | internal sealed class NullExternalScopeProvider : IExternalScopeProvider 10 | { 11 | private NullExternalScopeProvider() 12 | { 13 | } 14 | 15 | /// 16 | /// Returns a cached instance of . 17 | /// 18 | public static IExternalScopeProvider Instance { get; } = new NullExternalScopeProvider(); 19 | 20 | /// 21 | void IExternalScopeProvider.ForEachScope(Action callback, TState state) 22 | { 23 | } 24 | 25 | /// 26 | IDisposable IExternalScopeProvider.Push(object state) 27 | { 28 | return NullScope.Instance; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/AWS.Logger.AspNetCore/NullScope.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace AWS.Logger.AspNetCore 4 | { 5 | /// 6 | /// An empty scope without any logic 7 | /// 8 | internal sealed class NullScope : IDisposable 9 | { 10 | public static NullScope Instance { get; } = new NullScope(); 11 | 12 | private NullScope() 13 | { 14 | } 15 | 16 | /// 17 | public void Dispose() 18 | { 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/AWS.Logger.AspNetCore/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // Setting ComVisible to false makes the types in this assembly not visible 6 | // to COM components. If you need to access a type in this assembly from 7 | // COM, set the ComVisible attribute to true on that type. 8 | [assembly: ComVisible(false)] 9 | 10 | // The following GUID is for the ID of the typelib if this project is exposed to COM 11 | [assembly: Guid("ec54d8db-9ecc-4026-9d00-bdde02af650a")] -------------------------------------------------------------------------------- /src/AWS.Logger.Core/AWS.Logger.Core.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net472;netstandard2.0;net8.0 5 | 6 | AWS Core logging library used to send logging messages to Amazon CloudWatch Logs 7 | Amazon Web Services 8 | Amazon Web Services 9 | AWS;Cloudwatch;Logger 10 | icon.png 11 | https://github.com/aws/aws-logging-dotnet 12 | LICENSE 13 | git 14 | https://github.com/aws/aws-logging-dotnet.git 15 | README.md 16 | 17 | $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb 18 | true 19 | true 20 | 21 | True 22 | False 23 | ..\..\public.snk 24 | 25 | true 26 | true 27 | true 28 | snupkg 29 | 30 | 4.0.0 31 | 32 | 33 | 34 | true 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /src/AWS.Logger.Core/Core/IAWSLoggerCore.cs: -------------------------------------------------------------------------------- 1 | namespace AWS.Logger.Core 2 | { 3 | /// 4 | /// Interface for sending messages to CloudWatch Logs 5 | /// 6 | public interface IAWSLoggerCore 7 | { 8 | /// 9 | /// Flushes all pending messages 10 | /// 11 | void Flush(); 12 | 13 | /// 14 | /// Flushes and Closes the background task 15 | /// 16 | void Close(); 17 | 18 | /// 19 | /// Sends message to CloudWatch Logs 20 | /// 21 | /// Message to log. 22 | void AddMessage(string message); 23 | 24 | /// 25 | /// Start background task for sending messages to CloudWatch Logs 26 | /// 27 | void StartMonitor(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/AWS.Logger.Core/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // Setting ComVisible to false makes the types in this assembly not visible 5 | // to COM components. If you need to access a type in this assembly from 6 | // COM, set the ComVisible attribute to true on that type. 7 | [assembly: ComVisible(false)] 8 | 9 | // The following GUID is for the ID of the typelib if this project is exposed to COM 10 | [assembly: Guid("d99fe4cd-0566-43f0-a339-b6fd7e603d10")] -------------------------------------------------------------------------------- /src/AWS.Logger.Log4net/AWS.Logger.Log4net.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net472;netstandard2.0;net8.0 5 | 6 | An AWS Log4net appender that records logging messages to Amazon CloudWatch Logs. 7 | Amazon Web Services 8 | Amazon Web Services 9 | AWS;Cloudwatch;Logger;Log4net 10 | icon.png 11 | https://github.com/aws/aws-logging-dotnet 12 | LICENSE 13 | git 14 | https://github.com/aws/aws-logging-dotnet.git 15 | README.md 16 | 17 | $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb 18 | true 19 | true 20 | 21 | True 22 | ..\..\public.snk 23 | 24 | true 25 | true 26 | true 27 | snupkg 28 | 29 | 4.0.0 30 | 31 | 32 | 33 | true 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /src/AWS.Logger.Log4net/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // Setting ComVisible to false makes the types in this assembly not visible 6 | // to COM components. If you need to access a type in this assembly from 7 | // COM, set the ComVisible attribute to true on that type. 8 | [assembly: ComVisible(false)] 9 | 10 | // The following GUID is for the ID of the typelib if this project is exposed to COM 11 | [assembly: Guid("78312e9b-bc7c-4af8-9153-dd72bbf4fd36")] 12 | -------------------------------------------------------------------------------- /src/AWS.Logger.SeriLog/AWS.Logger.SeriLog.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net472;netstandard2.0;net8.0 5 | 6 | An AWS SeriLog sink that records logging messages to Amazon CloudWatch Logs. 7 | Amazon Web Services 8 | Amazon Web Services 9 | AWS;Cloudwatch;Logger;Serilog 10 | icon.png 11 | https://github.com/aws/aws-logging-dotnet 12 | LICENSE 13 | git 14 | https://github.com/aws/aws-logging-dotnet.git 15 | README.md 16 | 17 | $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb 18 | true 19 | true 20 | 21 | True 22 | ..\..\public.snk 23 | 24 | true 25 | true 26 | true 27 | snupkg 28 | 29 | 4.0.0 30 | 31 | 32 | 33 | true 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/AWS.Logger.SeriLog/AWSLoggerSeriLogExtension.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Serilog; 3 | using Serilog.Configuration; 4 | using Serilog.Events; 5 | using Serilog.Formatting; 6 | using System; 7 | 8 | namespace AWS.Logger.SeriLog 9 | { 10 | /// 11 | /// Extensions methods for to register 12 | /// 13 | public static class AWSLoggerSeriLogExtension 14 | { 15 | internal const string LOG_GROUP = "Serilog:LogGroup"; 16 | internal const string DISABLE_LOG_GROUP_CREATION = "Serilog:DisableLogGroupCreation"; 17 | internal const string NEW_LOG_GROUP_RETENTION_IN_DAYS = "Serilog:NewLogGroupRetentionInDays"; 18 | internal const string REGION = "Serilog:Region"; 19 | internal const string SERVICEURL = "Serilog:ServiceUrl"; 20 | internal const string PROFILE = "Serilog:Profile"; 21 | internal const string PROFILE_LOCATION = "Serilog:ProfilesLocation"; 22 | internal const string BATCH_PUSH_INTERVAL = "Serilog:BatchPushInterval"; 23 | internal const string BATCH_PUSH_SIZE_IN_BYTES = "Serilog:BatchPushSizeInBytes"; 24 | internal const string MAX_QUEUED_MESSAGES = "Serilog:MaxQueuedMessages"; 25 | internal const string LOG_STREAM_NAME = "Serilog:LogStreamName"; 26 | internal const string LOG_STREAM_NAME_SUFFIX = "Serilog:LogStreamNameSuffix"; 27 | internal const string LOG_STREAM_NAME_PREFIX = "Serilog:LogStreamNamePrefix"; 28 | internal const string LIBRARY_LOG_FILE_NAME = "Serilog:LibraryLogFileName"; 29 | internal const string LIBRARY_LOG_ERRORS = "Serilog:LibraryLogErrors"; 30 | internal const string FLUSH_TIMEOUT = "Serilog:FlushTimeout"; 31 | internal const string AUTHENTICATION_REGION = "Serilog:AuthenticationRegion"; 32 | 33 | /// 34 | /// AWSSeriLogger target that is called when the customer is using 35 | /// Serilog.Settings.Configuration to set the SeriLogger configuration 36 | /// using a Json input. 37 | /// 38 | public static LoggerConfiguration AWSSeriLog( 39 | this LoggerSinkConfiguration loggerConfiguration, 40 | IConfiguration configuration, 41 | IFormatProvider iFormatProvider = null, 42 | ITextFormatter textFormatter = null, 43 | LogEventLevel restrictedToMinimumLevel = LogEventLevel.Verbose) 44 | { 45 | AWSLoggerConfig config = new AWSLoggerConfig(); 46 | 47 | config.LogGroup = configuration[LOG_GROUP]; 48 | if (configuration[DISABLE_LOG_GROUP_CREATION] != null) 49 | { 50 | config.DisableLogGroupCreation = bool.Parse(configuration[DISABLE_LOG_GROUP_CREATION]); 51 | } 52 | if (configuration[NEW_LOG_GROUP_RETENTION_IN_DAYS] is string s && int.TryParse(s, out var retentionInDays)) 53 | { 54 | config.NewLogGroupRetentionInDays = retentionInDays; 55 | } 56 | if (configuration[REGION] != null) 57 | { 58 | config.Region = configuration[REGION]; 59 | } 60 | if (configuration[SERVICEURL] != null) 61 | { 62 | config.ServiceUrl = configuration[SERVICEURL]; 63 | } 64 | if (configuration[PROFILE] != null) 65 | { 66 | config.Profile = configuration[PROFILE]; 67 | } 68 | if (configuration[PROFILE_LOCATION] != null) 69 | { 70 | config.ProfilesLocation = configuration[PROFILE_LOCATION]; 71 | } 72 | if (configuration[BATCH_PUSH_INTERVAL] != null) 73 | { 74 | config.BatchPushInterval = TimeSpan.FromMilliseconds(Int32.Parse(configuration[BATCH_PUSH_INTERVAL])); 75 | } 76 | if (configuration[BATCH_PUSH_SIZE_IN_BYTES] != null) 77 | { 78 | config.BatchSizeInBytes = Int32.Parse(configuration[BATCH_PUSH_SIZE_IN_BYTES]); 79 | } 80 | if (configuration[MAX_QUEUED_MESSAGES] != null) 81 | { 82 | config.MaxQueuedMessages = Int32.Parse(configuration[MAX_QUEUED_MESSAGES]); 83 | } 84 | if (configuration[LOG_STREAM_NAME] != null) 85 | { 86 | config.LogStreamName = configuration[LOG_STREAM_NAME]; 87 | } 88 | if (configuration[LOG_STREAM_NAME_SUFFIX] != null) 89 | { 90 | config.LogStreamNameSuffix = configuration[LOG_STREAM_NAME_SUFFIX]; 91 | } 92 | if (configuration[LOG_STREAM_NAME_PREFIX] != null) 93 | { 94 | config.LogStreamNamePrefix = configuration[LOG_STREAM_NAME_PREFIX]; 95 | } 96 | if (configuration[LIBRARY_LOG_FILE_NAME] != null) 97 | { 98 | config.LibraryLogFileName = configuration[LIBRARY_LOG_FILE_NAME]; 99 | } 100 | if (configuration[LIBRARY_LOG_ERRORS] != null) 101 | { 102 | config.LibraryLogErrors = Boolean.Parse(configuration[LIBRARY_LOG_ERRORS]); 103 | } 104 | if (configuration[FLUSH_TIMEOUT] != null) 105 | { 106 | config.FlushTimeout = TimeSpan.FromMilliseconds(Int32.Parse(configuration[FLUSH_TIMEOUT])); 107 | } 108 | if (configuration[AUTHENTICATION_REGION] != null) 109 | { 110 | config.AuthenticationRegion = configuration[AUTHENTICATION_REGION]; 111 | } 112 | 113 | return AWSSeriLog(loggerConfiguration, config, iFormatProvider, textFormatter, restrictedToMinimumLevel); 114 | } 115 | 116 | /// 117 | /// AWSSeriLogger target that is called when the customer 118 | /// explicitly creates a configuration of type AWSLoggerConfig 119 | /// to set the SeriLogger configuration. 120 | /// 121 | public static LoggerConfiguration AWSSeriLog( 122 | this LoggerSinkConfiguration loggerConfiguration, 123 | AWSLoggerConfig configuration = null, 124 | IFormatProvider iFormatProvider = null, 125 | ITextFormatter textFormatter = null, 126 | LogEventLevel restrictedToMinimumLevel = LogEventLevel.Verbose) 127 | { 128 | return loggerConfiguration.Sink(new AWSSink(configuration, iFormatProvider, textFormatter), restrictedToMinimumLevel); 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/AWS.Logger.SeriLog/AWSSink.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Reflection; 4 | using AWS.Logger.Core; 5 | using Serilog; 6 | using Serilog.Core; 7 | using Serilog.Events; 8 | using Serilog.Formatting; 9 | 10 | namespace AWS.Logger.SeriLog 11 | { 12 | /// 13 | /// A Serilog sink that can be used with the Serilogger logging library to send messages to AWS. 14 | /// 15 | public class AWSSink: ILogEventSink, IDisposable 16 | { 17 | AWSLoggerCore _core = null; 18 | IFormatProvider _iformatDriver; 19 | ITextFormatter _textFormatter; 20 | 21 | private static readonly string _assemblyVersion = typeof(AWSSink).GetTypeInfo().Assembly.GetName().Version?.ToString() ?? string.Empty; 22 | private static readonly string _userAgentString = $"aws-logger-serilog#{_assemblyVersion}"; 23 | 24 | /// 25 | /// Default constructor 26 | /// 27 | public AWSSink() 28 | { 29 | } 30 | 31 | /// 32 | /// Constructor called by AWSLoggerSeriLoggerExtension 33 | /// 34 | public AWSSink(AWSLoggerConfig loggerConfiguration, IFormatProvider iFormatProvider = null, ITextFormatter textFormatter = null) 35 | { 36 | _core = new AWSLoggerCore(loggerConfiguration, _userAgentString); 37 | _iformatDriver = iFormatProvider; 38 | _textFormatter = textFormatter; 39 | } 40 | 41 | /// 42 | /// Method called to pass the LogEvent to the AWSLogger Sink 43 | /// 44 | /// 45 | public void Emit(LogEvent logEvent) 46 | { 47 | var message = RenderLogEvent(logEvent); 48 | 49 | // If there is no custom formatter passed that would have taken care of logging the exception then append the 50 | // exception to the log if one exists. 51 | if (_textFormatter == null && logEvent.Exception != null) 52 | { 53 | message = string.Concat(message, Environment.NewLine, logEvent.Exception.ToString(), Environment.NewLine); 54 | } 55 | else 56 | { 57 | message = string.Concat(message, Environment.NewLine); 58 | } 59 | _core.AddMessage(message); 60 | } 61 | 62 | private string RenderLogEvent(LogEvent logEvent) 63 | { 64 | if (_iformatDriver == null && _textFormatter != null) 65 | { 66 | using (var writer = new StringWriter()) 67 | { 68 | _textFormatter.Format(logEvent, writer); 69 | writer.Flush(); 70 | return writer.ToString(); 71 | } 72 | } 73 | return logEvent.RenderMessage(_iformatDriver); 74 | } 75 | 76 | private bool disposedValue = false; // To detect redundant calls 77 | 78 | /// 79 | /// Disposable Pattern 80 | /// 81 | protected virtual void Dispose(bool disposing) 82 | { 83 | if (!disposedValue) 84 | { 85 | if (disposing) 86 | { 87 | try 88 | { 89 | _core.Close(); 90 | } 91 | catch (Exception) 92 | { 93 | // .. and as ugly as THIS is, .Dispose() methods shall not throw exceptions 94 | } 95 | } 96 | 97 | disposedValue = true; 98 | } 99 | } 100 | 101 | /// 102 | public void Dispose() 103 | { 104 | // Do not change this code. Put cleanup code in Dispose(bool disposing) above. 105 | Dispose(true); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/AWS.Logger.SeriLog/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // Setting ComVisible to false makes the types in this assembly not visible 6 | // to COM components. If you need to access a type in this assembly from 7 | // COM, set the ComVisible attribute to true on that type. 8 | [assembly: ComVisible(false)] 9 | 10 | // The following GUID is for the ID of the typelib if this project is exposed to COM 11 | [assembly: Guid("180041e5-49b9-4e81-b2ad-d67eb440325c")] -------------------------------------------------------------------------------- /src/NLog.AWS.Logger/NLog.AWS.Logger.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net472;netstandard2.0;net8.0 5 | 6 | AWS.Logger.NLog 7 | An AWS NLog target that records logging messages to Amazon CloudWatch Logs. 8 | Amazon Web Services 9 | Amazon Web Services 10 | AWS;Cloudwatch;Logger;NLog 11 | icon.png 12 | https://github.com/aws/aws-logging-dotnet 13 | LICENSE 14 | git 15 | https://github.com/aws/aws-logging-dotnet.git 16 | README.md 17 | 18 | $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb 19 | true 20 | true 21 | 22 | True 23 | ..\..\public.snk 24 | 25 | true 26 | true 27 | true 28 | snupkg 29 | 30 | 4.0.0 31 | 32 | 33 | 34 | true 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /src/NLog.AWS.Logger/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // Setting ComVisible to false makes the types in this assembly not visible 5 | // to COM components. If you need to access a type in this assembly from 6 | // COM, set the ComVisible attribute to true on that type. 7 | [assembly: ComVisible(false)] 8 | 9 | // The following GUID is for the ID of the typelib if this project is exposed to COM 10 | [assembly: Guid("284abc3b-da69-4038-a025-0212a6df65a3")] -------------------------------------------------------------------------------- /test/AWS.Logger.AspNetCore.Tests/AWS.Logger.AspNetCore.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | AWS.Logger.AspNetCore.Tests 6 | true 7 | false 8 | false 9 | true 10 | true 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /test/AWS.Logger.AspNetCore.Tests/DefaultFilterCheck.json: -------------------------------------------------------------------------------- 1 | { 2 | "AWS.Logging": { 3 | "LogGroup": "AWSILoggerGroup", 4 | "Region": "us-west-2", 5 | "LogLevel": { 6 | "Default": "Debug", 7 | "System": "Information", 8 | "Microsoft": "Information", 9 | "AWS": "Debug" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /test/AWS.Logger.AspNetCore.Tests/FakeCoreLogger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | using AWS.Logger.Core; 7 | using System.Collections.Concurrent; 8 | 9 | namespace AWS.Logger.AspNetCore.Tests 10 | { 11 | 12 | /// 13 | /// FakeCoreLogger class used to make mock test calls instead of the actual AWS CloudWatchLogs. 14 | /// Implements the IAWSLoggerCore interface of AWS Logger Core 15 | /// 16 | public class FakeCoreLogger : IAWSLoggerCore 17 | { 18 | public ConcurrentQueue ReceivedMessages { get; private set; } = new ConcurrentQueue(); 19 | 20 | public void AddMessage(string message) 21 | { 22 | ReceivedMessages.Enqueue(message); 23 | } 24 | 25 | public void Flush() 26 | { 27 | } 28 | 29 | public void Close() 30 | { 31 | } 32 | 33 | public void StartMonitor() 34 | { 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /test/AWS.Logger.AspNetCore.Tests/InValidAppsettingsFilter.json: -------------------------------------------------------------------------------- 1 | { 2 | "AWS.Logging": { 3 | "LogGroup": "AWSILoggerGroup", 4 | "Region": "us-west-2", 5 | "LogStreamNameSuffix": "TestStream", 6 | "LogLevel": { 7 | "System": "Information", 8 | "Microsoft": "Information", 9 | "AWS.Log": "Debug" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /test/AWS.Logger.AspNetCore.Tests/MissingLogLevelCheck.json: -------------------------------------------------------------------------------- 1 | { 2 | "AWS.Logging": { 3 | "LogGroup": "AWSILoggerGroup", 4 | "Region": "us-west-2", 5 | "LogStreamNameSuffix": "TestStream" 6 | } 7 | } -------------------------------------------------------------------------------- /test/AWS.Logger.AspNetCore.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyCompany("")] 9 | [assembly: AssemblyProduct("AWS.Logger.AspNetCore.Tests")] 10 | [assembly: AssemblyTrademark("")] 11 | 12 | // Setting ComVisible to false makes the types in this assembly not visible 13 | // to COM components. If you need to access a type in this assembly from 14 | // COM, set the ComVisible attribute to true on that type. 15 | [assembly: ComVisible(false)] 16 | 17 | // The following GUID is for the ID of the typelib if this project is exposed to COM 18 | [assembly: Guid("77b72c22-7b5c-4412-98bf-9714574d8ad6")] 19 | -------------------------------------------------------------------------------- /test/AWS.Logger.AspNetCore.Tests/TestConfigurationBase.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Text; 6 | 7 | namespace AWS.Logger.AspNetCore.Tests 8 | { 9 | /// 10 | /// provides access to methods helpful when dealing with configuration in .net core JSON form 11 | /// 12 | public class TestConfigurationBase 13 | { 14 | /// 15 | /// read IConfiguration from a JSON file, for testing purposes 16 | /// 17 | /// 18 | /// 19 | /// 20 | /// IConfiguration from a JSON file 21 | public IConfiguration LoggerConfigSectionSetup(string jsonFileName, string configSectionInfoBlockName, [System.Runtime.CompilerServices.CallerFilePath]string sourceFilePath = "") 22 | { 23 | var configurationBuilder = new ConfigurationBuilder() 24 | .SetBasePath(Path.GetDirectoryName(sourceFilePath)) 25 | .AddJsonFile(jsonFileName); 26 | 27 | IConfiguration Config; 28 | if (configSectionInfoBlockName != null) 29 | { 30 | Config = configurationBuilder 31 | .Build() 32 | .GetSection(configSectionInfoBlockName); 33 | } 34 | 35 | else 36 | { 37 | Config = configurationBuilder 38 | .Build() 39 | .GetSection("AWS.Logging"); 40 | } 41 | 42 | return Config; 43 | 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /test/AWS.Logger.AspNetCore.Tests/TestDisableLogGroupCreation.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.Extensions.Logging; 4 | using System; 5 | using System.Diagnostics; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Threading; 9 | using Xunit; 10 | using AWS.Logger.AspNetCore; 11 | using System.Threading.Tasks; 12 | using System.Collections.Generic; 13 | using Amazon.CloudWatchLogs; 14 | using Amazon.CloudWatchLogs.Model; 15 | using AWS.Logger.TestUtils; 16 | namespace AWS.Logger.AspNetCore.Tests 17 | { 18 | public class TestDisableLogGroupCreation : TestConfigurationBase 19 | { 20 | [Fact] 21 | public void TestMissingDisableLogGroupCreation() 22 | { 23 | var config = LoggerConfigSectionSetup("disableLogGroupCreationMissing.json", null); 24 | var typed = new AWSLoggerConfigSection(config); 25 | Assert.False(typed.Config.DisableLogGroupCreation); 26 | } 27 | 28 | [Fact] 29 | public void TestTrueDisableLogGroupCreation() 30 | { 31 | var config = LoggerConfigSectionSetup("disableLogGroupCreationTrue.json", null); 32 | var typed = new AWSLoggerConfigSection(config); 33 | Assert.True(typed.Config.DisableLogGroupCreation); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /test/AWS.Logger.AspNetCore.Tests/TestFormatter.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | using System; 3 | using System.Linq; 4 | using Xunit; 5 | 6 | namespace AWS.Logger.AspNetCore.Tests 7 | { 8 | public class TestFormatter 9 | { 10 | [Theory] 11 | [InlineData("my log message", LogLevel.Trace)] 12 | [InlineData("my log message", LogLevel.Debug)] 13 | [InlineData("my log message", LogLevel.Critical)] 14 | public void CustomFormatter_Must_Be_Applied(string message, LogLevel logLevel) 15 | { 16 | Func customFormatter 17 | = (level, state, ex) => level + " hello world" + state.ToString(); 18 | 19 | Func filter = (categoryName, level) => true; 20 | 21 | var coreLogger = new FakeCoreLogger(); 22 | 23 | var logger = new AWSLogger("TestCategory", coreLogger, filter, customFormatter); 24 | 25 | logger.Log(logLevel, 0, message, null, (state, ex) => state.ToString()); 26 | 27 | string expectedMessage = customFormatter(logLevel, message, null); 28 | 29 | Assert.Equal(expectedMessage, coreLogger.ReceivedMessages.First().Replace(Environment.NewLine, string.Empty)); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test/AWS.Logger.AspNetCore.Tests/TestScope.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Microsoft.Extensions.Logging; 4 | using Xunit; 5 | 6 | namespace AWS.Logger.AspNetCore.Tests 7 | { 8 | // This project can output the Class library as a NuGet Package. 9 | // To enable this option, right-click on the project and select the Properties menu item. In the Build tab select "Produce outputs on build". 10 | public class TestScope 11 | { 12 | [Fact] 13 | // Make sure that a message will be logged inside a scope, even when scopes are not included. 14 | public void MakeSureCanCreateScope() 15 | { 16 | var coreLogger = new FakeCoreLogger(); 17 | var logger = new AWSLogger("MakeSureCanCreateScope", coreLogger, null) 18 | { 19 | IncludeScopes = false 20 | }; 21 | 22 | using (logger.BeginScope("Test Scope")) 23 | { 24 | logger.LogInformation("log"); 25 | } 26 | 27 | Assert.Single(coreLogger.ReceivedMessages); 28 | Assert.True(coreLogger.ReceivedMessages.Contains($"[Information] MakeSureCanCreateScope: log{Environment.NewLine}"), "Messages don't contain actual log message."); 29 | } 30 | 31 | [Fact] 32 | // Make sure that a message will be logged outside a scope, even when scopes are included. 33 | public void MakeSureCanLogWithoutScope() 34 | { 35 | var coreLogger = new FakeCoreLogger(); 36 | var logger = new AWSLogger("MakeSureCanCreateScope", coreLogger, null) 37 | { 38 | IncludeScopes = true 39 | }; 40 | 41 | logger.LogInformation("log"); 42 | 43 | Assert.Single(coreLogger.ReceivedMessages); 44 | var msg = coreLogger.ReceivedMessages.SingleOrDefault(m => m.Contains($"[Information] MakeSureCanCreateScope: log{Environment.NewLine}")); 45 | Assert.True(msg != null, "Messages don't contain actual log message."); 46 | Assert.False(msg.Contains("=>"), "Fragment of scopes exists (\"=>\")."); 47 | } 48 | 49 | [Fact] 50 | // Make sure that a message inside a scope will be logged together with the scope. 51 | public void MakeSureScopeIsIncluded() 52 | { 53 | var coreLogger = new FakeCoreLogger(); 54 | var logger = new AWSLogger("MakeSureCanCreateScope", coreLogger, null) 55 | { 56 | IncludeScopes = true 57 | }; 58 | 59 | using (logger.BeginScope("Test scope")) 60 | { 61 | logger.LogInformation("log"); 62 | } 63 | 64 | Assert.Single(coreLogger.ReceivedMessages); 65 | var msg = coreLogger.ReceivedMessages.SingleOrDefault(m => m.Contains($"[Information] Test scope => MakeSureCanCreateScope: log{Environment.NewLine}")); 66 | Assert.True(msg != null, "Messages don't contain actual log message."); 67 | // Same message should contain the scope 68 | Assert.True(msg.Contains("Test scope => "), "Scope is not included."); 69 | } 70 | 71 | [Fact] 72 | // Make sure that a message inside multiple scopes will be logged together with the scopes. 73 | public void MakeSureScopesAreIncluded() 74 | { 75 | var coreLogger = new FakeCoreLogger(); 76 | var logger = new AWSLogger("MakeSureCanCreateScope", coreLogger, null) 77 | { 78 | IncludeScopes = true 79 | }; 80 | 81 | using (logger.BeginScope("OuterScope")) 82 | { 83 | using (logger.BeginScope("InnerScope")) 84 | { 85 | logger.LogInformation("log"); 86 | } 87 | } 88 | 89 | Assert.Single(coreLogger.ReceivedMessages); 90 | var msg = coreLogger.ReceivedMessages.SingleOrDefault(m => m.Contains($"[Information] OuterScope InnerScope => MakeSureCanCreateScope: log{Environment.NewLine}")); 91 | Assert.True(msg != null, "Messages don't contain actual log message."); 92 | // Same message should contain the scope 93 | Assert.True(msg.Contains("OuterScope"), "Outer scope is not included."); 94 | Assert.True(msg.Contains("InnerScope"), "Inner scope is not included."); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /test/AWS.Logger.AspNetCore.Tests/ValidAppsettingsFilter.json: -------------------------------------------------------------------------------- 1 | { 2 | "AWS.Logging": { 3 | "LogGroup": "AWSILoggerGroup", 4 | "Region": "us-west-2", 5 | "LogLevel": { 6 | "Default": "Debug", 7 | "System": "Information", 8 | "Microsoft": "Information", 9 | "AWS": "Debug" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /test/AWS.Logger.AspNetCore.Tests/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogGroup": "AWSILogger", 4 | "Region": "us-west-2", 5 | "LogStreamNameSuffix": "Custom", 6 | "LogStreamNamePrefix": "CustomPrefix", 7 | "LogLevel": { 8 | "Default": "Debug", 9 | "System": "Information", 10 | "Microsoft": "Information", 11 | "AWS": "Debug" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /test/AWS.Logger.AspNetCore.Tests/disableLogGroupCreationMissing.json: -------------------------------------------------------------------------------- 1 | { 2 | "AWS.Logging": { 3 | "LogGroup": "AWSILoggerGroup", 4 | "Region": "us-west-2", 5 | "LogStreamNameSuffix": "TestStream" 6 | } 7 | } -------------------------------------------------------------------------------- /test/AWS.Logger.AspNetCore.Tests/disableLogGroupCreationTrue.json: -------------------------------------------------------------------------------- 1 | { 2 | "AWS.Logging": { 3 | "LogGroup": "AWSILoggerGroup", 4 | "DisableLogGroupCreation": true, 5 | "Region": "us-west-2", 6 | "LogStreamNameSuffix": "TestStream" 7 | } 8 | } -------------------------------------------------------------------------------- /test/AWS.Logger.AspNetCore.Tests/multiThreadBufferFullTest.json: -------------------------------------------------------------------------------- 1 | { 2 | "AWS.Logging": { 3 | "LogGroup": "AWSILoggerGroupMultiThreadBufferFullTest", 4 | "Region": "us-west-2", 5 | "LogStreamNameSuffix": "TestStream", 6 | "MaxQueuedMessages": "100", 7 | "LogLevel": { 8 | "Default": "Debug", 9 | "System": "Information", 10 | "Microsoft": "Information", 11 | "AWS": "Debug" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /test/AWS.Logger.AspNetCore.Tests/multiThreadTest.json: -------------------------------------------------------------------------------- 1 | { 2 | "AWS.Logging": { 3 | "LogGroup": "AWSGroupILogger", 4 | "Region": "us-west-2", 5 | "LogLevel": { 6 | "Default": "Debug", 7 | "System": "Information", 8 | "Microsoft": "Information", 9 | "AWS": "Debug" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /test/AWS.Logger.AspNetCore.Tests/overrideLogStreamName.json: -------------------------------------------------------------------------------- 1 | { 2 | "AWS.Logging": { 3 | "LogGroup": "AWSILoggerGroupOverrideLogStreamName", 4 | "Region": "us-west-2", 5 | "LogStreamName": "CustomLogStream", 6 | "LogLevel": { 7 | "Default": "Debug", 8 | "System": "Information", 9 | "Microsoft": "Information", 10 | "AWS": "Debug" 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /test/AWS.Logger.Log4Net.FilterTests/AWS.Logger.Log4Net.FilterTests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0;net472 5 | AWS.Logger.Log4Net.FilterTests 6 | true 7 | false 8 | false 9 | Full 10 | true 11 | true 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /test/AWS.Logger.Log4Net.FilterTests/FakeAWSAppender.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using log4net.Appender; 4 | using log4net.Core; 5 | 6 | 7 | namespace AWS.Logger.Log4Net.FilterTests 8 | { 9 | /// 10 | /// A mock Log4net appender that sends logging messages to a mock AWS Logger Core. 11 | /// 12 | public class FakeAWSAppender : AppenderSkeleton 13 | { 14 | public FakeCoreLogger _core = new FakeCoreLogger(); 15 | 16 | protected override void Append(LoggingEvent loggingEvent) 17 | { 18 | if (_core == null) 19 | return; 20 | 21 | _core.AddMessage(RenderLoggingEvent(loggingEvent)); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/AWS.Logger.Log4Net.FilterTests/FakeCoreLogger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | using AWS.Logger.Core; 7 | using System.Collections.Concurrent; 8 | 9 | namespace AWS.Logger.Log4Net.FilterTests 10 | { 11 | public class FakeCoreLogger : IAWSLoggerCore 12 | { 13 | public ConcurrentQueue ReceivedMessages { get; private set; } = new ConcurrentQueue(); 14 | 15 | public void AddMessage(string message) 16 | { 17 | ReceivedMessages.Enqueue(message); 18 | } 19 | 20 | public void Flush() 21 | { 22 | } 23 | 24 | public void Close() 25 | { 26 | } 27 | 28 | public void StartMonitor() 29 | { 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test/AWS.Logger.Log4Net.FilterTests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | 9 | [assembly: AssemblyCompany("")] 10 | [assembly: AssemblyProduct("AWS.Logger.Log4Net.FilterTests")] 11 | [assembly: AssemblyCopyright("Copyright © 2016")] 12 | [assembly: AssemblyTrademark("")] 13 | 14 | // Setting ComVisible to false makes the types in this assembly not visible 15 | // to COM components. If you need to access a type in this assembly from 16 | // COM, set the ComVisible attribute to true on that type. 17 | [assembly: ComVisible(false)] 18 | 19 | // The following GUID is for the ID of the typelib if this project is exposed to COM 20 | [assembly: Guid("1a4e2bc7-cfe5-4532-9cfd-4dc1efa0ad82")] 21 | 22 | // Version information for an assembly consists of the following four values: 23 | // 24 | // Major Version 25 | // Minor Version 26 | // Build Number 27 | // Revision 28 | // 29 | // You can specify all the values or you can default the Build and Revision Numbers 30 | // by using the '*' as shown below: 31 | // [assembly: AssemblyVersion("1.0.*")] 32 | -------------------------------------------------------------------------------- /test/AWS.Logger.Log4Net.FilterTests/TestFilter.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | using System; 3 | using System.IO; 4 | using System.Reflection; 5 | using System.Linq; 6 | using log4net.Repository.Hierarchy; 7 | using log4net; 8 | using log4net.Layout; 9 | using log4net.Core; 10 | 11 | namespace AWS.Logger.Log4Net.FilterTests 12 | { 13 | public class TestFilter 14 | { 15 | static Assembly repositoryAssembly = typeof(TestFilter).GetTypeInfo().Assembly; 16 | 17 | 18 | [Fact] 19 | public void FilterLogLevel() 20 | { 21 | FakeAWSAppender awsAppender; 22 | ILog logger; 23 | Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository(repositoryAssembly); 24 | PatternLayout patternLayout = new PatternLayout(); 25 | 26 | patternLayout.ConversionPattern = "%-4timestamp [%thread] %-5level %logger %ndc - %message%newline"; 27 | patternLayout.ActivateOptions(); 28 | 29 | awsAppender = new FakeAWSAppender(); 30 | awsAppender.Layout = patternLayout; 31 | 32 | var filter = new log4net.Filter.LevelRangeFilter(); 33 | filter.LevelMax = Level.Fatal; 34 | filter.LevelMin = Level.Warn; 35 | awsAppender.AddFilter(filter); 36 | 37 | awsAppender.ActivateOptions(); 38 | 39 | hierarchy.Root.AddAppender(awsAppender); 40 | 41 | hierarchy.Root.Level = Level.All; 42 | hierarchy.Configured = true; 43 | logger = LogManager.GetLogger(repositoryAssembly, "FilterLogLevel"); 44 | 45 | logger.Debug("debug"); 46 | logger.Info("information"); 47 | logger.Warn("warning"); 48 | logger.Error("error"); 49 | logger.Fatal("fatal"); 50 | 51 | Assert.Equal(3, awsAppender._core.ReceivedMessages.Count); 52 | Assert.Contains("warning", awsAppender._core.ReceivedMessages.ElementAt(0)); 53 | Assert.Contains("error", awsAppender._core.ReceivedMessages.ElementAt(1)); 54 | Assert.Contains("fatal", awsAppender._core.ReceivedMessages.ElementAt(2)); 55 | } 56 | 57 | [Fact] 58 | public void CustomFilter() 59 | { 60 | FakeAWSAppender awsAppender; 61 | ILog logger; 62 | Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository(repositoryAssembly); 63 | PatternLayout patternLayout = new PatternLayout(); 64 | 65 | patternLayout.ConversionPattern = "%logger %ndc - %message%newline"; 66 | patternLayout.ActivateOptions(); 67 | 68 | awsAppender = new FakeAWSAppender(); 69 | awsAppender.Layout = patternLayout; 70 | 71 | var filterName = new log4net.Filter.LoggerMatchFilter(); 72 | filterName.LoggerToMatch = "badCategory"; 73 | filterName.AcceptOnMatch = false; 74 | awsAppender.AddFilter(filterName); 75 | 76 | awsAppender.ActivateOptions(); 77 | 78 | hierarchy.Root.AddAppender(awsAppender); 79 | 80 | hierarchy.Root.Level = Level.All; 81 | hierarchy.Configured = true; 82 | 83 | logger = LogManager.GetLogger(repositoryAssembly,"goodCategory"); 84 | 85 | logger.Debug("trace"); 86 | logger.Warn("warning"); 87 | 88 | Assert.Equal(2, awsAppender._core.ReceivedMessages.Count); 89 | Assert.Contains("warning", awsAppender._core.ReceivedMessages.ElementAt(1)); 90 | string val; 91 | while (!awsAppender._core.ReceivedMessages.IsEmpty) 92 | { 93 | awsAppender._core.ReceivedMessages.TryDequeue(out val); 94 | } 95 | 96 | logger = LogManager.GetLogger(repositoryAssembly,"badCategory"); 97 | 98 | logger.Debug("trace"); 99 | logger.Warn("warning"); 100 | 101 | Assert.Empty(awsAppender._core.ReceivedMessages); 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /test/AWS.Logger.Log4Net.Tests/AWS.Logger.Log4Net.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0;net472 5 | AWS.Logger.Log4Net.Tests 6 | true 7 | false 8 | false 9 | Full 10 | true 11 | true 12 | 13 | 14 | 15 | 16 | PreserveNewest 17 | 18 | 19 | PreserveNewest 20 | 21 | 22 | PreserveNewest 23 | Designer 24 | 25 | 26 | PreserveNewest 27 | Designer 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /test/AWS.Logger.Log4Net.Tests/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/AWS.Logger.Log4Net.Tests/MultiThreadBufferFullTest.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | {LOG_GROUP_NAME} 7 | us-west-2 8 | 10 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /test/AWS.Logger.Log4Net.Tests/MultiThreadTest.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | {LOG_GROUP_NAME} 7 | us-west-2 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /test/AWS.Logger.Log4Net.Tests/OverrideLogStreamName.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | {LOG_GROUP_NAME} 8 | CustomStreamName 9 | us-west-2 10 | Custom 11 | CustomPrefix 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /test/AWS.Logger.Log4Net.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | 9 | [assembly: AssemblyCompany("")] 10 | [assembly: AssemblyProduct("AWS.Logger.Log4Net.Tests")] 11 | [assembly: AssemblyCopyright("Copyright © 2016")] 12 | [assembly: AssemblyTrademark("")] 13 | 14 | // Setting ComVisible to false makes the types in this assembly not visible 15 | // to COM components. If you need to access a type in this assembly from 16 | // COM, set the ComVisible attribute to true on that type. 17 | [assembly: ComVisible(false)] 18 | 19 | // The following GUID is for the ID of the typelib if this project is exposed to COM 20 | [assembly: Guid("91cf836a-4d1c-489f-9475-6c7c2673d617")] 21 | 22 | // Version information for an assembly consists of the following four values: 23 | // 24 | // Major Version 25 | // Minor Version 26 | // Build Number 27 | // Revision 28 | // 29 | // You can specify all the values or you can default the Build and Revision Numbers 30 | // by using the '*' as shown below: 31 | // [assembly: AssemblyVersion("1.0.*")] 32 | 33 | [assembly: Xunit.CollectionBehavior(DisableTestParallelization = true)] -------------------------------------------------------------------------------- /test/AWS.Logger.Log4Net.Tests/TestClass.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Text; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | using AWS.Logger.Log4net; 9 | using AWS.Logger.TestUtils; 10 | using log4net; 11 | using log4net.Config; 12 | using Xunit; 13 | 14 | namespace AWS.Logger.Log4Net.Tests 15 | { 16 | public class Log4NetTestClass : BaseTestClass 17 | { 18 | public ILog Logger; 19 | 20 | private void GetLog4NetLogger(string fileName, string logName, string logGroupName) 21 | { 22 | // Create logger 23 | var repositoryAssembly = typeof(Log4NetTestClass).GetTypeInfo().Assembly; 24 | var loggerRepository = LogManager.GetRepository(repositoryAssembly); 25 | var fileInfo = new FileInfo(fileName); 26 | var fileContent = File.ReadAllText(fileInfo.FullName); 27 | using (Stream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(fileContent.Replace("{LOG_GROUP_NAME}", logGroupName)))) 28 | { 29 | XmlConfigurator.Configure(loggerRepository, memoryStream); 30 | Logger = LogManager.GetLogger(repositoryAssembly, logName); 31 | } 32 | } 33 | 34 | public Log4NetTestClass(TestFixture testFixture) : base(testFixture) 35 | { 36 | } 37 | 38 | #region Test Cases 39 | [Fact] 40 | public async Task Log4Net() 41 | { 42 | var logGroupName = $"AWSLog4NetGroupLog4Net{Guid.NewGuid().ToString().Split('-').Last()}"; 43 | GetLog4NetLogger("log4net.config","Log4Net", logGroupName); 44 | await SimpleLoggingTest(logGroupName); 45 | } 46 | 47 | [Fact] 48 | public async Task MultiThreadTest() 49 | { 50 | var logGroupName = $"AWSLog4NetGroupLog4NetMultiThreadTest{Guid.NewGuid().ToString().Split('-').Last()}"; 51 | GetLog4NetLogger("MultiThreadTest.config", "MultiThreadTest", logGroupName); 52 | await MultiThreadTestGroup(logGroupName); 53 | } 54 | 55 | [Fact] 56 | public async Task MultiThreadBufferFullTest() 57 | { 58 | var logGroupName = $"AWSLog4NetGroupMultiThreadBufferFullTest{Guid.NewGuid().ToString().Split('-').Last()}"; 59 | GetLog4NetLogger("MultiThreadBufferFullTest.config", "MultiThreadBufferFullTest", logGroupName); 60 | await MultiThreadBufferFullTestGroup(logGroupName); 61 | } 62 | 63 | /// 64 | /// Verifies that multiple producers can log to the same log stream 65 | /// when an override log stream name is provided 66 | /// 67 | [Fact] 68 | public async Task CustomLogStreamNameTest() 69 | { 70 | var logGroupName = $"AWSLog4NetGroupMultiThreadBufferFullTest{Guid.NewGuid().ToString().Split('-').Last()}"; 71 | GetLog4NetLogger("OverrideLogStreamName.config", "OverrideLogStreamName", logGroupName); 72 | await MultiThreadTestGroup(logGroupName); 73 | } 74 | 75 | protected override void LogMessages(int count) 76 | { 77 | for (int i = 0; i < count-1; i++) 78 | { 79 | Logger.Debug(string.Format("Test logging message {0} Log4Net, Thread Id:{1}", i, Environment.CurrentManagedThreadId)); 80 | } 81 | Logger.Debug(LASTMESSAGE); 82 | } 83 | #endregion 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /test/AWS.Logger.Log4Net.Tests/log4net.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | {LOG_GROUP_NAME} 8 | us-west-2 9 | Custom 10 | CustomPrefix 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /test/AWS.Logger.Log4Net.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/AWS.Logger.NLog.FilterTests/AWS.Logger.NLog.FilterTests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0;net472 5 | AWS.Logger.NLog.FilterTests 6 | true 7 | false 8 | false 9 | Full 10 | true 11 | true 12 | 13 | 14 | 15 | 16 | PreserveNewest 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /test/AWS.Logger.NLog.FilterTests/FakeAWSTarget.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NLog; 3 | using NLog.Common; 4 | using NLog.Targets; 5 | 6 | namespace AWS.Logger.NLogger.FilterTests 7 | { 8 | [Target("FakeAWSTarget")] 9 | public class FakeAWSTarget : TargetWithLayout 10 | { 11 | public FakeCoreLogger _core; 12 | 13 | public FakeAWSTarget(TimeSpan asyncDelay = default(TimeSpan)) 14 | { 15 | _core = new FakeCoreLogger(asyncDelay); 16 | } 17 | 18 | protected override void Write(LogEventInfo logEvent) 19 | { 20 | var message = this.Layout.Render(logEvent); 21 | _core.AddMessage(message); 22 | } 23 | 24 | protected override void FlushAsync(AsyncContinuation asyncContinuation) 25 | { 26 | try 27 | { 28 | _core.Flush(); 29 | asyncContinuation(null); 30 | } 31 | catch (Exception ex) 32 | { 33 | asyncContinuation(ex); 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /test/AWS.Logger.NLog.FilterTests/FakeCoreLogger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | 5 | using AWS.Logger.Core; 6 | using System.Collections.Concurrent; 7 | 8 | namespace AWS.Logger.NLogger.FilterTests 9 | { 10 | public class FakeCoreLogger : IAWSLoggerCore 11 | { 12 | ConcurrentQueue _pendingMessages = new ConcurrentQueue(); 13 | public ConcurrentQueue ReceivedMessages { get; private set; } = new ConcurrentQueue(); 14 | private SemaphoreSlim _flushTriggerEvent; 15 | private ManualResetEventSlim _flushCompletedEvent; 16 | private CancellationTokenSource _closeTokenSource; 17 | TimeSpan _asyncDelay; 18 | 19 | public FakeCoreLogger(TimeSpan asyncDelay = default(TimeSpan)) 20 | { 21 | _asyncDelay = asyncDelay; 22 | } 23 | 24 | public void AddMessage(string message) 25 | { 26 | if (_asyncDelay == TimeSpan.Zero) 27 | { 28 | ReceivedMessages.Enqueue(message); 29 | } 30 | else 31 | { 32 | if (_flushTriggerEvent == null) 33 | { 34 | _flushTriggerEvent = new SemaphoreSlim(0, 1); 35 | _flushCompletedEvent = new ManualResetEventSlim(false); 36 | _closeTokenSource = new CancellationTokenSource(); 37 | Task.Run(async () => 38 | { 39 | await Task.Delay(100).ConfigureAwait(false); // Simulate slow connection 40 | 41 | bool flushNow = false; 42 | do 43 | { 44 | while (_pendingMessages.TryDequeue(out var msg)) 45 | { 46 | await Task.Delay(50); 47 | ReceivedMessages.Enqueue(msg); 48 | } 49 | if (flushNow) 50 | _flushCompletedEvent.Set(); 51 | flushNow = await _flushTriggerEvent.WaitAsync(_asyncDelay); 52 | } while (!_closeTokenSource.IsCancellationRequested); 53 | }, _closeTokenSource.Token); 54 | } 55 | 56 | _pendingMessages.Enqueue(message); 57 | } 58 | } 59 | 60 | public void Flush() 61 | { 62 | if (_flushTriggerEvent != null) 63 | { 64 | bool lockTaken = false; 65 | try 66 | { 67 | // Ensure only one thread executes the flush operation 68 | System.Threading.Monitor.TryEnter(_flushTriggerEvent, ref lockTaken); 69 | if (lockTaken) 70 | { 71 | _flushCompletedEvent.Reset(); 72 | _flushTriggerEvent.Release(); // Signal Monitor-Task to start premature flush 73 | } 74 | _flushCompletedEvent.Wait(TimeSpan.FromSeconds(15)); 75 | } 76 | finally 77 | { 78 | if (lockTaken) 79 | System.Threading.Monitor.Exit(_flushTriggerEvent); 80 | } 81 | } 82 | } 83 | 84 | public void Close() 85 | { 86 | Flush(); 87 | _closeTokenSource.Cancel(); 88 | } 89 | 90 | public void StartMonitor() 91 | { 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /test/AWS.Logger.NLog.FilterTests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyCompany("")] 9 | [assembly: AssemblyProduct("AWS.Logger.NLog.FilterTests")] 10 | [assembly: AssemblyTrademark("")] 11 | 12 | // Setting ComVisible to false makes the types in this assembly not visible 13 | // to COM components. If you need to access a type in this assembly from 14 | // COM, set the ComVisible attribute to true on that type. 15 | [assembly: ComVisible(false)] 16 | 17 | // The following GUID is for the ID of the typelib if this project is exposed to COM 18 | [assembly: Guid("48377844-b524-46ac-b465-246a1552fe64")] 19 | -------------------------------------------------------------------------------- /test/AWS.Logger.NLog.FilterTests/TestFilter.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | using System; 3 | using System.IO; 4 | using System.Reflection; 5 | using System.Linq; 6 | using NLog.Config; 7 | using NLog; 8 | using NLog.Filters; 9 | 10 | namespace AWS.Logger.NLogger.FilterTests 11 | { 12 | public class TestFilter 13 | { 14 | [Fact] 15 | public void FilterLogLevel() 16 | { 17 | var config = new LoggingConfiguration(); 18 | FakeAWSTarget proxyawsTarget = new FakeAWSTarget(); 19 | config.AddTarget("FakeAWSTarget", proxyawsTarget); 20 | config.AddRule(LogLevel.Warn, LogLevel.Fatal, proxyawsTarget, "FilterLogLevel"); 21 | LogManager.Configuration = config; 22 | var logger = LogManager.GetLogger("FilterLogLevel"); 23 | 24 | logger.Trace("trace"); 25 | logger.Debug("debug"); 26 | logger.Info("information"); 27 | logger.Warn("warning"); 28 | logger.Error("error"); 29 | logger.Fatal("fatal"); 30 | 31 | Assert.Equal(3, proxyawsTarget._core.ReceivedMessages.Count); 32 | Assert.Contains("warning", proxyawsTarget._core.ReceivedMessages.ElementAt(0)); 33 | Assert.Contains("error", proxyawsTarget._core.ReceivedMessages.ElementAt(1)); 34 | Assert.Contains("fatal", proxyawsTarget._core.ReceivedMessages.ElementAt(2)); 35 | } 36 | 37 | [Fact] 38 | public void CustomFilter() 39 | { 40 | var filter = new ConditionBasedFilter(); 41 | filter.Condition = "starts-with('${message}','badCategory')"; 42 | filter.Action = FilterResult.Ignore; 43 | 44 | FakeAWSTarget fakeawsTarget = new FakeAWSTarget(); 45 | var config = new LoggingConfiguration(); 46 | config.AddTarget("FakeAWSTarget", fakeawsTarget); 47 | 48 | var rule = new LoggingRule("CustomFilter", LogLevel.Warn,LogLevel.Fatal, fakeawsTarget); 49 | rule.Filters.Add(filter); 50 | 51 | config.LoggingRules.Add(rule); 52 | 53 | LogManager.Configuration = config; 54 | 55 | var logger = LogManager.GetLogger("CustomFilter"); 56 | 57 | logger.Trace("goodCategory|trace"); 58 | logger.Fatal("goodCategory|fatal"); 59 | 60 | Assert.Single(fakeawsTarget._core.ReceivedMessages); 61 | Assert.Contains("fatal", fakeawsTarget._core.ReceivedMessages.ElementAt(0)); 62 | 63 | string val; 64 | while (!fakeawsTarget._core.ReceivedMessages.IsEmpty) 65 | { 66 | fakeawsTarget._core.ReceivedMessages.TryDequeue(out val); 67 | } 68 | 69 | logger.Trace("badCategory|trace"); 70 | logger.Warn("badCategory|warning"); 71 | 72 | Assert.Empty(fakeawsTarget._core.ReceivedMessages); 73 | } 74 | 75 | [Fact] 76 | public void AsyncFlushLogLevel() 77 | { 78 | var config = new LoggingConfiguration(); 79 | FakeAWSTarget proxyawsTarget = new FakeAWSTarget(TimeSpan.FromSeconds(10)); 80 | config.AddTarget("FakeAWSTarget", proxyawsTarget); 81 | config.AddRule(LogLevel.Warn, LogLevel.Fatal, proxyawsTarget, "FilterLogLevel"); 82 | LogManager.Configuration = config; 83 | var logger = LogManager.GetLogger("FilterLogLevel"); 84 | 85 | logger.Trace("trace"); 86 | logger.Debug("debug"); 87 | logger.Info("information"); 88 | logger.Warn("warning"); 89 | 90 | Assert.Empty(proxyawsTarget._core.ReceivedMessages); 91 | LogManager.Flush(); 92 | Assert.Single(proxyawsTarget._core.ReceivedMessages); 93 | 94 | logger.Error("error"); 95 | logger.Fatal("fatal"); 96 | 97 | LogManager.Flush(); 98 | 99 | Assert.Equal(3, proxyawsTarget._core.ReceivedMessages.Count); 100 | Assert.Contains("warning", proxyawsTarget._core.ReceivedMessages.ElementAt(0)); 101 | Assert.Contains("error", proxyawsTarget._core.ReceivedMessages.ElementAt(1)); 102 | Assert.Contains("fatal", proxyawsTarget._core.ReceivedMessages.ElementAt(2)); 103 | } 104 | 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /test/AWS.Logger.NLog.Tests/AWS.Logger.NLog.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0;net472 5 | AWS.Logger.NLog.Tests 6 | true 7 | false 8 | false 9 | Full 10 | true 11 | true 12 | 13 | 14 | 15 | 16 | PreserveNewest 17 | 18 | 19 | PreserveNewest 20 | 21 | 22 | PreserveNewest 23 | 24 | 25 | PreserveNewest 26 | 27 | 28 | PreserveNewest 29 | 30 | 31 | PreserveNewest 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /test/AWS.Logger.NLog.Tests/AWSNLogGroupEventSizeExceededTest.config: -------------------------------------------------------------------------------- 1 |  2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/AWS.Logger.NLog.Tests/AWSNLogGroupMultiThreadBufferFullTest.config: -------------------------------------------------------------------------------- 1 |  2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/AWS.Logger.NLog.Tests/AWSNLogGroupMultiThreadTest.config: -------------------------------------------------------------------------------- 1 |  2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/AWS.Logger.NLog.Tests/AWSNLogOverrideLogStreamName.config: -------------------------------------------------------------------------------- 1 |  2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/AWS.Logger.NLog.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyCompany("")] 9 | [assembly: AssemblyProduct("AWS.Logger.Test")] 10 | [assembly: AssemblyTrademark("")] 11 | 12 | // Setting ComVisible to false makes the types in this assembly not visible 13 | // to COM components. If you need to access a type in this assembly from 14 | // COM, set the ComVisible attribute to true on that type. 15 | [assembly: ComVisible(false)] 16 | 17 | // The following GUID is for the ID of the typelib if this project is exposed to COM 18 | [assembly: Guid("f7986868-9d7e-4df6-a57e-e79e38ad166d")] 19 | -------------------------------------------------------------------------------- /test/AWS.Logger.NLog.Tests/Regular.config: -------------------------------------------------------------------------------- 1 |  2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/AWS.Logger.NLog.Tests/TestClass.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using System.Xml; 8 | using Amazon.CloudWatchLogs.Model; 9 | using AWS.Logger.TestUtils; 10 | using NLog; 11 | using NLog.Config; 12 | using Xunit; 13 | 14 | namespace AWS.Logger.NLogger.Tests 15 | { 16 | // This project can output the Class library as a NuGet Package. 17 | // To enable this option, right-click on the project and select the Properties menu item. In the Build tab select "Produce outputs on build". 18 | public class NLogTestClass: BaseTestClass 19 | { 20 | public NLog.Logger Logger; 21 | 22 | private void CreateLoggerFromConfiguration(string configFileName, string logGroupName) 23 | { 24 | var fileInfo = new FileInfo(configFileName); 25 | var fileContent = File.ReadAllText(fileInfo.FullName); 26 | using (Stream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(fileContent.Replace("{LOG_GROUP_NAME}", logGroupName)))) 27 | using (XmlReader reader = XmlReader.Create(memoryStream)) 28 | { 29 | LogManager.Configuration = new XmlLoggingConfiguration(reader, configFileName); 30 | } 31 | } 32 | 33 | public NLogTestClass(TestFixture testFixture) : base(testFixture) 34 | { 35 | } 36 | 37 | #region Test Cases 38 | [Fact] 39 | public async Task Nlog() 40 | { 41 | var logGroupName = $"AWSNLogGroup{Guid.NewGuid().ToString().Split('-').Last()}"; 42 | CreateLoggerFromConfiguration("Regular.config", logGroupName); 43 | Logger = LogManager.GetLogger("loggerRegular"); 44 | await SimpleLoggingTest(logGroupName); 45 | } 46 | 47 | [Fact] 48 | public async Task MultiThreadTest() 49 | { 50 | var logGroupName = $"AWSNLogGroupMultiThreadTest{Guid.NewGuid().ToString().Split('-').Last()}"; 51 | CreateLoggerFromConfiguration("AWSNLogGroupMultiThreadTest.config", logGroupName); 52 | Logger = LogManager.GetLogger("loggerMultiThread"); 53 | await MultiThreadTestGroup(logGroupName); 54 | } 55 | 56 | [Fact] 57 | public async Task MultiThreadBufferFullTest() 58 | { 59 | var logGroupName = $"AWSNLogGroupMultiThreadBufferFullTest{Guid.NewGuid().ToString().Split('-').Last()}"; 60 | CreateLoggerFromConfiguration("AWSNLogGroupMultiThreadBufferFullTest.config", logGroupName); 61 | Logger = LogManager.GetLogger("loggerMultiThreadBufferFull"); 62 | await MultiThreadBufferFullTestGroup(logGroupName); 63 | } 64 | 65 | /// 66 | /// Verifies that multiple producers can log to the same log stream 67 | /// when an override log stream name is provided 68 | /// 69 | [Fact] 70 | public async Task CustomLogStreamNameTest() 71 | { 72 | var logGroupName = $"AWSNLogOverrideLogStreamName{Guid.NewGuid().ToString().Split('-').Last()}"; 73 | CreateLoggerFromConfiguration("AWSNLogOverrideLogStreamName.config", logGroupName); 74 | Logger = LogManager.GetLogger("overrideLogStreamName"); 75 | await MultiThreadTestGroup(logGroupName, "CustomStreamName"); 76 | } 77 | 78 | [Fact] 79 | public async Task MessageHasToBeBrokenUp() 80 | { 81 | var logGroupName = $"AWSNLogGroupEventSizeExceededTest{Guid.NewGuid().ToString().Split('-').Last()}"; 82 | 83 | CreateLoggerFromConfiguration("AWSNLogGroupEventSizeExceededTest.config", logGroupName); 84 | Logger = LogManager.GetLogger("loggerRegularEventSizeExceeded"); 85 | 86 | // This will get broken up into 3 CloudWatch Log messages 87 | Logger.Debug(new string('a', 600000)); 88 | Logger.Debug(LASTMESSAGE); 89 | 90 | GetLogEventsResponse getLogEventsResponse = new GetLogEventsResponse(); 91 | if (await NotifyLoggingCompleted(logGroupName, "LASTMESSAGE")) 92 | { 93 | DescribeLogStreamsResponse describeLogstreamsResponse = 94 | await _testFixture.Client.DescribeLogStreamsAsync(new DescribeLogStreamsRequest 95 | { 96 | Descending = true, 97 | LogGroupName = logGroupName, 98 | OrderBy = "LastEventTime" 99 | }); 100 | 101 | // Wait for the large messages to propagate 102 | Thread.Sleep(5000); 103 | getLogEventsResponse = await _testFixture.Client.GetLogEventsAsync(new GetLogEventsRequest 104 | { 105 | LogGroupName = logGroupName, 106 | LogStreamName = describeLogstreamsResponse.LogStreams[0].LogStreamName 107 | }); 108 | } 109 | _testFixture.LogGroupNameList.Add(logGroupName); 110 | Assert.Equal(4, getLogEventsResponse.Events.Count); 111 | } 112 | 113 | protected override void LogMessages(int count) 114 | { 115 | for (int i = 0; i < count-1; i++) 116 | { 117 | Logger.Debug(string.Format("Test logging message {0} NLog, Thread Id:{1}", i, Environment.CurrentManagedThreadId)); 118 | } 119 | Logger.Debug(LASTMESSAGE); 120 | } 121 | } 122 | #endregion 123 | } 124 | -------------------------------------------------------------------------------- /test/AWS.Logger.SeriLog.Tests/AWS.Logger.SeriLog.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | AWS.Logger.SeriLog.Tests 6 | true 7 | false 8 | false 9 | true 10 | true 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | PreserveNewest 23 | 24 | 25 | PreserveNewest 26 | 27 | 28 | PreserveNewest 29 | 30 | 31 | PreserveNewest 32 | 33 | 34 | PreserveNewest 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /test/AWS.Logger.SeriLog.Tests/AWSSeriLogGroup.json: -------------------------------------------------------------------------------- 1 | { 2 | "Serilog": { 3 | "Using": [ "AWS.Logger.SeriLog" ], 4 | "MinimumLevel": "Debug", 5 | "LogGroup": "{LOG_GROUP_NAME}", 6 | "Region": "us-west-2", 7 | "LogStreamNameSuffix": "Custom", 8 | "LogStreamNamePrefix": "CustomPrefix", 9 | "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ] 10 | } 11 | } -------------------------------------------------------------------------------- /test/AWS.Logger.SeriLog.Tests/AWSSeriLogGroupMultiThreadBufferFullTest.json: -------------------------------------------------------------------------------- 1 | { 2 | "Serilog": { 3 | "Using": [ "AWS.Logger.SeriLog" ], 4 | "MinimumLevel": "Debug", 5 | "LogGroup": "{LOG_GROUP_NAME}", 6 | "Region": "us-west-2", 7 | "LogStreamNameSuffix": "Custom", 8 | "MaxQueuedMessages": "100", 9 | "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ] 10 | } 11 | } -------------------------------------------------------------------------------- /test/AWS.Logger.SeriLog.Tests/AWSSeriLogGroupMultiThreadTest.json: -------------------------------------------------------------------------------- 1 | { 2 | "Serilog": { 3 | "Using": [ "AWS.Logger.SeriLog" ], 4 | "MinimumLevel": "Debug", 5 | "LogGroup": "{LOG_GROUP_NAME}", 6 | "Region": "us-west-2", 7 | "LogStreamNameSuffix": "Custom", 8 | "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ] 9 | } 10 | } -------------------------------------------------------------------------------- /test/AWS.Logger.SeriLog.Tests/AWSSeriLogGroupOverrideLogStreamName.json: -------------------------------------------------------------------------------- 1 | { 2 | "Serilog": { 3 | "Using": [ "AWS.Logger.SeriLog" ], 4 | "MinimumLevel": "Debug", 5 | "LogGroup": "{LOG_GROUP_NAME}", 6 | "Region": "us-west-2", 7 | "LogStreamName": "CustomLogStream", 8 | "LogStreamNameSuffix": "Custom", 9 | "LogStreamNamePrefix": "CustomPrefix", 10 | "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ] 11 | } 12 | } -------------------------------------------------------------------------------- /test/AWS.Logger.SeriLog.Tests/AWSSeriLogGroupRestrictedToMinimumLevel.json: -------------------------------------------------------------------------------- 1 | { 2 | "Serilog": { 3 | "Using": [ "AWS.Logger.SeriLog" ], 4 | "MinimumLevel": "Debug", 5 | "LogGroup": "{LOG_GROUP_NAME}", 6 | "Region": "us-west-2", 7 | "LogStreamNameSuffix": "Custom", 8 | "LogStreamNamePrefix": "CustomPrefix", 9 | "WriteTo": [ 10 | { 11 | "Name": "AWSSeriLog", 12 | "Args": { 13 | "restrictedToMinimumLevel": "Error" 14 | } 15 | } 16 | ] 17 | } 18 | } -------------------------------------------------------------------------------- /test/AWS.Logger.SeriLog.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyCompany("")] 9 | [assembly: AssemblyProduct("AWS.Logger.SeriLog.Tests")] 10 | [assembly: AssemblyTrademark("")] 11 | 12 | // Setting ComVisible to false makes the types in this assembly not visible 13 | // to COM components. If you need to access a type in this assembly from 14 | // COM, set the ComVisible attribute to true on that type. 15 | [assembly: ComVisible(false)] 16 | 17 | // The following GUID is for the ID of the typelib if this project is exposed to COM 18 | [assembly: Guid("f7986868-9d7e-4df6-a57e-e79e38ad166d")] 19 | -------------------------------------------------------------------------------- /test/AWS.Logger.SeriLog.Tests/SeriLoggerTestClass.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using Amazon.CloudWatchLogs.Model; 8 | using AWS.Logger.SeriLog; 9 | using AWS.Logger.TestUtils; 10 | using Microsoft.Extensions.Configuration; 11 | using Serilog; 12 | using Xunit; 13 | 14 | namespace AWS.Logger.SeriLog.Tests 15 | { 16 | // This project can output the Class library as a NuGet Package. 17 | // To enable this option, right-click on the project and select the Properties menu item. 18 | // In the Build tab select "Produce outputs on build". 19 | public class SeriLoggerTestClass : BaseTestClass 20 | { 21 | public SeriLoggerTestClass(TestFixture testFixture) : base(testFixture) 22 | { 23 | } 24 | 25 | private void CreateLoggerFromConfiguration(string configurationFile, string logGroupName) 26 | { 27 | var fileInfo = new FileInfo(configurationFile); 28 | var fileContent = File.ReadAllText(fileInfo.FullName); 29 | using (Stream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(fileContent.Replace("{LOG_GROUP_NAME}", logGroupName)))) 30 | { 31 | var configuration = new ConfigurationBuilder() 32 | .AddJsonStream(memoryStream) 33 | .Build(); 34 | 35 | Log.Logger = new LoggerConfiguration(). 36 | ReadFrom.Configuration(configuration). 37 | WriteTo.AWSSeriLog(configuration).CreateLogger(); 38 | } 39 | } 40 | #region Test Cases 41 | 42 | [Fact] 43 | public async Task SeriLogger() 44 | { 45 | var logGroupName = $"AWSSeriLogGroup{Guid.NewGuid().ToString().Split('-').Last()}"; 46 | CreateLoggerFromConfiguration("AWSSeriLogGroup.json", logGroupName); 47 | await SimpleLoggingTest(logGroupName); 48 | } 49 | 50 | [Fact] 51 | public async Task MultiThreadTest() 52 | { 53 | var logGroupName = $"AWSSeriLogGroup{Guid.NewGuid().ToString().Split('-').Last()}"; 54 | CreateLoggerFromConfiguration("AWSSeriLogGroupMultiThreadTest.json", logGroupName); 55 | await MultiThreadTestGroup(logGroupName); 56 | } 57 | 58 | [Fact] 59 | public async Task MultiThreadBufferFullTest() 60 | { 61 | var logGroupName = $"AWSSeriLogGroup{Guid.NewGuid().ToString().Split('-').Last()}"; 62 | CreateLoggerFromConfiguration("AWSSeriLogGroupMultiThreadBufferFullTest.json", logGroupName); 63 | await MultiThreadBufferFullTestGroup(logGroupName); 64 | } 65 | 66 | /// 67 | /// Verifies that multiple producers can log to the same log stream 68 | /// when an override log stream name is provided 69 | /// 70 | [Fact] 71 | public async Task CustomLogStreamNameTest() 72 | { 73 | var logGroupName = $"AWSSeriLogGroup{Guid.NewGuid().ToString().Split('-').Last()}"; 74 | CreateLoggerFromConfiguration("AWSSeriLogGroupOverrideLogStreamName.json", logGroupName); 75 | await MultiThreadTestGroup(logGroupName, "CustomLogStream"); 76 | } 77 | 78 | [Fact] 79 | public async Task RestrictedToMinimumLevelTest() 80 | { 81 | var logGroupName = $"AWSSeriLogGroupRestrictedtoMinimumLevel{Guid.NewGuid().ToString().Split('-').Last()}"; 82 | 83 | var fileInfo = new FileInfo("AWSSeriLogGroupRestrictedToMinimumLevel.json"); 84 | var fileContent = File.ReadAllText(fileInfo.FullName); 85 | using (Stream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(fileContent.Replace("{LOG_GROUP_NAME}", logGroupName)))) 86 | { 87 | // Create logger 88 | var configuration = new ConfigurationBuilder() 89 | .AddJsonStream(memoryStream) 90 | .Build(); 91 | 92 | Log.Logger = new LoggerConfiguration(). 93 | ReadFrom.Configuration(configuration).CreateLogger(); 94 | } 95 | 96 | await ExecuteRestrictedToMinimumLevelTest(logGroupName); 97 | } 98 | 99 | private async Task ExecuteRestrictedToMinimumLevelTest(string logGroupName) 100 | { 101 | // Log 4 Debug messages 102 | for (int i = 0; i < 3; i++) 103 | { 104 | Log.Debug(string.Format("Test logging message {0} SeriLog, Thread Id:{1}", i, Environment.CurrentManagedThreadId)); 105 | } 106 | // Log 5 Error messages 107 | for (int i = 0; i < 5; i++) 108 | { 109 | Log.Error(string.Format("Test logging message {0} SeriLog, Thread Id:{1}", i, Environment.CurrentManagedThreadId)); 110 | } 111 | Log.Error(LASTMESSAGE); 112 | 113 | GetLogEventsResponse getLogEventsResponse = new GetLogEventsResponse(); 114 | if (await NotifyLoggingCompleted(logGroupName, "LASTMESSAGE")) 115 | { 116 | DescribeLogStreamsResponse describeLogstreamsResponse = await _testFixture.Client.DescribeLogStreamsAsync(new DescribeLogStreamsRequest 117 | { 118 | Descending = true, 119 | LogGroupName = logGroupName, 120 | OrderBy = "LastEventTime" 121 | }); 122 | 123 | getLogEventsResponse = await _testFixture.Client.GetLogEventsAsync(new GetLogEventsRequest 124 | { 125 | LogGroupName = logGroupName, 126 | LogStreamName = describeLogstreamsResponse.LogStreams[0].LogStreamName 127 | }); 128 | } 129 | Assert.Equal(6, getLogEventsResponse.Events.Count); 130 | } 131 | 132 | /// 133 | /// This method posts debug messages onto CloudWatchLogs. 134 | /// 135 | /// The number of messages that would be posted onto CloudWatchLogs 136 | protected override void LogMessages(int count) 137 | { 138 | for (int i = 0; i < count - 1; i++) 139 | { 140 | Log.Debug(string.Format("Test logging message {0} SeriLog, Thread Id:{1}", i, Environment.CurrentManagedThreadId)); 141 | } 142 | Log.Debug(LASTMESSAGE); 143 | } 144 | #endregion 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /test/AWS.Logger.TestUtils/AWS.Logger.TestUtils.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0;net472 5 | AWS.Logger.TestUtils 6 | false 7 | false 8 | Full 9 | true 10 | true 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /test/AWS.Logger.TestUtils/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyCompany("")] 9 | [assembly: AssemblyProduct("TestUtils")] 10 | [assembly: AssemblyTrademark("")] 11 | 12 | // Setting ComVisible to false makes the types in this assembly not visible 13 | // to COM components. If you need to access a type in this assembly from 14 | // COM, set the ComVisible attribute to true on that type. 15 | [assembly: ComVisible(false)] 16 | 17 | // The following GUID is for the ID of the typelib if this project is exposed to COM 18 | [assembly: Guid("adff6031-0f8e-4eed-8e28-f29f0900bc11")] 19 | -------------------------------------------------------------------------------- /test/AWS.Logger.TestUtils/TestFixture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using Amazon.CloudWatchLogs; 5 | using Amazon.CloudWatchLogs.Model; 6 | using Xunit; 7 | 8 | namespace AWS.Logger.TestUtils 9 | { 10 | // This project can output the Class library as a NuGet Package. 11 | // To enable this option, right-click on the project and select the Properties menu item. 12 | // In the Build tab select "Produce outputs on build". 13 | 14 | //TestClass to dispose test generated LogGroups. 15 | public class TestFixture : IAsyncLifetime 16 | { 17 | public List LogGroupNameList; 18 | public AmazonCloudWatchLogsClient Client; 19 | 20 | public Task InitializeAsync() 21 | { 22 | Client = new AmazonCloudWatchLogsClient(Amazon.RegionEndpoint.USWest2); 23 | LogGroupNameList = new List(); 24 | 25 | return Task.CompletedTask; 26 | } 27 | 28 | public async Task DisposeAsync() 29 | { 30 | foreach (var logGroupName in LogGroupNameList) 31 | { 32 | try 33 | { 34 | if (!(string.IsNullOrEmpty(logGroupName))) 35 | { 36 | var describeLogGroupsResponse = await Client.DescribeLogGroupsAsync( 37 | new DescribeLogGroupsRequest 38 | { 39 | LogGroupNamePrefix = logGroupName 40 | }); 41 | 42 | foreach (var logGroup in describeLogGroupsResponse.LogGroups) 43 | { 44 | if (!(string.IsNullOrEmpty(logGroup.LogGroupName))) 45 | { 46 | var response = await Client.DeleteLogGroupAsync(new DeleteLogGroupRequest 47 | { 48 | LogGroupName = logGroup.LogGroupName 49 | }); 50 | } 51 | } 52 | } 53 | } 54 | catch (Exception) { } 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /test/AWS.Logger.UnitTests/AWS.Logger.UnitTests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | AWS.Logger.UnitTests 6 | true 7 | true 8 | true 9 | false 10 | false 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /test/AWS.Logger.UnitTests/AWSLoggerConfigTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Xunit; 5 | using AWS.Logger; 6 | 7 | namespace AWS.Logger.UnitTests 8 | { 9 | public class AWSLoggerConfigTests 10 | { 11 | AWSLoggerConfig config; 12 | public AWSLoggerConfigTests() 13 | { 14 | config = new AWSLoggerConfig(); 15 | } 16 | [Fact] 17 | public void TestDefaultBatchSizeInBytes() 18 | { 19 | Assert.Equal(102400, config.BatchSizeInBytes); 20 | } 21 | 22 | [Fact] 23 | public void SetInvalidValueOnBatchSizeInBytes() 24 | { 25 | var exception = Record.Exception(() => config.BatchSizeInBytes = (int)Math.Pow(1024, 2) + 1); 26 | Assert.NotNull(exception); 27 | 28 | Assert.IsType(exception); 29 | } 30 | 31 | [Fact] 32 | public void SetValidValueOnBatchSizeInBytes() 33 | { 34 | var exception = Record.Exception(() => config.BatchSizeInBytes = (int)Math.Pow(1024, 2) - 1); 35 | Assert.Null(exception); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /test/AWS.Logger.UnitTests/GenerateStreamNameTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Collections.Generic; 4 | using System.Globalization; 5 | using System.Text; 6 | using Xunit; 7 | using AWS.Logger; 8 | 9 | using AWS.Logger.Core; 10 | 11 | namespace AWS.Logger.UnitTests 12 | { 13 | public class GenerateStreamNameTests 14 | { 15 | [Fact] 16 | public void DefaultConfig() 17 | { 18 | var config = new AWSLoggerConfig 19 | { 20 | 21 | }; 22 | var streamName = AWSLoggerCore.GenerateStreamName(config); 23 | 24 | var tokens = SplitStreamName(streamName); 25 | Assert.Equal(2, tokens.Length); 26 | 27 | Assert.True(IsTokenDate(tokens[0])); 28 | Assert.True(IsTokenGuid(tokens[1])); 29 | } 30 | 31 | [Fact] 32 | public void SuffixSet() 33 | { 34 | var config = new AWSLoggerConfig 35 | { 36 | LogStreamNameSuffix = "TheSuffix" 37 | }; 38 | var streamName = AWSLoggerCore.GenerateStreamName(config); 39 | 40 | var tokens = SplitStreamName(streamName); 41 | Assert.Equal(2, tokens.Length); 42 | 43 | Assert.True(IsTokenDate(tokens[0])); 44 | Assert.Equal(config.LogStreamNameSuffix, tokens[1]); 45 | } 46 | 47 | [Fact] 48 | public void PrefixSetSuffixAtDefault() 49 | { 50 | var config = new AWSLoggerConfig 51 | { 52 | LogStreamNamePrefix = "ThePrefix" 53 | }; 54 | var streamName = AWSLoggerCore.GenerateStreamName(config); 55 | 56 | var tokens = SplitStreamName(streamName); 57 | Assert.Equal(3, tokens.Length); 58 | 59 | Assert.Equal(config.LogStreamNamePrefix, tokens[0]); 60 | Assert.True(IsTokenDate(tokens[1])); 61 | Assert.True(IsTokenGuid(tokens[2])); 62 | } 63 | 64 | [Fact] 65 | public void PrefixSetSuffixSet() 66 | { 67 | var config = new AWSLoggerConfig 68 | { 69 | LogStreamNamePrefix = "ThePrefix", 70 | LogStreamNameSuffix = "TheSuffix" 71 | }; 72 | var streamName = AWSLoggerCore.GenerateStreamName(config); 73 | 74 | var tokens = SplitStreamName(streamName); 75 | Assert.Equal(3, tokens.Length); 76 | 77 | Assert.Equal(config.LogStreamNamePrefix, tokens[0]); 78 | Assert.True(IsTokenDate(tokens[1])); 79 | Assert.Equal(config.LogStreamNameSuffix, tokens[2]); 80 | } 81 | 82 | [Fact] 83 | public void PrefixSetSuffixSetToNull() 84 | { 85 | var config = new AWSLoggerConfig 86 | { 87 | LogStreamNamePrefix = "ThePrefix", 88 | LogStreamNameSuffix = null 89 | }; 90 | var streamName = AWSLoggerCore.GenerateStreamName(config); 91 | 92 | var tokens = SplitStreamName(streamName); 93 | Assert.Equal(2, tokens.Length); 94 | 95 | Assert.Equal(config.LogStreamNamePrefix, tokens[0]); 96 | Assert.True(IsTokenDate(tokens[1])); 97 | } 98 | 99 | [Fact] 100 | public void PrefixSetSuffixSetToEmptyString() 101 | { 102 | var config = new AWSLoggerConfig 103 | { 104 | LogStreamNamePrefix = "ThePrefix", 105 | LogStreamNameSuffix = string.Empty 106 | }; 107 | var streamName = AWSLoggerCore.GenerateStreamName(config); 108 | 109 | var tokens = SplitStreamName(streamName); 110 | Assert.Equal(2, tokens.Length); 111 | 112 | Assert.Equal(config.LogStreamNamePrefix, tokens[0]); 113 | Assert.True(IsTokenDate(tokens[1])); 114 | } 115 | 116 | 117 | private string[] SplitStreamName(string streamName) 118 | { 119 | const string searchToken = " - "; 120 | var tokens = new List(); 121 | int currentPos = 0; 122 | int pos = streamName.IndexOf(searchToken); 123 | while(pos != -1) 124 | { 125 | tokens.Add(streamName.Substring(currentPos, pos - currentPos)); 126 | currentPos = pos + searchToken.Length; 127 | pos = streamName.IndexOf(searchToken, currentPos); 128 | } 129 | 130 | if(currentPos < streamName.Length) 131 | { 132 | tokens.Add(streamName.Substring(currentPos, streamName.Length - currentPos)); 133 | } 134 | 135 | return tokens.ToArray(); 136 | } 137 | 138 | private bool IsTokenDate(string token) 139 | { 140 | DateTime dt; 141 | return DateTime.TryParseExact(token, "yyyy/MM/ddTHH.mm.ss", CultureInfo.InvariantCulture, DateTimeStyles.None, out dt); 142 | } 143 | 144 | private bool IsTokenGuid(string token) 145 | { 146 | Guid guid; 147 | return Guid.TryParse(token, out guid); 148 | } 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /test/AWS.Logger.UnitTests/MessageSizeBreakupTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | using Xunit; 6 | 7 | using AWS.Logger.Core; 8 | 9 | namespace AWS.Logger.UnitTests 10 | { 11 | public class MessageSizeBreakupTests 12 | { 13 | [Fact] 14 | public void AsciiTest() 15 | { 16 | var message = new string('a', 240000); 17 | Assert.Single(AWSLoggerCore.BreakupMessage(message)); 18 | } 19 | 20 | [Fact] 21 | public void UnicodeCharTest() 22 | { 23 | var testChar = '∀'; 24 | var charCount = 240000; 25 | var message = new string(testChar, charCount); 26 | var bytesSize = Encoding.UTF8.GetByteCount(message); 27 | Assert.Equal((bytesSize / 256000) + 1, AWSLoggerCore.BreakupMessage(message).Count); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/AWS.Logger.UnitTests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyCompany("")] 9 | [assembly: AssemblyProduct("UnitTest")] 10 | [assembly: AssemblyTrademark("")] 11 | 12 | // Setting ComVisible to false makes the types in this assembly not visible 13 | // to COM components. If you need to access a type in this assembly from 14 | // COM, set the ComVisible attribute to true on that type. 15 | [assembly: ComVisible(false)] 16 | 17 | // The following GUID is for the ID of the typelib if this project is exposed to COM 18 | [assembly: Guid("0cdf585c-ced0-456f-95ea-f2aab8b9f4e7")] 19 | --------------------------------------------------------------------------------