├── .dockerignore ├── .github ├── dependabot.yml ├── release.yml └── workflows │ └── release.yml ├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── Dockerfile ├── Filter_SecComply.txt ├── Jenkinsfile ├── LICENSE.txt ├── README.md ├── SECURITY.md ├── THIRD_PARTY_LICENSES.txt ├── build-helper-mojo ├── pom.xml ├── pom.xml.versionsBackup └── src │ ├── main │ └── java │ │ └── com │ │ └── oracle │ │ └── wls │ │ └── buildhelper │ │ ├── CopyExecutor.java │ │ ├── CopyExecutorImpl.java │ │ ├── FileCopyMojo.java │ │ ├── GitTagExecutor.java │ │ ├── GitTagExecutorImpl.java │ │ ├── GitTagMojo.java │ │ └── JavaxToJakartaMojo.java │ └── test │ └── java │ └── com │ └── oracle │ └── wls │ └── buildhelper │ ├── FileCopyMojoTest.java │ ├── GitTagMojoTest.java │ ├── InMemoryFileSystem.java │ ├── InMemoryFileSystemTest.java │ ├── JavaxToJakartaMojoTest.java │ └── MojoTestSupport.java ├── config_coordinator ├── COPYRIGHT ├── Dockerfile ├── README.md ├── config_coordinator.go └── config_coordinator_test.go ├── dependency-check-suppression.xml ├── get2.1.sh ├── owaspDependencyCheck.sh ├── pom.xml ├── pom.xml.versionsBackup ├── samples ├── configurations │ ├── healthState.yml │ ├── jvm.yml │ ├── qualified.yml │ ├── query_sync.yml │ ├── servlets.yml │ ├── threadpool.yml │ └── workmanagers.yml └── kubernetes │ ├── deployments │ ├── README.md │ ├── alertmanager-deployment.yaml │ ├── crossnsrbac.yaml │ ├── grafana-deployment.yaml │ ├── monitoring-namespace.yaml │ ├── prometheus-deployment.yaml │ └── prometheus-withalertmanager-deployment.yaml │ └── end2end │ ├── README.md │ ├── dashboard │ ├── exporter-config.yaml │ └── weblogic_dashboard.json │ ├── demo-domains │ ├── domain1.yaml │ └── domainBuilder │ │ ├── Dockerfile │ │ ├── build.sh │ │ ├── scripts │ │ ├── create-domain.sh │ │ ├── domain.properties │ │ └── simple-topology.yaml │ │ └── test-webapp │ │ ├── pom.xml │ │ └── src │ │ └── main │ │ └── webapp │ │ ├── WEB-INF │ │ ├── web.xml │ │ └── weblogic.xml │ │ └── index.jsp │ ├── docs │ ├── 01-pv-path.md │ ├── 02-mysql.md │ ├── 03-wls-operator.md │ ├── 04-wls-domain.md │ ├── 05-prometheus.md │ ├── 06-grafana.md │ ├── 07-webhook.md │ ├── 08-alert.md │ ├── cleanup.md │ ├── dashboard.md │ ├── existing-domain.md │ └── images │ │ ├── active-alert.png │ │ ├── alert-manager-config.png │ │ ├── alert-rule.png │ │ ├── architecture.png │ │ ├── dashboard-datasources.png │ │ ├── dashboard-jms.png │ │ ├── dashboard-overview.png │ │ ├── dashboard-servers.png │ │ ├── dashboard-webapp.png │ │ ├── datasource.png │ │ ├── prometheus-graph.png │ │ ├── prometheus-job.png │ │ ├── prometheus-targets.png │ │ ├── received-alert.png │ │ └── weblogicDashboard.png │ ├── grafana │ ├── dashboard.json │ ├── datasource.json │ ├── persistence.yaml │ └── values.yaml │ ├── mysql │ ├── mysql.yaml │ └── persistence.yaml │ ├── prometheus │ ├── alert-persistence.yaml │ ├── persistence.yaml │ └── values.yaml │ ├── util │ ├── clean-pv.sh │ └── curl.yaml │ └── webhook │ ├── Dockerfile │ ├── scripts │ └── server.py │ └── server.yaml ├── src └── main │ ├── notices │ └── META-INF │ │ ├── COPYRIGHT │ │ └── LICENSE │ └── resources │ └── META-INF │ ├── COPYRIGHT │ └── LICENSE ├── start_exporter.sh ├── wls-exporter-core ├── pom.xml ├── pom.xml.versionsBackup └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── oracle │ │ │ └── wls │ │ │ └── exporter │ │ │ ├── AuthenticatedCall.java │ │ │ ├── AuthenticationChallengeException.java │ │ │ ├── CallFactory.java │ │ │ ├── CallFactoryServletImpl.java │ │ │ ├── ConfigurationCall.java │ │ │ ├── ConfigurationDisplay.java │ │ │ ├── ConfigurationFormCall.java │ │ │ ├── ConfigurationPutCall.java │ │ │ ├── ConfigurationUpdate.java │ │ │ ├── ConfigurationUpdater.java │ │ │ ├── ConfigurationUpdaterImpl.java │ │ │ ├── ErrorLog.java │ │ │ ├── ExporterCall.java │ │ │ ├── ForbiddenException.java │ │ │ ├── Header.java │ │ │ ├── InvocationContext.java │ │ │ ├── JsonEntity.java │ │ │ ├── LiveConfiguration.java │ │ │ ├── MessagesCall.java │ │ │ ├── MetricsStream.java │ │ │ ├── MultipartContentParser.java │ │ │ ├── MultipartItem.java │ │ │ ├── ParserActions.java │ │ │ ├── ParserState.java │ │ │ ├── RestPortConnectionException.java │ │ │ ├── RestQueryException.java │ │ │ ├── ServerErrorException.java │ │ │ ├── SystemClock.java │ │ │ ├── UrlBuilder.java │ │ │ ├── WebAppConstants.java │ │ │ ├── WebClient.java │ │ │ ├── WebClient8Impl.java │ │ │ ├── WebClientCommon.java │ │ │ ├── WebClientException.java │ │ │ ├── WebClientFactory.java │ │ │ ├── WebClientFactoryImpl.java │ │ │ ├── WebClientImpl.java │ │ │ ├── WlsRestExchanges.java │ │ │ ├── domain │ │ │ ├── ConfigurationException.java │ │ │ ├── ExporterConfig.java │ │ │ ├── JsonQuerySpec.java │ │ │ ├── MBeanSelector.java │ │ │ ├── MapUtils.java │ │ │ ├── MetricsProcessor.java │ │ │ ├── MetricsScraper.java │ │ │ ├── Protocol.java │ │ │ ├── QuerySyncConfiguration.java │ │ │ ├── QueryType.java │ │ │ ├── SnakeCaseUtil.java │ │ │ └── YamlParserException.java │ │ │ └── javax │ │ │ ├── ConfigurationServlet.java │ │ │ ├── ExporterServlet.java │ │ │ ├── LogServlet.java │ │ │ ├── MainServlet.java │ │ │ ├── MessagesServlet.java │ │ │ ├── ServletInvocationContext.java │ │ │ └── ServletUtils.java │ └── java11 │ │ └── com │ │ └── oracle │ │ └── wls │ │ └── exporter │ │ └── WebClient11Impl.java │ └── test │ ├── java │ └── com │ │ └── oracle │ │ └── wls │ │ └── exporter │ │ ├── AuthenticatedCallTest.java │ │ ├── ClockStub.java │ │ ├── ConfigurationFormCallTest.java │ │ ├── ConfigurationPutCallTest.java │ │ ├── ConfigurationUpdaterImplTest.java │ │ ├── ConfigurationUpdaterStub.java │ │ ├── DemoInputs.java │ │ ├── ErrorLogTest.java │ │ ├── ExporterCallTest.java │ │ ├── ExporterServletTest.java │ │ ├── HeaderTest.java │ │ ├── InMemoryResources.java │ │ ├── InvocationContextStub.java │ │ ├── ItemHolder.java │ │ ├── LiveConfigurationTest.java │ │ ├── MetricsStreamTest.java │ │ ├── MultipartContentParserTest.java │ │ ├── MultipartTestUtils.java │ │ ├── ResponseDemo.java │ │ ├── SystemClockTestSupport.java │ │ ├── UrlBuilderTest.java │ │ ├── WebClient8ImplTest.java │ │ ├── WebClientFactoryImplTest.java │ │ ├── WebClientFactoryStub.java │ │ ├── WebClientImplTest.java │ │ ├── WebClientTestBase.java │ │ ├── WlsRestExchangesTest.java │ │ ├── YamlDemo.java │ │ ├── domain │ │ ├── ConfigurationExceptionTest.java │ │ ├── ExporterConfigTest.java │ │ ├── MBeanSelectorTest.java │ │ ├── MapUtilsTest.java │ │ ├── MetricMatcher.java │ │ ├── MetricsScraperTest.java │ │ ├── QueryTypeTest.java │ │ └── SnakeCaseUtilTest.java │ │ ├── javax │ │ ├── ConfigurationServletTest.java │ │ ├── HttpServletRequestStub.java │ │ ├── HttpServletResponseStub.java │ │ ├── LogServletTest.java │ │ ├── MainServletTest.java │ │ ├── MessagesServletTest.java │ │ └── ServletInvocationContextTest.java │ │ └── matchers │ │ ├── CommentsOnlyMatcher.java │ │ ├── MetricsNamesSnakeCaseMatcher.java │ │ ├── MetricsUtils.java │ │ ├── PrometheusMetricsMatcher.java │ │ ├── PrometheusMetricsMatcherTest.java │ │ └── ResponseHeaderMatcher.java │ └── java11 │ └── com │ └── oracle │ └── wls │ └── exporter │ └── WebClient11ImplTest.java ├── wls-exporter-sidecar ├── pom.xml ├── pom.xml.versionsBackup └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── oracle │ │ │ └── wls │ │ │ └── exporter │ │ │ └── sidecar │ │ │ ├── HelidonInvocationContext.java │ │ │ ├── Main.java │ │ │ ├── MetricsService.java │ │ │ └── SidecarConfiguration.java │ └── resources │ │ └── logging.properties │ └── test │ ├── java │ └── com │ │ └── oracle │ │ └── wls │ │ └── exporter │ │ └── sidecar │ │ ├── HelidonInvocationContextTest.java │ │ ├── ItemHolder.java │ │ ├── MetricsServiceTest.java │ │ ├── SidecarConfigurationTest.java │ │ ├── SidecarConfigurationTestSupport.java │ │ └── WebClientFactoryStub.java │ └── resources │ └── exporter-version.properties └── wls-exporter-war ├── pom.xml ├── pom.xml.versionsBackup └── src └── main ├── resources └── get.sh └── webapp └── WEB-INF └── weblogic.xml /.dockerignore: -------------------------------------------------------------------------------- 1 | target/* -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "maven" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "daily" 12 | - package-ecosystem: "github-actions" 13 | directory: "/" 14 | schedule: 15 | interval: "daily" 16 | -------------------------------------------------------------------------------- /.github/release.yml: -------------------------------------------------------------------------------- 1 | # .github/release.yml 2 | # Template for release notes (used by .github/workflows/release.yml) 3 | 4 | changelog: 5 | exclude: 6 | labels: 7 | - ignore-for-release 8 | - dependencies 9 | authors: 10 | - dependabot 11 | categories: 12 | - title: Major Changes 13 | labels: 14 | - breaking-change 15 | - title: Additional Features 16 | labels: 17 | - enhancement 18 | - title: Bug Fixes 19 | labels: 20 | - "*" 21 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | push: 4 | tags: 5 | - v* 6 | 7 | env: 8 | REGISTRY: ghcr.io 9 | BASE_IMAGE_NAME: ghcr.io/oracle/weblogic-monitoring-exporter 10 | 11 | jobs: 12 | build: 13 | name: Build 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: "Set environmental variables" 17 | run: | 18 | VERSION=${GITHUB_REF_NAME#v} 19 | echo "VERSION=$VERSION" >> $GITHUB_ENV 20 | echo "IMAGE_NAME=${{ env.REGISTRY }}/${{ env.BASE_IMAGE_NAME }}:$VERSION" >> $GITHUB_ENV 21 | - uses: actions/checkout@v4 22 | with: 23 | fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis 24 | - name: Set up JDK 25 | uses: actions/setup-java@v4 26 | with: 27 | distribution: 'oracle' 28 | java-version: 21 29 | - name: Cache Maven packages 30 | uses: actions/cache@v4 31 | with: 32 | path: ~/.m2 33 | key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} 34 | restore-keys: ${{ runner.os }}-m2 35 | - name: Build 36 | env: 37 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any 38 | run: mvn clean package -Dtag=${{ env.VERSION }} 39 | 40 | - name: Create Draft Release 41 | id: draft-release 42 | run: | 43 | echo 'PR_URL<> $GITHUB_ENV 44 | gh release create ${{ github.ref_name }} \ 45 | --draft \ 46 | --generate-notes \ 47 | --title 'WebLogic Monitoring Exporter ${{ env.VERSION }}' \ 48 | --repo https://github.com/oracle/weblogic-monitoring-exporter \ 49 | wls-exporter-war/target/wls-exporter.war wls-exporter-war/target/classes/get_v${{ env.VERSION }}.sh 50 | echo 'EOF' >> $GITHUB_ENV 51 | env: 52 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 53 | 54 | - name: Set up QEMU 55 | uses: docker/setup-qemu-action@v3 56 | 57 | - name: Set up Buildx 58 | uses: docker/setup-buildx-action@v3 59 | 60 | - name: Log in to the Container registry 61 | uses: docker/login-action@v3 62 | with: 63 | registry: ${{ env.REGISTRY }} 64 | username: ${{ github.actor }} 65 | password: ${{ secrets.PUBLISH_SECRET }} 66 | 67 | - name: Build and push container image 68 | uses: docker/build-push-action@v6 69 | with: 70 | context: . 71 | platforms: linux/amd64,linux/arm64 72 | push: true 73 | provenance: false 74 | tags: ${{ env.IMAGE_NAME }} 75 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | build/** 3 | .gradle/** 4 | **/target/** 5 | .idea/** 6 | *.iml 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - openjdk8 4 | - openjdk8 5 | - oraclejdk11 6 | sudo: false 7 | script: mvn clean verify 8 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to this repository 2 | 3 | We welcome your contributions! There are multiple ways to contribute. 4 | 5 | ## Opening issues 6 | 7 | For bugs or enhancement requests, please file a GitHub issue unless it's 8 | security related. When filing a bug remember that the better written the bug is, 9 | the more likely it is to be fixed. If you think you've found a security 10 | vulnerability, do not raise a GitHub issue and follow the instructions in our 11 | [security policy](./SECURITY.md). 12 | 13 | ## Contributing code 14 | 15 | We welcome your code contributions. Before submitting code via a pull request, 16 | you will need to have signed the [Oracle Contributor Agreement][OCA] (OCA) and 17 | your commits need to include the following line using the name and e-mail 18 | address you used to sign the OCA: 19 | 20 | ```text 21 | Signed-off-by: Your Name 22 | ``` 23 | 24 | This can be automatically added to pull requests by committing with `--sign-off` 25 | or `-s`, e.g. 26 | 27 | ```text 28 | git commit --signoff 29 | ``` 30 | 31 | Only pull requests from committers that can be verified as having signed the OCA 32 | can be accepted. 33 | 34 | ## Pull request process 35 | 36 | 1. Ensure there is an issue created to track and discuss the fix or enhancement 37 | you intend to submit. 38 | 1. Fork this repository 39 | 1. Create a branch in your fork to implement the changes. We recommend using 40 | the issue number as part of your branch name, e.g. `1234-fixes` 41 | 1. Ensure that any documentation is updated with the changes that are required 42 | by your change. 43 | 1. Ensure that any samples are updated if the base image has been changed. 44 | 1. Submit the pull request. *Do not leave the pull request blank*. Explain exactly 45 | what your changes are meant to do and provide simple steps on how to validate 46 | your changes. Ensure that you reference the issue you created as well. 47 | 1. We will assign the pull request to 2-3 people for review before it is merged. 48 | 49 | ## Code of conduct 50 | 51 | Follow the [Golden Rule](https://en.wikipedia.org/wiki/Golden_Rule). If you'd 52 | like more specific guidelines, see the [Contributor Covenant Code of Conduct][COC]. 53 | 54 | [OCA]: https://oca.opensource.oracle.com 55 | [COC]: https://www.contributor-covenant.org/version/1/4/code-of-conduct/ 56 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021, 2023, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | FROM ghcr.io/oracle/oraclelinux:9-slim AS jre-build 5 | 6 | ENV JAVA_URL_X64="https://download.oracle.com/java/21/latest/jdk-21_linux-x64_bin.tar.gz" 7 | ENV JAVA_URL_AARCH64="https://download.oracle.com/java/21/latest/jdk-21_linux-aarch64_bin.tar.gz" 8 | 9 | RUN set -eux; \ 10 | microdnf -y install gzip tar; \ 11 | MACHINE_TYPE=`uname -m`; \ 12 | if [ ${MACHINE_TYPE} == 'x86_64' ]; then \ 13 | JAVA_URL=$JAVA_URL_X64; \ 14 | else \ 15 | JAVA_URL=$JAVA_URL_AARCH64; \ 16 | fi; \ 17 | curl -fL -o jdk.tar.gz "$JAVA_URL"; \ 18 | mkdir -p /jdk; \ 19 | tar --extract --file jdk.tar.gz --directory /jdk --strip-components 1; \ 20 | /jdk/bin/jlink --verbose --compress 2 --strip-java-debug-attributes --no-header-files --no-man-pages --output jre --add-modules java.base,java.logging,java.desktop,java.instrument,java.management,java.naming,java.net.http,java.security.jgss,java.sql,jdk.attach,jdk.jdi,jdk.jfr,jdk.management,jdk.management.agent,jdk.management.jfr,jdk.net,jdk.unsupported,jdk.crypto.cryptoki,jdk.crypto.ec,jdk.zipfs,jdk.jcmd 21 | 22 | FROM ghcr.io/oracle/oraclelinux:9-slim 23 | 24 | LABEL "org.opencontainers.image.authors"="Ryan Eberhard , Russell Gold " \ 25 | "org.opencontainers.image.url"="https://github.com/oracle/weblogic-monitoring-exporter" \ 26 | "org.opencontainers.image.source"="https://github.com/oracle/weblogic-monitoring-exporter" \ 27 | "org.opencontainers.image.vendor"="Oracle Corporation" \ 28 | "org.opencontainers.image.title"="Oracle WebLogic Monitoring Exporter" \ 29 | "org.opencontainers.image.description"="Oracle WebLogic Monitoring Exporter" \ 30 | "org.opencontainers.image.documentation"="https://github.com/oracle/weblogic-monitoring-exporter" 31 | 32 | ENV LANG="en_US.UTF-8" 33 | 34 | COPY --from=jre-build /jre jre 35 | 36 | # Install Java and make the operator run with a non-root user id (1000 is the `oracle` user) 37 | RUN set -eux; \ 38 | microdnf -y update; \ 39 | microdnf clean all; \ 40 | for bin in /jre/bin/*; do \ 41 | base="$(basename "$bin")"; \ 42 | [ ! -e "/usr/bin/$base" ]; \ 43 | alternatives --install "/usr/bin/$base" "$base" "$bin" 20000; \ 44 | done; \ 45 | java -Xshare:dump; \ 46 | useradd -M -s /bin/bash -g root -u 1000 oracle 47 | 48 | USER oracle 49 | 50 | COPY --chown=oracle:root wls-exporter-sidecar/target/wls-exporter-sidecar.jar ./ 51 | COPY --chown=oracle:root wls-exporter-sidecar/target/libs ./libs 52 | COPY --chown=oracle:root start_exporter.sh . 53 | 54 | ENTRYPOINT ["sh", "start_exporter.sh"] 55 | 56 | EXPOSE 8080 57 | -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | // 4 | pipeline { 5 | agent any 6 | 7 | tools { 8 | maven 'maven-3.8.7' 9 | jdk 'jdk21' 10 | } 11 | 12 | stages { 13 | stage ('Build') { 14 | steps { 15 | withMaven(globalMavenSettingsConfig: 'wkt-maven-settings-xml', publisherStrategy: 'EXPLICIT') { 16 | sh "mvn -DtrimStackTrace=false clean install" 17 | } 18 | } 19 | } 20 | stage ('Sync') { 21 | when { 22 | branch 'main' 23 | anyOf { 24 | not { triggeredBy 'TimerTrigger' } 25 | tag 'v*' 26 | } 27 | } 28 | steps { 29 | build job: "wkt-sync", parameters: [ string(name: 'REPOSITORY', value: 'weblogic-monitoring-exporter') ] 30 | } 31 | } 32 | } 33 | post { 34 | failure { 35 | slackSend channel: '#wkt-build-failure-notifications', 36 | botUser: false, color: 'danger', 37 | message: "Build <${env.BUILD_URL}|${env.JOB_NAME}:${env.BUILD_NUMBER}> failed" 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021 Oracle and/or its affiliates. 2 | 3 | The Universal Permissive License (UPL), Version 1.0 4 | 5 | Subject to the condition set forth below, permission is hereby granted to any 6 | person obtaining a copy of this software, associated documentation and/or data 7 | (collectively the "Software"), free of charge and under any and all copyright 8 | rights in the Software, and any and all patent rights owned or freely 9 | licensable by each licensor hereunder covering either (i) the unmodified 10 | Software as contributed to or provided by such licensor, or (ii) the Larger 11 | Works (as defined below), to deal in both 12 | 13 | (a) the Software, and 14 | (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if 15 | one is included with the Software (each a "Larger Work" to which the Software 16 | is contributed by such licensors), 17 | 18 | without restriction, including without limitation the rights to copy, create 19 | derivative works of, display, perform, and distribute the Software and make, 20 | use, sell, offer for sale, import, export, have made, and have sold the 21 | Software and the Larger Work(s), and to sublicense the foregoing rights on 22 | either these or other terms. 23 | 24 | This license is subject to the following condition: 25 | The above copyright notice and either this complete permission notice or at 26 | a minimum a reference to the UPL must be included in all copies or 27 | substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 35 | SOFTWARE. 36 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Reporting security vulnerabilities 2 | 3 | Oracle values the independent security research community and believes that 4 | responsible disclosure of security vulnerabilities helps us ensure the security 5 | and privacy of all our users. 6 | 7 | Please do NOT raise a GitHub Issue to report a security vulnerability. If you 8 | believe you have found a security vulnerability, please submit a report to 9 | [secalert_us@oracle.com][1] preferably with a proof of concept. Please review 10 | some additional information on [how to report security vulnerabilities to Oracle][2]. 11 | We encourage people who contact Oracle Security to use email encryption using 12 | [our encryption key][3]. 13 | 14 | We ask that you do not use other channels or contact the project maintainers 15 | directly. 16 | 17 | Non-vulnerability related security issues including ideas for new or improved 18 | security features are welcome on GitHub Issues. 19 | 20 | ## Security updates, alerts and bulletins 21 | 22 | Security updates will be released on a regular cadence. Many of our projects 23 | will typically release security fixes in conjunction with the 24 | Oracle Critical Patch Update program. Additional 25 | information, including past advisories, is available on our [security alerts][4] 26 | page. 27 | 28 | ## Security-related information 29 | 30 | We will provide security related information such as a threat model, considerations 31 | for secure use, or any known security issues in our documentation. Please note 32 | that labs and sample code are intended to demonstrate a concept and may not be 33 | sufficiently hardened for production use. 34 | 35 | [1]: mailto:secalert_us@oracle.com 36 | [2]: https://www.oracle.com/corporate/security-practices/assurance/vulnerability/reporting.html 37 | [3]: https://www.oracle.com/security-alerts/encryptionkey.html 38 | [4]: https://www.oracle.com/security-alerts/ 39 | -------------------------------------------------------------------------------- /build-helper-mojo/src/main/java/com/oracle/wls/buildhelper/CopyExecutor.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, 2022, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.buildhelper; 5 | 6 | import java.io.File; 7 | import java.nio.file.Path; 8 | 9 | public interface CopyExecutor { 10 | 11 | Path toPath(File file); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /build-helper-mojo/src/main/java/com/oracle/wls/buildhelper/CopyExecutorImpl.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.buildhelper; 5 | 6 | import java.io.File; 7 | import java.nio.file.Path; 8 | 9 | public class CopyExecutorImpl implements CopyExecutor { 10 | 11 | @Override 12 | public Path toPath(File file) { 13 | return file.toPath(); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /build-helper-mojo/src/main/java/com/oracle/wls/buildhelper/FileCopyMojo.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, 2022, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.buildhelper; 5 | 6 | import org.apache.maven.plugin.AbstractMojo; 7 | import org.apache.maven.plugin.MojoExecutionException; 8 | import org.apache.maven.plugins.annotations.LifecyclePhase; 9 | import org.apache.maven.plugins.annotations.Mojo; 10 | import org.apache.maven.plugins.annotations.Parameter; 11 | 12 | import java.io.File; 13 | import java.io.IOException; 14 | import java.nio.file.Files; 15 | import java.nio.file.Path; 16 | import java.util.Optional; 17 | 18 | import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; 19 | 20 | @Mojo(name = "copy", defaultPhase = LifecyclePhase.PROCESS_RESOURCES) 21 | public class FileCopyMojo extends AbstractMojo { 22 | @Parameter(required = true) private String sourceFile; 23 | @Parameter(required = true) private File targetFile; 24 | @Parameter private File userDir; 25 | 26 | @SuppressWarnings("FieldMayBeFinal") // leave non-final for unit test 27 | private static CopyExecutor executor = new CopyExecutorImpl(); 28 | 29 | public void execute() throws MojoExecutionException { 30 | Path source = toPath(sourceFile); 31 | Path target = toPath(targetFile); 32 | try { 33 | getLog().info("Copying " + source + " to " + target); 34 | Files.createDirectories(target.getParent()); 35 | Files.copy(source, target, REPLACE_EXISTING); 36 | } catch (IOException e) { 37 | throw new MojoExecutionException("Unable to copy " + source + " to " + target, e); 38 | } 39 | } 40 | 41 | private Path toPath(String filePath) { 42 | return executor.toPath(getEffectiveFile(new File(filePath))); 43 | } 44 | 45 | private Path toPath(File file) { 46 | return executor.toPath(getEffectiveFile(file)); 47 | } 48 | 49 | private File getEffectiveFile(File file) { 50 | return file.isAbsolute() ? file : new File (getUserDir(), file.getPath()); 51 | } 52 | 53 | private File getUserDir() { 54 | return Optional.ofNullable(userDir).orElse(new File(System.getProperty("user.dir"))); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /build-helper-mojo/src/main/java/com/oracle/wls/buildhelper/GitTagExecutor.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.buildhelper; 5 | 6 | import org.apache.maven.plugin.MojoExecutionException; 7 | 8 | import java.io.File; 9 | import java.io.IOException; 10 | import java.nio.file.Path; 11 | 12 | /** 13 | * An interface for the system interaction functionality required to execute the GitTag mojo. 14 | */ 15 | interface GitTagExecutor { 16 | 17 | /** 18 | * Issues a command and returns the response. 19 | * @param commandLine the command to execute 20 | */ 21 | String runCommand(String... commandLine) throws IOException, MojoExecutionException; 22 | 23 | Path toPath(File file); 24 | } 25 | -------------------------------------------------------------------------------- /build-helper-mojo/src/main/java/com/oracle/wls/buildhelper/GitTagExecutorImpl.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.buildhelper; 5 | 6 | import org.apache.maven.plugin.MojoExecutionException; 7 | 8 | import java.io.BufferedReader; 9 | import java.io.File; 10 | import java.io.IOException; 11 | import java.io.InputStreamReader; 12 | import java.nio.file.Path; 13 | import java.util.stream.Collectors; 14 | 15 | public class GitTagExecutorImpl implements GitTagExecutor { 16 | @Override 17 | public String runCommand(String... commandLineStrings) throws IOException, MojoExecutionException { 18 | try { 19 | final Process vp = new ProcessBuilder(commandLineStrings).start(); 20 | 21 | vp.waitFor(); 22 | 23 | final BufferedReader br = new BufferedReader(new InputStreamReader(vp.getInputStream())); 24 | return br.lines().collect(Collectors.joining("\n")); 25 | } catch (InterruptedException e) { 26 | Thread.currentThread().interrupt(); 27 | throw new MojoExecutionException("Thread interrupted while running command " + String.join(" ", commandLineStrings)); 28 | } 29 | } 30 | 31 | @Override 32 | public Path toPath(File file) { 33 | return file.toPath(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /build-helper-mojo/src/main/java/com/oracle/wls/buildhelper/GitTagMojo.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, 2023, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.buildhelper; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | import java.nio.file.Files; 9 | import java.nio.file.Path; 10 | import java.util.Arrays; 11 | import java.util.Collections; 12 | import java.util.List; 13 | 14 | import org.apache.maven.plugin.AbstractMojo; 15 | import org.apache.maven.plugin.MojoExecutionException; 16 | import org.apache.maven.plugins.annotations.LifecyclePhase; 17 | import org.apache.maven.plugins.annotations.Mojo; 18 | import org.apache.maven.plugins.annotations.Parameter; 19 | 20 | @Mojo(name = "gitVersion", defaultPhase = LifecyclePhase.PREPARE_PACKAGE) 21 | public class GitTagMojo extends AbstractMojo { 22 | 23 | @Parameter(required = true, defaultValue = "${project.build.outputDirectory}/exporter-version.properties") 24 | private File outputFile; 25 | 26 | private final GitTagExecutor executor; 27 | 28 | GitTagMojo(GitTagExecutor executor) { 29 | this.executor = executor; 30 | } 31 | 32 | @SuppressWarnings("unused") 33 | public GitTagMojo() { 34 | this(new GitTagExecutorImpl()); 35 | } 36 | 37 | @Override 38 | public void execute() throws MojoExecutionException { 39 | try { 40 | final String versionString = toVersionString(executor.runCommand("git", "describe", "--tag")); 41 | final Path path = executor.toPath(outputFile); 42 | Files.createDirectories(path.getParent()); 43 | Files.write(path, createProperties(versionString)); 44 | } catch (IOException e) { 45 | throw new MojoExecutionException("Error writing " + outputFile + ": " + e ); 46 | } 47 | 48 | } 49 | 50 | private List createProperties(String versionString) { 51 | return Collections.singletonList("monitoring-exporter-version=" + versionString); 52 | } 53 | 54 | // parses the result of 'git describe --tag' to describe the current code version/ 55 | private String toVersionString(String gitResponse) { 56 | final String[] segments = gitResponse.split("-"); 57 | if (segments.length == 1 || segments.length == 2) 58 | return gitResponse; 59 | else 60 | return formatVersionString(segments); 61 | } 62 | 63 | private String formatVersionString(String[] segments) { 64 | final String commit = segments[segments.length - 1].substring(1); 65 | final String numCommits = segments[segments.length - 2]; 66 | final String versionParts = String.join("-", Arrays.copyOfRange(segments, 0, segments.length - 2)); 67 | return formatVersionString(commit, numCommits, versionParts); 68 | } 69 | 70 | private String formatVersionString(String commit, String numCommits, String versionParts) { 71 | return commit + " (" + numCommits + " commits since " + versionParts + ")"; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /config_coordinator/COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017, 2020, Oracle and/or its affiliates. 2 | Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /config_coordinator/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2019, 2022, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | # Start from a Debian image with the desired version of Go installed 5 | # and a workspace (GOPATH) configured at /go. 6 | FROM golang:1.18.1 7 | 8 | # Copy the local files to the container's workspace. 9 | COPY . /go/src/github.com/oracle/config_coordinator 10 | 11 | # Build the config_coordinator command inside the container. 12 | RUN go install /go/src/github.com/oracle/config_coordinator/config_coordinator.go 13 | 14 | # Run the config_coordinator by default when the container starts. 15 | ENTRYPOINT ["/go/bin/config_coordinator"] 16 | 17 | # Document that the service listens on port 8999. 18 | EXPOSE 8999 19 | -------------------------------------------------------------------------------- /config_coordinator/README.md: -------------------------------------------------------------------------------- 1 | WebLogic Monitoring Exporter Coordinator 2 | ===== 3 | 4 | Each instance in a WLS cluster maintains the configuration locally for its 5 | WebLogic Monitoring Exporter. The coordinator allows them to share 6 | changes to the query configurations. 7 | 8 | The coordinator is a simple web server, listening on port 8999, which accepts two requests: 9 | - A GET request returns the latest configuration update 10 | - A PUT request provides a new configuration update 11 | 12 | The following is an example configuration update: 13 | ``` 14 | { 15 | "timestamp": 14567894, 16 | "configuration": 17 | "queries: 18 | - JVMRuntime: 19 | key: name 20 | prefix: jvm_ 21 | values: [heapFreeCurrent, heapFreePercent, heapSizeCurrent, heapSizeMax, uptime, processCpuLoad]" 22 | } 23 | ``` 24 | An update is a JSON object with two fields: 25 | 26 | | Name | Description | 27 | | --- | --- | 28 | | timestamp | A long value, representing milliseconds since the epoch. | 29 | | configuration | A string representing the new YAML configuration. | 30 | 31 | ## Building 32 | 33 | This server is run in a Docker container, which is built using: 34 | 35 | `docker build -t config_coordinator .` 36 | 37 | from the config_coordinator directory, and may be run with: 38 | 39 | `docker run --publish 8999:8999 --name coordinator --rm config_coordinator` 40 | 41 | The `query_sync` section of the exporter configuration should point to this server 42 | 43 | ## Persistence 44 | 45 | Passing the option `-db ` will cause the coordinator to use the designated file path to persist changes 46 | to the configuration. This will preserve changes across container restarts. When running in a container, the file 47 | must be in a mounted volume. 48 | 49 | For example: 50 | 51 | ``` 52 | docker run --publish 8999:8999 --name coordinator --rm -v /my/storage:/var/lib/coordinator \ 53 | config_coordinator -db /var/lib/coordinator/configs.json 54 | ``` 55 | 56 | This will cause Docker to mount the host machine directory `/my/storage` at the path `/var/lib/coordinator` 57 | in the container, and to use a file named `configs.json` in that directory to persist its state. 58 | 59 | ## Copyright 60 | 61 | Copyright (c) 2017, 2020, Oracle and/or its affiliates. 62 | Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 63 | -------------------------------------------------------------------------------- /dependency-check-suppression.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | ^pkg:maven/org\.apache\.maven/maven-artifact-manager@.*$ 8 | CVE-2021-26291 9 | 10 | 11 | 14 | ^pkg:maven/org\.codehaus\.plexus/plexus-utils@.*$ 15 | CVE-2017-1000487 16 | 17 | 18 | 21 | CVE-2023-4586 22 | 23 | 24 | 27 | CVE-2022-4244 28 | 29 | 30 | 33 | CVE-2022-4245 34 | 35 | -------------------------------------------------------------------------------- /get2.1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) 2021, 2022, Oracle and/or its affiliates. 3 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 4 | 5 | curl -L -O https://github.com/oracle/weblogic-monitoring-exporter/releases/download/v${version}/wls-exporter.war 6 | 7 | if [ ! -z "$1" ]; then 8 | tmp_dir=$(mktemp -d -t ci-XXXXXXXXXX) 9 | echo "created $tmp_dir" 10 | cp $1 $tmp_dir/config.yml 11 | warDir=$PWD 12 | pushd $tmp_dir 13 | echo "in temp dir" 14 | zip $warDir/wls-exporter.war config.yml 15 | popd 16 | # rm -rf $tmp_dir 17 | fi 18 | -------------------------------------------------------------------------------- /owaspDependencyCheck.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) 2020, 2021, Oracle and/or its affiliates. 3 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 4 | 5 | # Generate report of known issues in dependencies 6 | 7 | set -e 8 | 9 | mvn ${MAVEN_ARGS} -Dorg.slf4j.simpleLogger.defaultLogLevel=WARN org.owasp:dependency-check-maven:aggregate 10 | -------------------------------------------------------------------------------- /samples/configurations/healthState.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2020, 2024, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | --- 5 | metricsNameSnakeCase: true 6 | queries: 7 | - key: name 8 | prefix: wls_server_ 9 | stringValues: 10 | state: [SHUTDOWN,STARTING,RUNNING,STANDBY,FORCE_SUSPENDING,RESUMING,SHUTTING_DOWN,FAILED,UNKNOWN,FAILED_NOT_RESTARTABLE,ADMIN,FORCE_SHUTTING_DOWN] 11 | overallHealthState: 12 | prefix: wls_server_overallhealth_ 13 | stringValues: 14 | state: [ok,failed,overloaded,critical,warn] 15 | healthState: 16 | prefix: wls_server_health_ 17 | stringValues: 18 | state: [ok,failed,overloaded,critical,warn] 19 | - JTARuntime: 20 | prefix: wls_jta_ 21 | key: name 22 | healthState: 23 | prefix: wls_jta_health_ 24 | stringValues: 25 | state: [ok,failed,overloaded,critical,warn] 26 | -------------------------------------------------------------------------------- /samples/configurations/jvm.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2019, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | metricsNameSnakeCase: true 5 | queries: 6 | - key: name 7 | keyName: server 8 | JVMRuntime: 9 | prefix: jvm_ 10 | key: name 11 | values: [heapFreeCurrent, heapFreePercent, heapSizeCurrent] 12 | -------------------------------------------------------------------------------- /samples/configurations/qualified.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2019, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | metricsNameSnakeCase: true 5 | domainQualifier: true 6 | queries: 7 | - key: name 8 | keyName: server 9 | applicationRuntimes: 10 | key: name 11 | workManagerRuntimes: 12 | prefix: workmanager_ 13 | key: applicationName 14 | -------------------------------------------------------------------------------- /samples/configurations/query_sync.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2019, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | query_sync: 5 | url: http://coordinator:8999/ 6 | metricsNameSnakeCase: true 7 | queries: 8 | - applicationRuntimes: 9 | key: name 10 | keyName: app 11 | componentRuntimes: 12 | type: WebAppComponentRuntime 13 | prefix: webapp_config_ 14 | key: name 15 | values: [openSessionsCurrentCount, openSessionsHighCount] 16 | servlets: 17 | prefix: weblogic_servlet_ 18 | key: servletName 19 | -------------------------------------------------------------------------------- /samples/configurations/servlets.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2019, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | --- 5 | metricsNameSnakeCase: true 6 | queries: 7 | - key: name 8 | keyName: server 9 | applicationRuntimes: 10 | key: name 11 | keyName: app 12 | componentRuntimes: 13 | type: WebAppComponentRuntime 14 | prefix: webapp_config_ 15 | key: name 16 | values: [deploymentState, servletReloadCheckSecs, openSessionsHighCount, openSessionsCurrentCount] 17 | servlets: 18 | prefix: weblogic_servlet_ 19 | key: servletName 20 | -------------------------------------------------------------------------------- /samples/configurations/threadpool.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2019, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | metricsNameSnakeCase: true 5 | queries: 6 | - key: name 7 | keyName: server 8 | threadPoolRuntime: 9 | key: name 10 | keyName: app 11 | values: throughput 12 | -------------------------------------------------------------------------------- /samples/configurations/workmanagers.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2019, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | metricsNameSnakeCase: true 5 | queries: 6 | - applicationRuntimes: 7 | key: name 8 | workManagerRuntimes: 9 | prefix: workmanager_ 10 | key: applicationName 11 | -------------------------------------------------------------------------------- /samples/kubernetes/deployments/README.md: -------------------------------------------------------------------------------- 1 | Monitoring with Prometheus and Grafana using the WebLogic Monitoring Exporter 2 | ===== 3 | 4 | Here are some examples of deployments to start Prometheus and Grafana in the Kubernetes cluster, and an example of the RBAC policy to set up all the required permissions to access pods. 5 | 6 | All the examples are configured to be deployed in the `monitoring` namespace. The WebLogic Server Kubernetes Operator is deployed in the `weblogic-operator` namespace and the WebLogic domain runs in the `weblogic-domain` namespace. 7 | 8 | You can customize the examples to reflect a specific configuration. 9 | 10 | For more details on how to set up and run Prometheus and Grafana with the WebLogic Monitoring Exporter, see the blog, [Using Prometheus and Grafana to Monitor WebLogic Server on Kubernetes](https://blogs.oracle.com/weblogicserver/use-prometheus-and-grafana-to-monitor-weblogic-server-on-kubernetes). 11 | 12 | 13 | ## Copyright 14 | 15 | Copyright (c) 2017, 2019, Oracle and/or its affiliates. 16 | -------------------------------------------------------------------------------- /samples/kubernetes/deployments/alertmanager-deployment.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2019, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | apiVersion: apps/v1beta1 5 | kind: Deployment 6 | metadata: 7 | labels: 8 | name: alertmanager 9 | name: alertmanager 10 | namespace: monitoring 11 | spec: 12 | replicas: 1 13 | selector: 14 | matchLabels: 15 | name: alertmanager 16 | template: 17 | metadata: 18 | creationTimestamp: null 19 | labels: 20 | name: alertmanager 21 | spec: 22 | hostname: alertmanager 23 | containers: 24 | - image: prom/alertmanager:v0.14.0 25 | imagePullPolicy: IfNotPresent 26 | name: alertmanager 27 | ports: 28 | - name: alertmanager 29 | containerPort: 9093 30 | protocol: TCP 31 | resources: 32 | limits: 33 | cpu: 500m 34 | memory: 2500Mi 35 | requests: 36 | cpu: 100m 37 | memory: 100Mi 38 | volumeMounts: 39 | # - mountPath: /var/lib/alertmanager 40 | # name: data 41 | - mountPath: /etc/alertmanager/ 42 | name: config-volume 43 | restartPolicy: Always 44 | securityContext: {} 45 | terminationGracePeriodSeconds: 30 46 | volumes: 47 | - name: config-volume 48 | configMap: 49 | name: alertmanager-configuration 50 | # - emptyDir: {} 51 | # name: data 52 | 53 | --- 54 | apiVersion: v1 55 | kind: ConfigMap 56 | metadata: 57 | name: alertmanager-configuration 58 | namespace: monitoring 59 | data: 60 | config.yml: |- 61 | route: 62 | group_by: ['alertname'] 63 | group_wait: 10s 64 | group_interval: 10s 65 | repeat_interval: 1h 66 | receiver: 'web.hook.scaleup' 67 | receivers: 68 | - name: 'web.hook.scaleup' 69 | webhook_configs: 70 | - url: 'http://webhook:9000/hooks/scaleup' 71 | inhibit_rules: 72 | - source_match: 73 | severity: 'critical' 74 | target_match: 75 | severity: 'warning' 76 | equal: ['alertname', 'dev', 'instance'] 77 | --- 78 | 79 | apiVersion: v1 80 | kind: Service 81 | metadata: 82 | name: alertmanager 83 | namespace: monitoring 84 | spec: 85 | type: ClusterIP 86 | selector: 87 | name: alertmanager 88 | ports: 89 | - port: 9093 90 | --- 91 | 92 | apiVersion: v1 93 | kind: Service 94 | metadata: 95 | name: alertweb 96 | namespace: monitoring 97 | spec: 98 | type: NodePort 99 | selector: 100 | name: alertmanager 101 | ports: 102 | - port: 9093 103 | protocol: TCP 104 | targetPort: 9093 105 | nodePort: 32001 106 | type: NodePort 107 | -------------------------------------------------------------------------------- /samples/kubernetes/deployments/crossnsrbac.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2019, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | --- 5 | kind: ClusterRole 6 | apiVersion: rbac.authorization.k8s.io/v1beta1 7 | metadata: 8 | name: weblogic-domain-cluster-role 9 | rules: 10 | - apiGroups: ["weblogic.oracle"] 11 | resources: ["domains"] 12 | verbs: ["get", "list"] 13 | --- 14 | # 15 | # creating role-bindings for cluster role 16 | # 17 | kind: ClusterRoleBinding 18 | apiVersion: rbac.authorization.k8s.io/v1beta1 19 | metadata: 20 | name: domain-cluster-rolebinding 21 | subjects: 22 | - kind: ServiceAccount 23 | name: default 24 | namespace: weblogic-domain 25 | apiGroup: "" 26 | roleRef: 27 | kind: ClusterRole 28 | name: weblogic-domain-cluster-role 29 | apiGroup: "rbac.authorization.k8s.io" 30 | --- 31 | # 32 | # creating role-bindings 33 | # 34 | kind: RoleBinding 35 | apiVersion: rbac.authorization.k8s.io/v1beta1 36 | metadata: 37 | name: weblogic-domain-operator-rolebinding 38 | namespace: weblogic-operator 39 | subjects: 40 | - kind: ServiceAccount 41 | name: default 42 | namespace: weblogic-domain 43 | apiGroup: "" 44 | roleRef: 45 | kind: ClusterRole 46 | name: cluster-admin 47 | apiGroup: "rbac.authorization.k8s.io" 48 | --- 49 | -------------------------------------------------------------------------------- /samples/kubernetes/deployments/grafana-deployment.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2019, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | apiVersion: extensions/v1beta1 5 | kind: Deployment 6 | metadata: 7 | labels: 8 | name: grafana 9 | name: grafana 10 | namespace: monitoring 11 | spec: 12 | replicas: 1 13 | selector: 14 | matchLabels: 15 | name: grafana 16 | strategy: 17 | rollingUpdate: 18 | maxSurge: 1 19 | maxUnavailable: 1 20 | type: RollingUpdate 21 | template: 22 | metadata: 23 | creationTimestamp: null 24 | labels: 25 | name: grafana 26 | spec: 27 | containers: 28 | - image: grafana/grafana:4.6.3 29 | imagePullPolicy: IfNotPresent 30 | name: grafana 31 | ports: 32 | - containerPort: 3000 33 | protocol: TCP 34 | resources: 35 | limits: 36 | cpu: 500m 37 | memory: 2500Mi 38 | requests: 39 | cpu: 100m 40 | memory: 100Mi 41 | volumeMounts: 42 | - mountPath: /var/lib/grafana 43 | name: data 44 | restartPolicy: Always 45 | securityContext: {} 46 | terminationGracePeriodSeconds: 30 47 | volumes: 48 | - emptyDir: {} 49 | name: data 50 | --- 51 | 52 | apiVersion: v1 53 | kind: Service 54 | metadata: 55 | name: grafana 56 | namespace: monitoring 57 | spec: 58 | ports: 59 | - port: 3000 60 | protocol: TCP 61 | targetPort: 3000 62 | nodePort: 31000 63 | selector: 64 | name: grafana 65 | type: NodePort 66 | -------------------------------------------------------------------------------- /samples/kubernetes/deployments/monitoring-namespace.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2019, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | --- 5 | apiVersion: v1 6 | kind: Namespace 7 | metadata: 8 | name: monitoring 9 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/README.md: -------------------------------------------------------------------------------- 1 | ## Monitoring WebLogic Server with the Grafana Dashboard 2 | This is an end-to-end sample that demonstrates setting up monitoring for WebLogic domains using Prometheus and Grafana. When completed, you'll have Prometheus, Grafana, and WebLogic domains installed, configured, and running. This sample includes Grafana dashboards to visualize the WebLogic Server runtime metrics and demonstrates how to fire alerts based on the metrics. 3 | 4 | First, look at [what's in the WebLogic Server Dashboard](docs/dashboard.md). 5 | 6 | See the following diagram for the overall architecture containing the basic components that we'll deploy to a Kubernetes cluster. 7 | 8 | ![architecture](docs/images/architecture.png) 9 | 10 | Here's how the WebLogic runtime metrics are generated, scraped, stored, and used: 11 | - WebLogic Servers expose their runtime data using the REST API. 12 | - The exporter, running on each WebLogic Server instance, acquires WebLogic data by calling the REST API, which it then translates to the Prometheus metrics format and exposes in an HTTP endpoint. 13 | - The Prometheus server periodically scrapes the metrics from the endpoints and stores them in its time series database. 14 | - Graphing - The Grafana server queries the metrics from the Prometheus server using PromQL and displays the metrics and series in a visualization dashboard. 15 | - Alerting 16 | - Alerting rules are defined in the Prometheus server using PromQL expressions. 17 | - When alert conditions are met, the Prometheus server fires alerts to the Alertmanager. 18 | - The Alertmanager can potentially deduplicate, group, and route all the alerts and send notifications accordingly to various receivers, like email, Slack, webhook, and such. In this sample, the Alertmanager simply sends notifications to a test webhook. 19 | 20 | ## Prerequisites 21 | - Have a running Kubernetes cluster version 1.10 or higher. 22 | - Have Helm installed. 23 | - Clone this repository. 24 | ``` 25 | git clone https://github.com/oracle/weblogic-monitoring-exporter.git 26 | ``` 27 | - Change the directory to the root folder of this sample. All the commands in the step-by-step guide are written to run under this root folder. 28 | ``` 29 | cd weblogic-monitoring-exporter/samples/kubernetes/end2end/ 30 | ``` 31 | 32 | ## Step-by-Step Guide 33 | 1. [Configuring the PV Path](docs/01-pv-path.md) 34 | 1. Preparing and Running a WebLogic Domain 35 | - [Setting up MYSQL Server](docs/02-mysql.md) 36 | - [Installing the WebLogic Server Kubernetes Operator](docs/03-wls-operator.md) 37 | - [Running a WebLogic Domain](docs/04-wls-domain.md) 38 | 1. [Setting up Prometheus](docs/05-prometheus.md) 39 | 1. [Setting up Grafana](docs/06-grafana.md) 40 | 1. Setting up and Firing Alerts 41 | - [Setting up a Webhook](docs/07-webhook.md) 42 | - [Firing Alerts](docs/08-alert.md) 43 | 1. [How to Monitor an Existing WebLogic Domain](docs/existing-domain.md) 44 | 1. [Cleanup](docs/cleanup.md) 45 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/dashboard/exporter-config.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2019, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | host: localhost 5 | port: 7001 6 | metricsNameSnakeCase: true 7 | queries: 8 | - key: name 9 | keyName: location 10 | prefix: wls_server_ 11 | applicationRuntimes: 12 | key: name 13 | keyName: app 14 | componentRuntimes: 15 | prefix: wls_webapp_config_ 16 | type: WebAppComponentRuntime 17 | key: name 18 | values: [deploymentState, contextRoot, sourceInfo, sessionsOpenedTotalCount, openSessionsCurrentCount, openSessionsHighCount] 19 | servlets: 20 | prefix: wls_servlet_ 21 | key: servletName 22 | - JVMRuntime: 23 | prefix: wls_jvm_ 24 | key: name 25 | - executeQueueRuntimes: 26 | prefix: wls_socketmuxer_ 27 | key: name 28 | values: [pendingRequestCurrentCount] 29 | - workManagerRuntimes: 30 | prefix: wls_workmanager_ 31 | key: name 32 | values: [stuckThreadCount, pendingRequests, completedRequests] 33 | - threadPoolRuntime: 34 | prefix: wls_threadpool_ 35 | key: name 36 | values: [executeThreadTotalCount, queueLength, stuckThreadCount, hoggingThreadCount] 37 | - JMSRuntime: 38 | key: name 39 | keyName: jmsruntime 40 | prefix: wls_jmsruntime_ 41 | JMSServers: 42 | prefix: wls_jms_ 43 | key: name 44 | keyName: jmsserver 45 | destinations: 46 | prefix: wls_jms_dest_ 47 | key: name 48 | keyName: destination 49 | 50 | - persistentStoreRuntimes: 51 | prefix: wls_persistentstore_ 52 | key: name 53 | - JDBCServiceRuntime: 54 | JDBCDataSourceRuntimeMBeans: 55 | prefix: wls_datasource_ 56 | key: name 57 | - JTARuntime: 58 | prefix: wls_jta_ 59 | key: name 60 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/demo-domains/domain1.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2017, 2022, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | # 4 | # This is an sample domain resource which has domainHome in image. 5 | # 6 | 7 | apiVersion: "weblogic.oracle/v9" 8 | kind: Domain 9 | metadata: 10 | name: domain1 11 | namespace: weblogic 12 | labels: 13 | weblogic.domainUID: domain1 14 | spec: 15 | domainHome: /u01/oracle/user-projects/domains/domain1 16 | domainHomeSourceType: Image 17 | image: domain1-image:1.0 18 | imagePullPolicy: "IfNotPresent" 19 | webLogicCredentialsSecret: 20 | name: domain1-weblogic-credentials 21 | includeServerOutInPodLog: true 22 | serverStartPolicy: "IfNeeded" 23 | serverPod: 24 | env: 25 | - name: JAVA_OPTIONS 26 | value: "-Dweblogic.StdoutDebugEnabled=false" 27 | - name: USER_MEM_ARGS 28 | value: "-Xms256m -Xmx512m -Djava.security.egd=file:/dev/./urandom " 29 | resources: 30 | requests: 31 | cpu: "250m" 32 | memory: "768Mi" 33 | adminServer: 34 | adminService: 35 | channels: 36 | - channelName: default 37 | nodePort: 30701 38 | - channelName: T3Channel 39 | nodePort: 30703 40 | # clusters is used to configure the desired behavior for starting member servers of a cluster. 41 | # If you use this entry, then the rules will be applied to ALL servers that are members of the named clusters. 42 | clusters: 43 | - name: cluster-1 44 | 45 | --- 46 | 47 | apiVersion: weblogic.oracle/v1 48 | kind: Cluster 49 | metadata: 50 | name: cluster-1 51 | # Update this with the namespace your domain will run in: 52 | namespace: weblogic 53 | labels: 54 | # Update this with the `domainUID` of your domain: 55 | weblogic.domainUID: domain1 56 | 57 | spec: 58 | clusterName: cluster-1 59 | replicas: 3 60 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/demo-domains/domainBuilder/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2019, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | FROM container-registry.oracle.com/middleware/weblogic:12.2.1.3 5 | 6 | ENV SCRIPTS_DIR="/tmp/scripts/" 7 | 8 | RUN mkdir -p $SCRIPTS_DIR 9 | COPY tmp/* $SCRIPTS_DIR 10 | RUN $SCRIPTS_DIR/create-domain.sh && \ 11 | rm -rf ${SCRIPTS_DIR} 12 | 13 | WORKDIR $ORACLE_HOME 14 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/demo-domains/domainBuilder/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2019, 2022, Oracle and/or its affiliates. All rights reserved. 3 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 4 | 5 | set -e # Exit immediately if a command exits with a non-zero status. 6 | 7 | WDT_VERSION=2.4.2 8 | MONITORING_EXPORTER_VERSION=2.1 9 | 10 | CUR_DIR="$(dirname "$(readlink -f "$0")")" # get the absolute path of this file's folder 11 | PRJ_ROOT=${CUR_DIR}/../../../../.. 12 | TMP_DIR=${CUR_DIR}/tmp 13 | 14 | # Create two webapps: testwebapp and wls-exporter. 15 | function createArchive() { 16 | mkdir -p ${TMP_DIR}/archive/wlsdeploy/applications 17 | 18 | echo 'Build the test webapp...' 19 | cd test-webapp && mvn clean install && cd .. 20 | cp test-webapp/target/testwebapp.war ${TMP_DIR}/archive/wlsdeploy/applications/testwebapp.war 21 | 22 | echo "Download the metrics exporter webapp from ://github.com/oracle/weblogic-monitoring-exporter/releases/download/v${MONITORING_EXPORTER_VERSION}/get${MONITORING_EXPORTER_VERSION}.sh..." 23 | 24 | cd $PRJ_ROOT 25 | curl -O -L https://github.com/oracle/weblogic-monitoring-exporter/releases/download/v${MONITORING_EXPORTER_VERSION}.0/get${MONITORING_EXPORTER_VERSION}.sh 26 | chmod 777 get${MONITORING_EXPORTER_VERSION}.sh 27 | bash get${MONITORING_EXPORTER_VERSION}.sh ${CUR_DIR}/../../dashboard/exporter-config.yaml 28 | echo 'Monitoring Exporter web application is built' 29 | 30 | cd $CUR_DIR 31 | cp $PRJ_ROOT/wls-exporter.war \ 32 | ${TMP_DIR}/archive/wlsdeploy/applications/wls-exporter.war 33 | 34 | echo 'Build the WDT archive...' 35 | jar cvf ${TMP_DIR}/archive.zip -C ${TMP_DIR}/archive wlsdeploy 36 | rm -rf ${TMP_DIR}/archive 37 | } 38 | 39 | function cleanTmpDir() { 40 | rm -rf ${CUR_DIR}/test-webapp/target 41 | rm -rf ${PRJ_ROOT}/wls-exporter.war 42 | rm -rf ${TMP_DIR} 43 | } 44 | 45 | function buildImage() { 46 | cp ${CUR_DIR}/scripts/* ${TMP_DIR} 47 | echo "Update domain.properties with cmdline arguments..." 48 | sed -i "s/^DOMAIN_NAME.*/DOMAIN_NAME=$1/g" ${TMP_DIR}/domain.properties 49 | sed -i "s/^ADMIN_USER.*/ADMIN_USER=$2/g" ${TMP_DIR}/domain.properties 50 | sed -i "s/^ADMIN_PWD.*/ADMIN_PWD=$3/g" ${TMP_DIR}/domain.properties 51 | sed -i "s/^MYSQL_USER.*/MYSQL_USER=$4/g" ${TMP_DIR}/domain.properties 52 | sed -i "s/^MYSQL_PWD.*/MYSQL_PWD=$5/g" ${TMP_DIR}/domain.properties 53 | 54 | echo 'Download the wdt zip...' 55 | wget -P ${TMP_DIR} \ 56 | https://github.com/oracle/weblogic-deploy-tooling/releases/download/release-${WDT_VERSION}/weblogic-deploy.zip 57 | 58 | imageName=$1-image:1.0 59 | echo "Build the domain image $imageName..." 60 | docker build $CUR_DIR --force-rm -t $imageName 61 | } 62 | 63 | if [ "$#" != 5 ] ; then 64 | echo "usage: $0 domainName adminUser adminPwd mysqlUser mysqlPwd" 65 | exit 1 66 | fi 67 | 68 | cleanTmpDir 69 | createArchive 70 | buildImage $@ 71 | cleanTmpDir 72 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/demo-domains/domainBuilder/scripts/create-domain.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2019, Oracle and/or its affiliates. All rights reserved. 3 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 4 | 5 | set -exu 6 | 7 | WDT_HOME="/u01" 8 | DOMAIN_PARENT="/u01/oracle/user-projects/domains" 9 | 10 | cd $WDT_HOME && \ 11 | jar xf ${SCRIPTS_DIR}/weblogic-deploy.zip && \ 12 | chmod +x weblogic-deploy/bin/*.sh && \ 13 | mkdir -p $DOMAIN_PARENT && \ 14 | 15 | ${WDT_HOME}/weblogic-deploy/bin/createDomain.sh \ 16 | -oracle_home $ORACLE_HOME \ 17 | -java_home $JAVA_HOME \ 18 | -domain_parent $DOMAIN_PARENT \ 19 | -domain_type WLS \ 20 | -model_file ${SCRIPTS_DIR}/simple-topology.yaml \ 21 | -archive_file ${SCRIPTS_DIR}/archive.zip \ 22 | -variable_file ${SCRIPTS_DIR}/domain.properties 23 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/demo-domains/domainBuilder/scripts/domain.properties: -------------------------------------------------------------------------------- 1 | # These variables are used for substitution in the WDT model file. 2 | # Any port that will be exposed through Docker is put in this file. 3 | # The sample Dockerfile will get the ports from this file and not the WDT model. 4 | DOMAIN_NAME= 5 | ADMIN_PORT=7001 6 | ADMIN_NAME=admin-server 7 | MANAGED_SERVER_PORT=8001 8 | MANAGED_SERVER_NAME_BASE=managed-server- 9 | CONFIGURED_MANAGED_SERVER_COUNT=3 10 | CLUSTER_NAME=cluster-1 11 | PRODUCTION_MODE_ENABLED=true 12 | CLUSTER_TYPE=DYNAMIC 13 | JAVA_OPTIONS=-Dweblogic.StdoutDebugEnabled=false 14 | T3_CHANNEL_PORT=30012 15 | T3_PUBLIC_ADDRESS=kubernetes 16 | SERVER_START_MODE=prod 17 | ADMIN_USER= 18 | ADMIN_PWD= 19 | 20 | MYSQL_USER= 21 | MYSQL_PWD= 22 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/demo-domains/domainBuilder/test-webapp/pom.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 8 | 4.0.0 9 | 10 | Test WebApp 11 | 12 | com.oracle.weblogic 13 | testwebapp 14 | 1.0 15 | war 16 | 17 | 18 | 19 | javax 20 | javaee-web-api 21 | 6.0 22 | provided 23 | 24 | 25 | javax.servlet 26 | javax.servlet-api 27 | 3.0.1 28 | provided 29 | 30 | 31 | 32 | 33 | testwebapp 34 | 35 | 36 | org.apache.maven.plugins 37 | maven-war-plugin 38 | 39 | false 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/demo-domains/domainBuilder/test-webapp/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 13 | TestWebApp 14 | 15 | index.jsp 16 | 17 | 18 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/demo-domains/domainBuilder/test-webapp/src/main/webapp/WEB-INF/weblogic.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 13 | 12.2.1 14 | 15 | false 16 | false 17 | 18 | testwebapp 19 | 20 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/demo-domains/domainBuilder/test-webapp/src/main/webapp/index.jsp: -------------------------------------------------------------------------------- 1 | <%@ page import="java.net.UnknownHostException" %> 2 | <%@ page import="java.net.InetAddress" %> 3 | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 4 | <%@page contentType="text/html" pageEncoding="UTF-8"%> 5 | 6 | 7 | 8 | 9 | 10 | 11 | Test WebApp 12 | 13 | 14 | <% 15 | String hostname, serverAddress; 16 | hostname = "error"; 17 | serverAddress = "error"; 18 | try { 19 | InetAddress inetAddress; 20 | inetAddress = InetAddress.getLocalHost(); 21 | hostname = inetAddress.getHostName(); 22 | serverAddress = inetAddress.toString(); 23 | } catch (UnknownHostException e) { 24 | 25 | e.printStackTrace(); 26 | } 27 | %> 28 | 29 |
  • InetAddress: <%=serverAddress %> 30 |
  • InetAddress.hostname: <%=hostname %> 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/docs/01-pv-path.md: -------------------------------------------------------------------------------- 1 | ## Configuring the PV Path 2 | In this sample, we need to create four Persistent Volumes (PV) and Persistent Volume Claims (PVC) to store data for MySQL, Prometheus server, Prometheus Alertmanager, and Grafana. See the following YAML files for the four PVs/PVCs: 3 | - [PV and PVC for MYSQL server](../mysql/persistence.yaml) 4 | - [PV and PVC for Prometheus server](../prometheus/persistence.yaml) 5 | - [PV and PVC for Prometheus Alertmanager](../prometheus/alert-persistence.yaml) 6 | - [PV and PVC for Grafana server](../grafana/persistence.yaml) 7 | 8 | > **Note**: To simplify the configuration, we use `hostPath` PV that works only in a single-node Kubernetes cluster; therefore, it's for demonstration purposes only. In a production environment, you would need to use a more sophisticated PV type like NFS, iSCSI. For detailed information, see the Kubernetes [Types of Persistent Volumes](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#types-of-persistent-volumes) document. 9 | 10 | To simplify the configuration and management, the four PVs will share the same root path. Prepare a host folder as the root path of the PVs. 11 | 12 | Create a new folder in the host machine and set the `PV_ROOT` env. 13 | ``` 14 | mkdir 15 | export PV_ROOT= 16 | ``` 17 | 18 | Then use the following commands to auto-update the path values in the PV and PVC YAML files: 19 | 20 | ``` 21 | sed -i 's@%PV_ROOT%@'"$PV_ROOT"'@' mysql/persistence.yaml 22 | sed -i 's@%PV_ROOT%@'"$PV_ROOT"'@' prometheus/persistence.yaml 23 | sed -i 's@%PV_ROOT%@'"$PV_ROOT"'@' prometheus/alert-persistence.yaml 24 | sed -i 's@%PV_ROOT%@'"$PV_ROOT"'@' grafana/persistence.yaml 25 | ``` 26 | 27 | ### Verification 28 | 29 | To confirm that the path value has been updated correctly, use the `grep` command to print the PV path lines in the YAML files. 30 | 31 | ``` 32 | grep -r --include="*.yaml" 'path: ' . 33 | ``` 34 | > output (assuming the `PV_ROOT` is set to `/scratch/test`) 35 | ``` 36 | ./mysql/persistence.yaml: path: "/scratch/test/monitoring/mysql_data" 37 | ./grafana/persistence.yaml: path: "/scratch/test/monitoring/grafana" 38 | ./prometheus/alert-persistent.yaml: path: "/scratch/test/monitoring/alertmanager" 39 | ./prometheus/persistence.yaml: path: "/scratch/test/monitoring/prometheus" 40 | ``` 41 | Next: [Setting up MYSQL Server](02-mysql.md) 42 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/docs/02-mysql.md: -------------------------------------------------------------------------------- 1 | ## Setting up MYSQL Server 2 | 3 | In this step, we describe how to set up MySQL database in the Kubernetes cluster. We are using the MySQL database to store application data. The WebLogic domain created in a later step, will store its data in the database, for example, persistent JMS messages. 4 | 5 | Deploy the PV and PVC. 6 | ``` 7 | kubectl apply -f ./mysql/persistence.yaml 8 | ``` 9 | Install a MySQL server. 10 | 11 | Note that the root password is set to `123456` in the [mysql YAML](../mysql/mysql.yaml) file. Change it to a more secure password when needed. 12 | ``` 13 | kubectl apply -f ./mysql/mysql.yaml 14 | ``` 15 | Wait until the MySQL server pod is running and ready. 16 | ``` 17 | kubectl get pod -l app=mysql 18 | ``` 19 | > output 20 | ``` 21 | NAME READY STATUS RESTARTS AGE 22 | mysql-7bf4d88f9-sbd25 1/1 Running 0 31h 23 | ``` 24 | Get the pod name of MySQL server. 25 | ``` 26 | POD_NAME=$(kubectl get pod -l app=mysql -o jsonpath="{.items[0].metadata.name}") 27 | ``` 28 | Create a new database with the name `domain1` and a new user `wluser1` with the password `wlpwd123`. 29 | ``` 30 | kubectl exec -it $POD_NAME -- mysql -p123456 -e "CREATE DATABASE domain1;" 31 | kubectl exec -it $POD_NAME -- mysql -p123456 -e "CREATE USER 'wluser1' IDENTIFIED BY 'wlpwd123';" 32 | kubectl exec -it $POD_NAME -- mysql -p123456 -e "GRANT ALL ON domain1.* TO 'wluser1';" 33 | ``` 34 | 35 | ## Verification 36 | Access the new database with the new user. 37 | ``` 38 | kubectl exec -it $POD_NAME -- mysql -u wluser1 -pwlpwd123 -D domain1 -e "show tables;" 39 | ``` 40 | Note that we have not created any user tables in the database. The purpose of running this query is to verify that the MySQL database has been created correctly. 41 | 42 | Next: [Installing the WebLogic Server Kubernetes Operator](03-wls-operator.md) 43 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/docs/03-wls-operator.md: -------------------------------------------------------------------------------- 1 | ## Installing the WebLogic Server Kubernetes Operator 2 | We depend on the [WebLogic Server Kubernetes Operator](https://github.com/oracle/weblogic-kubernetes-operator) to create and manage WebLogic domains. For detailed installation information, see [Install the Operator](https://oracle.github.io/weblogic-kubernetes-operator/managing-operators/installation/). 3 | 4 | In this example, we provide the steps to install the operator 4.0.1 release. 5 | 6 | ### Installing the WebLogic Server Kubernetes Operator 7 | 8 | Create a namespace in which to run the operator. 9 | ``` 10 | kubectl create namespace weblogic-operator1 11 | ``` 12 | Create a service account. 13 | ``` 14 | kubectl create serviceaccount -n weblogic-operator1 sample-weblogic-operator-sa 15 | ``` 16 | Add the operator chart repository to Helm. 17 | ``` 18 | helm repo add weblogic-operator https://oracle.github.io/weblogic-kubernetes-operator/charts 19 | ``` 20 | Install the operator with the operator chart with version `4.0.1`. 21 | ``` 22 | helm install weblogic-operator/weblogic-operator \ 23 | --version 4.0.1 \ 24 | --name weblogic-operator \ 25 | --namespace weblogic-operator1 \ 26 | --set serviceAccount=sample-weblogic-operator-sa \ 27 | --wait 28 | ``` 29 | 30 | ### Verification 31 | Wait until the operator pod is running and ready. 32 | ``` 33 | kubectl -n weblogic-operator1 get pod 34 | ``` 35 | > output 36 | ``` 37 | NAME READY STATUS RESTARTS AGE 38 | weblogic-operator-fcfff877c-c4972 1/1 Running 0 30h 39 | ``` 40 | Wait until the domain CRD is registered successfully. 41 | ``` 42 | kubectl get crd domains.weblogic.oracle 43 | ``` 44 | > output 45 | ``` 46 | NAME CREATED AT 47 | domains.weblogic.oracle 2019-05-28T07:17:26Z 48 | ``` 49 | Now the WebLogic Server Kubernetes Operator is running and it's monitoring all namespaces created with the label `weblogic weblogic-operator=enabled`. The operator will be responsible for creating, running, and managing any WebLogic domains deployed to namespaces with such labels. 50 | 51 | Next: [Running a WebLogic Domain](04-wls-domain.md) 52 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/docs/05-prometheus.md: -------------------------------------------------------------------------------- 1 | ## Setting up Prometheus 2 | Install Prometheus using a [Helm chart](https://github.com/helm/charts/tree/master/stable/prometheus) with the customized [values.yaml](../prometheus/values.yaml). There are four components that will be installed with this chart: Prometheus server, Alertmanager, node-exporter, and kube-state-metrics. 3 | 4 | Create a new namespace `monitoring`. 5 | ``` 6 | kubectl create ns monitoring 7 | ``` 8 | Deploy the PV and PVC YAML files. 9 | ``` 10 | kubectl apply -f prometheus/persistence.yaml 11 | kubectl apply -f prometheus/alert-persistence.yaml 12 | ``` 13 | Install the Prometheus chart. In this sample we will use version 17.0.0. 14 | ``` 15 | helm repo add prometheus-community https://prometheus-community.github.io/helm-charts --force-update 16 | helm install prometheus prometheus-community/prometheus --namespace monitoring --values prometheus/values.yaml --version 17.0.0 --wait 17 | ``` 18 | Note that in the customized `values.yaml` file, we added a new job [wls-domain1](../prometheus/values.yaml#L59) to scrape data from the WebLogic domain created in the previous step. 19 | 20 | ### Verification 21 | Wait until all the Prometheus pods are running and ready. 22 | ``` 23 | kubectl -n monitoring get pod -l app=prometheus 24 | ``` 25 | > output 26 | ``` 27 | NAME READY STATUS RESTARTS AGE 28 | prometheus-alertmanager-7456cdb5b8-9vfmd 2/2 Running 0 1h 29 | prometheus-kube-state-metrics-dbfff5557-f22xx 1/1 Running 0 1h 30 | prometheus-node-exporter-6n7rj 1/1 Running 0 1h 31 | prometheus-server-5789fffc86-mmh8f 2/2 Running 0 1h 32 | ``` 33 | Check the Prometheus sevices. 34 | ``` 35 | kubectl -n monitoring get svc -l app=prometheus 36 | ``` 37 | > output 38 | ``` 39 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 40 | prometheus-alertmanager NodePort 10.108.31.234 80:32000/TCP 1h 41 | prometheus-kube-state-metrics ClusterIP None 80/TCP 1h 42 | prometheus-node-exporter ClusterIP None 9100/TCP 1h 43 | prometheus-server NodePort 10.103.186.222 80:30000/TCP 1h 44 | ``` 45 | 46 | ### Access the Prometheus web UI 47 | Now you can access the Prometheus web UI in your browser with the URL `http://:30000`. 48 | 49 | #### Access the Target Page 50 | In the top menu, click `Status` and then `Targets`. The target page is displayed. Go to the bottom of the page; you'll find that the two targets of `wls-domain1` are up and healthy. 51 | 52 | ![Prometheus Targets](./images/prometheus-targets.png) 53 | 54 | #### Query the WebLogic Metrics from the Graph Page 55 | In the top menu, click `Graph`. The graph page is displayed. Enter the expression `wls_jvm_uptime` that is one of the WebLogic metrics, and click `Execute`. There will be two results displayed as shown below. This means that the Prometheus server can scrape metrics from WebLogic Servers successfully. 56 | 57 | ![Prometheus Targets](./images/prometheus-graph.png) 58 | 59 | 60 | We'll talk about Alertmanager in a later step. 61 | 62 | Next: [Setting up Grafana](06-grafana.md) 63 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/docs/07-webhook.md: -------------------------------------------------------------------------------- 1 | ## Setting up a Webhook 2 | We will set up a simple webhook as the notification receiver. The webhook is written as [a Python script](../webhook/scripts/server.py) which simply logs all the received notifications. Typically, webhook receivers are often used to notify systems that Alertmanager doesn’t support directly. 3 | 4 | Build the webhook image. 5 | ``` 6 | docker build ./webhook -t webhook-log:1.0 7 | ``` 8 | Create a new namespace and install the webhook server. 9 | ``` 10 | kubectl create ns webhook 11 | kubectl apply -f ./webhook/server.yaml 12 | ``` 13 | Wait until the webhook server pod is running and ready. 14 | ``` 15 | kubectl -n webhook get pod -l app=webhook 16 | ``` 17 | > output 18 | ``` 19 | NAME READY STATUS RESTARTS AGE 20 | webhook-bbfdffd48-tpzkl 1/1 Running 0 1h 21 | ``` 22 | Check the created service. 23 | ``` 24 | kubectl -n webhook get svc -l app=webhook 25 | ``` 26 | > output 27 | ``` 28 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 29 | webhook ClusterIP 10.102.22.170 8080/TCP 1h 30 | ``` 31 | Now the webhook server is ready. 32 | 33 | Next: [Firing Alerts](08-alert.md) 34 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/docs/cleanup.md: -------------------------------------------------------------------------------- 1 | ## Cleanup 2 | Follow these steps to clean up all the resources created in this sample. 3 | * [Delete Webhook](#delete-webhook) 4 | * [Delete Grafana](#delete-grafana) 5 | * [Delete Prometheus](#delete-prometheus) 6 | * [Delete the WebLogic Domain](#delete-the-wls-domain) 7 | * [Delete the WebLogic Server Kubernetes Operator](#delete-the-wls-kubernetes-operator) 8 | * [Delete MYSQL Server](#delete-mysql-server) 9 | * [Delete Content in PV Folder](#delete-content-in-pv-folder) 10 | 11 | ### Delete Webhook 12 | Delete the webhook server. 13 | ``` 14 | kubectl delete -f webhook/server.yaml 15 | ``` 16 | Delete the webhook namespace. 17 | ``` 18 | kubectl delete ns webhook 19 | ``` 20 | 21 | ### Delete Grafana 22 | Delete the Grafana chart. 23 | ``` 24 | helm delete --purge grafana 25 | ``` 26 | 27 | Delete the Grafana administrative credentials. 28 | ``` 29 | kubectl -n monitoring delete secret grafana-secret 30 | ``` 31 | 32 | Delete the PV and PVC used by the Grafana server. 33 | ``` 34 | kubectl delete -f grafana/persistence.yaml 35 | ``` 36 | ### Delete Prometheus 37 | Delete the Prometheus chart. 38 | ``` 39 | helm delete --purge prometheus 40 | ``` 41 | 42 | Delete the PV and PVC used by the Prometheus server. 43 | ``` 44 | kubectl delete -f prometheus/persistence.yaml 45 | ``` 46 | 47 | Now we can delete the `monitoring` namespace. 48 | ``` 49 | kubectl delete ns monitoring 50 | ``` 51 | 52 | ### Delete the WebLogic Domain 53 | Delete the domain resource. 54 | ``` 55 | kubectl delete -f demo-domains/domain1.yaml 56 | ``` 57 | 58 | Delete the WebLogic administrative credentials secret. 59 | ``` 60 | kubectl delete secret domain1-weblogic-credentials 61 | ``` 62 | 63 | Wait until all the pods in the domain are deleted. 64 | ``` 65 | kubectl get pod -l weblogic.domainName=domain1 66 | ``` 67 | > Expected result: 68 | ``` 69 | No resources found. 70 | ``` 71 | 72 | Wait until all the services in the domain are deleted. 73 | ``` 74 | kubectl get service -l weblogic.domainName=domain1 75 | ``` 76 | > Expected result: 77 | ``` 78 | No resources found. 79 | ``` 80 | 81 | ### Delete the WebLogic Server Kubernetes Operator 82 | Wait until all the WebLogic domain-related resources are deleted before deleting the operator. 83 | 84 | Delete the operator chart. 85 | ``` 86 | helm delete --purge sample-weblogic-operator 87 | ``` 88 | 89 | Delete the service account. 90 | ``` 91 | kubectl delete -n weblogic-operator1 serviceaccount sample-weblogic-operator-sa 92 | ``` 93 | 94 | Delete the namespace. 95 | ``` 96 | kubectl delete namespace weblogic-operator1 97 | ``` 98 | 99 | Delete the folder containing the operator repository. 100 | ``` 101 | rm -rf weblogic-kubernetes-operator 102 | ``` 103 | 104 | ### Delete MYSQL Server 105 | Delete the MYSQL server. 106 | ``` 107 | kubectl delete -f ./mysql/mysql.yaml 108 | ``` 109 | 110 | Delete the PV and PVC used by the MYSQL server. 111 | ``` 112 | kubectl delete -f ./mysql/persistence.yaml 113 | ``` 114 | 115 | ### Delete Content in PV Folder 116 | To get around file permission checking under this folder, we perform the deletion in a Docker container with root privilege. 117 | ``` 118 | docker run --rm -v $PV_ROOT:/tt -v $PWD/util:/util nginx /util/clean-pv.sh 119 | ``` 120 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/docs/dashboard.md: -------------------------------------------------------------------------------- 1 | ## What's on the WebLogic Server Dashboard 2 | ### Overview 3 | The WebLogic Server Grafana dashboard provides a visualization of WebLogic Server runtime metrics allowing you to monitor and diagnose the runtime deployment of WebLogic Server. 4 | 5 | At the top, left-hand corner of the dashboard page, there are filters for filtering out metrics based on specific domains, clusters, and servers. Another filter is `Top N`, whose candidate values are 3, 5, 7, and 10. The value will be applied to panels to show only the top N elements, thus avoiding too many elements being displayed. 6 | 7 | The WebLogic Server dashboard has four rows: `Servers`, `Web Applications`, `Data Sources` and `JMS Services`. Each row can be collapsed and expanded. 8 | 9 | ![Dashboard Overview](./images/dashboard-overview.png) 10 | 11 | ### Servers 12 | ![Servers](./images/dashboard-servers.png) 13 | 14 | ### Web Applications 15 | ![Web Applications](./images/dashboard-webapp.png) 16 | 17 | ### Data Sources 18 | ![Data Sources](./images/dashboard-datasources.png) 19 | 20 | ### JMS Services 21 | ![JMS Services](./images/dashboard-jms.png) 22 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/docs/existing-domain.md: -------------------------------------------------------------------------------- 1 | ## Monitoring an Existing WebLogic Domain 2 | In this step, we show you how to integrate Prometheus and Grafana with an existing WebLogic domain. 3 | 4 | We assume that you have already followed the [Manage WebLogic Domains](https://oracle.github.io/weblogic-kubernetes-operator/userguide/managing-domains/) guide in the WebLogic Server Kubernetes Operator to run a WebLogic domain and have followed the previous steps in this sample to setup Prometheus and Grafana. 5 | 6 | ### Installing the `wls-exporter` to the WebLogic domain 7 | You need to install the `wls-exporter` web application to the WebLogic domain. 8 | 9 | First, get the `wls-exporter` WAR file following the [Downloading the release](https://github.com/oracle/weblogic-monitoring-exporter#downloading-the-release) instructions using the configuration file in this sample [exporter-config.yaml](../dashboard/exporter-config.yaml) file. Then deploy the WAR to the WebLogic Servers and clusters using WLST or WDT. 10 | 11 | After the `wls-exporter` is installed successfully, you can check the exported WebLogic runtime metrics from each server. See the detailed instructions [here](04-wls-domain.md#check-the-weblogic-runtime-metrics). 12 | 13 | ### Updating the Prometheus Configuration 14 | Next, we need to instruc the Prometheus server to scrape metrics from the WebLogic domain. Basically, we need to add a new job to the `prometheus.yml` file, the configuration file of the Prometheus server. The job is similar to what we added for `domain1` in [values.yaml](../prometheus/values.yaml#L59) of the Prometheus chart. As shown below, lines in red need to be updated properly. 15 | 16 | ![job](images/prometheus-job.png) 17 | 18 | Because the Prometheus server is already running, can we update its configuration dynamically without restarting it? The answer is yes. When installing with the Prometheus chart, there are two containers running in the Prometheus server pod: one is for the Prometheus server, the other is to detect changes in the ConfigMap and apply the latest configuration to the runtime. What we need to do is to update the ConfigMap of the Prometheus server to add a new job to the `prometheus.yml` file. 19 | 20 | You can edit the ConfigMap directly using `kubectl edit`. 21 | ``` 22 | kubectl -n monitoring edit cm prometheus-server 23 | ``` 24 | Or you can save, update, and re-apply the ConfigMap. 25 | 1. Save the current ConfigMap to a temporary file `cm.yaml`. 26 | `kubectl -n monitoring get cm prometheus-server -oyaml > cm.yaml` 27 | 1. Update the file `cm.yaml` accordingly. 28 | `vi cm.yaml` 29 | 1. Apply the new ConfigMap. 30 | `kubectl -n monitoring apply -f cm.yaml` 31 | 32 | Wait until the new configuration is applied to the runtime. You can access the Prometheus web UI to verify that new targets are added and new metrics are scraped by the Prometheus server. Follow the instructions [here](05-prometheus.md#access-the-prometheus-web-ui). 33 | 34 | ### Integrating with Grafana and Dashboard 35 | You do not need to change anything in the Grafana configuration or the WebLogic dashboard. After the Prometheus server starts to scrape and store metrics of the new WebLogic domain, the metrics will be displayed in the WebLogic dashboard seamlessly. When you access the WebLogic dashboard in the Grafana web UI, the new domain name will be displayed in the drop-down list of the `domain` filter. 36 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/docs/images/active-alert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/weblogic-monitoring-exporter/cc7aa11a1cb39f61cbf355e8ef968b8361cdf90f/samples/kubernetes/end2end/docs/images/active-alert.png -------------------------------------------------------------------------------- /samples/kubernetes/end2end/docs/images/alert-manager-config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/weblogic-monitoring-exporter/cc7aa11a1cb39f61cbf355e8ef968b8361cdf90f/samples/kubernetes/end2end/docs/images/alert-manager-config.png -------------------------------------------------------------------------------- /samples/kubernetes/end2end/docs/images/alert-rule.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/weblogic-monitoring-exporter/cc7aa11a1cb39f61cbf355e8ef968b8361cdf90f/samples/kubernetes/end2end/docs/images/alert-rule.png -------------------------------------------------------------------------------- /samples/kubernetes/end2end/docs/images/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/weblogic-monitoring-exporter/cc7aa11a1cb39f61cbf355e8ef968b8361cdf90f/samples/kubernetes/end2end/docs/images/architecture.png -------------------------------------------------------------------------------- /samples/kubernetes/end2end/docs/images/dashboard-datasources.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/weblogic-monitoring-exporter/cc7aa11a1cb39f61cbf355e8ef968b8361cdf90f/samples/kubernetes/end2end/docs/images/dashboard-datasources.png -------------------------------------------------------------------------------- /samples/kubernetes/end2end/docs/images/dashboard-jms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/weblogic-monitoring-exporter/cc7aa11a1cb39f61cbf355e8ef968b8361cdf90f/samples/kubernetes/end2end/docs/images/dashboard-jms.png -------------------------------------------------------------------------------- /samples/kubernetes/end2end/docs/images/dashboard-overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/weblogic-monitoring-exporter/cc7aa11a1cb39f61cbf355e8ef968b8361cdf90f/samples/kubernetes/end2end/docs/images/dashboard-overview.png -------------------------------------------------------------------------------- /samples/kubernetes/end2end/docs/images/dashboard-servers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/weblogic-monitoring-exporter/cc7aa11a1cb39f61cbf355e8ef968b8361cdf90f/samples/kubernetes/end2end/docs/images/dashboard-servers.png -------------------------------------------------------------------------------- /samples/kubernetes/end2end/docs/images/dashboard-webapp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/weblogic-monitoring-exporter/cc7aa11a1cb39f61cbf355e8ef968b8361cdf90f/samples/kubernetes/end2end/docs/images/dashboard-webapp.png -------------------------------------------------------------------------------- /samples/kubernetes/end2end/docs/images/datasource.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/weblogic-monitoring-exporter/cc7aa11a1cb39f61cbf355e8ef968b8361cdf90f/samples/kubernetes/end2end/docs/images/datasource.png -------------------------------------------------------------------------------- /samples/kubernetes/end2end/docs/images/prometheus-graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/weblogic-monitoring-exporter/cc7aa11a1cb39f61cbf355e8ef968b8361cdf90f/samples/kubernetes/end2end/docs/images/prometheus-graph.png -------------------------------------------------------------------------------- /samples/kubernetes/end2end/docs/images/prometheus-job.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/weblogic-monitoring-exporter/cc7aa11a1cb39f61cbf355e8ef968b8361cdf90f/samples/kubernetes/end2end/docs/images/prometheus-job.png -------------------------------------------------------------------------------- /samples/kubernetes/end2end/docs/images/prometheus-targets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/weblogic-monitoring-exporter/cc7aa11a1cb39f61cbf355e8ef968b8361cdf90f/samples/kubernetes/end2end/docs/images/prometheus-targets.png -------------------------------------------------------------------------------- /samples/kubernetes/end2end/docs/images/received-alert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/weblogic-monitoring-exporter/cc7aa11a1cb39f61cbf355e8ef968b8361cdf90f/samples/kubernetes/end2end/docs/images/received-alert.png -------------------------------------------------------------------------------- /samples/kubernetes/end2end/docs/images/weblogicDashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle/weblogic-monitoring-exporter/cc7aa11a1cb39f61cbf355e8ef968b8361cdf90f/samples/kubernetes/end2end/docs/images/weblogicDashboard.png -------------------------------------------------------------------------------- /samples/kubernetes/end2end/grafana/datasource.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"Prometheus", 3 | "type":"prometheus", 4 | "url":"http://prometheus-server:80", 5 | "access":"proxy", 6 | "isDefault":true, 7 | "basicAuth":false 8 | } 9 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/grafana/persistence.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2019, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | apiVersion: v1 5 | kind: PersistentVolume 6 | metadata: 7 | name: pv-grafana 8 | 9 | spec: 10 | storageClassName: grafana 11 | capacity: 12 | storage: 10Gi 13 | accessModes: 14 | - ReadWriteOnce 15 | persistentVolumeReclaimPolicy: Retain 16 | hostPath: 17 | path: "%PV_ROOT%/monitoring/grafana" 18 | 19 | --- 20 | apiVersion: v1 21 | kind: PersistentVolumeClaim 22 | metadata: 23 | name: pvc-grafana 24 | namespace: monitoring 25 | 26 | spec: 27 | storageClassName: grafana 28 | resources: 29 | requests: 30 | storage: 10Gi 31 | accessModes: 32 | - ReadWriteOnce 33 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/grafana/values.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2019, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | persistence: 5 | enabled: true 6 | existingClaim: pvc-grafana 7 | service: 8 | type: NodePort 9 | port: 80 10 | targetPort: 3000 11 | nodePort: 31000 12 | 13 | admin: 14 | existingSecret: "grafana-secret" 15 | userKey: username 16 | passwordKey: password 17 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/mysql/mysql.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2019, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | apiVersion: apps/v1 5 | kind: Deployment 6 | metadata: 7 | name: mysql 8 | namespace: default 9 | spec: 10 | selector: 11 | matchLabels: 12 | app: mysql 13 | strategy: 14 | type: Recreate 15 | template: 16 | metadata: 17 | labels: 18 | app: mysql 19 | spec: 20 | containers: 21 | - image: mysql:5.6 22 | name: mysql 23 | env: 24 | - name: MYSQL_ROOT_PASSWORD 25 | valueFrom: 26 | secretKeyRef: 27 | name: mysql-secret 28 | key: root-password 29 | ports: 30 | - containerPort: 3306 31 | name: mysql 32 | volumeMounts: 33 | - name: mysql-persistent-storage 34 | mountPath: /var/lib/mysql 35 | volumes: 36 | - name: mysql-persistent-storage 37 | persistentVolumeClaim: 38 | claimName: pvc-mysql 39 | 40 | --- 41 | apiVersion: v1 42 | kind: Service 43 | metadata: 44 | name: mysql 45 | namespace: default 46 | spec: 47 | clusterIP: None 48 | ports: 49 | - port: 3306 50 | protocol: TCP 51 | selector: 52 | app: mysql 53 | 54 | --- 55 | apiVersion: v1 56 | kind: Secret 57 | metadata: 58 | name: mysql-secret 59 | namespace: default 60 | labels: 61 | app: mysql 62 | data: 63 | # echo -n "root" | base64 64 | root-user: cm9vdA== 65 | # echo -n "123456" | base64 66 | root-password: MTIzNDU2 -------------------------------------------------------------------------------- /samples/kubernetes/end2end/mysql/persistence.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2019, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | kind: PersistentVolume 5 | apiVersion: v1 6 | metadata: 7 | name: pv-mysql 8 | labels: 9 | type: local 10 | spec: 11 | storageClassName: mysql 12 | capacity: 13 | storage: 10Gi 14 | accessModes: 15 | - ReadWriteOnce 16 | hostPath: 17 | path: "%PV_ROOT%/monitoring/mysql_data" 18 | --- 19 | apiVersion: v1 20 | kind: PersistentVolumeClaim 21 | metadata: 22 | name: pvc-mysql 23 | namespace: default 24 | spec: 25 | storageClassName: mysql 26 | accessModes: 27 | - ReadWriteOnce 28 | resources: 29 | requests: 30 | storage: 10Gi 31 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/prometheus/alert-persistence.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2019, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | apiVersion: v1 5 | kind: PersistentVolume 6 | metadata: 7 | name: pv-alertmanager 8 | 9 | spec: 10 | storageClassName: alertmanager 11 | capacity: 12 | storage: 10Gi 13 | accessModes: 14 | - ReadWriteOnce 15 | persistentVolumeReclaimPolicy: Retain 16 | hostPath: 17 | path: "%PV_ROOT%/monitoring/alertmanager" 18 | 19 | --- 20 | apiVersion: v1 21 | kind: PersistentVolumeClaim 22 | metadata: 23 | name: pvc-alertmanager 24 | namespace: monitoring 25 | 26 | spec: 27 | storageClassName: alertmanager 28 | resources: 29 | requests: 30 | storage: 10Gi 31 | accessModes: 32 | - ReadWriteOnce 33 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/prometheus/persistence.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2019, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | apiVersion: v1 5 | kind: PersistentVolume 6 | metadata: 7 | name: pv-prometheus 8 | 9 | spec: 10 | storageClassName: prometheus 11 | capacity: 12 | storage: 10Gi 13 | accessModes: 14 | - ReadWriteOnce 15 | persistentVolumeReclaimPolicy: Retain 16 | hostPath: 17 | path: "%PV_ROOT%/monitoring/prometheus" 18 | 19 | --- 20 | apiVersion: v1 21 | kind: PersistentVolumeClaim 22 | metadata: 23 | name: pvc-prometheus 24 | namespace: monitoring 25 | 26 | spec: 27 | storageClassName: prometheus 28 | resources: 29 | requests: 30 | storage: 10Gi 31 | accessModes: 32 | - ReadWriteOnce 33 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/util/clean-pv.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright 2019, Oracle and/or its affiliates. 3 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 4 | 5 | rm -rf /tt/monitoring 6 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/util/curl.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2019, 2022, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | apiVersion: v1 5 | kind: Pod 6 | metadata: 7 | name: curl 8 | namespace: weblogic 9 | spec: 10 | containers: 11 | - image: pstauffer/curl 12 | command: 13 | - sleep 14 | - "3600" 15 | imagePullPolicy: IfNotPresent 16 | name: curl 17 | restartPolicy: Always 18 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/webhook/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2019, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | FROM python:3.7 5 | 6 | WORKDIR /usr/src/app 7 | 8 | COPY scripts/* ./ 9 | 10 | CMD ["python", "-u", "./server.py"] 11 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/webhook/scripts/server.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | import json 5 | from http.server import BaseHTTPRequestHandler 6 | from http.server import HTTPServer 7 | 8 | class LogHandler(BaseHTTPRequestHandler): 9 | def do_POST(self): 10 | print 11 | self.send_response(200) 12 | self.end_headers() 13 | if 'Content-Type' in self.headers and self.headers['Content-Type'] == 'application/json': 14 | if 'Content-Length' not in self.headers: 15 | print('Receiving a json request, but not an alert.') 16 | return 17 | length = int(self.headers['Content-Length']) 18 | data = json.loads(self.rfile.read(length).decode('utf-8')) 19 | for alert in data["alerts"]: 20 | print('!!! Receiving an alert.') 21 | print(json.dumps(alert, indent=2)) 22 | else: 23 | print('Receiving a non-json post.') 24 | 25 | 26 | PORT = 8080 27 | 28 | if __name__ == '__main__': 29 | httpd = HTTPServer(('', PORT), LogHandler) 30 | print ('Webhook is serving at port', PORT) 31 | httpd.serve_forever() 32 | -------------------------------------------------------------------------------- /samples/kubernetes/end2end/webhook/server.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2017, 2019, Oracle and/or its affiliates. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | apiVersion: apps/v1 5 | kind: Deployment 6 | metadata: 7 | name: webhook 8 | namespace: webhook 9 | labels: 10 | app: webhook 11 | spec: 12 | replicas: 1 13 | selector: 14 | matchLabels: 15 | app: webhook 16 | template: 17 | metadata: 18 | labels: 19 | app: webhook 20 | spec: 21 | containers: 22 | - image: webhook-log:1.0 23 | imagePullPolicy: Never 24 | name: webhook 25 | --- 26 | apiVersion: v1 27 | kind: Service 28 | metadata: 29 | name: webhook 30 | namespace: webhook 31 | labels: 32 | app: webhook 33 | spec: 34 | ports: 35 | - port: 8080 36 | protocol: TCP 37 | selector: 38 | app: webhook 39 | -------------------------------------------------------------------------------- /src/main/notices/META-INF/COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017, 2020, Oracle and/or its affiliates. 2 | Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main/notices/META-INF/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017, 2019, Oracle and/or its affiliates. 2 | Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | Subject to the condition set forth below, permission is hereby granted to any person obtaining 5 | a copy of this software, associated documentation and/or data (collectively the "Software"), 6 | free of charge and under any and all copyright rights in the Software, and any and all patent 7 | rights owned or freely licensable by each licensor hereunder covering either (i) the unmodified 8 | Software as contributed to or provided by such licensor, or (ii) the Larger Works 9 | (as defined below), to deal in both 10 | 11 | (a) the Software, and 12 | 13 | (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if one is included with 14 | the Software (each a "Larger Work" to which the Software is contributed by such licensors), without 15 | restriction, including without limitation the rights to copy, create derivative works of, display, 16 | perform, and distribute the Software and make, use, sell, offer for sale, import, export, have made, 17 | and have sold the Software and the Larger Work(s), and to sublicense the foregoing rights on either 18 | these or other terms. 19 | 20 | This license is subject to the following condition: 21 | 22 | The above copyright notice and either this complete permission notice or at a minimum a reference to 23 | the UPL must be included in all copies or substantial portions of the Software. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 26 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 27 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 28 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 29 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017, 2020, Oracle and/or its affiliates. 2 | Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017, 2019, Oracle and/or its affiliates. 2 | 3 | Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 4 | 5 | Subject to the condition set forth below, permission is hereby granted to any person obtaining 6 | a copy of this software, associated documentation and/or data (collectively the "Software"), 7 | free of charge and under any and all copyright rights in the Software, and any and all patent 8 | rights owned or freely licensable by each licensor hereunder covering either (i) the unmodified 9 | Software as contributed to or provided by such licensor, or (ii) the Larger Works 10 | (as defined below), to deal in both 11 | 12 | (a) the Software, and 13 | 14 | (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if one is included with 15 | the Software (each a "Larger Work" to which the Software is contributed by such licensors), without 16 | restriction, including without limitation the rights to copy, create derivative works of, display, 17 | perform, and distribute the Software and make, use, sell, offer for sale, import, export, have made, 18 | and have sold the Software and the Larger Work(s), and to sublicense the foregoing rights on either 19 | these or other terms. 20 | 21 | This license is subject to the following condition: 22 | 23 | The above copyright notice and either this complete permission notice or at a minimum a reference to 24 | the UPL must be included in all copies or substantial portions of the Software. 25 | 26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 27 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 28 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 29 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 30 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 31 | -------------------------------------------------------------------------------- /start_exporter.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) 2021, Oracle and/or its affiliates. 3 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 4 | 5 | java $JAVA_OPTS -jar wls-exporter-sidecar.jar -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/AuthenticationChallengeException.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019, 2021, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | /** 7 | * An exception indicating that the server has sent a challenge, demanding authentication. 8 | */ 9 | public class AuthenticationChallengeException extends WebClientException { 10 | private final String challenge; 11 | 12 | public AuthenticationChallengeException(String challenge) { 13 | this.challenge = challenge; 14 | } 15 | 16 | String getChallenge() { 17 | return challenge; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/CallFactory.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import java.io.IOException; 7 | 8 | public interface CallFactory { 9 | 10 | /** 11 | * Creates processing to handle a form submission to update the exporter configuration. 12 | * @param invocationContext context of the invocation, containing request and response objects. 13 | */ 14 | void invokeConfigurationFormCall(InvocationContext invocationContext) throws IOException; 15 | 16 | /** 17 | * Creates processing to handle a request for metrics. 18 | * @param invocationContext context of the invocation, containing request and response objects. 19 | */ 20 | void invokeMetricsCall(InvocationContext invocationContext) throws IOException; 21 | } 22 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/CallFactoryServletImpl.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import java.io.IOException; 7 | 8 | public class CallFactoryServletImpl implements CallFactory { 9 | 10 | private final WebClientFactory factory; 11 | 12 | public CallFactoryServletImpl(WebClientFactory factory) { 13 | this.factory = factory; 14 | } 15 | 16 | @Override 17 | public void invokeConfigurationFormCall(InvocationContext invocationContext) throws IOException { 18 | new ConfigurationFormCall(factory, invocationContext).doWithAuthentication(); 19 | } 20 | 21 | @Override 22 | public void invokeMetricsCall(InvocationContext invocationContext) throws IOException { 23 | new ExporterCall(factory, invocationContext).doWithAuthentication(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/ConfigurationCall.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, 2022, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | 9 | import com.oracle.wls.exporter.domain.ConfigurationException; 10 | import com.oracle.wls.exporter.domain.ExporterConfig; 11 | 12 | public abstract class ConfigurationCall extends AuthenticatedCall { 13 | 14 | protected ConfigurationCall(WebClientFactory webClientFactory, InvocationContext context) { 15 | super(webClientFactory, context); 16 | } 17 | 18 | @Override 19 | protected void invoke(WebClient webClient, InvocationContext context) throws IOException { 20 | try (InputStream requestStream = context.getRequestStream()){ 21 | authenticate(webClient.withUrl(getAuthenticationUrl())); 22 | createConfigurationAction(getRequestContentType(), requestStream).perform(); 23 | reportUpdatedConfiguration(context); 24 | } catch (RestPortConnectionException e) { 25 | reportFailure(e); 26 | webClient.setRetryNeeded(); 27 | } catch (ConfigurationException e) { 28 | reportUnableToUpdateConfiguration(context, e); 29 | } 30 | } 31 | 32 | // Authenticates by attempting to send a request to the Management RESTful API. 33 | private void authenticate(WebClient webClient) throws IOException { 34 | webClient.doPostRequest("{ 'links':[], 'fields':[], 'children':{} }".replace("'", "\"")); 35 | } 36 | 37 | abstract ConfigurationAction createConfigurationAction(String contentType, InputStream inputStream) throws IOException; 38 | 39 | protected abstract void reportUpdatedConfiguration(InvocationContext context) throws IOException; 40 | 41 | abstract void reportUnableToUpdateConfiguration(InvocationContext context, ConfigurationException e) throws IOException; 42 | 43 | abstract static class ConfigurationAction { 44 | 45 | private ExporterConfig uploadedConfig; 46 | 47 | final void defineUploadedFile(InputStream inputStream) { 48 | try { 49 | uploadedConfig = ExporterConfig.loadConfig(inputStream); 50 | } catch (ConfigurationException e) { 51 | throw e; 52 | } catch (Exception e) { 53 | throw new ConfigurationException("Unable to understand specified configuration"); 54 | } 55 | } 56 | 57 | public abstract void perform(); 58 | 59 | ExporterConfig getUploadedConfig() { 60 | return uploadedConfig; 61 | } 62 | } 63 | 64 | 65 | } 66 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/ConfigurationDisplay.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, 2022, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import java.io.OutputStream; 7 | import java.io.PrintStream; 8 | 9 | public class ConfigurationDisplay { 10 | 11 | private ConfigurationDisplay() { 12 | // no-op 13 | } 14 | 15 | public static void displayConfiguration(OutputStream outputStream) { 16 | try (PrintStream ps = new PrintStream(outputStream)) { 17 | ps.println("

    Current Configuration

    "); 18 | ps.println("

    ");
    19 |           ps.print(LiveConfiguration.asString());
    20 |           ps.println("

    "); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/ConfigurationFormCall.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.io.PrintStream; 9 | import java.util.List; 10 | import java.util.Locale; 11 | 12 | import com.oracle.wls.exporter.domain.ConfigurationException; 13 | 14 | import static com.oracle.wls.exporter.WebAppConstants.APPEND_ACTION; 15 | import static com.oracle.wls.exporter.WebAppConstants.DEFAULT_ACTION; 16 | import static com.oracle.wls.exporter.WebAppConstants.MAIN_PAGE; 17 | import static com.oracle.wls.exporter.WebAppConstants.REPLACE_ACTION; 18 | 19 | public class ConfigurationFormCall extends ConfigurationCall { 20 | 21 | public ConfigurationFormCall(WebClientFactory webClientFactory, InvocationContext context) { 22 | super(webClientFactory, context); 23 | } 24 | 25 | @Override 26 | ConfigurationAction createConfigurationAction(String contentType, InputStream inputStream) throws IOException { 27 | return new ConfigurationFormAction(contentType, inputStream); 28 | } 29 | 30 | @Override 31 | protected void reportUpdatedConfiguration(InvocationContext context) throws IOException { 32 | context.sendRedirect(MAIN_PAGE); 33 | } 34 | 35 | @Override 36 | void reportUnableToUpdateConfiguration(InvocationContext context, ConfigurationException e) throws IOException { 37 | PrintStream out = context.getResponseStream(); 38 | out.println(WebAppConstants.PAGE_HEADER); 39 | out.println("

    Unable to Update Configuration

    "); 40 | out.println(e.getMessage()); 41 | out.println("

    " + ""); 42 | out.println("
    "); 43 | out.println("
    "); 44 | out.println("
    "); 45 | out.close(); 46 | } 47 | 48 | private static class ConfigurationFormAction extends ConfigurationAction { 49 | 50 | // The action to take. May be either "replace" or "append" 51 | private String effect = DEFAULT_ACTION; 52 | 53 | public ConfigurationFormAction(String contentType, InputStream inputStream) throws IOException { 54 | if (!isMultipartContent(contentType)) throw new RuntimeException("Must be a multi-part request"); 55 | 56 | configure(MultipartContentParser.parse(contentType, inputStream)); 57 | } 58 | 59 | private boolean isMultipartContent(String contentType) { 60 | return contentType.toLowerCase(Locale.ENGLISH).startsWith("multipart/"); 61 | } 62 | 63 | private void configure(List fileItems) throws IOException { 64 | for (MultipartItem item : fileItems) { 65 | if (item.isFormField()) { 66 | if (item.getFieldName().equals(WebAppConstants.EFFECT_OPTION)) 67 | setEffect(item.getString()); 68 | } else { 69 | try (InputStream configStream = item.getInputStream()) { 70 | defineUploadedFile(configStream); 71 | } 72 | } 73 | } 74 | } 75 | 76 | void setEffect(String effect) { 77 | this.effect = effect; 78 | } 79 | 80 | @Override 81 | public void perform() { 82 | if (effect.equalsIgnoreCase(REPLACE_ACTION)) 83 | LiveConfiguration.replaceConfiguration(getUploadedConfig()); 84 | else if (effect.equalsIgnoreCase(APPEND_ACTION)) 85 | LiveConfiguration.appendConfiguration(getUploadedConfig()); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/ConfigurationPutCall.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.net.HttpURLConnection; 9 | import java.util.Arrays; 10 | import java.util.HashSet; 11 | import java.util.Set; 12 | 13 | import com.oracle.wls.exporter.domain.ConfigurationException; 14 | 15 | public class ConfigurationPutCall extends ConfigurationCall { 16 | 17 | private static final Set SUPPORTED_CONTENT_TYPES 18 | = new HashSet<>(Arrays.asList("application/yaml", "text/yaml", "application/json", "text/json")); 19 | 20 | public ConfigurationPutCall(WebClientFactory webClientFactory, InvocationContext context) { 21 | super(webClientFactory, context); 22 | } 23 | 24 | @Override 25 | ConfigurationAction createConfigurationAction(String contentType, InputStream inputStream) { 26 | return new ConfigurationPutAction(contentType, inputStream); 27 | } 28 | 29 | @Override 30 | protected void reportUpdatedConfiguration(InvocationContext context) { 31 | // do nothing 32 | } 33 | 34 | @Override 35 | void reportUnableToUpdateConfiguration(InvocationContext context, ConfigurationException e) throws IOException { 36 | context.sendError(HttpURLConnection.HTTP_BAD_REQUEST, e.getMessage()); 37 | } 38 | 39 | static class ConfigurationPutAction extends ConfigurationAction { 40 | 41 | public ConfigurationPutAction(String contentType, InputStream inputStream) { 42 | if (!isSupportedContentType(contentType)) 43 | throw new ServerErrorException(HttpURLConnection.HTTP_BAD_REQUEST, "Unsupported content type: " + contentType); 44 | 45 | defineUploadedFile(inputStream); 46 | } 47 | 48 | private boolean isSupportedContentType(String contentType) { 49 | return SUPPORTED_CONTENT_TYPES.contains(contentType); 50 | } 51 | 52 | @Override 53 | public void perform() { 54 | LiveConfiguration.replaceConfiguration(getUploadedConfig()); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/ConfigurationUpdate.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2021, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | /** 7 | * An update to the live configuration. This object is exchanged with the config coordinator server in JSON format 8 | * 9 | * @author Russell Gold 10 | */ 11 | public class ConfigurationUpdate { 12 | private final long timestamp; 13 | private final String configuration; 14 | 15 | public ConfigurationUpdate(long timestamp, String configuration) { 16 | this.timestamp = timestamp; 17 | this.configuration = configuration; 18 | } 19 | 20 | public long getTimestamp() { 21 | return timestamp; 22 | } 23 | 24 | String getConfiguration() { 25 | return configuration; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/ConfigurationUpdater.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019, 2021, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | /** 7 | * The means by which the exporter can share its configuration with other instances in a cluster. 8 | * 9 | * @author Russell Gold 10 | */ 11 | public interface ConfigurationUpdater { 12 | 13 | /** 14 | * Returns the timestamp associated with the latest known configuration update. 15 | * @return a timestamp, guaranteed to be non-decreasing across subsequent calls 16 | */ 17 | long getLatestConfigurationTimestamp(); 18 | 19 | /** 20 | * Distribute the specified configuration, with a timestamp indicating when it was created. 21 | * @param configuration a yaml representation of the configuration 22 | */ 23 | void shareConfiguration(String configuration); 24 | 25 | /** 26 | * Returns the latest available update. 27 | * @return an update containing a configuration string and associated timestamp 28 | */ 29 | ConfigurationUpdate getUpdate(); 30 | } 31 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/ErrorLog.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019, 2025, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | public class ErrorLog { 7 | private final StringBuilder errors = new StringBuilder(); 8 | 9 | /** 10 | * Report an exception. 11 | * @param throwable the exception 12 | */ 13 | public void log(Throwable throwable) { 14 | errors.append(toLogMessage(throwable)); 15 | for (Throwable cause = throwable.getCause(); cause != null; cause = cause.getCause()) 16 | errors.append(System.lineSeparator()).append(" ").append(toLogMessage(cause)); 17 | } 18 | 19 | private String toLogMessage(Throwable throwable) { 20 | StringBuilder sb = new StringBuilder(throwable.getClass().getSimpleName()); 21 | if (throwable.getMessage() != null && !throwable.getMessage().trim().isEmpty()) 22 | sb.append(": ").append(throwable.getMessage()); 23 | 24 | return sb.toString(); 25 | } 26 | 27 | /** 28 | * returns the current error log. 29 | * @return a string of errors, separated by line breaks. 30 | */ 31 | public String getErrors() { 32 | return errors.toString(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/ForbiddenException.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2021, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | /** 7 | * An exception thrown when a 403 request is received from the server. 8 | * 9 | * @author Russell Gold 10 | */ 11 | public class ForbiddenException extends WebClientException { 12 | } 13 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/Header.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import java.util.Arrays; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | public class Header { 11 | 12 | public static final String QUOTE = "\""; 13 | private final String name; 14 | private String value; 15 | private final Map parameters = new HashMap<>(); 16 | 17 | public Header(String headerLine) { 18 | String[] split = headerLine.split(":"); 19 | name = split[0].trim(); 20 | if (split.length > 1) 21 | Arrays.stream(split[1].split(";")).forEach(this::parse); 22 | } 23 | 24 | private void parse(String s) { 25 | if (value == null) 26 | value = s.trim(); 27 | else { 28 | String[] split = s.split("="); 29 | if (split.length >= 2) { 30 | parameters.put(trim(split[0]), trim(split[1])); 31 | } 32 | } 33 | } 34 | 35 | private String trim(String value) { 36 | value = value.trim(); 37 | if (value.startsWith(QUOTE) && value.endsWith(QUOTE)) 38 | value = value.substring(1, value.length()-1); 39 | return value; 40 | } 41 | 42 | public String getValue() { 43 | return value; 44 | } 45 | 46 | public String getValue(String key) { 47 | return parameters.get(key); 48 | } 49 | 50 | public String getName() { 51 | return name; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/InvocationContext.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, 2022, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.io.PrintStream; 9 | 10 | /** 11 | * Context for the invocation of AuthenticatedCall objects. This largely acts as a facade for request and response objects. 12 | */ 13 | public interface InvocationContext { 14 | 15 | /** 16 | * Creates an object that will generate an appropriate URL to contact WebLogic. 17 | */ 18 | UrlBuilder createUrlBuilder(); 19 | 20 | /** 21 | * Returns the root context of the exporter application, for use in error messages. 22 | */ 23 | String getApplicationContext(); 24 | 25 | /** 26 | * Returns the authentication header sent to the exporter from the client. It will be passed on to WebLogic. 27 | */ 28 | String getAuthenticationHeader(); 29 | 30 | /** 31 | * Returns the content type of the client request. 32 | */ 33 | String getContentType(); 34 | 35 | /** 36 | * Returns an identifier for the WebLogic Server instance. It will be included in generated metrics. 37 | */ 38 | String getInstanceName(); 39 | 40 | /** 41 | * Returns a stream from which client request contents may be read. 42 | * @throws IOException if unable to get the stream 43 | */ 44 | InputStream getRequestStream() throws IOException; 45 | 46 | /** 47 | * Returns a stream to which responses to the client may be written. 48 | * @throws IOException if unable to get the stream 49 | */ 50 | PrintStream getResponseStream() throws IOException; 51 | 52 | /** 53 | * Updates the response to specify an error code and explanatory message and closes the response stream. 54 | * @param status an HTTP error code 55 | * @param msg a descriptive message 56 | */ 57 | void sendError(int status, String msg) throws IOException; 58 | 59 | /** 60 | * Updates the response to redirect to a new web location and closes he response stream. 61 | * @param location the location, relative to the web application 62 | * @throws IOException if unable to redirect 63 | */ 64 | void sendRedirect(String location) throws IOException; 65 | 66 | /** 67 | * Sets a header on the response. 68 | * @param name the header name 69 | * @param value the value for the header 70 | */ 71 | void setResponseHeader(String name, String value); 72 | 73 | /** 74 | * Updates the response with a status but does not close the response stream. 75 | * @param status an HTTP status code 76 | */ 77 | void setStatus(int status); 78 | 79 | /** 80 | * Closes this context and flushes any pending outputs. 81 | */ 82 | void close(); 83 | } 84 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/JsonEntity.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, 2025, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import java.io.ByteArrayInputStream; 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.io.OutputStream; 10 | import java.nio.charset.Charset; 11 | import java.nio.charset.StandardCharsets; 12 | 13 | import com.google.gson.Gson; 14 | import org.apache.http.Header; 15 | import org.apache.http.HttpEntity; 16 | import org.apache.http.entity.ContentType; 17 | import org.apache.http.message.BasicHeader; 18 | import org.apache.http.protocol.HTTP; 19 | import org.apache.http.util.Args; 20 | 21 | public class JsonEntity implements HttpEntity { 22 | 23 | static final Charset CHARSET = StandardCharsets.UTF_8; 24 | private final byte[] representation; 25 | private final Header contentEncoding; 26 | private final Header contentType; 27 | 28 | public JsonEntity(T item) { 29 | representation = new Gson().toJson(item).getBytes(CHARSET); 30 | contentEncoding = new BasicHeader(HTTP.CONTENT_ENCODING, CHARSET.toString()); 31 | contentType = new BasicHeader(HTTP.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString()); 32 | } 33 | 34 | @Override 35 | public boolean isRepeatable() { 36 | return true; 37 | } 38 | 39 | @Override 40 | public boolean isChunked() { 41 | return false; 42 | } 43 | 44 | @Override 45 | public long getContentLength() { 46 | return representation.length; 47 | } 48 | 49 | @Override 50 | public Header getContentType() { 51 | return contentType; 52 | } 53 | 54 | @Override 55 | public Header getContentEncoding() { 56 | return contentEncoding; 57 | } 58 | 59 | @Override 60 | public InputStream getContent() throws UnsupportedOperationException { 61 | return new ByteArrayInputStream(representation); 62 | } 63 | 64 | @Override 65 | public void writeTo(OutputStream outStream) throws IOException { 66 | Args.notNull(outStream, "Output stream"); 67 | outStream.write(representation); 68 | outStream.flush(); 69 | } 70 | 71 | @Override 72 | public boolean isStreaming() { 73 | return false; 74 | } 75 | 76 | @Override 77 | @Deprecated 78 | public void consumeContent() { 79 | // no-op 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/MessagesCall.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import java.io.IOException; 7 | import java.io.PrintStream; 8 | 9 | public class MessagesCall extends AuthenticatedCall { 10 | 11 | public MessagesCall(WebClientFactory webClientFactory, InvocationContext context) { 12 | super(webClientFactory, context); 13 | } 14 | 15 | @Override 16 | protected void invoke(WebClient webClient, InvocationContext context) throws IOException { 17 | try (PrintStream out = context.getResponseStream()) { 18 | for (String message : WlsRestExchanges.getExchanges()) 19 | out.println(message); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/MultipartItem.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | 9 | /** 10 | * An item in a multi-part http message. Will be either a form field or file data. 11 | * 12 | * @author Russell Gold 13 | */ 14 | interface MultipartItem { 15 | 16 | /** 17 | * Returns true if this item represents a form field. 18 | */ 19 | boolean isFormField(); 20 | 21 | /** 22 | * Returns the name of this field. 23 | */ 24 | String getFieldName(); 25 | 26 | /** 27 | * Returns the value of this item as a string. 28 | */ 29 | String getString(); 30 | 31 | /** 32 | * Returns the value of this item as an input stream. 33 | */ 34 | InputStream getInputStream() throws IOException; 35 | } 36 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/ParserActions.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | public interface ParserActions { 7 | boolean isStart(String line); 8 | 9 | ParserState addHeader(String line); 10 | 11 | ParserState addDataLine(String line); 12 | 13 | boolean isEnd(String line); 14 | 15 | ParserState closeItem(ParserState state); 16 | } 17 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/ParserState.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | public enum ParserState { 7 | INITIAL { 8 | @Override 9 | ParserState processLine(String line, ParserActions actions) { 10 | return actions.isStart(line) ? HEADERS : this; 11 | } 12 | }, 13 | HEADERS { 14 | @Override 15 | ParserState processLine(String line, ParserActions actions) { 16 | if (line.isEmpty()) { 17 | return CONTENT; 18 | } else { 19 | return actions.addHeader(line); 20 | } 21 | } 22 | }, 23 | CONTENT { 24 | @Override 25 | ParserState processLine(String line, ParserActions actions) { 26 | if (actions.isEnd(line)) 27 | return actions.closeItem(DONE); 28 | else if (actions.isStart(line)) 29 | return actions.closeItem(HEADERS); 30 | else 31 | return actions.addDataLine(line); 32 | } 33 | }, 34 | DONE; 35 | 36 | ParserState processLine(String line, ParserActions actions) { 37 | return this; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/RestPortConnectionException.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019, 2020, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | /** 7 | * An exception indicating that the client could not connect to the REST port. 8 | */ 9 | public class RestPortConnectionException extends WebClientException { 10 | 11 | private final String uri; 12 | 13 | public RestPortConnectionException(String uri) { 14 | this.uri = uri; 15 | } 16 | 17 | String getUri() { 18 | return uri; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/RestQueryException.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2020, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | /** 7 | * Thrown when the REST API is unable to handle the query. 8 | * 9 | * @author Russell Gold 10 | */ 11 | class RestQueryException extends WebClientException { 12 | } 13 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/ServerErrorException.java: -------------------------------------------------------------------------------- 1 | // Copyright 2020, 2022, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import java.util.Optional; 7 | 8 | /** 9 | * An exception thrown when a 5xx status code is received from the server. 10 | */ 11 | public class ServerErrorException extends WebClientException { 12 | 13 | final int status; 14 | 15 | public ServerErrorException(int status) { 16 | this.status = status; 17 | } 18 | 19 | public ServerErrorException(int status, String message) { 20 | super(message); 21 | this.status = status; 22 | } 23 | 24 | public int getStatus() { 25 | return status; 26 | } 27 | 28 | @Override 29 | public String getMessage() { 30 | StringBuilder sb = new StringBuilder("Received status ").append(status); 31 | Optional.ofNullable(super.getMessage()).ifPresent(m -> sb.append(" - ").append(m)); 32 | return sb.toString(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/SystemClock.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import java.time.OffsetDateTime; 7 | 8 | /** 9 | * A wrapper for the system clock that facilitates unit testing of time. 10 | */ 11 | public abstract class SystemClock { 12 | 13 | // Leave as non-final; unit tests may replace this value 14 | @SuppressWarnings({"FieldMayBeFinal", "CanBeFinal"}) 15 | private static SystemClock delegate = new SystemClock() { 16 | @Override 17 | public OffsetDateTime getCurrentTime() { 18 | return OffsetDateTime.now(); 19 | } 20 | }; 21 | 22 | /** 23 | * Returns the current time. 24 | * 25 | * @return a time instance 26 | */ 27 | public static OffsetDateTime now() { 28 | return delegate.getCurrentTime(); 29 | } 30 | 31 | /** 32 | * Returns the delegate's current time. 33 | * 34 | * @return a time instance 35 | */ 36 | public abstract OffsetDateTime getCurrentTime(); 37 | } 38 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/WebAppConstants.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2025, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | /** 7 | * Constants needed by multiple servlets. 8 | * 9 | * @author Russell Gold 10 | */ 11 | public interface WebAppConstants { 12 | String PAGE_HEADER 13 | = "\n" + 14 | "\n" + 15 | "\n" + 16 | " \n" + 17 | " Weblogic Monitoring Exporter\n" + 18 | "\n" + 19 | ""; 20 | 21 | // The locations of the servlets relative to the web app 22 | String MAIN_PAGE = ""; 23 | String METRICS_PAGE = "metrics"; 24 | String CONFIGURATION_PAGE = "configure"; 25 | String MESSAGES_PAGE = "messages"; 26 | String LOG_PAGE = "log"; 27 | 28 | /** The header sent by a web server to require authentication. **/ 29 | String AUTHENTICATION_CHALLENGE_HEADER = "WWW-Authenticate"; 30 | 31 | /** The header used by a web server to define a new cookie. **/ 32 | String SET_COOKIE_HEADER = "Set-Cookie"; 33 | 34 | /** The header used by a web client to send its authentication credentials. **/ 35 | String AUTHENTICATION_HEADER = "Authorization"; 36 | 37 | /** The header used by a web client to pass a created cookie to a server. **/ 38 | String COOKIE_HEADER = "Cookie"; 39 | 40 | /** The header used by a web client to specify the content type of its data. **/ 41 | String CONTENT_TYPE_HEADER = "Content-Type"; 42 | 43 | // The field which defines the configuration update action 44 | String EFFECT_OPTION = "effect"; 45 | 46 | // The possible values for the effect 47 | String REPLACE_ACTION = "replace"; 48 | String APPEND_ACTION = "append"; 49 | String DEFAULT_ACTION = REPLACE_ACTION; 50 | } 51 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/WebClient.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2023, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import java.io.IOException; 7 | import java.util.function.Consumer; 8 | 9 | /** 10 | * An interface for an object responsible for sending requests from exporter web application to 11 | * web servers. 12 | * 13 | * @author Russell Gold 14 | */ 15 | public interface WebClient { 16 | 17 | String APPLICATION_JSON = "application/json; charset=UTF-8"; 18 | String X_REQUESTED_BY_HEADER = "X-Requested-By"; 19 | 20 | /** 21 | * Sets the url to which this client will send requests. 22 | * @param url a URL for requests 23 | * @return this instance 24 | */ 25 | WebClient withUrl(String url); 26 | 27 | /** 28 | * Sends a plain GET request to the defined URL without parameters 29 | * @return the body of the response 30 | */ 31 | String doGetRequest() throws IOException; 32 | 33 | /** 34 | * Sends a POST query to the server and returns the reply. 35 | * @param postBody query data 36 | * @return the body of the response 37 | */ 38 | String doPostRequest(String postBody) throws IOException; 39 | 40 | /** 41 | * Converts the specified object to JSON and uses a PUT request to send it to the server. 42 | * @param putBody query data 43 | * @return the reply 44 | */ 45 | @SuppressWarnings("UnusedReturnValue") 46 | String doPutRequest(T putBody) throws IOException; 47 | 48 | /** 49 | * Adds a header to be sent on every query. 50 | * @param name the header name 51 | * @param value the header value 52 | */ 53 | void addHeader(String name, String value); 54 | 55 | /** 56 | * Sets the user credentials to be sent to the server. 57 | * @param authentication the encoded user credentials 58 | */ 59 | void setAuthentication(String authentication); 60 | 61 | /** 62 | * Returns the user credentials defined for this web client. 63 | */ 64 | String getAuthentication(); 65 | 66 | /** 67 | * Set a flag to indicate that a retry of the request will be needed. Typically this means that the previous 68 | * request did not reach a server, and new port should be tried. 69 | */ 70 | void setRetryNeeded(); 71 | 72 | /** 73 | * Returns true if this client has been marked to retry the last request. 74 | */ 75 | boolean isRetryNeeded(); 76 | 77 | /** 78 | * Defines a handler to be called when a Set-Cookie header is found in a reply from the server. 79 | * @param setCookieHandler the handler to call with the value of the header 80 | */ 81 | void onSetCookieReceivedDo(Consumer setCookieHandler); 82 | 83 | 84 | interface Response { 85 | String getBody() throws IOException; 86 | 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/WebClientException.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2021, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | /** 7 | * An exception generated by the web client. 8 | */ 9 | public class WebClientException extends RuntimeException { 10 | WebClientException() {} 11 | 12 | public WebClientException(String message) { 13 | super(message); 14 | } 15 | 16 | WebClientException(Throwable cause, String message, Object... args) { 17 | super(formatMessage(message, args), cause); 18 | } 19 | 20 | WebClientException(String message, Object... args) { 21 | super(formatMessage(message, args)); 22 | } 23 | 24 | private static String formatMessage(String message, Object... args) { 25 | return String.format(message, args); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/WebClientFactory.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2020, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | /** 7 | * An interface for creating web clients. 8 | * 9 | * @author Russell Gold 10 | */ 11 | public interface WebClientFactory { 12 | 13 | /** 14 | * Creates a client which will send queries to a specified URL 15 | */ 16 | WebClient createClient(); 17 | } 18 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/WebClientFactoryImpl.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2025, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import java.lang.reflect.Constructor; 7 | import java.lang.reflect.InvocationTargetException; 8 | import java.util.function.Function; 9 | 10 | /** 11 | * The production implementation of the web client factory interface. 12 | * 13 | * @author Russell Gold 14 | */ 15 | public class WebClientFactoryImpl implements WebClientFactory { 16 | 17 | static final String APACHE_BASED_CLIENT = "com.oracle.wls.exporter.WebClientImpl"; 18 | static final String JDK_BASED_CLIENT = "com.oracle.wls.exporter.WebClient8Impl"; 19 | static final String[] CLIENT_CLASS_NAMES = {APACHE_BASED_CLIENT, JDK_BASED_CLIENT}; 20 | 21 | static Constructor clientConstructor; 22 | static Function> loadClientClass = WebClientFactoryImpl::getClientClass; 23 | 24 | static { 25 | clientConstructor = getClientConstructor(); 26 | } 27 | 28 | static Constructor getClientConstructor() { 29 | for (String className : CLIENT_CLASS_NAMES) { 30 | try { 31 | return getClientConstructor(className); 32 | } catch (NoClassDefFoundError | NoSuchMethodException ignored) { 33 | // no-op 34 | } 35 | } 36 | 37 | throw new IllegalStateException("Unable to select client constructor"); 38 | } 39 | 40 | private static Constructor getClientConstructor(String clientClassName) 41 | throws NoSuchMethodException { 42 | return loadClientClass.apply(clientClassName).getDeclaredConstructor(); 43 | } 44 | 45 | @SuppressWarnings("unchecked") 46 | private static Class getClientClass(String clientClassName) { 47 | try { 48 | return (Class) Class.forName(clientClassName); 49 | } catch (ClassNotFoundException e) { 50 | throw new NoClassDefFoundError(e.getMessage()); 51 | } 52 | } 53 | 54 | private static boolean isApacheClientAvailable() { 55 | try { 56 | Class.forName("org.apache.http.HttpEntity"); 57 | return true; 58 | } catch (ClassNotFoundException e) { 59 | return false; 60 | } 61 | } 62 | 63 | @Override 64 | public WebClient createClient() { 65 | try { 66 | return clientConstructor.newInstance(); 67 | } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { 68 | throw new IllegalStateException("Unable to instantiate client class", e); 69 | } 70 | } 71 | 72 | 73 | } 74 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/WlsRestExchanges.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, 2025, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import java.nio.charset.Charset; 7 | import java.time.Duration; 8 | import java.time.OffsetDateTime; 9 | import java.util.List; 10 | import java.util.Queue; 11 | import java.util.concurrent.ConcurrentLinkedDeque; 12 | import java.util.stream.Collectors; 13 | 14 | import static java.time.format.DateTimeFormatter.ISO_LOCAL_TIME; 15 | 16 | /** 17 | * A diagnostic class that records requests sent to WLS and the replies received. 18 | */ 19 | public class WlsRestExchanges { 20 | 21 | public static final int MAX_EXCHANGES = 5; 22 | private static final String TEMPLATE = "At %s, REQUEST to %s:%n%s%nREPLY:%n%s%n"; 23 | 24 | private static final Queue exchanges = new ConcurrentLinkedDeque<>(); 25 | static final int TEN_MINUTES = 10; 26 | 27 | private static class Exchange { 28 | private final OffsetDateTime time; 29 | private final String url; 30 | private final String request; 31 | private final String response; 32 | 33 | Exchange(String url, String request, String response) { 34 | this.time = SystemClock.now(); 35 | this.url = url; 36 | this.request = request; 37 | this.response = response; 38 | } 39 | 40 | private String getContent() { 41 | return String.format(TEMPLATE, ISO_LOCAL_TIME.format(time), url, request, response); 42 | } 43 | 44 | private int getContentLength() { 45 | return getContent().getBytes(Charset.defaultCharset()).length; 46 | } 47 | 48 | private boolean isWithinTenMinutes() { 49 | return Duration.between(time, SystemClock.now()).toMinutes() <= TEN_MINUTES; 50 | } 51 | } 52 | 53 | private WlsRestExchanges() { 54 | } 55 | 56 | /** 57 | * Returns a list of the most recent exchanges. 58 | */ 59 | public static List getExchanges() { 60 | return exchanges.stream().map(Exchange::getContent).collect(Collectors.toList()); 61 | } 62 | 63 | /** 64 | * Adds an exchange for later retrieval 65 | * @param url the URL of the WLS instance 66 | * @param request the request JSON string 67 | * @param response the returned JSON string 68 | */ 69 | public static void addExchange(String url, String request, String response) { 70 | exchanges.add(new Exchange(url, request, response)); 71 | if (exchanges.size() > MAX_EXCHANGES) exchanges.remove(); 72 | } 73 | 74 | /** 75 | * Clears the set of recorded exchanges. Intended for unit testing. 76 | */ 77 | public static void clear() { 78 | exchanges.clear(); 79 | } 80 | 81 | public static int getMessageAllocation() { 82 | return exchanges.stream().map(Exchange::getContentLength).reduce(Integer::sum).orElse(0); 83 | } 84 | 85 | public static int getMaximumExchangeLength() { 86 | return exchanges.stream().map(Exchange::getContentLength).reduce(Math::max).orElse(0); 87 | } 88 | 89 | public static int getTotalExchangeLengthOverPastTenMinutes() { 90 | return exchanges.stream().filter(Exchange::isWithinTenMinutes).map(Exchange::getContentLength).reduce(Integer::sum).orElse(0); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/domain/ConfigurationException.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2022, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.domain; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * An exception thrown if there is a problem with the exporter configuration. 11 | * 12 | * @author Russell Gold 13 | */ 14 | public class ConfigurationException extends RuntimeException { 15 | public static final String BAD_YAML_FORMAT = "Configuration YAML format has errors"; 16 | public static final String NOT_YAML_FORMAT = "Configuration is not in YAML format"; 17 | static final String NO_QUERY_SYNC_URL = "query_sync defined without url"; 18 | private final List context = new ArrayList<>(); 19 | 20 | public ConfigurationException(String description) { 21 | super(description); 22 | } 23 | 24 | void addContext(String parentContext) { 25 | context.add(0, parentContext); 26 | } 27 | 28 | @Override 29 | public String getMessage() { 30 | StringBuilder sb = new StringBuilder(super.getMessage()); 31 | if (!context.isEmpty()) 32 | sb.append(" at ").append(String.join(".", context)); 33 | return sb.toString(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/domain/MetricsProcessor.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.domain; 5 | 6 | import java.util.Map; 7 | 8 | interface MetricsProcessor { 9 | 10 | /** 11 | * Uses the specified metrics to update configuration information. 12 | * @param metrics a set of data scraped from a WebLogic Server response 13 | */ 14 | void updateConfiguration(Map metrics); 15 | } 16 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/domain/Protocol.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, 2023, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.domain; 5 | 6 | public enum Protocol { 7 | HTTP, HTTPS; 8 | 9 | public String format(String urlPattern, String hostName, int port) { 10 | if (hostName.contains(":")) { 11 | hostName = "[" + hostName + "]"; 12 | } 13 | return String.format(urlPattern, toString().toLowerCase(), hostName, port); 14 | } 15 | 16 | public static Protocol getProtocol(boolean secure) { 17 | return secure ? HTTPS : HTTP; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/domain/QuerySyncConfiguration.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2025, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.domain; 5 | 6 | import java.util.Map; 7 | /** 8 | * Configuration for synchronization of queries 9 | */ 10 | public class QuerySyncConfiguration { 11 | private static final String URL_KEY = "url"; 12 | private static final String REFRESH_INTERVAL = "interval"; 13 | private static final long DEFAULT_REFRESH_INTERVAL = 10; 14 | 15 | private final String url; 16 | private final long refreshInterval; 17 | 18 | QuerySyncConfiguration(Map map) { 19 | if (map == null || !map.containsKey(URL_KEY)) 20 | throw new ConfigurationException(ConfigurationException.NO_QUERY_SYNC_URL); 21 | 22 | url = MapUtils.getStringValue(map, URL_KEY); 23 | refreshInterval = map.containsKey(REFRESH_INTERVAL) 24 | ? MapUtils.getIntegerValue(map, REFRESH_INTERVAL) 25 | : DEFAULT_REFRESH_INTERVAL; 26 | } 27 | 28 | public String getUrl() { 29 | return url; 30 | } 31 | 32 | public long getRefreshInterval() { 33 | return refreshInterval; 34 | } 35 | 36 | @Override 37 | public String toString() { 38 | return "query_sync:\n" + 39 | " url: " + url + '\n' + 40 | " refreshInterval: " + refreshInterval + '\n'; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/domain/QueryType.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019, 2022, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.domain; 5 | 6 | import java.util.Map; 7 | 8 | public enum QueryType { 9 | RUNTIME { 10 | @Override 11 | public String getUrlPattern() { 12 | return RUNTIME_URL_PATTERN; 13 | } 14 | 15 | @Override 16 | public boolean acceptsStrings() { 17 | return false; 18 | } 19 | 20 | @Override 21 | public void postProcessMetrics(Map metrics, MetricsProcessor processor) { 22 | // do nothing 23 | } 24 | }, 25 | CONFIGURATION { 26 | @Override 27 | public String getUrlPattern() { 28 | return CONFIGURATION_URL_PATTERN; 29 | } 30 | 31 | @Override 32 | public boolean acceptsStrings() { 33 | return true; 34 | } 35 | 36 | @Override 37 | public void postProcessMetrics(Map metrics, MetricsProcessor processor) { 38 | processor.updateConfiguration(metrics); 39 | } 40 | }; 41 | 42 | 43 | /** 44 | * The pattern for a URL to which runtime REST queries are made. 45 | */ 46 | public static final String RUNTIME_URL_PATTERN = "%s://%s:%d/management/weblogic/latest/serverRuntime/search"; 47 | 48 | /** 49 | * The pattern for a URL to which configuration REST queries are made. 50 | */ 51 | public static final String CONFIGURATION_URL_PATTERN = "%s://%s:%d/management/weblogic/latest/serverConfig/search"; 52 | static final String DOMAIN_KEY = "name"; 53 | 54 | /** 55 | * Returns the appropriate pattern to create a URL string. 56 | * 57 | * @return a pattern on which to call {@link String#format(String, Object...)} 58 | */ 59 | public abstract String getUrlPattern(); 60 | 61 | public abstract boolean acceptsStrings(); 62 | 63 | public abstract void postProcessMetrics(Map metrics, MetricsProcessor processor); 64 | } 65 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/domain/SnakeCaseUtil.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2022, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.domain; 5 | 6 | import java.util.regex.Pattern; 7 | 8 | /** 9 | * A class which can convert strings from camel case to snake case. 10 | * 11 | * @author Russell Gold 12 | */ 13 | public class SnakeCaseUtil { 14 | 15 | private SnakeCaseUtil() { 16 | // no-op 17 | } 18 | 19 | private static final Pattern SNAKE_CASE_PATTERN = Pattern.compile("([a-z0-9])([A-Z])"); 20 | 21 | static String convert(String s) { 22 | return SNAKE_CASE_PATTERN.matcher(s).replaceAll("$1_$2").toLowerCase(); 23 | } 24 | 25 | public static boolean isCompliant(String s) { 26 | return s.equals(convert(s)); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/domain/YamlParserException.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2020, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.domain; 5 | 6 | import org.yaml.snakeyaml.scanner.ScannerException; 7 | 8 | /** 9 | * An exception thrown when there is an error parsing the YAML. 10 | * 11 | * @author Russell Gold 12 | */ 13 | public class YamlParserException extends ConfigurationException { 14 | private final ScannerException scannerException; 15 | 16 | YamlParserException(ScannerException scannerException) { 17 | super(BAD_YAML_FORMAT); 18 | this.scannerException = scannerException; 19 | } 20 | 21 | @Override 22 | public String getMessage() { 23 | return super.getMessage() + '\n' + scannerException.getMessage(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/javax/ConfigurationServlet.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2025, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.javax; 5 | 6 | import java.io.IOException; 7 | import javax.servlet.ServletException; 8 | import javax.servlet.annotation.WebServlet; 9 | import javax.servlet.http.HttpServlet; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | 13 | import com.oracle.wls.exporter.CallFactory; 14 | import com.oracle.wls.exporter.CallFactoryServletImpl; 15 | import com.oracle.wls.exporter.WebAppConstants; 16 | import com.oracle.wls.exporter.WebClientFactory; 17 | import com.oracle.wls.exporter.WebClientFactoryImpl; 18 | 19 | /** 20 | * A servlet which handles updates to the exporter configuration. 21 | * 22 | * @author Russell Gold 23 | */ 24 | @WebServlet(value = "/" + WebAppConstants.CONFIGURATION_PAGE) 25 | public class ConfigurationServlet extends HttpServlet { 26 | 27 | private final CallFactory callFactory; 28 | 29 | @SuppressWarnings("unused") // production constructor 30 | public ConfigurationServlet() { 31 | this(new WebClientFactoryImpl()); 32 | } 33 | 34 | ConfigurationServlet(WebClientFactory webClientFactory) { 35 | this.callFactory = new CallFactoryServletImpl(webClientFactory); 36 | } 37 | 38 | @Override 39 | public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 40 | try { 41 | ServletUtils.setServer(request); 42 | callFactory.invokeConfigurationFormCall(new ServletInvocationContext(request, response)); 43 | } catch (RuntimeException e) { 44 | throw new ServletException(e); 45 | } 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/javax/ExporterServlet.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2025, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.javax; 5 | 6 | import java.io.IOException; 7 | import javax.servlet.ServletConfig; 8 | import javax.servlet.annotation.WebServlet; 9 | import javax.servlet.http.HttpServlet; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | 13 | import com.oracle.wls.exporter.ExporterCall; 14 | import com.oracle.wls.exporter.WebAppConstants; 15 | import com.oracle.wls.exporter.WebClientFactory; 16 | import com.oracle.wls.exporter.WebClientFactoryImpl; 17 | 18 | /** 19 | * The servlet which produces the exported metrics. 20 | * 21 | * @author Russell Gold 22 | */ 23 | @WebServlet(value = "/" + WebAppConstants.METRICS_PAGE) 24 | public class ExporterServlet extends HttpServlet { 25 | 26 | private final WebClientFactory webClientFactory; 27 | 28 | @SuppressWarnings("unused") // production constructor 29 | public ExporterServlet() { 30 | this(new WebClientFactoryImpl()); 31 | } 32 | 33 | public ExporterServlet(WebClientFactory webClientFactory) { 34 | this.webClientFactory = webClientFactory; 35 | } 36 | 37 | @Override 38 | public void init(ServletConfig servletConfig) { 39 | ServletUtils.initializeConfiguration(servletConfig); 40 | } 41 | 42 | @Override 43 | public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { 44 | ServletUtils.setServer(req); 45 | ExporterCall call = new ExporterCall(webClientFactory, new ServletInvocationContext(req, resp)); 46 | call.doWithAuthentication(); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/javax/LogServlet.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2021, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.javax; 5 | 6 | import java.io.IOException; 7 | import javax.servlet.annotation.WebServlet; 8 | import javax.servlet.http.HttpServlet; 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | 12 | import com.oracle.wls.exporter.LiveConfiguration; 13 | import com.oracle.wls.exporter.WebAppConstants; 14 | 15 | @WebServlet(value = "/" + WebAppConstants.LOG_PAGE) 16 | public class LogServlet extends HttpServlet { 17 | @Override 18 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { 19 | String errors = LiveConfiguration.getErrors(); 20 | if (errors == null || errors.trim().isEmpty()) 21 | resp.getOutputStream().println("No errors reported."); 22 | else 23 | resp.getOutputStream().println("
    " + errors + "
    "); 24 | 25 | resp.getOutputStream().close(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/javax/MessagesServlet.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019, 2025, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.javax; 5 | 6 | import java.io.IOException; 7 | import javax.servlet.annotation.WebServlet; 8 | import javax.servlet.http.HttpServlet; 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | 12 | import com.oracle.wls.exporter.MessagesCall; 13 | import com.oracle.wls.exporter.WebClientFactory; 14 | import com.oracle.wls.exporter.WebClientFactoryImpl; 15 | 16 | import static com.oracle.wls.exporter.WebAppConstants.MESSAGES_PAGE; 17 | 18 | /** 19 | * A collector of REST requests and replies, that can be viewed to diagnose problems. 20 | */ 21 | @WebServlet("/" + MESSAGES_PAGE) 22 | public class MessagesServlet extends HttpServlet { 23 | 24 | private final WebClientFactory webClientFactory; 25 | 26 | @SuppressWarnings("unused") 27 | public MessagesServlet() { 28 | this(new WebClientFactoryImpl()); 29 | } 30 | 31 | public MessagesServlet(WebClientFactory webClientFactory) { 32 | this.webClientFactory = webClientFactory; 33 | } 34 | 35 | @Override 36 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { 37 | try { 38 | ServletUtils.setServer(req); 39 | MessagesCall call = new MessagesCall(webClientFactory, new ServletInvocationContext(req, resp)); 40 | call.doWithAuthentication(); 41 | } catch (IOException e) { 42 | resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); 43 | } 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /wls-exporter-core/src/main/java/com/oracle/wls/exporter/javax/ServletUtils.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, 2025, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.javax; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import javax.servlet.ServletConfig; 9 | import javax.servlet.http.HttpServletRequest; 10 | 11 | import com.oracle.wls.exporter.LiveConfiguration; 12 | 13 | /** 14 | * Some methods used by multiple servlets. 15 | */ 16 | public class ServletUtils { 17 | 18 | private ServletUtils() { 19 | // no-op 20 | } 21 | 22 | /** The path to the configuration file within the web application. */ 23 | public static final String CONFIG_YML = "/config.yml"; 24 | 25 | /** 26 | * Specifies the server on which to contact the Management RESTful services. 27 | * 28 | * @param req the incoming request 29 | */ 30 | public static void setServer(HttpServletRequest req) { 31 | LiveConfiguration.setServer(req.getServerName(), req.getServerPort()); 32 | } 33 | 34 | /** 35 | * Loads the initial configuration during servlet load. Will skip the initialization if the configuration 36 | * has already been loaded from the config coordinator. 37 | * 38 | * @param servletConfig a standard servlet configuration which points to an exporter configuration 39 | */ 40 | public static void initializeConfiguration(ServletConfig servletConfig) { 41 | try (InputStream configurationFile = getConfigurationFile(servletConfig)) { 42 | LiveConfiguration.initialize(configurationFile); 43 | } catch (IOException ignored) { 44 | // this is called only once, when the web application starts up, so if it fails to close, we can ignore it. 45 | } 46 | } 47 | 48 | private static InputStream getConfigurationFile(ServletConfig config) { 49 | return config.getServletContext().getResourceAsStream(CONFIG_YML); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java/com/oracle/wls/exporter/ClockStub.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, 2025, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import java.time.Clock; 7 | import java.time.Instant; 8 | 9 | /** 10 | * A unit-test implementation of the Clock interface. 11 | */ 12 | public abstract class ClockStub extends Clock { 13 | private long currentMsec = 1000L; 14 | 15 | public void setCurrentMsec(long currentMsec) { 16 | this.currentMsec = currentMsec; 17 | } 18 | 19 | public void incrementSeconds(long seconds) { 20 | this.currentMsec += 1000 * seconds; 21 | } 22 | 23 | @Override 24 | public Instant instant() { 25 | return Instant.ofEpochMilli(currentMsec); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java/com/oracle/wls/exporter/ConfigurationPutCallTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, 2022, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import java.io.IOException; 7 | import java.net.HttpURLConnection; 8 | 9 | import org.junit.jupiter.api.BeforeEach; 10 | import org.junit.jupiter.api.Test; 11 | 12 | import static com.oracle.wls.exporter.InvocationContextStub.HOST_NAME; 13 | import static com.oracle.wls.exporter.InvocationContextStub.PORT; 14 | import static org.hamcrest.MatcherAssert.assertThat; 15 | import static org.hamcrest.Matchers.equalTo; 16 | 17 | class ConfigurationPutCallTest { 18 | 19 | private static final String BAD_BOOLEAN_STRING = "blabla"; 20 | private static final String YAML_CONFIGURATION = 21 | "hostName: " + HOST_NAME + "\n" + 22 | "port: " + PORT + "\n" + 23 | "queries:\n" + "" + 24 | "- groups:\n" + 25 | " prefix: new_\n" + 26 | " key: name\n" + 27 | " values: [sample1, sample2]\n"; 28 | private static final String JSON_CONFIGURATION = replaceQuotes( 29 | "{'queries': [{'groups':" 30 | + "{'prefix':'new_', 'key':'name', 'values': ['sample1','sample2']}" 31 | + "}]}"); 32 | 33 | private static final String NO_CONFIGURATION = ""; 34 | private final WebClientFactoryStub factory = new WebClientFactoryStub(); 35 | private final InvocationContextStub context = InvocationContextStub.create(); 36 | 37 | @SuppressWarnings("SameParameterValue") 38 | private static String replaceQuotes(String in) { 39 | return in.replace("'", "\""); 40 | } 41 | 42 | @BeforeEach 43 | void setUp() { 44 | LiveConfiguration.setServer(HOST_NAME, PORT); 45 | LiveConfiguration.loadFromString(NO_CONFIGURATION); 46 | } 47 | 48 | @Test 49 | void whenBadRequestContentType_reportFailure() throws IOException { 50 | handleConfigurationPutCall(context.withConfiguration("text/xml", YAML_CONFIGURATION)); 51 | 52 | assertThat(context.getResponseStatus(), equalTo(HttpURLConnection.HTTP_BAD_REQUEST)); 53 | } 54 | 55 | private void handleConfigurationPutCall(InvocationContextStub context) throws IOException { 56 | final ConfigurationPutCall call = new ConfigurationPutCall(factory, context); 57 | 58 | call.doWithAuthentication(); 59 | } 60 | 61 | @Test 62 | void whenSpecifiedConfigurationHasBadBooleanValue_reportError() throws Exception { 63 | handleConfigurationPutCall(context.withConfiguration("application/yaml", CONFIGURATION_WITH_BAD_BOOLEAN)); 64 | 65 | assertThat(context.getResponseStatus(), equalTo(HttpURLConnection.HTTP_BAD_REQUEST)); 66 | } 67 | 68 | @Test 69 | void updateSpecifiedConfiguration() throws Exception { 70 | handleConfigurationPutCall(context.withConfiguration("application/yaml", YAML_CONFIGURATION)); 71 | 72 | assertThat(LiveConfiguration.asString(), equalTo(YAML_CONFIGURATION)); 73 | } 74 | 75 | @Test 76 | void updateConfigurationWithJson() throws Exception { 77 | handleConfigurationPutCall(context.withConfiguration("application/json", JSON_CONFIGURATION)); 78 | 79 | assertThat(LiveConfiguration.asString(), equalTo(YAML_CONFIGURATION)); 80 | } 81 | 82 | private static final String CONFIGURATION_WITH_BAD_BOOLEAN = 83 | "metricsNameSnakeCase: " + BAD_BOOLEAN_STRING + "\n" + 84 | "queries:\n" + "" + 85 | "- people:\n" + 86 | " key: name\n" + 87 | " values: [age, sex]\n"; 88 | } -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java/com/oracle/wls/exporter/ConfigurationUpdaterStub.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2021, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import com.meterware.simplestub.Memento; 7 | import com.meterware.simplestub.StaticStubSupport; 8 | 9 | import static com.meterware.simplestub.Stub.createStrictStub; 10 | 11 | public abstract class ConfigurationUpdaterStub implements ConfigurationUpdater { 12 | private static Memento memento; 13 | private static ConfigurationUpdaterStub updaterStub; 14 | 15 | private String sharedConfiguration; 16 | private ConfigurationUpdate update; 17 | 18 | protected ConfigurationUpdaterStub() { 19 | } 20 | 21 | public static void install() throws NoSuchFieldException { 22 | updaterStub = createStrictStub(ConfigurationUpdaterStub.class); 23 | memento = StaticStubSupport.install(LiveConfiguration.class, "updater", updaterStub); 24 | } 25 | 26 | public static void uninstall() { 27 | memento.revert(); 28 | } 29 | 30 | static String getSharedConfiguration() { 31 | return updaterStub.sharedConfiguration; 32 | } 33 | 34 | public static void newConfiguration(long newTimestamp, String configuration) { 35 | updaterStub.update = new ConfigurationUpdate(newTimestamp, configuration); 36 | } 37 | 38 | @Override 39 | public long getLatestConfigurationTimestamp() { 40 | return update == null ? 0 : update.getTimestamp(); 41 | } 42 | 43 | @Override 44 | public void shareConfiguration(String configuration) { 45 | sharedConfiguration = configuration; 46 | update = new ConfigurationUpdate(1, configuration); 47 | } 48 | 49 | @Override 50 | public ConfigurationUpdate getUpdate() { 51 | return update; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java/com/oracle/wls/exporter/ErrorLogTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019, 2022, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.IOException; 8 | import java.io.StringReader; 9 | import java.util.ArrayList; 10 | import java.util.Arrays; 11 | import java.util.List; 12 | 13 | import org.hamcrest.Description; 14 | import org.hamcrest.TypeSafeDiagnosingMatcher; 15 | import org.junit.jupiter.api.Test; 16 | 17 | import static com.oracle.wls.exporter.ErrorLogTest.LogMatcher.containsErrors; 18 | import static org.hamcrest.MatcherAssert.assertThat; 19 | 20 | class ErrorLogTest { 21 | private final ErrorLog errorLog = new ErrorLog(); 22 | 23 | @Test 24 | void afterExceptionReported_isAddedToLog() { 25 | errorLog.log(new IOException("Unable to read value")); 26 | 27 | assertThat(errorLog, containsErrors("IOException: Unable to read value")); 28 | } 29 | 30 | @Test 31 | void afterExceptionWithNoMessageReported_logSimpleNameOnly() { 32 | errorLog.log(new IOException()); 33 | 34 | assertThat(errorLog, containsErrors("IOException")); 35 | } 36 | 37 | @Test 38 | void afterExceptionWithNestedThrowableReported_addToLog() { 39 | errorLog.log(new IOException("Unable to read value", new RuntimeException("has impossible format"))); 40 | 41 | assertThat(errorLog, containsErrors("IOException: Unable to read value", " RuntimeException: has impossible format")); 42 | } 43 | 44 | @SuppressWarnings("unused") 45 | static class LogMatcher extends TypeSafeDiagnosingMatcher { 46 | private final String[] expectedMessages; 47 | 48 | private LogMatcher(String[] expectedMessages) { 49 | this.expectedMessages = expectedMessages; 50 | } 51 | 52 | static LogMatcher containsErrors(String... expectedMessages) { 53 | return new LogMatcher(expectedMessages); 54 | } 55 | 56 | @Override 57 | protected boolean matchesSafely(ErrorLog errorLog, Description description) { 58 | String[] actualMessages = getActualMessages(errorLog); 59 | if (Arrays.equals(expectedMessages, actualMessages)) return true; 60 | 61 | description.appendValueList("[", ",", "]", actualMessages); 62 | return false; 63 | } 64 | 65 | private String[] getActualMessages(ErrorLog errorLog) { 66 | try { 67 | List actualMessages = new ArrayList<>(); 68 | String line; 69 | BufferedReader reader = new BufferedReader(new StringReader(errorLog.getErrors())); 70 | while ((line = reader.readLine()) != null) actualMessages.add(line); 71 | return actualMessages.toArray(new String[0]); 72 | } catch (IOException e) { 73 | return new String[0]; 74 | } 75 | } 76 | 77 | @Override 78 | public void describeTo(Description description) { 79 | description.appendValueList("[", ",", "]", expectedMessages); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java/com/oracle/wls/exporter/HeaderTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, 2022, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import org.junit.jupiter.api.Test; 7 | 8 | import static org.hamcrest.MatcherAssert.assertThat; 9 | import static org.hamcrest.Matchers.equalTo; 10 | 11 | class HeaderTest { 12 | 13 | @Test 14 | void fetchHeaderName() { 15 | Header header = new Header("Content-type: text/plain"); 16 | 17 | assertThat(header.getName(), equalTo("Content-type")); 18 | } 19 | 20 | @Test 21 | void fetchMainValue() { 22 | Header header = new Header("Content-type: text/plain"); 23 | 24 | assertThat(header.getValue(), equalTo("text/plain")); 25 | } 26 | 27 | @Test 28 | void whenSeparatorPresent_truncateValue() { 29 | Header header = new Header("Content-type: text/plain; more stuff"); 30 | 31 | assertThat(header.getValue(), equalTo("text/plain")); 32 | } 33 | 34 | @Test 35 | void whenParametersPresent_fetchValues() { 36 | Header header = new Header("Content-disposition: form-data; name=\"file1\"; filename=\"a.txt\""); 37 | 38 | assertThat(header.getValue(), equalTo("form-data")); 39 | assertThat(header.getValue("name"), equalTo("file1")); 40 | assertThat(header.getValue("filename"), equalTo("a.txt")); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java/com/oracle/wls/exporter/InMemoryResources.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2025, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import com.google.common.collect.ImmutableMap; 7 | import com.meterware.simplestub.Memento; 8 | import com.meterware.simplestub.StaticStubSupport; 9 | import com.oracle.wls.exporter.javax.ServletUtils; 10 | 11 | import javax.servlet.ServletConfig; 12 | import javax.servlet.ServletContext; 13 | import java.io.ByteArrayInputStream; 14 | import java.io.InputStream; 15 | import java.util.ArrayList; 16 | import java.util.HashMap; 17 | import java.util.List; 18 | import java.util.Map; 19 | 20 | import static com.meterware.simplestub.Stub.createStrictStub; 21 | 22 | /** 23 | * @author Russell Gold 24 | */ 25 | public class InMemoryResources { 26 | private static Map resources; 27 | private static final List mementos = new ArrayList<>(); 28 | 29 | public static void install() throws NoSuchFieldException { 30 | resources = new HashMap<>(); 31 | mementos.add(StaticStubSupport.install(LiveConfiguration.class, "config", null)); 32 | mementos.add(StaticStubSupport.install(LiveConfiguration.class, "timestamp", null)); 33 | } 34 | 35 | public static void uninstall() { 36 | for (Memento memento : mementos) memento.revert(); 37 | } 38 | 39 | public static ServletConfig withNoParams() { 40 | return createStrictStub(ServletConfigStub.class, ImmutableMap.of()); 41 | } 42 | 43 | @SuppressWarnings("SameParameterValue") 44 | public static void defineResource(String filePath, String contents) { 45 | resources.put(filePath, toInputStream(contents)); 46 | } 47 | 48 | private static InputStream toInputStream(String contents) { 49 | return new ByteArrayInputStream(contents.getBytes()); 50 | } 51 | 52 | abstract static class ServletConfigStub implements ServletConfig { 53 | 54 | private final Map params; 55 | private final ServletContext context; 56 | 57 | ServletConfigStub(Map params) { 58 | this.params = params; 59 | context = createStrictStub(ServletContextStub.class); 60 | } 61 | 62 | @Override 63 | public String getInitParameter(String s) { 64 | return params.get(s); 65 | } 66 | 67 | @Override 68 | public ServletContext getServletContext() { 69 | return context; 70 | } 71 | 72 | } 73 | 74 | abstract static class ServletContextStub implements ServletContext { 75 | 76 | @Override 77 | public InputStream getResourceAsStream(String path) { 78 | return !ServletUtils.CONFIG_YML.equals(path) ? null : InMemoryResources.resources.get(path); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java/com/oracle/wls/exporter/ItemHolder.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2020, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | import java.util.Map; 9 | 10 | /** 11 | * A class to provide the "items" potion of the json REST query. 12 | * 13 | * @author Russell Gold 14 | */ 15 | @SuppressWarnings("rawtypes") 16 | class ItemHolder { 17 | ItemHolder(Map... maps) { 18 | items.addAll(Arrays.asList(maps)); 19 | } 20 | 21 | @SuppressWarnings({"FieldCanBeLocal", "MismatchedQueryAndUpdateOfCollection"}) 22 | private final ArrayList items = new ArrayList<>(); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java/com/oracle/wls/exporter/MultipartTestUtils.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, 2025, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.nio.charset.Charset; 9 | 10 | import com.oracle.wls.exporter.javax.HttpServletRequestStub; 11 | import org.apache.http.HttpEntity; 12 | import org.apache.http.entity.ContentType; 13 | import org.apache.http.entity.mime.MultipartEntityBuilder; 14 | 15 | import static com.oracle.wls.exporter.javax.HttpServletRequestStub.createPostRequest; 16 | 17 | public class MultipartTestUtils { 18 | 19 | private static final String BOUNDARY = "C3n5NKoslNBKj4wBHR8kCX6OtVYEqeFYNjorlBP"; 20 | 21 | public static HttpServletRequestStub createUploadRequest(String contents) { 22 | return createPostRequest().withMultipartContent(contents, BOUNDARY); 23 | } 24 | 25 | public static String getContentType() { 26 | return "multipart/form-data; boundary=" + BOUNDARY; 27 | } 28 | 29 | public static String createEncodedForm(String effect, String configuration) throws IOException { 30 | MultipartEntityBuilder builder = MultipartEntityBuilder.create(); 31 | builder.setBoundary(BOUNDARY); 32 | builder.addTextBody("effect", effect); 33 | builder.addBinaryBody("configuration", configuration.getBytes(), ContentType.create("text/plain", Charset.defaultCharset()), "newconfig.yml"); 34 | HttpEntity entity = builder.build(); 35 | return asString(entity); 36 | } 37 | 38 | @SuppressWarnings("ResultOfMethodCallIgnored") 39 | static String asString(HttpEntity entity) throws IOException { 40 | byte[] result = new byte[(int) entity.getContentLength()]; 41 | InputStream inputStream = entity.getContent(); 42 | inputStream.read(result); 43 | return new String(result); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java/com/oracle/wls/exporter/ResponseDemo.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2020, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import java.util.Map; 7 | 8 | import com.google.common.collect.ImmutableMap; 9 | import com.google.gson.GsonBuilder; 10 | 11 | /** 12 | * @author Russell Gold 13 | */ 14 | public class ResponseDemo { 15 | 16 | public static void main(String... args) { 17 | Map map3 = ImmutableMap.of("deploymentState", 2, "name", "EjbStatusBean", "type", "EJBComponentRuntime"); 18 | ItemHolder items2 = new ItemHolder(map3); 19 | Map map1 = ImmutableMap.of("internal", "false", "name", "mbeans", "componentRuntimes", items2); 20 | ItemHolder items0 = new ItemHolder(map1); 21 | 22 | System.out.println(new GsonBuilder().setPrettyPrinting().create().toJson( 23 | ImmutableMap.of("name", "ejb30flexadmin", "applicationRuntimes", items0))); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java/com/oracle/wls/exporter/SystemClockTestSupport.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import java.time.OffsetDateTime; 7 | import java.time.temporal.ChronoUnit; 8 | 9 | import com.meterware.simplestub.Memento; 10 | import com.meterware.simplestub.StaticStubSupport; 11 | 12 | public class SystemClockTestSupport { 13 | private static TestSystemClock clock; 14 | 15 | public static Memento installClock() throws NoSuchFieldException { 16 | clock = new TestSystemClock(); 17 | return StaticStubSupport.install(SystemClock.class, "delegate", clock); 18 | } 19 | 20 | /** 21 | * Increments the system clock by the specified number of seconds. 22 | * @param numSeconds the number of seconds by which to advance the system clock 23 | */ 24 | public static void increment(long numSeconds) { 25 | clock.increment(numSeconds); 26 | } 27 | 28 | static class TestSystemClock extends SystemClock { 29 | private final OffsetDateTime testStartTime = SystemClock.now().truncatedTo(ChronoUnit.SECONDS); 30 | private OffsetDateTime currentTime = testStartTime; 31 | 32 | @Override 33 | public OffsetDateTime getCurrentTime() { 34 | return currentTime; 35 | } 36 | 37 | void increment(long numSeconds) { 38 | currentTime = currentTime.plusSeconds(numSeconds); 39 | } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java/com/oracle/wls/exporter/WebClient8ImplTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | public class WebClient8ImplTest extends WebClientTestBase { 7 | public WebClient8ImplTest() { 8 | super(WebClient8Impl::new); 9 | } 10 | } -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java/com/oracle/wls/exporter/WebClientFactoryImplTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2025, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.function.Function; 9 | 10 | import com.meterware.simplestub.Memento; 11 | import com.meterware.simplestub.StaticStubSupport; 12 | import org.junit.jupiter.api.AfterEach; 13 | import org.junit.jupiter.api.Test; 14 | 15 | import static org.hamcrest.MatcherAssert.assertThat; 16 | import static org.hamcrest.Matchers.sameInstance; 17 | 18 | class WebClientFactoryImplTest { 19 | 20 | private final List mementos = new ArrayList<>(); 21 | private final Function> apacheClassesMissing = WebClientFactoryImplTest::reportApacheClassesMissing; 22 | 23 | static Class reportApacheClassesMissing(String className) { 24 | if (className.equals(WebClientImpl.class.getName())) 25 | throw new NoClassDefFoundError("a class"); 26 | else if (className.equals(WebClient8Impl.class.getName())) 27 | return WebClient8Impl.class; 28 | else 29 | throw new RuntimeException("Unexpected client class name: " + className); 30 | } 31 | 32 | @AfterEach 33 | void tearDown() { 34 | mementos.forEach(Memento::revert); 35 | } 36 | 37 | @Test 38 | void whenApacheClientDependentClassesFound_selectApacheClient() { 39 | assertThat(WebClientFactoryImpl.getClientConstructor().getDeclaringClass(), sameInstance(WebClientImpl.class)); 40 | } 41 | 42 | @Test 43 | void whenApacheClientDependentClassesMissing_selectJKD8Client() throws NoSuchFieldException { 44 | mementos.add(StaticStubSupport.install(WebClientFactoryImpl.class, "loadClientClass", apacheClassesMissing)); 45 | 46 | assertThat(WebClientFactoryImpl.getClientConstructor().getDeclaringClass(), sameInstance(WebClient8Impl.class)); 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java/com/oracle/wls/exporter/WebClientImplTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | public class WebClientImplTest extends WebClientTestBase { 7 | 8 | public WebClientImplTest() { 9 | super(WebClientImpl::new); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java/com/oracle/wls/exporter/YamlDemo.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2025, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | import java.io.ByteArrayInputStream; 7 | 8 | import com.google.gson.JsonObject; 9 | import com.oracle.wls.exporter.domain.ExporterConfig; 10 | import com.oracle.wls.exporter.domain.MBeanSelector; 11 | 12 | import static com.google.gson.JsonParser.parseString; 13 | import static com.oracle.wls.exporter.DemoInputs.*; 14 | 15 | /** 16 | * @author Russell Gold 17 | */ 18 | public class YamlDemo { 19 | 20 | public static void main(String... args) { 21 | String yamlString = YAML_STRING; 22 | System.out.println("The following configuration:\n" + yamlString); 23 | ExporterConfig exporterConfig = ExporterConfig.loadConfig(new ByteArrayInputStream(yamlString.getBytes())); 24 | 25 | System.out.println("Generates the query:"); 26 | MBeanSelector selector = exporterConfig.getQueries()[0]; 27 | System.out.println(selector.getPrintableRequest()); 28 | 29 | System.out.println(); 30 | String response = compressedJsonForm(RESPONSE); 31 | System.out.println("The response\n" + response + "\nwill be transformed into the following metrics:"); 32 | 33 | exporterConfig.scrapeMetrics(selector, getJsonResponse(response)). 34 | forEach((name, value) -> System.out.printf(" %s %s%n", name, value)); 35 | } 36 | 37 | private static JsonObject getJsonResponse(String jsonString) { 38 | return parseString(jsonString).getAsJsonObject(); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java/com/oracle/wls/exporter/domain/ConfigurationExceptionTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2022, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.domain; 5 | 6 | import org.junit.jupiter.api.Test; 7 | 8 | import static org.hamcrest.MatcherAssert.assertThat; 9 | import static org.hamcrest.Matchers.equalTo; 10 | 11 | /** 12 | * @author Russell Gold 13 | */ 14 | class ConfigurationExceptionTest { 15 | @Test 16 | void afterAddMultipleContexts_messageContainsFullContext() { 17 | ConfigurationException exception = new ConfigurationException("Something went wrong"); 18 | 19 | exception.addContext("second"); 20 | exception.addContext("first"); 21 | 22 | assertThat(exception.getMessage(), equalTo("Something went wrong at first.second")); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java/com/oracle/wls/exporter/domain/MapUtilsTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2022, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.domain; 5 | 6 | import java.util.Arrays; 7 | import java.util.Map; 8 | 9 | import com.google.common.collect.ImmutableMap; 10 | import org.junit.jupiter.api.Test; 11 | 12 | import static org.hamcrest.MatcherAssert.assertThat; 13 | import static org.hamcrest.Matchers.arrayContaining; 14 | 15 | /** 16 | * @author Russell Gold 17 | */ 18 | class MapUtilsTest { 19 | 20 | private static final String[] STRING_ARRAY = {"1", "2", "3"}; 21 | 22 | @Test 23 | void whenStringArrayValueIsStringArray_returnAsIs() { 24 | Map map = ImmutableMap.of("values", STRING_ARRAY); 25 | 26 | assertThat(MapUtils.getStringArray(map, "values"), arrayContaining(STRING_ARRAY)); 27 | } 28 | 29 | @Test 30 | void whenStringArrayValueIsSingleObject_returnAsLengthOneArray() { 31 | Map map = ImmutableMap.of("values", 33); 32 | 33 | assertThat(MapUtils.getStringArray(map, "values"), arrayContaining("33")); 34 | } 35 | 36 | @Test 37 | void whenStringArrayValueIsList_returnAsArray() { 38 | Map map = ImmutableMap.of("values", Arrays.asList(7, 8, true)); 39 | 40 | assertThat(MapUtils.getStringArray(map, "values"), arrayContaining("7", "8", "true")); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java/com/oracle/wls/exporter/domain/MetricMatcher.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019, 2025, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.domain; 5 | 6 | import java.util.Map; 7 | import java.util.Objects; 8 | 9 | import org.hamcrest.Description; 10 | 11 | @SuppressWarnings("unused") 12 | class MetricMatcher extends org.hamcrest.TypeSafeDiagnosingMatcher> { 13 | private final String expectedKey; 14 | private final Object expectedValue; 15 | 16 | private MetricMatcher(String expectedKey, Object expectedValue) { 17 | this.expectedKey = expectedKey; 18 | this.expectedValue = expectedValue; 19 | } 20 | 21 | static MetricMatcher hasMetric(String expectedKey, Object expectedValue) { 22 | return new MetricMatcher(expectedKey, expectedValue); 23 | } 24 | 25 | static MetricMatcher hasNoSuchMetric(String expectedKey) { 26 | return new MetricMatcher(expectedKey, null); 27 | } 28 | 29 | @Override 30 | protected boolean matchesSafely(Map map, Description description) { 31 | if ((expectedValue == null && !map.containsKey(expectedKey)) || matchesValue(map.get(expectedKey))) 32 | return true; 33 | 34 | description.appendText("map was ").appendValueList("[", ", ", "]", map.entrySet()); 35 | return false; 36 | } 37 | 38 | private boolean matchesValue(Object o) { 39 | if (o == null) 40 | return false; 41 | if (expectedValue instanceof String) 42 | return Objects.equals(o, expectedValue); 43 | else if (expectedValue instanceof Integer) 44 | return ((Number) o).intValue() == ((Number) expectedValue).intValue(); 45 | else if (expectedValue instanceof Double) 46 | return ((Number) o).doubleValue() == ((Number) expectedValue).doubleValue(); 47 | else 48 | return false; 49 | } 50 | 51 | @Override 52 | public void describeTo(Description description) { 53 | if (expectedValue == null) 54 | describeUnexpectedMetric(description); 55 | else 56 | describeMissingMetric(description); 57 | } 58 | 59 | private void describeUnexpectedMetric(Description description) { 60 | description.appendText("map not containing [") 61 | .appendValue(expectedKey) 62 | .appendText("]"); 63 | } 64 | 65 | private void describeMissingMetric(Description description) { 66 | description.appendText("map containing [") 67 | .appendValue(expectedKey) 68 | .appendText("->") 69 | .appendValue(expectedValue) 70 | .appendText("]"); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java/com/oracle/wls/exporter/domain/QueryTypeTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019, 2022, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.domain; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | import org.junit.jupiter.api.Test; 10 | 11 | import static com.oracle.wls.exporter.domain.QueryType.CONFIGURATION; 12 | import static com.oracle.wls.exporter.domain.QueryType.RUNTIME; 13 | import static org.hamcrest.MatcherAssert.assertThat; 14 | import static org.hamcrest.Matchers.equalTo; 15 | import static org.hamcrest.Matchers.hasEntry; 16 | import static org.hamcrest.Matchers.is; 17 | import static org.hamcrest.Matchers.nullValue; 18 | 19 | class QueryTypeTest implements MetricsProcessor { 20 | 21 | private final Map metrics = new HashMap<>(); 22 | private Map selectedMetrics; 23 | 24 | @Test 25 | void runtimeQueryType_usesRuntimeMbeanUrl() { 26 | assertThat(RUNTIME.getUrlPattern(), equalTo(QueryType.RUNTIME_URL_PATTERN)); 27 | } 28 | 29 | @Test 30 | void configurationQueryType_usesConfigMbeanUrl() { 31 | assertThat(CONFIGURATION.getUrlPattern(), equalTo(QueryType.CONFIGURATION_URL_PATTERN)); 32 | } 33 | 34 | @Test 35 | void runtimeQueryType_ignoresStrings() { 36 | assertThat(RUNTIME.acceptsStrings(), is(false)); 37 | } 38 | 39 | @Test 40 | void configurationQueryType_acceptsStrings() { 41 | assertThat(CONFIGURATION.acceptsStrings(), is(true)); 42 | } 43 | 44 | @Test 45 | void runtimeQueryType_doesNotProcessMetrics() { 46 | metrics.put("name", "domain1"); 47 | RUNTIME.postProcessMetrics(metrics, this); 48 | 49 | assertThat(selectedMetrics, nullValue()); 50 | } 51 | 52 | @Test 53 | void configurationQueryType_processesNameAsDomainName() { 54 | metrics.put("name", "domain1"); 55 | CONFIGURATION.postProcessMetrics(metrics, this); 56 | 57 | assertThat(selectedMetrics, hasEntry(QueryType.DOMAIN_KEY, "domain1")); 58 | } 59 | 60 | @Override 61 | public void updateConfiguration(Map metrics) { 62 | this.selectedMetrics = metrics; 63 | } 64 | } -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java/com/oracle/wls/exporter/domain/SnakeCaseUtilTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2022, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.domain; 5 | 6 | import org.junit.jupiter.api.Test; 7 | 8 | import static org.hamcrest.MatcherAssert.assertThat; 9 | import static org.hamcrest.Matchers.equalTo; 10 | import static org.hamcrest.Matchers.is; 11 | 12 | /** 13 | * @author Russell Gold 14 | */ 15 | class SnakeCaseUtilTest { 16 | 17 | @Test 18 | void convertToSnakeCase() { 19 | assertThat(SnakeCaseUtil.convert("simple"), equalTo("simple")); 20 | assertThat(SnakeCaseUtil.convert("already_snake_case"), equalTo("already_snake_case")); 21 | assertThat(SnakeCaseUtil.convert("isCamelCase"), equalTo("is_camel_case")); 22 | assertThat(SnakeCaseUtil.convert("PascalCase"), equalTo("pascal_case")); 23 | } 24 | 25 | @Test 26 | void verifiesSnakeCase() { 27 | assertThat(SnakeCaseUtil.isCompliant("simple"), is(true)); 28 | assertThat(SnakeCaseUtil.isCompliant("an_example_with_multiple_words"), is(true)); 29 | assertThat(SnakeCaseUtil.isCompliant("camelCaseWithMultipleWords"), is(false)); 30 | assertThat(SnakeCaseUtil.isCompliant("PascalCase"), is(false)); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java/com/oracle/wls/exporter/javax/LogServletTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019, 2025, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.javax; 5 | 6 | import java.io.IOException; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import javax.servlet.annotation.WebServlet; 10 | import javax.servlet.http.HttpServlet; 11 | 12 | import com.meterware.simplestub.Memento; 13 | import com.meterware.simplestub.StaticStubSupport; 14 | import com.oracle.wls.exporter.ErrorLog; 15 | import com.oracle.wls.exporter.InMemoryResources; 16 | import com.oracle.wls.exporter.LiveConfiguration; 17 | import com.oracle.wls.exporter.WebClientException; 18 | import org.junit.jupiter.api.AfterEach; 19 | import org.junit.jupiter.api.BeforeEach; 20 | import org.junit.jupiter.api.Test; 21 | 22 | import static org.hamcrest.MatcherAssert.assertThat; 23 | import static org.hamcrest.Matchers.arrayContaining; 24 | import static org.hamcrest.Matchers.containsString; 25 | import static org.hamcrest.Matchers.instanceOf; 26 | import static org.hamcrest.Matchers.notNullValue; 27 | 28 | class LogServletTest { 29 | 30 | private final LogServlet servlet = new LogServlet(); 31 | private final HttpServletRequestStub request = HttpServletRequestStub.createGetRequest(); 32 | private final HttpServletResponseStub response = HttpServletResponseStub.createServletResponse(); 33 | private final List mementos = new ArrayList<>(); 34 | 35 | @BeforeEach 36 | void setUp() throws Exception { 37 | InMemoryResources.install(); 38 | LiveConfiguration.loadFromString(""); 39 | } 40 | 41 | @AfterEach 42 | void tearDown() { 43 | mementos.forEach(Memento::revert); 44 | InMemoryResources.uninstall(); 45 | } 46 | 47 | @Test 48 | void landingPage_isHttpServlet() { 49 | assertThat(servlet, instanceOf(HttpServlet.class)); 50 | } 51 | 52 | @Test 53 | void servlet_hasWebServletAnnotation() { 54 | assertThat(LogServlet.class.getAnnotation(WebServlet.class), notNullValue()); 55 | } 56 | 57 | @Test 58 | void servletAnnotationIndicatesMainPage() { 59 | WebServlet annotation = LogServlet.class.getAnnotation(WebServlet.class); 60 | 61 | assertThat(annotation.value(), arrayContaining("/log")); 62 | } 63 | 64 | @Test 65 | void whenNoErrorsReported_saySo() throws IOException { 66 | servlet.doGet(request, response); 67 | 68 | assertThat(response.getHtml(), containsString("No errors reported.")); 69 | } 70 | 71 | @Test 72 | void whenErrorsReported_listThem() throws NoSuchFieldException, IOException { 73 | ErrorLog errorLog = new ErrorLog(); 74 | mementos.add(StaticStubSupport.install(LiveConfiguration.class, "errorLog", errorLog)); 75 | 76 | errorLog.log(new WebClientException("Unable to reach server")); 77 | servlet.doGet(request, response); 78 | 79 | assertThat(response.getHtml(), containsString("WebClientException: Unable to reach server")); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java/com/oracle/wls/exporter/matchers/CommentsOnlyMatcher.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2020, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.matchers; 5 | 6 | import org.hamcrest.Description; 7 | import org.hamcrest.TypeSafeDiagnosingMatcher; 8 | 9 | /** 10 | * A matcher which confirms that the text contains only comments (lines starting with '#') 11 | * 12 | * @author Russell Gold 13 | */ 14 | public class CommentsOnlyMatcher extends TypeSafeDiagnosingMatcher { 15 | 16 | public static CommentsOnlyMatcher containsOnlyComments() { 17 | return new CommentsOnlyMatcher(); 18 | } 19 | 20 | @Override 21 | protected boolean matchesSafely(String s, Description description) { 22 | String[] lines = s.split("\n"); 23 | for (int i = 0; i < lines.length; i++) 24 | if (!lines[i].trim().startsWith("#")) return foundNonCommentLine(description, i, lines[i]); 25 | return true; 26 | } 27 | 28 | private boolean foundNonCommentLine(Description description, int lineNum, String line) { 29 | description.appendText("Found non-comment @line ") 30 | .appendText(Integer.toString(lineNum)) 31 | .appendText("\n") 32 | .appendValue(line); 33 | return false; 34 | } 35 | 36 | @Override 37 | public void describeTo(Description description) { 38 | description.appendText("only lines beginning with '#'"); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java/com/oracle/wls/exporter/matchers/MetricsNamesSnakeCaseMatcher.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2025, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.matchers; 5 | 6 | import java.util.Arrays; 7 | import java.util.List; 8 | import java.util.stream.Collectors; 9 | 10 | import com.oracle.wls.exporter.domain.SnakeCaseUtil; 11 | import org.hamcrest.Description; 12 | 13 | /** 14 | * @author Russell Gold 15 | */ 16 | public class MetricsNamesSnakeCaseMatcher extends org.hamcrest.TypeSafeDiagnosingMatcher { 17 | 18 | public static MetricsNamesSnakeCaseMatcher usesSnakeCase() { 19 | return new MetricsNamesSnakeCaseMatcher(); 20 | } 21 | 22 | @Override 23 | protected boolean matchesSafely(String metricsList, Description description) { 24 | String[] metrics = metricsList.split("\n"); 25 | List badNames = getNonSnakeCaseNames(metrics); 26 | if (badNames.isEmpty()) return true; 27 | 28 | description.appendValueList("found names not in snake case:[", ",", "]", badNames); 29 | return false; 30 | } 31 | 32 | private List getNonSnakeCaseNames(String[] metrics) { 33 | return Arrays.stream(metrics) 34 | .filter(s -> !s.startsWith("#")) 35 | .map(MetricsUtils::getMetricName) 36 | .filter(s -> !SnakeCaseUtil.isCompliant(s)) 37 | .filter(new MetricsUtils.Uniq()) 38 | .collect(Collectors.toList()); 39 | } 40 | 41 | @Override 42 | public void describeTo(Description description) { 43 | description.appendText("all metrics names in snake case"); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java/com/oracle/wls/exporter/matchers/MetricsUtils.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2020, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.matchers; 5 | 6 | import java.util.function.Predicate; 7 | 8 | class MetricsUtils { 9 | static String getMetricName(String s) { 10 | String spec = s.trim().split(" ")[0]; 11 | return spec.contains("{") ? spec.split("\\{")[0] : spec; 12 | } 13 | 14 | /** 15 | * @author Russell Gold 16 | */ 17 | static class Uniq implements Predicate { 18 | String last = ""; 19 | @Override 20 | public boolean test(String s) { 21 | try { 22 | return s != null && !s.equals(last); 23 | } finally { 24 | last = s; 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java/com/oracle/wls/exporter/matchers/PrometheusMetricsMatcherTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2025, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.matchers; 5 | 6 | import java.util.Arrays; 7 | 8 | import org.junit.jupiter.api.Test; 9 | 10 | import static com.oracle.wls.exporter.matchers.PrometheusMetricsMatcher.followsPrometheusRules; 11 | import static java.util.stream.Collectors.joining; 12 | import static org.junit.jupiter.api.Assertions.assertFalse; 13 | import static org.junit.jupiter.api.Assertions.assertTrue; 14 | 15 | /** 16 | * @author Russell Gold 17 | */ 18 | class PrometheusMetricsMatcherTest { 19 | 20 | private final PrometheusMetricsMatcher matcher = followsPrometheusRules(); 21 | 22 | @Test 23 | void whenMetricsAreGrouped_matcherPasses() { 24 | assertTrue(matcher.matches(toHtml(orderedList))); 25 | } 26 | 27 | private final String[] orderedList = 28 | {"metric1 1", "metric2{name='red'} 23", "metric2{name='blue'} 34"}; 29 | 30 | private String toHtml(String... metrics) { 31 | return Arrays.stream(metrics).map(s -> s.replace('\'', '"')).collect(joining("\n")); 32 | } 33 | 34 | @Test 35 | void whenMetricsAreInterspersed_matcherFails() { 36 | assertFalse(matcher.matches(toHtml(misorderedList))); 37 | } 38 | 39 | private final String[] misorderedList = 40 | {"metric2{name='red'} 23", "metric1 1", "metric2{name='blue'} 34"}; 41 | 42 | @Test 43 | void whenMetricsHaveNonNumericValues_matcherFails() { 44 | assertFalse(matcher.matches(toHtml(textList))); 45 | } 46 | 47 | private final String[] textList = 48 | {"metric1 1", "metric2{name='red'} 23", "metric2{name='blue'} some-color"}; 49 | } 50 | -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java/com/oracle/wls/exporter/matchers/ResponseHeaderMatcher.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2020, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.matchers; 5 | 6 | import javax.servlet.http.HttpServletResponse; 7 | 8 | import org.hamcrest.Description; 9 | import org.hamcrest.TypeSafeDiagnosingMatcher; 10 | 11 | /** 12 | * @author Russell Gold 13 | */ 14 | public class ResponseHeaderMatcher extends TypeSafeDiagnosingMatcher { 15 | private final String expectedHeaderName; 16 | private final String expectedHeaderValue; 17 | 18 | private ResponseHeaderMatcher(String expectedHeaderName, String expectedHeaderValue) { 19 | this.expectedHeaderName = expectedHeaderName; 20 | this.expectedHeaderValue = expectedHeaderValue; 21 | } 22 | 23 | public static ResponseHeaderMatcher containsHeader(String expectedHeaderName, String expectedHeaderValue) { 24 | return new ResponseHeaderMatcher(expectedHeaderName, expectedHeaderValue); 25 | } 26 | 27 | @SuppressWarnings("SimplifiableIfStatement") 28 | @Override 29 | protected boolean matchesSafely(HttpServletResponse response, Description description) { 30 | if (!response.containsHeader(expectedHeaderName)) 31 | return reportNoSuchHeader(response, description); 32 | else if (!response.getHeaders(expectedHeaderName).contains(expectedHeaderValue)) 33 | return reportNoMatchingHeaderValue(response, description); 34 | else 35 | return true; 36 | } 37 | 38 | private boolean reportNoSuchHeader(HttpServletResponse response, Description description) { 39 | description.appendValueList("found header names: {", ", ", "}", response.getHeaderNames()); 40 | return false; 41 | } 42 | 43 | private boolean reportNoMatchingHeaderValue(HttpServletResponse response, Description description) { 44 | description.appendText("found ").appendText(expectedHeaderName) 45 | .appendValueList(" with value(s) ", ", ", "", response.getHeaders(expectedHeaderName)); 46 | return false; 47 | } 48 | 49 | @Override 50 | public void describeTo(Description description) { 51 | description.appendText("response containing header ") 52 | .appendValue(expectedHeaderName) 53 | .appendText(" with value ") 54 | .appendValue(expectedHeaderValue); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /wls-exporter-core/src/test/java11/com/oracle/wls/exporter/WebClient11ImplTest.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter; 5 | 6 | public class WebClient11ImplTest extends WebClientTestBase { 7 | 8 | public WebClient11ImplTest() { 9 | super(WebClient11Impl::new); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /wls-exporter-sidecar/src/main/java/com/oracle/wls/exporter/sidecar/HelidonInvocationContext.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, 2024, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.sidecar; 5 | 6 | import java.io.ByteArrayOutputStream; 7 | import java.io.InputStream; 8 | import java.io.PrintStream; 9 | import java.net.URI; 10 | 11 | import com.oracle.wls.exporter.InvocationContext; 12 | import com.oracle.wls.exporter.UrlBuilder; 13 | import io.helidon.http.HeaderNames; 14 | import io.helidon.common.media.type.MediaType; 15 | import io.helidon.http.Status; 16 | import io.helidon.webserver.http.ServerRequest; 17 | import io.helidon.webserver.http.ServerResponse; 18 | 19 | public class HelidonInvocationContext implements InvocationContext { 20 | 21 | private final ServerRequest request; 22 | private final ServerResponse response; 23 | private final ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); 24 | private final PrintStream printStream = new PrintStream(baos); 25 | private final SidecarConfiguration configuration = new SidecarConfiguration(); 26 | 27 | public HelidonInvocationContext(ServerRequest request, ServerResponse response) { 28 | this.request = request; 29 | this.response = response; 30 | } 31 | 32 | @Override 33 | public UrlBuilder createUrlBuilder() { 34 | return UrlBuilder.create(configuration.useWebLogicSsl()) 35 | .withHostName(configuration.getWebLogicHost()) 36 | .withPort(configuration.getWebLogicPort()); 37 | } 38 | 39 | @Override 40 | public String getApplicationContext() { 41 | return "/"; 42 | } 43 | 44 | @Override 45 | public String getAuthenticationHeader() { 46 | return request.headers().first(HeaderNames.AUTHORIZATION).orElse(null); 47 | } 48 | 49 | @Override 50 | public String getContentType() { 51 | return request.headers().contentType().map(MediaType::toString).orElse("application/json"); 52 | } 53 | 54 | @Override 55 | public String getInstanceName() { 56 | return configuration.getPodName(); 57 | } 58 | 59 | @Override 60 | public InputStream getRequestStream() { 61 | return request.content().inputStream(); 62 | } 63 | 64 | @Override 65 | public PrintStream getResponseStream() { 66 | return printStream; 67 | } 68 | 69 | @Override 70 | public void sendError(int status, String msg) { 71 | response.status(status).send(msg); 72 | } 73 | 74 | @Override 75 | public void sendRedirect(String location) { 76 | response.headers().location(URI.create(location)); 77 | 78 | response.status(Status.FOUND_302).send(); 79 | } 80 | 81 | @Override 82 | public void setResponseHeader(String name, String value) { 83 | response.headers().add(HeaderNames.create(name), value); 84 | } 85 | 86 | @Override 87 | public void setStatus(int status) { 88 | response.status(status); 89 | } 90 | 91 | @Override 92 | public void close() { 93 | if (!response.isSent()) { 94 | response.send(baos.toByteArray()); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /wls-exporter-sidecar/src/main/java/com/oracle/wls/exporter/sidecar/Main.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, 2024, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.sidecar; 5 | 6 | import com.oracle.wls.exporter.WebClientFactoryImpl; 7 | import io.helidon.logging.common.LogConfig; 8 | import io.helidon.webserver.WebServer; 9 | import io.helidon.webserver.http.HttpRouting; 10 | 11 | 12 | // Main program for the Exporter sidecar using Helidon 13 | public class Main { 14 | public static void main(String[] args) { 15 | LogConfig.configureRuntime(); 16 | final SidecarConfiguration configuration = new SidecarConfiguration(); 17 | final MetricsService metricsService = new MetricsService(configuration, new WebClientFactoryImpl()); 18 | 19 | WebServer.builder() 20 | .addRouting(HttpRouting.builder().register(metricsService)) 21 | .port(metricsService.getListenPort()) 22 | .build() 23 | .start(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /wls-exporter-sidecar/src/main/java/com/oracle/wls/exporter/sidecar/SidecarConfiguration.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, 2022, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.sidecar; 5 | 6 | import java.net.InetAddress; 7 | import java.net.UnknownHostException; 8 | 9 | public class SidecarConfiguration { 10 | 11 | static final String LISTEN_PORT_PROPERTY = "EXPORTER_PORT"; 12 | static final String WLS_HOST_PROPERTY = "WLS_HOST"; 13 | static final String WLS_PORT_PROPERTY = "WLS_PORT"; 14 | static final String WLS_SECURE_PROPERTY = "WLS_SECURE"; 15 | static final String POD_NAME_PROPERTY = "POD_NAME"; 16 | 17 | static final int DEFAULT_LISTEN_PORT = 8080; 18 | static final int DEFAULT_WLS_PORT = 7001; 19 | static final String DEFAULT_POD_NAME = ""; 20 | 21 | private final int listenPort; 22 | private final String webLogicHost; 23 | private final int webLogicPort; 24 | private final String podName; 25 | private final boolean secure; 26 | 27 | public SidecarConfiguration() { 28 | listenPort = Integer.getInteger(LISTEN_PORT_PROPERTY, DEFAULT_LISTEN_PORT); 29 | webLogicHost = System.getProperty(WLS_HOST_PROPERTY, getDefaultWlsHostName()); 30 | webLogicPort = Integer.getInteger(WLS_PORT_PROPERTY, DEFAULT_WLS_PORT); 31 | podName = System.getProperty(POD_NAME_PROPERTY, DEFAULT_POD_NAME); 32 | secure = Boolean.getBoolean(WLS_SECURE_PROPERTY); 33 | } 34 | 35 | static String getDefaultWlsHostName() { 36 | try { 37 | return InetAddress.getLocalHost().getHostAddress(); 38 | } catch (UnknownHostException e) { 39 | return "127.0.0.1"; 40 | } 41 | } 42 | 43 | public int getListenPort() { 44 | return listenPort; 45 | } 46 | 47 | public int getWebLogicPort() { 48 | return webLogicPort; 49 | } 50 | 51 | public String getWebLogicHost() { 52 | return webLogicHost; 53 | } 54 | 55 | public String getPodName() { 56 | return podName; 57 | } 58 | 59 | public boolean useWebLogicSsl() { 60 | return secure; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /wls-exporter-sidecar/src/main/resources/logging.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2018, 2020 Oracle and/or its affiliates. All rights reserved. 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 | # Example Logging Configuration File 18 | # For more information see $JAVA_HOME/jre/lib/logging.properties 19 | 20 | ## Send messages to the console 21 | handlers=io.helidon.logging.jul.HelidonConsoleHandler 22 | # 23 | ## HelidonConsoleHandler uses a SimpleFormatter subclass that replaces "!thread!" with the current thread 24 | java.util.logging.SimpleFormatter.format=%1$tY.%1$tm.%1$td %1$tH:%1$tM:%1$tS %4$s %3$s !thread!: %5$s%6$s%n 25 | # 26 | ## Global logging level. Can be overridden by specific loggers 27 | .level=INFO 28 | # 29 | # Component specific log levels 30 | #io.helidon.webserver.level=INFO 31 | #io.helidon.config.level=INFO 32 | #io.helidon.security.level=INFO 33 | #io.helidon.microprofile.level=INFO 34 | #io.helidon.common.level=INFO 35 | #io.netty.level=INFO 36 | #org.glassfish.jersey.level=INFO 37 | #org.jboss.weld=INFO 38 | -------------------------------------------------------------------------------- /wls-exporter-sidecar/src/test/java/com/oracle/wls/exporter/sidecar/ItemHolder.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, 2020, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.sidecar; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | import java.util.Map; 9 | 10 | /** 11 | * A class to provide the "items" potion of the json REST query. 12 | * 13 | * @author Russell Gold 14 | */ 15 | @SuppressWarnings("rawtypes") 16 | class ItemHolder { 17 | ItemHolder(Map... maps) { 18 | items.addAll(Arrays.asList(maps)); 19 | } 20 | 21 | @SuppressWarnings({"FieldCanBeLocal", "MismatchedQueryAndUpdateOfCollection"}) 22 | private final ArrayList items = new ArrayList<>(); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /wls-exporter-sidecar/src/test/java/com/oracle/wls/exporter/sidecar/SidecarConfigurationTestSupport.java: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021, Oracle and/or its affiliates. 2 | // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 | 4 | package com.oracle.wls.exporter.sidecar; 5 | 6 | import java.util.Arrays; 7 | import java.util.List; 8 | 9 | import com.meterware.simplestub.Memento; 10 | import com.meterware.simplestub.SystemPropertySupport; 11 | 12 | import static com.oracle.wls.exporter.sidecar.SidecarConfiguration.LISTEN_PORT_PROPERTY; 13 | import static com.oracle.wls.exporter.sidecar.SidecarConfiguration.POD_NAME_PROPERTY; 14 | import static com.oracle.wls.exporter.sidecar.SidecarConfiguration.WLS_HOST_PROPERTY; 15 | import static com.oracle.wls.exporter.sidecar.SidecarConfiguration.WLS_PORT_PROPERTY; 16 | import static com.oracle.wls.exporter.sidecar.SidecarConfiguration.WLS_SECURE_PROPERTY; 17 | 18 | public class SidecarConfigurationTestSupport { 19 | private static final String[] CONFIGURATION_PROPERTIES 20 | = {LISTEN_PORT_PROPERTY, POD_NAME_PROPERTY, WLS_HOST_PROPERTY, WLS_PORT_PROPERTY, WLS_SECURE_PROPERTY}; 21 | 22 | static void preserveConfigurationProperties(List mementos) { 23 | Arrays.stream(CONFIGURATION_PROPERTIES).forEach(property -> preserveAndClearProperty(mementos, property)); 24 | } 25 | 26 | private static void preserveAndClearProperty(List mementos, String property) { 27 | mementos.add(SystemPropertySupport.preserve(property)); 28 | System.clearProperty(property); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /wls-exporter-sidecar/src/test/resources/exporter-version.properties: -------------------------------------------------------------------------------- 1 | monitoring-exporter-version=1 -------------------------------------------------------------------------------- /wls-exporter-war/src/main/resources/get.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) 2021, 2022, Oracle and/or its affiliates. 3 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 4 | 5 | curl -L -O https://github.com/oracle/weblogic-monitoring-exporter/releases/download/v${tag}/wls-exporter.war 6 | 7 | if [ ! -z "$1" ]; then 8 | tmp_dir=$(mktemp -d -t ci-XXXXXXXXXX) 9 | echo "created $tmp_dir" 10 | cp $1 $tmp_dir/config.yml 11 | warDir=$PWD 12 | pushd $tmp_dir 13 | echo "in temp dir" 14 | zip $warDir/wls-exporter.war config.yml 15 | popd 16 | # rm -rf $tmp_dir 17 | fi 18 | -------------------------------------------------------------------------------- /wls-exporter-war/src/main/webapp/WEB-INF/weblogic.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | false 8 | 9 | 10 | 11 | true 12 | 13 | 14 | 15 | --------------------------------------------------------------------------------