├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── support_request.md ├── PULL_REQUEST_TEMPLATE.md ├── auto-label.yaml ├── blunderbuss.yml ├── dependabot.yml ├── release-please.yml ├── release-trigger.yml ├── snippet-bot.yml ├── sync-repo-settings.yaml ├── trusted-contribution.yml └── workflows │ ├── approve-readme.yaml │ ├── auto-release.yaml │ ├── ci.yaml │ ├── renovate_config_check.yaml │ ├── samples.yaml │ └── unmanaged_dependency_check.yaml ├── .gitignore ├── .kokoro ├── build.bat ├── build.sh ├── coerce_logs.sh ├── common.cfg ├── common.sh ├── common_env_vars.cfg ├── continuous │ ├── common.cfg │ ├── java8.cfg │ └── propose_release.sh ├── dependencies.sh ├── nightly │ ├── common.cfg │ ├── integration.cfg │ ├── java11-integration.cfg │ ├── java11.cfg │ ├── java7.cfg │ ├── java8-osx.cfg │ ├── java8-win.cfg │ ├── java8.cfg │ └── samples.cfg ├── populate-secrets.sh ├── presubmit │ ├── clirr.cfg │ ├── common.cfg │ ├── dependencies.cfg │ ├── graalvm-native-a.cfg │ ├── graalvm-native-b.cfg │ ├── graalvm-native-c.cfg │ ├── integration.cfg │ ├── java11.cfg │ ├── java7.cfg │ ├── java8-osx.cfg │ ├── java8-win.cfg │ ├── java8.cfg │ ├── linkage-monitor.cfg │ ├── lint.cfg │ └── samples.cfg ├── readme.sh ├── requirements.in └── trampoline.sh ├── .repo-metadata.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── java.header ├── license-checks.xml ├── pom.xml ├── renovate.json ├── samples ├── install-without-bom │ └── pom.xml ├── pom.xml ├── snapshot │ └── pom.xml └── snippets │ ├── pom.xml │ └── src │ └── main │ ├── java │ └── com │ │ └── example │ │ └── logging │ │ └── logback │ │ ├── Quickstart.java │ │ └── enhancers │ │ └── ExampleEnhancer.java │ └── resources │ └── logback.xml ├── src ├── main │ ├── java │ │ └── com │ │ │ └── google │ │ │ └── cloud │ │ │ └── logging │ │ │ └── logback │ │ │ ├── LogbackBatchingSettings.java │ │ │ ├── LoggingAppender.java │ │ │ ├── LoggingEventEnhancer.java │ │ │ ├── MDCEventEnhancer.java │ │ │ └── TraceLoggingEventEnhancer.java │ └── resources │ │ └── META-INF │ │ └── native-image │ │ └── com.google.cloud │ │ └── google-cloud-logging-logback │ │ └── reflect-config.json └── test │ └── java │ └── com │ └── google │ └── cloud │ └── logging │ └── logback │ ├── LoggingAppenderLogbackTest.java │ ├── LoggingAppenderTest.java │ ├── MDCEventEnhancerTest.java │ ├── StackTraceTest.java │ ├── TraceLoggingEventEnhancerTest.java │ ├── dummy-credentials.json │ └── logback.xml └── versions.txt /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Code owners file. 2 | # This file controls who is tagged for review for any given pull request. 3 | 4 | # For syntax help see: 5 | # https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax 6 | 7 | # @googleapis/yoshi-java @googleapis/api-logging @googleapis/api-logging-partners are the default owners for changes in this repo 8 | * @googleapis/yoshi-java @googleapis/api-logging @googleapis/api-logging-partners 9 | **/*.java @googleapis/api-logging @googleapis/api-logging-partners @googleapis/cloud-java-team-teamsync 10 | 11 | # @googleapis/java-samples-reviewers @googleapis/api-logging @googleapis/api-logging-partners teams are the default owners for samples changes 12 | samples/**/*.java @googleapis/java-samples-reviewers @googleapis/api-logging @googleapis/api-logging-partners 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | Thanks for stopping by to let us know something could be better! 8 | 9 | **PLEASE READ**: If you have a support contract with Google, please create an issue in the [support console](https://cloud.google.com/support/) instead of filing on GitHub. This will ensure a timely response. 10 | 11 | Please run down the following list and make sure you've tried the usual "quick fixes": 12 | 13 | - Search the issues already opened: https://github.com/googleapis/java-logging-logback/issues 14 | - Check for answers on StackOverflow: http://stackoverflow.com/questions/tagged/google-cloud-platform 15 | 16 | If you are still having issues, please include as much information as possible: 17 | 18 | #### Environment details 19 | 20 | 1. Specify the API at the beginning of the title. For example, "BigQuery: ..."). 21 | General, Core, and Other are also allowed as types 22 | 2. OS type and version: 23 | 3. Java version: 24 | 4. version(s): 25 | 26 | #### Steps to reproduce 27 | 28 | 1. ? 29 | 2. ? 30 | 31 | #### Code example 32 | 33 | ```java 34 | // example 35 | ``` 36 | 37 | #### Stack trace 38 | ``` 39 | Any relevant stacktrace here. 40 | ``` 41 | 42 | #### External references such as API reference guides 43 | 44 | - ? 45 | 46 | #### Any additional information below 47 | 48 | 49 | Following these steps guarantees the quickest resolution possible. 50 | 51 | Thanks! 52 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this library 4 | 5 | --- 6 | 7 | Thanks for stopping by to let us know something could be better! 8 | 9 | **PLEASE READ**: If you have a support contract with Google, please create an issue in the [support console](https://cloud.google.com/support/) instead of filing on GitHub. This will ensure a timely response. 10 | 11 | **Is your feature request related to a problem? Please describe.** 12 | What the problem is. Example: I'm always frustrated when [...] 13 | 14 | **Describe the solution you'd like** 15 | What you want to happen. 16 | 17 | **Describe alternatives you've considered** 18 | Any alternative solutions or features you've considered. 19 | 20 | **Additional context** 21 | Any other context or screenshots about the feature request. 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/support_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Support request 3 | about: If you have a support contract with Google, please create an issue in the Google Cloud Support console. 4 | 5 | --- 6 | 7 | **PLEASE READ**: If you have a support contract with Google, please create an issue in the [support console](https://cloud.google.com/support/) instead of filing on GitHub. This will ensure a timely response. 8 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly: 2 | - [ ] Make sure to open an issue as a [bug/issue](https://github.com/googleapis/java-logging-logback/issues/new/choose) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea 3 | - [ ] Ensure the tests and linter pass 4 | - [ ] Code coverage does not decrease (if any source code was changed) 5 | - [ ] Appropriate docs were updated (if necessary) 6 | 7 | Fixes # ☕️ 8 | 9 | If you write sample code, please follow the [samples format]( 10 | https://github.com/GoogleCloudPlatform/java-docs-samples/blob/main/SAMPLE_FORMAT.md). 11 | -------------------------------------------------------------------------------- /.github/auto-label.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | requestsize: 15 | enabled: true 16 | staleness: 17 | pullrequest: true 18 | old: 30 19 | extraold: 60 20 | -------------------------------------------------------------------------------- /.github/blunderbuss.yml: -------------------------------------------------------------------------------- 1 | # Configuration for the Blunderbuss GitHub app. For more info see 2 | # https://github.com/googleapis/repo-automation-bots/tree/main/packages/blunderbuss 3 | assign_issues: 4 | - googleapis/api-logging-java-reviewers 5 | assign_prs: 6 | - googleapis/api-logging-java-reviewers 7 | assign_prs_by: 8 | - labels: 9 | - samples 10 | to: 11 | - googleapis/java-samples-reviewers 12 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "maven" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | # Disable version updates for Maven dependencies 8 | # we use renovate-bot as well as shared-dependencies BOM to update maven dependencies. 9 | ignore: 10 | - dependency-name: "*" 11 | - package-ecosystem: "pip" 12 | directory: "/" 13 | schedule: 14 | interval: "daily" 15 | # Disable version updates for pip dependencies 16 | # If a security vulnerability comes in, we will be notified about 17 | # it via template in the synthtool repository. 18 | ignore: 19 | - dependency-name: "*" 20 | -------------------------------------------------------------------------------- /.github/release-please.yml: -------------------------------------------------------------------------------- 1 | bumpMinorPreMajor: true 2 | handleGHRelease: true 3 | releaseType: java-yoshi 4 | branches: 5 | - bumpMinorPreMajor: true 6 | handleGHRelease: true 7 | releaseType: java-yoshi 8 | branch: java7 9 | extraFiles: 10 | - src/main/java/com/google/cloud/logging/logback/LoggingAppender.java 11 | -------------------------------------------------------------------------------- /.github/release-trigger.yml: -------------------------------------------------------------------------------- 1 | enabled: true 2 | multiScmName: java-logging-logback 3 | -------------------------------------------------------------------------------- /.github/snippet-bot.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/googleapis/java-logging-logback/e64b094f61630704514b2d08840b13f66b579155/.github/snippet-bot.yml -------------------------------------------------------------------------------- /.github/sync-repo-settings.yaml: -------------------------------------------------------------------------------- 1 | rebaseMergeAllowed: false 2 | squashMergeAllowed: true 3 | mergeCommitAllowed: false 4 | branchProtectionRules: 5 | - pattern: main 6 | isAdminEnforced: true 7 | requiredApprovingReviewCount: 1 8 | requiresCodeOwnerReviews: true 9 | requiresStrictStatusChecks: false 10 | requiredStatusCheckContexts: 11 | - dependencies (17) 12 | - lint 13 | - clirr 14 | - units (8) 15 | - units (11) 16 | - 'Kokoro - Test: Integration' 17 | - cla/google 18 | - javadoc 19 | - unmanaged_dependency_check 20 | - pattern: java7 21 | isAdminEnforced: true 22 | requiredApprovingReviewCount: 1 23 | requiresCodeOwnerReviews: true 24 | requiresStrictStatusChecks: false 25 | requiredStatusCheckContexts: 26 | - dependencies (8) 27 | - dependencies (11) 28 | - lint 29 | - clirr 30 | - units (7) 31 | - units (8) 32 | - units (11) 33 | - 'Kokoro - Test: Integration' 34 | - cla/google 35 | permissionRules: 36 | - team: yoshi-admins 37 | permission: admin 38 | - team: yoshi-java-admins 39 | permission: admin 40 | - team: yoshi-java 41 | permission: push 42 | - team: api-logging-partners 43 | permission: push 44 | -------------------------------------------------------------------------------- /.github/trusted-contribution.yml: -------------------------------------------------------------------------------- 1 | trustedContributors: 2 | - renovate-bot 3 | - gcf-owl-bot[bot] 4 | 5 | annotations: 6 | - type: comment 7 | text: "/gcbrun" 8 | - type: label 9 | text: "kokoro:force-run" 10 | -------------------------------------------------------------------------------- /.github/workflows/approve-readme.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # Github action job to test core java library features on 15 | # downstream client libraries before they are released. 16 | on: 17 | pull_request: 18 | name: auto-merge-readme 19 | jobs: 20 | approve: 21 | runs-on: ubuntu-latest 22 | if: github.repository_owner == 'googleapis' && github.head_ref == 'autosynth-readme' 23 | steps: 24 | - uses: actions/github-script@v7 25 | with: 26 | github-token: ${{secrets.YOSHI_APPROVER_TOKEN}} 27 | script: | 28 | // only approve PRs from yoshi-automation 29 | if (context.payload.pull_request.user.login !== "yoshi-automation") { 30 | return; 31 | } 32 | 33 | // only approve PRs like "chore: release " 34 | if (!context.payload.pull_request.title === "chore: regenerate README") { 35 | return; 36 | } 37 | 38 | // only approve PRs with README.md and synth.metadata changes 39 | const files = new Set( 40 | ( 41 | await github.paginate( 42 | github.pulls.listFiles.endpoint({ 43 | owner: context.repo.owner, 44 | repo: context.repo.repo, 45 | pull_number: context.payload.pull_request.number, 46 | }) 47 | ) 48 | ).map(file => file.filename) 49 | ); 50 | if (files.size != 2 || !files.has("README.md") || !files.has(".github/readme/synth.metadata/synth.metadata")) { 51 | return; 52 | } 53 | 54 | // approve README regeneration PR 55 | await github.pulls.createReview({ 56 | owner: context.repo.owner, 57 | repo: context.repo.repo, 58 | body: 'Rubber stamped PR!', 59 | pull_number: context.payload.pull_request.number, 60 | event: 'APPROVE' 61 | }); 62 | 63 | // attach automerge label 64 | await github.issues.addLabels({ 65 | owner: context.repo.owner, 66 | repo: context.repo.repo, 67 | issue_number: context.payload.pull_request.number, 68 | labels: ['automerge'] 69 | }); 70 | -------------------------------------------------------------------------------- /.github/workflows/auto-release.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # Github action job to test core java library features on 15 | # downstream client libraries before they are released. 16 | on: 17 | pull_request: 18 | name: auto-release 19 | jobs: 20 | approve: 21 | runs-on: ubuntu-latest 22 | if: contains(github.head_ref, 'release-please') 23 | steps: 24 | - uses: actions/github-script@v7 25 | with: 26 | github-token: ${{secrets.YOSHI_APPROVER_TOKEN}} 27 | debug: true 28 | script: | 29 | // only approve PRs from release-please[bot] 30 | if (context.payload.pull_request.user.login !== "release-please[bot]") { 31 | return; 32 | } 33 | 34 | // only approve PRs like "chore(main): release " 35 | if ( !context.payload.pull_request.title.startsWith("chore(main): release") ) { 36 | return; 37 | } 38 | 39 | // only approve PRs with pom.xml and versions.txt changes 40 | const filesPromise = github.rest.pulls.listFiles.endpoint({ 41 | owner: context.repo.owner, 42 | repo: context.repo.repo, 43 | pull_number: context.payload.pull_request.number, 44 | }); 45 | const changed_files = await github.paginate(filesPromise) 46 | 47 | if ( changed_files.length < 1 ) { 48 | console.log( "Not proceeding since PR is empty!" ) 49 | return; 50 | } 51 | 52 | if ( !changed_files.some(v => v.filename.includes("pom")) || !changed_files.some(v => v.filename.includes("versions.txt")) ) { 53 | console.log( "PR file changes do not have pom.xml or versions.txt -- something is wrong. PTAL!" ) 54 | return; 55 | } 56 | 57 | // trigger auto-release when 58 | // 1) it is a SNAPSHOT release (auto-generated post regular release) 59 | // 2) there are dependency updates only 60 | // 3) there are no open dependency update PRs in this repo (to avoid multiple releases) 61 | if ( 62 | context.payload.pull_request.body.includes("Fix") || 63 | context.payload.pull_request.body.includes("Build") || 64 | context.payload.pull_request.body.includes("Documentation") || 65 | context.payload.pull_request.body.includes("BREAKING CHANGES") || 66 | context.payload.pull_request.body.includes("Features") 67 | ) { 68 | console.log( "Not auto-releasing since it is not a dependency-update-only release." ); 69 | return; 70 | } 71 | 72 | const promise = github.rest.pulls.list.endpoint({ 73 | owner: context.repo.owner, 74 | repo: context.repo.repo, 75 | state: 'open' 76 | }); 77 | const open_pulls = await github.paginate(promise) 78 | 79 | if ( open_pulls.length > 1 && !context.payload.pull_request.title.includes("SNAPSHOT") ) { 80 | for ( const pull of open_pulls ) { 81 | if ( pull.title.startsWith("deps: update dependency") ) { 82 | console.log( "Not auto-releasing yet since there are dependency update PRs open in this repo." ); 83 | return; 84 | } 85 | } 86 | } 87 | 88 | // approve release PR 89 | await github.rest.pulls.createReview({ 90 | owner: context.repo.owner, 91 | repo: context.repo.repo, 92 | body: 'Rubber stamped release!', 93 | pull_number: context.payload.pull_request.number, 94 | event: 'APPROVE' 95 | }); 96 | 97 | // attach kokoro:force-run and automerge labels 98 | await github.rest.issues.addLabels({ 99 | owner: context.repo.owner, 100 | repo: context.repo.repo, 101 | issue_number: context.payload.pull_request.number, 102 | labels: ['kokoro:force-run', 'automerge'] 103 | }); 104 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # Github action job to test core java library features on 15 | # downstream client libraries before they are released. 16 | on: 17 | push: 18 | branches: 19 | - main 20 | pull_request: 21 | name: ci 22 | jobs: 23 | units: 24 | runs-on: ubuntu-latest 25 | strategy: 26 | fail-fast: false 27 | matrix: 28 | java: [11, 17, 21] 29 | steps: 30 | - uses: actions/checkout@v4 31 | - uses: actions/setup-java@v4 32 | with: 33 | distribution: temurin 34 | java-version: ${{matrix.java}} 35 | - run: java -version 36 | - run: .kokoro/build.sh 37 | env: 38 | JOB_TYPE: test 39 | units-java8: 40 | # Building using Java 17 and run the tests with Java 8 runtime 41 | name: "units (8)" 42 | runs-on: ubuntu-latest 43 | steps: 44 | - uses: actions/checkout@v4 45 | - uses: actions/setup-java@v4 46 | with: 47 | java-version: 8 48 | distribution: temurin 49 | - name: "Set jvm system property environment variable for surefire plugin (unit tests)" 50 | # Maven surefire plugin (unit tests) allows us to specify JVM to run the tests. 51 | # https://maven.apache.org/surefire/maven-surefire-plugin/test-mojo.html#jvm 52 | run: echo "SUREFIRE_JVM_OPT=-Djvm=${JAVA_HOME}/bin/java" >> $GITHUB_ENV 53 | shell: bash 54 | - uses: actions/setup-java@v4 55 | with: 56 | java-version: 17 57 | distribution: temurin 58 | - run: .kokoro/build.sh 59 | env: 60 | JOB_TYPE: test 61 | windows: 62 | runs-on: windows-latest 63 | steps: 64 | - name: Support longpaths 65 | run: git config --system core.longpaths true 66 | - uses: actions/checkout@v4 67 | - uses: actions/setup-java@v4 68 | with: 69 | distribution: temurin 70 | java-version: 8 71 | - run: java -version 72 | - run: .kokoro/build.bat 73 | env: 74 | JOB_TYPE: test 75 | dependencies: 76 | runs-on: ubuntu-latest 77 | strategy: 78 | matrix: 79 | java: [17] 80 | steps: 81 | - uses: actions/checkout@v4 82 | - uses: actions/setup-java@v4 83 | with: 84 | distribution: temurin 85 | java-version: ${{matrix.java}} 86 | - run: java -version 87 | - run: .kokoro/dependencies.sh 88 | javadoc: 89 | runs-on: ubuntu-latest 90 | steps: 91 | - uses: actions/checkout@v4 92 | - uses: actions/setup-java@v4 93 | with: 94 | distribution: temurin 95 | java-version: 17 96 | - run: java -version 97 | - run: .kokoro/build.sh 98 | env: 99 | JOB_TYPE: javadoc 100 | lint: 101 | runs-on: ubuntu-latest 102 | steps: 103 | - uses: actions/checkout@v4 104 | - uses: actions/setup-java@v4 105 | with: 106 | distribution: temurin 107 | java-version: 17 108 | - run: java -version 109 | - run: .kokoro/build.sh 110 | env: 111 | JOB_TYPE: lint 112 | clirr: 113 | runs-on: ubuntu-latest 114 | steps: 115 | - uses: actions/checkout@v4 116 | - uses: actions/setup-java@v4 117 | with: 118 | distribution: temurin 119 | java-version: 8 120 | - run: java -version 121 | - run: .kokoro/build.sh 122 | env: 123 | JOB_TYPE: clirr 124 | -------------------------------------------------------------------------------- /.github/workflows/renovate_config_check.yaml: -------------------------------------------------------------------------------- 1 | name: Renovate Bot Config Validation 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - 'renovate.json' 7 | 8 | jobs: 9 | renovate_bot_config_validation: 10 | runs-on: ubuntu-22.04 11 | 12 | steps: 13 | - name: Checkout code 14 | uses: actions/checkout@v4 15 | 16 | - name: Set up Node.js 17 | uses: actions/setup-node@v4 18 | with: 19 | node-version: '20' 20 | 21 | - name: Install Renovate and Config Validator 22 | run: | 23 | npm install -g npm@latest 24 | npm install --global renovate 25 | renovate-config-validator 26 | -------------------------------------------------------------------------------- /.github/workflows/samples.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # Github action job to test core java library features on 15 | # downstream client libraries before they are released. 16 | on: 17 | pull_request: 18 | name: samples 19 | jobs: 20 | checkstyle: 21 | runs-on: ubuntu-latest 22 | steps: 23 | - uses: actions/checkout@v4 24 | - uses: actions/setup-java@v4 25 | with: 26 | distribution: temurin 27 | java-version: 8 28 | - name: Run checkstyle 29 | run: mvn -P lint --quiet --batch-mode checkstyle:check 30 | working-directory: samples/snippets 31 | -------------------------------------------------------------------------------- /.github/workflows/unmanaged_dependency_check.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | pull_request: 3 | name: Unmanaged dependency check 4 | jobs: 5 | unmanaged_dependency_check: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - uses: actions/checkout@v4 9 | - uses: actions/setup-java@v4 10 | with: 11 | distribution: temurin 12 | java-version: 11 13 | - name: Install modules 14 | shell: bash 15 | run: .kokoro/build.sh 16 | - name: Unmanaged dependency check 17 | uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.49.0 18 | with: 19 | bom-path: pom.xml 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | 3 | # Packages 4 | dist 5 | bin 6 | var 7 | sdist 8 | target 9 | 10 | # Unit test / coverage reports 11 | .coverage 12 | .tox 13 | nosetests.xml 14 | 15 | # Translations 16 | *.mo 17 | 18 | # Mr Developer 19 | .mr.developer.cfg 20 | 21 | .metadata 22 | .project 23 | .pydevproject 24 | *.iml 25 | .idea 26 | .settings 27 | .DS_Store 28 | .classpath 29 | 30 | # Built documentation 31 | docs/ 32 | 33 | 34 | # Wheel directory used in Travis builds. 35 | gcloud-java-wheels/ 36 | src/test/resources/gcd-head.zip 37 | src/test/resources/gcd-v1beta2-rev1-2.1.1.zip 38 | 39 | # API key file containing value of GOOGLE_API_KEY for integration tests 40 | api_key 41 | 42 | # Python utilities 43 | *.pyc 44 | artman-genfiles 45 | venv 46 | 47 | .flattened-pom.xml -------------------------------------------------------------------------------- /.kokoro/build.bat: -------------------------------------------------------------------------------- 1 | :: Copyright 2022 Google LLC 2 | :: 3 | :: Licensed under the Apache License, Version 2.0 (the "License"); 4 | :: you may not use this file except in compliance with the License. 5 | :: You may obtain a copy of the License at 6 | :: 7 | :: http://www.apache.org/licenses/LICENSE-2.0 8 | :: 9 | :: Unless required by applicable law or agreed to in writing, software 10 | :: distributed under the License is distributed on an "AS IS" BASIS, 11 | :: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | :: See the License for the specific language governing permissions and 13 | :: limitations under the License. 14 | :: Github action job to test core java library features on 15 | :: downstream client libraries before they are released. 16 | :: See documentation in type-shell-output.bat 17 | 18 | "C:\Program Files\Git\bin\bash.exe" %~dp0build.sh 19 | -------------------------------------------------------------------------------- /.kokoro/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2019 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | set -eo pipefail 17 | 18 | ## Get the directory of the build script 19 | scriptDir=$(realpath $(dirname "${BASH_SOURCE[0]}")) 20 | ## cd to the parent directory, i.e. the root of the git repo 21 | cd ${scriptDir}/.. 22 | 23 | # include common functions 24 | source ${scriptDir}/common.sh 25 | 26 | # Print out Maven & Java version 27 | mvn -version 28 | echo ${JOB_TYPE} 29 | 30 | # attempt to install 3 times with exponential backoff (starting with 10 seconds) 31 | retry_with_backoff 3 10 \ 32 | mvn install -B -V -ntp \ 33 | -DskipTests=true \ 34 | -Dclirr.skip=true \ 35 | -Denforcer.skip=true \ 36 | -Dmaven.javadoc.skip=true \ 37 | -Dgcloud.download.skip=true \ 38 | -T 1C 39 | 40 | # if GOOGLE_APPLICATION_CREDENTIALS is specified as a relative path, prepend Kokoro root directory onto it 41 | if [[ ! -z "${GOOGLE_APPLICATION_CREDENTIALS}" && "${GOOGLE_APPLICATION_CREDENTIALS}" != /* ]]; then 42 | export GOOGLE_APPLICATION_CREDENTIALS=$(realpath ${KOKORO_GFILE_DIR}/${GOOGLE_APPLICATION_CREDENTIALS}) 43 | fi 44 | 45 | RETURN_CODE=0 46 | set +e 47 | 48 | case ${JOB_TYPE} in 49 | test) 50 | echo "SUREFIRE_JVM_OPT: ${SUREFIRE_JVM_OPT}" 51 | mvn test -B -ntp -Dclirr.skip=true -Denforcer.skip=true ${SUREFIRE_JVM_OPT} 52 | RETURN_CODE=$? 53 | ;; 54 | lint) 55 | mvn com.spotify.fmt:fmt-maven-plugin:check -B -ntp 56 | RETURN_CODE=$? 57 | ;; 58 | javadoc) 59 | mvn javadoc:javadoc javadoc:test-javadoc -B -ntp 60 | RETURN_CODE=$? 61 | ;; 62 | integration) 63 | mvn -B ${INTEGRATION_TEST_ARGS} \ 64 | -ntp \ 65 | -Penable-integration-tests \ 66 | -DtrimStackTrace=false \ 67 | -Dclirr.skip=true \ 68 | -Denforcer.skip=true \ 69 | -fae \ 70 | verify 71 | RETURN_CODE=$? 72 | ;; 73 | graalvm) 74 | # Run Unit and Integration Tests with Native Image 75 | mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative test 76 | RETURN_CODE=$? 77 | ;; 78 | samples) 79 | SAMPLES_DIR=samples 80 | # only run ITs in snapshot/ on presubmit PRs. run ITs in all 3 samples/ subdirectories otherwise. 81 | if [[ ! -z ${KOKORO_GITHUB_PULL_REQUEST_NUMBER} ]] 82 | then 83 | SAMPLES_DIR=samples/snapshot 84 | fi 85 | 86 | if [[ -f ${SAMPLES_DIR}/pom.xml ]] 87 | then 88 | for FILE in ${KOKORO_GFILE_DIR}/secret_manager/*-samples-secrets; do 89 | [[ -f "$FILE" ]] || continue 90 | source "$FILE" 91 | done 92 | 93 | pushd ${SAMPLES_DIR} 94 | mvn -B \ 95 | -ntp \ 96 | -DtrimStackTrace=false \ 97 | -Dclirr.skip=true \ 98 | -Denforcer.skip=true \ 99 | -fae \ 100 | verify 101 | RETURN_CODE=$? 102 | popd 103 | else 104 | echo "no sample pom.xml found - skipping sample tests" 105 | fi 106 | ;; 107 | clirr) 108 | mvn -B -ntp -Denforcer.skip=true clirr:check 109 | RETURN_CODE=$? 110 | ;; 111 | *) 112 | ;; 113 | esac 114 | 115 | if [ "${REPORT_COVERAGE}" == "true" ] 116 | then 117 | bash ${KOKORO_GFILE_DIR}/codecov.sh 118 | fi 119 | 120 | # fix output location of logs 121 | bash .kokoro/coerce_logs.sh 122 | 123 | if [[ "${ENABLE_FLAKYBOT}" == "true" ]] 124 | then 125 | chmod +x ${KOKORO_GFILE_DIR}/linux_amd64/flakybot 126 | ${KOKORO_GFILE_DIR}/linux_amd64/flakybot -repo=googleapis/java-logging-logback 127 | fi 128 | 129 | echo "exiting with ${RETURN_CODE}" 130 | exit ${RETURN_CODE} 131 | -------------------------------------------------------------------------------- /.kokoro/coerce_logs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2019 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | # This script finds and moves sponge logs so that they can be found by placer 17 | # and are not flagged as flaky by sponge. 18 | 19 | set -eo pipefail 20 | 21 | ## Get the directory of the build script 22 | scriptDir=$(realpath $(dirname "${BASH_SOURCE[0]}")) 23 | ## cd to the parent directory, i.e. the root of the git repo 24 | cd ${scriptDir}/.. 25 | 26 | job=$(basename ${KOKORO_JOB_NAME}) 27 | 28 | echo "coercing sponge logs..." 29 | for xml in `find . -name *-sponge_log.xml` 30 | do 31 | class=$(basename ${xml} | cut -d- -f2) 32 | dir=$(dirname ${xml})/${job}/${class} 33 | text=$(dirname ${xml})/${class}-sponge_log.txt 34 | mkdir -p ${dir} 35 | mv ${xml} ${dir}/sponge_log.xml 36 | mv ${text} ${dir}/sponge_log.txt 37 | done 38 | -------------------------------------------------------------------------------- /.kokoro/common.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Download trampoline resources. These will be in ${KOKORO_GFILE_DIR} 4 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 5 | 6 | # All builds use the trampoline script to run in docker. 7 | build_file: "java-logging-logback/.kokoro/trampoline.sh" 8 | 9 | # Tell the trampoline which build file to use. 10 | env_vars: { 11 | key: "TRAMPOLINE_BUILD_FILE" 12 | value: "github/java-logging-logback/.kokoro/build.sh" 13 | } 14 | 15 | 16 | ############################################# 17 | # this section merged from .kokoro/common_env_vars.cfg using owlbot.py 18 | 19 | env_vars: { 20 | key: "PRODUCT_AREA_LABEL" 21 | value: "observability" 22 | } 23 | env_vars: { 24 | key: "PRODUCT_LABEL" 25 | value: "logging" 26 | } 27 | env_vars: { 28 | key: "LANGUAGE_LABEL" 29 | value: "java" 30 | } 31 | 32 | ################################################### 33 | 34 | -------------------------------------------------------------------------------- /.kokoro/common.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2020 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | function retry_with_backoff { 17 | attempts_left=$1 18 | sleep_seconds=$2 19 | shift 2 20 | command=$@ 21 | 22 | 23 | # store current flag state 24 | flags=$- 25 | 26 | # allow a failures to continue 27 | set +e 28 | ${command} 29 | exit_code=$? 30 | 31 | # restore "e" flag 32 | if [[ ${flags} =~ e ]] 33 | then set -e 34 | else set +e 35 | fi 36 | 37 | if [[ $exit_code == 0 ]] 38 | then 39 | return 0 40 | fi 41 | 42 | # failure 43 | if [[ ${attempts_left} > 0 ]] 44 | then 45 | echo "failure (${exit_code}), sleeping ${sleep_seconds}..." 46 | sleep ${sleep_seconds} 47 | new_attempts=$((${attempts_left} - 1)) 48 | new_sleep=$((${sleep_seconds} * 2)) 49 | retry_with_backoff ${new_attempts} ${new_sleep} ${command} 50 | fi 51 | 52 | return $exit_code 53 | } 54 | 55 | ## Helper functionss 56 | function now() { date +"%Y-%m-%d %H:%M:%S" | tr -d '\n'; } 57 | function msg() { println "$*" >&2; } 58 | function println() { printf '%s\n' "$(now) $*"; } 59 | 60 | ## Helper comment to trigger updated repo dependency release -------------------------------------------------------------------------------- /.kokoro/common_env_vars.cfg: -------------------------------------------------------------------------------- 1 | 2 | ############################################# 3 | # this section merged from .kokoro/common_env_vars.cfg using owlbot.py 4 | 5 | env_vars: { 6 | key: "PRODUCT_AREA_LABEL" 7 | value: "observability" 8 | } 9 | env_vars: { 10 | key: "PRODUCT_LABEL" 11 | value: "logging" 12 | } 13 | env_vars: { 14 | key: "LANGUAGE_LABEL" 15 | value: "java" 16 | } 17 | 18 | ################################################### 19 | 20 | -------------------------------------------------------------------------------- /.kokoro/continuous/common.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Build logs will be here 4 | action { 5 | define_artifacts { 6 | regex: "**/*sponge_log.xml" 7 | regex: "**/*sponge_log.txt" 8 | } 9 | } 10 | 11 | # Download trampoline resources. 12 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 13 | 14 | # Use the trampoline script to run in docker. 15 | build_file: "java-logging-logback/.kokoro/trampoline.sh" 16 | 17 | env_vars: { 18 | key: "TRAMPOLINE_BUILD_FILE" 19 | value: "github/java-logging-logback/.kokoro/build.sh" 20 | } 21 | 22 | env_vars: { 23 | key: "JOB_TYPE" 24 | value: "test" 25 | } 26 | 27 | 28 | ############################################# 29 | # this section merged from .kokoro/common_env_vars.cfg using owlbot.py 30 | 31 | env_vars: { 32 | key: "PRODUCT_AREA_LABEL" 33 | value: "observability" 34 | } 35 | env_vars: { 36 | key: "PRODUCT_LABEL" 37 | value: "logging" 38 | } 39 | env_vars: { 40 | key: "LANGUAGE_LABEL" 41 | value: "java" 42 | } 43 | 44 | ################################################### 45 | 46 | -------------------------------------------------------------------------------- /.kokoro/continuous/java8.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Configure the docker image for kokoro-trampoline. 4 | env_vars: { 5 | key: "TRAMPOLINE_IMAGE" 6 | value: "gcr.io/cloud-devrel-kokoro-resources/java8" 7 | } 8 | 9 | env_vars: { 10 | key: "REPORT_COVERAGE" 11 | value: "true" 12 | } 13 | -------------------------------------------------------------------------------- /.kokoro/continuous/propose_release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2019 Google LLC 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -eo pipefail 18 | 19 | export NPM_CONFIG_PREFIX=/home/node/.npm-global 20 | 21 | if [ -f ${KOKORO_KEYSTORE_DIR}/73713_github-magic-proxy-url-release-please ]; then 22 | # Groom the release PR as new commits are merged. 23 | npx release-please release-pr --token=${KOKORO_KEYSTORE_DIR}/73713_github-magic-proxy-token-release-please \ 24 | --repo-url=googleapis/java-logging-logback \ 25 | --package-name="logging-logback" \ 26 | --api-url=${KOKORO_KEYSTORE_DIR}/73713_github-magic-proxy-url-release-please \ 27 | --proxy-key=${KOKORO_KEYSTORE_DIR}/73713_github-magic-proxy-key-release-please \ 28 | --release-type=java-yoshi 29 | fi 30 | -------------------------------------------------------------------------------- /.kokoro/dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2019 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | set -eo pipefail 17 | shopt -s nullglob 18 | 19 | ## Get the directory of the build script 20 | scriptDir=$(realpath $(dirname "${BASH_SOURCE[0]}")) 21 | ## cd to the parent directory, i.e. the root of the git repo 22 | cd ${scriptDir}/.. 23 | 24 | # include common functions 25 | source ${scriptDir}/common.sh 26 | 27 | # Print out Java 28 | java -version 29 | echo $JOB_TYPE 30 | 31 | function determineMavenOpts() { 32 | local javaVersion=$( 33 | # filter down to the version line, then pull out the version between quotes, 34 | # then trim the version number down to its minimal number (removing any 35 | # update or suffix number). 36 | java -version 2>&1 | grep "version" \ 37 | | sed -E 's/^.*"(.*?)".*$/\1/g' \ 38 | | sed -E 's/^(1\.[0-9]\.0).*$/\1/g' 39 | ) 40 | 41 | if [[ $javaVersion == 17* ]] 42 | then 43 | # MaxPermSize is no longer supported as of jdk 17 44 | echo -n "-Xmx1024m" 45 | else 46 | echo -n "-Xmx1024m -XX:MaxPermSize=128m" 47 | fi 48 | } 49 | 50 | export MAVEN_OPTS=$(determineMavenOpts) 51 | 52 | # this should run maven enforcer 53 | retry_with_backoff 3 10 \ 54 | mvn install -B -V -ntp \ 55 | -DskipTests=true \ 56 | -Dmaven.javadoc.skip=true \ 57 | -Dclirr.skip=true 58 | 59 | mvn -B dependency:analyze -DfailOnWarning=true 60 | -------------------------------------------------------------------------------- /.kokoro/nightly/common.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Build logs will be here 4 | action { 5 | define_artifacts { 6 | regex: "**/*sponge_log.xml" 7 | regex: "**/*sponge_log.txt" 8 | } 9 | } 10 | 11 | # Download trampoline resources. 12 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 13 | 14 | # Use the trampoline script to run in docker. 15 | build_file: "java-logging-logback/.kokoro/trampoline.sh" 16 | 17 | env_vars: { 18 | key: "TRAMPOLINE_BUILD_FILE" 19 | value: "github/java-logging-logback/.kokoro/build.sh" 20 | } 21 | 22 | env_vars: { 23 | key: "JOB_TYPE" 24 | value: "test" 25 | } 26 | 27 | 28 | ############################################# 29 | # this section merged from .kokoro/common_env_vars.cfg using owlbot.py 30 | 31 | env_vars: { 32 | key: "PRODUCT_AREA_LABEL" 33 | value: "observability" 34 | } 35 | env_vars: { 36 | key: "PRODUCT_LABEL" 37 | value: "logging" 38 | } 39 | env_vars: { 40 | key: "LANGUAGE_LABEL" 41 | value: "java" 42 | } 43 | 44 | ################################################### 45 | 46 | -------------------------------------------------------------------------------- /.kokoro/nightly/integration.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Configure the docker image for kokoro-trampoline. 4 | env_vars: { 5 | key: "TRAMPOLINE_IMAGE" 6 | value: "gcr.io/cloud-devrel-kokoro-resources/java8" 7 | } 8 | 9 | env_vars: { 10 | key: "JOB_TYPE" 11 | value: "integration" 12 | } 13 | # TODO: remove this after we've migrated all tests and scripts 14 | env_vars: { 15 | key: "GCLOUD_PROJECT" 16 | value: "java-docs-samples-testing" 17 | } 18 | 19 | env_vars: { 20 | key: "GOOGLE_CLOUD_PROJECT" 21 | value: "java-docs-samples-testing" 22 | } 23 | 24 | env_vars: { 25 | key: "ENABLE_FLAKYBOT" 26 | value: "true" 27 | } 28 | 29 | env_vars: { 30 | key: "GOOGLE_APPLICATION_CREDENTIALS" 31 | value: "secret_manager/java-it-service-account" 32 | } 33 | 34 | env_vars: { 35 | key: "SECRET_MANAGER_KEYS" 36 | value: "java-it-service-account" 37 | } 38 | 39 | -------------------------------------------------------------------------------- /.kokoro/nightly/java11-integration.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Configure the docker image for kokoro-trampoline. 4 | env_vars: { 5 | key: "TRAMPOLINE_IMAGE" 6 | value: "gcr.io/cloud-devrel-public-resources/java11014" 7 | } 8 | 9 | env_vars: { 10 | key: "JOB_TYPE" 11 | value: "integration" 12 | } 13 | # TODO: remove this after we've migrated all tests and scripts 14 | env_vars: { 15 | key: "GCLOUD_PROJECT" 16 | value: "gcloud-devel" 17 | } 18 | 19 | env_vars: { 20 | key: "GOOGLE_CLOUD_PROJECT" 21 | value: "gcloud-devel" 22 | } 23 | 24 | env_vars: { 25 | key: "ENABLE_FLAKYBOT" 26 | value: "true" 27 | } 28 | 29 | env_vars: { 30 | key: "GOOGLE_APPLICATION_CREDENTIALS" 31 | value: "secret_manager/java-it-service-account" 32 | } 33 | 34 | env_vars: { 35 | key: "SECRET_MANAGER_KEYS" 36 | value: "java-it-service-account" 37 | } 38 | 39 | -------------------------------------------------------------------------------- /.kokoro/nightly/java11.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Configure the docker image for kokoro-trampoline. 4 | env_vars: { 5 | key: "TRAMPOLINE_IMAGE" 6 | value: "gcr.io/cloud-devrel-kokoro-resources/java11" 7 | } 8 | -------------------------------------------------------------------------------- /.kokoro/nightly/java7.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Configure the docker image for kokoro-trampoline. 4 | env_vars: { 5 | key: "TRAMPOLINE_IMAGE" 6 | value: "gcr.io/cloud-devrel-kokoro-resources/java7" 7 | } 8 | -------------------------------------------------------------------------------- /.kokoro/nightly/java8-osx.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | build_file: "java-logging-logback/.kokoro/build.sh" 4 | -------------------------------------------------------------------------------- /.kokoro/nightly/java8-win.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | build_file: "java-logging-logback/.kokoro/build.bat" 4 | -------------------------------------------------------------------------------- /.kokoro/nightly/java8.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Configure the docker image for kokoro-trampoline. 4 | env_vars: { 5 | key: "TRAMPOLINE_IMAGE" 6 | value: "gcr.io/cloud-devrel-kokoro-resources/java8" 7 | } 8 | 9 | env_vars: { 10 | key: "REPORT_COVERAGE" 11 | value: "true" 12 | } 13 | -------------------------------------------------------------------------------- /.kokoro/nightly/samples.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Configure the docker image for kokoro-trampoline. 4 | env_vars: { 5 | key: "TRAMPOLINE_IMAGE" 6 | value: "gcr.io/cloud-devrel-kokoro-resources/java8" 7 | } 8 | 9 | env_vars: { 10 | key: "JOB_TYPE" 11 | value: "samples" 12 | } 13 | 14 | # TODO: remove this after we've migrated all tests and scripts 15 | env_vars: { 16 | key: "GCLOUD_PROJECT" 17 | value: "java-docs-samples-testing" 18 | } 19 | 20 | env_vars: { 21 | key: "GOOGLE_CLOUD_PROJECT" 22 | value: "java-docs-samples-testing" 23 | } 24 | 25 | env_vars: { 26 | key: "GOOGLE_APPLICATION_CREDENTIALS" 27 | value: "secret_manager/java-docs-samples-service-account" 28 | } 29 | 30 | env_vars: { 31 | key: "SECRET_MANAGER_KEYS" 32 | value: "java-docs-samples-service-account" 33 | } 34 | 35 | env_vars: { 36 | key: "ENABLE_FLAKYBOT" 37 | value: "true" 38 | } 39 | -------------------------------------------------------------------------------- /.kokoro/populate-secrets.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2020 Google LLC. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | set -eo pipefail 17 | 18 | function now { date +"%Y-%m-%d %H:%M:%S" | tr -d '\n' ;} 19 | function msg { println "$*" >&2 ;} 20 | function println { printf '%s\n' "$(now) $*" ;} 21 | 22 | 23 | # Populates requested secrets set in SECRET_MANAGER_KEYS from service account: 24 | # kokoro-trampoline@cloud-devrel-kokoro-resources.iam.gserviceaccount.com 25 | SECRET_LOCATION="${KOKORO_GFILE_DIR}/secret_manager" 26 | msg "Creating folder on disk for secrets: ${SECRET_LOCATION}" 27 | mkdir -p ${SECRET_LOCATION} 28 | for key in $(echo ${SECRET_MANAGER_KEYS} | sed "s/,/ /g") 29 | do 30 | msg "Retrieving secret ${key}" 31 | docker run --entrypoint=gcloud \ 32 | --volume=${KOKORO_GFILE_DIR}:${KOKORO_GFILE_DIR} \ 33 | gcr.io/google.com/cloudsdktool/cloud-sdk \ 34 | secrets versions access latest \ 35 | --project cloud-devrel-kokoro-resources \ 36 | --secret ${key} > \ 37 | "${SECRET_LOCATION}/${key}" 38 | if [[ $? == 0 ]]; then 39 | msg "Secret written to ${SECRET_LOCATION}/${key}" 40 | else 41 | msg "Error retrieving secret ${key}" 42 | fi 43 | done 44 | -------------------------------------------------------------------------------- /.kokoro/presubmit/clirr.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Configure the docker image for kokoro-trampoline. 4 | 5 | env_vars: { 6 | key: "TRAMPOLINE_IMAGE" 7 | value: "gcr.io/cloud-devrel-kokoro-resources/java8" 8 | } 9 | 10 | env_vars: { 11 | key: "JOB_TYPE" 12 | value: "clirr" 13 | } -------------------------------------------------------------------------------- /.kokoro/presubmit/common.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Build logs will be here 4 | action { 5 | define_artifacts { 6 | regex: "**/*sponge_log.xml" 7 | regex: "**/*sponge_log.txt" 8 | } 9 | } 10 | 11 | # Download trampoline resources. 12 | gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" 13 | 14 | # Use the trampoline script to run in docker. 15 | build_file: "java-logging-logback/.kokoro/trampoline.sh" 16 | 17 | env_vars: { 18 | key: "TRAMPOLINE_BUILD_FILE" 19 | value: "github/java-logging-logback/.kokoro/build.sh" 20 | } 21 | 22 | env_vars: { 23 | key: "JOB_TYPE" 24 | value: "test" 25 | } 26 | 27 | before_action { 28 | fetch_keystore { 29 | keystore_resource { 30 | keystore_config_id: 73713 31 | keyname: "dpebot_codecov_token" 32 | } 33 | } 34 | } 35 | 36 | 37 | ############################################# 38 | # this section merged from .kokoro/common_env_vars.cfg using owlbot.py 39 | 40 | env_vars: { 41 | key: "PRODUCT_AREA_LABEL" 42 | value: "observability" 43 | } 44 | env_vars: { 45 | key: "PRODUCT_LABEL" 46 | value: "logging" 47 | } 48 | env_vars: { 49 | key: "LANGUAGE_LABEL" 50 | value: "java" 51 | } 52 | 53 | ################################################### 54 | 55 | -------------------------------------------------------------------------------- /.kokoro/presubmit/dependencies.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Configure the docker image for kokoro-trampoline. 4 | env_vars: { 5 | key: "TRAMPOLINE_IMAGE" 6 | value: "gcr.io/cloud-devrel-kokoro-resources/java8" 7 | } 8 | 9 | env_vars: { 10 | key: "TRAMPOLINE_BUILD_FILE" 11 | value: "github/java-logging-logback/.kokoro/dependencies.sh" 12 | } 13 | -------------------------------------------------------------------------------- /.kokoro/presubmit/graalvm-native-a.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Configure the docker image for kokoro-trampoline. 4 | env_vars: { 5 | key: "TRAMPOLINE_IMAGE" 6 | value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.49.0" 7 | } 8 | 9 | env_vars: { 10 | key: "JOB_TYPE" 11 | value: "graalvm" 12 | } 13 | 14 | # TODO: remove this after we've migrated all tests and scripts 15 | env_vars: { 16 | key: "GCLOUD_PROJECT" 17 | value: "gcloud-devel" 18 | } 19 | 20 | env_vars: { 21 | key: "GOOGLE_CLOUD_PROJECT" 22 | value: "gcloud-devel" 23 | } 24 | 25 | env_vars: { 26 | key: "GOOGLE_APPLICATION_CREDENTIALS" 27 | value: "secret_manager/java-it-service-account" 28 | } 29 | 30 | env_vars: { 31 | key: "SECRET_MANAGER_KEYS" 32 | value: "java-it-service-account" 33 | } 34 | -------------------------------------------------------------------------------- /.kokoro/presubmit/graalvm-native-b.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Configure the docker image for kokoro-trampoline. 4 | env_vars: { 5 | key: "TRAMPOLINE_IMAGE" 6 | value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.49.0" 7 | } 8 | 9 | env_vars: { 10 | key: "JOB_TYPE" 11 | value: "graalvm" 12 | } 13 | 14 | # TODO: remove this after we've migrated all tests and scripts 15 | env_vars: { 16 | key: "GCLOUD_PROJECT" 17 | value: "gcloud-devel" 18 | } 19 | 20 | env_vars: { 21 | key: "GOOGLE_CLOUD_PROJECT" 22 | value: "gcloud-devel" 23 | } 24 | 25 | env_vars: { 26 | key: "GOOGLE_APPLICATION_CREDENTIALS" 27 | value: "secret_manager/java-it-service-account" 28 | } 29 | 30 | env_vars: { 31 | key: "SECRET_MANAGER_KEYS" 32 | value: "java-it-service-account" 33 | } -------------------------------------------------------------------------------- /.kokoro/presubmit/graalvm-native-c.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Configure the docker image for kokoro-trampoline. 4 | env_vars: { 5 | key: "TRAMPOLINE_IMAGE" 6 | value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_c:3.49.0" 7 | } 8 | 9 | env_vars: { 10 | key: "JOB_TYPE" 11 | value: "graalvm17" 12 | } 13 | 14 | # TODO: remove this after we've migrated all tests and scripts 15 | env_vars: { 16 | key: "GCLOUD_PROJECT" 17 | value: "gcloud-devel" 18 | } 19 | 20 | env_vars: { 21 | key: "GOOGLE_CLOUD_PROJECT" 22 | value: "gcloud-devel" 23 | } 24 | 25 | env_vars: { 26 | key: "GOOGLE_APPLICATION_CREDENTIALS" 27 | value: "secret_manager/java-it-service-account" 28 | } 29 | 30 | env_vars: { 31 | key: "SECRET_MANAGER_KEYS" 32 | value: "java-it-service-account" 33 | } -------------------------------------------------------------------------------- /.kokoro/presubmit/integration.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Configure the docker image for kokoro-trampoline. 4 | env_vars: { 5 | key: "TRAMPOLINE_IMAGE" 6 | value: "gcr.io/cloud-devrel-kokoro-resources/java8" 7 | } 8 | 9 | env_vars: { 10 | key: "JOB_TYPE" 11 | value: "integration" 12 | } 13 | 14 | # TODO: remove this after we've migrated all tests and scripts 15 | env_vars: { 16 | key: "GCLOUD_PROJECT" 17 | value: "gcloud-devel" 18 | } 19 | 20 | env_vars: { 21 | key: "GOOGLE_CLOUD_PROJECT" 22 | value: "gcloud-devel" 23 | } 24 | 25 | env_vars: { 26 | key: "GOOGLE_APPLICATION_CREDENTIALS" 27 | value: "secret_manager/java-it-service-account" 28 | } 29 | 30 | env_vars: { 31 | key: "SECRET_MANAGER_KEYS" 32 | value: "java-it-service-account" 33 | } 34 | 35 | -------------------------------------------------------------------------------- /.kokoro/presubmit/java11.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Configure the docker image for kokoro-trampoline. 4 | env_vars: { 5 | key: "TRAMPOLINE_IMAGE" 6 | value: "gcr.io/cloud-devrel-kokoro-resources/java11" 7 | } 8 | -------------------------------------------------------------------------------- /.kokoro/presubmit/java7.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Configure the docker image for kokoro-trampoline. 4 | env_vars: { 5 | key: "TRAMPOLINE_IMAGE" 6 | value: "gcr.io/cloud-devrel-kokoro-resources/java7" 7 | } 8 | -------------------------------------------------------------------------------- /.kokoro/presubmit/java8-osx.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | build_file: "java-logging-logback/.kokoro/build.sh" 4 | -------------------------------------------------------------------------------- /.kokoro/presubmit/java8-win.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | build_file: "java-logging-logback/.kokoro/build.bat" 4 | -------------------------------------------------------------------------------- /.kokoro/presubmit/java8.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Configure the docker image for kokoro-trampoline. 4 | env_vars: { 5 | key: "TRAMPOLINE_IMAGE" 6 | value: "gcr.io/cloud-devrel-kokoro-resources/java8" 7 | } 8 | 9 | env_vars: { 10 | key: "REPORT_COVERAGE" 11 | value: "true" 12 | } 13 | -------------------------------------------------------------------------------- /.kokoro/presubmit/linkage-monitor.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Configure the docker image for kokoro-trampoline. 4 | env_vars: { 5 | key: "TRAMPOLINE_IMAGE" 6 | value: "gcr.io/cloud-devrel-kokoro-resources/java8" 7 | } 8 | 9 | env_vars: { 10 | key: "TRAMPOLINE_BUILD_FILE" 11 | value: "github/java-logging-logback/.kokoro/linkage-monitor.sh" 12 | } -------------------------------------------------------------------------------- /.kokoro/presubmit/lint.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Configure the docker image for kokoro-trampoline. 4 | 5 | env_vars: { 6 | key: "TRAMPOLINE_IMAGE" 7 | value: "gcr.io/cloud-devrel-kokoro-resources/java8" 8 | } 9 | 10 | env_vars: { 11 | key: "JOB_TYPE" 12 | value: "lint" 13 | } -------------------------------------------------------------------------------- /.kokoro/presubmit/samples.cfg: -------------------------------------------------------------------------------- 1 | # Format: //devtools/kokoro/config/proto/build.proto 2 | 3 | # Configure the docker image for kokoro-trampoline. 4 | env_vars: { 5 | key: "TRAMPOLINE_IMAGE" 6 | value: "gcr.io/cloud-devrel-kokoro-resources/java8" 7 | } 8 | 9 | env_vars: { 10 | key: "JOB_TYPE" 11 | value: "samples" 12 | } 13 | 14 | # TODO: remove this after we've migrated all tests and scripts 15 | env_vars: { 16 | key: "GCLOUD_PROJECT" 17 | value: "java-docs-samples-testing" 18 | } 19 | 20 | env_vars: { 21 | key: "GOOGLE_CLOUD_PROJECT" 22 | value: "java-docs-samples-testing" 23 | } 24 | 25 | env_vars: { 26 | key: "GOOGLE_APPLICATION_CREDENTIALS" 27 | value: "secret_manager/java-docs-samples-service-account" 28 | } 29 | 30 | env_vars: { 31 | key: "SECRET_MANAGER_KEYS" 32 | value: "java-docs-samples-service-account" 33 | } -------------------------------------------------------------------------------- /.kokoro/readme.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2020 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | set -eo pipefail 17 | 18 | cd ${KOKORO_ARTIFACTS_DIR}/github/java-logging-logback 19 | 20 | # Disable buffering, so that the logs stream through. 21 | export PYTHONUNBUFFERED=1 22 | 23 | # Kokoro exposes this as a file, but the scripts expect just a plain variable. 24 | export GITHUB_TOKEN=$(cat ${KOKORO_KEYSTORE_DIR}/73713_yoshi-automation-github-key) 25 | 26 | # Setup git credentials 27 | echo "https://${GITHUB_TOKEN}:@github.com" >> ~/.git-credentials 28 | git config --global credential.helper 'store --file ~/.git-credentials' 29 | 30 | python3.6 -m pip install git+https://github.com/googleapis/synthtool.git#egg=gcp-synthtool 31 | 32 | set +e 33 | python3.6 -m autosynth.synth \ 34 | --repository=googleapis/java-logging-logback \ 35 | --synth-file-name=.github/readme/synth.py \ 36 | --metadata-path=.github/readme/synth.metadata \ 37 | --pr-title="chore: regenerate README" \ 38 | --branch-suffix="readme" 39 | 40 | # autosynth returns 28 to signal there are no changes 41 | RETURN_CODE=$? 42 | if [[ ${RETURN_CODE} -ne 0 && ${RETURN_CODE} -ne 28 ]] 43 | then 44 | exit ${RETURN_CODE} 45 | fi 46 | -------------------------------------------------------------------------------- /.kokoro/requirements.in: -------------------------------------------------------------------------------- 1 | gcp-docuploader 2 | gcp-releasetool>=1.10.5 # required for compatibility with cryptography>=39.x 3 | wheel 4 | setuptools 5 | typing-extensions 6 | click<8.1.0 -------------------------------------------------------------------------------- /.kokoro/trampoline.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2018 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | set -eo pipefail 16 | # Always run the cleanup script, regardless of the success of bouncing into 17 | # the container. 18 | function cleanup() { 19 | chmod +x ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh 20 | ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh 21 | echo "cleanup"; 22 | } 23 | trap cleanup EXIT 24 | 25 | $(dirname $0)/populate-secrets.sh # Secret Manager secrets. 26 | python3 "${KOKORO_GFILE_DIR}/trampoline_v1.py" 27 | -------------------------------------------------------------------------------- /.repo-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "api_shortname": "logging-logback", 3 | "name_pretty": "Cloud Logging Logback Appender", 4 | "product_documentation": "https://cloud.google.com/logging/docs/setup/java#logback_appender_for", 5 | "client_documentation": "https://cloud.google.com/java/docs/reference/google-cloud-logging-logback/latest/history", 6 | "issue_tracker": "https://issuetracker.google.com/savedsearches/559764", 7 | "release_level": "preview", 8 | "language": "java", 9 | "repo": "googleapis/java-logging-logback", 10 | "repo_short": "java-logging-logback", 11 | "distribution_name": "com.google.cloud:google-cloud-logging-logback", 12 | "codeowner_team": "@googleapis/yoshi-java @googleapis/api-logging @googleapis/api-logging-partners", 13 | "library_type": "OTHER", 14 | "api_id": "logging.googleapis.com" 15 | } 16 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | 2 | # Code of Conduct 3 | 4 | ## Our Pledge 5 | 6 | In the interest of fostering an open and welcoming environment, we as 7 | contributors and maintainers pledge to making participation in our project and 8 | our community a harassment-free experience for everyone, regardless of age, body 9 | size, disability, ethnicity, gender identity and expression, level of 10 | experience, education, socio-economic status, nationality, personal appearance, 11 | race, religion, or sexual identity and orientation. 12 | 13 | ## Our Standards 14 | 15 | Examples of behavior that contributes to creating a positive environment 16 | include: 17 | 18 | * Using welcoming and inclusive language 19 | * Being respectful of differing viewpoints and experiences 20 | * Gracefully accepting constructive criticism 21 | * Focusing on what is best for the community 22 | * Showing empathy towards other community members 23 | 24 | Examples of unacceptable behavior by participants include: 25 | 26 | * The use of sexualized language or imagery and unwelcome sexual attention or 27 | advances 28 | * Trolling, insulting/derogatory comments, and personal or political attacks 29 | * Public or private harassment 30 | * Publishing others' private information, such as a physical or electronic 31 | address, without explicit permission 32 | * Other conduct which could reasonably be considered inappropriate in a 33 | professional setting 34 | 35 | ## Our Responsibilities 36 | 37 | Project maintainers are responsible for clarifying the standards of acceptable 38 | behavior and are expected to take appropriate and fair corrective action in 39 | response to any instances of unacceptable behavior. 40 | 41 | Project maintainers have the right and responsibility to remove, edit, or reject 42 | comments, commits, code, wiki edits, issues, and other contributions that are 43 | not aligned to this Code of Conduct, or to ban temporarily or permanently any 44 | contributor for other behaviors that they deem inappropriate, threatening, 45 | offensive, or harmful. 46 | 47 | ## Scope 48 | 49 | This Code of Conduct applies both within project spaces and in public spaces 50 | when an individual is representing the project or its community. Examples of 51 | representing a project or community include using an official project e-mail 52 | address, posting via an official social media account, or acting as an appointed 53 | representative at an online or offline event. Representation of a project may be 54 | further defined and clarified by project maintainers. 55 | 56 | This Code of Conduct also applies outside the project spaces when the Project 57 | Steward has a reasonable belief that an individual's behavior may have a 58 | negative impact on the project or its community. 59 | 60 | ## Conflict Resolution 61 | 62 | We do not believe that all conflict is bad; healthy debate and disagreement 63 | often yield positive results. However, it is never okay to be disrespectful or 64 | to engage in behavior that violates the project’s code of conduct. 65 | 66 | If you see someone violating the code of conduct, you are encouraged to address 67 | the behavior directly with those involved. Many issues can be resolved quickly 68 | and easily, and this gives people more control over the outcome of their 69 | dispute. If you are unable to resolve the matter for any reason, or if the 70 | behavior is threatening or harassing, report it. We are dedicated to providing 71 | an environment where participants feel welcome and safe. 72 | 73 | Reports should be directed to *googleapis-stewards@google.com*, the 74 | Project Steward(s) for *Google Cloud Client Libraries*. It is the Project Steward’s duty to 75 | receive and address reported violations of the code of conduct. They will then 76 | work with a committee consisting of representatives from the Open Source 77 | Programs Office and the Google Open Source Strategy team. If for any reason you 78 | are uncomfortable reaching out to the Project Steward, please email 79 | opensource@google.com. 80 | 81 | We will investigate every complaint, but you may not receive a direct response. 82 | We will use our discretion in determining when and how to follow up on reported 83 | incidents, which may range from not taking action to permanent expulsion from 84 | the project and project-sponsored spaces. We will notify the accused of the 85 | report and provide them an opportunity to discuss it before any action is taken. 86 | The identity of the reporter will be omitted from the details of the report 87 | supplied to the accused. In potentially harmful situations, such as ongoing 88 | harassment or threats to anyone's safety, we may take action without notice. 89 | 90 | ## Attribution 91 | 92 | This Code of Conduct is adapted from the Contributor Covenant, version 1.4, 93 | available at 94 | https://www.contributor-covenant.org/version/1/4/code-of-conduct.html -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution; 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to to see 12 | your current agreements on file or to sign a new one. 13 | 14 | You generally only need to submit a CLA once, so if you've already submitted one 15 | (even if it was for a different project), you probably don't need to do it 16 | again. 17 | 18 | ## Code reviews 19 | 20 | All submissions, including submissions by project members, require review. We 21 | use GitHub pull requests for this purpose. Consult 22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 23 | information on using pull requests. 24 | 25 | ## Community Guidelines 26 | 27 | This project follows 28 | [Google's Open Source Community Guidelines](https://opensource.google.com/conduct/). 29 | 30 | ## Building the project 31 | 32 | To build, package, and run all unit tests run the command 33 | 34 | ``` 35 | mvn clean verify 36 | ``` 37 | 38 | ### Running Integration tests 39 | 40 | To include integration tests when building the project, you need access to 41 | a GCP Project with a valid service account. 42 | 43 | For instructions on how to generate a service account and corresponding 44 | credentials JSON see: [Creating a Service Account][1]. 45 | 46 | Then run the following to build, package, run all unit tests and run all 47 | integration tests. 48 | 49 | ```bash 50 | export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service/account.json 51 | mvn -Penable-integration-tests clean verify 52 | ``` 53 | 54 | ## Code Samples 55 | 56 | Code Samples must be bundled in separate Maven modules, and guarded by a 57 | Maven profile with the name `enable-samples`. 58 | 59 | The samples must be separate from the primary project for a few reasons: 60 | 1. Primary projects have a minimum Java version of Java 7 whereas samples have 61 | a minimum Java version of Java 8. Due to this we need the ability to 62 | selectively exclude samples from a build run. 63 | 2. Many code samples depend on external GCP services and need 64 | credentials to access the service. 65 | 3. Code samples are not released as Maven artifacts and must be excluded from 66 | release builds. 67 | 68 | ### Building 69 | 70 | ```bash 71 | mvn -Penable-samples clean verify 72 | ``` 73 | 74 | Some samples require access to GCP services and require a service account: 75 | 76 | ```bash 77 | export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service/account.json 78 | mvn -Penable-samples clean verify 79 | ``` 80 | 81 | ### Profile Config 82 | 83 | 1. To add samples in a profile to your Maven project, add the following to your 84 | `pom.xml` 85 | 86 | ```xml 87 | 88 | [...] 89 | 90 | 91 | enable-samples 92 | 93 | sample 94 | 95 | 96 | 97 | [...] 98 | 99 | ``` 100 | 101 | 2. [Activate](#profile-activation) the profile. 102 | 3. Define your samples in a normal Maven project in the `samples/` directory. 103 | 104 | ### Code Formatting 105 | 106 | Code in this repo is formatted with 107 | [google-java-format](https://github.com/google/google-java-format). 108 | To run formatting on your project, you can run: 109 | ``` 110 | mvn com.coveo:fmt-maven-plugin:format 111 | ``` 112 | 113 | ### Profile Activation 114 | 115 | To include code samples when building and testing the project, enable the 116 | `enable-samples` Maven profile. 117 | 118 | #### Command line 119 | 120 | To activate the Maven profile on the command line add `-Penable-samples` to your 121 | Maven command. 122 | 123 | #### Maven `settings.xml` 124 | 125 | To activate the Maven profile in your `~/.m2/settings.xml` add an entry of 126 | `enable-samples` following the instructions in [Active Profiles][2]. 127 | 128 | This method has the benefit of applying to all projects you build (and is 129 | respected by IntelliJ IDEA) and is recommended if you are going to be 130 | contributing samples to several projects. 131 | 132 | #### IntelliJ IDEA 133 | 134 | To activate the Maven Profile inside IntelliJ IDEA, follow the instructions in 135 | [Activate Maven profiles][3] to activate `enable-samples`. 136 | 137 | [1]: https://cloud.google.com/docs/authentication/getting-started#creating_a_service_account 138 | [2]: https://maven.apache.org/settings.html#Active_Profiles 139 | [3]: https://www.jetbrains.com/help/idea/work-with-maven-profiles.html#activate_maven_profiles 140 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Google Cloud Logging Logback Appender Client for Java 2 | 3 | Java idiomatic client for [Cloud Logging Logback Appender][product-docs]. 4 | 5 | [![Maven][maven-version-image]][maven-version-link] 6 | ![Stability][stability-image] 7 | 8 | - [Product Documentation][product-docs] 9 | - [Client Library Documentation][javadocs] 10 | 11 | > Note: This client is a work-in-progress, and may occasionally 12 | > make backwards-incompatible changes. 13 | 14 | 15 | ## Quickstart 16 | 17 | 18 | If you are using Maven, add this to your pom.xml file: 19 | 20 | 21 | 22 | ```xml 23 | 24 | com.google.cloud 25 | google-cloud-logging-logback 26 | 0.131.11-alpha 27 | 28 | ``` 29 | 30 | If you are using Gradle without BOM, add this to your dependencies: 31 | 32 | ```Groovy 33 | implementation 'com.google.cloud:google-cloud-logging-logback:0.131.11-alpha' 34 | ``` 35 | 36 | If you are using SBT, add this to your dependencies: 37 | 38 | ```Scala 39 | libraryDependencies += "com.google.cloud" % "google-cloud-logging-logback" % "0.131.11-alpha" 40 | ``` 41 | 42 | 43 | ## Authentication 44 | 45 | See the [Authentication][authentication] section in the base directory's README. 46 | 47 | ## Authorization 48 | 49 | The client application making API calls must be granted [authorization scopes][auth-scopes] required for the desired Cloud Logging Logback Appender APIs, and the authenticated principal must have the [IAM role(s)][predefined-iam-roles] required to access GCP resources using the Cloud Logging Logback Appender API calls. 50 | 51 | ## Getting Started 52 | 53 | ### Prerequisites 54 | 55 | You will need a [Google Cloud Platform Console][developer-console] project with the Cloud Logging Logback Appender [API enabled][enable-api]. 56 | 57 | [Follow these instructions][create-project] to get your project set up. You will also need to set up the local development environment by 58 | [installing the Google Cloud Command Line Interface][cloud-cli] and running the following commands in command line: 59 | `gcloud auth login` and `gcloud config set project [YOUR PROJECT ID]`. 60 | 61 | ### Installation and setup 62 | 63 | You'll need to obtain the `google-cloud-logging-logback` library. See the [Quickstart](#quickstart) section 64 | to add `google-cloud-logging-logback` as a dependency in your code. 65 | 66 | ## About Cloud Logging Logback Appender 67 | 68 | 69 | [Cloud Logging Logback Appender][product-docs] 70 | 71 | See the [Cloud Logging Logback Appender client library docs][javadocs] to learn how to 72 | use this Cloud Logging Logback Appender Client Library. 73 | 74 | 75 | ### Usage 76 | Add the appender to your [Logback configuration](https://logback.qos.ch/manual/configuration.html) `logback.xml`. 77 | See [Logback filters](https://logback.qos.ch/manual/filters.html#thresholdFilter) for information on filtering log output and 78 | [encoders](https://logback.qos.ch/manual/encoders.html) for information on formatting. 79 | 80 | 81 | ```xml 82 | 83 | 84 | 85 | 86 | INFO 87 | 88 | 89 | 90 | application.log 91 | 92 | 93 | WARN 94 | 95 | 96 | SYNC 97 | 98 | 99 | false 100 | 101 | 102 | true 103 | 104 | 105 | 106 | 107 | 108 | /path/to/credentials/file 109 | 110 | 111 | String 112 | 113 | 114 | com.example.enhancers.TestLoggingEnhancer 115 | com.example.enhancers.AnotherEnhancer 116 | 117 | 119 | true 120 | 121 | 126 | 127 | 100 128 | 1000 129 | 500 130 | 10000 131 | 100000 132 | Ignore 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | ``` 141 | 142 | In your code: 143 | 144 | ```java 145 | import org.slf4j.Logger; 146 | import org.slf4j.LoggerFactory; 147 | 148 | public class TestLogger { 149 | private final Logger logger = LoggerFactory.getLogger(TestLogger.class); 150 | 151 | public void log(String name) { 152 | logger.info("This is a test"); 153 | } 154 | 155 | public static void main(String[] args) { 156 | TestLogger testLogger = new TestLogger(); 157 | testLogger.log("test"); 158 | } 159 | } 160 | ``` 161 | 162 | ### Controlling the batching settings 163 | When using asynchronous logging, the Logging API is called asynchronously. This allows the appender 164 | to combine multiple `write()` calls into a single, more efficient request to the Logging API. The 165 | `logbackBatchingSettings` in the `logback.xml` file configures the batching behavior: 166 | 167 | ``` 168 | 169 | 100 170 | 1000 171 | 500 172 | 10000 173 | 100000 174 | Ignore 175 | 176 | ``` 177 | Here are some explanations for [BatchingSettings](https://cloud.google.com/java/docs/reference/gax/latest/com.google.api.gax.batching.BatchingSettings): 178 | * `elementCountThreshold`: Triggers a `writeLogEntries` request when the number of batched log entries exceeds this threshold. 179 | * `requestByteThreshold`: Triggers a `writeLogEntries` request when the total size of batched log entries (in bytes) exceeds this threshold. 180 | * `delayThreshold`: Triggers a `writeLogEntries` request when the threshold in milliseconds has passed since the first log entry created the batch. 181 | 182 | Batching also supports [FlowControl](https://cloud.google.com/java/docs/reference/gax/latest/com.google.api.gax.batching.FlowControlSettings), which can be used to 183 | prevent the batching implementation from accumulating messages without limit, resulting eventually in an OutOfMemory exception. These settings in the configuration controls 184 | flow control behavior: 185 | 186 | * `maxOutstandingElementCount`: When the total number of outstanding log events exceeds this threshold, flow control will be initiated. 187 | * `maxOutstandingRequestBytes`: When the total size of outstanding `writeLogEntries` requests exceeds this threshold, flow control will be initiated. 188 | * `limitExceededBehavior`: This value defines what action the appender should take when the configured limits (like `maxOutstandingRequestBytes` or `maxOutstandingElementCount`) are exceeded. 189 | 190 | For more information about batching configurations, see [BatchingSettings](https://cloud.google.com/java/docs/reference/gax/latest/com.google.api.gax.batching.BatchingSettings). 191 | 192 | ### Populate log entries with metadata 193 | 194 | The library provides multiple ways to enrich log entries with additional information. 195 | You can select one or more ways to customize log entries that will be written into Cloud Logging. 196 | 197 | * Manually update a log entry using [`LoggingEnhancer`] 198 | (https://github.com/googleapis/java-logging/blob/main/google-cloud-logging/src/main/java/com/google/cloud/logging/. 199 | * Use [`ILoggingEvent`](https://logback.qos.ch/apidocs/ch/qos/logback/classic/spi/ILoggingEvent.html) to update a log entry with [`LoggingEventEnhancer`] 200 | (https://github.com/googleapis/java-logging-logback/blob/main/src/main/java/com/google/cloud/logging/logback/LoggingEventEnhancer.java). 201 | * Enable [auto-population](https://github.com/googleapis/java-logging#auto-population-of-log-entrys-metadata) of the `LogEntry` metadata using the `autoPopulateMetadata` configuration flag. 202 | 203 | #### Optimize log ingestion 204 | 205 | By default, the appender will ingest log entries asynchronously by calling Logging API. 206 | Multiple calls may be aggregated before being sent to improve use of API quota and bandwidth. 207 | You can set the `writeSynchronicity` configuration flag to `SYNC` if they want to ingest log entries synchronously. 208 | Note that configuring synchronous ingestion will probably result in performance penalties to your applications. 209 | If you plan to deploy your application in one of Google Cloud managed environments (e.g. Cloud Run, Cloud Function or App Engine), 210 | you can leverage the support provided by the implicit logging agent and the [structured logging](https://cloud.google.com/logging/docs/structured-logging) feature. 211 | To use it, set the `redirectToStdout` configuration flag to `true`. 212 | This flag instructs the appender to print the log entries to `stdout` instead of ingesting them using Logging API. 213 | The log entries are printed using the [structured logging Json format](https://cloud.google.com/logging/docs/structured-logging#special-payload-fields). 214 | In result, the logging agent will be responsible for ingesting the logs to Logging API. 215 | Note that using the structured logging Json format you cannot control the log name where the logs will be ingested. 216 | The logs will be ingested into the project that hosts the environment where your application is running. 217 | The configuration `logDestinationProjectId` will be ignored. 218 | 219 | ### Recommended way to ingest logs in Google Cloud managed environments 220 | If your application is running on Google Cloud Environments such as Google Kubernetes Engine, App Engine flexible environment, and Cloud Run functions, it is recommended to use [logging agent](https://cloud.google.com/logging/docs/agent) 221 | to send application logs to Cloud Logging. Logging agents send data written to a file, such as `stdout` or a file, as logs to Cloud Logging. Using logging agents and relying on logging files such as `stdout` and `stderr` will 222 | ensure that application crashes don't break sending logs to your project. It will also reduce complex coding to explicitly handle buffering and retries using client libraries. For a detailed comparison of logging agents and 223 | client libraries, see [Choosing an agent or client libraries](https://cloud.google.com/logging/docs/agent-or-library#choosing). 224 | 225 | 226 | ## Samples 227 | 228 | Samples are in the [`samples/`](https://github.com/googleapis/java-logging-logback/tree/main/samples) directory. 229 | 230 | | Sample | Source Code | Try it | 231 | | --------------------------- | --------------------------------- | ------ | 232 | | Quickstart | [source code](https://github.com/googleapis/java-logging-logback/blob/main/samples/snippets/src/main/java/com/example/logging/logback/Quickstart.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-logging-logback&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/logging/logback/Quickstart.java) | 233 | | Example Enhancer | [source code](https://github.com/googleapis/java-logging-logback/blob/main/samples/snippets/src/main/java/com/example/logging/logback/enhancers/ExampleEnhancer.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-logging-logback&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/logging/logback/enhancers/ExampleEnhancer.java) | 234 | 235 | 236 | 237 | ## Troubleshooting 238 | 239 | To get help, follow the instructions in the [shared Troubleshooting document][troubleshooting]. 240 | 241 | ## Supported Java Versions 242 | 243 | Java 8 or above is required for using this client. 244 | 245 | Google's Java client libraries, 246 | [Google Cloud Client Libraries][cloudlibs] 247 | and 248 | [Google Cloud API Libraries][apilibs], 249 | follow the 250 | [Oracle Java SE support roadmap][oracle] 251 | (see the Oracle Java SE Product Releases section). 252 | 253 | ### For new development 254 | 255 | In general, new feature development occurs with support for the lowest Java 256 | LTS version covered by Oracle's Premier Support (which typically lasts 5 years 257 | from initial General Availability). If the minimum required JVM for a given 258 | library is changed, it is accompanied by a [semver][semver] major release. 259 | 260 | Java 11 and (in September 2021) Java 17 are the best choices for new 261 | development. 262 | 263 | ### Keeping production systems current 264 | 265 | Google tests its client libraries with all current LTS versions covered by 266 | Oracle's Extended Support (which typically lasts 8 years from initial 267 | General Availability). 268 | 269 | #### Legacy support 270 | 271 | Google's client libraries support legacy versions of Java runtimes with long 272 | term stable libraries that don't receive feature updates on a best efforts basis 273 | as it may not be possible to backport all patches. 274 | 275 | Google provides updates on a best efforts basis to apps that continue to use 276 | Java 7, though apps might need to upgrade to current versions of the library 277 | that supports their JVM. 278 | 279 | #### Where to find specific information 280 | 281 | The latest versions and the supported Java versions are identified on 282 | the individual GitHub repository `github.com/GoogleAPIs/java-SERVICENAME` 283 | and on [google-cloud-java][g-c-j]. 284 | 285 | ## Versioning 286 | 287 | 288 | This library follows [Semantic Versioning](http://semver.org/). 289 | 290 | 291 | It is currently in major version zero (``0.y.z``), which means that anything may change at any time 292 | and the public API should not be considered stable. 293 | 294 | 295 | ## Contributing 296 | 297 | 298 | Contributions to this library are always welcome and highly encouraged. 299 | 300 | See [CONTRIBUTING][contributing] for more information how to get started. 301 | 302 | Please note that this project is released with a Contributor Code of Conduct. By participating in 303 | this project you agree to abide by its terms. See [Code of Conduct][code-of-conduct] for more 304 | information. 305 | 306 | 307 | ## License 308 | 309 | Apache 2.0 - See [LICENSE][license] for more information. 310 | 311 | ## CI Status 312 | 313 | Java Version | Status 314 | ------------ | ------ 315 | Java 8 | [![Kokoro CI][kokoro-badge-image-2]][kokoro-badge-link-2] 316 | Java 8 OSX | [![Kokoro CI][kokoro-badge-image-3]][kokoro-badge-link-3] 317 | Java 8 Windows | [![Kokoro CI][kokoro-badge-image-4]][kokoro-badge-link-4] 318 | Java 11 | [![Kokoro CI][kokoro-badge-image-5]][kokoro-badge-link-5] 319 | 320 | Java is a registered trademark of Oracle and/or its affiliates. 321 | 322 | [product-docs]: https://cloud.google.com/logging/docs/setup/java#logback_appender_for 323 | [javadocs]: https://cloud.google.com/java/docs/reference/google-cloud-logging-logback/latest/history 324 | [kokoro-badge-image-1]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-logging-logback/java7.svg 325 | [kokoro-badge-link-1]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-logging-logback/java7.html 326 | [kokoro-badge-image-2]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-logging-logback/java8.svg 327 | [kokoro-badge-link-2]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-logging-logback/java8.html 328 | [kokoro-badge-image-3]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-logging-logback/java8-osx.svg 329 | [kokoro-badge-link-3]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-logging-logback/java8-osx.html 330 | [kokoro-badge-image-4]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-logging-logback/java8-win.svg 331 | [kokoro-badge-link-4]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-logging-logback/java8-win.html 332 | [kokoro-badge-image-5]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-logging-logback/java11.svg 333 | [kokoro-badge-link-5]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-logging-logback/java11.html 334 | [stability-image]: https://img.shields.io/badge/stability-preview-yellow 335 | [maven-version-image]: https://img.shields.io/maven-central/v/com.google.cloud/google-cloud-logging-logback.svg 336 | [maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-logging-logback/0.131.11-alpha 337 | [authentication]: https://github.com/googleapis/google-cloud-java#authentication 338 | [auth-scopes]: https://developers.google.com/identity/protocols/oauth2/scopes 339 | [predefined-iam-roles]: https://cloud.google.com/iam/docs/understanding-roles#predefined_roles 340 | [iam-policy]: https://cloud.google.com/iam/docs/overview#cloud-iam-policy 341 | [developer-console]: https://console.developers.google.com/ 342 | [create-project]: https://cloud.google.com/resource-manager/docs/creating-managing-projects 343 | [cloud-cli]: https://cloud.google.com/cli 344 | [troubleshooting]: https://github.com/googleapis/google-cloud-java/blob/main/TROUBLESHOOTING.md 345 | [contributing]: https://github.com/googleapis/java-logging-logback/blob/main/CONTRIBUTING.md 346 | [code-of-conduct]: https://github.com/googleapis/java-logging-logback/blob/main/CODE_OF_CONDUCT.md#contributor-code-of-conduct 347 | [license]: https://github.com/googleapis/java-logging-logback/blob/main/LICENSE 348 | 349 | [enable-api]: https://console.cloud.google.com/flows/enableapi?apiid=logging.googleapis.com 350 | [libraries-bom]: https://github.com/GoogleCloudPlatform/cloud-opensource-java/wiki/The-Google-Cloud-Platform-Libraries-BOM 351 | [shell_img]: https://gstatic.com/cloudssh/images/open-btn.png 352 | 353 | [semver]: https://semver.org/ 354 | [cloudlibs]: https://cloud.google.com/apis/docs/client-libraries-explained 355 | [apilibs]: https://cloud.google.com/apis/docs/client-libraries-explained#google_api_client_libraries 356 | [oracle]: https://www.oracle.com/java/technologies/java-se-support-roadmap.html 357 | [g-c-j]: http://github.com/googleapis/google-cloud-java 358 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | To report a security issue, please use [g.co/vulnz](https://g.co/vulnz). 4 | 5 | The Google Security Team will respond within 5 working days of your report on g.co/vulnz. 6 | 7 | We use g.co/vulnz for our intake, and do coordination and disclosure here using GitHub Security Advisory to privately discuss and fix the issue. 8 | -------------------------------------------------------------------------------- /java.header: -------------------------------------------------------------------------------- 1 | ^/\*$ 2 | ^ \* Copyright \d\d\d\d,? Google (Inc\.|LLC)$ 3 | ^ \*$ 4 | ^ \* Licensed under the Apache License, Version 2\.0 \(the "License"\);$ 5 | ^ \* you may not use this file except in compliance with the License\.$ 6 | ^ \* You may obtain a copy of the License at$ 7 | ^ \*$ 8 | ^ \*[ ]+https?://www.apache.org/licenses/LICENSE-2\.0$ 9 | ^ \*$ 10 | ^ \* Unless required by applicable law or agreed to in writing, software$ 11 | ^ \* distributed under the License is distributed on an "AS IS" BASIS,$ 12 | ^ \* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied\.$ 13 | ^ \* See the License for the specific language governing permissions and$ 14 | ^ \* limitations under the License\.$ 15 | ^ \*/$ 16 | -------------------------------------------------------------------------------- /license-checks.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | google-cloud-logging-logback 8 | 0.132.10-alpha-SNAPSHOT 9 | jar 10 | Google Cloud Logging Logback Appender 11 | https://github.com/googleapis/java-logging-logback 12 | 13 | Logback support for Google Cloud Logging 14 | 15 | 16 | 17 | 1.2.13 18 | 5.6.0 19 | 1.4.4 20 | 3.22.5 21 | 1.7.36 22 | 1.10.1 23 | 24 | 25 | 26 | com.google.cloud 27 | sdk-platform-java-config 28 | 3.49.0 29 | 30 | 31 | 32 | 33 | chingor 34 | Jeff Ching 35 | chingor@google.com 36 | Google 37 | 38 | Developer 39 | 40 | 41 | 42 | 43 | Google LLC 44 | 45 | 46 | scm:git:git@github.com:googleapis/java-logging-logback.git 47 | scm:git:git@github.com:googleapis/java-logging-logback.git 48 | https://github.com/googleapis/java-logging-logback 49 | HEAD 50 | 51 | 52 | https://github.com/googleapis/java-logging-logback/issues 53 | GitHub Issues 54 | 55 | 56 | 57 | 58 | Apache-2.0 59 | https://www.apache.org/licenses/LICENSE-2.0.txt 60 | 61 | 62 | 63 | 64 | 65 | 66 | com.google.cloud 67 | google-cloud-shared-dependencies 68 | ${google-cloud-shared-dependencies.version} 69 | pom 70 | import 71 | 72 | 73 | 74 | io.opentelemetry 75 | opentelemetry-context 76 | 1.47.0 77 | 78 | 79 | 80 | io.opentelemetry 81 | opentelemetry-api 82 | 1.47.0 83 | 84 | 85 | 86 | 87 | 88 | ch.qos.logback 89 | logback-classic 90 | ${logback.version} 91 | 92 | 93 | ch.qos.logback 94 | logback-core 95 | ${logback.version} 96 | 97 | 98 | com.google.cloud 99 | google-cloud-logging 100 | ${logging.version} 101 | 102 | 103 | org.slf4j 104 | slf4j-api 105 | ${slf4j.version} 106 | 107 | 108 | com.google.api 109 | api-common 110 | 111 | 112 | com.google.cloud 113 | google-cloud-core 114 | 115 | 116 | com.google.auth 117 | google-auth-library-oauth2-http 118 | 119 | 120 | com.google.guava 121 | guava 122 | 123 | 124 | com.google.guava 125 | failureaccess 126 | 127 | 128 | 129 | 130 | com.google.auth 131 | google-auth-library-credentials 132 | 133 | 134 | 135 | 136 | junit 137 | junit 138 | 4.13.2 139 | test 140 | 141 | 142 | org.easymock 143 | easymock 144 | ${easymock.version} 145 | test 146 | 147 | 148 | com.google.truth 149 | truth 150 | ${truth.version} 151 | test 152 | 153 | 154 | org.checkerframework 155 | checker-qual 156 | 157 | 158 | 159 | 160 | com.google.protobuf 161 | protobuf-java 162 | 163 | 164 | com.google.api 165 | gax 166 | 167 | 168 | org.threeten 169 | threetenbp 170 | test 171 | 172 | 173 | 174 | 175 | 176 | 177 | org.apache.maven.plugins 178 | maven-project-info-reports-plugin 179 | 3.8.0 180 | 181 | 182 | 183 | index 184 | dependency-info 185 | team 186 | ci-management 187 | issue-management 188 | licenses 189 | scm 190 | dependency-management 191 | distribution-management 192 | summary 193 | modules 194 | 195 | 196 | 197 | 198 | true 199 | ${site.installationModule} 200 | jar 201 | 202 | 203 | 204 | org.apache.maven.plugins 205 | maven-javadoc-plugin 206 | 207 | 208 | html 209 | 210 | aggregate 211 | javadoc 212 | 213 | 214 | 215 | 216 | none 217 | protected 218 | true 219 | ${project.build.directory}/javadoc 220 | 221 | 222 | Test helpers packages 223 | com.google.cloud.testing 224 | 225 | 226 | SPI packages 227 | com.google.cloud.spi* 228 | 229 | 230 | 231 | 232 | https://grpc.io/grpc-java/javadoc/ 233 | https://developers.google.com/protocol-buffers/docs/reference/java/ 234 | https://googleapis.dev/java/google-auth-library/latest/ 235 | https://googleapis.dev/java/gax/latest/ 236 | https://googleapis.github.io/api-common-java/${google.api-common.version}/apidocs/ 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | org.codehaus.mojo 247 | flatten-maven-plugin 248 | 249 | 250 | 251 | 252 | 253 | native 254 | 255 | 256 | !LoggingAppenderTest 257 | 258 | 259 | 260 | 261 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | ":separateMajorReleases", 4 | ":combinePatchMinorReleases", 5 | ":ignoreUnstable", 6 | ":prImmediately", 7 | ":updateNotScheduled", 8 | ":automergeDisabled", 9 | ":ignoreModulesAndTests", 10 | ":maintainLockFilesDisabled" 11 | ], 12 | "ignorePaths": [ 13 | ".kokoro/requirements.txt", 14 | ".github/workflows/approve-readme.yaml", 15 | ".github/workflows/ci.yaml", 16 | ".github/workflows/renovate_config_check.yaml", 17 | ".github/workflows/samples.yaml" 18 | ], 19 | "customManagers": [ 20 | { 21 | "customType": "regex", 22 | "fileMatch": [ 23 | "^.kokoro/presubmit/graalvm-native.*.cfg$" 24 | ], 25 | "matchStrings": [ 26 | "value: \"gcr.io/cloud-devrel-public-resources/graalvm.*:(?.*?)\"" 27 | ], 28 | "depNameTemplate": "com.google.cloud:sdk-platform-java-config", 29 | "datasourceTemplate": "maven" 30 | }, 31 | { 32 | "customType": "regex", 33 | "fileMatch": [ 34 | "^.github/workflows/unmanaged_dependency_check.yaml$" 35 | ], 36 | "matchStrings": [ 37 | "uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v(?.+?)\\n" 38 | ], 39 | "depNameTemplate": "com.google.cloud:sdk-platform-java-config", 40 | "datasourceTemplate": "maven" 41 | } 42 | ], 43 | "packageRules": [ 44 | { 45 | "versioning": "docker", 46 | "matchPackageNames": [ 47 | "/^com.google.guava:/" 48 | ] 49 | }, 50 | { 51 | "semanticCommitType": "deps", 52 | "semanticCommitScope": null, 53 | "matchPackageNames": [ 54 | "*" 55 | ] 56 | }, 57 | { 58 | "semanticCommitType": "build", 59 | "semanticCommitScope": "deps", 60 | "matchPackageNames": [ 61 | "/^org.apache.maven/", 62 | "/^org.jacoco:/", 63 | "/^org.codehaus.mojo:/", 64 | "/^org.sonatype.plugins:/", 65 | "/^com.coveo:/", 66 | "/^com.google.cloud:google-cloud-shared-config/" 67 | ] 68 | }, 69 | { 70 | "semanticCommitType": "chore", 71 | "semanticCommitScope": "deps", 72 | "matchPackageNames": [ 73 | "/^com.google.cloud:google-cloud-logging-logback/", 74 | "/^com.google.cloud:libraries-bom/", 75 | "/^com.google.cloud.samples:shared-configuration/" 76 | ] 77 | }, 78 | { 79 | "semanticCommitType": "test", 80 | "semanticCommitScope": "deps", 81 | "matchPackageNames": [ 82 | "/^junit:junit/", 83 | "/^com.google.truth:truth/", 84 | "/^org.mockito:mockito-core/", 85 | "/^org.objenesis:objenesis/", 86 | "/^com.google.cloud:google-cloud-conformance-tests/", 87 | "/^org.graalvm.buildtools:junit-platform-native/" 88 | ] 89 | }, 90 | { 91 | "ignoreUnstable": false, 92 | "matchPackageNames": [ 93 | "/^com.google.cloud:google-cloud-/" 94 | ] 95 | }, 96 | { 97 | "groupName": "jackson dependencies", 98 | "matchPackageNames": [ 99 | "/^com.fasterxml.jackson.core/" 100 | ] 101 | } 102 | ], 103 | "semanticCommits": "enabled", 104 | "dependencyDashboard": true 105 | } 106 | -------------------------------------------------------------------------------- /samples/install-without-bom/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.google.cloud 5 | logging-logback-install-without-bom 6 | jar 7 | Google Google Cloud Logging Logback Appender Install Without Bom 8 | https://github.com/googleapis/java-logging-logback 9 | 10 | 14 | 15 | com.google.cloud.samples 16 | shared-configuration 17 | 1.2.0 18 | 19 | 20 | 21 | 1.8 22 | 1.8 23 | UTF-8 24 | 25 | 26 | 27 | 28 | 29 | 30 | com.google.cloud 31 | google-cloud-logging-logback 32 | 0.132.3-alpha 33 | 34 | 35 | 36 | 37 | junit 38 | junit 39 | 4.13.2 40 | test 41 | 42 | 43 | com.google.truth 44 | truth 45 | 1.4.4 46 | test 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | org.codehaus.mojo 55 | build-helper-maven-plugin 56 | 3.6.0 57 | 58 | 59 | add-snippets-source 60 | 61 | add-source 62 | 63 | 64 | 65 | ../snippets/src/main/java 66 | 67 | 68 | 69 | 70 | add-snippets-tests 71 | 72 | add-test-source 73 | 74 | 75 | 76 | ../snippets/src/test/java 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /samples/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.google.cloud 5 | google-cloud-logging-logback-samples 6 | 0.0.1-SNAPSHOT 7 | pom 8 | Google Google Cloud Logging Logback Appender Samples Parent 9 | https://github.com/googleapis/java-logging-logback 10 | 11 | Java idiomatic client for Google Cloud Platform services. 12 | 13 | 14 | 18 | 19 | com.google.cloud.samples 20 | shared-configuration 21 | 1.2.0 22 | 23 | 24 | 25 | 1.8 26 | 1.8 27 | UTF-8 28 | 29 | 30 | 31 | install-without-bom 32 | snapshot 33 | snippets 34 | 35 | 36 | 37 | 38 | 39 | org.apache.maven.plugins 40 | maven-deploy-plugin 41 | 3.1.3 42 | 43 | true 44 | 45 | 46 | 47 | org.sonatype.plugins 48 | nexus-staging-maven-plugin 49 | 1.7.0 50 | 51 | true 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /samples/snapshot/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.google.cloud 5 | logging-logback-snapshot 6 | jar 7 | Google Google Cloud Logging Logback Appender Snapshot Samples 8 | https://github.com/googleapis/java-logging-logback 9 | 10 | 14 | 15 | com.google.cloud.samples 16 | shared-configuration 17 | 1.2.0 18 | 19 | 20 | 21 | 1.8 22 | 1.8 23 | UTF-8 24 | 25 | 26 | 27 | 28 | 29 | com.google.cloud 30 | google-cloud-logging-logback 31 | 0.132.10-alpha-SNAPSHOT 32 | 33 | 34 | 35 | 36 | junit 37 | junit 38 | 4.13.2 39 | test 40 | 41 | 42 | com.google.truth 43 | truth 44 | 1.4.4 45 | test 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | org.codehaus.mojo 54 | build-helper-maven-plugin 55 | 3.6.0 56 | 57 | 58 | add-snippets-source 59 | 60 | add-source 61 | 62 | 63 | 64 | ../snippets/src/main/java 65 | 66 | 67 | 68 | 69 | add-snippets-tests 70 | 71 | add-test-source 72 | 73 | 74 | 75 | ../snippets/src/test/java 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /samples/snippets/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.google.cloud 5 | logging-logback-snippets 6 | jar 7 | Google Google Cloud Logging Logback Appender Snippets 8 | https://github.com/googleapis/java-logging-logback 9 | 10 | 14 | 15 | com.google.cloud.samples 16 | shared-configuration 17 | 1.2.0 18 | 19 | 20 | 21 | 1.8 22 | 1.8 23 | UTF-8 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | com.google.cloud 32 | libraries-bom 33 | 26.55.0 34 | pom 35 | import 36 | 37 | 38 | 39 | 40 | 41 | 42 | com.google.cloud 43 | google-cloud-logging-logback 44 | 45 | 46 | 47 | 48 | junit 49 | junit 50 | 4.13.2 51 | test 52 | 53 | 54 | com.google.truth 55 | truth 56 | 1.4.4 57 | test 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /samples/snippets/src/main/java/com/example/logging/logback/Quickstart.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.logging.logback; 18 | 19 | // [START logging_logback_quickstart] 20 | 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | public class Quickstart { 25 | private static final Logger logger = LoggerFactory.getLogger(Quickstart.class); 26 | 27 | public static void main(String[] args) { 28 | logger.info("Logging INFO with Logback"); 29 | logger.error("Logging ERROR with Logback"); 30 | } 31 | } 32 | // [END logging_logback_quickstart] 33 | -------------------------------------------------------------------------------- /samples/snippets/src/main/java/com/example/logging/logback/enhancers/ExampleEnhancer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.example.logging.logback.enhancers; 18 | 19 | // [START logging_enhancer] 20 | 21 | import com.google.cloud.logging.LogEntry; 22 | import com.google.cloud.logging.LoggingEnhancer; 23 | 24 | // Add / update additional fields to the log entry 25 | public class ExampleEnhancer implements LoggingEnhancer { 26 | 27 | @Override 28 | public void enhanceLogEntry(LogEntry.Builder logEntry) { 29 | // add additional labels 30 | logEntry.addLabel("test-label-1", "test-value-1"); 31 | } 32 | } 33 | // [END logging_enhancer] 34 | -------------------------------------------------------------------------------- /samples/snippets/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 21 | INFO 22 | 23 | application.log 24 | gae_app 25 | com.example.logging.logback.enhancers.ExampleEnhancer 26 | WARN 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/main/java/com/google/cloud/logging/logback/LogbackBatchingSettings.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.logging.logback; 18 | 19 | import com.google.api.gax.batching.BatchingSettings; 20 | import com.google.api.gax.batching.FlowControlSettings; 21 | import com.google.api.gax.batching.FlowController.LimitExceededBehavior; 22 | import java.time.Duration; 23 | 24 | /** 25 | * This class is used only to provide batch settings configuration in logback.xml since {@link 26 | * com.google.api.gax.batching.BatchingSettings} cannot be used as is with logback configuration 27 | * described in https://logback.qos.ch/manual/configuration.html. All data members below are simply 28 | * copy of {@link com.google.api.gax.batching.BatchingSettings} class, so it could be used with 29 | * logback.xml. 30 | */ 31 | public class LogbackBatchingSettings { 32 | private Long elementCountThreshold = null; 33 | private Long requestByteThreshold = null; 34 | private Long delayThreshold = null; 35 | private Long maxOutstandingElementCount = null; 36 | private Long maxOutstandingRequestBytes = null; 37 | private LimitExceededBehavior limitExceededBehavior = null; 38 | 39 | public void setElementCountThreshold(Long value) { 40 | elementCountThreshold = value; 41 | } 42 | 43 | public void setRequestByteThreshold(Long value) { 44 | requestByteThreshold = value; 45 | } 46 | 47 | public void setDelayThreshold(Long value) { 48 | delayThreshold = value; 49 | } 50 | 51 | public void setMaxOutstandingElementCount(Long value) { 52 | maxOutstandingElementCount = value; 53 | } 54 | 55 | public void setMaxOutstandingRequestBytes(Long value) { 56 | maxOutstandingRequestBytes = value; 57 | } 58 | 59 | public void setLimitExceededBehavior(LimitExceededBehavior value) { 60 | limitExceededBehavior = value; 61 | } 62 | 63 | public BatchingSettings build() { 64 | BatchingSettings.Builder settings = BatchingSettings.newBuilder(); 65 | if (elementCountThreshold != null) { 66 | settings.setElementCountThreshold(elementCountThreshold); 67 | } 68 | if (requestByteThreshold != null) { 69 | settings.setRequestByteThreshold(requestByteThreshold); 70 | } 71 | if (delayThreshold != null) { 72 | settings.setDelayThresholdDuration(Duration.ofMillis(delayThreshold)); 73 | } 74 | if (maxOutstandingElementCount != null 75 | || maxOutstandingRequestBytes != null 76 | || limitExceededBehavior != null) { 77 | FlowControlSettings.Builder flowControlSettings = FlowControlSettings.newBuilder(); 78 | flowControlSettings.setMaxOutstandingElementCount(maxOutstandingElementCount); 79 | flowControlSettings.setMaxOutstandingRequestBytes(maxOutstandingRequestBytes); 80 | if (limitExceededBehavior != null) { 81 | flowControlSettings.setLimitExceededBehavior(limitExceededBehavior); 82 | } 83 | settings.setFlowControlSettings(flowControlSettings.build()); 84 | } 85 | return settings.build(); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/com/google/cloud/logging/logback/LoggingAppender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.logging.logback; 18 | 19 | import ch.qos.logback.classic.Level; 20 | import ch.qos.logback.classic.spi.ILoggingEvent; 21 | import ch.qos.logback.classic.spi.IThrowableProxy; 22 | import ch.qos.logback.classic.spi.StackTraceElementProxy; 23 | import ch.qos.logback.core.UnsynchronizedAppenderBase; 24 | import ch.qos.logback.core.util.Loader; 25 | import com.google.api.core.InternalApi; 26 | import com.google.auth.oauth2.GoogleCredentials; 27 | import com.google.cloud.MonitoredResource; 28 | import com.google.cloud.logging.Instrumentation; 29 | import com.google.cloud.logging.LogEntry; 30 | import com.google.cloud.logging.Logging; 31 | import com.google.cloud.logging.Logging.WriteOption; 32 | import com.google.cloud.logging.LoggingEnhancer; 33 | import com.google.cloud.logging.LoggingOptions; 34 | import com.google.cloud.logging.MonitoredResourceUtil; 35 | import com.google.cloud.logging.Payload; 36 | import com.google.cloud.logging.Severity; 37 | import com.google.cloud.logging.Synchronicity; 38 | import com.google.common.base.Strings; 39 | import com.google.common.collect.ImmutableList; 40 | import java.io.FileInputStream; 41 | import java.io.IOException; 42 | import java.time.Instant; 43 | import java.util.ArrayList; 44 | import java.util.HashMap; 45 | import java.util.HashSet; 46 | import java.util.List; 47 | import java.util.Map; 48 | import java.util.Set; 49 | 50 | /** 51 | * Logback appender for Google Cloud Logging. 52 | * 53 | *

Appender configuration in logback.xml: 54 | * 55 | *

 56 |  *    <appender name="CLOUD" class="com.google.cloud.logging.logback.LoggingAppender">
 57 |  *         <!-- Optional: filter logs at and above this level -->
 58 |  *         <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
 59 |  *             <level>INFO</level>
 60 |  *         </filter>
 61 |  *
 62 |  *         <!-- Optional: defaults to {@code "java.log"} -->
 63 |  *         <log>application.log</log>
 64 |  *
 65 |  *         <!-- Optional: defaults to {@code "OFF"} -->
 66 |  *         <flushLevel>WARN</flushLevel>
 67 |  *
 68 |  *         <!-- Optional: defaults to {@code ASYNC} -->
 69 |  *         <writeSynchronicity>SYNC</writeSynchronicity>
 70 |  *
 71 |  *         <!-- Optional: defaults to {@code true} -->
 72 |  *         <autoPopulateMetadata>false</autoPopulateMetadata>
 73 |  *
 74 |  *         <!-- Optional: defaults to {@code false} -->
 75 |  *         <redirectToStdout>true</redirectToStdout>
 76 |  *
 77 |  *         <!-- Optional: auto detects on App Engine Flex, Standard, GCE and GKE, defaults to "global". See supported resource types -->
 80 |  *         <resourceType></resourceType>
 81 |  *
 82 |  *         <!-- Optional: defaults to the default credentials of the environment -->
 83 |  *         <credentialsFile>/path/to/credentials/file</credentialsFile>
 84 |  *
 85 |  *         <!-- Optional: defaults to the project id obtained during authentication process. Project id is also used to construct resource name of the log entries -->
 86 |  *         <logDestinationProjectId>String</logDestinationProjectId>
 87 |  *
 88 |  *         <!-- Optional: add custom labels to log entries using {@link LoggingEnhancer} classes -->
 89 |  *         <enhancer>com.example.enhancers.TestLoggingEnhancer</enhancer>
 90 |  *         <enhancer>com.example.enhancers.AnotherEnhancer</enhancer>
 91 |  *
 92 |  *         <!-- Optional: specifies if a batch's valid entries should be written even if some other entry failed due to an error. Defaults to {@code true} -->
 93 |  *         <partialSuccess>true</partialSuccess>
 94 |  *
 95 |  *         <!-- Optional: In the asynchronous mode the call(s) to Logging API takes place asynchronously and few calls to `write()`
 96 |  *         method may be batched together to compose a single call to Logging API. In order to control the batching settings,
 97 |  *         the `logbackBatchingSettings` section can be used as shown below.
 98 |  *         See [BatchingSettings](https://cloud.google.com/java/docs/reference/gax/latest/com.google.api.gax.batching.BatchingSettings)
 99 |  *         for more info regarding parameters shown below -->
100 |  *         <logbackBatchingSettings>
101 |  *            <elementCountThreshold>100</elementCountThreshold>
102 |  *            <requestByteThreshold>1000</requestByteThreshold>
103 |  *            <delayThreshold>500</delayThreshold>
104 |  *            <maxOutstandingElementCount>10000</maxOutstandingElementCount>
105 |  *            <maxOutstandingRequestBytes>100000</maxOutstandingRequestBytes>
106 |  *            <limitExceededBehavior>Ignore</limitExceededBehavior>
107 |  *         </logbackBatchingSettings>
108 |  *     </appender>
109 |  * 
110 | */ 111 | public class LoggingAppender extends UnsynchronizedAppenderBase { 112 | 113 | private static final String LEVEL_NAME_KEY = "levelName"; 114 | private static final String LEVEL_VALUE_KEY = "levelValue"; 115 | private static final String LOGGER_NAME_KEY = "loggerName"; 116 | private static final String TYPE = 117 | "type.googleapis.com/google.devtools.clouderrorreporting.v1beta1.ReportedErrorEvent"; 118 | private static final List DEFAULT_LOGGING_EVENT_ENHANCERS = 119 | ImmutableList.of(new MDCEventEnhancer()); 120 | public static final String JAVA_LOGBACK_LIBRARY_NAME = "java-logback"; 121 | // Using release-please annotations to update DEFAULT_INSTRUMENTATION_VERSION with latest version. 122 | // See 123 | // https://github.com/googleapis/release-please/blob/main/docs/customizing.md#updating-arbitrary-files 124 | // {x-version-update-start:google-cloud-logging-logback:current} 125 | public static final String DEFAULT_INSTRUMENTATION_VERSION = "0.132.10-alpha-SNAPSHOT"; 126 | // {x-version-update-end} 127 | private static boolean instrumentationAdded = false; 128 | private static final Object instrumentationLock = new Object(); 129 | 130 | private volatile Logging logging; 131 | private LoggingOptions loggingOptions; 132 | private MonitoredResource monitoredResource; 133 | private List loggingEnhancers; 134 | private List loggingEventEnhancers; 135 | private WriteOption[] defaultWriteOptions; 136 | 137 | private Level flushLevel; 138 | private String log; 139 | private String resourceType; 140 | private String credentialsFile; 141 | private String logDestinationProjectId; 142 | private boolean autoPopulateMetadata = true; 143 | private boolean redirectToStdout = false; 144 | private boolean partialSuccess = true; 145 | private Synchronicity writeSyncFlag = Synchronicity.ASYNC; 146 | private final Set enhancerClassNames = new HashSet<>(); 147 | private final Set loggingEventEnhancerClassNames = new HashSet<>(); 148 | private LogbackBatchingSettings logbackBatchingSettings = null; 149 | 150 | /** 151 | * Sets a threshold for log severity level to flush all log entries that were batched so far. 152 | * 153 | *

Defaults to OFF. 154 | * 155 | * @param flushLevel Logback log level 156 | */ 157 | public void setFlushLevel(Level flushLevel) { 158 | this.flushLevel = flushLevel; 159 | } 160 | 161 | /** 162 | * Sets the LOG_ID part of the log 164 | * name for which the logs are ingested. 165 | * 166 | * @param log LOG_ID part of the name 167 | */ 168 | public void setLog(String log) { 169 | this.log = log; 170 | } 171 | 172 | /** 173 | * Sets the name of the monitored resource (Optional). If not define the appender will try to 174 | * identify the resource type automatically. Currently support resource types include "gae_app", 175 | * "gce_instance", "k8s_container", "cloud_run_revision" and "cloud_function". If the appender 176 | * fails to identify the resource type, it will be set to "global". 177 | * 178 | *

Must be a one of the supported resource types. 180 | * 181 | * @param resourceType the name of the monitored resource. 182 | */ 183 | public void setResourceType(String resourceType) { 184 | this.resourceType = resourceType; 185 | } 186 | 187 | /** 188 | * Sets the path to the credential 190 | * file. If not set the appender will use {@link GoogleCredentials#getApplicationDefault()} to 191 | * authenticate. 192 | * 193 | * @param credentialsFile the path to the credentials file. 194 | */ 195 | public void setCredentialsFile(String credentialsFile) { 196 | this.credentialsFile = credentialsFile; 197 | } 198 | 199 | /** 200 | * Sets project ID to be used to customize log destination name for written log entries. 201 | * 202 | * @param projectId The project ID to be used to construct the resource destination name for log 203 | * entries. 204 | */ 205 | public void setLogDestinationProjectId(String projectId) { 206 | this.logDestinationProjectId = projectId; 207 | } 208 | 209 | /** 210 | * Sets the log ingestion mode. It can be one of the {@link Synchronicity} values. 211 | * 212 | *

Default to {@code Synchronicity.ASYNC} 213 | * 214 | * @param flag the new ingestion mode. 215 | */ 216 | public void setWriteSynchronicity(Synchronicity flag) { 217 | this.writeSyncFlag = flag; 218 | } 219 | 220 | /** 221 | * Sets the automatic population of metadata fields for ingested logs. 222 | * 223 | *

Default to {@code true}. 224 | * 225 | * @param flag the metadata auto-population flag. 226 | */ 227 | public void setAutoPopulateMetadata(boolean flag) { 228 | autoPopulateMetadata = flag; 229 | } 230 | 231 | /** 232 | * Sets the redirect of the appender's output to STDOUT instead of ingesting logs to Cloud Logging 233 | * using Logging API. 234 | * 235 | *

Default to {@code false}. 236 | * 237 | * @param flag the redirect flag. 238 | */ 239 | public void setRedirectToStdout(boolean flag) { 240 | redirectToStdout = flag; 241 | } 242 | 243 | /** 244 | * Sets the {@link LogbackBatchingSettings} to be used for the asynchronous mode call(s) to 245 | * Logging API 246 | * 247 | *

Default to {@code null}. 248 | * 249 | * @param batchingSettings the {@link LogbackBatchingSettings} to be used for asynchronous mode 250 | * call(s) to Logging API 251 | */ 252 | public void setLogbackBatchingSettings(LogbackBatchingSettings batchingSettings) { 253 | logbackBatchingSettings = batchingSettings; 254 | } 255 | 256 | /** 257 | * Sets the flag indicating if a batch's valid entries should be written even if some other entry 258 | * failed due to an error. 259 | * 260 | *

Default to {@code true}. 261 | * 262 | * @param flag the partialSuccess flag. 263 | */ 264 | public void setPartialSuccess(boolean flag) { 265 | partialSuccess = flag; 266 | } 267 | 268 | /** Add extra labels using classes that implement {@link LoggingEnhancer}. */ 269 | public void addEnhancer(String enhancerClassName) { 270 | this.enhancerClassNames.add(enhancerClassName); 271 | } 272 | 273 | public void addLoggingEventEnhancer(String enhancerClassName) { 274 | this.loggingEventEnhancerClassNames.add(enhancerClassName); 275 | } 276 | 277 | /** 278 | * Returns the current value of the ingestion mode. 279 | * 280 | *

The method is deprecated. Use appender configuration to set up the ingestion 281 | * 282 | * @return a {@link Synchronicity} value of the ingestion module. 283 | */ 284 | @Deprecated 285 | public Synchronicity getWriteSynchronicity() { 286 | return (this.writeSyncFlag != null) ? this.writeSyncFlag : Synchronicity.ASYNC; 287 | } 288 | 289 | private void setupMonitoredResource() { 290 | if (monitoredResource == null && autoPopulateMetadata) { 291 | monitoredResource = MonitoredResourceUtil.getResource(getProjectId(), resourceType); 292 | } 293 | } 294 | 295 | @InternalApi("Visible for testing") 296 | void setupMonitoredResource(MonitoredResource monitoredResource) { 297 | this.monitoredResource = monitoredResource; 298 | } 299 | 300 | private Level getFlushLevel() { 301 | return (flushLevel != null) ? flushLevel : Level.OFF; 302 | } 303 | 304 | private String getLogName() { 305 | return (log != null) ? log : "java.log"; 306 | } 307 | 308 | private List getLoggingEnhancers() { 309 | return getEnhancers(enhancerClassNames, LoggingEnhancer.class); 310 | } 311 | 312 | private List getLoggingEventEnhancers() { 313 | if (loggingEventEnhancerClassNames.isEmpty()) { 314 | return DEFAULT_LOGGING_EVENT_ENHANCERS; 315 | } else { 316 | return getEnhancers(loggingEventEnhancerClassNames, LoggingEventEnhancer.class); 317 | } 318 | } 319 | 320 | private List getEnhancers(Set classNames, Class classOfT) { 321 | List enhancers = new ArrayList<>(); 322 | if (classNames != null) { 323 | for (String className : classNames) { 324 | if (className != null) { 325 | try { 326 | T enhancer = 327 | Loader.loadClass(className.trim()) 328 | .asSubclass(classOfT) 329 | .getDeclaredConstructor() 330 | .newInstance(); 331 | enhancers.add(enhancer); 332 | } catch (Exception ex) { 333 | // invalid className: ignore 334 | } 335 | } 336 | } 337 | } 338 | return enhancers; 339 | } 340 | 341 | /** Initialize and configure the cloud logging service. */ 342 | @Override 343 | public synchronized void start() { 344 | if (isStarted()) { 345 | return; 346 | } 347 | 348 | setupMonitoredResource(); 349 | 350 | defaultWriteOptions = 351 | new WriteOption[] { 352 | WriteOption.logName(getLogName()), 353 | WriteOption.resource(monitoredResource), 354 | WriteOption.partialSuccess(partialSuccess) 355 | }; 356 | Level flushLevel = getFlushLevel(); 357 | if (flushLevel != Level.OFF) { 358 | getLogging().setFlushSeverity(severityFor(flushLevel)); 359 | } 360 | loggingEnhancers = new ArrayList<>(); 361 | List resourceEnhancers = MonitoredResourceUtil.getResourceEnhancers(); 362 | loggingEnhancers.addAll(resourceEnhancers); 363 | loggingEnhancers.addAll(getLoggingEnhancers()); 364 | loggingEventEnhancers = new ArrayList<>(); 365 | loggingEventEnhancers.addAll(getLoggingEventEnhancers()); 366 | 367 | super.start(); 368 | } 369 | 370 | String getProjectId() { 371 | return getLoggingOptions().getProjectId(); 372 | } 373 | 374 | @Override 375 | protected void append(ILoggingEvent e) { 376 | List entriesList = new ArrayList<>(); 377 | entriesList.add(logEntryFor(e)); 378 | // Check if instrumentation was already added - if not, create a log entry with instrumentation 379 | // data 380 | if (!setInstrumentationStatus(true)) { 381 | entriesList.add( 382 | Instrumentation.createDiagnosticEntry( 383 | JAVA_LOGBACK_LIBRARY_NAME, DEFAULT_INSTRUMENTATION_VERSION)); 384 | } 385 | Iterable entries = entriesList; 386 | if (autoPopulateMetadata) { 387 | entries = 388 | getLogging() 389 | .populateMetadata( 390 | entries, 391 | monitoredResource, 392 | "com.google.cloud.logging", 393 | "jdk", 394 | "sun", 395 | "java", 396 | "ch.qos.logback"); 397 | } 398 | if (redirectToStdout) { 399 | for (LogEntry entry : entries) { 400 | System.out.println(entry.toStructuredJsonString()); 401 | } 402 | } else { 403 | getLogging().write(entries, defaultWriteOptions); 404 | } 405 | } 406 | 407 | @Override 408 | public synchronized void stop() { 409 | if (logging != null) { 410 | try { 411 | logging.close(); 412 | } catch (Exception ex) { 413 | // ignore 414 | } 415 | } 416 | logging = null; 417 | super.stop(); 418 | } 419 | 420 | Logging getLogging() { 421 | if (logging == null) { 422 | synchronized (this) { 423 | if (logging == null) { 424 | logging = getLoggingOptions().getService(); 425 | logging.setWriteSynchronicity(writeSyncFlag); 426 | } 427 | } 428 | } 429 | return logging; 430 | } 431 | 432 | /** Flushes any pending asynchronous logging writes. */ 433 | @Deprecated 434 | public void flush() { 435 | if (!isStarted()) { 436 | return; 437 | } 438 | synchronized (this) { 439 | getLogging().flush(); 440 | } 441 | } 442 | 443 | /** Gets the {@link LoggingOptions} to use for this {@link LoggingAppender}. */ 444 | protected LoggingOptions getLoggingOptions() { 445 | if (loggingOptions == null) { 446 | LoggingOptions.Builder builder = LoggingOptions.newBuilder(); 447 | builder.setProjectId(logDestinationProjectId); 448 | if (!Strings.isNullOrEmpty(credentialsFile)) { 449 | try { 450 | builder.setCredentials( 451 | GoogleCredentials.fromStream(new FileInputStream(credentialsFile))); 452 | } catch (IOException e) { 453 | throw new RuntimeException( 454 | String.format( 455 | "Could not read credentials file %s. Please verify that the file exists and is a valid Google credentials file.", 456 | credentialsFile), 457 | e); 458 | } 459 | } 460 | // opt-out metadata auto-population to control it in the appender code 461 | builder.setAutoPopulateMetadata(false); 462 | builder.setBatchingSettings( 463 | this.logbackBatchingSettings != null ? this.logbackBatchingSettings.build() : null); 464 | loggingOptions = builder.build(); 465 | } 466 | return loggingOptions; 467 | } 468 | 469 | private LogEntry logEntryFor(ILoggingEvent e) { 470 | StringBuilder payload = new StringBuilder().append(e.getFormattedMessage()).append('\n'); 471 | writeStack(e.getThrowableProxy(), "", payload); 472 | 473 | Level level = e.getLevel(); 474 | Severity severity = severityFor(level); 475 | 476 | Map jsonContent = new HashMap<>(); 477 | jsonContent.put("message", payload.toString().trim()); 478 | if (severity == Severity.ERROR) { 479 | jsonContent.put("@type", TYPE); 480 | } 481 | LogEntry.Builder builder = 482 | LogEntry.newBuilder(Payload.JsonPayload.of(jsonContent)) 483 | .setTimestamp(Instant.ofEpochMilli(e.getTimeStamp())) 484 | .setSeverity(severity); 485 | builder 486 | .addLabel(LEVEL_NAME_KEY, level.toString()) 487 | .addLabel(LEVEL_VALUE_KEY, String.valueOf(level.toInt())) 488 | .addLabel(LOGGER_NAME_KEY, e.getLoggerName()); 489 | 490 | if (loggingEnhancers != null) { 491 | for (LoggingEnhancer enhancer : loggingEnhancers) { 492 | enhancer.enhanceLogEntry(builder); 493 | } 494 | } 495 | 496 | if (loggingEventEnhancers != null) { 497 | for (LoggingEventEnhancer enhancer : loggingEventEnhancers) { 498 | enhancer.enhanceLogEntry(builder, e); 499 | } 500 | } 501 | 502 | return builder.build(); 503 | } 504 | 505 | @InternalApi("Visible for testing") 506 | static void writeStack(IThrowableProxy throwProxy, String prefix, StringBuilder payload) { 507 | if (throwProxy == null) { 508 | return; 509 | } 510 | payload 511 | .append(prefix) 512 | .append(throwProxy.getClassName()) 513 | .append(": ") 514 | .append(throwProxy.getMessage()) 515 | .append('\n'); 516 | StackTraceElementProxy[] trace = throwProxy.getStackTraceElementProxyArray(); 517 | if (trace == null) { 518 | trace = new StackTraceElementProxy[0]; 519 | } 520 | 521 | int commonFrames = throwProxy.getCommonFrames(); 522 | int printFrames = trace.length - commonFrames; 523 | for (int i = 0; i < printFrames; i++) { 524 | payload.append(" ").append(trace[i]).append('\n'); 525 | } 526 | if (commonFrames != 0) { 527 | payload.append(" ... ").append(commonFrames).append(" common frames elided\n"); 528 | } 529 | 530 | writeStack(throwProxy.getCause(), "caused by: ", payload); 531 | } 532 | 533 | /** 534 | * Transforms Logback logging levels to Cloud severity. 535 | * 536 | * @param level Logback logging level 537 | * @return Cloud severity level 538 | */ 539 | private static Severity severityFor(Level level) { 540 | switch (level.toInt()) { 541 | // TRACE 542 | case 5000: 543 | return Severity.DEBUG; 544 | // DEBUG 545 | case 10000: 546 | return Severity.DEBUG; 547 | // INFO 548 | case 20000: 549 | return Severity.INFO; 550 | // WARNING 551 | case 30000: 552 | return Severity.WARNING; 553 | // ERROR 554 | case 40000: 555 | return Severity.ERROR; 556 | default: 557 | return Severity.DEFAULT; 558 | } 559 | } 560 | 561 | /** 562 | * The package-private helper method used to set the flag which indicates if instrumentation info 563 | * already written or not. 564 | * 565 | * @return The value of the flag before it was set. 566 | */ 567 | static boolean setInstrumentationStatus(boolean value) { 568 | if (instrumentationAdded == value) return instrumentationAdded; 569 | synchronized (instrumentationLock) { 570 | boolean current = instrumentationAdded; 571 | instrumentationAdded = value; 572 | return current; 573 | } 574 | } 575 | } 576 | -------------------------------------------------------------------------------- /src/main/java/com/google/cloud/logging/logback/LoggingEventEnhancer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.logging.logback; 18 | 19 | import ch.qos.logback.classic.spi.ILoggingEvent; 20 | import com.google.cloud.logging.LogEntry; 21 | 22 | /** 23 | * An enhancer for {@linkplain ILoggingEvent} log entries. Used to add custom labels to the {@link 24 | * LogEntry.Builder}. 25 | */ 26 | public interface LoggingEventEnhancer { 27 | void enhanceLogEntry(LogEntry.Builder builder, ILoggingEvent e); 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/google/cloud/logging/logback/MDCEventEnhancer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.logging.logback; 18 | 19 | import ch.qos.logback.classic.spi.ILoggingEvent; 20 | import com.google.cloud.logging.LogEntry; 21 | import java.util.Map; 22 | 23 | /** 24 | * MDCEventEnhancer takes values found in the MDC property map and adds them as labels to the {@link 25 | * LogEntry}. This {@link LoggingEventEnhancer} is turned on by default. If you wish to filter which 26 | * MDC values get added as labels to your {@link LogEntry}, implement a {@link LoggingEventEnhancer} 27 | * and add its classpath to your {@code logback.xml}. If any {@link LoggingEventEnhancer} is added 28 | * this class is no longer registered. 29 | */ 30 | final class MDCEventEnhancer implements LoggingEventEnhancer { 31 | 32 | @Override 33 | public void enhanceLogEntry(LogEntry.Builder builder, ILoggingEvent e) { 34 | for (Map.Entry entry : e.getMDCPropertyMap().entrySet()) { 35 | if (null != entry.getKey() && null != entry.getValue()) { 36 | builder.addLabel(entry.getKey(), entry.getValue()); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/google/cloud/logging/logback/TraceLoggingEventEnhancer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.logging.logback; 18 | 19 | import ch.qos.logback.classic.spi.ILoggingEvent; 20 | import com.google.cloud.logging.LogEntry; 21 | import org.slf4j.MDC; 22 | 23 | /** Adds support for grouping logs by incoming http request */ 24 | public class TraceLoggingEventEnhancer implements LoggingEventEnhancer { 25 | 26 | // A key used by Cloud Logging for trace Id 27 | private static final String TRACE_ID = "logging.googleapis.trace"; 28 | 29 | /** 30 | * Set the Trace ID associated with any logging done by the current thread. 31 | * 32 | * @param id The traceID, in the form projects/[PROJECT_ID]/traces/[TRACE_ID] 33 | */ 34 | public static void setCurrentTraceId(String id) { 35 | MDC.put(TRACE_ID, id); 36 | } 37 | 38 | /** Clearing a trace Id from the MDC */ 39 | public static void clearTraceId() { 40 | MDC.remove(TRACE_ID); 41 | } 42 | 43 | /** 44 | * Get the Trace ID associated with any logging done by the current thread. 45 | * 46 | * @return id The traceID 47 | */ 48 | public static String getCurrentTraceId() { 49 | return MDC.get(TRACE_ID); 50 | } 51 | 52 | @Override 53 | public void enhanceLogEntry(LogEntry.Builder builder, ILoggingEvent e) { 54 | Object value = e.getMDCPropertyMap().get(TRACE_ID); 55 | String traceId = value != null ? value.toString() : null; 56 | if (traceId != null) { 57 | builder.setTrace(traceId); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/native-image/com.google.cloud/google-cloud-logging-logback/reflect-config.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name":"ch.qos.logback.classic.Level", 4 | "methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }] 5 | }, 6 | { 7 | "name":"ch.qos.logback.classic.filter.ThresholdFilter", 8 | "queryAllPublicMethods":true, 9 | "methods":[ 10 | {"name":"","parameterTypes":[] }, 11 | {"name":"setLevel","parameterTypes":["java.lang.String"] } 12 | ] 13 | }, 14 | { 15 | "name":"ch.qos.logback.core.UnsynchronizedAppenderBase", 16 | "methods":[{"name":"addFilter","parameterTypes":["ch.qos.logback.core.filter.Filter"] }] 17 | }, 18 | { 19 | "name":"com.google.cloud.logging.logback.LogbackBatchingSettings", 20 | "queryAllPublicMethods":true, 21 | "methods":[ 22 | {"name":"","parameterTypes":[] }, 23 | {"name":"setDelayThreshold","parameterTypes":["java.lang.Long"] }, 24 | {"name":"setElementCountThreshold","parameterTypes":["java.lang.Long"] }, 25 | {"name":"setLimitExceededBehavior","parameterTypes":["com.google.api.gax.batching.FlowController$LimitExceededBehavior"] }, 26 | {"name":"setMaxOutstandingElementCount","parameterTypes":["java.lang.Long"] }, 27 | {"name":"setMaxOutstandingRequestBytes","parameterTypes":["java.lang.Long"] }, 28 | {"name":"setRequestByteThreshold","parameterTypes":["java.lang.Long"] } 29 | ] 30 | }, 31 | { 32 | "name":"com.google.cloud.logging.logback.LoggingAppender", 33 | "queryAllPublicMethods":true, 34 | "methods":[ 35 | {"name":"","parameterTypes":[] }, 36 | {"name":"setAutoPopulateMetadata","parameterTypes":["boolean"] }, 37 | {"name":"setCredentialsFile","parameterTypes":["java.lang.String"] }, 38 | {"name":"setFlushLevel","parameterTypes":["ch.qos.logback.classic.Level"] }, 39 | {"name":"setLog","parameterTypes":["java.lang.String"] }, 40 | {"name":"setLogDestinationProjectId","parameterTypes":["java.lang.String"] }, 41 | {"name":"setLogbackBatchingSettings","parameterTypes":["com.google.cloud.logging.logback.LogbackBatchingSettings"] }, 42 | {"name":"setPartialSuccess","parameterTypes":["boolean"] }, 43 | {"name":"setRedirectToStdout","parameterTypes":["boolean"] }, 44 | {"name":"setResourceType","parameterTypes":["java.lang.String"] }, 45 | {"name":"setWriteSynchronicity","parameterTypes":["com.google.cloud.logging.Synchronicity"] } 46 | ] 47 | }, 48 | { 49 | "name":"java.lang.Long", 50 | "methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }] 51 | } 52 | ] 53 | -------------------------------------------------------------------------------- /src/test/java/com/google/cloud/logging/logback/LoggingAppenderLogbackTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.logging.logback; 18 | 19 | import static com.google.common.truth.Truth.assertThat; 20 | 21 | import ch.qos.logback.classic.LoggerContext; 22 | import ch.qos.logback.classic.joran.JoranConfigurator; 23 | import ch.qos.logback.core.joran.spi.JoranException; 24 | import com.google.api.gax.batching.FlowController.LimitExceededBehavior; 25 | import com.google.cloud.logging.LoggingOptions; 26 | import org.junit.Test; 27 | import org.slf4j.Logger; 28 | import org.slf4j.LoggerFactory; 29 | 30 | public class LoggingAppenderLogbackTest { 31 | @Test 32 | public void testLoggingOptionsFromLogbackXMLFileConfig() throws JoranException { 33 | LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); 34 | JoranConfigurator jc = new JoranConfigurator(); 35 | jc.setContext(context); 36 | context.reset(); 37 | jc.doConfigure("src/test/java/com/google/cloud/logging/logback/logback.xml"); 38 | Logger logger = LoggerFactory.getLogger(LoggingAppenderLogbackTest.class); 39 | assertThat(logger.getName()) 40 | .isEqualTo("com.google.cloud.logging.logback.LoggingAppenderLogbackTest"); 41 | LoggingAppender appender = (LoggingAppender) context.getLogger("ROOT").getAppender("CLOUD"); 42 | LoggingOptions options = appender.getLoggingOptions(); 43 | assertThat(options.getAutoPopulateMetadata()).isEqualTo(false); 44 | assertThat(options.getBatchingSettings().getDelayThreshold().toMillis()).isEqualTo(500); 45 | assertThat(options.getBatchingSettings().getElementCountThreshold()).isEqualTo(100); 46 | assertThat(options.getBatchingSettings().getIsEnabled()).isEqualTo(true); 47 | assertThat(options.getBatchingSettings().getRequestByteThreshold()).isEqualTo(1000); 48 | assertThat(options.getBatchingSettings().getFlowControlSettings().getLimitExceededBehavior()) 49 | .isEqualTo(LimitExceededBehavior.Ignore); 50 | assertThat( 51 | options.getBatchingSettings().getFlowControlSettings().getMaxOutstandingElementCount()) 52 | .isEqualTo(10000); 53 | assertThat( 54 | options.getBatchingSettings().getFlowControlSettings().getMaxOutstandingRequestBytes()) 55 | .isEqualTo(100000); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/test/java/com/google/cloud/logging/logback/LoggingAppenderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.logging.logback; 18 | 19 | import static com.google.common.truth.Truth.assertThat; 20 | import static org.easymock.EasyMock.anyObject; 21 | import static org.easymock.EasyMock.capture; 22 | import static org.easymock.EasyMock.expectLastCall; 23 | import static org.easymock.EasyMock.replay; 24 | import static org.easymock.EasyMock.verify; 25 | import static org.junit.Assert.assertEquals; 26 | 27 | import ch.qos.logback.classic.Level; 28 | import ch.qos.logback.classic.filter.ThresholdFilter; 29 | import ch.qos.logback.classic.spi.ILoggingEvent; 30 | import ch.qos.logback.classic.spi.LoggingEvent; 31 | import com.google.cloud.MonitoredResource; 32 | import com.google.cloud.Timestamp; 33 | import com.google.cloud.logging.Instrumentation; 34 | import com.google.cloud.logging.LogEntry; 35 | import com.google.cloud.logging.Logging; 36 | import com.google.cloud.logging.Logging.WriteOption; 37 | import com.google.cloud.logging.LoggingEnhancer; 38 | import com.google.cloud.logging.Payload; 39 | import com.google.cloud.logging.Payload.JsonPayload; 40 | import com.google.cloud.logging.Payload.Type; 41 | import com.google.cloud.logging.Severity; 42 | import com.google.common.base.Strings; 43 | import com.google.common.collect.ImmutableList; 44 | import com.google.common.collect.ImmutableMap; 45 | import com.google.protobuf.ListValue; 46 | import com.google.protobuf.Value; 47 | import java.io.ByteArrayOutputStream; 48 | import java.io.PrintStream; 49 | import java.time.Instant; 50 | import java.util.Map; 51 | import org.easymock.Capture; 52 | import org.easymock.EasyMock; 53 | import org.easymock.EasyMockRunner; 54 | import org.junit.Before; 55 | import org.junit.Test; 56 | import org.junit.runner.RunWith; 57 | import org.slf4j.MDC; 58 | 59 | @RunWith(EasyMockRunner.class) 60 | public class LoggingAppenderTest { 61 | private static final String PROJECT_ID = "test-project"; 62 | private static final String CRED_FILE_PROJECT_ID = "project-12345"; 63 | private static final String OVERRIDED_PROJECT_ID = "some-project-id"; 64 | private static final String DUMMY_CRED_FILE_PATH = 65 | "src/test/java/com/google/cloud/logging/logback/dummy-credentials.json"; 66 | private static final Payload.JsonPayload JSON_PAYLOAD = 67 | Payload.JsonPayload.of(ImmutableMap.of("message", "this is a test")); 68 | private static final Payload.JsonPayload JSON_ERROR_PAYLOAD = 69 | Payload.JsonPayload.of( 70 | ImmutableMap.of( 71 | "message", 72 | "this is a test", 73 | "@type", 74 | "type.googleapis.com/google.devtools.clouderrorreporting.v1beta1.ReportedErrorEvent")); 75 | private static final MonitoredResource DEFAULT_RESOURCE = 76 | MonitoredResource.of("global", ImmutableMap.of("project_id", PROJECT_ID)); 77 | private static final LogEntry WARN_ENTRY = 78 | LogEntry.newBuilder(JSON_PAYLOAD) 79 | .setTimestamp(Instant.ofEpochMilli(100000L)) 80 | .setSeverity(Severity.WARNING) 81 | .setLabels( 82 | new ImmutableMap.Builder() 83 | .put("levelName", "WARN") 84 | .put("levelValue", String.valueOf(30000L)) 85 | .put("loggerName", LoggingAppenderTest.class.getName()) 86 | // .put("test-label-1", "test-value-1") 87 | // .put("test-label-2", "test-value-2") 88 | .build()) 89 | .build(); 90 | private static final LogEntry ERROR_ENTRY = 91 | LogEntry.newBuilder(JSON_ERROR_PAYLOAD) 92 | .setTimestamp(Instant.ofEpochMilli(100000L)) 93 | .setSeverity(Severity.ERROR) 94 | .setLabels( 95 | new ImmutableMap.Builder() 96 | .put("levelName", "ERROR") 97 | .put("levelValue", String.valueOf(40000L)) 98 | .put("loggerName", LoggingAppenderTest.class.getName()) 99 | .build()) 100 | .build(); 101 | private static final LogEntry INFO_ENTRY = 102 | LogEntry.newBuilder(JSON_PAYLOAD) 103 | .setTimestamp(Instant.ofEpochMilli(100000L)) 104 | .setSeverity(Severity.INFO) 105 | .setLabels( 106 | new ImmutableMap.Builder() 107 | .put("levelName", "INFO") 108 | .put("levelValue", String.valueOf(20000L)) 109 | .put("loggerName", LoggingAppenderTest.class.getName()) 110 | .put("mdc1", "value1") 111 | .put("mdc2", "value2") 112 | .build()) 113 | .build(); 114 | 115 | private Logging logging; 116 | private LoggingAppender loggingAppender; 117 | 118 | static class CustomLoggingEventEnhancer implements LoggingEventEnhancer { 119 | 120 | @Override 121 | public void enhanceLogEntry(LogEntry.Builder builder, ILoggingEvent e) { 122 | builder.addLabel("foo", "bar"); 123 | } 124 | } 125 | 126 | static class CustomLoggingEnhancer implements LoggingEnhancer { 127 | 128 | @Override 129 | public void enhanceLogEntry(LogEntry.Builder builder) { 130 | builder.addLabel("foo", "bar"); 131 | } 132 | } 133 | 134 | class TestLoggingAppender extends LoggingAppender { 135 | @Override 136 | String getProjectId() { 137 | return PROJECT_ID; 138 | } 139 | 140 | @Override 141 | Logging getLogging() { 142 | return logging; 143 | } 144 | } 145 | 146 | @Before 147 | public void setUp() { 148 | LoggingAppender.setInstrumentationStatus(true); 149 | logging = EasyMock.createStrictMock(Logging.class); 150 | loggingAppender = new TestLoggingAppender(); 151 | loggingAppender.setAutoPopulateMetadata(false); 152 | } 153 | 154 | private final WriteOption[] defaultWriteOptions = 155 | new WriteOption[] { 156 | WriteOption.logName("java.log"), 157 | WriteOption.resource( 158 | MonitoredResource.newBuilder("global") 159 | .setLabels( 160 | new ImmutableMap.Builder() 161 | .put("project_id", PROJECT_ID) 162 | .build()) 163 | .build()), 164 | WriteOption.partialSuccess(true), 165 | }; 166 | 167 | @Test 168 | public void testFlushLevelConfigUpdatesLoggingFlushSeverity() { 169 | logging.setFlushSeverity(Severity.WARNING); 170 | Capture> capturedArgument = Capture.newInstance(); 171 | logging.write( 172 | capture(capturedArgument), 173 | anyObject(WriteOption.class), 174 | anyObject(WriteOption.class), 175 | anyObject(WriteOption.class)); 176 | replay(logging); 177 | Timestamp timestamp = Timestamp.ofTimeSecondsAndNanos(100000, 0); 178 | LoggingEvent loggingEvent = createLoggingEvent(Level.WARN, timestamp.getSeconds()); 179 | // error is the default, updating to warn for test 180 | loggingAppender.setFlushLevel(Level.WARN); 181 | loggingAppender.start(); 182 | loggingAppender.doAppend(loggingEvent); 183 | verify(logging); 184 | assertThat(capturedArgument.getValue().iterator().hasNext()).isTrue(); 185 | assertThat(capturedArgument.getValue().iterator().next()).isEqualTo(WARN_ENTRY); 186 | } 187 | 188 | @Test 189 | public void testFlushLevelConfigSupportsFlushLevelOff() { 190 | loggingAppender.setFlushLevel(Level.OFF); 191 | loggingAppender.start(); 192 | Severity foundSeverity = logging.getFlushSeverity(); 193 | assertThat(foundSeverity).isEqualTo(null); 194 | } 195 | 196 | @Test 197 | public void testDefaultFlushLevelOff() { 198 | loggingAppender.start(); 199 | Severity foundSeverity = logging.getFlushSeverity(); 200 | assertThat(foundSeverity).isEqualTo(null); 201 | } 202 | 203 | @Test 204 | public void testFilterLogsOnlyLogsAtOrAboveLogLevel() { 205 | Capture> capturedArgument = Capture.newInstance(); 206 | logging.write( 207 | capture(capturedArgument), 208 | anyObject(WriteOption.class), 209 | anyObject(WriteOption.class), 210 | anyObject(WriteOption.class)); 211 | expectLastCall().once(); 212 | replay(logging); 213 | Timestamp timestamp = Timestamp.ofTimeSecondsAndNanos(100000, 0); 214 | LoggingEvent loggingEvent1 = createLoggingEvent(Level.INFO, timestamp.getSeconds()); 215 | ThresholdFilter thresholdFilter = new ThresholdFilter(); 216 | thresholdFilter.setLevel("ERROR"); 217 | thresholdFilter.start(); 218 | loggingAppender.addFilter(thresholdFilter); 219 | loggingAppender.start(); 220 | // info event does not get logged 221 | loggingAppender.doAppend(loggingEvent1); 222 | LoggingEvent loggingEvent2 = createLoggingEvent(Level.ERROR, timestamp.getSeconds()); 223 | // error event gets logged 224 | loggingAppender.doAppend(loggingEvent2); 225 | verify(logging); 226 | assertThat(capturedArgument.getValue().iterator().hasNext()).isTrue(); 227 | assertThat(capturedArgument.getValue().iterator().next()).isEqualTo(ERROR_ENTRY); 228 | } 229 | 230 | @Test 231 | public void testPartialSuccessOverrideHasExpectedValue() { 232 | Capture logNameArg = Capture.newInstance(); 233 | Capture resourceArg = Capture.newInstance(); 234 | Capture partialSuccessArg = Capture.newInstance(); 235 | logging.write( 236 | EasyMock.>anyObject(), 237 | capture(logNameArg), 238 | capture(resourceArg), 239 | capture(partialSuccessArg)); 240 | expectLastCall().once(); 241 | replay(logging); 242 | loggingAppender.start(); 243 | Timestamp timestamp = Timestamp.ofTimeSecondsAndNanos(100000, 0); 244 | LoggingEvent loggingEvent = createLoggingEvent(Level.ERROR, timestamp.getSeconds()); 245 | loggingAppender.doAppend(loggingEvent); 246 | 247 | assertThat(logNameArg.getValue()).isEqualTo(defaultWriteOptions[0]); 248 | // TODO(chingor): Fix this test to work on GCE and locally 249 | // assertThat(resourceArg.getValue()).isEqualTo(defaultWriteOptions[1]); 250 | assertThat(partialSuccessArg.getValue()).isEqualTo(defaultWriteOptions[2]); 251 | } 252 | 253 | @Test 254 | public void testDefaultWriteOptionsHasExpectedDefaults() { 255 | Capture partialSuccessArg = Capture.newInstance(); 256 | logging.write( 257 | EasyMock.>anyObject(), 258 | anyObject(WriteOption.class), 259 | anyObject(WriteOption.class), 260 | capture(partialSuccessArg)); 261 | expectLastCall().once(); 262 | replay(logging); 263 | loggingAppender.setPartialSuccess(false); 264 | loggingAppender.start(); 265 | Timestamp timestamp = Timestamp.ofTimeSecondsAndNanos(100000, 0); 266 | LoggingEvent loggingEvent = createLoggingEvent(Level.ERROR, timestamp.getSeconds()); 267 | loggingAppender.doAppend(loggingEvent); 268 | assertThat(partialSuccessArg.getValue()).isEqualTo(WriteOption.partialSuccess(false)); 269 | } 270 | 271 | @Test 272 | public void testMdcValuesAreConvertedToLabels() { 273 | Capture> capturedArgument = Capture.newInstance(); 274 | logging.write( 275 | capture(capturedArgument), 276 | anyObject(WriteOption.class), 277 | anyObject(WriteOption.class), 278 | anyObject(WriteOption.class)); 279 | expectLastCall().once(); 280 | replay(logging); 281 | Timestamp timestamp = Timestamp.ofTimeSecondsAndNanos(100000, 0); 282 | LoggingEvent loggingEvent = createLoggingEvent(Level.INFO, timestamp.getSeconds()); 283 | loggingEvent.setMDCPropertyMap(ImmutableMap.of("mdc1", "value1", "mdc2", "value2")); 284 | loggingAppender.start(); 285 | // info event does not get logged 286 | loggingAppender.doAppend(loggingEvent); 287 | verify(logging); 288 | assertThat(capturedArgument.getValue().iterator().hasNext()).isTrue(); 289 | assertThat(capturedArgument.getValue().iterator().next()).isEqualTo(INFO_ENTRY); 290 | } 291 | 292 | @Test(expected = RuntimeException.class) 293 | public void testCreateLoggingOptionsWithInvalidCredentials() { 294 | final String nonExistentFile = "/path/to/non/existent/file"; 295 | LoggingAppender appender = new LoggingAppender(); 296 | appender.setCredentialsFile(nonExistentFile); 297 | appender.getLoggingOptions(); 298 | } 299 | 300 | @Test 301 | public void testCreateLoggingOptionsWithCredentials() { 302 | // Try to build LoggingOptions with file based credentials. 303 | LoggingAppender appender = new LoggingAppender(); 304 | appender.setCredentialsFile(DUMMY_CRED_FILE_PATH); 305 | assertThat(appender.getLoggingOptions().getProjectId()).isEqualTo(CRED_FILE_PROJECT_ID); 306 | } 307 | 308 | @Test 309 | public void testCreateLoggingOptionsWithDestination() { 310 | // Try to build LoggingOptions with file based credentials. 311 | LoggingAppender appender = new LoggingAppender(); 312 | appender.setCredentialsFile(DUMMY_CRED_FILE_PATH); 313 | appender.setLogDestinationProjectId(OVERRIDED_PROJECT_ID); 314 | assertThat(appender.getLoggingOptions().getProjectId()).isEqualTo(OVERRIDED_PROJECT_ID); 315 | } 316 | 317 | private LoggingEvent createLoggingEvent(Level level, long timestamp) { 318 | LoggingEvent loggingEvent = new LoggingEvent(); 319 | loggingEvent.setMessage("this is a test"); 320 | loggingEvent.setLevel(level); 321 | loggingEvent.setTimeStamp(timestamp); 322 | loggingEvent.setLoggerName(this.getClass().getName()); 323 | return loggingEvent; 324 | } 325 | 326 | @Test 327 | public void testMdcValuesAreConvertedToLabelsWithPassingNullValues() { 328 | MDC.put("mdc1", "value1"); 329 | MDC.put("mdc2", null); 330 | MDC.put("mdc3", "value3"); 331 | Capture> capturedArgument = Capture.newInstance(); 332 | logging.write( 333 | capture(capturedArgument), 334 | anyObject(WriteOption.class), 335 | anyObject(WriteOption.class), 336 | anyObject(WriteOption.class)); 337 | expectLastCall().once(); 338 | replay(logging); 339 | Timestamp timestamp = Timestamp.ofTimeSecondsAndNanos(100000, 0); 340 | LoggingEvent loggingEvent = createLoggingEvent(Level.INFO, timestamp.getSeconds()); 341 | loggingAppender.start(); 342 | loggingAppender.doAppend(loggingEvent); 343 | verify(logging); 344 | MDC.remove("mdc1"); 345 | MDC.remove("mdc3"); 346 | Map capturedArgumentMap = 347 | capturedArgument.getValue().iterator().next().getLabels(); 348 | assertThat(capturedArgumentMap.get("mdc1")).isEqualTo("value1"); 349 | assertThat(capturedArgumentMap.get("mdc2")).isNull(); 350 | assertThat(capturedArgumentMap.get("mdc3")).isEqualTo("value3"); 351 | } 352 | 353 | @Test 354 | public void testAddCustomLoggingEventEnhancers() { 355 | MDC.put("mdc1", "value1"); 356 | Capture> capturedArgument = Capture.newInstance(); 357 | logging.write( 358 | capture(capturedArgument), 359 | anyObject(WriteOption.class), 360 | anyObject(WriteOption.class), 361 | anyObject(WriteOption.class)); 362 | expectLastCall().once(); 363 | replay(logging); 364 | Timestamp timestamp = Timestamp.ofTimeSecondsAndNanos(100000, 0); 365 | LoggingEvent loggingEvent = createLoggingEvent(Level.INFO, timestamp.getSeconds()); 366 | loggingAppender.addLoggingEventEnhancer(CustomLoggingEventEnhancer.class.getName()); 367 | loggingAppender.start(); 368 | loggingAppender.doAppend(loggingEvent); 369 | verify(logging); 370 | MDC.remove("mdc1"); 371 | Map capturedArgumentMap = 372 | capturedArgument.getValue().iterator().next().getLabels(); 373 | assertThat(capturedArgumentMap.get("mdc1")).isNull(); 374 | assertThat(capturedArgumentMap.get("foo")).isEqualTo("bar"); 375 | } 376 | 377 | @Test 378 | public void testAddCustomLoggingEnhancer() { 379 | Capture> capturedArgument = Capture.newInstance(); 380 | logging.write( 381 | capture(capturedArgument), 382 | anyObject(WriteOption.class), 383 | anyObject(WriteOption.class), 384 | anyObject(WriteOption.class)); 385 | expectLastCall().once(); 386 | replay(logging); 387 | loggingAppender.addEnhancer(CustomLoggingEnhancer.class.getName()); 388 | loggingAppender.start(); 389 | Timestamp timestamp = Timestamp.ofTimeSecondsAndNanos(100000, 0); 390 | LoggingEvent loggingEvent = createLoggingEvent(Level.WARN, timestamp.getSeconds()); 391 | loggingAppender.doAppend(loggingEvent); 392 | verify(logging); 393 | Map capturedArgumentMap = 394 | capturedArgument.getValue().iterator().next().getLabels(); 395 | assertThat(capturedArgumentMap.get("foo")).isEqualTo("bar"); 396 | } 397 | 398 | @Test 399 | @SuppressWarnings("deprecation") 400 | public void testFlush() { 401 | logging.write( 402 | EasyMock.>anyObject(), 403 | anyObject(WriteOption.class), 404 | anyObject(WriteOption.class), 405 | anyObject(WriteOption.class)); 406 | expectLastCall().times(2); 407 | logging.flush(); 408 | replay(logging); 409 | loggingAppender.start(); 410 | Timestamp timestamp = Timestamp.ofTimeSecondsAndNanos(100000, 0); 411 | LoggingEvent firstLoggingEvent = createLoggingEvent(Level.WARN, timestamp.getSeconds()); 412 | LoggingEvent secondLoggingEvent = createLoggingEvent(Level.INFO, timestamp.getSeconds()); 413 | loggingAppender.doAppend(firstLoggingEvent); 414 | loggingAppender.doAppend(secondLoggingEvent); 415 | loggingAppender.flush(); 416 | verify(logging); 417 | } 418 | 419 | @Test 420 | public void testAutoPopulationEnabled() { 421 | Capture> capturedLogEntries = Capture.newInstance(); 422 | EasyMock.expect( 423 | logging.populateMetadata( 424 | capture(capturedLogEntries), 425 | EasyMock.eq(DEFAULT_RESOURCE), 426 | EasyMock.eq("com.google.cloud.logging"), 427 | EasyMock.eq("jdk"), 428 | EasyMock.eq("sun"), 429 | EasyMock.eq("java"), 430 | EasyMock.eq("ch.qos.logback"))) 431 | .andReturn(ImmutableList.of(INFO_ENTRY)) 432 | .once(); 433 | // it is impossible to define expectation for varargs using a single anyObject() matcher 434 | // see the EasyMock bug https://github.com/easymock/easymock/issues/130. 435 | // the following mock uses the known fact that the method pass two WriteOption arguments 436 | // the arguments should be replaced with a single anyObject() matchers when the bug is fixed 437 | logging.write( 438 | EasyMock.>anyObject(), 439 | anyObject(WriteOption.class), 440 | anyObject(WriteOption.class), 441 | anyObject(WriteOption.class)); 442 | expectLastCall().once(); 443 | replay(logging); 444 | 445 | loggingAppender.setupMonitoredResource(DEFAULT_RESOURCE); 446 | loggingAppender.setAutoPopulateMetadata(true); 447 | loggingAppender.start(); 448 | Timestamp timestamp = Timestamp.ofTimeSecondsAndNanos(100000, 0); 449 | LoggingEvent loggingEvent = createLoggingEvent(Level.INFO, timestamp.getSeconds()); 450 | loggingEvent.setMDCPropertyMap(ImmutableMap.of("mdc1", "value1", "mdc2", "value2")); 451 | loggingAppender.doAppend(loggingEvent); 452 | verify(logging); 453 | LogEntry testLogEntry = capturedLogEntries.getValue().iterator().next(); 454 | assertThat(testLogEntry).isEqualTo(INFO_ENTRY); 455 | } 456 | 457 | @Test 458 | public void testRedirectToStdoutEnabled() { 459 | EasyMock.expect( 460 | logging.populateMetadata( 461 | EasyMock.>anyObject(), 462 | EasyMock.anyObject(MonitoredResource.class), 463 | EasyMock.anyString(), 464 | EasyMock.anyString(), 465 | EasyMock.anyString(), 466 | EasyMock.anyString(), 467 | EasyMock.anyString())) 468 | .andReturn(ImmutableList.of(INFO_ENTRY)) 469 | .once(); 470 | replay(logging); 471 | 472 | ByteArrayOutputStream bout = new ByteArrayOutputStream(); 473 | PrintStream out = new PrintStream(bout); 474 | System.setOut(out); 475 | loggingAppender.setupMonitoredResource(DEFAULT_RESOURCE); 476 | loggingAppender.setAutoPopulateMetadata(true); 477 | loggingAppender.setRedirectToStdout(true); 478 | loggingAppender.start(); 479 | Timestamp timestamp = Timestamp.ofTimeSecondsAndNanos(100000, 0); 480 | LoggingEvent loggingEvent = createLoggingEvent(Level.INFO, timestamp.getSeconds()); 481 | loggingAppender.doAppend(loggingEvent); 482 | verify(logging); 483 | assertThat(Strings.isNullOrEmpty(bout.toString())).isFalse(); 484 | System.setOut(null); 485 | } 486 | 487 | @Test 488 | public void testRedirectToStdoutDisabled() { 489 | ByteArrayOutputStream bout = new ByteArrayOutputStream(); 490 | PrintStream out = new PrintStream(bout); 491 | System.setOut(out); 492 | 493 | testAutoPopulationEnabled(); 494 | 495 | assertThat(Strings.isNullOrEmpty(bout.toString())).isTrue(); 496 | System.setOut(null); 497 | } 498 | 499 | @Test 500 | public void testFDiagnosticInfoAdded() { 501 | LoggingAppender.setInstrumentationStatus(false); 502 | Capture> capturedArgument = Capture.newInstance(); 503 | logging.write( 504 | capture(capturedArgument), 505 | anyObject(WriteOption.class), 506 | anyObject(WriteOption.class), 507 | anyObject(WriteOption.class)); 508 | replay(logging); 509 | LoggingEvent loggingEvent = 510 | createLoggingEvent(Level.ERROR, Timestamp.ofTimeSecondsAndNanos(100000, 0).getSeconds()); 511 | loggingAppender.start(); 512 | loggingAppender.doAppend(loggingEvent); 513 | verify(logging); 514 | int count = 0; 515 | int diagnosticRecordCount = 0; 516 | for (LogEntry entry : capturedArgument.getValue()) { 517 | count++; 518 | if (entry.getPayload().getType() == Type.JSON) { 519 | JsonPayload payload = entry.getPayload(); 520 | if (!payload.getData().containsFields(Instrumentation.DIAGNOSTIC_INFO_KEY)) continue; 521 | ListValue infoList = 522 | payload 523 | .getData() 524 | .getFieldsOrThrow(Instrumentation.DIAGNOSTIC_INFO_KEY) 525 | .getStructValue() 526 | .getFieldsOrThrow(Instrumentation.INSTRUMENTATION_SOURCE_KEY) 527 | .getListValue(); 528 | for (Value val : infoList.getValuesList()) { 529 | String name = 530 | val.getStructValue() 531 | .getFieldsOrThrow(Instrumentation.INSTRUMENTATION_NAME_KEY) 532 | .getStringValue(); 533 | assertThat(name.startsWith(Instrumentation.JAVA_LIBRARY_NAME_PREFIX)).isTrue(); 534 | if (name.equals(LoggingAppender.JAVA_LOGBACK_LIBRARY_NAME)) { 535 | diagnosticRecordCount++; 536 | } 537 | } 538 | } 539 | } 540 | assertEquals(count, 2); 541 | assertEquals(diagnosticRecordCount, 1); 542 | } 543 | 544 | @Test 545 | public void testFDiagnosticInfoNotAdded() { 546 | Capture> capturedArgument = Capture.newInstance(); 547 | logging.write( 548 | capture(capturedArgument), 549 | anyObject(WriteOption.class), 550 | anyObject(WriteOption.class), 551 | anyObject(WriteOption.class)); 552 | replay(logging); 553 | LoggingEvent loggingEvent = 554 | createLoggingEvent(Level.WARN, Timestamp.ofTimeSecondsAndNanos(100000, 0).getSeconds()); 555 | loggingAppender.start(); 556 | loggingAppender.doAppend(loggingEvent); 557 | verify(logging); 558 | int count = 0; 559 | for (LogEntry entry : capturedArgument.getValue()) { 560 | count++; 561 | if (entry.getPayload().getType() == Type.JSON) { 562 | JsonPayload payload = entry.getPayload(); 563 | assertThat(payload.getData().containsFields(Instrumentation.DIAGNOSTIC_INFO_KEY)).isFalse(); 564 | } 565 | } 566 | assertEquals(count, 1); 567 | } 568 | } 569 | -------------------------------------------------------------------------------- /src/test/java/com/google/cloud/logging/logback/MDCEventEnhancerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.logging.logback; 18 | 19 | import static com.google.common.truth.Truth.assertThat; 20 | 21 | import ch.qos.logback.classic.spi.LoggingEvent; 22 | import com.google.cloud.logging.LogEntry; 23 | import com.google.cloud.logging.Payload.StringPayload; 24 | import java.util.Collections; 25 | import org.junit.Before; 26 | import org.junit.Test; 27 | 28 | public class MDCEventEnhancerTest { 29 | private MDCEventEnhancer classUnderTest; 30 | 31 | @Before 32 | public void setUp() { 33 | classUnderTest = new MDCEventEnhancer(); 34 | } 35 | 36 | @Test 37 | public void testEnhanceLogEntry() { 38 | LoggingEvent loggingEvent = new LoggingEvent(); 39 | loggingEvent.setMessage("this is a test"); 40 | loggingEvent.setMDCPropertyMap(Collections.singletonMap("foo", "bar")); 41 | LogEntry.Builder builder = LogEntry.newBuilder(StringPayload.of("this is a test")); 42 | 43 | classUnderTest.enhanceLogEntry(builder, loggingEvent); 44 | LogEntry logEntry = builder.build(); 45 | 46 | assertThat(logEntry.getLabels().get("foo")).isEqualTo("bar"); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/test/java/com/google/cloud/logging/logback/StackTraceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.logging.logback; 18 | 19 | import static com.google.common.truth.Truth.assertThat; 20 | 21 | import ch.qos.logback.classic.spi.ThrowableProxy; 22 | import org.junit.Test; 23 | 24 | public class StackTraceTest { 25 | @Test 26 | public void testStack() { 27 | Exception ex = new UnsupportedOperationException("foo"); 28 | ex = new IllegalStateException("bar", ex); 29 | 30 | StringBuilder stackBuilder = new StringBuilder(); 31 | LoggingAppender.writeStack(new ThrowableProxy(ex), "", stackBuilder); 32 | String stack = stackBuilder.toString(); 33 | 34 | assertThat(stack).contains("java.lang.IllegalStateException: bar"); 35 | assertThat(stack).contains("caused by: java.lang.UnsupportedOperationException: foo"); 36 | assertThat(stack).contains("common frames elided"); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/com/google/cloud/logging/logback/TraceLoggingEventEnhancerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.cloud.logging.logback; 18 | 19 | import static com.google.common.truth.Truth.assertThat; 20 | 21 | import ch.qos.logback.classic.spi.LoggingEvent; 22 | import com.google.cloud.logging.LogEntry; 23 | import com.google.cloud.logging.Payload.StringPayload; 24 | import org.junit.After; 25 | import org.junit.Before; 26 | import org.junit.Test; 27 | 28 | public class TraceLoggingEventEnhancerTest { 29 | private TraceLoggingEventEnhancer classUnderTest; 30 | 31 | @Before 32 | public void setUp() { 33 | classUnderTest = new TraceLoggingEventEnhancer(); 34 | } 35 | 36 | @After 37 | public void tearDown() { 38 | TraceLoggingEventEnhancer.clearTraceId(); 39 | } 40 | 41 | @Test 42 | public void testEnhanceLogEntry() { 43 | // setup 44 | String traceId = "abc"; 45 | TraceLoggingEventEnhancer.setCurrentTraceId(traceId); 46 | LoggingEvent loggingEvent = new LoggingEvent(); 47 | loggingEvent.setMessage("this is a test"); 48 | LogEntry.Builder builder = LogEntry.newBuilder(StringPayload.of("this is a test")); 49 | 50 | // act 51 | classUnderTest.enhanceLogEntry(builder, loggingEvent); 52 | LogEntry logEntry = builder.build(); 53 | 54 | // assert - Trace Id should be recorded as explicit Trace field, not as a label 55 | assertThat(traceId.equalsIgnoreCase(logEntry.getTrace())); 56 | } 57 | 58 | @Test 59 | public void testGetCurrentTraceId() { 60 | // setup 61 | String traceId = "abc"; 62 | TraceLoggingEventEnhancer.setCurrentTraceId(traceId); 63 | 64 | // act 65 | String currentTraceId = TraceLoggingEventEnhancer.getCurrentTraceId(); 66 | 67 | // assert 68 | assertThat(traceId.equalsIgnoreCase(currentTraceId)); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/test/java/com/google/cloud/logging/logback/dummy-credentials.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "service_account", 3 | "project_id": "project-12345", 4 | "private_key_id": "12345", 5 | "private_key": "-----BEGIN PRIVATE KEY-----\nMIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKhPSTDs4cpKfnMc\np86fCkpnuER7bGc+mGkhkw6bE+BnROfrDCFBSjrENLS5JcsenANQ1kYGt9iVW2fd\nZAWUdDoj+t7g6+fDpzY1BzPSUls421Dmu7joDPY8jSdMzFCeg7Lyj0I36bJJ7ooD\nVPW6Q0XQcb8FfBiFPAKuY4elj/YDAgMBAAECgYBo2GMWmCmbM0aL/KjH/KiTawMN\nnfkMY6DbtK9/5LjADHSPKAt5V8ueygSvI7rYSiwToLKqEptJztiO3gnls/GmFzj1\nV/QEvFs6Ux3b0hD2SGpGy1m6NWWoAFlMISRkNiAxo+AMdCi4I1hpk4+bHr9VO2Bv\nV0zKFxmgn1R8qAR+4QJBANqKxJ/qJ5+lyPuDYf5s+gkZWjCLTC7hPxIJQByDLICw\niEnqcn0n9Gslk5ngJIGQcKBXIp5i0jWSdKN/hLxwgHECQQDFKGmo8niLzEJ5sa1r\nspww8Hc2aJM0pBwceshT8ZgVPnpgmITU1ENsKpJ+y1RTjZD6N0aj9gS9UB/UXdTr\nHBezAkEAqkDRTYOtusH9AXQpM3zSjaQijw72Gs9/wx1RxOSsFtVwV6U97CLkV1S+\n2HG1/vn3w/IeFiYGfZXLKFR/pA5BAQJAbFeu6IaGM9yFUzaOZDZ8mnAqMp349t6Q\nDB5045xJxLLWsSpfJE2Y12H1qvO1XUzYNIgXq5ZQOHBFbYA6txBy/QJBAKDRQN47\n6YClq9652X+1lYIY/h8MxKiXpVZVncXRgY6pbj4pmWEAM88jra9Wq6R77ocyECzi\nXCqi18A/sl6ymWc=\n-----END PRIVATE KEY-----\n", 6 | "client_email": "project-12345@appspot.gserviceaccount.com", 7 | "client_id": "123456789012345678901", 8 | "auth_uri": "https://accounts.google.com/o/oauth2/auth", 9 | "token_uri": "https://oauth2.googleapis.com/token", 10 | "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", 11 | "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/project-12345%40appspot.gserviceaccount.com" 12 | } 13 | -------------------------------------------------------------------------------- /src/test/java/com/google/cloud/logging/logback/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | INFO 6 | 7 | 8 | 9 | application.log 10 | 11 | 12 | WARN 13 | 14 | 15 | SYNC 16 | 17 | 18 | false 19 | 20 | 21 | true 22 | 23 | 24 | global 25 | 26 | 27 | src/test/java/com/google/cloud/logging/logback/dummy-credentials.json 28 | 29 | 30 | String 31 | 32 | 33 | 34 | 35 | 37 | true 38 | 39 | 44 | 45 | 100 46 | 1000 47 | 500 48 | 10000 49 | 100000 50 | Ignore 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /versions.txt: -------------------------------------------------------------------------------- 1 | # Format: 2 | # module:released-version:current-version 3 | 4 | google-cloud-logging-logback:0.132.9-alpha:0.132.10-alpha-SNAPSHOT 5 | --------------------------------------------------------------------------------