From 38518ac44716b6b5f1b5e1d922f92fca2392e6ac Mon Sep 17 00:00:00 2001 From: "Arora, Kaushal" Date: Thu, 20 Feb 2025 13:44:35 +0530 Subject: [PATCH 1/4] WI 705913 Push code from Harman Automotive with modifications for ECSP --- .github/ISSUE_TEMPLATE/bug.yml | 41 ++ .github/ISSUE_TEMPLATE/documentation.yml | 41 ++ .github/ISSUE_TEMPLATE/feature.yml | 41 ++ .github/ISSUE_TEMPLATE/maintenance.yml | 41 ++ .github/pull_request_template.md | 32 + .github/release.yml | 24 + .github/workflows/dependencies-update.yaml | 60 ++ .github/workflows/license-compliance.yml | 48 ++ .github/workflows/maven-publish.yml | 36 + .github/workflows/sonarcloud.yml | 67 ++ CODE_OF_CONDUCT.md | 3 + CONTRIBUTING.md | 42 ++ DEPENDENCIES | 34 + LICENSE | 201 ++++++ NOTICE.md | 44 ++ README.md | 182 ++++- SECURITY.md | 21 + checkstyle-suppressions.xml | 13 + harman_checks.xml | 420 +++++++++++ images/logo.png | Bin 0 -> 17097 bytes pom.xml | 455 ++++++++++++ release_notes.txt | 2 + settings.xml | 11 + .../diagnostic/DiagnosticConstants.java | 46 ++ .../ignite/diagnostic/DiagnosticData.java | 44 ++ .../ignite/diagnostic/DiagnosticReporter.java | 69 ++ .../ignite/diagnostic/DiagnosticResult.java | 65 ++ .../ignite/diagnostic/DiagnosticService.java | 134 ++++ .../PropertyDiagnosticReporterImpl.java | 121 ++++ .../ignite/healthcheck/HealthMonitor.java | 82 +++ .../ignite/healthcheck/HealthService.java | 340 +++++++++ .../healthcheck/HealthServiceCallBack.java | 53 ++ .../healthcheck/HealthServiceState.java | 102 +++ .../InvalidMetricNamingException.java | 12 + .../ignite/healthcheck/ThreadUtils.java | 106 +++ .../filter/DuplicateExceptionFilter.java | 166 +++++ .../logger/IgniteCallerDataConverter.java | 133 ++++ .../ignite/utils/logger/IgniteLogger.java | 147 ++++ .../utils/logger/IgniteLoggerFactory.java | 52 ++ .../ignite/utils/logger/IgniteLoggerImpl.java | 337 +++++++++ .../logger/IgniteThrowableProxyConverter.java | 298 ++++++++ .../ignite/utils/logger/LoggerUtils.java | 101 +++ .../utils/metrics/AbstractIgniteCounter.java | 131 ++++ .../utils/metrics/AbstractIgniteGauge.java | 170 +++++ .../metrics/AbstractIgniteHistogram.java | 150 ++++ .../utils/metrics/GenericIgniteCounter.java | 50 ++ .../utils/metrics/GenericIgniteGauge.java | 48 ++ .../utils/metrics/GenericIgniteHistogram.java | 50 ++ .../ignite/utils/metrics/IgniteCounter.java | 95 +++ .../utils/metrics/IgniteDiagnosticGuage.java | 52 ++ .../utils/metrics/IgniteErrorCounter.java | 120 ++++ .../ignite/utils/metrics/IgniteGuage.java | 104 +++ .../utils/metrics/IgniteHealthGuage.java | 52 ++ .../utils/metrics/IgniteRocksDBGuage.java | 59 ++ .../utils/metrics/InternalCacheGuage.java | 81 +++ .../utils/test/NightlyBuildTestCase.java | 54 ++ .../diagnostic/DiagnosticResultTest.java | 55 ++ .../ignite/diagnostic/DiagnosticUnitTest.java | 185 +++++ .../PropertyDiagnosticReporterTest.java | 107 +++ .../diagnostic/TestDiagnosticReporter.java | 85 +++ .../TestDiagnosticReporterConfig.java | 56 ++ .../HealthServiceIntegrationTestCase.java | 161 +++++ .../healthcheck/HealthServiceStateTest.java | 110 +++ .../healthcheck/HealthServiceUnitTest.java | 678 ++++++++++++++++++ .../ignite/healthcheck/TestHealthMonitor.java | 102 +++ .../TestHealthMonitorWithForce.java | 105 +++ .../healthcheck/TestHealthServiceConfig.java | 86 +++ .../filter/TestDuplicateExceptionFilter.java | 118 +++ .../ignite/utils/logger/EventLogger1.java | 57 ++ .../ignite/utils/logger/EventLogger2.java | 55 ++ .../utils/logger/IgniteLoggerFactoryTest.java | 55 ++ .../ignite/utils/logger/TestIgniteLogger.java | 358 +++++++++ .../utils/logger/TestIgniteLoggerDebug.java | 79 ++ .../utils/logger/TestIgniteLoggerError.java | 79 ++ .../utils/logger/TestIgniteLoggerInfo.java | 80 +++ .../utils/logger/TestIgniteLoggerTrace.java | 80 +++ .../utils/logger/TestIgniteLoggerWarn.java | 81 +++ .../utils/metrics/GenericIgniteGuageTest.java | 169 +++++ .../utils/metrics/IgniteCounterTest.java | 93 +++ .../utils/metrics/IgniteErrorCounterTest.java | 115 +++ .../ignite/utils/metrics/IgniteGuageTest.java | 104 +++ .../utils/metrics/IgniteRocksDBGuageTest.java | 67 ++ .../utils/metrics/InternalCacheGuageTest.java | 91 +++ .../metrics/TestGenericIgniteHistogram.java | 236 ++++++ src/test/resources/logback.xml | 87 +++ .../property-diagnostic-test-2.properties | 43 ++ .../property-diagnostic-test.properties | 83 +++ target/classes/META-INF/MANIFEST.MF | 5 + 88 files changed, 9347 insertions(+), 1 deletion(-) create mode 100644 .github/ISSUE_TEMPLATE/bug.yml create mode 100644 .github/ISSUE_TEMPLATE/documentation.yml create mode 100644 .github/ISSUE_TEMPLATE/feature.yml create mode 100644 .github/ISSUE_TEMPLATE/maintenance.yml create mode 100644 .github/pull_request_template.md create mode 100644 .github/release.yml create mode 100644 .github/workflows/dependencies-update.yaml create mode 100644 .github/workflows/license-compliance.yml create mode 100644 .github/workflows/maven-publish.yml create mode 100644 .github/workflows/sonarcloud.yml create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 DEPENDENCIES create mode 100644 LICENSE create mode 100644 NOTICE.md create mode 100644 SECURITY.md create mode 100644 checkstyle-suppressions.xml create mode 100644 harman_checks.xml create mode 100644 images/logo.png create mode 100644 pom.xml create mode 100644 release_notes.txt create mode 100644 settings.xml create mode 100644 src/main/java/com/harman/ignite/diagnostic/DiagnosticConstants.java create mode 100644 src/main/java/com/harman/ignite/diagnostic/DiagnosticData.java create mode 100644 src/main/java/com/harman/ignite/diagnostic/DiagnosticReporter.java create mode 100644 src/main/java/com/harman/ignite/diagnostic/DiagnosticResult.java create mode 100644 src/main/java/com/harman/ignite/diagnostic/DiagnosticService.java create mode 100644 src/main/java/com/harman/ignite/diagnostic/PropertyDiagnosticReporterImpl.java create mode 100644 src/main/java/com/harman/ignite/healthcheck/HealthMonitor.java create mode 100644 src/main/java/com/harman/ignite/healthcheck/HealthService.java create mode 100644 src/main/java/com/harman/ignite/healthcheck/HealthServiceCallBack.java create mode 100644 src/main/java/com/harman/ignite/healthcheck/HealthServiceState.java create mode 100644 src/main/java/com/harman/ignite/healthcheck/InvalidMetricNamingException.java create mode 100644 src/main/java/com/harman/ignite/healthcheck/ThreadUtils.java create mode 100644 src/main/java/com/harman/ignite/utils/filter/DuplicateExceptionFilter.java create mode 100644 src/main/java/com/harman/ignite/utils/logger/IgniteCallerDataConverter.java create mode 100644 src/main/java/com/harman/ignite/utils/logger/IgniteLogger.java create mode 100644 src/main/java/com/harman/ignite/utils/logger/IgniteLoggerFactory.java create mode 100644 src/main/java/com/harman/ignite/utils/logger/IgniteLoggerImpl.java create mode 100644 src/main/java/com/harman/ignite/utils/logger/IgniteThrowableProxyConverter.java create mode 100644 src/main/java/com/harman/ignite/utils/logger/LoggerUtils.java create mode 100644 src/main/java/com/harman/ignite/utils/metrics/AbstractIgniteCounter.java create mode 100644 src/main/java/com/harman/ignite/utils/metrics/AbstractIgniteGauge.java create mode 100644 src/main/java/com/harman/ignite/utils/metrics/AbstractIgniteHistogram.java create mode 100644 src/main/java/com/harman/ignite/utils/metrics/GenericIgniteCounter.java create mode 100644 src/main/java/com/harman/ignite/utils/metrics/GenericIgniteGauge.java create mode 100644 src/main/java/com/harman/ignite/utils/metrics/GenericIgniteHistogram.java create mode 100644 src/main/java/com/harman/ignite/utils/metrics/IgniteCounter.java create mode 100644 src/main/java/com/harman/ignite/utils/metrics/IgniteDiagnosticGuage.java create mode 100644 src/main/java/com/harman/ignite/utils/metrics/IgniteErrorCounter.java create mode 100644 src/main/java/com/harman/ignite/utils/metrics/IgniteGuage.java create mode 100644 src/main/java/com/harman/ignite/utils/metrics/IgniteHealthGuage.java create mode 100644 src/main/java/com/harman/ignite/utils/metrics/IgniteRocksDBGuage.java create mode 100644 src/main/java/com/harman/ignite/utils/metrics/InternalCacheGuage.java create mode 100644 src/main/java/com/harman/ignite/utils/test/NightlyBuildTestCase.java create mode 100644 src/test/java/com/harman/ignite/diagnostic/DiagnosticResultTest.java create mode 100644 src/test/java/com/harman/ignite/diagnostic/DiagnosticUnitTest.java create mode 100644 src/test/java/com/harman/ignite/diagnostic/PropertyDiagnosticReporterTest.java create mode 100644 src/test/java/com/harman/ignite/diagnostic/TestDiagnosticReporter.java create mode 100644 src/test/java/com/harman/ignite/diagnostic/TestDiagnosticReporterConfig.java create mode 100644 src/test/java/com/harman/ignite/healthcheck/HealthServiceIntegrationTestCase.java create mode 100644 src/test/java/com/harman/ignite/healthcheck/HealthServiceStateTest.java create mode 100644 src/test/java/com/harman/ignite/healthcheck/HealthServiceUnitTest.java create mode 100644 src/test/java/com/harman/ignite/healthcheck/TestHealthMonitor.java create mode 100644 src/test/java/com/harman/ignite/healthcheck/TestHealthMonitorWithForce.java create mode 100644 src/test/java/com/harman/ignite/healthcheck/TestHealthServiceConfig.java create mode 100644 src/test/java/com/harman/ignite/utils/filter/TestDuplicateExceptionFilter.java create mode 100644 src/test/java/com/harman/ignite/utils/logger/EventLogger1.java create mode 100644 src/test/java/com/harman/ignite/utils/logger/EventLogger2.java create mode 100644 src/test/java/com/harman/ignite/utils/logger/IgniteLoggerFactoryTest.java create mode 100644 src/test/java/com/harman/ignite/utils/logger/TestIgniteLogger.java create mode 100644 src/test/java/com/harman/ignite/utils/logger/TestIgniteLoggerDebug.java create mode 100644 src/test/java/com/harman/ignite/utils/logger/TestIgniteLoggerError.java create mode 100644 src/test/java/com/harman/ignite/utils/logger/TestIgniteLoggerInfo.java create mode 100644 src/test/java/com/harman/ignite/utils/logger/TestIgniteLoggerTrace.java create mode 100644 src/test/java/com/harman/ignite/utils/logger/TestIgniteLoggerWarn.java create mode 100644 src/test/java/com/harman/ignite/utils/metrics/GenericIgniteGuageTest.java create mode 100644 src/test/java/com/harman/ignite/utils/metrics/IgniteCounterTest.java create mode 100644 src/test/java/com/harman/ignite/utils/metrics/IgniteErrorCounterTest.java create mode 100644 src/test/java/com/harman/ignite/utils/metrics/IgniteGuageTest.java create mode 100644 src/test/java/com/harman/ignite/utils/metrics/IgniteRocksDBGuageTest.java create mode 100644 src/test/java/com/harman/ignite/utils/metrics/InternalCacheGuageTest.java create mode 100644 src/test/java/com/harman/ignite/utils/metrics/TestGenericIgniteHistogram.java create mode 100644 src/test/resources/logback.xml create mode 100644 src/test/resources/property-diagnostic-test-2.properties create mode 100644 src/test/resources/property-diagnostic-test.properties create mode 100644 target/classes/META-INF/MANIFEST.MF diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml new file mode 100644 index 0000000..375f3bd --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -0,0 +1,41 @@ +name: Bug +description: File a bug report +title: "[BUG]: " +labels: ["Type: Bug", "Status: Triage"] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! + - type: textarea + id: what-happened + attributes: + label: What happened? + description: What did you do? What happened? What did you expect to happen? + placeholder: Put your description of the bug here. + validations: + required: true + - type: textarea + id: versions + attributes: + label: Versions + description: What versions of the relevant software are you running? + placeholder: 1.0.0 + validations: + required: true + - type: textarea + id: logs + attributes: + label: Relevant log output + description: | + Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. + Please check your logs before submission to ensure sensitive information is redacted. + render: shell + - type: checkboxes + id: terms + attributes: + label: Code of Conduct + description: By submitting this issue, you agree to follow our [Code of Conduct](./CODE_OF_CONDUCT.md) + options: + - label: I agree to follow this project's Code of Conduct + required: true diff --git a/.github/ISSUE_TEMPLATE/documentation.yml b/.github/ISSUE_TEMPLATE/documentation.yml new file mode 100644 index 0000000..1990961 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/documentation.yml @@ -0,0 +1,41 @@ +name: Documentation +description: Update or add documentation +title: "[DOCS]: " +labels: ["Type: Documentation", "Status: Triage"] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill this out! + - type: textarea + id: describe-need + attributes: + label: Describe the need + description: What do you wish was different about our docs? + placeholder: Describe the need for documentation updates here. + validations: + required: true + - type: input + id: library_version + attributes: + label: Version + description: Do these docs apply to a specific version? + placeholder: 1.1.1 + validations: + required: false + - type: textarea + id: logs + attributes: + label: Relevant log output + description: | + Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. + Please check your logs before submission to ensure sensitive information is redacted. + render: shell + - type: checkboxes + id: terms + attributes: + label: Code of Conduct + description: By submitting this documentation issue, you agree to follow our [Code of Conduct](CODE_OF_CONDUCT.md) + options: + - label: I agree to follow this project's Code of Conduct + required: true diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml new file mode 100644 index 0000000..3bf43c6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature.yml @@ -0,0 +1,41 @@ +name: Feature +description: Suggest an idea for a new feature or enhancement +title: "[FEAT]: " +labels: ["Type: Feature", "Status: Triage"] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill this out! + - type: textarea + id: describe-need + attributes: + label: Describe the need + description: What do you want to happen? What problem are you trying to solve? + placeholder: Describe the need for the feature. + validations: + required: true + - type: input + id: library_version + attributes: + label: Library Version + description: Does this feature suggestion apply to a specific version? + placeholder: 1.0.0 + validations: + required: false + - type: textarea + id: logs + attributes: + label: Relevant log output + description: | + Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. + Please check your logs before submission to ensure sensitive information is redacted. + render: shell + - type: checkboxes + id: terms + attributes: + label: Code of Conduct + description: By submitting this feature request, you agree to follow our [Code of Conduct](CODE_OF_CONDUCT.md) + options: + - label: I agree to follow this project's Code of Conduct + required: true diff --git a/.github/ISSUE_TEMPLATE/maintenance.yml b/.github/ISSUE_TEMPLATE/maintenance.yml new file mode 100644 index 0000000..5eff93c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/maintenance.yml @@ -0,0 +1,41 @@ +name: Maintenance +description: Dependencies, cleanup, refactoring, reworking of code +title: "[MAINT]: " +labels: ["Type: Maintenance", "Status: Triage"] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill this out! + - type: textarea + id: describe-need + attributes: + label: Describe the need + description: What do you want to happen? + placeholder: Describe the maintenance need here. + validations: + required: true + - type: input + id: library_version + attributes: + label: Library Version + description: Does this maintenance apply to a specific version? + placeholder: v1.0.0 + validations: + required: false + - type: textarea + id: logs + attributes: + label: Relevant log output + description: | + Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. + Please check your logs before submission to ensure sensitive information is redacted. + render: shell + - type: checkboxes + id: terms + attributes: + label: Code of Conduct + description: By submitting this request, you agree to follow our [Code of Conduct](CODE_OF_CONDUCT.md) + options: + - label: I agree to follow this project's Code of Conduct + required: true diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..2512348 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,32 @@ +Please refer to our [contributing docs](./CONTRIBUTING.md) for any questions on submitting a pull request. +Issues are required for both bug fixes and features. + +Resolves #ISSUE_NUMBER + + +---- +### Describe behaviour before the change + + +* + +### Describe behaviour after the change + + +* + +### Pull request checklist +- [ ] I have read the [CONTRIBUTING.md](./CONTRIBUTING.md) +- [ ] My code follows the code style of this project +- [ ] Tests for the changes have been added (for bug fixes / features) +- [ ] All new and existing tests passed. +- [ ] Docs have been reviewed and added / updated if needed (for bug fixes / features) + +### Does this introduce a breaking change? + + +- [ ] Yes +- [ ] No + +---- + diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 0000000..b0f48a3 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,24 @@ +# .github/release.yml + +changelog: + exclude: + labels: + - ignore-for-release + authors: + - HARMAN-Automotive + categories: + - title: Breaking Changes + labels: + - breaking-change + - title: Features + labels: + - feature + - title: Bug Fixes + labels: + - bug + - title: Other Changes + labels: + - "*" + exclude: + labels: + - dependencies diff --git a/.github/workflows/dependencies-update.yaml b/.github/workflows/dependencies-update.yaml new file mode 100644 index 0000000..da9bb76 --- /dev/null +++ b/.github/workflows/dependencies-update.yaml @@ -0,0 +1,60 @@ +name: "Update DEPENDENCIES file" + +on: + push: + branches: [ "*" ] + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + permissions: + pull-requests: write + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'zulu' + cache: maven + server-id: github # Value of the distributionManagement/repository/id field of the pom.xml + settings-path: ${{ github.workspace }} # location for the settings.xml file + + - name: Generate Dependencies file + run: mvn org.eclipse.dash:license-tool-plugin:license-check -Ddash.summary=DEPENDENCIES -P dash + + - name: Check if file was changed + run: | + if git diff --name-only ${{ github.base_ref }}...${{ github.sha }} | grep -e 'DEPENDENCIES'; then + echo "The file was changed" + echo "was_file_changed=true" >> "$GITHUB_ENV" + git + else + echo "The file was not changed" + echo "was_file_changed=false" >> "$GITHUB_ENV" + fi + + - name: Configure Git + if: ${{ env.was_file_changed }} == 'true' + run: | + git config user.name "$GITHUB_ACTOR" + git config user.email "$GITHUB_ACTOR@users.noreply.github.com" + + - name: Create pull request + if: ${{ env.was_file_changed }} == 'true' + uses: peter-evans/create-pull-request@v6 + with: + add-paths: | + DEPENDENCIES + token: ${{ secrets.GITHUB_TOKEN }} + branch: chore/update-DEPENDENCIES + commit-message: "chore(dependencies): Update DEPENDENCIES" + delete-branch: true + title: Update DEPENDENCIES + body: | + This PR updates the DEPENDENCIES \ No newline at end of file diff --git a/.github/workflows/license-compliance.yml b/.github/workflows/license-compliance.yml new file mode 100644 index 0000000..40366b3 --- /dev/null +++ b/.github/workflows/license-compliance.yml @@ -0,0 +1,48 @@ +name: License Compliance + +on: + push: + branches: [ "*" ] + paths-ignore: + - '**/*.md' + - '**/*.txt' + pull_request: + branches: [ "*" ] + paths: + - '**/pom.xml' + - 'pom.xml' + workflow_dispatch: + +permissions: + pull-requests: read + contents: write + +jobs: + check-licenses: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'zulu' + cache: maven + server-id: github # Value of the distributionManagement/repository/id field of the pom.xml + settings-path: ${{ github.workspace }} # location for the settings.xml file + + - name: Build with Maven and check dependencies with dash + run: | + mvn --batch-mode --update-snapshots verify -P dash + + - name: Ensure DEPENDENCIES file is reflecting the current state + run: | + mvn org.eclipse.dash:license-tool-plugin:license-check -Ddash.summary=DEPENDENCIES-gen -P dash + diff DEPENDENCIES DEPENDENCIES-gen + + - name: upload results + if: always() + uses: actions/upload-artifact@v4 + with: + path: 'target/dash/summary' \ No newline at end of file diff --git a/.github/workflows/maven-publish.yml b/.github/workflows/maven-publish.yml new file mode 100644 index 0000000..00d64ad --- /dev/null +++ b/.github/workflows/maven-publish.yml @@ -0,0 +1,36 @@ +# This workflow will build a package using Maven and then publish it to GitHub packages when a release is created +# For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#apache-maven-with-a-settings-path + +name: Maven Package + +on: + release: + types: [created] + push: + branches: [ "main" ] + +jobs: + build: + + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'zulu' + server-id: github # Value of the distributionManagement/repository/id field of the pom.xml + settings-path: ${{ github.workspace }} # location for the settings.xml file + + - name: Build with Maven + run: mvn clean -B package --file pom.xml + + - name: Publish to GitHub Packages Apache Maven + run: mvn -DskipTests=true deploy -s $GITHUB_WORKSPACE/settings.xml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml new file mode 100644 index 0000000..7284194 --- /dev/null +++ b/.github/workflows/sonarcloud.yml @@ -0,0 +1,67 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +# This workflow helps you trigger a SonarCloud analysis of your code and populates +# GitHub Code Scanning alerts with the vulnerabilities found. +# Free for open source project. + +# 1. Login to SonarCloud.io using your GitHub account + +# 2. Import your project on SonarCloud +# * Add your GitHub organization first, then add your repository as a new project. +# * Please note that many languages are eligible for automatic analysis, +# which means that the analysis will start automatically without the need to set up GitHub Actions. +# * This behavior can be changed in Administration > Analysis Method. +# +# 3. Follow the SonarCloud in-product tutorial +# * a. Copy/paste the Project Key and the Organization Key into the args parameter below +# (You'll find this information in SonarCloud. Click on "Information" at the bottom left) +# +# * b. Generate a new token and add it to your Github repository's secrets using the name SONAR_TOKEN +# (On SonarCloud, click on your avatar on top-right > My account > Security +# or go directly to https://sonarcloud.io/account/security/) + +# Feel free to take a look at our documentation (https://docs.sonarcloud.io/getting-started/github/) +# or reach out to our community forum if you need some help (https://community.sonarsource.com/c/help/sc/9) + +name: SonarCloud analysis + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + workflow_dispatch: + +permissions: + pull-requests: read # allows SonarCloud to decorate PRs with analysis results + +jobs: + Analysis: + runs-on: ubuntu-latest + + steps: + - name: Analyze with SonarCloud + + # You can pin the exact commit or the version. + # uses: SonarSource/sonarcloud-github-action@v2.2.0 + uses: SonarSource/sonarcloud-github-action@4006f663ecaf1f8093e8e4abb9227f6041f52216 + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} # Generate a token on Sonarcloud.io, add it to the secrets of this repo with the name SONAR_TOKEN (Settings > Secrets > Actions > add new repository secret) + with: + # Additional arguments for the SonarScanner CLI + args: + # Unique keys of your project and organization. You can find them in SonarCloud > Information (bottom-left menu) + # mandatory + -Dsonar.projectKey=eclipse-ecsp_utils + -Dsonar.organization=eclipse-ecsp + # Comma-separated paths to directories containing main source files. + #-Dsonar.sources= # optional, default is project base directory + # Comma-separated paths to directories containing test source files. + #-Dsonar.tests= # optional. For more info about Code Coverage, please refer to https://docs.sonarcloud.io/enriching/test-coverage/overview/ + # Adds more detail to both client and server-side analysis logs, activating DEBUG mode for the scanner, and adding client-side environment variables and system properties to the server-side log of analysis report processing. + #-Dsonar.verbose= # optional, default is false + # When you need the analysis to take place in a directory other than the one from which it was launched, default is . + projectBaseDir: . diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..951dd81 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,3 @@ +# Eclipse Foundation Community Code of Conduct + +This project has adopted the [Eclipse Foundation Community Code of Conduct](https://raw.githubusercontent.com/eclipse/.github/master/CODE_OF_CONDUCT.md). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..ed62cf5 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,42 @@ +# How to contribute + +Support and contributions from the open source community are essential for keeping +`HARMAN-Automotive/utils` up to date and always improving! There are a few guidelines that we need +contributors to follow to keep the project consistent, as well as allow us to keep +maintaining `HARMAN-Automotive/utils` in a reasonable amount of time. + +Please note that this project is released with a [Contributor Code of Conduct][coc]. + +By participating in this project you agree to abide by its terms. + +[coc]: ./CODE_OF_CONDUCT.template + +## Creating an Issue + +Before you create a new Issue: + +1. Please make sure there is no [open issue](https://github.com/HARMAN-Automotive/utils/issues) yet. +2. If it is a bug report, include the steps to reproduce the issue and please create a reproducible test case. +3. If it is a feature request, please share the motivation for the new feature and how you would implement it. +4. Please include links to the corresponding GitHub documentation. + +## Making Changes + +- Create a topic branch from the main branch. +- Check for unnecessary whitespace / changes with `git diff --check` before committing. +- Keep git commit messages clear and appropriate. Ideally follow commit conventions described below. + +## Submitting the Pull Request + +- Push your changes to your topic branch on your fork of the repo. +- Submit a pull request from your topic branch to the [main](https://github.com/HARMAN-Automotive/utils) branch on the `HARMAN-Automotive/utils` repository. +- Be sure to tag any issues your pull request is taking care of / contributing to. \* Adding "Closes #123" +to a pull request description will auto close the issue once the pull request is merged in. + + +## Merging a PR and Shipping a release (maintainers only) + +- A PR can only be merged into main branch by a maintainer if: CI is passing, approved by another maintainer and is up-to-date with the default branch. +- Ensure that the PR is tagged with related [issue](https://github.com/HARMAN-Automotive/utils/issues) it intends to resolve. +- Change log for all the PRs merged since the last release should be included in the release notes. +- Automatically generated release notes is configured for the repo and must be used while creating a new release tag. diff --git a/DEPENDENCIES b/DEPENDENCIES new file mode 100644 index 0000000..295e015 --- /dev/null +++ b/DEPENDENCIES @@ -0,0 +1,34 @@ +maven/mavencentral/ch.qos.logback/logback-classic/1.5.5, EPL-1.0 AND LGPL-2.1-only, approved, #15279 +maven/mavencentral/ch.qos.logback/logback-core/1.5.5, EPL-1.0 AND LGPL-2.1-only, approved, #15210 +maven/mavencentral/com.fasterxml.jackson.core/jackson-annotations/2.15.3, Apache-2.0, approved, #15260 +maven/mavencentral/com.fasterxml.jackson.core/jackson-core/2.15.3, , approved, #15194 +maven/mavencentral/com.fasterxml.jackson.core/jackson-databind/2.15.3, Apache-2.0, approved, #15199 +maven/mavencentral/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.15.3, Apache-2.0, approved, #15189 +maven/mavencentral/com.google.code.findbugs/jsr305/3.0.2, Apache-2.0 and CC-BY-2.5, approved, #15220 +maven/mavencentral/com.google.errorprone/error_prone_annotations/2.26.1, Apache-2.0, approved, #13657 +maven/mavencentral/com.google.guava/failureaccess/1.0.2, Apache-2.0, approved, CQ22654 +maven/mavencentral/com.google.guava/guava/33.1.0-jre, Apache-2.0 AND CC0-1.0, approved, #13675 +maven/mavencentral/com.google.guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava, Apache-2.0, approved, CQ22657 +maven/mavencentral/com.google.j2objc/j2objc-annotations/3.0.0, Apache-2.0, approved, #13676 +maven/mavencentral/com.openpojo/openpojo/0.9.1, Apache-2.0, approved, clearlydefined +maven/mavencentral/dev.morphia.morphia/morphia-core/2.2.3, Apache-2.0, approved, clearlydefined +maven/mavencentral/io.github.classgraph/classgraph/4.8.78, MIT, approved, CQ22530 +maven/mavencentral/javax.el/javax.el-api/3.0.0, CDDL-1.0 or Apache-2.0, approved, CQ7249 +maven/mavencentral/junit/junit/4.13.2, EPL-2.0, approved, CQ23636 +maven/mavencentral/net.bytebuddy/byte-buddy-agent/1.11.13, Apache-2.0, approved, clearlydefined +maven/mavencentral/net.bytebuddy/byte-buddy/1.11.13, Apache-2.0 AND BSD-3-Clause, approved, #2712 +maven/mavencentral/org.apache.commons/commons-lang3/3.9, Apache-2.0, approved, CQ21762 +maven/mavencentral/org.checkerframework/checker-qual/3.42.0, MIT, approved, clearlydefined +maven/mavencentral/org.glassfish.web/javax.el/2.2.6, CDDL-1.0 OR GPL-2.0-only WITH Classpath-exception-2.0, approved, #1654 +maven/mavencentral/org.hamcrest/hamcrest-core/1.3, BSD-2-Clause, approved, CQ11429 +maven/mavencentral/org.javassist/javassist/3.21.0-GA, MPL-1.1 OR LGPL-2.1-or-later OR Apache-2.0, approved, CQ14999 +maven/mavencentral/org.jetbrains/annotations/13.0, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.mockito/mockito-core/3.12.4, MIT, approved, clearlydefined +maven/mavencentral/org.mongodb/bson/4.5.1, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.mongodb/mongodb-driver-core/4.5.1, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.mongodb/mongodb-driver-legacy/4.5.1, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.mongodb/mongodb-driver-sync/4.5.1, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.objenesis/objenesis/3.2, Apache-2.0, approved, clearlydefined +maven/mavencentral/org.projectlombok/lombok/1.18.30, MIT, approved, #15192 +maven/mavencentral/org.reflections/reflections/0.9.11, MIT, approved, CQ16665 +maven/mavencentral/org.slf4j/slf4j-api/2.0.13, MIT, approved, #5915 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..612c4db --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2023 Harman Connected Services Pvt. Ltd. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/NOTICE.md b/NOTICE.md new file mode 100644 index 0000000..fb37fcd --- /dev/null +++ b/NOTICE.md @@ -0,0 +1,44 @@ +# Notices for HARMAN-Automotive/utils + +This content is produced and maintained by the Eclipse Connected Services Platform Project. + +* Project home: [https://projects.eclipse.org/projects/automotive.ecsp](https://projects.eclipse.org/projects/automotive.ecsp) + +## Trademarks + +HARMAN-Automotive/utils is a trademark of the Eclipse Foundation. + +## Copyright + +All content is the property of the respective authors or their employers. For +more information regarding authorship of content, please consult the listed +source code repository logs. + +## Declared Project Licenses + +This program and the accompanying materials are made available under the terms +of the Apache License, Version 2.0 which is available at +https://www.apache.org/licenses/LICENSE-2.0. + +SPDX-License-Identifier: Apache-2.0 + +## Source Code + +The project maintains the following source code repositories: + +https://github.com/HARMAN-Automotive/utils + +## Third-party Content + +This project leverages the following third party content. + +ignite-utils(1.0-SNAPSHOT)
      License: Apache-2.0
      Project: https://github.com/HARMAN-Automotive/utils


spring-boot-autoconfigure(3.3.3)
      License: Apache-2.0
      Project: https://github.com/spring-projects/spring-boot


spring-boot(3.3.3)
      License: Apache-2.0
      Project: https://github.com/spring-projects/spring-boot


spring-boot-starter-aop(3.3.3)
      License: Apache-2.0
      Project: https://github.com/spring-projects/spring-boot


spring-boot-starter(3.3.3)
      License: Apache-2.0
      Project: https://github.com/spring-projects/spring-boot


jakarta.annotation-api(2.1.1)
      License: EPL-2.0
      Project: https://github.com/eclipse-ee4j/common-annotations-api


aspectjweaver(1.9.22.1)
      License: EPL-2.0
      Project: https://github.com/eclipse/org.aspectj


snakeyaml(2.0)
      License: Apache-2.0
      Project: https://bitbucket.org/snakeyaml/snakeyaml/src


ignite-entities(3.0.3)
      License:
      Project:


commons-lang3(3.9)
      License: Apache-2.0
      Project: https://git-wip-us.apache.org/repos/asf?p=commons-lang.git


morphia-core(2.2.3)
      License:
      Project:


classgraph(4.8.78)
      License: MIT
      Project: https://github.com/classgraph/classgraph


annotations(13.0)
      License: Apache-2.0
      Project: https://github.com/JetBrains/intellij-community


spotbugs-annotations(3.1.9)
      License: LGPL-2.1-only
      Project: https://github.com/spotbugs/spotbugs/


mongodb-driver-sync(4.5.1)
      License: Apache-2.0
      Project: https://github.com/mongodb/mongo-java-driver


bson(4.5.1)
      License: Apache-2.0
      Project: https://github.com/mongodb/mongo-java-driver


mongodb-driver-core(4.5.1)
      License: Apache-2.0
      Project: https://github.com/mongodb/mongo-java-driver


mongodb-driver-legacy(4.5.1)
      License: Apache-2.0
      Project: https://github.com/mongodb/mongo-java-driver


logback-classic(1.5.5)
      License: EPL-1.0
      Project: https://github.com/qos-ch/logback/logback-classic


slf4j-api(2.0.13)
      License: MIT
      Project: https://github.com/qos-ch/slf4j/slf4j-parent/slf4j-api


logback-core(1.5.5)
      License: EPL-1.0
      Project: https://github.com/qos-ch/logback/logback-core


reflections(0.9.11)
      License: WTFPL
      Project: https://github.com/ronmamo/reflections/issues


javassist(3.21.0-GA)
      License: MPL-1.1
      Project: scm:git:git@github.com:jboss-javassist/javassist.git


jackson-core(2.15.3)
      License: Apache-2.0
      Project: https://github.com/FasterXML/jackson-core


jackson-databind(2.15.3)
      License: Apache-2.0
      Project: https://github.com/FasterXML/jackson-databind


jackson-annotations(2.15.3)
      License: Apache-2.0
      Project: https://github.com/FasterXML/jackson-annotations


jackson-datatype-jsr310(2.15.3)
      License: Apache-2.0
      Project: http://github.com/FasterXML/jackson-modules-java8/jackson-datatype-jsr310


hibernate-validator(6.1.5.Final)
      License: Apache-2.0
      Project: http://github.com/hibernate/hibernate-validator/hibernate-validator


jakarta.validation-api(2.0.2)
      License: Apache-2.0
      Project: https://github.com/eclipse-ee4j/beanvalidation-api


jboss-logging(3.3.2.Final)
      License: Apache-2.0
      Project: https://github.com/jboss-logging/jboss-logging


classmate(1.3.4)
      License: Apache-2.0
      Project: http://github.com/FasterXML/java-classmate


hibernate-validator-annotation-processor(6.1.5.Final)
      License: Apache-2.0
      Project: http://github.com/hibernate/hibernate-validator/hibernate-validator-annotation-processor


javax.el-api(3.0.0)
      License:
      Project: http://java.net/projects/el-spec/sources/source-code/show/tags/javax.el-api-3.0.0


javax.el(2.2.6)
      License:
      Project: http://java.net/projects/uel/sources/svn/show/tags/javax.el-2.2.6


guava(33.1.0-jre)
      License: Apache-2.0
      Project: https://github.com/google/guava/guava


failureaccess(1.0.2)
      License: Apache-2.0
      Project: https://github.com/google/guava/failureaccess


listenablefuture(9999.0-empty-to-avoid-conflict-with-guava)
      License: Apache-2.0
      Project: https://github.com/google/guava/listenablefuture


jsr305(3.0.2)
      License: Apache-2.0
      Project: https://code.google.com/p/jsr-305/


checker-qual(3.42.0)
      License: MIT
      Project: https://github.com/typetools/checker-framework.git


error_prone_annotations(2.26.1)
      License: Apache-2.0
      Project: https://github.com/google/error-prone/error_prone_annotations


j2objc-annotations(3.0.0)
      License: Apache-2.0
      Project: http://github.com/google/j2objc


logback-gelf(6.0.1)
      License:
      Project: https://github.com/osiegmar/logback-gelf


junit(4.13.2)
      License: EPL-1.0
      Project: https://github.com/junit-team/junit4


hamcrest-core(1.3)
      License: BSD-3-Clause
      Project: https://github.com/hamcrest/JavaHamcrest/hamcrest-core


mockito-core(3.12.4)
      License: MIT
      Project: https://github.com/mockito/mockito.git


byte-buddy(1.11.13)
      License: Apache-2.0
      Project:


byte-buddy-agent(1.11.13)
      License: Apache-2.0
      Project:


objenesis(3.2)
      License: Apache-2.0
      Project: https://github.com/easymock/objenesis/objenesis


simpleclient(0.6.0)
      License: Apache-2.0
      Project:


spring-context(6.1.14)
      License: Apache-2.0
      Project: https://github.com/spring-projects/spring-framework


spring-beans(6.1.14)
      License: Apache-2.0
      Project: https://github.com/spring-projects/spring-framework


spring-expression(6.1.14)
      License: Apache-2.0
      Project: https://github.com/spring-projects/spring-framework


micrometer-observation(1.12.11)
      License: Apache-2.0
      Project:


micrometer-commons(1.12.11)
      License: Apache-2.0
      Project:


spring-core(6.1.14)
      License: Apache-2.0
      Project: https://github.com/spring-projects/spring-framework


spring-jcl(6.1.14)
      License: Apache-2.0
      Project: https://github.com/spring-projects/spring-framework


spring-aop(6.1.14)
      License: Apache-2.0
      Project: https://github.com/spring-projects/spring-framework


spring-test(6.1.14)
      License: Apache-2.0
      Project: https://github.com/spring-projects/spring-framework


assertj-core(3.6.2)
      License: Apache-2.0
      Project:


+ +## Cryptography + +Content may contain encryption software. The country in which you are currently +may have restrictions on the import, possession, and use, and/or re-export to +another country, of encryption software. BEFORE using any encryption software, +please check the country's laws, regulations and policies concerning the import, +possession, or use, and re-export of encryption software, to see if this is +permitted. diff --git a/README.md b/README.md index 75db3f6..73f4fbd 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,182 @@ +[](./images/logo.png) + # utils -ECSP utils +`utils` project provides the below functionalities to a service. +[![Build](https://github.com/HARMAN-Automotive/utils/actions/workflows/maven-publish.yml/badge.svg)](https://github.com/HARMAN-Automotive/utils/actions/workflows/maven-publish.yml) +[![License Compliance](https://github.com/Harman-Automotive/utils/actions/workflows/license-compliance.yml/badge.svg)](https://github.com/Harman-Automotive/utils/actions/workflows/license-compliance.yml) + +1. Centralized logging. +2. Health checks. +3. Diagnostic data reporting. +4. Application Metrics - counters, gauges and histograms. + +# Table of Contents +* [Getting Started](#getting-started) +* [Usage](#usage) +* [How to contribute](#how-to-contribute) +* [Built with Dependencies](#built-with-dependencies) +* [Code of Conduct](#code-of-conduct) +* [Authors](#authors) +* [Security Contact Information](#security-contact-information) +* [Support](#support) +* [Troubleshooting](#troubleshooting) +* [License](#license) +* [Announcements](#announcements) + + +## Getting Started + +To build the project in the local working directory after the project has been cloned/forked, run: + +```mvn clean install``` + +from the command line interface. + +### Prerequisites + +1. Maven +2. Java 17 + +### Installation + +[How to set up maven](https://maven.apache.org/install.html) + +[Install Java](https://adoptium.net/installation/) + +### Running the tests + +```mvn test``` + +### Deployment + +`utils` project serves as a library for the services. It is not meant to be deployed as a service in any cloud environment. + +## Usage +Add the following dependency in the target project +``` + + com.harman.ignite + ignite-utils + 3.X.X + +``` + +### Logging + +To implement logging in the services, the services need to get an instance of `IgniteLogger` class using the `IgniteLoggerFactory` factory class. + +Example: +```java +private static IgniteLogger logger = IgniteLoggerFactory.getLogger(ProtocolTranslatorPreProcessor.class); +``` + +The `IgniteLogger` is an extension of slf4j logger. All the concepts related to logging an error message, exception, stack traces, etc. alongwith the different log levels remain the same. + +### Health Check + +`utils` provides the services with Health Check capabilities by implementing a number of different `HealthMonitor` instances. +`HealthService` listens to the health state changes in all the `HealthMonitor` instances implemented by the service and maintains Gauge data for the healthy and unhealthy health monitors along with the overall health of the service for service health monitoring. + + +### Diagnostic Reporting + +`utils` provides the service with Diagnostic reporting capabilities by implementing a number of `DiagnosticReporter` instances which in turn maintain `DiagnosticData` for the metrics and the corresponding `DiagnosticResult`. +`DiagnosticService` listens to all the enabled diagnostic reporters and do the reporting in Graylog besides publishing the metrics in prometheus about diagnostic data of a service. + +### Implementing metrics +`utils` provides the service with metrics - Counters, Gauge and Histogram. +Any service can extend the above metrics for reporting and monitoring purpose. + +Examples: + + Implementing a Counter + +Custom `Counter` classes need to extend the abstract class `AbstractIgniteCounter` + +```java +public class GenericIgniteCounter extends AbstractIgniteCounter { + public GenericIgniteCounter(String name, String help, String... labels) { + createCounter(name, help, labels); + } +} +``` + + Implementing a Gauge + +Custom `Gauge` classes need to extend the abstract class `AbstractIgniteGauge` + +```java +public class IgniteDiagnosticGuage extends IgniteGuage { + public IgniteDiagnosticGuage() { + createGuage("diagnostic_metric", "node", "diagnostic_reporter_name", "diagnostic_reporter_sublabel"); + } +} +``` + + Implementing a Histogram + +Custom `Histogram` classes need to extend the abstract class `AbstractIgniteHistogram` + +```java +public class GenericIgniteHistogram extends AbstractIgniteHistogram { + public GenericIgniteHistogram(String name, String help, double[] buckets, String... labelNames) { + createHistogram(name, help, buckets, labelNames); + } +} +``` + +## Built With Dependencies + +| Dependency | Purpose | +|:---------------------------------------------------------------:|:-------------------------------------------| +| [Entities](https://github.com/eclipse-ecsp/entities) | The library to implement database entities | +| [Spring Framework](https://spring.io/projects/spring-framework) | The core spring support | +| [Spring Boot](https://spring.io/projects/spring-boot/) | The web framework used | +| [Maven](https://maven.apache.org/) | Dependency Management | +| [Junit](https://junit.org/junit5/) | Testing framework | +| [Mockito](https://site.mockito.org/) | Test Mocking framework | + +## How to contribute + +Please read [CONTRIBUTING.md](./CONTRIBUTING.md) for details on our contribution guidelines, and the process for submitting pull requests to us. + +## Code of Conduct + +Please read [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md) for details on our code of conduct. + +## Authors + + + + + + + + + + + + +
Ashish Kumar Singh
Ashish Kumar Singh

📖 👀
Kaushal Arora
Kaushal Arora

📖 👀
Asim Manzoor
Asim Manzoor

📖 👀
+ +See also the list of [contributors](https://github.com/HARMAN-Automotive/utils/graphs/contributors) who participated in this project. + +## Security Contact Information + +Please read [SECURITY.md](./SECURITY.md) to raise any security related issues. + +## Support +Please write to us at [csp@harman.com](mailto:csp@harman.com) + +## Troubleshooting + +Please read [CONTRIBUTING.md](./CONTRIBUTING.md) for details on how to raise an issue and submit a pull request to us. + +## License + +This project is licensed under the Apache-2.0 License - see the [LICENSE](./LICENSE) file for details. + +## Announcements +All updates to this library are documented in our [Release Notes](./release_notes.txt) and [releases](https://github.com/HARMAN-Automotive/utils/releases). +For the versions available, see the [tags on this repository](https://github.com/HARMAN-Automotive/utils/tags). + diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..4773bf0 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,21 @@ +## Security Policy + +Thanks for helping make GitHub Open Source Software safe for everyone. + +GitHub takes the security of our software products and services seriously, including all the open source code repositories managed through our GitHub organizations, such as [HARMAN-Automotive](https://github.com/HARMAN-Automotive). + +Even though [open source repositories are outside of the scope of our bug bounty program](https://bounty.github.com/index.html#scope) and therefore not eligible for bounty rewards, we want to make sure that your finding gets passed along to the maintainers of this project for remediation. + +## Reporting a Vulnerability + +Since this source is part of [HARMAN-Automotive](https://github.com/HARMAN-Automotive) (a GitHub organization) we ask that you follow the guidelines [here](https://github.com/github/.github/blob/master/SECURITY.md#reporting-security-issues) to report anything that you might've found. + +## Dependency Security Management + +This project uses Dependabot tool to monitor (and fix) vulnerabilities in this project's dependencies. + +### Dependabot + +* [Dependabot](https://docs.github.com/en/free-pro-team@latest/github/managing-security-vulnerabilities/about-dependabot-security-updates) is a GitHub Security Feature. It tracks vulnerabilities in several languages including JavaScript. +* When Dependabot detects any vulnerabilities in the [GitHub Advisory Database](https://docs.github.com/en/free-pro-team@latest/github/managing-security-vulnerabilities/browsing-security-vulnerabilities-in-the-github-advisory-database), it sends a notification and may also open a pull request to fix the vulnerability. +* Only project maintainers can see Dependabot alerts \ No newline at end of file diff --git a/checkstyle-suppressions.xml b/checkstyle-suppressions.xml new file mode 100644 index 0000000..42ee9f5 --- /dev/null +++ b/checkstyle-suppressions.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/harman_checks.xml b/harman_checks.xml new file mode 100644 index 0000000..fa7cd59 --- /dev/null +++ b/harman_checks.xml @@ -0,0 +1,420 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/logo.png b/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..d97dc019a96904b33ee9dbcd11fd40ecac7aeb71 GIT binary patch literal 17097 zcmeIZWmFtN+bue{LkJE*BDg0=aCdhYY;d;(cL_=G5JIrvHn_V5C%F5d0S1TQkQq+r zeZRZz@B8cAb=LX8Vs&?Q%~M@f``LR}Rg|W>0s$^HE(io7P*RlD27yq?|NUWO0(bBf z`euNCIPQu@?}00le}5>T^dFSKO_cZA3eup;@n`$M1-hM-niL3BlYsZv0s{n+HdB(7 z()C3-hN;Es*>s+s54v^`2x>!ooEwx;cnKoCwLR0Dl6;By?A>iQWtrPAhiG#1?U*hl zX+Mv)M)A0N=A@c1heu>6q8le<@^O2sC)TTVM`17P*rft_|0UdwmFGL^rT6VA!P(UE}4F#YXKZ(PEnA|@?fIB~)8v^0lVFPXa zN%enk{~z{EcJ&r=;!uJt zi8(;4)_=D6>jv>iu?CBu(l^;$p}rA*E&CJXP6CXL^&O}6j2f%GvBfEkj?=D@OA)D? zA=EB1G|&eK3ZIE!SRO43TBuw#h}!uG&TQ5+xKxQICxVIz3dfj~r2f)^7$X|{-CxE; zG_t#H;Vp_(888PC$O6S*RZhR;*8Kt+lL0Pr;F44Ep(uP<-Kfx-^1^(%Tv;-xL^y_~ z3>TZ&pB|7#&KfqkWZX9)&H9%R&=v5$V~^Lqy%sj5WXBVZ(CCpi&w7?`P}D2QY7krL zdNQ3~Za6wr0H}c1i-7bPD8^3=6k{<4-eJ+gD2;@md^1V@pQ?p{s+EXYih!DT6skeW z&{80P=fDNfD&+#M|39zb!LgOdA4?dJ*{W_;KB;#45|Hl` zUA-U{BA|M0^jLdz+?-V)o?pij_fbneM@a)%u~JoKR)gC_#4Mp-UmAkQa{kOjY-iu; z_zRAeQ#IYa*LOA%YRX@)OBU$$b7d z&WSP{yqM;L8|~jIq^xc?K|t;?5R_TTId;X?l1uj*MH;7g&`3fjKuG{dR zQ29{0Q6(o1w1Fqex>|O?6H_PULIpD@gA^@d2qa0t_kAmLL0bw6UjxPqVxBHX-M$7i zN#Ygq7rF7Nh1*eI5XLc$sS8vSN^D>u6g4wGj@6j9oPN)MNe1@R>ENRzQ zt7vtla6l^skc)u=JyxwL7x9G9^ot&`(s z-1J3=eex|j-fT~P8`4>zym*jpBqbdU?)PlA<*?IIAuc%p*KW$5PJG-E;5)GFu|sFf%;` zEt$X}hvJ1}IOd8O8m7PY8{F=){wwz*J1i7 z=erUDYE4`-!_rN)jSTc$cu>t;J?UEK-|aHPMIL?~uz7}vTXBj?|m%FzuRb$tJ5}xA7JfJ^FDi(NuSvvhx1HdR_I2lT=x1UJS;i^WQ zRTD1jbNwkhXwe7*r!YU%7#)v6eqTkmjE-fQ%p^~FpXCdHWnZKzxJ*^$Q&z16DpOM& zc+4wjBXg9AOg|j5>^;>}RtO8^^(AT8uspLR52|4B(AuAhYR7W3-K-8Tpa)tHIb-_I z2Vr3|G>pWI%|naS`v|ePdcreI$HMVHpMyo%&`_o#_}+%)@@8`mT@c*_-ZJG>BefxmG zYH@5aDiz(j98c1J!1Z>cJiNdaNG1E#viyX}bfEw={miXI!wkz4q5Td8mtHO+ch|8= zB?*B~MA!ph1ZB;E88G`@BqD1c1Zdtr)~%(vsQ>Qe>`9%6@GrryFX5KFGCwEWcKBYCgFM)<867WNj&vlz`O#ccTD>PtD z@&T9v+Q9Ed1%ciISrY^r2fzyy`sRP*?S|^@^G~B2KhiMc|2jADcKJR>?!A0;9UZ;H zbmhqQ`Q&FihlUA_FecDM0|*DAO6)X?A4^?5tt7^Ppf#sDXEFzp_h{728(ydK`)APOiRm_w7@Sf88cK>)EF8}FWXGF0(C*6)mHp#1KwnC=J8z^T-b zyCmL=>^DQM^RX+Vkf&W(TZp=h?ce16fWzKkAgjZ1p)$M6s%`k@UU z%W=mSN~Sy;9cH*GnfnBPmbe?WLGGub1zIGSmXycerVXGLi2~(60>m^&)1|oi4q_l- z%XKJLr$vSMXQZZ=3vcmBkDY%S-Z5kPrb8e_J;#k+G1#Q`=-2P~2L9an-1@`3g3{S4Mw!Ba)+pO>Y0pSZX>oRLc`U7IsDI zr#wJS!mZMp1doVH-aYSrr0+upefqDM1yyEJE<(|cX?oRSDX#{Sldo_CD0ZDG53UgZ z(F-lXj9s0jHb2%})HwNS$re`4X9%^kt1;iB-r4&zc;$@Dtz`FzvkVpeGbKefUX4or#?SEv;&QP0C{OJ)WG=B+q{VT7ui)swIpo zyZu>Gh($B7eI&Im1i#Y<@@Gr0%gK5oz^mMuaI14VH1g1{?VQE-YXy)%6E0 z0T3^NVJ=F_Bj5*n>GbiGZ)KjqjxOYRAr9p~?x?Jt=g2MwOml#FkZJ(fTL^y#^yOOG z?ewFz=A=DR9ql7nlrTPIw;?pp8aKZZmB7<^S$E053s)=qgrIf!o#UKiaah{QJZHf$ z8XUD7wSWJ8j(zbwR*)Ap&umwvR6xGU$*->P0%ZVe&SmCefb1)DgZq?CEOgD|H$#Zy z0GEeSZcl&Id-De=DU_FGCMvo(q%%8)dCEDU)!bFmJFU6~Fblv){`leYA*DArrc6Ul zLZV93AIl7d!Qb4YN+W8R*l6d_9lph*y1J8gcRW*8h?!n^I@kIwo?LE4X(ri6=x35L z5d%FsUUT6;Bpt?x_U2O2)!{D$Ncu6^D^{TWovwG?R-tBOyfukjbglUbXB#SR8KPb~ zQkH4}`k z;TGHNXg_p(kiAT`q@6N=o8J%$5)Nv$b4F2Ypjq0TqM?EB@yNj{YI?SEGi6<3ucDDe0deKxBM{+Js9crV&tr;i_|3ph;PDJk?^9v~*6LoqY7@cnAM8 zW;2n4PqDz{!3XgHBt%f;K4YUyV?=i$s#T5-cGXEG;=cxx)Oo_;UiUFMf!t!N2M{-E z06+c@zJ`kDeeKH}S?ClDSbG?9Mo4U9N3l3p7It)|A7A#Lm42`-#(khd<4VhDL(F@ zYr#kP9FTG>P%5=2k}FTm{AiSL^cg@bP&8eEV!w|p?XU(VE_(U_<(1D$$}$k2d4t+t zymqrr^&ic`)}#OB$nVto7|2ejP_BQvM*tE_`_SiX+%&|I5%Q^o#OskobUz3cN(VgD zVyh|FiDFBplN9@>p33|&aDdk+fF~pZ5ND%~pRw`y$>I=AVcb~~K#@@yOVwKR2LVXn zSLDn>i*XPK(E2Z!;wPe>14k0q4i0RJ&`VHy7;x9nNLe?692XU15*>&e#rfx3_jkib zzJF69CYtjU`6ZVHqi%}EAUP-b-^mwZg#uF$)Tz#4khp#Dzj;GrTWRSb1(nb0z)64g0x>>0GAsyDE zi4SpiBW~fRVbRYGbN-&doJYHmc4zC9RpR`X-V!Z+_~U5~p~E;>(Qmld>}w`(PJJJ* z6M`_IxZxPXhjwLgMt96s@<>=}+Jz2%r|qr!``e{YWATIZFCaO>;%i?2CVZ&JyEiCk z$x_vlcZ-s_+(GNlla-$GX!<`QT%V95ktYAZA8p{F3pbd8g%zk)rsAmzktZ$7GArb0 z<;qTf%b;}Z^S~%c@3{m9Cgaac5*y5 z14QFOIIr+@He)Y}`CH9qdym_}wVeKl(6FyS8$(E0g3rTwojN2v9^W%*;8Kdn{|nYP zm}0;U2F!i|$X~=dHYE!NQ2RF0E<&>Ate*iw`sx|a_ldS%P)kiR-Q#)L##VMy!lPmo zn{pT=%(A3R#*~f-Su-g)r4FRZT_9C{2+;bker5!?Kd*D)CrmqA7C=amy>e%(_>Y3i zOTZ={GDrYQ)u33dw9295dsYJcGfy)wTAaam>|)wQ8(eRcbrXmG*#RtCawyp3?k`P*!R~u1;weVI){RUPAK0&4`9);FZvnyXqlD0~N_!7Xod{{Bzd=>AP9E`Q7K9T~nFTwC= zw8H3(>!GuA4C+AFUsn5RI}R;Tmkg}OCm(oGF|=3zL=1x98NXr-#bC@(b)bL@R? z?9U1-iM2RWg8q&v{mqZ2cfk|G5?WQZFUcVgd9*^CvF= zip10!JgvX!>K@_6wnvM8IzH5?EjDwgArRXV78AJT-~BZR=0vGlZDDsRwG1$wFo)10 z1jBII@&H#NLhwD{8L1@ygGfm!ptX@ZR6O^@9DEjrjHq&Lud(n^F>nFT!g1sO(O<&I zydg+p05Cj;_5aDK`%qqTNdgx1XTjH-!+KvXD}a=2!>Uy{jTZFJ2PEN#FeJ-*ii z_<$r1fala~PEn=G3Qd*Zjjl#{mQvZ|X{~SA0FLt-=PjS|D+067OylJaP=239`Ez%M zq>Lw6Y73BJg}}Jp$_xLXO!N)-HujVlv6*g}yb9_efH7ni(T~Zk>TG%i3VWe0h!Pgk=pms&5 zWQoTt8o^GhY{NCcb(GluHG=G)|5v&2R1Y=sK~yO9xq)sG2OD00&48P>w(Os5ktqw?-C|<@8K}{1M9XUk#-9{Qp|o|KDx?UHyo7RnvA` zF4Ko`lg?{IeKx^ZngizEC=ba0@^RcIC*ju^CMz_?ETpCW_AYK z3&TFm(6^%Jk!gQ-OaJLsRkQYkM`Lna3S6pQpNZEor|CP72Ikm}hb4F^?Zy5%+ z^1{;_*8%e~J$LC%$Eln1M5(aHiBkyuw1JuJSo0XZea4c@!oAy$iJ0AJ_Q?eD*1X+* zw1+}9vA&CrGW#`2w)yo0(efwGwkob{9|aq3d^pjug0R8ReWH|(9(v4^pqx({Ar}8Q zdFI>BH?Zk`9dmCi;!Nl7V_m%(xoWsn*XV(N{~D}aH>diwW$~CRAln*q8`odP1fPVM zds`_;@CK}jtjr*1@m$z3V2}XBERh2|>v|9H!8<0dW)>%A=^h?BCV~N1Hf@S=u0s+8 zvk$DUrs#ZWmV=FjvhcTU?!3&*KJAapz;``7$DkfRyDgQv2@#aGwIYAH$mMQ(I!OwqGZ~SgHM3TkAkX=F~x+1DK2OPb+V)nNW9Xj>o$01er#> zvJ7p$B*|mOh@A$_rU2=jxdecMb1unj{Z0%SigJVYwhK|?ps(;#SK*s5dJe$YAJI19 z(C|Z?+7#hscVbiiT9)bmK1Xyr=tSKrIjI}RCOFr>2M7~^fHg7WQd{Mf@Z1G~G>=gG zH2Y`WBvrJ>#!zfL@$DPL*`k{cM*VVgj{A9^QwVFn0Q*aq6m=PlN$WU=n#GF~ga#@!b<$ip8tO~gonua^9s`qJlC@h`^9!&M;r12l23@N?fnWx|D_bymoEbF@ zaO9n}gR(J*yj_i_ubTjrDTkHQWq`l<)cd937aarJd!2u>PSbtpeoRdr;z`^P>#dZ~ z)Ln_*)4+5mKCs_hwqLh=Jf&;i7yG!LP$B*>@ZfeU&(aR7{VO)rAX(KmW7R)*@y+Ns zBC-PSaN02PGEKb8HSt%kF8gBE^>wyRw)uXujXE=g z|AAx(RXDh!Lg+(uLFscuzQhXzRZ2KJtZteHK6^o*UB0G*NYMy$m0U7CVFZt}D#xv0Q&svgAlW}o~#)@I~ zn1EYGkxNAV-W0)(eWZ$NuOlr-p1eo#l$?fzG?p1Rg%{#v8SrAcwT8|f>NV7D?t|jC zLbiIQrn5G@a%>66a7m;XduY3JN@9;58do$uH}Oh+J4Z?9NmYYy?tf`Fpc445SOrNT zPM6KR*GHD4i?$=(i8UKi;lAEtwl7wf?cA)%8@S3_&sY^#T(w~^TUdz8VYztQ&PDJ+ zQ~C1V%=uZs>7D1)*gK8`%9(94eHV;a35vKT?tMF9EI6i>`KVkAf`94eeke}_k%0%} zv8TZjMCrcc+V^sh2;P}YJKXH+RCqAC_G+09Ca77FJQ5m`Xly@z7?@#yBcU-XaMlK| z3U)i#_)afc^ii0AY}q2~{9Yqv&qOb0VOwy<4xdsO#r_kg&Pe2R!-@Dbbl=x0K0@c6|oj==7UacsZ82|H`A=G_8wZ4+S_g zz%0n|-n2`+O6>vZkC0CDoSK9AyoD>oVNBV%4NkHA9*jgWW$E>~6^_4gxxZ55jLB?o zbU*y{G5I~>pyDimK*C_UCf7=7QzloM!nVO(7NOP=+@L9c+~h4{gAk4Ia5J!aH1o}1 zg0+8;$c9eHhsX#@Hjc=bief3d0G=%YnWO&rH6PhUQ^-WlXv?tx4I0fFs9eu0U_q4_xoGMxNHk;F4W8>^IjrkEn}uEFcEM zFCvva^IP$ICJJ5Xd}5K~D-89+a8bc&nnP- z-fh>xH{(~1>qy1%ExzspZlN74k&KvSc`2zK8N57hts?Zm87Lk5X0df-4#j{pQ<2oN zmXD0x#9AnKJ`HwLi~c(E$)NIEdW9(yZ=A?Mmk-?IQz1S@MiTE59y`Qi&S+hJ6j*6c z_^^)%X;-j%Smk)G)#uv%IfU;C=XPgRbmjX=SU#%5TaF-08QFUS0qYxHW#qgPLx${6 z_8S;s3`-?Vy%Dm#voTd`qWoE-+q30?c|JK}3433G=K0BFws}UtFG9NbPF`!xx*o_HY!RF+wY@k)Ovf z1Z2R2&`EmlV?Cq>%FiG?-r)kHa+n4`bJ=M9<8q0#;4Y28iKt)6W_LtV=;a&I80?0e z6MXu>A9JD_=-m98>ENPf@7MneBIx0~nP8J%yZ-9>Ql6*~-$oaamrs8dG$VD0pJFdDTxBLm)*>8L&Fux!~T2qYrcOpx_iy;nZPh%kB1m9k_6u zM%VS$vr-uktxjj0VDtT_nCetB9O8DfxNKkRg@>qwj=m34w(UShR<0<%vX`@!5YYy@x~;jN5G3?XtZVg zVP1xF?bOoOIs`b$k+K5JNz9JR=eH4s=0>`( zH{P327RNbCS}L}Bd>&CHO;Q3ywiWNW!>PttnvAEa*D__1g)u4j4}ydEq=Zby>6hub zdudEmoe$R;-`h`b`g2Qnx`gQjt)EHoe3`_ZPJk5F`1bnPh;%hzWgAiTTES+S44+-9 z`zuwDwcaK>d@Xp}X#A>#)!b*rA)?bnnD}7bxwvh$07VH=K+?1MLC>jyHf6%cK-$m? z$8AoFe6GxAk~{%;{NH#$#)dXN5~8VRD|oahyl zV^BHE$QyjcgW>`_srj#MOiIFG0v-VvBs&emVjc569C}m^-^cJU;c5-G-_`Qd>^Rj7 zOc}4$A3dFh&rh^3pN@HDBm$I-b=CWoD#W%_HoXRpBC z4cO#LXn2UCd)#p|@>#yYCNL>~s(Q%FN)@J&9x~1i%2<}n zk>{S0ReWDn!Fl`?)b(v7TEObj4fBtfu8oga1qSDsN)&c06+GXyU(=5!kx zv6{RxZT|!&$yBqo=d7*B?5+iEM{P=niEw#-GFC(EFIi>nCCiW?XZO7{?|8}YzkHo9 zhi-M-m&{onEfyzIcpo1*3XFu{{<)2C@W7CcgbD@NjWUcw)Wfz0%7Ddh&Y)FUMK8O( z_L_?PR>?)V=Gj#@tY-&yxaQ2`rk4rEagku#BKrJI4_y(WOkRM0pQFMu7uv`W{2uCS zqE=RVZeNaaAenWS<{b&wH>D@~k@5YlZRTVM6Ms69t0vP9L(^67=e;^+DT!GM*;DK0 zzI=a#{!041zBRj8at0H}QcW+$UGw^STXM9Ke>Q8w%;9n!Bijm@M>-J=c=X2w%v``* z$V87WKA1P{!Zn4;f{Q{-+>*(Gkei4?v zy6dwIKkbL*yb7AX_G|P%h3Qkub+}51#;?j$vqThxMQ-ZxmJLfxT6*)HG}g_8w)~2j zVtxZ-eZt{NPSGc9#M&J1+@v^piLiOX)rqqUsYXNAFBjSVR5gBX^zfr7uZaR&0V#Dk zF)y&4I5U>v`^Y-dS#nYq(2IrK8CvkIT5mM5 zPlg~m!l)#!!DX0#yV9}Z1@m(A&Jg3V7&1%(~5HOO?u4PRXqS5$Q`UoS5; zubh}RL9LDbgwj-DP=f@Mra4d$h0g;Ux^(*xhsa@c^}1VaRGSKf>@ z4z60RLnhlF{%DOV2OzVp8T3Qsnfa+@6 zSZyvn^6j|8uE{9A+P<<0KvC4*Cy#0Vm4WGGh)c0xQbl$2r*XdPR(`#ZZM9I%&4ej9 z4*9kF(A?xzu}buYM!ZL%J z*No`-vKG^iQl2(NZBj2Ut#mvFHO>f(KQ*E@Ve~a4s3csatR*zoOQO;kp`MpiIWNIT zpAHJTuePvR+SB~DH9=s-7plt27Ot79yLo|q5p-MBK3Q%Q(z|maQ_&E0ARKBWi0c?P zn=Vo%E~K5|mHKbPfv{x?ZSYouRY`-=;>4B&dc6wNZw!u z4=)VM^i24+KzC}H$QR=@TVAMUaXL@-tvC0DPrPj7}_|MISkP4zU{^+^HX)H^lqyl`rMf-2tvEquYMtC(cWUSGAWnajG_RFSbZ zW>IGIy@{*ci(j{wDlU8uQ9w4gI&wN??)?a~3(9 z=cl#b^U*JhyV{X}le3>R!~4J?8H4f64_On5L^a37)uAnKb~NUh9c>M^u0BUYzbI&P zz=#eS9Jj-Le}L-eclmtAIz<}o+eNF@LUUYqdeiFC_aCm|2G!nUH)1X?DJH^>03Tjn zt=q9Y-+Eu_JYF=I3Q&8tA^^uC zVa76&#(+tp%53Ch-lJ@r`>$C8y@MLV)O$NBI}3BWhv4FE;|d9-WXo%@27^ub>48t( zYA76WCm!!T|Ex?F7ABtSNbQ4)`b-oTj zv8bY;+(O336VoVOreW2=*6bPE1NrS~Cr?*mTCbz(A-PX-_ViTr0zzvmOy9BEJX4wu zAQhY79OyeSzek*fF7b#JgXONkJ^|TsCOngO+sQI^FA`A1K6N&hgC(nnaE!@XCNob6 ztEfz$=VydI-_*zVs)MUn;#5#Jw%3@)9EqL6eqA}$wAD@p7l)Q1Cdb*z@U#Uj3@G-_ zFmx(V{j(TACf9p`Q?!l2mES*d#N5Zx63|Hqzsq;DV(_e4ZQc@pyq&W83O1>qSo$^f z{f4L4F@S~A1xC5pe>h!g*V9$?&TK{4qA8Irm9P=@3)mnJa|V->zq?fqS1EmV0vRM$ zm1XBMy!hhsBP7hE0V{TUuj|Af|0CSGdR-(JUWPOG3Tu%0;VGNv)3vek=oxsAHG6h= zOtAZ4``ijqiq|B6UL|@!H|+eD8=)_zvhw$CF#M^$R}#D@t?+PXUGQM)}`Xo^Y8prpuBMcvUd5`oG}K>?4~8_FjC|B<|K1 zk1Q^3(&Nu~T^U2-N{oH7bs81;gX_S1tD<0kjuhU5OeKMY(uCchGdyqoxH;Y3 zp|W*)Yb`&>^tfJa4#BLn9njOQfRYa@Y%H1A5)H?|EpCexMBXT$##-Ixom8z=y@o=7Q-+VspeI0mSd>MP(tHGtP5p#n%lKpn63MFI5NJa z^C)MzT(p9&Y->3?R9@$E6t>I+cagFET}V9Zy!_kP|7X^2X3*n9TX@ez)RsGw)cRtP zT4r^G_)HzGPtq;Q_9_rO%_Oxx^qc4U{C>hm%x;YrK?_D3c~tA}P*`^0;_ zje^I|(~mCnhZ?9bul*w>tv@jTE(b*>?_7io|C%GF;nC%u&H#9fP`rqi3Aou7Pd9GVg?+b=Y6RGmcUDPyljeMzU%)|Wj~IQ_GO7L zl_!Si5$v1nE_f5@#inw-KQaIufZ z$L$~%CD8te`p+&`AT0%=e5#c zg3(@I8OF`9q?;w2{6>5ov)Zfb5~qj|uwkg5F5A`J@3-WJ9*=1{W-zU~kcoeS|IL|* zc2A_objzFl2u5@^rWYjbf-@zve2=+2d%L5|h%Z$|4p$Q4UUAi4 z^EXr0vr1tT_Q*}&Ccf(RA-a7O^XfjHzSw;Kx#DPQ?}?rksvxkB4nOnRwX4~|x`QHtkpg%xV&gl~S}M)YW(6eJMzc#s#Si{kP4YIC_lk{OrtZ7|7JDuZ z*SX_U^ZTnt?O{`8FP)Lci*{s64xDJdBFd|;M z(1+-zgk_n(adUNyTW}xq#`vIO7C==`RkS_T=_4|sI@@n9u@da=Kc`UrbFuxfiu>dS z!LQfuf_z9ltG%e0K?=m)n-ZKfo(8CuMPi)rzQ#{3PFkvMB;N4w)Ly`0ckM)Bh~_jR zZM(eQae8cbIPi+ZReMgWP!{i4i76seC|$`_bbUvveI&xyM-E@1K>sKF%Q9AiuN%PCt;@c`^9utoF&bPL6)164;)d8OR;L8H#p{ zKQ{PfVe@aHN94vX)2SQLax@6*klzvTS_x%%wEKXUe+MPm@%?f zJOM6Qu-p^eFEXiJS#NsyBZ*}*d3>t%5Ij$1ek^dhd$S@@rT!@3-%BokjNg!6z@O=+ zy`N#byN#N_;mM0D4Q*p^G`K(7ZMb~raddsthQkZ%RH#{LUvc?;e^p239UYEY*y63=CjLq!J-R9j}F_jzRBW<+}IORM5CYuQ!dso)-;e>ermr*-5jr0_t4SCLp{$#g919eJ4Ge|AJ9A{q1jwN72)<`6|lasb$eso>6sT02{k=$XDVSB2bW`}T%9}{+_s37}1N1w>i_-x)v*UcCE zh~^(cr$EMh@o0KTqnn2LZeUDM@(BjW$5CiNTK$L9fGPCwm)RDZvL?kSf_gntSfQuaD zF7>O$>s{SRVLk=>Z~=!*ent&98TP3Kd$#gx1e*5gadDiy%M5?3M(Mmn4~6kQOk#7SBn+(#ASw2APBh&2z$^Xt81fNLuyld#vV0)Wd@PcP1Sq za-7;H8V85lS}Vs(z$kA6UFS;kD<=e@#lu)J1$Q_AzcY$~B=S9(y9(^@N`kY^Kkp!0bgdkJLdR?)UZ>2bR!CBOP8Qj!$w^<)j-1fvsPr?v?ok~O^jBrbs zT9dAAS)_yw&25RM!ozcw&m3gy}JFkyz541U3s}-S-=e&lJ>4)@9`b zSomv0@zeN2^Mi40tZAQi@@ZzX2bB`=wdaZE%?NM^=e0Pp>`;(QK=<=_U8S3)rg_8L z3?{En=rcM7O>@#!5+|-wry@in?MX$p8?o=)|JDtAb2F;J)Yf^Y;XT0iiD`$&N`_p# zrUB0qIgK|9j-t|3;A?>feTlVNN2#L070qvaxzD~70cy{&b+?r(uEKVa#j$9Vox>qu zKx;^g-gyqrKS&T-;cq~7uR^gwn@^M$#~#jl>J_W&Wg#LGZy8!CbqRQJ()<3~(GQj( zm2JqH{5hu{gAlt_xj?4@kuR?H0ZcyJnH45?MkbO;a;s_GVFc`MKOznU5(p=wmOVL~ z!pZ?+FtC<H>Jg;>00Hw_2%EVs&g3p0`}&g{pTzHM_D)p56Z6>}gy{=F4b`1@Qs zr#8tRlJiLV?0NpYy~*ey5~Nedu7p|Ltz%YZ`5xQDO;6QWWqtWEb-n7k|IB)Qm2s7t z#7tKS%|d)JIBw*GNSh41{l zS#ym%FDw@>(_p=0G1m*grtT~5FT&aT@|L~PEyxs88pVXABh$|hON=F5h(0F;H~$Jp zgbvT7Q$q}LX~91yqQ*$z*}f22*7R_<%h05n)okPP?6SUqF8uB*-KVwL(gAgmIYMr# zGMg9bnoqrFRf<%UmyQZalH`*Ir%dIwY|L9lCNqb-Q_pdPL0$}{WYAdFkcl>W#_vn} zA6|pQ$SHJXn!h^M51#Ow-ZoYk!zVmxTrK9DGey>gw^M=+rJ-F*okWMe_5VG`vPmB8 zeINAjY=tNoPJb#q2qk0q#hyzOL%_c0{~QtKP|+>C?s~y>i%ZuE<(`;?ZpN z)V7Q>yJmXknv$Mcq7Amw@^^<^X=WKP`y?yp5E-&o?F@I}dQneBhPxtKcz2pBuQAg7 zAOku2S;+fHUIhYPD5tGrlv?t+zw`F|O*a!&kny1*=Hv+O!J)X=238k@qPeXXnFmlD zbQPVvazw>r3Ib22;Kh9nahFmL&UD;8T!_?U#*AzzkosbY^?Bc`l(hz4S(HQLAnLXH zN!l)rB2-#vpE9VgjVg-7)0|`2CASlTKRBly>r~6h=+qwL@%@PnGjILr^O8f|y$tmT zqv?yt2^pn?y1LWX19?6TnS+KRw)5_}w5Ak3upKrCsg^fsgFoaMEk1(lShsrWw~!GN z4IUQ07woqfvPYnX?Nt$#^Dza7Fs1=1OMP|%SIgl3EpsMKz4{kqz%M6)G&ZFL7vF}R zeyW7yv(jJ4gG!t(!MAM}E~!_(>P|S}G!1KCGe6+fpvZV?>CU8%v=PyMp{5Ed@TwiM ztky%-!)*NZ=1{dr00MuNSBV9SYR0F!?kgiN=3oqN1=%Ce=0zn1JvXOv+?;-%);5pb zseJ~o@qJQz5Rwj2*(vY!AxH&uw72&Ba-2$T*Wp(9T71i^(yD7>HHt(ujjGF2TM;A4 z5i?RR9_|c@L5}Pj9f{19D8p&=5@f*pgC54mSCABylMm#={#PZ8h04>o6vAiu2mRZ( zJ9QM{uB1V9;Pj4}W7bxy8Ec{Rzf4Z4)t5qS*4p{;t`3?u#4}x3Xd@9c&oSP?R`DO$ zsn(k}97X4�ggM^H)Gx)Kk~_cq#H&L;)1_Ff$(o=7{&6=i0w!MRF5+S{3(O^57rb z@0KM3Iy3CKGucQQcI|oe=fCIhxX=f6%n1DPpA>PBZ+Hdon{#?oeT>X0M71f-prT>R zx`}^`V~?po9eL3nKUC;ehY{lrqWb-|yhGlLZ3!<=0&-z}gXh4?_uH!pGLk#o$@86S znk{N3s(PlHyg$CyM=fH2&x!$23`G@Tna);v`&{?(eS4&YX_L>(94?xWtY~~e$%EQ@ z@)<|NfCdghwLH8$EVS-a` zn*R$kw=`>eGHpOXp@9%SGCom-#&e3J?J3EXEjZ|WMmWyapk4qBJ9F=|vO^N^vj*{s z^YFfV#+|O0t(hVMeUswO%-Q!HKHd6v0o9HN6~X*zO(;a!JZ>WblK{r)pzjxwiLTvuiOnc6iBG%uhQCu*$A0Mh8|arFX>FV<+y|U$ zo%Uz*#gaG|Ld!1KmfmE3FnBOgf<-nK7(a}aOhj18K1v9`{(UOqPivH=;7O-LQAoa> ze*5?9qnk{f-N1L#!}F%pqYHHwlSO^vw(P^V^M`ZmQ`QmJ{KZD=)J=&EuT1t(A4Je_ z%CZmcgoB>>zaJr@Lj&1(T>aoZUCl literal 0 HcmV?d00001 diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..9bd2883 --- /dev/null +++ b/pom.xml @@ -0,0 +1,455 @@ + + + + 4.0.0 + org.eclipse.ecsp + utils + 1.0-SNAPSHOT + + Utils + Utility library for ECSP project + https://github.com/eclipse-ecsp/utils + + + + Apache-2.0 + http://www.apache.org/licenses/LICENSE-2.0 + + + + + scm:git:https://github.com/eclipse-ecsp/utils.git + https://github.com/eclipse-ecsp/utils + HEAD + + + + + kaushalaroraharman + Kaushal Arora + kaushal.arora@harman.com + + + + + GitHub + https://github.com/eclipse-ecsp/utils/issues + + + + https://github.com/eclipse-ecsp + eclipse-ecsp + + + + UTF-8 + https://artifactory-fr.harman.com/artifactory + + 10.13.0 + 1.1.0 + 3.3.1 + ${project.basedir}/harman_checks.xml + ${project.basedir}/checkstyle-suppressions.xml + + ${project.build.directory}/checkstyle-result.xml + + 3.0.3 + + jacoco + 17 + 17 + ${project.build.directory}/site/jacoco-ut/jacoco.xml + + java + ${project.build.directory}/coverage-reports/jacoco-ut.exec + + 1.5.5 + 6.0.1 + 0.6.0 + 2.18.1 + 6.1.14 + 3.12.4 + 3.3.3 + 3.3.3 + 2.0 + + src/main/java/com/harman/ignite/utils/logger/IgniteCallerDataConverter.java, + src/main/java/com/harman/ignite/utils/logger/IgniteThrowableProxyConverter.java + + + + + + github + GitHub OWNER Apache Maven Packages + https://maven.pkg.github.com/eclipse-ecsp/utils + + + + + + github + https://maven.pkg.github.com/harman-automotive/csp-central-repo + + true + + + + + + + dash-licenses-releases + https://repo.eclipse.org/content/repositories/dash-licenses-releases/ + + false + + + + + + + org.springframework.boot + spring-boot-autoconfigure + ${spring.boot.autoconfigure} + + + org.springframework.boot + spring-boot-starter-aop + ${springboot.version} + + + org.springframework + spring-aop + + + org.springframework.boot + spring-boot-starter-logging + + + org.yaml + snakeyaml + + + + + org.yaml + snakeyaml + ${snakeyaml.version} + + + com.harman.ignite + ignite-entities + ${ignite.entities.version} + + + de.siegmar + logback-gelf + ${logback.gelf.version} + + + junit + junit + 4.13.2 + test + + + org.mockito + mockito-core + ${mockito.version} + test + + + + io.prometheus + simpleclient + ${prometheus.client.version} + + + org.springframework + spring-context + ${spring.version} + + + org.springframework + spring-core + ${spring.version} + + + org.springframework + spring-aop + ${spring.version} + + + org.springframework + spring-test + ${spring.version} + test + + + org.assertj + assertj-core + 3.6.2 + test + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 17 + 17 + + + + + org.cyclonedx + cyclonedx-maven-plugin + 2.7.10 + + application + 1.5 + true + true + true + true + true + true + true + all + ${project.basedir}/sbom + false + + + + package + + makeAggregateBom + + + + + + + + + maven-clean-plugin + 2.5 + + + + ${basedir} + + **/jar/ + + false + + + + + + org.cyclonedx + cyclonedx-maven-plugin + + + org.apache.maven.plugins + maven-shade-plugin + 2.1 + + + package + + shade + + + true + false + + + + + + + maven-surefire-plugin + ${maven.surefire.version} + + + -Xmx2G + ${surefireArgLine} + + pertest + true + + + + org.jacoco + jacoco-maven-plugin + 0.8.8 + + + + pre-unit-test + + prepare-agent + + + + ${jacoco.ut.execution.data.file} + + surefireArgLine + + + + + post-unit-test + test + + report + + + + ${jacoco.ut.execution.data.file} + + ${project.reporting.outputDirectory}/jacoco-ut + + com/harman/ignite/utils/logger/IgniteCallerDataConverter.* + com/harman/ignite/utils/logger/IgniteThrowableProxyConverter.* + + + + + + + + org.apache.maven.plugins + maven-release-plugin + 2.5.3 + + + + org.sonarsource.scanner.maven + sonar-maven-plugin + 3.10.0.2594 + + + + org.apache.maven.plugins + maven-checkstyle-plugin + ${maven.checkstyle.version} + + + validate + validate + + true + true + xml + true + true + warning + true + true + true + + + check + + + + + + com.puppycrawl.tools + checkstyle + ${checkstyle.version} + + + + + org.eclipse.dash + license-tool-plugin + ${license-tool-plugin.version} + + test + + + + license-check + + license-check + + + + + + + + + dash + + + + org.eclipse.dash + license-tool-plugin + + false + true + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + + + + diff --git a/release_notes.txt b/release_notes.txt new file mode 100644 index 0000000..581fd82 --- /dev/null +++ b/release_notes.txt @@ -0,0 +1,2 @@ +==== 1.0-SNAPSHOT ================================================================ +Open source SNAPSHOT release for utils \ No newline at end of file diff --git a/settings.xml b/settings.xml new file mode 100644 index 0000000..3183838 --- /dev/null +++ b/settings.xml @@ -0,0 +1,11 @@ + + + + github + ${env.GITHUB_ACTOR} + ${env.GITHUB_TOKEN} + + + \ No newline at end of file diff --git a/src/main/java/com/harman/ignite/diagnostic/DiagnosticConstants.java b/src/main/java/com/harman/ignite/diagnostic/DiagnosticConstants.java new file mode 100644 index 0000000..6c72293 --- /dev/null +++ b/src/main/java/com/harman/ignite/diagnostic/DiagnosticConstants.java @@ -0,0 +1,46 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.diagnostic; + +/** Constants for diagnostic module. */ +public class DiagnosticConstants { + + public static final String DIAGNOSTIC_KEYWORD = "diagnostic."; + public static final String PROPERTY_DIAGNOSTIC_REPORTER_ENABLED = "property.diagnostic.reporter.enabled"; + + private DiagnosticConstants() {} +} diff --git a/src/main/java/com/harman/ignite/diagnostic/DiagnosticData.java b/src/main/java/com/harman/ignite/diagnostic/DiagnosticData.java new file mode 100644 index 0000000..b4ce106 --- /dev/null +++ b/src/main/java/com/harman/ignite/diagnostic/DiagnosticData.java @@ -0,0 +1,44 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.diagnostic; + +import java.util.HashMap; + +/** This class is used to store the diagnostic data. */ +public class DiagnosticData extends HashMap { + +} diff --git a/src/main/java/com/harman/ignite/diagnostic/DiagnosticReporter.java b/src/main/java/com/harman/ignite/diagnostic/DiagnosticReporter.java new file mode 100644 index 0000000..0dcdc51 --- /dev/null +++ b/src/main/java/com/harman/ignite/diagnostic/DiagnosticReporter.java @@ -0,0 +1,69 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.diagnostic; + +/** + * This interface is used to report the diagnostic data. + * + * @author avadakkootko + */ +public interface DiagnosticReporter { + + public DiagnosticData getDiagnosticData(); + + /** + * This method is used to name of the DiagnosticReporter. + * + * @return name of the DiagnosticReporter + */ + public String getDiagnosticReporterName(); + + /** + * This method is used to return the name of the DiagnosticMetric. + * + * @return name of the DiagnosticMetric + */ + public String getDiagnosticMetricName(); + + /** + * This method is used to check if the DiagnosticReporter is enabled. + * + * @return is DiagnosticReporter enabled or not + */ + public boolean isDiagnosticReporterEnabled(); + +} diff --git a/src/main/java/com/harman/ignite/diagnostic/DiagnosticResult.java b/src/main/java/com/harman/ignite/diagnostic/DiagnosticResult.java new file mode 100644 index 0000000..68c2cba --- /dev/null +++ b/src/main/java/com/harman/ignite/diagnostic/DiagnosticResult.java @@ -0,0 +1,65 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.diagnostic; + +/** + * This enum is used to report the diagnostic result. + * + * @author avadakkootko + */ +public enum DiagnosticResult { + /** + * Used by diagnostic metric to report success. + */ + PASS { + @Override + public double getValue() { + return 1.0; + } + }, + /** + * Used by diagnostic metric to report an issue. + */ + FAIL { + @Override + public double getValue() { + return 0.0; + } + }; + + public abstract double getValue(); +} diff --git a/src/main/java/com/harman/ignite/diagnostic/DiagnosticService.java b/src/main/java/com/harman/ignite/diagnostic/DiagnosticService.java new file mode 100644 index 0000000..45ad1b8 --- /dev/null +++ b/src/main/java/com/harman/ignite/diagnostic/DiagnosticService.java @@ -0,0 +1,134 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.diagnostic; + +import com.harman.ignite.healthcheck.InvalidMetricNamingException; +import com.harman.ignite.healthcheck.InvalidMetricNamingException; +import com.harman.ignite.utils.logger.IgniteLogger; +import com.harman.ignite.utils.logger.IgniteLoggerFactory; +import com.harman.ignite.utils.metrics.IgniteDiagnosticGuage; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * The objective of DiagnosticService is to do reporting in Graylog, + * and publish metrics in prometheus about diagnostic data of a service. + * + * @author avadakkootko + */ +@Component +public class DiagnosticService { + private static final IgniteLogger LOGGER = IgniteLoggerFactory.getLogger(DiagnosticService.class); + + @Autowired(required = false) + private List reporters; + + @Value("${NODE_NAME:localhost}") + private String nodeName; + + @Autowired + private IgniteDiagnosticGuage serviceDiagnosticGuage; + + /** + * This method is used to trigger the diagnosis. + */ + public void triggerDiagnosis() { + List enabledDiagnosticReporters = getEnabledReporters(); + for (DiagnosticReporter reporter : enabledDiagnosticReporters) { + String metricName = reporter.getDiagnosticMetricName(); + DiagnosticData data = reporter.getDiagnosticData(); + for (Map.Entry entry : data.entrySet()) { + String key = entry.getKey(); + DiagnosticResult result = data.get(key); + serviceDiagnosticGuage.set(result.getValue(), nodeName, metricName, key); + if (result == DiagnosticResult.PASS) { + LOGGER.info("Diagnosis for metric name {} and key {} is {}", metricName, key, result); + } else { + LOGGER.warn("Diagnosis for metric name {} and key {} is {}", metricName, key, result); + } + } + } + } + + protected List getEnabledReporters() { + Map metricToReporterMapping = new HashMap<>(); + List enabledDiagnosticReporters = new ArrayList<>(); + if (reporters != null) { + for (DiagnosticReporter reporter : reporters) { + if (reporter.isDiagnosticReporterEnabled()) { + String reporterName = reporter.getDiagnosticReporterName(); + String metricName = reporter.getDiagnosticMetricName(); + // If two reporters have metrics with same name throw + // exception + if (metricToReporterMapping.containsKey(metricName)) { + LOGGER.error("Two diagnostic reporters {} and {} cannot have same MetricName :", reporterName, + metricToReporterMapping.get(metricName), metricName); + throw new InvalidMetricNamingException("Two diagnostic reporters " + + reporterName + "and " + metricToReporterMapping.get(metricName) + + "cannot have same MetricName " + metricName); + } + LOGGER.info("Diagnostic reporter {}, is enabled.", reporterName); + metricToReporterMapping.put(metricName, reporterName); + enabledDiagnosticReporters.add(reporter); + } else { + LOGGER.info("Diagnostic reporter {}, is disabled.", reporter.getDiagnosticReporterName()); + } + } + } + return enabledDiagnosticReporters; + } + + // for testing + void setReporters(List reporters) { + this.reporters = reporters; + } + + void setNodeName(String nodeName) { + this.nodeName = nodeName; + } + + void setServiceDiagnosticGuage(IgniteDiagnosticGuage serviceDiagnosticGuage) { + this.serviceDiagnosticGuage = serviceDiagnosticGuage; + } + +} diff --git a/src/main/java/com/harman/ignite/diagnostic/PropertyDiagnosticReporterImpl.java b/src/main/java/com/harman/ignite/diagnostic/PropertyDiagnosticReporterImpl.java new file mode 100644 index 0000000..c66547f --- /dev/null +++ b/src/main/java/com/harman/ignite/diagnostic/PropertyDiagnosticReporterImpl.java @@ -0,0 +1,121 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.diagnostic; + +import com.harman.ignite.utils.logger.IgniteLogger; +import com.harman.ignite.utils.logger.IgniteLoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationContext; +import org.springframework.core.env.AbstractEnvironment; +import org.springframework.core.env.EnumerablePropertySource; +import org.springframework.core.env.MutablePropertySources; +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Objects; +import java.util.stream.StreamSupport; + +/** + * Performs the validation of the values of the properties configured against the expected diagnostic value provided. + * + * @author MaKumari + */ +@Component("propertyDiagnostic") +public class PropertyDiagnosticReporterImpl implements DiagnosticReporter { + + private static IgniteLogger igniteLogger = IgniteLoggerFactory.getLogger(PropertyDiagnosticReporterImpl.class); + + private static final String DIAGNOSTIC_PROPERTY_METRIC_NAME = "DIAGNOSTIC_PROPERTY_METRIC"; + private static final String DIAGNOSTIC_PROPERTY_REPORTER_NAME = "DIAGNOSTIC_PROPERTY_REPORTER"; + + HashMap configurationMap = new HashMap<>(); + + @Autowired + ApplicationContext ctx; + @Value("${" + DiagnosticConstants.PROPERTY_DIAGNOSTIC_REPORTER_ENABLED + ": true }") + private boolean diagnosticPropertyReporterEnabled; + + @Override + public DiagnosticData getDiagnosticData() { + StringBuilder passedParms = new StringBuilder().append('\n'); + StringBuilder failedParms = new StringBuilder().append('\n'); + DiagnosticData diagnosticData = new DiagnosticData(); + MutablePropertySources propSources = ((AbstractEnvironment) ctx.getEnvironment()).getPropertySources(); + StreamSupport.stream(propSources.spliterator(), false) + + .filter(ps -> ps instanceof EnumerablePropertySource) + .map(ps -> ((EnumerablePropertySource) ps).getPropertyNames()) + .flatMap(Arrays::stream) + .filter(diagnosticPropertyName -> + diagnosticPropertyName.startsWith(DiagnosticConstants.DIAGNOSTIC_KEYWORD)) + .forEach(diagnosticPropertyName -> { + String propertyToBeValidated = diagnosticPropertyName + .substring(DiagnosticConstants.DIAGNOSTIC_KEYWORD.length()); + // Check if the property to be validated is present in the environment + if (Objects.equals(((AbstractEnvironment) ctx.getEnvironment()).getProperty(diagnosticPropertyName), + ((AbstractEnvironment) ctx.getEnvironment()) + .getProperty(propertyToBeValidated))) { + diagnosticData.put(propertyToBeValidated, DiagnosticResult.PASS); + passedParms.append(propertyToBeValidated).append('\n'); + } else { + diagnosticData.put(propertyToBeValidated, DiagnosticResult.FAIL); + failedParms.append(propertyToBeValidated).append('\n'); + } + }); + igniteLogger.debug("Properties that matches diagnostic criteria are : {}", passedParms.toString()); + igniteLogger.warn("Properties that don't matches diagnostic criteria are : {}", failedParms.toString()); + return diagnosticData; + } + + @Override + public boolean isDiagnosticReporterEnabled() { + return diagnosticPropertyReporterEnabled; + } + + @Override + public String getDiagnosticReporterName() { + return DIAGNOSTIC_PROPERTY_REPORTER_NAME; + } + + @Override + public String getDiagnosticMetricName() { + return DIAGNOSTIC_PROPERTY_METRIC_NAME; + } + +} diff --git a/src/main/java/com/harman/ignite/healthcheck/HealthMonitor.java b/src/main/java/com/harman/ignite/healthcheck/HealthMonitor.java new file mode 100644 index 0000000..f9574e3 --- /dev/null +++ b/src/main/java/com/harman/ignite/healthcheck/HealthMonitor.java @@ -0,0 +1,82 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.healthcheck; + +/** + * Contract for health monitors that intend to publish health to the HealthService. + * + * @author avadakkootko + */ +public interface HealthMonitor { + + /** + * This method is used to check if the health monitor is healthy. + * + * @param forceHealthCheck if true, then it needs to trigger a forced health check + * @return true if health monitor is healthy. If forceHealthCheck is true, trigger a forced health check. + */ + public boolean isHealthy(boolean forceHealthCheck); + + /** + * This method is used to get name of the health monitor. + * + * @return name of the health monitor + */ + public String monitorName(); + + /** + * This method is used to check if the health monitor is unhealthy and hence service should be restarted. + * + * @return true if the health monitor is unhealthy and hence service should be restarted. + */ + public boolean needsRestartOnFailure(); + + /** + * This method is used to get the name of the ignite gauge. + * + * @return name of the ignite gauge + */ + public String metricName(); + + /** + * This method is used to check if the service is enabled or not. + * + * @return if the service is enabled or not + */ + public boolean isEnabled(); + +} diff --git a/src/main/java/com/harman/ignite/healthcheck/HealthService.java b/src/main/java/com/harman/ignite/healthcheck/HealthService.java new file mode 100644 index 0000000..e9f82e6 --- /dev/null +++ b/src/main/java/com/harman/ignite/healthcheck/HealthService.java @@ -0,0 +1,340 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.healthcheck; + +import com.harman.ignite.utils.logger.IgniteLogger; +import com.harman.ignite.utils.logger.IgniteLoggerFactory; +import com.harman.ignite.utils.metrics.IgniteHealthGuage; +import jakarta.annotation.PostConstruct; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * The objective of IgniteHealthMonitor is to publish the health of stream processor to prometheus. + * This can also be used for readiness and liveliness probe. + * + * @author avadakkootko + */ +@Component +public class HealthService { + + static final String SERVICE_HEALTH = "SERVICE_HEALTH"; + static final String ISHEALTHY = " is healthy; "; + static final String ISUNHEALTHY = " is unhealthy;"; + static final double HEALTHY = 0; + static final double UNHEALTHY = 1; + private static final IgniteLogger LOGGER = IgniteLoggerFactory.getLogger(HealthService.class); + private final AtomicBoolean startedExecutor = new AtomicBoolean(false); + @Autowired(required = false) + private List healthMonitors; + @Value("${NODE_NAME:localhost}") + private String nodeName; + @Value("${health.service.failure.retry.thrshold:10}") + private int failureRetryThreshold; + @Value("${health.service.failure.retry.interval.millis:50}") + private int failureRetryInterval; + @Value("${health.service.retry.interval.millis:100}") + private int retryInterval; + @Value("${health.service.executor.shutdown.millis:2000}") + private int shutdownBuffer; + @Value("${health.service.executor.initial.delay:300000}") + private long initialDelay; + private HealthServiceCallBack callback; + // Here we are using a single guage with multiple labels for each monitor. + @Autowired + private IgniteHealthGuage serviceHealthGuage; + private ScheduledExecutorService healthServiceExecutor = null; + private final HealthServiceState previousState = new HealthServiceState(); + private final HealthServiceState currentState = new HealthServiceState(); + + /** + * It accepts two parameters boolean value force and list of health-monitor to be checked for health status. + * If force is true, it triggers a forced health check for all health monitors. + * It returns a list of failed monitors which can be retried in case of failures. + * + * @param force if true, then it needs to trigger a forced health check + * @param hms list of health monitors to be checked for health status + * @return list of failed monitors + */ + protected synchronized List checkHealthAndGetFailedMonitors(boolean force, List hms) { + List failedHealthMonitors = new ArrayList<>(); + boolean spHealthy = true; + StringBuilder status = new StringBuilder(); + for (HealthMonitor healthMonitor : hms) { + String monitorName = healthMonitor.monitorName(); + String metricName = healthMonitor.metricName(); + if (healthMonitor.isHealthy(force)) { + status.append(healthMonitor.monitorName()).append(ISHEALTHY); + serviceHealthGuage.set(HEALTHY, nodeName, metricName); + } else { + status.append(monitorName).append(ISUNHEALTHY); + serviceHealthGuage.set(UNHEALTHY, nodeName, metricName); + failedHealthMonitors.add(healthMonitor); + spHealthy = false; + } + } + + String statusMsg = status.toString(); + double state = 0; + if (spHealthy) { + state = HEALTHY; + serviceHealthGuage.set(HEALTHY, nodeName, SERVICE_HEALTH); + } else { + state = UNHEALTHY; + serviceHealthGuage.set(UNHEALTHY, nodeName, SERVICE_HEALTH); + } + currentState.setState(state); + currentState.setMessage(statusMsg); + if (!currentState.equals(previousState)) { + printStatus(spHealthy, statusMsg); + previousState.setState(currentState.getState()); + previousState.setMessage(currentState.getMessage()); + } + return failedHealthMonitors; + } + + private void printStatus(boolean spHealthy, String statusMsg) { + if (spHealthy) { + LOGGER.info("Health status :: healthy; desc: {}", statusMsg); + } else { + LOGGER.error("Health status :: unhealthy; desc: {}", statusMsg); + } + } + + /** + * This method can be used:
+ * For the initial forced health check by Stream base Launcher or API without starting the scheduled executor.
+ * Why this approach?
+ * Because there may be certain monitors which is bound to return unhealthy unless the process starts.
+ * For example:
+ * Kafka state listener health monitor will return unhealthy unless stream processor starts. + * Hence, this may have to be ignored for the initial health check.
+ * Another approach is to come up with a new contract that says:
+ * initialCheckDisabled
+ * This can be achieved in the next step. + * + * @return list of failed health monitors + */ + public List triggerInitialCheck() { + List failedHealthMonitors; + boolean force = true; + failedHealthMonitors = checkHealthAndGetFailedMonitors(force, healthMonitors); + int failedMonitorsSize = failedHealthMonitors.size(); + if (failedMonitorsSize > 0) { + LOGGER.error("Initial health check failed with {} health monitors", failedMonitorsSize); + } else { + LOGGER.info("Initial health check has passed"); + } + return failedHealthMonitors; + } + + /** + * Invoked by the scheduled executor. It wraps the retry strategy in case of failure scenario. + * + * @return true if service needs to be restarted + * @throws InterruptedException if the thread is interrupted + */ + protected boolean needsRestart() throws InterruptedException { + // For the first health check default states of variable unHealthy will + // be true and force will be force. + startedExecutor.set(true); + boolean restart = true; + boolean force = false; + List hms = new ArrayList<>(healthMonitors); + int counter = 0; + do { + List failedHms = checkHealthAndGetFailedMonitors(force, hms); + hms.clear(); + for (HealthMonitor hm : failedHms) { + if (hm.needsRestartOnFailure()) { + hms.add(hm); + } + } + if (!hms.isEmpty()) { + restart = true; + force = true; + } else { + restart = false; + force = false; + } + counter++; + Thread.sleep(failureRetryInterval); + } while (counter <= (failureRetryThreshold) && restart); + return restart; + } + + /** + * Create a list of health monitors that are enabled and if two monitors have same name throw exception. + */ + @PostConstruct + public void init() { + Map metricToMonitorMapping = new HashMap<>(); + List enabledHealthMonitors = new ArrayList<>(); + if (healthMonitors != null) { + for (HealthMonitor healthMonitor : healthMonitors) { + if (healthMonitor.isEnabled()) { + String metricName = healthMonitor.metricName(); + String monitorName = healthMonitor.monitorName(); + // If two monitors have metrics with same name throw + // exception + if (metricToMonitorMapping.containsKey(metricName)) { + LOGGER.error("Two health monitors {} and {} cannot have same MetricName :", monitorName, + metricToMonitorMapping.get(metricName), metricName); + throw new InvalidMetricNamingException( + "Two health monitors " + monitorName + "and " + metricToMonitorMapping.get(metricName) + + "cannot have same MetricName " + metricName); + } + LOGGER.info("Health monitor {}, is enabled.", healthMonitor.monitorName()); + metricToMonitorMapping.put(metricName, healthMonitor.monitorName()); + enabledHealthMonitors.add(healthMonitor); + } else { + LOGGER.info("Health monitor {}, is disabled.", healthMonitor.monitorName()); + } + } + } + healthMonitors = new ArrayList<>(enabledHealthMonitors); + createhHealthServiceExecutor(); + } + + private void createhHealthServiceExecutor() { + healthServiceExecutor = Executors.newSingleThreadScheduledExecutor(runnable -> { + Thread t = Executors.defaultThreadFactory().newThread(runnable); + t.setDaemon(true); + t.setUncaughtExceptionHandler(new HealthServiceUncaughtExceptionHandler()); + t.setName(Thread.currentThread().getName() + ":" + "HealthService"); + return t; + }); + } + + /** + * Start the scheduled executor which will periodically check health of HealthMonitors. + */ + public synchronized void startHealthServiceExecutor() { + if (!startedExecutor.get()) { + healthServiceExecutor.scheduleWithFixedDelay(() -> { + try { + checkCallback(callback); + } catch (InterruptedException e) { + LOGGER.error("Error occurred while executing health service scheduled thread {}", e); + Thread.currentThread().interrupt(); + } catch (Exception e) { + LOGGER.error("Error occurred while executing health service scheduled thread {}", e); + } + + }, initialDelay, retryInterval, TimeUnit.MILLISECONDS); + } + } + + private void checkCallback(HealthServiceCallBack callback) throws InterruptedException { + boolean restart = needsRestart(); + if (restart) { + if (callback != null && callback.performRestart()) { + close(); + } else { + LOGGER.trace("Service is unhealthy. Continuing health check without restart"); + } + } + } + + private class HealthServiceUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler { + @Override + public void uncaughtException(Thread thread, Throwable t) { + LOGGER.error("Uncaught exception in thread {} ", thread.getName(), t); + } + } + + protected void close() { + if (healthServiceExecutor != null && !healthServiceExecutor.isShutdown()) { + LOGGER.info("Shutting the SingleThreadScheduledExecutor for health service!"); + ThreadUtils.shutdownExecutor(healthServiceExecutor, shutdownBuffer, false); + startedExecutor.set(false); + } + } + + public void registerCallBack(HealthServiceCallBack callback) { + this.callback = callback; + LOGGER.info("Registered HealthService callback"); + } + + boolean isStartedExecutor() { + return startedExecutor.get(); + } + + List getHealthMonitors() { + return this.healthMonitors; + } + + // Below are for test case support + void setHealthMonitors(List healthMonitors) { + this.healthMonitors = healthMonitors; + } + + void setNodeName(String nodeName) { + this.nodeName = nodeName; + } + + void setFailureRetryThreshold(int failureRetryThreshold) { + this.failureRetryThreshold = failureRetryThreshold; + } + + void setFailureRetryInterval(int failureRetryInterval) { + this.failureRetryInterval = failureRetryInterval; + } + + void setRetryInterval(int retryInterval) { + this.retryInterval = retryInterval; + } + + void setServiceHealthGuage(IgniteHealthGuage serviceHealthGuage) { + this.serviceHealthGuage = serviceHealthGuage; + } + + HealthServiceCallBack getCallback() { + return this.callback; + } + +} diff --git a/src/main/java/com/harman/ignite/healthcheck/HealthServiceCallBack.java b/src/main/java/com/harman/ignite/healthcheck/HealthServiceCallBack.java new file mode 100644 index 0000000..2ebe9ce --- /dev/null +++ b/src/main/java/com/harman/ignite/healthcheck/HealthServiceCallBack.java @@ -0,0 +1,53 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.healthcheck; + +/** + * Enables the application implementing health service to take appropriate action on critical health monitor failure. + * + * @author avadakkootko + */ +public interface HealthServiceCallBack { + + /** + * This method is used to perform a restart of the service. + * + * @return true if a restart is required, else false + */ + public boolean performRestart(); + +} diff --git a/src/main/java/com/harman/ignite/healthcheck/HealthServiceState.java b/src/main/java/com/harman/ignite/healthcheck/HealthServiceState.java new file mode 100644 index 0000000..61ee026 --- /dev/null +++ b/src/main/java/com/harman/ignite/healthcheck/HealthServiceState.java @@ -0,0 +1,102 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.healthcheck; + +/** + * This class is used to store the health service state. + */ +public class HealthServiceState { + + private static final int BITS = 32; + + private double state; + private String message; + + public double getState() { + return state; + } + + public void setState(double state) { + this.state = state; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public HealthServiceState() { + //default constructor + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((message != null) ? message.hashCode() : 0); + long temp; + temp = Double.doubleToLongBits(state); + result = prime * result + (int) (temp ^ (temp >>> BITS)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + HealthServiceState other = (HealthServiceState) obj; + if (message == null) { + if (other.message != null) { + return false; + } + } else if (!message.equals(other.message)) { + return false; + } + return (Double.doubleToLongBits(state) == Double.doubleToLongBits(other.state)); + } + +} diff --git a/src/main/java/com/harman/ignite/healthcheck/InvalidMetricNamingException.java b/src/main/java/com/harman/ignite/healthcheck/InvalidMetricNamingException.java new file mode 100644 index 0000000..f02e08b --- /dev/null +++ b/src/main/java/com/harman/ignite/healthcheck/InvalidMetricNamingException.java @@ -0,0 +1,12 @@ +package com.harman.ignite.healthcheck; + +/** + * Custom exception for duplicate metric name. + */ +public class InvalidMetricNamingException extends RuntimeException { + private static final long serialVersionUID = 1L; + + public InvalidMetricNamingException(String s) { + super(s); + } +} diff --git a/src/main/java/com/harman/ignite/healthcheck/ThreadUtils.java b/src/main/java/com/harman/ignite/healthcheck/ThreadUtils.java new file mode 100644 index 0000000..bd710e0 --- /dev/null +++ b/src/main/java/com/harman/ignite/healthcheck/ThreadUtils.java @@ -0,0 +1,106 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.healthcheck; + +import com.harman.ignite.utils.logger.IgniteLogger; +import com.harman.ignite.utils.logger.IgniteLoggerFactory; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; + +/** + * Utility class for thread related operations. + */ +public abstract class ThreadUtils { + + private static final IgniteLogger LOGGER = IgniteLoggerFactory.getLogger(ThreadUtils.class); + + private ThreadUtils() { + } + + /** + * Shuts down an executor reliably. Optionally allows shutting down the JVM if executor doesn't shutdown + * + * @param exec Executor service to shut down + * @param waitTimeMs Time to wait for executor to shut down + * @param exitOnFailure Exit the JVM if executor doesn't shut down + */ + public static void shutdownExecutor(ExecutorService exec, int waitTimeMs, boolean exitOnFailure) { + if (exec != null && !exec.isShutdown()) { + LOGGER.info("Shutting down executor service"); + exec.shutdown(); // Disable new tasks from being submitted + try { + // Wait a while for existing tasks to terminate + if (!exec.awaitTermination(waitTimeMs, TimeUnit.MILLISECONDS)) { + LOGGER.info("Shutting down executor service forcefully," + + " as it has not responded to graceful shutdown"); + exec.shutdownNow(); // Cancel currently executing tasks + // Wait a while for tasks to respond to being cancelled + execWithAwaitTermination(exec, waitTimeMs, exitOnFailure); + } + } catch (InterruptedException ie) { + // (Re-)Cancel if current thread also interrupted + exec.shutdownNow(); + try { + execWithAwaitTermination(exec, waitTimeMs, exitOnFailure); + } catch (InterruptedException e) { + logErrorAndExit(exitOnFailure); + Thread.currentThread().interrupt(); + } + } + } + } + + private static void execWithAwaitTermination(ExecutorService exec, int waitTimeMs, boolean exitOnFailure) + throws InterruptedException { + if (!exec.awaitTermination(waitTimeMs, TimeUnit.MILLISECONDS)) { + LOGGER.error("Executor service not closed after waiting {} ms", waitTimeMs); + if (exitOnFailure) { + LOGGER.error("Executor service not closed after waiting {} ms . Exiting application", waitTimeMs); + System.exit(1); + } + } + } + + private static void logErrorAndExit(boolean exitOnFailure) { + LOGGER.error("Interrupted when waiting on executor"); + if (exitOnFailure) { + LOGGER.error("Executor service shutdown failed. Interrupted. Exiting application"); + System.exit(1); + } + } +} diff --git a/src/main/java/com/harman/ignite/utils/filter/DuplicateExceptionFilter.java b/src/main/java/com/harman/ignite/utils/filter/DuplicateExceptionFilter.java new file mode 100644 index 0000000..2f3e2de --- /dev/null +++ b/src/main/java/com/harman/ignite/utils/filter/DuplicateExceptionFilter.java @@ -0,0 +1,166 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.filter; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.turbo.TurboFilter; +import ch.qos.logback.core.spi.FilterReply; +import com.harman.ignite.utils.logger.LoggerUtils; +import org.slf4j.Marker; + +import java.util.concurrent.ConcurrentHashMap; + +/** + * This class will suppress repeating exception for a configurable amount of time in millis (typically for minutes). + * It will help non-pollute the log files and reduce disk pressure.
+ * The implementation is based on TurboFilter (logback). + * + * @author vkoul + */ +public class DuplicateExceptionFilter extends TurboFilter { + + private static ConcurrentHashMap exceptionCache = null; + + static { + exceptionCache = new ConcurrentHashMap<>(); + } + + // provide suppress time in milliseconds + private long suppressTimeInMs = 10L * 60 * 1000; + + @Override + public void start() { + super.start(); + } + + /** + * This method is invoked in deciding if log statement would be logged or not. + * The filter is configured in logback.xml, where we are providing "suppressTimeInMs" like below: + *

+ * <turboFilter class="com.harman.ignite.utils.filter.DuplicateExceptionFilter">
+ *   <suppressTimeInMs>60000</suppressTimeInMs>
+ * </turboFilter>> + * + */ + @Override + public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) { + + FilterReply reply = FilterReply.NEUTRAL; + + // Throwable is coming from last argument of decide() + if (null != t) { + reply = decide(logger, t); + } else if (LoggerUtils.hasThrowableObject(format, params)) { // Check if we get Throwable from var-args. + reply = decide(logger, (Throwable) params[params.length - 1]); + } + + return reply; + } + + /** + * Internally, this method maintains ConcurrentHashMap which keeps:
+ * Throwable as key and values at which point-in-time it was logged in. + * Based on setSuppressTimeInMs value multiple logs would be filtered out, + * that is at most one log statement would be logged-in within setSuppressTimeInMs time. + * + * @param logger Logger from which log statement is being invoked. + * @param t Throwable object. + * @return decision if a log statement would be logged-in or not. + */ + + private FilterReply decide(Logger logger, Throwable t) { + FilterReply reply; + long currTime = System.currentTimeMillis(); + + // The exceptionKey need to have both: + // 1) Exception-Name and 2) Logger from which it came from. + // + // Else, we may have a scenario in which if we have entry for an + // exception in cache, + // even though we may be logging it for first time, it would get + // discarded. + + StringBuilder exceptionKey = new StringBuilder().append(t.getClass().getName()).append(logger.toString()); + + if (!exceptionCache.containsKey(exceptionKey.toString())) { + exceptionCache.put(exceptionKey.toString(), currTime); + + // We are returning NEUTRAL to propagate + // it thru next filter chains. + reply = FilterReply.NEUTRAL; + } else { + // It means we have entry inside our map, hence we need to check last time when exception came in. + // We need to keep a gap of 10 minutes (configurable) + // so that we can allow it to pass through, else DENY. + long previousTime = exceptionCache.get(exceptionKey.toString()); + + // We are returning NEUTRAL to propagate + // it through next filter chains. + if ((currTime - previousTime) >= suppressTimeInMs) { + // Update the time-stamp in cache + exceptionCache.put(exceptionKey.toString(), currTime); + reply = FilterReply.NEUTRAL; + } else { + reply = FilterReply.DENY; + } + } + + return reply; + + } + + public long getSuppressTimeInMs() { + return suppressTimeInMs; + } + + /** + * The value of suppressTimeInMs will be taken from logback.xml. Refer below for an example: + * <turboFilter class="com.harman.ignite.utils.filter.DuplicateExceptionFilter">
+ *   <suppressTimeInMs>60000</suppressTimeInMs>
+ * </turboFilter> + * + * @param suppressTimeInMs - time in milliseconds. + */ + public void setSuppressTimeInMs(long suppressTimeInMs) { + this.suppressTimeInMs = suppressTimeInMs; + } + + static void setExceptionCache(ConcurrentHashMap exceptionCache) { + DuplicateExceptionFilter.exceptionCache = exceptionCache; + } +} diff --git a/src/main/java/com/harman/ignite/utils/logger/IgniteCallerDataConverter.java b/src/main/java/com/harman/ignite/utils/logger/IgniteCallerDataConverter.java new file mode 100644 index 0000000..28ce84e --- /dev/null +++ b/src/main/java/com/harman/ignite/utils/logger/IgniteCallerDataConverter.java @@ -0,0 +1,133 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.logger; + +import ch.qos.logback.classic.pattern.CallerDataConverter; +import ch.qos.logback.classic.spi.CallerData; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.boolex.EvaluationException; +import ch.qos.logback.core.boolex.EventEvaluator; +import ch.qos.logback.core.status.ErrorStatus; + +import java.util.List; + +/** + * This is used to customize log messages. + * This class overrides methods from CallerDataConverter and customize log messages.
+ * Customizations include:
+ * 1. removing of "caller" from log message.
+ * 2. Printing short-form of fully qualified package
+ * name(eg:com.harman.ignite.utils.logger.IgniteCallerDataConverter + * will be replaced as c.h.i.u.l.IgniteCallerDataConverter) + * + * @author vishnu.k; + */ +public class IgniteCallerDataConverter extends CallerDataConverter { + + private int depthStart = 1; + static final int MAX_ERR_COUNT = 4; + private int errCount = 0; + List> eventEvaluatorList = null; + + @Override + public String convert(ILoggingEvent logEvent) { + if (eventEvaluatorList != null) { + boolean printCallerData = false; + + for (int i = 0; i < eventEvaluatorList.size(); i++) { + EventEvaluator eventEvaluator = eventEvaluatorList.get(i); + if (canEvaluatorProcessLogEvent(logEvent, eventEvaluator)) { + printCallerData = true; + break; + } + } + + // no evaluator can process the logging event + if (!printCallerData) { + return CoreConstants.EMPTY_STRING; + } + } + + return convertToCallerData(logEvent); + } + + private String convertToCallerData(ILoggingEvent le) { + StringBuilder buf = new StringBuilder(); + StackTraceElement[] cda = le.getCallerData(); + if (cda != null && cda.length > depthStart) { + buf.append(getCallerLinePrefix()); + buf.append(cda[depthStart]); + buf.append(" "); + + return buf.toString(); + } else { + return CallerData.CALLER_DATA_NA; + } + } + + @Override + protected String getCallerLinePrefix() { + return ""; + } + + private boolean canEvaluatorProcessLogEvent(ILoggingEvent logEvent, EventEvaluator eventEvaluator) { + try { + if (eventEvaluator.evaluate(logEvent)) { + return true; + } + } catch (EvaluationException eex) { + errCount++; + processErrorCount(eventEvaluator, eex); + } + return false; + } + + private void processErrorCount(EventEvaluator ee, EvaluationException eex) { + if (errCount < MAX_ERR_COUNT) { + addError("Exception thrown for evaluator named [" + ee.getName() + "]", eex); + } else if (errCount == MAX_ERR_COUNT) { + ErrorStatus errorStatus = new ErrorStatus( + "Exception thrown for evaluator named [" + ee.getName() + "].", + this, eex); + errorStatus.add(new ErrorStatus("This was the last warning about this evaluator's errors." + + "We don't want the StatusManager to get flooded.", this)); + addStatus(errorStatus); + } + } + +} diff --git a/src/main/java/com/harman/ignite/utils/logger/IgniteLogger.java b/src/main/java/com/harman/ignite/utils/logger/IgniteLogger.java new file mode 100644 index 0000000..0c026b0 --- /dev/null +++ b/src/main/java/com/harman/ignite/utils/logger/IgniteLogger.java @@ -0,0 +1,147 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.logger; + +import com.harman.ignite.entities.IgniteEvent; + +/** + * MDC (Mapped Diagnostic Context) will help produce customized logs for Ignite + * product. It will bring together the core parameters like the TimeStamp, + * RequestId, MessageId, BizTransactionId and CorrelationId as a wrapper for all + * the events being logged. + * + * @author AKumar + * + */ +public interface IgniteLogger { + + /** + * Method to know if Trace level log is enable or not. + * + * @return - true - if trace level enabled, false - otherwise. + */ + public boolean isTraceEnabled(); + + /** + * Method to know if Debug level log is enable or not. + * + * @return - true - if Debug level enabled, false - otherwise. + */ + public boolean isDebugEnabled(); + + /** + * Method to know if Info level log is enable or not. + * + * @return - true - if Info level enabled, false - otherwise. + */ + public boolean isInfoEnabled(); + + /** + * Method to know if Warn level log is enable or not. + * + * @return - true - if Warn level enabled, false - otherwise. + */ + public boolean isWarnEnabled(); + + /** + * Method to know if Error level log is enable or not. + * + * @return - true - if Error level enabled, false - otherwise. + */ + public boolean isErrorEnabled(); + + public void trace(IgniteEvent event, String msg); + + public void trace(IgniteEvent event, String format, Object... arguments); + + public void trace(IgniteEvent event, String msg, Throwable t); + + public void trace(String msg); + + public void trace(String format, Object... arguments); + + public void trace(String msg, Throwable t); + + public void debug(IgniteEvent event, String msg); + + public void debug(IgniteEvent event, String format, Object... arguments); + + public void debug(IgniteEvent event, String msg, Throwable t); + + public void debug(String msg); + + public void debug(String format, Object... arguments); + + public void debug(String msg, Throwable t); + + public void info(IgniteEvent event, String msg); + + public void info(IgniteEvent event, String format, Object... arguments); + + public void info(IgniteEvent event, String msg, Throwable t); + + public void info(String msg); + + public void info(String format, Object... arguments); + + public void info(String msg, Throwable t); + + public void warn(IgniteEvent event, String msg); + + public void warn(IgniteEvent event, String format, Object... arguments); + + public void warn(IgniteEvent event, String msg, Throwable t); + + public void warn(String msg); + + public void warn(String format, Object... arguments); + + public void warn(String msg, Throwable t); + + public void error(IgniteEvent event, String msg); + + public void error(IgniteEvent event, String format, Object... arguments); + + public void error(IgniteEvent event, String msg, Throwable t); + + public void error(String msg); + + public void error(String format, Object... arguments); + + public void error(String msg, Throwable t); + +} \ No newline at end of file diff --git a/src/main/java/com/harman/ignite/utils/logger/IgniteLoggerFactory.java b/src/main/java/com/harman/ignite/utils/logger/IgniteLoggerFactory.java new file mode 100644 index 0000000..d0c8ed1 --- /dev/null +++ b/src/main/java/com/harman/ignite/utils/logger/IgniteLoggerFactory.java @@ -0,0 +1,52 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.logger; + +/** + * Factory class which gives a logger instance for the requested type. + * + * @author AKumar + */ +public class IgniteLoggerFactory { + + private IgniteLoggerFactory() { + } + + public static IgniteLogger getLogger(Class clazz) { + return IgniteLoggerImpl.getIgniteLoggerInstance(clazz); + } +} diff --git a/src/main/java/com/harman/ignite/utils/logger/IgniteLoggerImpl.java b/src/main/java/com/harman/ignite/utils/logger/IgniteLoggerImpl.java new file mode 100644 index 0000000..0ebcba8 --- /dev/null +++ b/src/main/java/com/harman/ignite/utils/logger/IgniteLoggerImpl.java @@ -0,0 +1,337 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.logger; + +import ch.qos.logback.classic.PatternLayout; +import com.harman.ignite.entities.IgniteEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Implementation class for IgniteLogger interface. + * This class is used to customize log messages. + * + * @author AKumar + * + */ +public class IgniteLoggerImpl implements IgniteLogger { + + private Logger logger; + private static final String MESSAGE = "message"; + private static Map igniteLoggersMap = new ConcurrentHashMap<>(); + + private IgniteLoggerImpl(Class clazz) { + PatternLayout.defaultConverterMap + .put("caller", com.harman.ignite.utils.logger.IgniteCallerDataConverter.class.getName()); + PatternLayout.defaultConverterMap + .put("ex", com.harman.ignite.utils.logger.IgniteThrowableProxyConverter.class.getName()); + PatternLayout.defaultConverterMap + .put("exception", com.harman.ignite.utils.logger.IgniteThrowableProxyConverter.class.getName()); + PatternLayout.defaultConverterMap + .put("throwable", com.harman.ignite.utils.logger.IgniteThrowableProxyConverter.class.getName()); + logger = LoggerFactory.getLogger(clazz); + } + + public void setLogger(Logger logger) { + this.logger = logger; + } + + protected static IgniteLogger getIgniteLoggerInstance(Class clazz) { + igniteLoggersMap.putIfAbsent(clazz.getName(), new IgniteLoggerImpl(clazz)); + return (IgniteLogger) igniteLoggersMap.get(clazz.getName()); + } + + /* + * Added for JUnit test purpose only. + */ + static IgniteLoggerImpl getIgniteLoggerImplInstance(Class clazz) { + igniteLoggersMap.putIfAbsent(clazz.getName(), new IgniteLoggerImpl(clazz)); + return igniteLoggersMap.get(clazz.getName()); + } + + @Override + public boolean isTraceEnabled() { + return logger.isTraceEnabled(); + } + + @Override + public boolean isDebugEnabled() { + return logger.isDebugEnabled(); + } + + @Override + public boolean isInfoEnabled() { + return logger.isInfoEnabled(); + } + + @Override + public boolean isWarnEnabled() { + return logger.isWarnEnabled(); + } + + @Override + public boolean isErrorEnabled() { + return logger.isErrorEnabled(); + } + + @Override + public void trace(IgniteEvent event, String msg) { + if (logger.isTraceEnabled()) { + logger.trace(getMessageWithHeader(event, msg)); + } + } + + @Override + public void trace(IgniteEvent event, String format, Object... arguments) { + if (isTraceEnabled()) { + logger.trace(getMessageWithHeader(event, format), arguments); + } + } + + @Override + public void trace(IgniteEvent event, String msg, Throwable t) { + if (isTraceEnabled()) { + logger.trace(getMessageWithHeader(event, msg), t); + } + } + + @Override + public void trace(String msg) { + if (isTraceEnabled()) { + logger.trace(msg); + } + } + + @Override + public void trace(String format, Object... arguments) { + if (logger.isTraceEnabled()) { + logger.trace(format, arguments); + } + } + + @Override + public void trace(String msg, Throwable t) { + if (logger.isTraceEnabled()) { + logger.trace(msg, t); + } + } + + @Override + public void debug(IgniteEvent event, String msg) { + if (logger.isDebugEnabled()) { + logger.debug(getMessageWithHeader(event, msg)); + } + } + + @Override + public void debug(IgniteEvent event, String format, Object... arguments) { + if (logger.isDebugEnabled()) { + logger.debug(getMessageWithHeader(event, format), arguments); + } + } + + @Override + public void debug(IgniteEvent event, String msg, Throwable t) { + if (logger.isDebugEnabled()) { + logger.debug(getMessageWithHeader(event, msg), t); + } + } + + @Override + public void debug(String msg) { + if (logger.isDebugEnabled()) { + logger.debug(msg); + } + } + + @Override + public void debug(String format, Object... arguments) { + if (logger.isDebugEnabled()) { + logger.debug(format, arguments); + } + } + + @Override + public void debug(String msg, Throwable t) { + if (logger.isDebugEnabled()) { + logger.debug(msg, t); + } + } + + @Override + public void info(IgniteEvent event, String msg) { + if (logger.isInfoEnabled()) { + logger.info(getMessageWithHeader(event, msg)); + } + } + + @Override + public void info(IgniteEvent event, String format, Object... arguments) { + if (logger.isInfoEnabled()) { + logger.info(getMessageWithHeader(event, format), arguments); + } + } + + @Override + public void info(IgniteEvent event, String msg, Throwable t) { + if (logger.isInfoEnabled()) { + logger.info(getMessageWithHeader(event, msg), t); + } + } + + @Override + public void info(String msg) { + if (logger.isInfoEnabled()) { + logger.info(msg); + } + } + + @Override + public void info(String format, Object... arguments) { + if (logger.isInfoEnabled()) { + logger.info(format, arguments); + } + } + + @Override + public void info(String msg, Throwable t) { + if (isInfoEnabled()) { + logger.info(msg, t); + } + } + + @Override + public void warn(IgniteEvent event, String msg) { + logger.warn(getMessageWithHeader(event, msg)); + } + + @Override + public void warn(IgniteEvent event, String format, Object... arguments) { + logger.warn(getMessageWithHeader(event, format), arguments); + } + + @Override + public void warn(IgniteEvent event, String msg, Throwable t) { + logger.warn(getMessageWithHeader(event, msg), t); + } + + @Override + public void warn(String msg) { + logger.warn(msg); + } + + @Override + public void warn(String format, Object... arguments) { + logger.warn(format, arguments); + } + + @Override + public void warn(String msg, Throwable t) { + logger.warn(msg, t); + } + + @Override + public void error(IgniteEvent event, String msg) { + logger.error(getMessageWithHeader(event, msg)); + } + + @Override + public void error(IgniteEvent event, String format, Object... arguments) { + logger.error(getMessageWithHeader(event, format), arguments); + } + + @Override + public void error(IgniteEvent event, String msg, Throwable t) { + logger.error(getMessageWithHeader(event, msg), t); + } + + @Override + public void error(String msg) { + logger.error(msg); + } + + @Override + public void error(String format, Object... arguments) { + logger.error(format, arguments); + } + + @Override + public void error(String msg, Throwable t) { + logger.error(msg, t); + } + + private String getMessageWithHeader(IgniteEvent event, String format) { + StringBuilder formatBuilder = new StringBuilder(); + long timeStamp = event.getTimestamp(); + formatBuilder.append("Timestamp:").append(timeStamp); + + String requestId = event.getRequestId(); + formatBuilder.append(" , RequestId:").append(requestId); + + String messageId = event.getMessageId(); + formatBuilder.append(" , MessageId:").append(messageId); + + String bizTransactionId = event.getBizTransactionId(); + formatBuilder.append(" , BizTransactionId:").append(bizTransactionId); + + formatBuilder.append(" , VehicleID:").append(event.getVehicleId()); + + formatBuilder.append(" , EventID:").append(event.getEventId()); + + formatBuilder.append(" , Version:").append(event.getSchemaVersion()); + + formatBuilder.append(" , SourceDeviceID:").append(event.getSourceDeviceId()); + + Optional correlateionId = Optional.ofNullable(event.getCorrelationId()); + if (correlateionId.isPresent()) { + formatBuilder.append(" , CorrelationId:").append(correlateionId); + } + formatBuilder.append(" ," + MESSAGE + ":").append(format); + return formatBuilder.toString(); + } + + /* + * Added for JUnit test purpose only. + */ + Map getIgniteLoggersMap() { + return igniteLoggersMap; + } +} diff --git a/src/main/java/com/harman/ignite/utils/logger/IgniteThrowableProxyConverter.java b/src/main/java/com/harman/ignite/utils/logger/IgniteThrowableProxyConverter.java new file mode 100644 index 0000000..93cb53c --- /dev/null +++ b/src/main/java/com/harman/ignite/utils/logger/IgniteThrowableProxyConverter.java @@ -0,0 +1,298 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.logger; + +import ch.qos.logback.classic.pattern.ThrowableHandlingConverter; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.IThrowableProxy; +import ch.qos.logback.classic.spi.StackTraceElementProxy; +import ch.qos.logback.classic.spi.ThrowableProxyUtil; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.boolex.EvaluationException; +import ch.qos.logback.core.boolex.EventEvaluator; +import ch.qos.logback.core.status.ErrorStatus; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Add a stack trace in case the event contains a Throwable. This is used to customize error message.
+ * Customizations include:
+ * 1. removing of "at" from stack trace.
+ * 2. printing full stack-trace in single line separated by comma(,)
+ * + * @author vishnu.k + */ +public class IgniteThrowableProxyConverter extends ThrowableHandlingConverter { + + protected static final int BUILDER_CAPACITY = 2048; + + int lengthOption; + List> evaluatorList = null; + List ignoredStackTraceLines = null; + + int errorCount = 0; + + + /** + * This method is used to start the converter. + */ + @SuppressWarnings("unchecked") + @Override + public void start() { + + String lengthStr = getFirstOption(); + createLengthOption(lengthStr); + + final List optionList = getOptionList(); + if (optionList != null && optionList.size() > 1) { + final int optionListSize = optionList.size(); + for (int i = 1; i < optionListSize; i++) { + String evaluatorOrIgnoredStackTraceLine = (String) optionList.get(i); + Context context = getContext(); + Map> evaluatorMap = (Map>) context + .getObject(CoreConstants.EVALUATOR_MAP); + EventEvaluator ee = (EventEvaluator) evaluatorMap + .get(evaluatorOrIgnoredStackTraceLine); + if (ee != null) { + addEvaluator(ee); + } else { + addIgnoreStackTraceLine(evaluatorOrIgnoredStackTraceLine); + } + } + } + super.start(); + } + + + private void createLengthOption(String lengthStr) { + if (lengthStr == null) { + lengthOption = Integer.MAX_VALUE; + } else { + lengthStr = lengthStr.toLowerCase(); + if ("full".equals(lengthStr)) { + lengthOption = Integer.MAX_VALUE; + } else if ("short".equals(lengthStr)) { + lengthOption = 1; + } else { + try { + lengthOption = Integer.parseInt(lengthStr); + } catch (NumberFormatException nfe) { + addError("Could not parse [" + lengthStr + "] as an integer"); + lengthOption = Integer.MAX_VALUE; + } + } + } + } + + private void addEvaluator(EventEvaluator ee) { + if (evaluatorList == null) { + evaluatorList = new ArrayList<>(); + } + evaluatorList.add(ee); + } + + private void addIgnoreStackTraceLine(String ignoredStackTraceLine) { + if (ignoredStackTraceLines == null) { + ignoredStackTraceLines = new ArrayList<>(); + } + ignoredStackTraceLines.add(ignoredStackTraceLine); + } + + @Override + public void stop() { + evaluatorList = null; + super.stop(); + } + + protected void extraData(StringBuilder builder, StackTraceElementProxy step) { + // nop + } + + /** + * Convert the event to a string. + * + * @param event the log event + * @return the string representation of the event + */ + public String convert(ILoggingEvent event) { + + IThrowableProxy tp = event.getThrowableProxy(); + if (tp == null) { + return CoreConstants.EMPTY_STRING; + } + // an evaluator match will cause stack printing to be skipped + if (evaluatorList != null) { + boolean printStack = true; + for (EventEvaluator ee : evaluatorList) { + try { + if (ee.evaluate(event)) { + printStack = false; + break; + } + } catch (EvaluationException eex) { + errorCount++; + processErrorCount(ee, eex); + } + } + + if (!printStack) { + return CoreConstants.EMPTY_STRING; + } + } + + return throwableProxyToString(tp); + } + + protected String throwableProxyToString(IThrowableProxy tp) { + StringBuilder sb = new StringBuilder(BUILDER_CAPACITY); + + recursiveAppend(sb, null, ThrowableProxyUtil.REGULAR_EXCEPTION_INDENT, tp); + return sb.toString().replace("\t", ", "); + } + + private void recursiveAppend(StringBuilder sb, String prefix, int indent, IThrowableProxy tp) { + if (tp == null) { + return; + } + subjoinFirstLine(sb, prefix, indent, tp); + subjoinStepArray(sb, indent, tp); + IThrowableProxy[] suppressed = tp.getSuppressed(); + if (suppressed != null) { + for (IThrowableProxy current : suppressed) { + recursiveAppend(sb, + CoreConstants.SUPPRESSED, + indent + ThrowableProxyUtil.SUPPRESSED_EXCEPTION_INDENT, + current); + } + } + recursiveAppend(sb, CoreConstants.CAUSED_BY, indent, tp.getCause()); + } + + private void subjoinFirstLine(StringBuilder buf, String prefix, int indent, IThrowableProxy tp) { + ThrowableProxyUtil.indent(buf, indent - 1); + if (prefix != null) { + buf.append(prefix); + } + subjoinExceptionMessage(buf, tp); + } + + private void subjoinExceptionMessage(StringBuilder buf, IThrowableProxy tp) { + buf.append(tp.getClassName()).append(": ").append(tp.getMessage()); + } + + protected void subjoinStepArray(StringBuilder buf, int indent, IThrowableProxy tp) { + StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray(); + int commonFrames = tp.getCommonFrames(); + + boolean unrestrictedPrinting = lengthOption > stepArray.length; + + int maxIndex = (unrestrictedPrinting) ? stepArray.length : lengthOption; + if (commonFrames > 0 && unrestrictedPrinting) { + maxIndex -= commonFrames; + } + + int ignoredCount = 0; + for (int i = 0; i < maxIndex; i++) { + StackTraceElementProxy element = stepArray[i]; + if (!isIgnoredStackTraceLine(element.toString())) { + ThrowableProxyUtil.indent(buf, indent); + printStackLine(buf, ignoredCount, element); + ignoredCount = 0; + buf.append(CoreConstants.LINE_SEPARATOR); + } else { + ++ignoredCount; + if (maxIndex < stepArray.length) { + ++maxIndex; + } + } + } + if (ignoredCount > 0) { + printIgnoredCount(buf, ignoredCount); + buf.append(CoreConstants.LINE_SEPARATOR); + } + + if (commonFrames > 0 && unrestrictedPrinting) { + ThrowableProxyUtil.indent(buf, indent); + buf + .append("... ") + .append(tp.getCommonFrames()) + .append(" common frames omitted") + .append(CoreConstants.LINE_SEPARATOR); + } + } + + private void printStackLine(StringBuilder buf, int ignoredCount, StackTraceElementProxy element) { + buf.append(element); + extraData(buf, element); // allow other data to be added + if (ignoredCount > 0) { + printIgnoredCount(buf, ignoredCount); + } + } + + private void printIgnoredCount(StringBuilder buf, int ignoredCount) { + buf.append(" [").append(ignoredCount).append(" skipped]"); + } + + private boolean isIgnoredStackTraceLine(String line) { + if (ignoredStackTraceLines != null) { + for (String ignoredStackTraceLine : ignoredStackTraceLines) { + if (line.contains(ignoredStackTraceLine)) { + return true; + } + } + } + return false; + } + + private void processErrorCount(EventEvaluator ee, EvaluationException eex) { + if (errorCount < CoreConstants.MAX_ERROR_COUNT) { + addError("Exception thrown for evaluator named [" + ee.getName() + "]", eex); + } else if (errorCount == CoreConstants.MAX_ERROR_COUNT) { + ErrorStatus errorStatus = new ErrorStatus( + "Exception thrown for evaluator named [" + ee.getName() + "].", + this, + eex); + errorStatus.add(new ErrorStatus("This was the last warning about this evaluator's errors." + + "We don't want the StatusManager to get flooded.", this)); + addStatus(errorStatus); + } + } + +} diff --git a/src/main/java/com/harman/ignite/utils/logger/LoggerUtils.java b/src/main/java/com/harman/ignite/utils/logger/LoggerUtils.java new file mode 100644 index 0000000..97231c8 --- /dev/null +++ b/src/main/java/com/harman/ignite/utils/logger/LoggerUtils.java @@ -0,0 +1,101 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.logger; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * This class has utility methods which helps in deciding if Object[] args (AKS var-args) has Throwable.
+ * The methods of this class is used in case decide()'s Throwable arg is null, + * but still we can get Throwable as part of var-args. + * + * @author vkoul + */ +public class LoggerUtils { + + private LoggerUtils() { + + } + + private static final String CURLYBRACES_REGEX = "\\{\\}"; + private static final Pattern CURLYBRACES_PATTERN = Pattern.compile(CURLYBRACES_REGEX); + + /** + * Helper method to identify if the last element of object[] is throwable or not. + * + * @param format log message format + * @param args var-args + * @return true if last element of args is Throwable, else false. + */ + public static boolean hasThrowableObject(String format, Object[] args) { + + boolean hasThrowable = false; + if (null == args || args.length < 1) { + return false; + } + int curlyBracesCount = getCurlyBracesCount(format); + // check if the counts are unequal and curly brace count should exactly + // be 1 less than arguments length + if (curlyBracesCount != args.length + && (curlyBracesCount == (args.length - 1)) + && (args[args.length - 1] instanceof Throwable)) { + hasThrowable = true; + } + return hasThrowable; + } + + /** + * Helper method to retrieve the number of curly braces from the format. + * + * @param format log message format + * @return count of curly braces + */ + private static int getCurlyBracesCount(String format) { + Matcher m = CURLYBRACES_PATTERN.matcher(format); + // we are trying to find the pattern {} and group count will always give + // 0. + // Hence, we will iterate and get the count + int count = 0; + + while (m.find()) { + count++; + } + return count; + } + +} diff --git a/src/main/java/com/harman/ignite/utils/metrics/AbstractIgniteCounter.java b/src/main/java/com/harman/ignite/utils/metrics/AbstractIgniteCounter.java new file mode 100644 index 0000000..5c6f3af --- /dev/null +++ b/src/main/java/com/harman/ignite/utils/metrics/AbstractIgniteCounter.java @@ -0,0 +1,131 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.metrics; + +import com.harman.ignite.utils.logger.IgniteLogger; +import com.harman.ignite.utils.logger.IgniteLoggerFactory; +import io.prometheus.client.Counter; + +/** + * Abstract class for creating prometheus counter metric. + */ +public abstract class AbstractIgniteCounter { + + private static final IgniteLogger LOGGER = IgniteLoggerFactory.getLogger(AbstractIgniteCounter.class); + + private Counter counter; + + private boolean isInitialized; + + protected void createCounter(String name, String help, String... labels) { + + if (null == counter) { + synchronized (this) { + counter = Counter.build().name(name).help(help).labelNames(labels).register(); + } + } + + if (null != counter) { + isInitialized = true; + LOGGER.info("Created prometheus counter metric with name : {}", name); + } else { + LOGGER.warn("Error creating prometheus counter metric with name : {}", name); + } + } + + /** + * Increment the counter by 1. + * + * @param labelValues label values + */ + public void inc(String... labelValues) { + if (isInitialized) { + synchronized (counter) { + counter.labels(labelValues).inc(); + } + } + } + + /** Increment the counter by the given amount. + * + * @param value The value to increment the counter by. + * @param label values + */ + public void inc(double value, String ... label) { + if (isInitialized) { + synchronized (counter) { + counter.labels(label).inc(value); + } + } + } + + /** Get the value of the counter. + * + * @param labelValues label values + * @return The value of the counter. + */ + public double get(String... labelValues) { + double val = 0; + if (isInitialized) { + synchronized (counter) { + val = counter.labels(labelValues).get(); + } + } + return val; + } + + /** + * Remove the counter from the registry it was registered with. + */ + public void clear() { + if (isInitialized) { + synchronized (counter) { + counter.clear(); + } + } + } + + //Below setters/getters are just for test cases + public Counter getCounter() { + return this.counter; + } + + public boolean isInitialized() { + return isInitialized; + } + +} diff --git a/src/main/java/com/harman/ignite/utils/metrics/AbstractIgniteGauge.java b/src/main/java/com/harman/ignite/utils/metrics/AbstractIgniteGauge.java new file mode 100644 index 0000000..0f71d38 --- /dev/null +++ b/src/main/java/com/harman/ignite/utils/metrics/AbstractIgniteGauge.java @@ -0,0 +1,170 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.metrics; + +import com.harman.ignite.utils.logger.IgniteLogger; +import com.harman.ignite.utils.logger.IgniteLoggerFactory; +import io.prometheus.client.CollectorRegistry; +import io.prometheus.client.Gauge; + +/** + * Abstract class for creating prometheus gauge metric. + */ +public abstract class AbstractIgniteGauge { + + private static final IgniteLogger LOGGER = IgniteLoggerFactory.getLogger(AbstractIgniteGauge.class); + + private Gauge guage; + + private boolean isInitialized; + + protected void createGauge(String name, String help, String... labels) { + if (null == guage) { + synchronized (this) { + guage = Gauge.build(name, name) + .labelNames(labels) + .help(help) + .register(CollectorRegistry.defaultRegistry); + LOGGER.info("Created ignite guage with name : {} and labels {}", name, labels); + } + } + + if (null != guage) { + isInitialized = true; + LOGGER.info("Created prometheus gauge metric with name : {}", name); + } else { + LOGGER.warn("Error creating prometheus guage metric with name : {}", name); + } + } + + /** Increment the gauge by 1. + * + * @param labelValues label values + */ + public void inc(String... labelValues) { + if (isInitialized) { + synchronized (guage) { + guage.labels(labelValues).inc(); + } + } + } + + /** Increment the gauge by the given amount. + * + * @param value The value to increment the gauge by. + * @param labelValues label values + */ + public void inc(double value, String... labelValues) { + if (isInitialized) { + synchronized (guage) { + guage.labels(labelValues).inc(value); + } + } + } + + /** Decrement the gauge by 1. + * + * @param labelValues label values + */ + public void dec(String... labelValues) { + if (isInitialized) { + synchronized (guage) { + guage.labels(labelValues).dec(); + } + } + } + + /** Decrement the gauge by the given amount. + * + * @param value The value to decrement the gauge by. + * @param labelValues label values + */ + public void dec(double value, String... labelValues) { + if (isInitialized) { + synchronized (guage) { + guage.labels(labelValues).dec(value); + } + } + } + + /** Get the value of the gauge. + * + * @param labelValues label values + * @return The value of the gauge. + */ + public double get(String... labelValues) { + double val = 0; + if (isInitialized) { + synchronized (guage) { + val = guage.labels(labelValues).get(); + } + } + return val; + } + + /** Set the gauge to the given value. + * + * @param value The value to set the gauge to. + * @param labelValues label values + */ + public void set(double value, String... labelValues) { + if (isInitialized) { + synchronized (guage) { + guage.labels(labelValues).set(value); + } + } + } + + /** + * Remove the gauge from the registry it was registered with. + */ + public void clear() { + if (isInitialized) { + synchronized (guage) { + guage.clear(); + } + } + } + + Gauge getGuage() { + return this.guage; + } + + boolean getIsInitialized() { + return this.isInitialized; + } +} diff --git a/src/main/java/com/harman/ignite/utils/metrics/AbstractIgniteHistogram.java b/src/main/java/com/harman/ignite/utils/metrics/AbstractIgniteHistogram.java new file mode 100644 index 0000000..a801a14 --- /dev/null +++ b/src/main/java/com/harman/ignite/utils/metrics/AbstractIgniteHistogram.java @@ -0,0 +1,150 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.metrics; + +import io.prometheus.client.CollectorRegistry; +import io.prometheus.client.Histogram; + +import java.util.concurrent.Callable; +import java.util.function.Supplier; + +/** + * Base histogram for Ignite. + * + * @author ssasidharan + */ +public abstract class AbstractIgniteHistogram { + + private static final double TIMER_DIVISOR = 1E9D; + private Histogram histogram; + + protected void createHistogram(String name, String help, double[] buckets, String... labelNames) { + histogram = Histogram + .build(name, help) + .labelNames(labelNames) + .buckets(buckets) + .register(CollectorRegistry.defaultRegistry); + } + + public IgniteTimer start() { + return new IgniteTimer(this); + } + + public void observe(double amt, String... labels) { + histogram.labels(labels).observe(amt); + } + + /** + * Observe the time taken for a function to execute. + * + * @param f supplier function to execute + * @param labels labels to be observed + * @param type of the result + * @return result of the function + */ + public T observe(Supplier f, String... labels) { + IgniteTimer timer = start(); + try { + return f.get(); + } finally { + timer.observe(labels); + } + } + + /** + * Observe the time taken for a function to execute. + * + * @param f runnable function to execute + * @param labels labels to be observed + */ + public void observe(Runnable f, String... labels) { + IgniteTimer timer = start(); + try { + f.run(); + } finally { + timer.observe(labels); + } + } + + /** + * Allows exception to be thrown unlike observe(Supplier). + * + * @param f function to execute + * @param labels labels to be observed + * @return result of the function + * @throws Exception the exception thrown by the function + */ + public V observeExtended(Callable f, String... labels) throws Exception { + IgniteTimer timer = start(); + try { + return f.call(); + } finally { + timer.observe(labels); + } + } + + + + /** + * Timer for Ignite. + */ + public static class IgniteTimer { + private AbstractIgniteHistogram histo = null; + private long start = 0L; + + public IgniteTimer(AbstractIgniteHistogram histo) { + this.histo = histo; + this.start = System.nanoTime(); + } + + /** + * Observe the time taken for the function to execute. + * + * @param labels labels to be observed + * @return time taken + */ + public double observe(String... labels) { + double amt = (System.nanoTime() - start) / TIMER_DIVISOR; + histo.observe(amt, labels); + return amt; + } + } + + Histogram getHistogram() { + return histogram; + } +} \ No newline at end of file diff --git a/src/main/java/com/harman/ignite/utils/metrics/GenericIgniteCounter.java b/src/main/java/com/harman/ignite/utils/metrics/GenericIgniteCounter.java new file mode 100644 index 0000000..09b7ad7 --- /dev/null +++ b/src/main/java/com/harman/ignite/utils/metrics/GenericIgniteCounter.java @@ -0,0 +1,50 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.metrics; + +/** + * The default Ignite Counter implementation. + * + * @author avadakkootko + */ +public class GenericIgniteCounter extends AbstractIgniteCounter { + + public GenericIgniteCounter(String name, String help, String... labels) { + createCounter(name, help, labels); + } + +} diff --git a/src/main/java/com/harman/ignite/utils/metrics/GenericIgniteGauge.java b/src/main/java/com/harman/ignite/utils/metrics/GenericIgniteGauge.java new file mode 100644 index 0000000..154bd3c --- /dev/null +++ b/src/main/java/com/harman/ignite/utils/metrics/GenericIgniteGauge.java @@ -0,0 +1,48 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.metrics; + +/** + * Gauge for Ignite. + * + * @author ssasidharan + */ +public class GenericIgniteGauge extends AbstractIgniteGauge { + public GenericIgniteGauge(String name, String help, String... labels) { + createGauge(name, help, labels); + } +} diff --git a/src/main/java/com/harman/ignite/utils/metrics/GenericIgniteHistogram.java b/src/main/java/com/harman/ignite/utils/metrics/GenericIgniteHistogram.java new file mode 100644 index 0000000..afef655 --- /dev/null +++ b/src/main/java/com/harman/ignite/utils/metrics/GenericIgniteHistogram.java @@ -0,0 +1,50 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.metrics; + +/** + * Histogram for Ignite. + * + * @author ssasidharan + */ +public class GenericIgniteHistogram extends AbstractIgniteHistogram { + + public GenericIgniteHistogram(String name, String help, double[] buckets, String... labelNames) { + createHistogram(name, help, buckets, labelNames); + } + +} diff --git a/src/main/java/com/harman/ignite/utils/metrics/IgniteCounter.java b/src/main/java/com/harman/ignite/utils/metrics/IgniteCounter.java new file mode 100644 index 0000000..b329c6f --- /dev/null +++ b/src/main/java/com/harman/ignite/utils/metrics/IgniteCounter.java @@ -0,0 +1,95 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.metrics; + +import com.harman.ignite.utils.logger.IgniteLogger; +import com.harman.ignite.utils.logger.IgniteLoggerFactory; +import io.prometheus.client.CollectorRegistry; +import io.prometheus.client.Counter; + +import java.util.Objects; + +/** + * Wrapper around Prometheus Counter. + * + * @author sanketadhikari + */ +public abstract class IgniteCounter { + + private static final IgniteLogger LOGGER = IgniteLoggerFactory.getLogger(IgniteCounter.class); + + private Counter counter; + + /** + * Increment the counter metric's value by 1 for given labels. + * + * @param labelValues Values of the labels + */ + public void inc(String... labelValues) { + Objects.requireNonNull(counter, "IgniteCounter is not initialized"); + synchronized (this.counter) { + counter.labels(labelValues).inc(); + } + } + + /** + * Get the metric's value for given labels. + * + * @param labelValues label values + */ + public double get(String... labelValues) { + double value = 0; + Objects.requireNonNull(counter, "IgniteCounter is not initialized"); + value = counter.labels(labelValues).get(); + return value; + } + + protected void createCounter(String name, String... labels) { + if (null == counter) { + synchronized (this) { + counter = Counter.build(name, name).labelNames(labels).register(CollectorRegistry.defaultRegistry); + LOGGER.info("Created ignite counter with name : {} and labels {}", name, labels); + } + } else { + LOGGER.warn("Ignite counter with name : {} and labels {}, already created", name, labels); + } + } + + Counter getCounter() { + return this.counter; + } +} diff --git a/src/main/java/com/harman/ignite/utils/metrics/IgniteDiagnosticGuage.java b/src/main/java/com/harman/ignite/utils/metrics/IgniteDiagnosticGuage.java new file mode 100644 index 0000000..1c69d30 --- /dev/null +++ b/src/main/java/com/harman/ignite/utils/metrics/IgniteDiagnosticGuage.java @@ -0,0 +1,52 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.metrics; + +import org.springframework.stereotype.Component; + +/** + * To be used by various Diagnostic reporters for publishing their respective report to prometheus. + * + * @author avadakkootko + */ +@Component +public class IgniteDiagnosticGuage extends IgniteGuage { + + public IgniteDiagnosticGuage() { + createGuage("diagnostic_metric", "node", "diagnostic_reporter_name", "diagnostic_reporter_sublabel"); + } +} diff --git a/src/main/java/com/harman/ignite/utils/metrics/IgniteErrorCounter.java b/src/main/java/com/harman/ignite/utils/metrics/IgniteErrorCounter.java new file mode 100644 index 0000000..fa8f4c2 --- /dev/null +++ b/src/main/java/com/harman/ignite/utils/metrics/IgniteErrorCounter.java @@ -0,0 +1,120 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.metrics; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.util.Optional; + +/** + * The default implementation of error counter for ignite platform.
+ * If prometheus is enabled all base framework and services can inject + * this bean to register error counter metric and continuously publish values. + * + * @author avadakkootko + */ +@Component +public class IgniteErrorCounter extends GenericIgniteCounter { + + public static final String NA = "N/A"; + private static final String ERROR_COUNT = "error_count"; + private static final String NODE = "node"; + private static final String TASKID = "tid"; + private static final String EXCEPTION_CLASS_NAME = "ecn"; + @Value("${NODE_NAME:localhost}") + private String nodeName; + + public IgniteErrorCounter() { + super(ERROR_COUNT, ERROR_COUNT, NODE, TASKID, EXCEPTION_CLASS_NAME); + } + + /** + * Increments the counter by 1. + * + * @param taskId Optional and refers to the stream processor's current task id. Defaults to N/A + * @param exceptionClassName The exception class name + */ + public void incErrorCounter(Optional taskId, Class exceptionClassName) { + String tid = null; + if (taskId.isPresent()) { + tid = taskId.get(); + } else { + tid = NA; + } + inc(nodeName, tid, exceptionClassName.getName()); + } + + /** + * Increments the counter with value specified. + * + * @param value The value to increment the counter by. + * @param taskId Optional and refers to the stream processor's current task id. Defaults to N/A + * @param exceptionClassName The exception class name + */ + public void incErrorCounter(double value, Optional taskId, Class exceptionClassName) { + String tid = null; + if (taskId.isPresent()) { + tid = taskId.get(); + } else { + tid = NA; + } + inc(value, nodeName, tid, exceptionClassName.getName()); + } + + /** + * This returns the error count grouped by nodename, taskId if present and exceptionClassName. + * + * @param taskId Optional and refers to the stream processor's current task id. Defaults to N/A + * @param exceptionClassName The exception class name + * @return The value of the counter + */ + public double getErrorCounterValue(Optional taskId, Class exceptionClassName) { + String tid = null; + if (taskId.isPresent()) { + tid = taskId.get(); + } else { + tid = NA; + } + return get(nodeName, tid, exceptionClassName.getName()); + } + + public void setNodeName(String nodeName) { + this.nodeName = nodeName; + } + +} diff --git a/src/main/java/com/harman/ignite/utils/metrics/IgniteGuage.java b/src/main/java/com/harman/ignite/utils/metrics/IgniteGuage.java new file mode 100644 index 0000000..cb3b1b6 --- /dev/null +++ b/src/main/java/com/harman/ignite/utils/metrics/IgniteGuage.java @@ -0,0 +1,104 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.metrics; + +import com.harman.ignite.utils.logger.IgniteLogger; +import com.harman.ignite.utils.logger.IgniteLoggerFactory; +import io.prometheus.client.CollectorRegistry; +import io.prometheus.client.Gauge; + +import java.util.Objects; + +/** + * Wrapper around Prometheus Guage. + * + * @author avadakkootko + */ +public abstract class IgniteGuage { + + private static final IgniteLogger LOGGER = IgniteLoggerFactory.getLogger(IgniteGuage.class); + + private Gauge igniteGuageMetric; + + /** + * Set the metric's value. + + * @param value The value to set. + * @param labelValues Label values to set the value for. + */ + public void set(double value, String... labelValues) { + Objects.requireNonNull(igniteGuageMetric, "IgniteGuage is not initialized"); + synchronized (this.igniteGuageMetric) { + igniteGuageMetric.labels(labelValues).set(value); + } + } + + /** + * Get the value of the guage. + * + * @param labelValues label values + * @return The value of the guage. + */ + public double get(String... labelValues) { + double value = 0; + Objects.requireNonNull(igniteGuageMetric, "IgniteGuage is not initialized"); + value = igniteGuageMetric.labels(labelValues).get(); + return value; + } + + protected void createGuage(String name, String... labels) { + if (null == igniteGuageMetric) { + synchronized (this) { + igniteGuageMetric = Gauge.build(name, name) + .labelNames(labels) + .register(CollectorRegistry.defaultRegistry); + LOGGER.info("Created ignite guage with name : {} and labels {}", name, labels); + } + } else { + LOGGER.warn("Ignite guage with name : {} and labels {}, already created", name, labels); + } + } + + // setter and getter for unit tests + Gauge getIgniteGuageMetric() { + return this.igniteGuageMetric; + } + + void setIgniteGuageMetric(Gauge igniteGuageMetric) { + this.igniteGuageMetric = igniteGuageMetric; + } +} diff --git a/src/main/java/com/harman/ignite/utils/metrics/IgniteHealthGuage.java b/src/main/java/com/harman/ignite/utils/metrics/IgniteHealthGuage.java new file mode 100644 index 0000000..eb82ae6 --- /dev/null +++ b/src/main/java/com/harman/ignite/utils/metrics/IgniteHealthGuage.java @@ -0,0 +1,52 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.metrics; + +import org.springframework.stereotype.Component; + +/** + * IgniteHealthGuage will be used by various HealthMonitors for publishing their respective health status to prometheus. + * + * @author avadakkootko + */ +@Component +public class IgniteHealthGuage extends IgniteGuage { + + public IgniteHealthGuage() { + createGuage("service_health_metric", "node", "monitorname"); + } +} diff --git a/src/main/java/com/harman/ignite/utils/metrics/IgniteRocksDBGuage.java b/src/main/java/com/harman/ignite/utils/metrics/IgniteRocksDBGuage.java new file mode 100644 index 0000000..5d461db --- /dev/null +++ b/src/main/java/com/harman/ignite/utils/metrics/IgniteRocksDBGuage.java @@ -0,0 +1,59 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.metrics; + +import com.harman.ignite.utils.logger.IgniteLogger; +import com.harman.ignite.utils.logger.IgniteLoggerFactory; +import org.springframework.stereotype.Component; + +/** + * Creates and registers Guage metric in Prometheus for each one of the property-based metrics in RocksDB. + * with labels = serviceName + * and metricName(the actual name of the RocksDB metric property) + * + * @author hbadshah + */ +@SuppressWarnings("checkstyle:AbbreviationAsWordInName") +@Component +public class IgniteRocksDBGuage extends IgniteGuage { + private static final IgniteLogger LOGGER = IgniteLoggerFactory.getLogger(IgniteRocksDBGuage.class); + + public void setup() { + createGuage("rocksdb_metric", "metric_name", "svc", "node"); + LOGGER.debug("rocksdb_metric guage successfully created."); + } +} diff --git a/src/main/java/com/harman/ignite/utils/metrics/InternalCacheGuage.java b/src/main/java/com/harman/ignite/utils/metrics/InternalCacheGuage.java new file mode 100644 index 0000000..d1480be --- /dev/null +++ b/src/main/java/com/harman/ignite/utils/metrics/InternalCacheGuage.java @@ -0,0 +1,81 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.metrics; + +import com.harman.ignite.utils.logger.IgniteLogger; +import com.harman.ignite.utils.logger.IgniteLoggerFactory; +import jakarta.annotation.PostConstruct; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.util.Arrays; + +/** + * Guage for internal cache(s) metric. + * + * @author hbadshah + */ +@Component +public class InternalCacheGuage extends IgniteGuage { + + private static final IgniteLogger LOGGER = IgniteLoggerFactory.getLogger(InternalCacheGuage.class); + + @Value("${internal.metrics.enabled:false}") + private boolean internalMetricsEnabled; + + @Value("${metrics.prometheus.enabled:true}") + private boolean prometheusEnabled; + + /** + * Setup the guage metric for internal cache. + */ + @PostConstruct + public void setup() { + if (prometheusEnabled && internalMetricsEnabled) { + createGuage("internal_cache_size_metric", "cache_type", "svc", "node", "task_id"); + LOGGER.info("Guage metric for internal cache created."); + } + } + + @Override + public void set(double value, String... labels) { + if (prometheusEnabled && internalMetricsEnabled) { + super.set(value, labels); + LOGGER.debug("Published metrics for labels: {} with value: {}", Arrays.asList(labels), value); + } + } +} diff --git a/src/main/java/com/harman/ignite/utils/test/NightlyBuildTestCase.java b/src/main/java/com/harman/ignite/utils/test/NightlyBuildTestCase.java new file mode 100644 index 0000000..3af114c --- /dev/null +++ b/src/main/java/com/harman/ignite/utils/test/NightlyBuildTestCase.java @@ -0,0 +1,54 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.test; + +/** + * Marker interface to tag a JUnit4 test case to run for nightly build. + * Typically, a long-running test case is tagged for nightly build process. + *

This interface is specified in Maven pom.xml's <excludeGroups/> XML tag to exclude the test cases.

+ *

Usage: Tag a test method or class,

+ *
    + *
  • @org.junit.Test @org.junit.experimental.categories.Category(NightlyBuildTestCase.class) + * public void testFoo(){...}
  • + *
  • @org.junit.experimental.categories.Category(NightlyBuildTestCase.class) + * public class Foo{...}
  • + *
+ * + * @author KJalawadi + */ +public interface NightlyBuildTestCase { +} diff --git a/src/test/java/com/harman/ignite/diagnostic/DiagnosticResultTest.java b/src/test/java/com/harman/ignite/diagnostic/DiagnosticResultTest.java new file mode 100644 index 0000000..90cc8ab --- /dev/null +++ b/src/test/java/com/harman/ignite/diagnostic/DiagnosticResultTest.java @@ -0,0 +1,55 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.diagnostic; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Test class for DiagnosticResult. + * + * @see DiagnosticResult + */ +public class DiagnosticResultTest { + private DiagnosticResult res; + + @Test + public void testPassAndFail() { + Assert.assertEquals(1.0, DiagnosticResult.PASS.getValue(), 0); + Assert.assertEquals(0.0, DiagnosticResult.FAIL.getValue(), 0); + } +} diff --git a/src/test/java/com/harman/ignite/diagnostic/DiagnosticUnitTest.java b/src/test/java/com/harman/ignite/diagnostic/DiagnosticUnitTest.java new file mode 100644 index 0000000..38eb671 --- /dev/null +++ b/src/test/java/com/harman/ignite/diagnostic/DiagnosticUnitTest.java @@ -0,0 +1,185 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.diagnostic; + +import com.harman.ignite.utils.logger.IgniteLogger; +import com.harman.ignite.utils.logger.IgniteLoggerFactory; +import com.harman.ignite.utils.metrics.IgniteDiagnosticGuage; +import io.prometheus.client.Collector.MetricFamilySamples; +import io.prometheus.client.CollectorRegistry; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +/** + * Test class for DiagnosticService. + * + * @see DiagnosticService + */ +public class DiagnosticUnitTest { + private static final IgniteLogger LOGGER = IgniteLoggerFactory.getLogger(DiagnosticUnitTest.class); + @Rule + public MockitoRule mockitoRule = MockitoJUnit.rule(); + + @InjectMocks + private DiagnosticService diagnosticService = new DiagnosticService(); + + @Mock + private IgniteDiagnosticGuage diagnosticGuage; + + /** + * Setup the test. + */ + @Before + public void setUp() { + clearMetrics(); + MockitoAnnotations.initMocks(this); + diagnosticService.setServiceDiagnosticGuage(diagnosticGuage); + diagnosticService.setNodeName("localhost"); + + } + + /** + * If two DiagnosticReporters have same name it should throw runtime exception. + */ + @Test(expected = RuntimeException.class) + public void testInitTwoReportersWithSameName() { + final List reporters = new ArrayList<>(); + TestDiagnosticReporter reporter1 = new TestDiagnosticReporter(); + reporter1.setEnabled(true); + reporter1.setMetricName("Metric1"); + reporter1.setReporterName("Reporter1"); + reporters.add(reporter1); + + TestDiagnosticReporter reporter2 = new TestDiagnosticReporter(); + reporter2.setEnabled(true); + reporter2.setMetricName("Metric1"); + reporter2.setReporterName("Reporter2"); + reporters.add(reporter2); + + diagnosticService.setReporters(reporters); + diagnosticService.getEnabledReporters(); + } + + /** + * If a DiagnosticReporter is disabled it should not be added in the list of DiagnosticReporters. + */ + @Test + public void testInitWithDisabledReporter() { + final List reporters = new ArrayList<>(); + TestDiagnosticReporter reporter1 = new TestDiagnosticReporter(); + reporter1.setEnabled(true); + reporter1.setMetricName("Metric1"); + reporter1.setReporterName("Reporter1"); + reporters.add(reporter1); + + TestDiagnosticReporter reporter2 = new TestDiagnosticReporter(); + reporter2.setEnabled(false); + reporter2.setMetricName("Metric1"); + reporter2.setReporterName("Reporter2"); + reporters.add(reporter2); + + diagnosticService.setReporters(reporters); + + List enabledReporters = diagnosticService.getEnabledReporters(); + Assert.assertEquals(1, enabledReporters.size()); + Assert.assertEquals("Metric1", enabledReporters.get(0).getDiagnosticMetricName()); + Assert.assertEquals("Reporter1", enabledReporters.get(0).getDiagnosticReporterName()); + } + + @Test + public void testMetricPublishing() { + final List reporters = new ArrayList<>(); + TestDiagnosticReporter reporter1 = new TestDiagnosticReporter(); + reporter1.setEnabled(true); + reporter1.setMetricName("Metric1"); + reporter1.setReporterName("Reporter1"); + DiagnosticData data = new DiagnosticData(); + data.put("Metric1Key1", DiagnosticResult.FAIL); + data.put("Metric1Key2", DiagnosticResult.PASS); + data.put("Metric1Key3", DiagnosticResult.FAIL); + reporter1.setData(data); + reporters.add(reporter1); + + TestDiagnosticReporter reporter2 = new TestDiagnosticReporter(); + reporter2.setEnabled(true); + reporter2.setMetricName("Metric2"); + reporter2.setReporterName("Reporter2"); + DiagnosticData data2 = new DiagnosticData(); + data2.put("Metric2Key1", DiagnosticResult.PASS); + reporter2.setData(data2); + reporters.add(reporter2); + + diagnosticService.setReporters(reporters); + diagnosticService.triggerDiagnosis(); + + Mockito.verify(diagnosticGuage, Mockito.times(1)) + .set(DiagnosticResult.FAIL.getValue(), "localhost", "Metric1", "Metric1Key1"); + Mockito.verify(diagnosticGuage, Mockito.times(1)) + .set(DiagnosticResult.PASS.getValue(), "localhost", "Metric1", "Metric1Key2"); + Mockito.verify(diagnosticGuage, Mockito.times(1)) + .set(DiagnosticResult.FAIL.getValue(), "localhost", "Metric1", "Metric1Key3"); + Mockito.verify(diagnosticGuage, Mockito.times(1)) + .set(DiagnosticResult.PASS.getValue(), "localhost", "Metric2", "Metric2Key1"); + + } + + /** + * Clear all the metrics. + */ + public void clearMetrics() { + Enumeration mfsEnumerator = CollectorRegistry.defaultRegistry.metricFamilySamples(); + while (mfsEnumerator.hasMoreElements()) { + MetricFamilySamples mfs = mfsEnumerator.nextElement(); + if (mfs.samples != null) { + mfs.samples.clear(); + } + } + } + +} diff --git a/src/test/java/com/harman/ignite/diagnostic/PropertyDiagnosticReporterTest.java b/src/test/java/com/harman/ignite/diagnostic/PropertyDiagnosticReporterTest.java new file mode 100644 index 0000000..be8f138 --- /dev/null +++ b/src/test/java/com/harman/ignite/diagnostic/PropertyDiagnosticReporterTest.java @@ -0,0 +1,107 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.diagnostic; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * Test class for DiagnosticReporter. + * + * @see DiagnosticReporter + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { TestDiagnosticReporterConfig.class }) +@TestPropertySource( + locations = {"classpath:property-diagnostic-test.properties", "classpath:property-diagnostic-test-2.properties"} +) +public class PropertyDiagnosticReporterTest { + @Autowired + @Qualifier("propertyDiagnostic") + DiagnosticReporter propertyDiagnosticReporterImpl; + + @Before + public void setUp() { + + } + + @Test + public void testDiagnosticReporterName() { + Assert.assertEquals("DIAGNOSTIC_PROPERTY_REPORTER", propertyDiagnosticReporterImpl.getDiagnosticReporterName()); + } + + @Test + public void testDiagnosticMetricName() { + Assert.assertEquals("DIAGNOSTIC_PROPERTY_METRIC", propertyDiagnosticReporterImpl.getDiagnosticMetricName()); + } + + @Test + public void isDiagnosticReporterEnabled() { + Assert.assertTrue(propertyDiagnosticReporterImpl.isDiagnosticReporterEnabled()); + + } + + @Test + public void testPropertyDiagnosticReporter() { + DiagnosticData diagnosticData = propertyDiagnosticReporterImpl.getDiagnosticData(); + + diagnosticData.forEach((key, value) -> System.out.println("property: " + key + "value: " + value)); + + Assert.assertEquals(DiagnosticResult.FAIL, diagnosticData.get("mongodb.hosts")); + Assert.assertEquals(DiagnosticResult.FAIL, diagnosticData.get("mongodb.port")); + Assert.assertEquals(DiagnosticResult.FAIL, diagnosticData.get("mongodb.username")); + Assert.assertEquals(DiagnosticResult.FAIL, diagnosticData.get("mongodb.hosts")); + Assert.assertEquals(DiagnosticResult.PASS, diagnosticData.get("mongodb.pool.max.size")); + Assert.assertEquals(DiagnosticResult.PASS, diagnosticData.get("mongodb.max.wait.time.ms")); + Assert.assertEquals(DiagnosticResult.PASS, diagnosticData.get("mongodb.socket.timeout.ms")); + Assert.assertEquals(DiagnosticResult.PASS, diagnosticData.get("mongodb.max.connections.per.host")); + Assert.assertEquals(DiagnosticResult.PASS, diagnosticData.get("mongodb.block.threads.allowed.multiplier")); + Assert.assertEquals(DiagnosticResult.PASS, diagnosticData.get("mongodb.read.preference")); + Assert.assertEquals(DiagnosticResult.PASS, diagnosticData.get("morphia.map.packages")); + Assert.assertEquals(DiagnosticResult.PASS, diagnosticData.get("mongodb.socket.timeout.ms")); + Assert.assertEquals(DiagnosticResult.PASS, diagnosticData.get("morphia.converters.fqn")); + Assert.assertEquals(DiagnosticResult.FAIL, diagnosticData.get("vault.secret.folder")); + Assert.assertEquals(DiagnosticResult.FAIL, diagnosticData.get("vault.environment")); + } +} diff --git a/src/test/java/com/harman/ignite/diagnostic/TestDiagnosticReporter.java b/src/test/java/com/harman/ignite/diagnostic/TestDiagnosticReporter.java new file mode 100644 index 0000000..52a9d7c --- /dev/null +++ b/src/test/java/com/harman/ignite/diagnostic/TestDiagnosticReporter.java @@ -0,0 +1,85 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.diagnostic; + +/** + * Test POJO for DiagnosticReporter. + */ +public class TestDiagnosticReporter implements DiagnosticReporter { + + private boolean enabled; + private String reporterName = "TestDiagnosticReporter"; + private String metricName = "TestDiagnosticReporterGuage"; + private DiagnosticData data = new DiagnosticData(); + + @Override + public boolean isDiagnosticReporterEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + @Override + public String getDiagnosticReporterName() { + return reporterName; + } + + @Override + public String getDiagnosticMetricName() { + return metricName; + } + + public void setReporterName(String reporterName) { + this.reporterName = reporterName; + } + + public void setMetricName(String metricName) { + this.metricName = metricName; + } + + @Override + public DiagnosticData getDiagnosticData() { + return data; + } + + public void setData(DiagnosticData data) { + this.data = data; + } + +} diff --git a/src/test/java/com/harman/ignite/diagnostic/TestDiagnosticReporterConfig.java b/src/test/java/com/harman/ignite/diagnostic/TestDiagnosticReporterConfig.java new file mode 100644 index 0000000..492ed50 --- /dev/null +++ b/src/test/java/com/harman/ignite/diagnostic/TestDiagnosticReporterConfig.java @@ -0,0 +1,56 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.diagnostic; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +/** + * Test configuration for initializing a diagnostic reporter and testing it as PropertyDiagnosticReporterTest. + * + * @see PropertyDiagnosticReporterTest + */ +@Configuration +@ComponentScan(basePackages = { "com.harman.ignite" }) +public class TestDiagnosticReporterConfig { + + @Bean + public PropertyDiagnosticReporterTest testPropertyDiagnosticReporter() { + return new PropertyDiagnosticReporterTest(); + } +} diff --git a/src/test/java/com/harman/ignite/healthcheck/HealthServiceIntegrationTestCase.java b/src/test/java/com/harman/ignite/healthcheck/HealthServiceIntegrationTestCase.java new file mode 100644 index 0000000..ea123cd --- /dev/null +++ b/src/test/java/com/harman/ignite/healthcheck/HealthServiceIntegrationTestCase.java @@ -0,0 +1,161 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.healthcheck; + +import com.harman.ignite.utils.logger.IgniteLogger; +import com.harman.ignite.utils.logger.IgniteLoggerFactory; +import io.prometheus.client.Collector.MetricFamilySamples; +import io.prometheus.client.Collector.MetricFamilySamples.Sample; +import io.prometheus.client.CollectorRegistry; +import org.junit.Assert; +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.MethodSorters; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.Enumeration; +import java.util.List; + +/** + * Integration test for HealthService. + * + * @see HealthService + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { TestHealthServiceConfig.class }) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class HealthServiceIntegrationTestCase { + + static final double HEALTHY = 0.0; + static final double UNHEALTHY = 1.0; + static final int TWO = 2; + static final String SERVICE_HEALTH = "SERVICE_HEALTH"; + private static final IgniteLogger LOGGER = IgniteLoggerFactory.getLogger(HealthServiceIntegrationTestCase.class); + @Autowired + private HealthService healthService; + + @Before + public void setup() { + clearMetrics(); + } + + /** + * Post constructor should have autowired the health monitors and not started the executor. + */ + @Test + public void testInit() { + List monitors = healthService.getHealthMonitors(); + // Although 3 monitors are present in Configuration class one is + // disabled hence only 2 monitors should be present + Assert.assertEquals(TWO, monitors.size()); + } + + @Test + public void testNeedsRestartWithHealthyMonitor() throws InterruptedException { + TestHealthMonitor overrideMonitor = new TestHealthMonitor(); + overrideMonitor.setEnabled(true); + overrideMonitor.setHealthy(true); + overrideMonitor.setNeedsRestartOnFailure(true); + + List monitors = healthService.getHealthMonitors(); + + monitors.clear(); + monitors.add(overrideMonitor); + + healthService.setHealthMonitors(monitors); + + Assert.assertFalse(healthService.needsRestart()); + + Enumeration allSamples = CollectorRegistry.defaultRegistry.metricFamilySamples(); + + while (allSamples.hasMoreElements()) { + MetricFamilySamples samples = allSamples.nextElement(); + LOGGER.info("Metric name {}", samples.name); + + for (Sample sample : samples.samples) { + Assert.assertEquals(HEALTHY, sample.value, 0.0D); + } + } + + } + + @Test + public void testNeedsRestartWithUnHealthyMonitor() throws InterruptedException { + TestHealthMonitor overrideMonitor = new TestHealthMonitor(); + overrideMonitor.setEnabled(true); + overrideMonitor.setHealthy(false); + overrideMonitor.setNeedsRestartOnFailure(true); + + List monitors = healthService.getHealthMonitors(); + + monitors.clear(); + monitors.add(overrideMonitor); + + healthService.setHealthMonitors(monitors); + + Assert.assertTrue(healthService.needsRestart()); + + Enumeration allSamples = CollectorRegistry.defaultRegistry.metricFamilySamples(); + + while (allSamples.hasMoreElements()) { + MetricFamilySamples samples = allSamples.nextElement(); + LOGGER.info("Metric name {}", samples.name); + + for (Sample sample : samples.samples) { + Assert.assertEquals(UNHEALTHY, sample.value, 1.0D); + } + } + } + + /** + * Clear all the metrics. + */ + public void clearMetrics() { + Enumeration mfsEnumerator = CollectorRegistry.defaultRegistry.metricFamilySamples(); + while (mfsEnumerator.hasMoreElements()) { + MetricFamilySamples mfs = mfsEnumerator.nextElement(); + if (mfs.samples != null) { + mfs.samples.clear(); + } + } + } + +} diff --git a/src/test/java/com/harman/ignite/healthcheck/HealthServiceStateTest.java b/src/test/java/com/harman/ignite/healthcheck/HealthServiceStateTest.java new file mode 100644 index 0000000..6b0a6cf --- /dev/null +++ b/src/test/java/com/harman/ignite/healthcheck/HealthServiceStateTest.java @@ -0,0 +1,110 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.healthcheck; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.MockitoAnnotations; + +import java.util.ArrayList; + +/** Test class for HealthServiceState. + * + * @see HealthServiceState + */ +public class HealthServiceStateTest { + + @InjectMocks + private HealthServiceState serviceState; + + private double state; + private String message; + + /** + * Setup the test. + */ + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + state = 0; + message = "Test message"; + } + + @Test + public void testSetState() { + serviceState.setState(state); + Assert.assertEquals(0, serviceState.getState(), 0); + } + + @Test + public void testSetMessage() { + serviceState.setMessage(message); + Assert.assertEquals("Test message", serviceState.getMessage()); + } + + @Test + public void testEquals() { + HealthServiceState serviceState1 = new HealthServiceState(); + serviceState1.setState(1); + serviceState1.setMessage("Unhealthy"); + HealthServiceState serviceState2 = new HealthServiceState(); + serviceState2.setState(1); + serviceState2.setMessage("Unhealthy"); + Assert.assertEquals(serviceState1, (serviceState2)); + serviceState1.setState(0); + Assert.assertNotEquals(serviceState1, (serviceState2)); + serviceState2.setMessage("test"); + Assert.assertNotNull(String.valueOf(serviceState1), (serviceState2)); + serviceState2.setMessage(null); + Assert.assertNotEquals(serviceState1, (serviceState2)); + Assert.assertNotNull(serviceState1); + Assert.assertNotEquals(serviceState1, (new ArrayList())); + serviceState1.setMessage(null); + serviceState2.setMessage("test"); + Assert.assertNotEquals(serviceState1, (serviceState2)); + } + + + @Test + public void testHashCode() { + serviceState.setState(0); + serviceState.setMessage(message); + Assert.assertNotEquals(serviceState.hashCode(), 0); + } +} diff --git a/src/test/java/com/harman/ignite/healthcheck/HealthServiceUnitTest.java b/src/test/java/com/harman/ignite/healthcheck/HealthServiceUnitTest.java new file mode 100644 index 0000000..4533603 --- /dev/null +++ b/src/test/java/com/harman/ignite/healthcheck/HealthServiceUnitTest.java @@ -0,0 +1,678 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.healthcheck; + +import com.harman.ignite.utils.logger.IgniteLogger; +import com.harman.ignite.utils.logger.IgniteLoggerFactory; +import com.harman.ignite.utils.metrics.IgniteHealthGuage; +import io.prometheus.client.Collector.MetricFamilySamples; +import io.prometheus.client.CollectorRegistry; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +/** + * Test class for HealthService. + * + * @see HealthService + */ +public class HealthServiceUnitTest { + static final String SERVICE_HEALTH = "SERVICE_HEALTH"; + static final double HEALTHY = 0; + static final double UNHEALTHY = 1; + static final int TWO = 2; + static final int THREE = 3; + static final int FOUR = 4; + static final int FIVE = 5; + static final int SEVEN = 7; + static final int HUNDRED = 100; + static final long THOUSAND = 1000L; + private static final IgniteLogger LOGGER = IgniteLoggerFactory.getLogger(HealthServiceUnitTest.class); + @Rule + public MockitoRule mockitoRule = MockitoJUnit.rule(); + @InjectMocks + private HealthService healthService = new HealthService(); + + @Mock + private IgniteHealthGuage serviceHealthGuage; + @Mock + private ThreadUtils threadUtils; + + /** + * Setup the test. + */ + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + healthService.setServiceHealthGuage(serviceHealthGuage); + healthService.setFailureRetryInterval(HUNDRED); + healthService.setFailureRetryThreshold(TWO); + healthService.setRetryInterval(HUNDRED); + healthService.setNodeName("localhost"); + } + + /** + * HealthMonitor used simple TestHealthMonitor; + * Count = 2; Both healthMonitors are enabled; Both healthMonitors are set healthy ; Force + * is set to false; + * Expecting success. + */ + @Test + public void testCheckHealthAndGetFailedMonitorsWithForceFalse() { + final List hms = new ArrayList<>(); + TestHealthMonitor hm = new TestHealthMonitor(); + hm.setEnabled(true); + hm.setMetricName("Metric1"); + hm.setMonitorName("Monitor1"); + hm.setHealthy(true); + hms.add(hm); + + TestHealthMonitor hm2 = new TestHealthMonitor(); + hm2.setEnabled(true); + hm2.setMetricName("Metric2"); + hm2.setMonitorName("Monitor2"); + hm2.setHealthy(true); + hms.add(hm2); + + healthService.setHealthMonitors(hms); + healthService.init(); + List enabledHms = healthService.getHealthMonitors(); + Assert.assertEquals(TWO, enabledHms.size()); + boolean force = false; + + // Validate Failed hms should be 0 + List failedHms = healthService.checkHealthAndGetFailedMonitors(force, hms); + Assert.assertEquals(0, failedHms.size()); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(HEALTHY, "localhost", "Metric1"); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(HEALTHY, "localhost", "Metric2"); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(HEALTHY, "localhost", SERVICE_HEALTH); + } + + /** + * HealthMonitor used simple TestHealthMonitor; + * Count = 2; Both healthMonitors are enabled; Both healthMonitors are set healthy ; Force + * is set to false; + * Expecting success. + */ + @Test + public void testCheckHealthAndGetFailedMonitorsWithForceFalseWithPromethus() { + Enumeration allSamples = CollectorRegistry.defaultRegistry.metricFamilySamples(); + final List hms = new ArrayList<>(); + TestHealthMonitor hm = new TestHealthMonitor(); + hm.setEnabled(true); + hm.setMetricName("Metric1"); + hm.setMonitorName("Monitor1"); + hm.setHealthy(true); + hms.add(hm); + + TestHealthMonitor hm2 = new TestHealthMonitor(); + hm2.setEnabled(true); + hm2.setMetricName("Metric2"); + hm2.setMonitorName("Monitor2"); + hm2.setHealthy(true); + hms.add(hm2); + + healthService.setHealthMonitors(hms); + healthService.init(); + List enabledHms = healthService.getHealthMonitors(); + Assert.assertEquals(TWO, enabledHms.size()); + boolean force = false; + + // Validate Failed hms should be 0 + List failedHms = healthService.checkHealthAndGetFailedMonitors(force, hms); + Assert.assertEquals(0, failedHms.size()); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(HEALTHY, "localhost", "Metric1"); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(HEALTHY, "localhost", "Metric2"); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(HEALTHY, "localhost", SERVICE_HEALTH); + + } + + /** + * HealthMonitor used simple TestHealthMonitor; + * Count = 2; Both healthMonitors are enabled; HealthMonitor 1 is set healthy ; + * HealthMonitor 2 is set to unhealthy ; Force is set to false; + * As one health monitor is not healthy we are expecting one failed health monitor
+ * Expecting failure. + */ + @Test + public void testCheckHealthAndGetFailedMonitorsWithForceFalseWhenOneMonitorIsUnHealthy() { + final List hms = new ArrayList<>(); + TestHealthMonitor hm = new TestHealthMonitor(); + hm.setEnabled(true); + hm.setMetricName("Metric1"); + hm.setMonitorName("Monitor1"); + hm.setHealthy(true); + hms.add(hm); + + TestHealthMonitor hm2 = new TestHealthMonitor(); + hm2.setEnabled(true); + hm2.setMetricName("Metric2"); + hm2.setMonitorName("Monitor2"); + hm2.setHealthy(false); + hms.add(hm2); + + healthService.setHealthMonitors(hms); + healthService.init(); + List enabledHms = healthService.getHealthMonitors(); + Assert.assertEquals(TWO, enabledHms.size()); + boolean force = false; + + // Validate Failed hms should be 1 + List failedHms = healthService.checkHealthAndGetFailedMonitors(force, hms); + Assert.assertEquals(1, failedHms.size()); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(HEALTHY, "localhost", "Metric1"); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(UNHEALTHY, "localhost", "Metric2"); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(UNHEALTHY, "localhost", SERVICE_HEALTH); + } + + /** + * HealthMonitor used simple TestHealthMonitor; + * Count = 2; Both healthMonitors are enabled; Both HealthMonitors are set healthy ; Force + * is set to true; + * As both health monitors are healthy setting force to true or false should not have any impact + * Expecting success. + */ + @Test + public void testCheckHealthAndGetFailedMonitorsWithForceTrueWhenHealthMonitorsAreHealthy() { + final List hms = new ArrayList<>(); + TestHealthMonitor hm = new TestHealthMonitor(); + hm.setEnabled(true); + hm.setMetricName("Metric1"); + hm.setMonitorName("Monitor1"); + hm.setHealthy(true); + hms.add(hm); + + TestHealthMonitor hm2 = new TestHealthMonitor(); + hm2.setEnabled(true); + hm2.setMetricName("Metric2"); + hm2.setMonitorName("Monitor2"); + hm2.setHealthy(true); + hms.add(hm2); + + healthService.setHealthMonitors(hms); + healthService.init(); + List enabledHms = healthService.getHealthMonitors(); + Assert.assertEquals(TWO, enabledHms.size()); + boolean force = true; + + // Validate Failed hms should be 0 + List failedHms = healthService.checkHealthAndGetFailedMonitors(force, hms); + Assert.assertEquals(0, failedHms.size()); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(HEALTHY, "localhost", "Metric1"); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(HEALTHY, "localhost", "Metric2"); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(HEALTHY, "localhost", SERVICE_HEALTH); + } + + /** + * Here we are using two types of health monitors TestHealthMonitor and TestHealthMonitorWithForce. + * Both healthMonitors are enabled; + * Both HealthMonitors are set healthy ; Force is set to true; + * As one is unhealthy and force is true we will be retrying. + * Expecting success after retrying. + */ + @Test + public void testCheckHealthAndGetFailedMonitorsWithForceTrueWhenHealthMonitorsAreUnHealthy() { + final List hms = new ArrayList<>(); + TestHealthMonitorWithForce hm = new TestHealthMonitorWithForce(); + hm.setEnabled(true); + hm.setMetricName("Metric1"); + hm.setMonitorName("Monitor1"); + hm.setHealthy(true); + hms.add(hm); + + TestHealthMonitor hm2 = new TestHealthMonitor(); + hm2.setEnabled(true); + hm2.setMetricName("Metric2"); + hm2.setMonitorName("Monitor2"); + hm2.setHealthy(true); + hms.add(hm2); + + healthService.setHealthMonitors(hms); + healthService.init(); + List enabledHms = healthService.getHealthMonitors(); + Assert.assertEquals(TWO, enabledHms.size()); + boolean force = true; + healthService.checkHealthAndGetFailedMonitors(force, hms); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(UNHEALTHY, "localhost", "Metric1"); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(HEALTHY, "localhost", "Metric2"); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(UNHEALTHY, "localhost", SERVICE_HEALTH); + + healthService.checkHealthAndGetFailedMonitors(force, hms); + Mockito.verify(serviceHealthGuage, Mockito.times(TWO)) + .set(UNHEALTHY, "localhost", "Metric1"); + Mockito.verify(serviceHealthGuage, Mockito.times(TWO)) + .set(HEALTHY, "localhost", "Metric2"); + Mockito.verify(serviceHealthGuage, Mockito.times(TWO)) + .set(UNHEALTHY, "localhost", SERVICE_HEALTH); + + healthService.checkHealthAndGetFailedMonitors(force, hms); + Mockito.verify(serviceHealthGuage, Mockito.times(THREE)) + .set(UNHEALTHY, "localhost", "Metric1"); + Mockito.verify(serviceHealthGuage, Mockito.times(THREE)) + .set(HEALTHY, "localhost", "Metric2"); + Mockito.verify(serviceHealthGuage, Mockito.times(THREE)) + .set(UNHEALTHY, "localhost", SERVICE_HEALTH); + + healthService.checkHealthAndGetFailedMonitors(force, hms); + Mockito.verify(serviceHealthGuage, Mockito.times(FOUR)) + .set(UNHEALTHY, "localhost", "Metric1"); + Mockito.verify(serviceHealthGuage, Mockito.times(FOUR)) + .set(HEALTHY, "localhost", "Metric2"); + Mockito.verify(serviceHealthGuage, Mockito.times(FOUR)) + .set(UNHEALTHY, "localhost", SERVICE_HEALTH); + + healthService.checkHealthAndGetFailedMonitors(force, hms); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(HEALTHY, "localhost", "Metric1"); + Mockito.verify(serviceHealthGuage, Mockito.times(FIVE)) + .set(HEALTHY, "localhost", "Metric2"); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(HEALTHY, "localhost", SERVICE_HEALTH); + + } + + /** + * HealthMonitor used simple TestHealthMonitor; + * Count = 2; Both healthMonitors are enabled; HealthMonitor 1 is set healthy ; + * HealthMonitor 2 is set to unhealthy ; + *
+ * As one health monitor is unhealthy we are expecting failure not have any impact + *
+ * Expecting failure. + */ + @Test + public void testTriggerInitialCheck() { + final List hms = new ArrayList<>(); + TestHealthMonitor hm = new TestHealthMonitor(); + hm.setEnabled(true); + hm.setMetricName("Metric1"); + hm.setMonitorName("Monitor1"); + hm.setHealthy(true); + hms.add(hm); + + TestHealthMonitor hm2 = new TestHealthMonitor(); + hm2.setEnabled(true); + hm2.setMetricName("Metric2"); + hm2.setMonitorName("Monitor2"); + hm2.setHealthy(false); + hms.add(hm2); + + healthService.setHealthMonitors(hms); + healthService.init(); + List enabledHms = healthService.getHealthMonitors(); + Assert.assertEquals(TWO, enabledHms.size()); + + List failedList = healthService.triggerInitialCheck(); + Assert.assertEquals(1, failedList.size()); + + Assert.assertEquals("Metric2", failedList.get(0).metricName()); + Assert.assertEquals("Monitor2", failedList.get(0).monitorName()); + + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(HEALTHY, "localhost", "Metric1"); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(UNHEALTHY, "localhost", "Metric2"); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(UNHEALTHY, "localhost", SERVICE_HEALTH); + + hms.clear(); + hm2.setHealthy(true); + hms.add(hm2); + healthService.setHealthMonitors(hms); + healthService.init(); + List list = healthService.triggerInitialCheck(); + Assert.assertEquals(0, list.size()); + } + + @Test + public void testClose() { + final List hms = new ArrayList<>(); + TestHealthMonitor hm = new TestHealthMonitor(); + hm.setEnabled(true); + hm.setMetricName("Metric1"); + hm.setMonitorName("Monitor1"); + hm.setHealthy(true); + hms.add(hm); + + TestHealthMonitor hm2 = new TestHealthMonitor(); + hm2.setEnabled(true); + hm2.setMetricName("Metric2"); + hm2.setMonitorName("Monitor2"); + hm2.setHealthy(false); + hms.add(hm2); + + healthService.setHealthMonitors(hms); + healthService.init(); + healthService.close(); + + Assert.assertFalse(healthService.isStartedExecutor()); + } + + @Test + public void testRegisterCallback() { + TestHealthMonitor hm = new TestHealthMonitor(); + healthService.registerCallBack(hm); + + Assert.assertNotNull(healthService.getCallback()); + } + + /** + * Here we are using two types of health monitors TestHealthMonitor and TestHealthMonitorWithForce. + * Both healthMonitors are enabled; + * Both HealthMonitors are set healthy ; + *
+ * As both are healthy it is a success scenario + *
+ * Expecting success. + */ + @Test + public void testNeedsRestartFalseScenario() throws InterruptedException { + healthService.setFailureRetryThreshold(SEVEN); + final List hms = new ArrayList(); + TestHealthMonitorWithForce hm = new TestHealthMonitorWithForce(); + hm.setEnabled(true); + hm.setMetricName("Metric1"); + hm.setMonitorName("Monitor1"); + hm.setHealthy(true); + hm.setNeedsRestartOnFailure(true); + hms.add(hm); + + TestHealthMonitor hm2 = new TestHealthMonitor(); + hm2.setEnabled(true); + hm2.setMetricName("Metric2"); + hm2.setMonitorName("Monitor2"); + hm2.setHealthy(true); + hm2.setNeedsRestartOnFailure(true); + hms.add(hm2); + + healthService.setHealthMonitors(hms); + healthService.init(); + List enabledHms = healthService.getHealthMonitors(); + Assert.assertEquals(TWO, enabledHms.size()); + + boolean restart = healthService.needsRestart(); + Assert.assertFalse(restart); + + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(HEALTHY, "localhost", "Metric1"); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(HEALTHY, "localhost", "Metric2"); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(HEALTHY, "localhost", SERVICE_HEALTH); + + } + + /** + * Objective is to test the retry threshold of health service. + * The method needsRestart will repeat in a loop until the retry threshold is exceeded; + * or before that the service becomes healthy. Testing with retry threshold 5. + *
+ * The health monitor TestHealthMonitorWithForce will give true after 3 attempts with force true + * As both are healthy it is a success scenario. + * Hence, for retry threshold > 4 we should get healthy + *
+ *
+ * Expecting success after retry. + */ + @Test + public void testNeedsRestartFalseScenarioWithRetry() throws InterruptedException { + healthService.setFailureRetryThreshold(FIVE); + final List hms = new ArrayList<>(); + TestHealthMonitorWithForce hm = new TestHealthMonitorWithForce(); + hm.setEnabled(true); + hm.setMetricName("Metric1"); + hm.setMonitorName("Monitor1"); + hm.setNeedsRestartOnFailure(true); + hms.add(hm); + + TestHealthMonitor hm2 = new TestHealthMonitor(); + hm2.setEnabled(true); + hm2.setMetricName("Metric2"); + hm2.setMonitorName("Monitor2"); + hm2.setHealthy(true); + hm2.setNeedsRestartOnFailure(true); + hms.add(hm2); + + healthService.setHealthMonitors(hms); + healthService.init(); + List enabledHms = healthService.getHealthMonitors(); + Assert.assertEquals(TWO, enabledHms.size()); + + boolean restart = healthService.needsRestart(); + Assert.assertFalse(restart); + + Mockito.verify(serviceHealthGuage, Mockito.times(FIVE)) + .set(UNHEALTHY, "localhost", "Metric1"); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(HEALTHY, "localhost", "Metric2"); + Mockito.verify(serviceHealthGuage, Mockito.times(FIVE)) + .set(UNHEALTHY, "localhost", SERVICE_HEALTH); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(HEALTHY, "localhost", SERVICE_HEALTH); + + } + + /** + * Objective is to test the retry threshold of health service. + * The method needsRestart will repeat in a loop until the retry threshold is exceeded; + * or before that the service becomes healthy. Testing with retry threshold 5. + *
+ * The health monitor TestHealthMonitorWithForce will give true after 3 attempts with force true + * As both are healthy it is a success scenario. + * Hence, for retry threshold > 4 we should get healthy + *
+ *
+ * Expecting failure as retry threshold == 4 + */ + + @Test + public void testNeedsRestartTrueScenario() throws InterruptedException { + healthService.setFailureRetryThreshold(FOUR); + final List hms = new ArrayList<>(); + TestHealthMonitorWithForce hm = new TestHealthMonitorWithForce(); + hm.setEnabled(true); + hm.setMetricName("Metric1"); + hm.setMonitorName("Monitor1"); + hm.setNeedsRestartOnFailure(true); + hms.add(hm); + + TestHealthMonitor hm2 = new TestHealthMonitor(); + hm2.setEnabled(true); + hm2.setMetricName("Metric2"); + hm2.setMonitorName("Monitor2"); + hm2.setHealthy(true); + hm2.setNeedsRestartOnFailure(true); + hms.add(hm2); + + healthService.setHealthMonitors(hms); + healthService.init(); + List enabledHms = healthService.getHealthMonitors(); + Assert.assertEquals(TWO, enabledHms.size()); + + boolean restart = healthService.needsRestart(); + Assert.assertTrue(restart); + + Mockito.verify(serviceHealthGuage, Mockito.times(FIVE)) + .set(UNHEALTHY, "localhost", "Metric1"); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(HEALTHY, "localhost", "Metric2"); + Mockito.verify(serviceHealthGuage, Mockito.times(FIVE)) + .set(UNHEALTHY, "localhost", SERVICE_HEALTH); + } + + /** + * If a health monitor needs restart is false. + * Even if it is unhealthy the service should return restart false. + */ + @Test + public void testNeedsRestartFalseScenarioWithMonitorRestartFalse() throws InterruptedException { + healthService.setFailureRetryThreshold(FOUR); + final List hms = new ArrayList<>(); + TestHealthMonitorWithForce hm = new TestHealthMonitorWithForce(); + hm.setEnabled(true); + hm.setMetricName("Metric1"); + hm.setMonitorName("Monitor1"); + hm.setNeedsRestartOnFailure(false); + hms.add(hm); + + TestHealthMonitor hm2 = new TestHealthMonitor(); + hm2.setEnabled(true); + hm2.setMetricName("Metric2"); + hm2.setMonitorName("Monitor2"); + hm2.setHealthy(true); + hm2.setNeedsRestartOnFailure(true); + hms.add(hm2); + + healthService.setHealthMonitors(hms); + healthService.init(); + List enabledHms = healthService.getHealthMonitors(); + Assert.assertEquals(TWO, enabledHms.size()); + + boolean restart = healthService.needsRestart(); + Assert.assertFalse(restart); + + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(UNHEALTHY, "localhost", "Metric1"); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(HEALTHY, "localhost", "Metric2"); + Mockito.verify(serviceHealthGuage, Mockito.times(1)) + .set(UNHEALTHY, "localhost", SERVICE_HEALTH); + } + + /** + * If two health monitors have same name it should throw runtime exception. + */ + @Test(expected = RuntimeException.class) + public void testInitTwoMonitorsWithSameName() { + final List hms = new ArrayList<>(); + TestHealthMonitor hm = new TestHealthMonitor(); + hm.setEnabled(true); + hm.setMetricName("Metric1"); + hm.setMonitorName("Monitor1"); + hms.add(hm); + + TestHealthMonitor hm2 = new TestHealthMonitor(); + hm2.setEnabled(true); + hm2.setMetricName("Metric1"); + hm2.setMonitorName("Monitor2"); + hms.add(hm2); + + healthService.setHealthMonitors(hms); + healthService.init(); + } + + /** + * If a health monitor is disabled, it should not be added in the list of health monitors. + */ + @Test + public void testInitWithDisabledMonitor() { + final List hms = new ArrayList<>(); + TestHealthMonitor hm = new TestHealthMonitor(); + hm.setEnabled(true); + hm.setMetricName("Metric1"); + hm.setMonitorName("Monitor1"); + hms.add(hm); + + TestHealthMonitor hm2 = new TestHealthMonitor(); + hm2.setEnabled(false); + hm2.setMetricName("Metric2"); + hm2.setMonitorName("Monitor2"); + hms.add(hm2); + + healthService.setHealthMonitors(hms); + healthService.init(); + + List enabledHms = healthService.getHealthMonitors(); + Assert.assertEquals(1, enabledHms.size()); + Assert.assertEquals("Metric1", enabledHms.get(0).metricName()); + Assert.assertEquals("Monitor1", enabledHms.get(0).monitorName()); + } + + @Test + public void testStartHealthServiceExecutor() throws InterruptedException { + final List hms = new ArrayList<>(); + TestHealthMonitor hm = new TestHealthMonitor(); + hm.setEnabled(true); + hm.setMetricName("Metric1"); + hm.setMonitorName("Monitor1"); + hm.setHealthy(true); + hms.add(hm); + + TestHealthMonitor hm2 = new TestHealthMonitor(); + hm2.setEnabled(true); + hm2.setMetricName("Metric2"); + hm2.setMonitorName("Monitor2"); + hm2.setHealthy(true); + hms.add(hm2); + + healthService.setHealthMonitors(hms); + healthService.init(); + healthService.startHealthServiceExecutor(); + LOGGER.info("Started health service"); + Thread.sleep(THOUSAND); + healthService.startHealthServiceExecutor(); + List enabledHms = healthService.getHealthMonitors(); + Assert.assertEquals(TWO, enabledHms.size()); + LOGGER.info("Started again health service"); + } +} diff --git a/src/test/java/com/harman/ignite/healthcheck/TestHealthMonitor.java b/src/test/java/com/harman/ignite/healthcheck/TestHealthMonitor.java new file mode 100644 index 0000000..1fffe88 --- /dev/null +++ b/src/test/java/com/harman/ignite/healthcheck/TestHealthMonitor.java @@ -0,0 +1,102 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.healthcheck; + +/** + * Test POJO class for HealthMonitor. + * + * @see HealthMonitor + */ +public class TestHealthMonitor implements HealthMonitor, HealthServiceCallBack { + + private boolean healthy; + private boolean needsRestartOnFailure; + private boolean enabled; + private String monitorName = "TestHealthMonitor"; + private String metricName = "TestHealthMonitorGuage"; + + @Override + public boolean isHealthy(boolean forceHealthCheck) { + return healthy; + } + + @Override + public boolean needsRestartOnFailure() { + return needsRestartOnFailure; + } + + @Override + public boolean performRestart() { + return false; + } + + public void setNeedsRestartOnFailure(boolean needsRestartOnFailure) { + this.needsRestartOnFailure = needsRestartOnFailure; + } + + public void setHealthy(boolean healthy) { + this.healthy = healthy; + } + + @Override + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + @Override + public String monitorName() { + return monitorName; + } + + public void setMonitorName(String monitorName) { + this.monitorName = monitorName; + } + + @Override + public String metricName() { + return metricName; + } + + public void setMetricName(String metricName) { + this.metricName = metricName; + } + +} diff --git a/src/test/java/com/harman/ignite/healthcheck/TestHealthMonitorWithForce.java b/src/test/java/com/harman/ignite/healthcheck/TestHealthMonitorWithForce.java new file mode 100644 index 0000000..ebe2001 --- /dev/null +++ b/src/test/java/com/harman/ignite/healthcheck/TestHealthMonitorWithForce.java @@ -0,0 +1,105 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.healthcheck; + +/** Test POJO class for HealthMonitor with force health check. + * + * @see HealthMonitor + */ +public class TestHealthMonitorWithForce implements HealthMonitor { + + private static final int THREE = 3; + private boolean healthy; + private boolean needsRestartOnFailure; + private boolean enabled; + private String monitorName = "TestHealthMonitorWithForce"; + private String metricName = "TestHealthMonitorWithForceGuage"; + @SuppressWarnings("checkstyle:MemberName") + private int i = 0; + + @Override + public boolean isHealthy(boolean forceHealthCheck) { + if (i > THREE) { + return true; + } + if (forceHealthCheck) { + i++; + } + return false; + } + + @Override + public String monitorName() { + return monitorName; + } + + @Override + public boolean needsRestartOnFailure() { + return needsRestartOnFailure; + } + + @Override + public String metricName() { + return metricName; + } + + @Override + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public void setHealthy(boolean healthy) { + this.healthy = healthy; + } + + public void setNeedsRestartOnFailure(boolean needsRestartOnFailure) { + this.needsRestartOnFailure = needsRestartOnFailure; + } + + public void setMonitorName(String monitorName) { + this.monitorName = monitorName; + } + + public void setMetricName(String metricName) { + this.metricName = metricName; + } + +} diff --git a/src/test/java/com/harman/ignite/healthcheck/TestHealthServiceConfig.java b/src/test/java/com/harman/ignite/healthcheck/TestHealthServiceConfig.java new file mode 100644 index 0000000..5eaa9af --- /dev/null +++ b/src/test/java/com/harman/ignite/healthcheck/TestHealthServiceConfig.java @@ -0,0 +1,86 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.healthcheck; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +/** Test configuration for initializing TestHealthMonitor and TestHealthMonitorWithForce beans. + * + * @see HealthServiceStateTest + */ +@Configuration +@ComponentScan(basePackages = { "com.harman.ignite" }) +public class TestHealthServiceConfig { + + /** Bean for TestHealthMonitor. + * + * @return TestHealthMonitor + */ + @Bean + public TestHealthMonitor testHealthMonitor() { + TestHealthMonitor monitor1 = new TestHealthMonitor(); + monitor1.setEnabled(true); + return monitor1; + } + + /** Bean for TestHealthMonitor. + * This should be skipped at the time of init of healthservice as enabled is false. + * + * @return TestHealthMonitor + */ + @Bean + public TestHealthMonitor testHealthMonitor2() { + TestHealthMonitor monitor1 = new TestHealthMonitor(); + monitor1.setEnabled(false); + return monitor1; + } + + /** + * Bean for TestHealthMonitorWithForce. + * + * @return TestHealthMonitorWithForce + */ + @Bean + public TestHealthMonitorWithForce testHealthMonitorWithForce() { + TestHealthMonitorWithForce monitor1 = new TestHealthMonitorWithForce(); + monitor1.setEnabled(true); + return monitor1; + } + +} diff --git a/src/test/java/com/harman/ignite/utils/filter/TestDuplicateExceptionFilter.java b/src/test/java/com/harman/ignite/utils/filter/TestDuplicateExceptionFilter.java new file mode 100644 index 0000000..f6eeba0 --- /dev/null +++ b/src/test/java/com/harman/ignite/utils/filter/TestDuplicateExceptionFilter.java @@ -0,0 +1,118 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.filter; + +import ch.qos.logback.classic.turbo.TurboFilter; +import ch.qos.logback.core.spi.FilterReply; +import com.harman.ignite.utils.logger.LoggerUtils; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.concurrent.ConcurrentHashMap; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * This test case is used to test the filter DuplicateExceptionFilter. + * + * @author vkoul + */ +public class TestDuplicateExceptionFilter { + + private static final long SIXTY_THOUSAND = 60000L; + private static final long LONG_VALUE_FOR_LOGGER = 2628077220L; + private static final Logger LOGGER = LoggerFactory.getLogger(TestDuplicateExceptionFilter.class); + private DuplicateExceptionFilter def = null; + @Mock + private LoggerUtils loggerUtils; + + /** + * Setup the test. + */ + @Before + public void setUp() { + def = new DuplicateExceptionFilter(); + def.setSuppressTimeInMs(SIXTY_THOUSAND); + def.start(); + } + + /** + * This test case calls decide() twice within a minute. + *
+ * First invocation to decide() should return NEUTRAL whereas the next invocation should return DENY, + * as it is occurring within a minute, for which suppression should happen. + */ + @Test + public void testExceptionSuppressed() { + + assertThat(logMessage(def, new IOException())).isEqualTo(FilterReply.NEUTRAL); + + // Now, next log is within one minute, so it should be DENY + assertThat(logMessage(def, new IOException())).isEqualTo(FilterReply.DENY); + assertThat(def.decide(null, (ch.qos.logback.classic.Logger) LOGGER, + null, + "", + new Object[] { new IOException() }, null)) + .isEqualTo(FilterReply.DENY); + + ConcurrentHashMap exceptionCache = new ConcurrentHashMap<>(); + exceptionCache.put(IOException.class.getName() + LOGGER.toString(), LONG_VALUE_FOR_LOGGER); + def.setExceptionCache(exceptionCache); + + assertThat(logMessage(def, new IOException())).isEqualTo(FilterReply.NEUTRAL); + } + + @Test + public void testGetSuppressTimeInMs() { + Assert.assertEquals(SIXTY_THOUSAND, def.getSuppressTimeInMs()); + } + + @After + public void tearDown() { + def.stop(); + } + + private FilterReply logMessage(final TurboFilter def, Throwable t) { + return def.decide(null, (ch.qos.logback.classic.Logger) LOGGER, null, null, null, t); + } +} \ No newline at end of file diff --git a/src/test/java/com/harman/ignite/utils/logger/EventLogger1.java b/src/test/java/com/harman/ignite/utils/logger/EventLogger1.java new file mode 100644 index 0000000..54b21d1 --- /dev/null +++ b/src/test/java/com/harman/ignite/utils/logger/EventLogger1.java @@ -0,0 +1,57 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.logger; + +/** Thread class for EventLogger1. + * + * @author AKumar + */ +public class EventLogger1 implements Runnable { + private static IgniteLogger igniteLogger = IgniteLoggerFactory.getLogger(EventLogger1.class); + + public static IgniteLogger getIgniteLogger() { + return igniteLogger; + } + + @Override + public void run() { + igniteLogger.info("Info message from EventLogger1"); + igniteLogger.trace("Info message from EventLogger1"); + igniteLogger.debug("Info message from EventLogger1"); + igniteLogger.error("Error message from EventLogger1", new Exception("exception occurred")); + } +} diff --git a/src/test/java/com/harman/ignite/utils/logger/EventLogger2.java b/src/test/java/com/harman/ignite/utils/logger/EventLogger2.java new file mode 100644 index 0000000..d9eb8f7 --- /dev/null +++ b/src/test/java/com/harman/ignite/utils/logger/EventLogger2.java @@ -0,0 +1,55 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.logger; + +/** Thread class for EventLogger2. + * + * @author AKumar + */ +public class EventLogger2 implements Runnable { + + private static IgniteLogger igniteLogger = IgniteLoggerFactory.getLogger(EventLogger2.class); + + @Override + public void run() { + igniteLogger.info("Info message from EventLogger2"); + igniteLogger.trace("Info message from EventLogger2"); + igniteLogger.debug("Info message from EventLogger2"); + igniteLogger.error("Error message from EventLogger2", new Exception("exception occurred")); + } + +} diff --git a/src/test/java/com/harman/ignite/utils/logger/IgniteLoggerFactoryTest.java b/src/test/java/com/harman/ignite/utils/logger/IgniteLoggerFactoryTest.java new file mode 100644 index 0000000..51d25ca --- /dev/null +++ b/src/test/java/com/harman/ignite/utils/logger/IgniteLoggerFactoryTest.java @@ -0,0 +1,55 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.logger; + +import org.junit.Assert; +import org.junit.Test; +import org.mockito.MockitoAnnotations; + +/** Test class for IgniteLoggerFactory. + * + * @see IgniteLoggerFactory + */ +public class IgniteLoggerFactoryTest { + + @Test + public void testGetLogger() { + MockitoAnnotations.initMocks(this); + IgniteLogger logger = IgniteLoggerFactory.getLogger(EventLogger1.class); + Assert.assertTrue(logger instanceof IgniteLoggerImpl); + } +} diff --git a/src/test/java/com/harman/ignite/utils/logger/TestIgniteLogger.java b/src/test/java/com/harman/ignite/utils/logger/TestIgniteLogger.java new file mode 100644 index 0000000..860bffc --- /dev/null +++ b/src/test/java/com/harman/ignite/utils/logger/TestIgniteLogger.java @@ -0,0 +1,358 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.logger; + +import com.harman.ignite.entities.IgniteEvent; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.ArgumentMatchers; +import org.mockito.Mockito; +import org.slf4j.Logger; + +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; + +/** + * Test class for IgniteLogger. + * + * @author AKumar + */ + +public class TestIgniteLogger { + private static final int TWO = 2; + private static IgniteLoggerImpl igniteLogger = + IgniteLoggerImpl.getIgniteLoggerImplInstance(EventLogger2.class); + Logger logger; + + /** + * Setup method. + */ + @Before + public void setup() { + logger = Mockito.mock(Logger.class); + when(logger.isTraceEnabled()).thenReturn(true); + when(logger.isDebugEnabled()).thenReturn(true); + when(logger.isInfoEnabled()).thenReturn(true); + igniteLogger.setLogger(logger); + } + + @Test + public void testIgniteLoggersInMap() { + Thread igniteEventTh1 = new Thread(new EventLogger1(), "EventLogger1"); + Thread igniteEventTh2 = new Thread(new EventLogger2(), "EventLogger2"); + igniteEventTh1.start(); + igniteEventTh2.start(); + + Map igniteLoggersMap = igniteLogger.getIgniteLoggersMap(); + assertEquals(TWO, igniteLoggersMap.size()); + Assert.assertTrue(igniteLoggersMap.containsKey(EventLogger1.class.getName())); + Assert.assertTrue(igniteLoggersMap.containsKey(EventLogger2.class.getName())); + } + + @Test + public void testInfo() { + ArgumentCaptor arg = ArgumentCaptor.forClass(String.class); + igniteLogger.info("InfoWithMsg"); + Mockito.verify(logger).info(arg.capture()); + assertEquals("InfoWithMsg", arg.getValue()); + } + + @Test + public void testInfoWithMsgAndThrowable() { + igniteLogger.info("InfoWithMsgAndThrowable", new Throwable()); + Mockito.verify(logger).info(Mockito.eq("InfoWithMsgAndThrowable"), Mockito.any()); + } + + @Test + public void testInfoWithFormatNArgs() { + igniteLogger.info("Display message as: parameter1={}", "value1"); + Mockito.verify(logger) + .info( + ArgumentMatchers.contains("Display message as: parameter1={}"), + ArgumentMatchers.any()); + } + + @Test + public void testInfoWithIgniteEvent() { + IgniteEvent igniteEvent = Mockito.mock(IgniteEvent.class); + igniteLogger.info(igniteEvent, "InfoWithMsgAndThrowable"); + Mockito.verify(logger).info(ArgumentMatchers.endsWith("InfoWithMsgAndThrowable")); + } + + @Test + public void testInfoWithIgniteEventNMsgNThrowable() { + IgniteEvent igniteEvent = Mockito.mock(IgniteEvent.class); + igniteLogger.info(igniteEvent, "InfoWithIgniteEventnMsgnThrowable", new Throwable()); + Mockito.verify(logger).info(Mockito.endsWith("InfoWithIgniteEventnMsgnThrowable"), Mockito.any()); + } + + @Test + public void testInfoWithIgniteEventNFormatNargs() { + IgniteEvent igniteEvent = Mockito.mock(IgniteEvent.class); + igniteLogger.info(igniteEvent, "Display message as: parameter1={} parameter2={}", "value1", new Object()); + Mockito.verify(logger) + .info( + ArgumentMatchers.contains("Display message as: parameter1={}"), + ArgumentMatchers.any()); + + } + + @Test + public void testInfoWithIgniteEventAndCorrId() { + IgniteEvent igniteEvent = Mockito.mock(IgniteEvent.class); + Mockito.when(igniteEvent.getCorrelationId()).thenReturn("correlationIdMock"); + igniteLogger.info(igniteEvent, "InfoWithMsgAndThrowable"); + Mockito.verify(logger).info(Mockito.contains("InfoWithMsgAndThrowable")); + } + + @Test + public void testDebug() { + ArgumentCaptor arg = ArgumentCaptor.forClass(String.class); + igniteLogger.debug("DebugWithMsg"); + Mockito.verify(logger).debug(arg.capture()); + assertEquals("DebugWithMsg", arg.getValue()); + } + + @Test + public void testDebugWithMsgAndThrowable() { + igniteLogger.debug("DebugWithMsgAndThrowable", new Throwable()); + Mockito.verify(logger).debug(Mockito.eq("DebugWithMsgAndThrowable"), Mockito.any()); + } + + @Test + public void testDebugWithFormatNArgs() { + igniteLogger.debug("Display message as: parameter1={}", "value1"); + Mockito.verify(logger) + .debug( + ArgumentMatchers.contains("Display message as: parameter1={}"), + ArgumentMatchers.any()); + + } + + @Test + public void testDebugWithIgniteEvent() { + IgniteEvent igniteEvent = Mockito.mock(IgniteEvent.class); + igniteLogger.debug(igniteEvent, "DebugWithMsgAndThrowable"); + Mockito.verify(logger).debug(ArgumentMatchers.endsWith("DebugWithMsgAndThrowable")); + } + + @Test + public void testDebugWithIgniteEventnMsgNThrowable() { + IgniteEvent igniteEvent = Mockito.mock(IgniteEvent.class); + igniteLogger.debug(igniteEvent, "DebugWithIgniteEventnMsgnThrowable", new Throwable()); + Mockito.verify(logger) + .debug( + Mockito.endsWith("DebugWithIgniteEventnMsgnThrowable"), + Mockito.any()); + } + + @Test + public void testDebugWithIgniteEventNFormatNargs() { + IgniteEvent igniteEvent = Mockito.mock(IgniteEvent.class); + igniteLogger.debug(igniteEvent, "Display message as: parameter1={} parameter2={}", "value1", new Object()); + Mockito.verify(logger).debug(ArgumentMatchers.endsWith("Display message as: parameter1={} parameter2={}"), + ArgumentMatchers.any()); + } + + @Test + public void testWarn() { + ArgumentCaptor arg = ArgumentCaptor.forClass(String.class); + igniteLogger.warn("WarnWithMsg"); + Mockito.verify(logger).warn(arg.capture()); + assertEquals("WarnWithMsg", arg.getValue()); + } + + @Test + public void testWarnWithMsgAndThrowable() { + igniteLogger.warn("WarnWithMsgAndThrowable", new Throwable()); + Mockito.verify(logger).warn(Mockito.eq("WarnWithMsgAndThrowable"), Mockito.any()); + } + + @Test + public void testWarnWithFormatNArgs() { + igniteLogger.warn("Display message as: parameter1={}", "value1"); + Mockito.verify(logger) + .warn( + ArgumentMatchers.endsWith("Display message as: parameter1={}"), + ArgumentMatchers.any()); + + } + + @Test + public void testWarnWithIgniteEvent() { + IgniteEvent igniteEvent = Mockito.mock(IgniteEvent.class); + igniteLogger.warn(igniteEvent, "WarnWithMsgAndThrowable"); + Mockito.verify(logger).warn(Mockito.endsWith("WarnWithMsgAndThrowable")); + } + + @Test + public void testWarnWithIgniteEventNMsgNThrowable() { + IgniteEvent igniteEvent = Mockito.mock(IgniteEvent.class); + igniteLogger.warn(igniteEvent, "WarnWithIgniteEventnMsgnThrowable", new Throwable()); + Mockito.verify(logger) + .warn( + Mockito.endsWith("WarnWithIgniteEventnMsgnThrowable"), + Mockito.any()); + } + + @Test + public void testWarnWithIgniteEventNFormatNargs() { + IgniteEvent igniteEvent = Mockito.mock(IgniteEvent.class); + igniteLogger.warn(igniteEvent, "Display message as: parameter1={} parameter2={}", "value1", new Object()); + Mockito.verify(logger) + .warn( + ArgumentMatchers.endsWith("Display message as: parameter1={} parameter2={}"), + ArgumentMatchers.any()); + + } + + @Test + public void testTrace() { + ArgumentCaptor arg = ArgumentCaptor.forClass(String.class); + igniteLogger.trace("TraceWithMsg"); + Mockito.verify(logger).trace(arg.capture()); + assertEquals("TraceWithMsg", arg.getValue()); + } + + @Test + public void testTraceWithMsgAndThrowable() { + igniteLogger.trace("TraceWithMsgAndThrowable", new Throwable()); + Mockito.verify(logger).trace(Mockito.eq("TraceWithMsgAndThrowable"), Mockito.any()); + } + + @Test + public void testTraceWithFormatNArgs() { + igniteLogger.trace("Display message as: parameter1={}", "value1"); + Mockito.verify(logger) + .trace( + ArgumentMatchers.contains("Display message as: parameter1={}"), + ArgumentMatchers.any()); + } + + @Test + public void testTraceWithIgniteEvent() { + IgniteEvent igniteEvent = Mockito.mock(IgniteEvent.class); + igniteLogger.trace(igniteEvent, "TraceWithMsgAndThrowable"); + Mockito.verify(logger).trace(ArgumentMatchers.endsWith("TraceWithMsgAndThrowable")); + } + + @Test + public void testTraceWithIgniteEventNMsgnThrowable() { + IgniteEvent igniteEvent = Mockito.mock(IgniteEvent.class); + igniteLogger.trace(igniteEvent, "TraceWithIgniteEventnMsgnThrowable", new Throwable()); + Mockito.verify(logger) + .trace( + Mockito.endsWith("TraceWithIgniteEventnMsgnThrowable"), + Mockito.any()); + } + + @Test + public void testTraceWithIgniteEventNFormatNargs() { + IgniteEvent igniteEvent = Mockito.mock(IgniteEvent.class); + igniteLogger.trace(igniteEvent, "Display message as: parameter1={} parameter2={}", "value1", new Object()); + Mockito.verify(logger) + .trace( + ArgumentMatchers.endsWith("Display message as: parameter1={} parameter2={}"), + ArgumentMatchers.any()); + } + + @Test + public void testError() { + ArgumentCaptor arg = ArgumentCaptor.forClass(String.class); + igniteLogger.error("ErrorWithMsg"); + Mockito.verify(logger).error(arg.capture()); + assertEquals("ErrorWithMsg", arg.getValue()); + } + + @Test + public void testErrorWithMsgAndThrowable() { + igniteLogger.error("ErrorWithMsgAndThrowable", new Throwable()); + Mockito.verify(logger) + .error( + Mockito.eq("ErrorWithMsgAndThrowable"), + Mockito.any()); + } + + @Test + public void testErrorWithFormatnArgs() { + igniteLogger.error("Display message as: parameter1={}", "value1"); + Mockito.verify(logger) + .error( + ArgumentMatchers.contains("Display message as: parameter1={}"), + ArgumentMatchers.any()); + + } + + @Test + public void testErrorWithIgniteEvent() { + IgniteEvent igniteEvent = Mockito.mock(IgniteEvent.class); + igniteLogger.error(igniteEvent, "ErrorWithMsgAndThrowable"); + Mockito.verify(logger).error(ArgumentMatchers.endsWith("ErrorWithMsgAndThrowable")); + } + + @Test + public void testErrorWithIgniteEventNMsgNThrowable() { + IgniteEvent igniteEvent = Mockito.mock(IgniteEvent.class); + igniteLogger.error(igniteEvent, "ErrorWithIgniteEventnMsgnThrowable", new Throwable()); + Mockito.verify(logger) + .error( + Mockito.endsWith("ErrorWithIgniteEventnMsgnThrowable"), + Mockito.any()); + } + + @Test + public void testErrorWithIgniteEventNFormatNArgs() { + IgniteEvent igniteEvent = Mockito.mock(IgniteEvent.class); + igniteLogger.error(igniteEvent, "Display message as: parameter1={} parameter2={}", "value1", new Object()); + Mockito.verify(logger) + .error( + ArgumentMatchers.endsWith("Display message as: parameter1={} parameter2={}"), + ArgumentMatchers.any()); + + } + + @Test + public void testErrorWithIgniteEventNMsgNException() { + IgniteEvent igniteEvent = Mockito.mock(IgniteEvent.class); + igniteLogger.error(igniteEvent, "EXCEPTION", new Exception()); + Mockito.verify(logger).error(Mockito.endsWith("EXCEPTION"), Mockito.any()); + } +} diff --git a/src/test/java/com/harman/ignite/utils/logger/TestIgniteLoggerDebug.java b/src/test/java/com/harman/ignite/utils/logger/TestIgniteLoggerDebug.java new file mode 100644 index 0000000..d8ce985 --- /dev/null +++ b/src/test/java/com/harman/ignite/utils/logger/TestIgniteLoggerDebug.java @@ -0,0 +1,79 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.logger; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; +import org.mockito.internal.verification.Times; +import org.slf4j.Logger; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; + +/** Test class for IgniteLogger for debug. + * + * @author AKumar + */ + +public class TestIgniteLoggerDebug { + private static IgniteLoggerImpl igniteLogger = IgniteLoggerImpl.getIgniteLoggerImplInstance(EventLogger2.class); + Logger logger; + + @Before + public void setup() { + logger = Mockito.mock(Logger.class); + igniteLogger.setLogger(logger); + } + + @Test + public void testIgniteLoggersWhenDebugEnabled() { + when(logger.isDebugEnabled()).thenReturn(true); + ArgumentCaptor arg = ArgumentCaptor.forClass(String.class); + igniteLogger.debug("DebugWithMsg"); + Mockito.verify(logger).debug(arg.capture()); + assertEquals("DebugWithMsg", arg.getValue()); + } + + @Test + public void testIgniteLoggersWhenDebugDisabled() { + when(logger.isDebugEnabled()).thenReturn(false); + igniteLogger.debug("DebugWithMsg"); + Mockito.verify(logger, new Times(0)).debug("DebugWithMsg"); + } +} diff --git a/src/test/java/com/harman/ignite/utils/logger/TestIgniteLoggerError.java b/src/test/java/com/harman/ignite/utils/logger/TestIgniteLoggerError.java new file mode 100644 index 0000000..ef30e57 --- /dev/null +++ b/src/test/java/com/harman/ignite/utils/logger/TestIgniteLoggerError.java @@ -0,0 +1,79 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.logger; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; +import org.mockito.internal.verification.Times; +import org.slf4j.Logger; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; + +/** Test class for IgniteLogger for error. + * + * @author AKumar + */ + +public class TestIgniteLoggerError { + private static IgniteLoggerImpl igniteLogger = IgniteLoggerImpl.getIgniteLoggerImplInstance(EventLogger2.class); + Logger logger; + + @Before + public void setup() { + logger = Mockito.mock(Logger.class); + igniteLogger.setLogger(logger); + } + + @Test + public void testIgniteLoggersWhenErrorEnabled() { + when(logger.isErrorEnabled()).thenReturn(true); + ArgumentCaptor arg = ArgumentCaptor.forClass(String.class); + igniteLogger.error("ErrorWithMsg"); + Mockito.verify(logger).error(arg.capture()); + assertEquals("ErrorWithMsg", arg.getValue()); + } + + @Test + public void testIgniteLoggersWhenErrorDisabled() { + when(logger.isErrorEnabled()).thenReturn(false); + igniteLogger.error("ErrorWithMsg"); + Mockito.verify(logger, new Times(1)).error("ErrorWithMsg"); + } +} diff --git a/src/test/java/com/harman/ignite/utils/logger/TestIgniteLoggerInfo.java b/src/test/java/com/harman/ignite/utils/logger/TestIgniteLoggerInfo.java new file mode 100644 index 0000000..fac9753 --- /dev/null +++ b/src/test/java/com/harman/ignite/utils/logger/TestIgniteLoggerInfo.java @@ -0,0 +1,80 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.logger; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; +import org.mockito.internal.verification.Times; +import org.slf4j.Logger; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; + +/** + * Test class for IgniteLogger for info. + * + * @author AKumar + */ + +public class TestIgniteLoggerInfo { + private static IgniteLoggerImpl igniteLogger = IgniteLoggerImpl.getIgniteLoggerImplInstance(EventLogger2.class); + Logger logger; + + @Before + public void setup() { + logger = Mockito.mock(Logger.class); + igniteLogger.setLogger(logger); + } + + @Test + public void testIgniteLoggersWhenInfoEnabled() { + when(logger.isInfoEnabled()).thenReturn(true); + ArgumentCaptor arg = ArgumentCaptor.forClass(String.class); + igniteLogger.info("InfoWithMsg"); + Mockito.verify(logger).info(arg.capture()); + assertEquals("InfoWithMsg", arg.getValue()); + } + + @Test + public void testIgniteLoggersWhenInfoDisabled() { + when(logger.isInfoEnabled()).thenReturn(false); + igniteLogger.info("InfoWithMsg"); + Mockito.verify(logger, new Times(0)).info("InfoWithMsg"); + } +} diff --git a/src/test/java/com/harman/ignite/utils/logger/TestIgniteLoggerTrace.java b/src/test/java/com/harman/ignite/utils/logger/TestIgniteLoggerTrace.java new file mode 100644 index 0000000..127ae27 --- /dev/null +++ b/src/test/java/com/harman/ignite/utils/logger/TestIgniteLoggerTrace.java @@ -0,0 +1,80 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.logger; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; +import org.mockito.internal.verification.Times; +import org.slf4j.Logger; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; + +/** + * Test class for IgniteLogger for trace. + * + * @author AKumar + */ + +public class TestIgniteLoggerTrace { + private static IgniteLoggerImpl igniteLogger = IgniteLoggerImpl.getIgniteLoggerImplInstance(EventLogger2.class); + Logger logger; + + @Before + public void setup() { + logger = Mockito.mock(Logger.class); + igniteLogger.setLogger(logger); + } + + @Test + public void testIgniteLoggersWhenTraceEnabled() { + when(logger.isTraceEnabled()).thenReturn(true); + ArgumentCaptor arg = ArgumentCaptor.forClass(String.class); + igniteLogger.trace("TraceWithMsg"); + Mockito.verify(logger).trace(arg.capture()); + assertEquals("TraceWithMsg", arg.getValue()); + } + + @Test + public void testIgniteLoggersWhenTraceDisabled() { + when(logger.isTraceEnabled()).thenReturn(false); + igniteLogger.trace("TraceWithMsg"); + Mockito.verify(logger, new Times(0)).trace("TraceWithMsg"); + } +} diff --git a/src/test/java/com/harman/ignite/utils/logger/TestIgniteLoggerWarn.java b/src/test/java/com/harman/ignite/utils/logger/TestIgniteLoggerWarn.java new file mode 100644 index 0000000..3de8b85 --- /dev/null +++ b/src/test/java/com/harman/ignite/utils/logger/TestIgniteLoggerWarn.java @@ -0,0 +1,81 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.logger; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; +import org.mockito.internal.verification.Times; +import org.slf4j.Logger; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; + +/** + * Test class for IgniteLogger for warn. + * + * @author AKumar + * + */ + +public class TestIgniteLoggerWarn { + private static IgniteLoggerImpl igniteLogger = IgniteLoggerImpl.getIgniteLoggerImplInstance(EventLogger2.class); + Logger logger; + + @Before + public void setup() { + logger = Mockito.mock(Logger.class); + igniteLogger.setLogger(logger); + } + + @Test + public void testIgniteLoggersWhenWarnEnabled() { + when(logger.isWarnEnabled()).thenReturn(true); + ArgumentCaptor arg = ArgumentCaptor.forClass(String.class); + igniteLogger.warn("WarnWithMsg"); + Mockito.verify(logger).warn(arg.capture()); + assertEquals("WarnWithMsg", arg.getValue()); + } + + @Test + public void testIgniteLoggersWhenWarnDisabled() { + when(logger.isWarnEnabled()).thenReturn(false); + igniteLogger.warn("WarnWithMsg"); + Mockito.verify(logger, new Times(1)).warn("WarnWithMsg"); + } +} diff --git a/src/test/java/com/harman/ignite/utils/metrics/GenericIgniteGuageTest.java b/src/test/java/com/harman/ignite/utils/metrics/GenericIgniteGuageTest.java new file mode 100644 index 0000000..10ce899 --- /dev/null +++ b/src/test/java/com/harman/ignite/utils/metrics/GenericIgniteGuageTest.java @@ -0,0 +1,169 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.metrics; + +import io.prometheus.client.Collector.MetricFamilySamples; +import io.prometheus.client.CollectorRegistry; +import io.prometheus.client.Gauge; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.MockitoAnnotations; + +import java.util.List; + +/** + * Test class for IgniteGuageTest. + * + * @see IgniteGuageTest + */ +public class GenericIgniteGuageTest { + + @InjectMocks + IgniteGuageTest guage = new IgniteGuageTest(); + private static final double THREE = 3.0; + private static final double THREE_DOT_FIVE = 3.5; + private static final double FIVE = 5.0; + private static final double SEVEN = 7.0; + private static final double NINE = 9.0; + private static final double TEN = 10.0; + private final String name = null; + private final String[] labels = { "node", "taskId" }; + + /** + * Setup method to initialize the mocks. + */ + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + CollectorRegistry.defaultRegistry.clear(); + System.out.println("In before"); + } + + @Test + public void testCreateGuage() { + guage.createGauge("test_guage", "test_guage", labels); + Gauge newGuage = guage.getGuage(); + List samples = newGuage.collect(); + + Assert.assertTrue(guage.getIsInitialized()); + samples.forEach(sample -> { + Assert.assertEquals("test_guage", sample.name); + }); + + guage.createGauge(name, name, labels); + } + + @Test + public void testInc() { + guage.createGauge("test_guage1", "test_guage1", labels); + double value = guage.get(labels); + + Assert.assertEquals(0.0, value, 0.0); + + guage.inc(labels); + value = guage.get(labels); + + Assert.assertEquals(1.0, value, 0.0); + } + + @Test + public void testIncBySomeValue() { + guage.createGauge("test_guage2", "test_guage2", labels); + Assert.assertEquals(0.0, guage.get(labels), 0.0); + + guage.inc(FIVE, labels); + + Assert.assertEquals(FIVE, guage.get(labels), 0.0); + } + + @Test + public void testDecBySomeValue() { + guage.createGauge("test_guage3", "test_guage3", labels); + guage.inc(TEN, labels); + + Assert.assertEquals(TEN, guage.get(labels), 0.0); + + guage.dec(THREE, labels); + + Assert.assertEquals(SEVEN, guage.get(labels), 0.0); + } + + @Test + public void testDec() { + guage.createGauge("test_guage4", "test_guage4", labels); + guage.inc(TEN, labels); + + Assert.assertEquals(TEN, guage.get(labels), 0.0); + + guage.dec(labels); + + Assert.assertEquals(NINE, guage.get(labels), 0.0); + } + + @Test + public void testSetGaugeValue() { + guage.createGauge("test_guage5", "test_guage5", labels); + + Assert.assertEquals(0.0, guage.get(labels), 0.0); + + guage.set(THREE_DOT_FIVE, labels); + + Assert.assertEquals(THREE_DOT_FIVE, guage.get(labels), 0.0); + } + + @Test + public void testClear() { + guage.createGauge("test_guage6", "test_guage6", labels); + guage.set(SEVEN, labels); + + Assert.assertEquals(SEVEN, guage.get(labels), 0.0); + + guage.clear(); + + Assert.assertEquals(0.0, guage.get(labels), 0.0); + } + + /** Test Gauge class. + * + * @see IgniteGuageTest + */ + public static class IgniteGuageTest extends AbstractIgniteGauge { + + } +} diff --git a/src/test/java/com/harman/ignite/utils/metrics/IgniteCounterTest.java b/src/test/java/com/harman/ignite/utils/metrics/IgniteCounterTest.java new file mode 100644 index 0000000..ebbafe0 --- /dev/null +++ b/src/test/java/com/harman/ignite/utils/metrics/IgniteCounterTest.java @@ -0,0 +1,93 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.metrics; + +import io.prometheus.client.Collector.MetricFamilySamples; +import io.prometheus.client.CollectorRegistry; +import io.prometheus.client.Counter; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.List; + +/** + * Test class for TestCounter. + * + * @see TestCounter + */ +public class IgniteCounterTest { + String name = "test_counter"; + String[] labels = { "node", "taskId" }; + + private final TestCounter testCounter = new TestCounter(); + + @Before + public void setup() { + CollectorRegistry.defaultRegistry.clear(); + } + + @Test + public void testCreateCounter() { + testCounter.createCounter(name, labels); + Counter counter = testCounter.getCounter(); + List samples = counter.collect(); + + samples.forEach(sample -> { + Assert.assertEquals(name, sample.name); + }); + + //again trying to create counter that's already created, won't do anything + testCounter.createCounter(name, labels); + } + + @Test + public void testInc() { + testCounter.createCounter(name, labels); + Assert.assertEquals(0.0, testCounter.get(labels), 0.0); + testCounter.inc(labels); + Assert.assertEquals(1.0, testCounter.get(labels), 0.0); + } + + /** Test class for IgniteCounter. + * + * @see IgniteCounter + */ + public static class TestCounter extends IgniteCounter { + + } +} diff --git a/src/test/java/com/harman/ignite/utils/metrics/IgniteErrorCounterTest.java b/src/test/java/com/harman/ignite/utils/metrics/IgniteErrorCounterTest.java new file mode 100644 index 0000000..361eb7e --- /dev/null +++ b/src/test/java/com/harman/ignite/utils/metrics/IgniteErrorCounterTest.java @@ -0,0 +1,115 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.metrics; + +import io.prometheus.client.Collector.MetricFamilySamples; +import io.prometheus.client.CollectorRegistry; +import io.prometheus.client.Counter; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.MockitoAnnotations; + +import java.util.List; + +/** + * Test class for IgniteErrorCounter. + * + * @see IgniteErrorCounter + */ +public class IgniteErrorCounterTest { + + @InjectMocks + private IgniteErrorCounter igniteCounter; + private static final double FIVE = 5.0; + private final String name = "test_count"; + private final String[] labels = { "node", "taskId", "IllegalArgumentException" }; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + CollectorRegistry.defaultRegistry.clear(); + } + + @Test + public void testCreateCounter() { + igniteCounter.createCounter(name, name, labels); + + Counter counter = igniteCounter.getCounter(); + List samples = counter.collect(); + Assert.assertTrue(igniteCounter.isInitialized()); + for (MetricFamilySamples sample : samples) { + Assert.assertEquals("error_count", sample.name); + } + + } + + @Test + public void testIncErrorCounter() { + //create a counter with initial metric value as 0.0 + igniteCounter.createCounter(name, name, labels); + igniteCounter.setNodeName("node"); + //increment the metric value of the counter with labels = {"node","taskId","IllegalArgumentException"} by 1 + igniteCounter.inc(labels); + + Assert.assertEquals(1.0, igniteCounter.get(labels), 0.0); + } + + @Test + public void testIncErrorCounterBySomeValue() { + //create a counter with initial metric value as 0.0 + igniteCounter.createCounter(name, name, labels); + igniteCounter.setNodeName("node"); + //increment the metric value of the counter with labels = {"node","taskId","IllegalArgumentException"} by 5 + igniteCounter.inc(FIVE, labels); + + //since initial value was 0.0 and we incremented the metric value by 5.0, hence asserting as 5.0 + Assert.assertEquals(FIVE, igniteCounter.get(labels), 0.0); + } + + @Test + public void testClearCounter() { + igniteCounter.createCounter(name, name, labels); + igniteCounter.setNodeName("node"); + igniteCounter.inc(FIVE, labels); + + Assert.assertEquals(FIVE, igniteCounter.get(labels), 0.0); + igniteCounter.clear(); + Assert.assertEquals(0.0, igniteCounter.get(labels), 0.0); + } +} diff --git a/src/test/java/com/harman/ignite/utils/metrics/IgniteGuageTest.java b/src/test/java/com/harman/ignite/utils/metrics/IgniteGuageTest.java new file mode 100644 index 0000000..f94ef68 --- /dev/null +++ b/src/test/java/com/harman/ignite/utils/metrics/IgniteGuageTest.java @@ -0,0 +1,104 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.metrics; + +import io.prometheus.client.Collector.MetricFamilySamples; +import io.prometheus.client.CollectorRegistry; +import io.prometheus.client.Gauge; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.MockitoAnnotations; + +import java.util.List; + +/** + * Test class for IgniteGuageTest. + * + * @see TestGuage + */ +public class IgniteGuageTest { + + private static final double TEN_DOT_FIVE = 10.5; + private final String name = "test_guage"; + private final String[] labels = { "test_metric", "node", "monitorname" }; + + @InjectMocks + private TestGuage testGuage = new TestGuage(); + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + CollectorRegistry.defaultRegistry.clear(); + } + + @Test + public void testCreateGuage() { + testGuage.createGuage(name, labels); + Gauge guage = testGuage.getIgniteGuageMetric(); + + Assert.assertTrue(guage != null && guage instanceof Gauge); + + List samples = guage.collect(); + for (MetricFamilySamples sample : samples) { + Assert.assertEquals("test_guage", sample.name); + } + + //trying to create a guage that already exists, it won't create and publish a WARN logger + testGuage.createGuage(name, labels); + } + + @Test + public void testSetValueOnGuage() { + testGuage.createGuage(name, labels); + Gauge guage = testGuage.getIgniteGuageMetric(); + testGuage.setIgniteGuageMetric(guage); + testGuage.set(TEN_DOT_FIVE, labels); + double value = testGuage.get(labels); + + Assert.assertEquals(TEN_DOT_FIVE, value, 0); + } + + /** Test class for IgniteGuage. + * + * @see IgniteGuage + */ + public static class TestGuage extends IgniteGuage { + + } +} diff --git a/src/test/java/com/harman/ignite/utils/metrics/IgniteRocksDBGuageTest.java b/src/test/java/com/harman/ignite/utils/metrics/IgniteRocksDBGuageTest.java new file mode 100644 index 0000000..5a3a482 --- /dev/null +++ b/src/test/java/com/harman/ignite/utils/metrics/IgniteRocksDBGuageTest.java @@ -0,0 +1,67 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.metrics; + +import io.prometheus.client.Collector.MetricFamilySamples; +import io.prometheus.client.Gauge; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.InjectMocks; + +import java.util.List; + +/** Test class for IgniteRocksDBGuage. + * + * @see IgniteRocksDBGuage + */ +@SuppressWarnings("checkstyle:AbbreviationAsWordInName") +public class IgniteRocksDBGuageTest { + @InjectMocks + private IgniteRocksDBGuage guage = new IgniteRocksDBGuage(); + + @Test + public void testSetup() { + guage.setup(); + Gauge testGuage = guage.getIgniteGuageMetric(); + Assert.assertTrue(testGuage != null && testGuage instanceof Gauge); + + List samples = testGuage.collect(); + for (MetricFamilySamples familySample : samples) { + Assert.assertEquals("rocksdb_metric", familySample.name); + } + } +} diff --git a/src/test/java/com/harman/ignite/utils/metrics/InternalCacheGuageTest.java b/src/test/java/com/harman/ignite/utils/metrics/InternalCacheGuageTest.java new file mode 100644 index 0000000..20b2ad6 --- /dev/null +++ b/src/test/java/com/harman/ignite/utils/metrics/InternalCacheGuageTest.java @@ -0,0 +1,91 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.metrics; + +import io.prometheus.client.Collector.MetricFamilySamples; +import io.prometheus.client.Collector.MetricFamilySamples.Sample; +import io.prometheus.client.CollectorRegistry; +import io.prometheus.client.Gauge; +import org.junit.Assert; +import org.junit.Test; +import org.springframework.test.util.ReflectionTestUtils; + +import java.util.List; + +/** Test class for InternalCacheGuage. + * + * @see InternalCacheGuage + */ +public class InternalCacheGuageTest { + + private final InternalCacheGuage cacheGuage = new InternalCacheGuage(); + private static final double TEN = 10.0; + + @Test + public void testSetupIfMetricsEnabled() { + ReflectionTestUtils.setField(cacheGuage, "internalMetricsEnabled", true); + ReflectionTestUtils.setField(cacheGuage, "prometheusEnabled", true); + + cacheGuage.setup(); + Gauge guage = cacheGuage.getIgniteGuageMetric(); + Assert.assertNotNull(guage); + + List samples = guage.collect(); + for (MetricFamilySamples familySample : samples) { + Assert.assertEquals("internal_cache_size_metric", familySample.name); + } + } + + @Test + public void testSet() { + //Below code is to avoid "Collector already registered the metric..." error. + CollectorRegistry.defaultRegistry.clear(); + ReflectionTestUtils.setField(cacheGuage, "internalMetricsEnabled", true); + ReflectionTestUtils.setField(cacheGuage, "prometheusEnabled", true); + + cacheGuage.setup(); + cacheGuage.set(TEN, "test_cache", "test_svc", "test_node", "0_1"); + Gauge guage = cacheGuage.getIgniteGuageMetric(); + + List samples = guage.collect(); + for (MetricFamilySamples familySample : samples) { + for (Sample sample : familySample.samples) { + Assert.assertEquals(TEN, sample.value, 0.0); + } + } + } +} diff --git a/src/test/java/com/harman/ignite/utils/metrics/TestGenericIgniteHistogram.java b/src/test/java/com/harman/ignite/utils/metrics/TestGenericIgniteHistogram.java new file mode 100644 index 0000000..d78b2be --- /dev/null +++ b/src/test/java/com/harman/ignite/utils/metrics/TestGenericIgniteHistogram.java @@ -0,0 +1,236 @@ +/* + * ******************************************************************************* + * + * Copyright (c) 2023-24 Harman International + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * + * you may not use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * + * + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *       + * + * Unless required by applicable law or agreed to in writing, software + * + * distributed under the License is distributed on an "AS IS" BASIS, + * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * + * limitations under the License. + * + * + * + * SPDX-License-Identifier: Apache-2.0 + * + * ******************************************************************************* + */ + +package com.harman.ignite.utils.metrics; + +import io.prometheus.client.Collector; +import io.prometheus.client.Collector.MetricFamilySamples; +import io.prometheus.client.Collector.MetricFamilySamples.Sample; +import io.prometheus.client.Histogram; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; +import java.util.concurrent.Callable; +import java.util.function.Supplier; + +/** + * This class tests basic functionality of Histogram. + *

Key point to note while testing:

+ * + *
    + *
  • Create Histogram.
  • + *
  • Do observe.
  • + *
  • Check data on Collector.
  • + *
+ * + * @author vkoul + * + */ + +public class TestGenericIgniteHistogram { + private static final double TWO = 2.0; + private static final double THREE = 3.0; + private static final int TEN = 10; + private static final int HUNDRED = 100; + private static final long TWO_THOUSAND = 2000L; + private static final long THREE_THOUSAND = 3000L; + private static final double HUNDRED_DOUBLE = 100.0; + + @SuppressWarnings("unchecked") + @Test + public void testObserveExtended() throws Exception { + GenericIgniteHistogram genericIgniteHistogram = new GenericIgniteHistogram( + "testHistogram", + "testHistogramDoubleHelp", + new double[] { HUNDRED }, + "testHistogramDoubleLabel"); + String[] labels = { "testHistogramDoubleLabel" }; + Assert.assertEquals("Test invocation", genericIgniteHistogram.observeExtended(new Callable() { + @Override + public String call() { + return "Test invocation"; + } + }, labels)); + } + + /** + * This test cases tests observe(Double...) functionality. + */ + @Test + public void testObserveDouble() { + GenericIgniteHistogram genericIgniteHistogram = new GenericIgniteHistogram( + "testHistogramDouble", + "testHistogramDoubleHelp", + new double[] { HUNDRED }, + "testHistogramDoubleLabel"); + Histogram hg = genericIgniteHistogram.getHistogram(); + // Observe a value. + genericIgniteHistogram.observe(HUNDRED, "testHistogramDoubleLabel"); + // Collect all metric from this Collector (Histogram). + List lists = hg.collect(); + + // Should be one, since we observed only once. + Assert.assertEquals(1, lists.size()); + for (MetricFamilySamples mfs : lists) { + // Sanity check. + Assert.assertEquals("testHistogramDoubleHelp", mfs.help); + Assert.assertEquals("testHistogramDouble", mfs.name); + Assert.assertEquals(Collector.Type.HISTOGRAM, mfs.type); + + // Collect sample. + List samples = mfs.samples; + + // Iterate through all Sample and do sanity check. + // Refer to io.prometheus.client.Collector and + // io.prometheus.client.Collector.MetricFamilySamples.Sample for + // full details. + for (Sample sample : samples) { + switch (sample.name) { + // Test _count for metric "testHistogram" + case "testHistogramDouble_count": + Assert.assertEquals(1.0, sample.value, 0); + break; + // Test _sum for metric "testHistogram" + case "testHistogramDouble_sum": + Assert.assertEquals(HUNDRED_DOUBLE, sample.value, 0); + break; + default: + // do nothing + } + } + } + } + + /** + * This test cases tests observe(Supplier...) functionality. + */ + @Test + public void testObserveSupplier() { + GenericIgniteHistogram genericIgniteHistogram = new GenericIgniteHistogram( + "testHistogramSupplier", + "testHistogramSupplierHelp", + new double[] { HUNDRED }, + "testHistogramSupplierLabel"); + Histogram hg = genericIgniteHistogram.getHistogram(); + genericIgniteHistogram.observe(new Supplier() { + @Override + public Integer get() { + try { + // Forcefully sleeping for 2 seconds + Thread.sleep(TWO_THOUSAND); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return TEN; + } + }, "testHistogramSupplierLabel"); + + List lists = hg.collect(); + Assert.assertEquals(1, lists.size()); + for (MetricFamilySamples mfs : lists) { + Assert.assertEquals("testHistogramSupplierHelp", mfs.help); + Assert.assertEquals("testHistogramSupplier", mfs.name); + Assert.assertEquals(Collector.Type.HISTOGRAM, mfs.type); + + List samples = mfs.samples; + for (Sample sample : samples) { + switch (sample.name) { + case "testHistogramSupplier_count": + Assert.assertEquals(1.0, sample.value, 0); + break; + case "testHistogramSupplier_sum": + System.out.println("sample.value is ---> " + sample.value); + // This means it took between 2-3 seconds. 2 seconds minimum + // since we forcefully slept for 2 seconds. + Assert.assertEquals(TWO, sample.value, 1); + break; + default: + // do nothing + } + } + } + } + + /** + * This test cases tests observe(Runnable...) functionality. + */ + @Test + public void testObserveRunnable() { + GenericIgniteHistogram genericIgniteHistogram = new GenericIgniteHistogram( + "testHistogramRunnable", + "testHistogramRunnableHelp", + new double[] { HUNDRED }, + "testHistogramRunnableLabel"); + Histogram hg = genericIgniteHistogram.getHistogram(); + genericIgniteHistogram.observe(new Runnable() { + @Override + public void run() { + try { + // Forcefully sleeping for 3 seconds + Thread.sleep(THREE_THOUSAND); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }, "testHistogramRunnableLabel"); + + List lists = hg.collect(); + Assert.assertEquals(1, lists.size()); + for (MetricFamilySamples mfs : lists) { + Assert.assertEquals("testHistogramRunnableHelp", mfs.help); + Assert.assertEquals("testHistogramRunnable", mfs.name); + Assert.assertEquals(Collector.Type.HISTOGRAM, mfs.type); + + List samples = mfs.samples; + for (Sample sample : samples) { + switch (sample.name) { + case "testHistogramRunnable_count": + Assert.assertEquals(1.0, sample.value, 0); + break; + case "testHistogramRunnable_sum": + System.out.println("sample.value is ---> " + sample.value); + // This means it took between 3-4 seconds. 3 seconds minimum + // since we forcefully slept for 3 seconds. + Assert.assertEquals(THREE, sample.value, 1); + break; + default: + // do nothing + } + } + } + } +} \ No newline at end of file diff --git a/src/test/resources/logback.xml b/src/test/resources/logback.xml new file mode 100644 index 0000000..c03fb36 --- /dev/null +++ b/src/test/resources/logback.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + 60000 + + + + + + %d{HH:mm:ss.SSS} [%thread] %c{1} %-5level - %msg + %ex{full} %n + + + + + + 1000000 + 20 + true + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/property-diagnostic-test-2.properties b/src/test/resources/property-diagnostic-test-2.properties new file mode 100644 index 0000000..33e277b --- /dev/null +++ b/src/test/resources/property-diagnostic-test-2.properties @@ -0,0 +1,43 @@ +#* ******************************************************************************* +#* +#* Copyright (c) 2023-24 Harman International +#* +#* +#* +#* Licensed under the Apache License, Version 2.0 (the "License"); +#* +#* you may not use this file except in compliance with the License. +#* +#* You may obtain a copy of the License at +#* +#* +#* +#* http://www.apache.org/licenses/LICENSE-2.0 +#* +#* ????? +#* +#* Unless required by applicable law or agreed to in writing, software +#* +#* distributed under the License is distributed on an "AS IS" BASIS, +#* +#* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +#* +#* See the License for the specific language governing permissions and +#* +#* limitations under the License. +#* +#* +#* +#* SPDX-License-Identifier: Apache-2.0 +#* +#* ******************************************************************************* +mongodb.vault.enabled=true +vault.server.ipaddress=10.0.0.167 +vault.server.port.number=8200 +vault.environment=dev +vault.secret.folder=kafka-redis-connector +diagnostic.mongodb.vault.enabled=true +diagnostic.vault.server.ipaddress=10.0.0.167 +diagnostic.vault.server.port.number=8200 +diagnostic.vault.environment=dev2 +diagnostic.vault.secret.folder=kafka-redis-connector1 \ No newline at end of file diff --git a/src/test/resources/property-diagnostic-test.properties b/src/test/resources/property-diagnostic-test.properties new file mode 100644 index 0000000..76c7403 --- /dev/null +++ b/src/test/resources/property-diagnostic-test.properties @@ -0,0 +1,83 @@ +#* ******************************************************************************* +#* +#* Copyright (c) 2023-24 Harman International +#* +#* +#* +#* Licensed under the Apache License, Version 2.0 (the "License"); +#* +#* you may not use this file except in compliance with the License. +#* +#* You may obtain a copy of the License at +#* +#* +#* +#* http://www.apache.org/licenses/LICENSE-2.0 +#* +#* ????? +#* +#* Unless required by applicable law or agreed to in writing, software +#* +#* distributed under the License is distributed on an "AS IS" BASIS, +#* +#* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +#* +#* See the License for the specific language governing permissions and +#* +#* limitations under the License. +#* +#* +#* +#* SPDX-License-Identifier: Apache-2.0 +#* +#* ******************************************************************************* +mongodb.hosts=localhost +mongodb.port=27017 +mongodb.username=admin +mongodb.password=password +mongodb.auth.db=admin +mongodb.name=admin +mongodb.pool.max.size=1 +mongodb.max.wait.time.ms=60000 +mongodb.connection.timeout.ms=60000 +mongodb.socket.timeout.ms=60000 +mongodb.max.connections.per.host=200 +mongodb.block.threads.allowed.multiplier=10 +mongodb.read.preference=secondaryPreferred +morphia.map.packages=com.harman.ignite.dao +mongodb.server.selection.timeout=60000 +#Comma separated fully qualified names for Morphia converters +morphia.converters.fqn=com.harman.ignite.dao.mongodb.BytesBufferConverter +mongodb.client.cleanup.interval.ms=10000 +mongodb.client.create.retry.count=3 +#Assumed time interval for running threads to release the old mongo client before forced close. +mongodb.client.close.wait.interval.ms=60000 +mongodb.taggable.read.preference.enabled=false +mongodb.read.preference.tag= +health.mongo.monitor.enabled=true +health.mongo.needs.restart.on.failure=true +diagnostic.mongodb.hosts=localhost123 +diagnostic.mongodb.port=27018 +diagnostic.mongodb.username=admin123 +diagnostic.mongodb.password=password +diagnostic.mongodb.auth.db=admin +diagnostic.mongodb.name=admin +diagnostic.mongodb.pool.max.size=1 +diagnostic.mongodb.max.wait.time.ms=60000 +diagnostic.mongodb.connection.timeout.ms=60000 +diagnostic.mongodb.socket.timeout.ms=60000 +diagnostic.mongodb.max.connections.per.host=200 +diagnostic.mongodb.block.threads.allowed.multiplier=10 +diagnostic.mongodb.read.preference=secondaryPreferred +diagnostic.morphia.map.packages=com.harman.ignite.dao +diagnostic.mongodb.server.selection.timeout=60000 +#Comma separated fully qualified names for Morphia converters +diagnostic.morphia.converters.fqn=com.harman.ignite.dao.mongodb.BytesBufferConverter +diagnostic.mongodb.client.cleanup.interval.ms=10000 +diagnostic.mongodb.client.create.retry.count=3 +#Assumed time interval for running threads to release the old mongo client before forced close. +diagnostic.mongodb.client.close.wait.interval.ms=60000 +diagnostic.mongodb.taggable.read.preference.enabled=false +diagnostic.mongodb.read.preference.tag=primary_region +diagnostic.health.mongo.monitor.enabled=true +diagnostic.health.mongo.needs.restart.on.failure=true \ No newline at end of file diff --git a/target/classes/META-INF/MANIFEST.MF b/target/classes/META-INF/MANIFEST.MF new file mode 100644 index 0000000..02782f6 --- /dev/null +++ b/target/classes/META-INF/MANIFEST.MF @@ -0,0 +1,5 @@ +Manifest-Version: 1.0 +Built-By: karora +Build-Jdk: 15.0.2 +Created-By: Maven Integration for Eclipse + From cb8b4fa54bbabc85957915465be2e80fb9641a21 Mon Sep 17 00:00:00 2001 From: "Arora, Kaushal" Date: Thu, 20 Feb 2025 13:47:32 +0530 Subject: [PATCH 2/4] WI 705913 Updating ReadMe file --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 73f4fbd..378d4df 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ # utils `utils` project provides the below functionalities to a service. -[![Build](https://github.com/HARMAN-Automotive/utils/actions/workflows/maven-publish.yml/badge.svg)](https://github.com/HARMAN-Automotive/utils/actions/workflows/maven-publish.yml) -[![License Compliance](https://github.com/Harman-Automotive/utils/actions/workflows/license-compliance.yml/badge.svg)](https://github.com/Harman-Automotive/utils/actions/workflows/license-compliance.yml) +[![Build](https://github.com/eclipse-ecsp/utils/actions/workflows/maven-publish.yml/badge.svg)](https://github.com/eclipse-ecsp/utils/actions/workflows/maven-publish.yml) +[![License Compliance](https://github.com/eclipse-ecsp/utils/actions/workflows/license-compliance.yml/badge.svg)](https://github.com/eclipse-ecsp/utils/actions/workflows/license-compliance.yml) 1. Centralized logging. 2. Health checks. @@ -55,9 +55,9 @@ from the command line interface. Add the following dependency in the target project ``` - com.harman.ignite - ignite-utils - 3.X.X + org.eclipse.ecsp + utils + 1.X.X ``` @@ -177,6 +177,6 @@ Please read [CONTRIBUTING.md](./CONTRIBUTING.md) for details on how to raise an This project is licensed under the Apache-2.0 License - see the [LICENSE](./LICENSE) file for details. ## Announcements -All updates to this library are documented in our [Release Notes](./release_notes.txt) and [releases](https://github.com/HARMAN-Automotive/utils/releases). -For the versions available, see the [tags on this repository](https://github.com/HARMAN-Automotive/utils/tags). +All updates to this library are documented in our [Release Notes](./release_notes.txt) and [releases](https://github.com/eclipse-ecsp/utils/releases). +For the versions available, see the [tags on this repository](https://github.com/eclipse-ecsp/utils/tags). From bc2dc1f5330e949985c9c82ec88b4b3cf4b3f405 Mon Sep 17 00:00:00 2001 From: "Arora, Kaushal" Date: Thu, 20 Feb 2025 13:49:54 +0530 Subject: [PATCH 3/4] WI 705913 Updating ReadMe file --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 378d4df..5ff1ee5 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ [](./images/logo.png) -# utils -`utils` project provides the below functionalities to a service. +# Utils +`Utils` project consists frequently used utilities for ECSP project and provides the below functionalities to a service. [![Build](https://github.com/eclipse-ecsp/utils/actions/workflows/maven-publish.yml/badge.svg)](https://github.com/eclipse-ecsp/utils/actions/workflows/maven-publish.yml) [![License Compliance](https://github.com/eclipse-ecsp/utils/actions/workflows/license-compliance.yml/badge.svg)](https://github.com/eclipse-ecsp/utils/actions/workflows/license-compliance.yml) From 70cba2e9d2965f64094ee146246cace287daa876 Mon Sep 17 00:00:00 2001 From: "Arora, Kaushal" Date: Thu, 20 Feb 2025 14:40:03 +0530 Subject: [PATCH 4/4] WI 705913 Fix sonar smell in logback file --- src/test/resources/logback.xml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/test/resources/logback.xml b/src/test/resources/logback.xml index c03fb36..a9cde56 100644 --- a/src/test/resources/logback.xml +++ b/src/test/resources/logback.xml @@ -35,12 +35,6 @@ * ******************************************************************************* --> - - - - - -