├── .gitlab └── issue_templates │ ├── .gitkeep │ └── Default.md ├── docs ├── img │ ├── 05-pushgateway-view.png │ ├── 01-add-reporting-task.png │ ├── 04-run-reporting-task.png │ ├── 00-controller-settings.png │ ├── 03-settings-reporting-task.png │ └── 02-configure-reporting-task.png └── Configuration.md ├── .idea ├── vcs.xml ├── kotlinc.xml ├── shelf │ ├── current_testing.xml │ └── current_testing │ │ └── shelved.patch ├── encodings.xml ├── misc.xml ├── modules.xml └── compiler.xml ├── Dockerfile ├── .circleci └── config.yml ├── docker-compose.yml ├── conf └── prometheus.yml ├── nifi-prometheus-reporting-task ├── src │ ├── main │ │ ├── resources │ │ │ ├── META-INF │ │ │ │ └── services │ │ │ │ │ └── org.apache.nifi.reporting.ReportingTask │ │ │ └── docs │ │ │ │ └── org │ │ │ │ └── apache │ │ │ │ └── nifi │ │ │ │ └── reporting │ │ │ │ └── prometheus │ │ │ │ └── PrometheusReportingTask │ │ │ │ └── additionalDetails.html │ │ └── java │ │ │ └── org │ │ │ └── apache │ │ │ └── nifi │ │ │ └── reporting │ │ │ └── prometheus │ │ │ ├── metrics │ │ │ ├── MetricNames.java │ │ │ └── MetricsService.java │ │ │ ├── api │ │ │ └── PrometheusMetricsFactory.java │ │ │ └── PrometheusReportingTask.java │ └── test │ │ └── java │ │ └── org │ │ └── apache │ │ └── nifi │ │ └── reporting │ │ └── prometheus │ │ ├── metrics │ │ └── TestMetricsService.java │ │ └── TestPrometheusReportingTask.java ├── pom.xml └── nifi-prometheus-reporting-task.iml ├── nifi-prometheus-nar ├── pom.xml ├── src │ └── main │ │ └── resources │ │ └── META-INF │ │ └── NOTICE └── nifi-prometheus-nar.iml ├── .gitignore ├── nifi-prometheus-bundle.iml ├── pom.xml ├── Readme.md └── LICENSE /.gitlab/issue_templates/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/img/05-pushgateway-view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/containerpope/nifi-prometheus-reporter/HEAD/docs/img/05-pushgateway-view.png -------------------------------------------------------------------------------- /docs/img/01-add-reporting-task.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/containerpope/nifi-prometheus-reporter/HEAD/docs/img/01-add-reporting-task.png -------------------------------------------------------------------------------- /docs/img/04-run-reporting-task.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/containerpope/nifi-prometheus-reporter/HEAD/docs/img/04-run-reporting-task.png -------------------------------------------------------------------------------- /docs/img/00-controller-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/containerpope/nifi-prometheus-reporter/HEAD/docs/img/00-controller-settings.png -------------------------------------------------------------------------------- /docs/img/03-settings-reporting-task.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/containerpope/nifi-prometheus-reporter/HEAD/docs/img/03-settings-reporting-task.png -------------------------------------------------------------------------------- /docs/img/02-configure-reporting-task.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/containerpope/nifi-prometheus-reporter/HEAD/docs/img/02-configure-reporting-task.png -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /.idea/shelf/current_testing.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM apache/nifi:1.9.2 2 | 3 | ADD https://github.com/mkjoerg/nifi-prometheus-reporter/releases/download/nifi-1.9.2/nifi-prometheus-nar-1.9.2.nar ${NIFI_BASE_DIR}/nifi-current/lib 4 | 5 | USER root 6 | 7 | # Setup NiFi user and create necessary directories 8 | RUN chown -R nifi:nifi ${NIFI_BASE_DIR}/nifi-current/lib 9 | 10 | USER nifi 11 | 12 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # Java Maven CircleCI 2.0 configuration file 2 | # 3 | # Check https://circleci.com/docs/2.0/language-java/ for more details 4 | # 5 | version: 2 6 | jobs: 7 | build: 8 | docker: 9 | - image: circleci/openjdk:8u171-jdk 10 | 11 | working_directory: ~/repo 12 | 13 | environment: 14 | # Customize the JVM maximum heap limit 15 | MAVEN_OPTS: -Xmx3200m 16 | 17 | steps: 18 | - checkout 19 | 20 | - run: mvn clean install 21 | 22 | - store_artifacts: 23 | path: nifi-prometheus-nar/target/ 24 | destination: artifact-file -------------------------------------------------------------------------------- /.gitlab/issue_templates/Default.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | Informal description or user story 3 | 4 | ## Why? (Business value) 5 | How this task/goal serves a defined milestone/department goal 6 | 7 | ## Deliverables 8 | Which artefacts (software feature, prototype, guide, presentation, evaluation matrix etc) should be delivered 9 | * [ ] Deliverable 1 10 | * [ ] Deliverable 2 11 | * [ ] Deliverable 3 12 | 13 | ``` 14 | Checklist ticket specification 15 | 1. Format above used? 16 | 2. Labels set? 17 | - Type-Label e.g. #Feature, #Orga, #Debts, ... 18 | - Area-Label e.g. DevOps, BizDev, AI 19 | 3. Assignee set? 20 | 4. Milestone set? 21 | ``` -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.1' 2 | 3 | volumes: 4 | grafana-data: 5 | 6 | services: 7 | prometheus: 8 | image: prom/prometheus 9 | ports: 10 | - "9090:9090" 11 | volumes: 12 | - "./conf/prometheus.yml:/etc/prometheus/prometheus.yml" 13 | 14 | pushgateway: 15 | image: prom/pushgateway 16 | ports: 17 | - "9091:9091" 18 | 19 | nifi: 20 | build: . 21 | ports: 22 | - "8080:8080" 23 | 24 | grafana: 25 | image: grafana/grafana:latest 26 | ports: 27 | - "3000:3000" 28 | volumes: 29 | - "grafana-data:/var/lib/grafana" -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /conf/prometheus.yml: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 15s # By default, scrape targets every 15 seconds. 3 | 4 | # Attach these labels to any time series or alerts when communicating with 5 | # external systems (federation, remote storage, Alertmanager). 6 | external_labels: 7 | monitor: 'local-monitor' 8 | 9 | # A scrape configuration containing exactly one endpoint to scrape: 10 | # Here it's Prometheus itself. 11 | scrape_configs: 12 | 13 | - job_name: 'nifi_reporting_job' 14 | 15 | # Override the global default and scrape targets from this job every 5 seconds. 16 | scrape_interval: 5s 17 | honor_labels: true 18 | static_configs: 19 | - targets: ['pushgateway:9091'] -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /docs/Configuration.md: -------------------------------------------------------------------------------- 1 | # Configuration 2 | 3 | Open your Nifi under http://localhost:8080/nifi and go to the menu in the upper right: 4 | ![Controller Settings](./img/00-controller-settings.png) 5 | 6 | Go to Controller Settings and add a new reporting task: 7 | ![Add Reporting Task](./img/01-add-reporting-task.png) 8 | 9 | After the task is added, it has to be configured: 10 | ![Configure Reporting Task](./img/02-configure-reporting-task.png) 11 | 12 | The following settings can be edited: (See the help texts for more details) 13 | ![Settings Reporting Task](./img/03-settings-reporting-task.png) 14 | 15 | After the reporting task is configured, run it: 16 | ![Run Reporting Task](./img/04-run-reporting-task.png) 17 | 18 | If everything went well, the prometheus pushgateway (localhost:9091) should now provide your metrics: 19 | ![Check Pushgateway](./img/05-pushgateway-view.png) 20 | 21 | After this the metrics can be scraped by prometheus and then visualized in Grafana. -------------------------------------------------------------------------------- /nifi-prometheus-reporting-task/src/main/resources/META-INF/services/org.apache.nifi.reporting.ReportingTask: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. 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 | org.apache.nifi.reporting.prometheus.PrometheusReportingTask -------------------------------------------------------------------------------- /nifi-prometheus-nar/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 17 | 4.0.0 18 | 19 | org.apache.nifi 20 | nifi-prometheus-bundle 21 | 1.9.2 22 | 23 | 24 | nifi-prometheus-nar 25 | nar 26 | 27 | true 28 | true 29 | 30 | 31 | 32 | org.apache.nifi 33 | nifi-prometheus-reporting-task 34 | 1.9.2 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------- 2 | # Jetbrains gitignore 3 | # --------------------------------------------------- 4 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 5 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 6 | 7 | 8 | # User-specific stuff: 9 | .idea/**/workspace.xml 10 | .idea/**/tasks.xml 11 | .idea/checkstyle-idea.xml 12 | .idea/dictionaries 13 | 14 | # Sensitive or high-churn files: 15 | .idea/**/dataSources/ 16 | .idea/**/dataSources.ids 17 | .idea/**/dataSources.xml 18 | .idea/**/dataSources.local.xml 19 | .idea/**/sqlDataSources.xml 20 | .idea/**/dynamic.xml 21 | .idea/**/uiDesigner.xml 22 | 23 | # Gradle: 24 | .idea/**/gradle.xml 25 | .idea/**/libraries 26 | 27 | # CMake 28 | cmake-build-debug/ 29 | 30 | # Mongo Explorer plugin: 31 | .idea/**/mongoSettings.xml 32 | 33 | ## File-based project format: 34 | *.iws 35 | 36 | ## Plugin-specific files: 37 | 38 | # IntelliJ 39 | out/ 40 | 41 | # mpeltonen/sbt-idea plugin 42 | .idea_modules/ 43 | 44 | # JIRA plugin 45 | atlassian-ide-plugin.xml 46 | 47 | # Cursive Clojure plugin 48 | .idea/replstate.xml 49 | 50 | # Crashlytics plugin (for Android Studio and IntelliJ) 51 | com_crashlytics_export_strings.xml 52 | crashlytics.properties 53 | crashlytics-build.properties 54 | fabric.properties 55 | 56 | # --------------------------------------------------- 57 | # Maven gitignore 58 | # --------------------------------------------------- 59 | 60 | target/ 61 | pom.xml.tag 62 | pom.xml.releaseBackup 63 | pom.xml.versionsBackup 64 | pom.xml.next 65 | release.properties 66 | dependency-reduced-pom.xml 67 | buildNumber.properties 68 | .mvn/timing.properties 69 | 70 | # Avoid ignoring Maven wrapper jar file (.jar files are usually ignored) 71 | !/.mvn/wrapper/maven-wrapper.jar 72 | 73 | 74 | # Mac 75 | 76 | .DS_Store -------------------------------------------------------------------------------- /nifi-prometheus-reporting-task/src/main/resources/docs/org/apache/nifi/reporting/prometheus/PrometheusReportingTask/additionalDetails.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 17 | 18 | 19 | PrometheusReportingTask 20 | 21 | 22 | 23 | 24 |

PrometheusReportingTask

25 | 26 |

This ReportingTask sends the following metrics to Prometheus:

27 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /nifi-prometheus-bundle.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 18 | 4.0.0 19 | 20 | 1.9.2 21 | 22 | 23 | 24 | org.apache.nifi 25 | nifi-nar-bundles 26 | 1.9.2 27 | 28 | 29 | nifi-prometheus-bundle 30 | pom 31 | 32 | 33 | nifi-prometheus-reporting-task 34 | nifi-prometheus-nar 35 | 36 | 37 | 38 | 39 | 40 | org.glassfish.jersey.core 41 | jersey-client 42 | 2.19 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | org.apache.maven.plugins 51 | maven-compiler-plugin 52 | 3.6.1 53 | 54 | 1.8 55 | 1.8 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /nifi-prometheus-reporting-task/src/main/java/org/apache/nifi/reporting/prometheus/metrics/MetricNames.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.nifi.reporting.prometheus.metrics; 18 | 19 | /** 20 | * The Metric names to send to Prometheus. 21 | */ 22 | public interface MetricNames { 23 | 24 | // Metric Name separator 25 | String METRIC_NAME_SEPARATOR = "."; 26 | 27 | // NiFi Metrics 28 | String FLOW_FILES_RECEIVED = "FlowFilesReceivedLast5Minutes"; 29 | String BYTES_RECEIVED = "BytesReceivedLast5Minutes"; 30 | String FLOW_FILES_SENT = "FlowFilesSentLast5Minutes"; 31 | String BYTES_SENT = "BytesSentLast5Minutes"; 32 | String FLOW_FILES_QUEUED = "FlowFilesQueued"; 33 | String BYTES_QUEUED = "BytesQueued"; 34 | String BYTES_READ = "BytesReadLast5Minutes"; 35 | String BYTES_WRITTEN = "BytesWrittenLast5Minutes"; 36 | String ACTIVE_THREADS = "ActiveThreads"; 37 | String TOTAL_TASK_DURATION_SECONDS = "TotalTaskDurationSeconds"; 38 | String TOTAL_TASK_DURATION_NANOS = "TotalTaskDurationNanoSeconds"; 39 | 40 | // JVM Metrics 41 | String JVM_UPTIME = "jvm.uptime"; 42 | String JVM_HEAP_USED = "jvm.heap_used"; 43 | String JVM_HEAP_USAGE = "jvm.heap_usage"; 44 | String JVM_NON_HEAP_USAGE = "jvm.non_heap_usage"; 45 | String JVM_THREAD_STATES_RUNNABLE = "jvm.thread_states.runnable"; 46 | String JVM_THREAD_STATES_BLOCKED = "jvm.thread_states.blocked"; 47 | String JVM_THREAD_STATES_TIMED_WAITING = "jvm.thread_states.timed_waiting"; 48 | String JVM_THREAD_STATES_TERMINATED = "jvm.thread_states.terminated"; 49 | String JVM_THREAD_COUNT = "jvm.thread_count"; 50 | String JVM_DAEMON_THREAD_COUNT = "jvm.daemon_thread_count"; 51 | String JVM_FILE_DESCRIPTOR_USAGE = "jvm.file_descriptor_usage"; 52 | String JVM_GC_RUNS = "jvm.gc.runs"; 53 | String JVM_GC_TIME = "jvm.gc.time"; 54 | 55 | } 56 | -------------------------------------------------------------------------------- /nifi-prometheus-nar/src/main/resources/META-INF/NOTICE: -------------------------------------------------------------------------------- 1 | nifi-prometheus-nar 2 | Copyright 2015-2017 The Apache Software Foundation 3 | 4 | This product includes software developed at 5 | The Apache Software Foundation (http://www.apache.org/). 6 | 7 | ****************** 8 | Apache Software License v2 9 | ****************** 10 | 11 | The following binary components are provided under the Apache Software License v2 12 | 13 | (ASLv2) Yammer Metrics 14 | The following NOTICE information applies: 15 | Metrics 16 | Copyright 2010-2012 Coda Hale and Yammer, Inc. 17 | 18 | This product includes software developed by Coda Hale and Yammer, Inc. 19 | 20 | This product includes code derived from the JSR-166 project (ThreadLocalRandom), which was released 21 | with the following comments: 22 | 23 | Written by Doug Lea with assistance from members of JCP JSR-166 24 | Expert Group and released to the public domain, as explained at 25 | http://creativecommons.org/publicdomain/zero/1.0/ 26 | 27 | ************************ 28 | Common Development and Distribution License 1.1 29 | ************************ 30 | 31 | The following binary components are provided under the Common Development and Distribution License 1.1. See project link for details. 32 | 33 | (CDDL 1.1) (GPL2 w/ CPE) JSON Processing API (javax.json:javax.json-api:jar:1.0 - http://json-processing-spec.java.net) 34 | (CDDL 1.1) (GPL2 w/ CPE) JSON Processing Default Provider (org.glassfish:javax.json:jar:1.0.4 - https://jsonp.java.net) 35 | (CDDL 1.1) (GPL2 w/ CPE) OSGi resource locator bundle (org.glassfish.hk2:osgi-resource-locator:jar:1.0.1 - http://glassfish.org/osgi-resource-locator) 36 | (CDDL 1.1) (GPL2 w/ CPE) javax.annotation API (javax.annotation:javax.annotation-api:jar:1.2 - http://jcp.org/en/jsr/detail?id=250) 37 | (CDDL 1.1) (GPL2 w/ CPE) HK2 API module (org.glassfish.hk2:hk2-api:jar:2.4.0-b25 - https://hk2.java.net/hk2-api) 38 | (CDDL 1.1) (GPL2 w/ CPE) ServiceLocator Default Implementation (org.glassfish.hk2:hk2-locator:jar:2.4.0-b25 - https://hk2.java.net/hk2-locator) 39 | (CDDL 1.1) (GPL2 w/ CPE) HK2 Implementation Utilities (org.glassfish.hk2:hk2-utils:jar:2.4.0-b25 - https://hk2.java.net/hk2-utils) 40 | (CDDL 1.1) (GPL2 w/ CPE) aopalliance version 1.0 repackaged as a module (org.glassfish.hk2.external:aopalliance-repackaged:jar:2.4.0-b25 - https://hk2.java.net/external/aopalliance-repackaged) 41 | (CDDL 1.1) (GPL2 w/ CPE) javax.inject:1 as OSGi bundle (org.glassfish.hk2.external:javax.inject:jar:2.4.0-b25 - https://hk2.java.net/external/javax.inject) 42 | (CDDL 1.1) (GPL2 w/ CPE) javax.ws.rs-api (javax.ws.rs:javax.ws.rs-api:jar:2.0.1 - http://jax-rs-spec.java.net) 43 | (CDDL 1.1) (GPL2 w/ CPE) jersey-repackaged-guava (org.glassfish.jersey.bundles.repackaged:jersey-guava:bundle:2.19 - https://jersey.java.net/project/project/jersey-guava/) 44 | (CDDL 1.1) (GPL2 w/ CPE) jersey-core-client (org.glassfish.jersey.core:jersey-client:jar:2.19 - https://jersey.java.net/jersey-client/) 45 | (CDDL 1.1) (GPL2 w/ CPE) jersey-core-common (org.glassfish.jersey.core:jersey-common:jar:2.19 - https://jersey.java.net/jersey-common/) 46 | 47 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Nifi Prometheus Reporter [![Build Status](https://travis-ci.org/mkjoerg/nifi-prometheus-reporter.svg?branch=master)](https://travis-ci.org/mkjoerg/nifi-prometheus-reporter) 2 | 3 | A reporting task in Nifi which is capable of sending monitoring statistics as 4 | prometheus metrics to a prometheus pushgateway. After this, the Prometheus 5 | server scrapes the metrics from the pushgateway. 6 | 7 | ## Getting Started 8 | 9 | For setting up the requirements there is a docker-compose file in docker/prometheus, that sets up the Pushgateway, the Prometheus server and a Grafana server. 10 | After starting the docker containers nifi needs to be downloaded and the ReportingTask has to be copied into the lib directory. 11 | 12 | To setup the test environment have docker-compose and docker installed: [see link](https://docs.docker.com/compose/install/) 13 | ```sh 14 | docker-compose up -d 15 | ``` 16 | This will bootstrap: 17 | * A Prometheus server that runs under: http://localhost:9090 18 | * A Pushgateway that runs under: http://localhost:9091 19 | * A Grafana instance that runs under: http://localhost:3000 20 | * A Nifi instance, containing the reporting task under: http://localhost:8080/nifi 21 | 22 | A sample dashboard can be found here: [Sample Dashboard](https://grafana.com/dashboards/3294) 23 | 24 | After setting up a simple flow and the ReportingTask, the flow can be started and the results should be visible in the Grafana dashboard. 25 | 26 | ## Docs 27 | 28 | See the docs for more details: 29 | 30 | 1. [Configuration](docs/Configuration.md) 31 | 32 | ### Prerequisites 33 | 34 | To test or use the PrometheusReportingTask the following systems should be 35 | setup and running. 36 | * Running Prometheus instance 37 | * Running Prometheus Pushgateway instance 38 | * Running Nifi instance 39 | 40 | The tools can be setup with Docker or manually. 41 | 42 | ### Install to running Nifi instance 43 | First download the [current release](https://github.com/mkjoerg/nifi-prometheus-reporter/releases) and then 44 | copy the nar file into your Nifi lib folder. (Most times under __/opt/nifi//lib__) 45 | 46 | After this, just restart Nifi. 47 | 48 | ### Limitations 49 | The Reporting Task can't send custom metrics from processors to the Pushgateway. If you want 50 | something like this, you have to setup your own processor, that can read FlowFiles, generate custom metrics 51 | and send them to a Pushgateway. Because this is such a custom thing, it can't be done with this Reporting Task 52 | and it is also not the scope of this project. 53 | 54 | ### Build it yourself 55 | 56 | The project can be build with maven as the standard fashion of building 57 | nifi-processor-bundles. Following snippet shows the entire setup with pre-installed Nifi: 58 | ```sh 59 | # Clone project 60 | git clone https://github.com/mkjoerg/nifi-prometheus-reporter.git 61 | # Move into cloned dir 62 | cd nifi-prometheus-reporter 63 | 64 | # Build project 65 | mvn clean install 66 | ``` 67 | The previously built .nar archive has to be copied into the nifi/lib directory 68 | and can be used after a restart of nifi. 69 | ```sh 70 | # Copy .nar into Nifi's lib folder 71 | cp nifi-prometheus-nar/target/nifi-prometheus-nar-1.9.2.nar NIFI_HOME/lib/nifi-prometheus-nar-1.9.2.nar 72 | 73 | # Start nifi 74 | NIFI_HOME/bin/nifi.sh start 75 | # Or restart if already running 76 | NIFI_HOME/bin/nifi.sh restart 77 | 78 | 79 | ## Authors 80 | 81 | * **Matthias Jörg** - *Initial work* - [mkjoerg](https://github.com/mkjoerg) 82 | * **Daniel Seifert** - *Initial work* - [Daniel-Seifert](https://github.com/Daniel-Seifert) 83 | -------------------------------------------------------------------------------- /nifi-prometheus-reporting-task/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 18 | 4.0.0 19 | 20 | org.apache.nifi 21 | nifi-prometheus-bundle 22 | 1.9.2 23 | 24 | 25 | 0.5.0 26 | 2.2.0 27 | 28 | 29 | nifi-prometheus-reporting-task 30 | Publishes NiFi metrics to Prometheus 31 | 32 | 33 | 34 | com.yammer.metrics 35 | metrics-core 36 | ${yammer.metrics.version} 37 | 38 | 39 | org.apache.nifi 40 | nifi-api 41 | 42 | 43 | org.apache.nifi 44 | nifi-utils 45 | ${nifi.version} 46 | 47 | 48 | 49 | io.prometheus 50 | simpleclient 51 | ${prometheus.version} 52 | 53 | 54 | 55 | io.prometheus 56 | simpleclient_hotspot 57 | ${prometheus.version} 58 | 59 | 60 | 61 | io.prometheus 62 | simpleclient_servlet 63 | ${prometheus.version} 64 | 65 | 66 | 67 | io.prometheus 68 | simpleclient_pushgateway 69 | ${prometheus.version} 70 | 71 | 72 | 73 | 74 | org.apache.nifi 75 | nifi-mock 76 | ${nifi.version} 77 | test 78 | 79 | 80 | org.mockito 81 | mockito-all 82 | test 83 | 84 | 85 | 86 | org.glassfish.jersey.core 87 | jersey-client 88 | test 89 | 90 | 91 | org.glassfish 92 | javax.json 93 | 1.0.4 94 | test 95 | 96 | 97 | javax.json 98 | javax.json-api 99 | 1.0 100 | test 101 | 102 | 103 | 104 | 105 | 106 | 107 | org.apache.maven.plugins 108 | maven-surefire-plugin 109 | 2.22.0 110 | 111 | 3 112 | true 113 | -Xmx1024m -XX:MaxPermSize=256m 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /nifi-prometheus-nar/nifi-prometheus-nar.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /nifi-prometheus-reporting-task/src/test/java/org/apache/nifi/reporting/prometheus/metrics/TestMetricsService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.nifi.reporting.prometheus.metrics; 18 | 19 | import com.yammer.metrics.core.VirtualMachineMetrics; 20 | import org.apache.nifi.controller.status.ProcessGroupStatus; 21 | import org.apache.nifi.controller.status.ProcessorStatus; 22 | import org.junit.Assert; 23 | import org.junit.Test; 24 | 25 | import java.util.ArrayList; 26 | import java.util.Collection; 27 | import java.util.Map; 28 | 29 | public class TestMetricsService { 30 | 31 | @Test 32 | public void testGetProcessGroupStatusMetrics() { 33 | ProcessGroupStatus status = new ProcessGroupStatus(); 34 | status.setId("1234"); 35 | status.setFlowFilesReceived(5); 36 | status.setBytesReceived(10000); 37 | status.setFlowFilesSent(10); 38 | status.setBytesSent(20000); 39 | status.setQueuedCount(100); 40 | status.setQueuedContentSize(1024L); 41 | status.setBytesRead(60000L); 42 | status.setBytesWritten(80000L); 43 | status.setActiveThreadCount(5); 44 | 45 | // create a processor status with processing time 46 | ProcessorStatus procStatus = new ProcessorStatus(); 47 | procStatus.setProcessingNanos(123456789); 48 | 49 | Collection processorStatuses = new ArrayList<>(); 50 | processorStatuses.add(procStatus); 51 | status.setProcessorStatus(processorStatuses); 52 | 53 | // create a group status with processing time 54 | ProcessGroupStatus groupStatus = new ProcessGroupStatus(); 55 | groupStatus.setProcessorStatus(processorStatuses); 56 | 57 | Collection groupStatuses = new ArrayList<>(); 58 | groupStatuses.add(groupStatus); 59 | status.setProcessGroupStatus(groupStatuses); 60 | 61 | final MetricsService service = new MetricsService(); 62 | 63 | final Map metrics = service.getMetrics(status, false); 64 | 65 | Assert.assertTrue(metrics.containsKey(MetricNames.FLOW_FILES_RECEIVED)); 66 | Assert.assertTrue(metrics.containsKey(MetricNames.BYTES_RECEIVED)); 67 | Assert.assertTrue(metrics.containsKey(MetricNames.FLOW_FILES_SENT)); 68 | Assert.assertTrue(metrics.containsKey(MetricNames.BYTES_SENT)); 69 | Assert.assertTrue(metrics.containsKey(MetricNames.FLOW_FILES_QUEUED)); 70 | Assert.assertTrue(metrics.containsKey(MetricNames.BYTES_QUEUED)); 71 | Assert.assertTrue(metrics.containsKey(MetricNames.BYTES_READ)); 72 | Assert.assertTrue(metrics.containsKey(MetricNames.BYTES_WRITTEN)); 73 | Assert.assertTrue(metrics.containsKey(MetricNames.ACTIVE_THREADS)); 74 | Assert.assertTrue(metrics.containsKey(MetricNames.TOTAL_TASK_DURATION_SECONDS)); 75 | Assert.assertTrue(metrics.containsKey(MetricNames.TOTAL_TASK_DURATION_NANOS)); 76 | } 77 | 78 | @Test 79 | public void testGetProcessGroupStatusMetricsWithID() { 80 | ProcessGroupStatus status = new ProcessGroupStatus(); 81 | String id = "1234"; 82 | status.setId(id); 83 | status.setFlowFilesReceived(5); 84 | status.setBytesReceived(10000); 85 | status.setFlowFilesSent(10); 86 | status.setBytesSent(20000); 87 | status.setQueuedCount(100); 88 | status.setQueuedContentSize(1024L); 89 | status.setBytesRead(60000L); 90 | status.setBytesWritten(80000L); 91 | status.setActiveThreadCount(5); 92 | 93 | // create a processor status with processing time 94 | ProcessorStatus procStatus = new ProcessorStatus(); 95 | procStatus.setProcessingNanos(123456789); 96 | 97 | Collection processorStatuses = new ArrayList<>(); 98 | processorStatuses.add(procStatus); 99 | status.setProcessorStatus(processorStatuses); 100 | 101 | // create a group status with processing time 102 | ProcessGroupStatus groupStatus = new ProcessGroupStatus(); 103 | groupStatus.setProcessorStatus(processorStatuses); 104 | 105 | Collection groupStatuses = new ArrayList<>(); 106 | groupStatuses.add(groupStatus); 107 | status.setProcessGroupStatus(groupStatuses); 108 | 109 | final MetricsService service = new MetricsService(); 110 | 111 | final Map metrics = service.getMetrics(status, true); 112 | 113 | Assert.assertTrue(metrics.containsKey(MetricNames.FLOW_FILES_RECEIVED + MetricNames.METRIC_NAME_SEPARATOR + id)); 114 | } 115 | 116 | @Test 117 | public void testGetVirtualMachineMetrics() { 118 | final VirtualMachineMetrics virtualMachineMetrics = VirtualMachineMetrics.getInstance(); 119 | final MetricsService service = new MetricsService(); 120 | 121 | final Map metrics = service.getMetrics(virtualMachineMetrics); 122 | Assert.assertTrue(metrics.containsKey(MetricNames.JVM_UPTIME)); 123 | Assert.assertTrue(metrics.containsKey(MetricNames.JVM_HEAP_USED)); 124 | Assert.assertTrue(metrics.containsKey(MetricNames.JVM_HEAP_USAGE)); 125 | Assert.assertTrue(metrics.containsKey(MetricNames.JVM_NON_HEAP_USAGE)); 126 | Assert.assertTrue(metrics.containsKey(MetricNames.JVM_THREAD_STATES_RUNNABLE)); 127 | Assert.assertTrue(metrics.containsKey(MetricNames.JVM_THREAD_STATES_BLOCKED)); 128 | Assert.assertTrue(metrics.containsKey(MetricNames.JVM_THREAD_STATES_TIMED_WAITING)); 129 | Assert.assertTrue(metrics.containsKey(MetricNames.JVM_THREAD_STATES_TERMINATED)); 130 | Assert.assertTrue(metrics.containsKey(MetricNames.JVM_THREAD_COUNT)); 131 | Assert.assertTrue(metrics.containsKey(MetricNames.JVM_DAEMON_THREAD_COUNT)); 132 | Assert.assertTrue(metrics.containsKey(MetricNames.JVM_FILE_DESCRIPTOR_USAGE)); 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /nifi-prometheus-reporting-task/src/test/java/org/apache/nifi/reporting/prometheus/TestPrometheusReportingTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.nifi.reporting.prometheus; 18 | 19 | import org.apache.nifi.controller.status.ProcessGroupStatus; 20 | import org.apache.nifi.controller.status.ProcessorStatus; 21 | import org.apache.nifi.logging.ComponentLog; 22 | import org.apache.nifi.reporting.EventAccess; 23 | import org.apache.nifi.reporting.InitializationException; 24 | import org.apache.nifi.reporting.ReportingContext; 25 | import org.apache.nifi.reporting.ReportingInitializationContext; 26 | import org.apache.nifi.util.MockPropertyValue; 27 | import org.junit.Before; 28 | import org.junit.Test; 29 | import org.mockito.Matchers; 30 | import org.mockito.Mockito; 31 | 32 | import javax.ws.rs.client.Client; 33 | import javax.ws.rs.client.Entity; 34 | import javax.ws.rs.client.Invocation; 35 | import javax.ws.rs.client.WebTarget; 36 | import javax.ws.rs.core.Response; 37 | import java.io.IOException; 38 | import java.util.ArrayList; 39 | import java.util.Collection; 40 | import java.util.UUID; 41 | 42 | public class TestPrometheusReportingTask { 43 | 44 | private ProcessGroupStatus status; 45 | 46 | @Before 47 | public void setup() { 48 | status = new ProcessGroupStatus(); 49 | status.setId("1234"); 50 | status.setName("localTest"); 51 | status.setFlowFilesReceived(5); 52 | status.setFlowFilesSent(10); 53 | status.setFlowFilesTransferred(10); 54 | status.setBytesReceived(10000); 55 | status.setBytesSent(20000); 56 | status.setBytesTransferred(10000); 57 | status.setBytesRead(60000L); 58 | status.setBytesWritten(80000L); 59 | status.setQueuedCount(100); 60 | status.setQueuedContentSize(1024L); 61 | status.setActiveThreadCount(5); 62 | status.setInputCount(10); 63 | status.setOutputCount(20); 64 | status.setQueuedCount(30); 65 | status.setInputContentSize(Integer.toUnsignedLong(0)); 66 | status.setOutputContentSize(Integer.toUnsignedLong(0)); 67 | status.setOutputContentSize(Integer.toUnsignedLong(0)); 68 | 69 | 70 | // create a processor status with processing time 71 | ProcessorStatus procStatus = new ProcessorStatus(); 72 | procStatus.setProcessingNanos(123456789); 73 | 74 | Collection processorStatuses = new ArrayList<>(); 75 | processorStatuses.add(procStatus); 76 | status.setProcessorStatus(processorStatuses); 77 | 78 | // create a group status with processing time 79 | ProcessGroupStatus groupStatus = new ProcessGroupStatus(); 80 | groupStatus.setProcessorStatus(processorStatuses); 81 | 82 | Collection groupStatuses = new ArrayList<>(); 83 | groupStatuses.add(groupStatus); 84 | status.setProcessGroupStatus(groupStatuses); 85 | } 86 | 87 | @Test 88 | public void testOnTrigger() throws InitializationException { 89 | final String metricsUrl = "http://localhost:9091"; 90 | final String applicationId = "nifi"; 91 | final String hostName = "localhost"; 92 | final String jobName = "nifi_reporting_job"; 93 | final boolean jvmMetrics = true; 94 | final boolean authentication = false; 95 | 96 | // create the jersey client mocks for handling the post 97 | final Client client = Mockito.mock(Client.class); 98 | final WebTarget target = Mockito.mock(WebTarget.class); 99 | final Invocation.Builder builder = Mockito.mock(Invocation.Builder.class); 100 | 101 | final Response response = Mockito.mock(Response.class); 102 | Mockito.when(response.getStatus()).thenReturn(200); 103 | 104 | Mockito.when(client.target(metricsUrl)).thenReturn(target); 105 | Mockito.when(target.request()).thenReturn(builder); 106 | Mockito.when(builder.post(Matchers.any(Entity.class))).thenReturn(response); 107 | 108 | // mock the ReportingInitializationContext for initialize(...) 109 | final ComponentLog logger = Mockito.mock(ComponentLog.class); 110 | final ReportingInitializationContext initContext = Mockito.mock(ReportingInitializationContext.class); 111 | Mockito.when(initContext.getIdentifier()).thenReturn(UUID.randomUUID().toString()); 112 | Mockito.when(initContext.getLogger()).thenReturn(logger); 113 | 114 | 115 | // mock the ReportingContext for onTrigger(...) 116 | final ReportingContext context = Mockito.mock(ReportingContext.class); 117 | Mockito.when(context.getProperty(PrometheusReportingTask.METRICS_COLLECTOR_URL)) 118 | .thenReturn(new MockPropertyValue(metricsUrl)); 119 | Mockito.when(context.getProperty(PrometheusReportingTask.APPLICATION_ID)) 120 | .thenReturn(new MockPropertyValue(applicationId)); 121 | Mockito.when(context.getProperty(PrometheusReportingTask.INSTANCE_ID)) 122 | .thenReturn(new MockPropertyValue(hostName)); 123 | Mockito.when(context.getProperty(PrometheusReportingTask.PROCESS_GROUP_IDS)) 124 | .thenReturn(new MockPropertyValue("1234")); 125 | Mockito.when(context.getProperty(PrometheusReportingTask.JOB_NAME)) 126 | .thenReturn(new MockPropertyValue(jobName)); 127 | Mockito.when(context.getProperty(PrometheusReportingTask.SEND_JVM_METRICS)) 128 | .thenReturn(new MockPropertyValue(Boolean.toString(jvmMetrics))); 129 | Mockito.when(context.getProperty(PrometheusReportingTask.USE_AUTHENTICATION)) 130 | .thenReturn(new MockPropertyValue(Boolean.toString(authentication))); 131 | 132 | final EventAccess eventAccess = Mockito.mock(EventAccess.class); 133 | Mockito.when(context.getEventAccess()).thenReturn(eventAccess); 134 | Mockito.when(eventAccess.getControllerStatus()).thenReturn(status); 135 | Mockito.when(eventAccess.getGroupStatus("1234")).thenReturn(status); 136 | 137 | // create a testable instance of the reporting task 138 | final PrometheusReportingTask task = new PrometheusReportingTask(); 139 | task.initialize(initContext); 140 | task.onTrigger(context); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /nifi-prometheus-reporting-task/src/main/java/org/apache/nifi/reporting/prometheus/metrics/MetricsService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.nifi.reporting.prometheus.metrics; 18 | 19 | import com.yammer.metrics.core.VirtualMachineMetrics; 20 | import org.apache.nifi.controller.status.ProcessGroupStatus; 21 | import org.apache.nifi.controller.status.ProcessorStatus; 22 | 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | import java.util.concurrent.TimeUnit; 26 | 27 | /** 28 | * A service used to produce key/value metrics based on a given input. 29 | */ 30 | public class MetricsService { 31 | 32 | /** 33 | * Generates a Map of metrics for a ProcessGroupStatus instance. 34 | * 35 | * @param status a ProcessGroupStatus to get metrics from 36 | * @param appendPgId if true, the process group ID will be appended at the end of the metric name 37 | * @return a map of metrics for the given status 38 | */ 39 | public Map getMetrics(ProcessGroupStatus status, boolean appendPgId) { 40 | final Map metrics = new HashMap<>(); 41 | metrics.put(appendPgId(MetricNames.FLOW_FILES_RECEIVED, status, appendPgId), String.valueOf(status.getFlowFilesReceived())); 42 | metrics.put(appendPgId(MetricNames.BYTES_RECEIVED, status, appendPgId), String.valueOf(status.getBytesReceived())); 43 | metrics.put(appendPgId(MetricNames.FLOW_FILES_SENT, status, appendPgId), String.valueOf(status.getFlowFilesSent())); 44 | metrics.put(appendPgId(MetricNames.BYTES_SENT, status, appendPgId), String.valueOf(status.getBytesSent())); 45 | metrics.put(appendPgId(MetricNames.FLOW_FILES_QUEUED, status, appendPgId), String.valueOf(status.getQueuedCount())); 46 | metrics.put(appendPgId(MetricNames.BYTES_QUEUED, status, appendPgId), String.valueOf(status.getQueuedContentSize())); 47 | metrics.put(appendPgId(MetricNames.BYTES_READ, status, appendPgId), String.valueOf(status.getBytesRead())); 48 | metrics.put(appendPgId(MetricNames.BYTES_WRITTEN, status, appendPgId), String.valueOf(status.getBytesWritten())); 49 | metrics.put(appendPgId(MetricNames.ACTIVE_THREADS, status, appendPgId), String.valueOf(status.getActiveThreadCount())); 50 | 51 | final long durationNanos = calculateProcessingNanos(status); 52 | metrics.put(appendPgId(MetricNames.TOTAL_TASK_DURATION_NANOS, status, appendPgId), String.valueOf(durationNanos)); 53 | 54 | final long durationSeconds = TimeUnit.SECONDS.convert(durationNanos, TimeUnit.NANOSECONDS); 55 | metrics.put(appendPgId(MetricNames.TOTAL_TASK_DURATION_SECONDS, status, appendPgId), String.valueOf(durationSeconds)); 56 | 57 | return metrics; 58 | } 59 | 60 | /** 61 | * Generates a Map of metrics for VirtualMachineMetrics. 62 | * 63 | * @param virtualMachineMetrics a VirtualMachineMetrics instance to get metrics from 64 | * @return a map of metrics from the given VirtualMachineStatus 65 | */ 66 | public Map getMetrics(VirtualMachineMetrics virtualMachineMetrics) { 67 | final Map metrics = new HashMap<>(); 68 | metrics.put(MetricNames.JVM_UPTIME, String.valueOf(virtualMachineMetrics.uptime())); 69 | metrics.put(MetricNames.JVM_HEAP_USED, String.valueOf(virtualMachineMetrics.heapUsed())); 70 | metrics.put(MetricNames.JVM_HEAP_USAGE, String.valueOf(virtualMachineMetrics.heapUsage())); 71 | metrics.put(MetricNames.JVM_NON_HEAP_USAGE, String.valueOf(virtualMachineMetrics.nonHeapUsage())); 72 | metrics.put(MetricNames.JVM_THREAD_COUNT, String.valueOf(virtualMachineMetrics.threadCount())); 73 | metrics.put(MetricNames.JVM_DAEMON_THREAD_COUNT, String.valueOf(virtualMachineMetrics.daemonThreadCount())); 74 | metrics.put(MetricNames.JVM_FILE_DESCRIPTOR_USAGE, String.valueOf(virtualMachineMetrics.fileDescriptorUsage())); 75 | 76 | for (Map.Entry entry : virtualMachineMetrics.threadStatePercentages().entrySet()) { 77 | final int normalizedValue = (int) (100 * (entry.getValue() == null ? 0 : entry.getValue())); 78 | switch (entry.getKey()) { 79 | case BLOCKED: 80 | metrics.put(MetricNames.JVM_THREAD_STATES_BLOCKED, String.valueOf(normalizedValue)); 81 | break; 82 | case RUNNABLE: 83 | metrics.put(MetricNames.JVM_THREAD_STATES_RUNNABLE, String.valueOf(normalizedValue)); 84 | break; 85 | case TERMINATED: 86 | metrics.put(MetricNames.JVM_THREAD_STATES_TERMINATED, String.valueOf(normalizedValue)); 87 | break; 88 | case TIMED_WAITING: 89 | metrics.put(MetricNames.JVM_THREAD_STATES_TIMED_WAITING, String.valueOf(normalizedValue)); 90 | break; 91 | default: 92 | break; 93 | } 94 | } 95 | 96 | for (Map.Entry entry : virtualMachineMetrics.garbageCollectors().entrySet()) { 97 | final String gcName = entry.getKey().replace(" ", ""); 98 | final long runs = entry.getValue().getRuns(); 99 | final long timeMS = entry.getValue().getTime(TimeUnit.MILLISECONDS); 100 | metrics.put(MetricNames.JVM_GC_RUNS + "." + gcName, String.valueOf(runs)); 101 | metrics.put(MetricNames.JVM_GC_TIME + "." + gcName, String.valueOf(timeMS)); 102 | } 103 | 104 | return metrics; 105 | } 106 | 107 | // calculates the total processing time of all processors in nanos 108 | protected long calculateProcessingNanos(final ProcessGroupStatus status) { 109 | long nanos = 0L; 110 | 111 | for (final ProcessorStatus procStats : status.getProcessorStatus()) { 112 | nanos += procStats.getProcessingNanos(); 113 | } 114 | 115 | for (final ProcessGroupStatus childGroupStatus : status.getProcessGroupStatus()) { 116 | nanos += calculateProcessingNanos(childGroupStatus); 117 | } 118 | 119 | return nanos; 120 | } 121 | 122 | // append the process group ID if necessary 123 | private String appendPgId(String name, ProcessGroupStatus status, boolean appendPgId) { 124 | if (appendPgId) { 125 | return name + MetricNames.METRIC_NAME_SEPARATOR + status.getId(); 126 | } else { 127 | return name; 128 | } 129 | } 130 | 131 | } 132 | -------------------------------------------------------------------------------- /nifi-prometheus-reporting-task/src/main/java/org/apache/nifi/reporting/prometheus/api/PrometheusMetricsFactory.java: -------------------------------------------------------------------------------- 1 | package org.apache.nifi.reporting.prometheus.api; 2 | 3 | import com.yammer.metrics.core.VirtualMachineMetrics; 4 | import io.prometheus.client.CollectorRegistry; 5 | import io.prometheus.client.Gauge; 6 | import org.apache.nifi.controller.status.ProcessGroupStatus; 7 | 8 | import java.util.concurrent.TimeUnit; 9 | 10 | /** 11 | * Factory class to create {@link CollectorRegistry}s by several metrics. 12 | */ 13 | public class PrometheusMetricsFactory { 14 | 15 | 16 | private static final CollectorRegistry NIFI_METRICS_REGISTRY = new CollectorRegistry(); 17 | private static final CollectorRegistry JVM_REGISTRY = new CollectorRegistry(); 18 | 19 | 20 | private static final Gauge AMOUNT_FLOWFILES_TOTAL = Gauge.build() 21 | .name("process_group_amount_flowfiles_total") 22 | .help("Total number of FlowFiles in ProcessGroup") 23 | .labelNames("status", "application", "process_group") 24 | .register(NIFI_METRICS_REGISTRY); 25 | 26 | private static final Gauge AMOUNT_BYTES_TOTAL = Gauge.build() 27 | .name("process_group_amount_bytes_total") 28 | .help("Total number of Bytes in ProcessGroup") 29 | .labelNames("status", "application", "process_group") 30 | .register(NIFI_METRICS_REGISTRY); 31 | 32 | private static final Gauge AMOUNT_THREADS_TOTAL = Gauge.build() 33 | .name("process_group_amount_threads_total") 34 | .help("Total amount of threads in ProcessGroup") 35 | .labelNames("status", "application", "process_group") 36 | .register(NIFI_METRICS_REGISTRY); 37 | 38 | private static final Gauge SIZE_CONTENT_TOTAL = Gauge.build() 39 | .name("process_group_size_content_total") 40 | .help("Total size of content in ProcessGroup") 41 | .labelNames("status", "application", "process_group") 42 | .register(NIFI_METRICS_REGISTRY); 43 | 44 | private static final Gauge AMOUNT_ITEMS = Gauge.build() 45 | .name("process_group_amount_items") 46 | .help("Total amount of items in ProcessGroup") 47 | .labelNames("status", "application", "process_group") 48 | .register(NIFI_METRICS_REGISTRY); 49 | 50 | private static final Gauge JVM_HEAP = Gauge.build() 51 | .name("jvm_heap_stats") 52 | .help("The JVM heap stats") 53 | .labelNames("status") 54 | .register(JVM_REGISTRY); 55 | 56 | private static final Gauge JVM_POOL = Gauge.build() 57 | .name("jvm_pool_stats") 58 | .help("The JVM pool stats") 59 | .labelNames("status") 60 | .register(JVM_REGISTRY); 61 | 62 | private static final Gauge JVM_THREAD = Gauge.build() 63 | .name("jvm_thread_stats") 64 | .help("The JVM thread stats") 65 | .labelNames("status") 66 | .register(JVM_REGISTRY); 67 | 68 | private static final Gauge JVM_GC = Gauge.build() 69 | .name("jvm_gc_stats") 70 | .help("The JVM Garbage Collector stats") 71 | .labelNames("status") 72 | .register(JVM_REGISTRY); 73 | 74 | private static final Gauge JVM_STATUS = Gauge.build() 75 | .name("jvm_general_stats") 76 | .help("The JVM general stats") 77 | .labelNames("status") 78 | .register(JVM_REGISTRY); 79 | 80 | public static CollectorRegistry createNifiMetrics(ProcessGroupStatus status, String applicationId) { 81 | String processGroupName = status.getName(); 82 | AMOUNT_FLOWFILES_TOTAL.labels("sent", applicationId, processGroupName).set(status.getFlowFilesSent()); 83 | AMOUNT_FLOWFILES_TOTAL.labels("transferred", applicationId, processGroupName).set(status.getFlowFilesTransferred()); 84 | AMOUNT_FLOWFILES_TOTAL.labels("received", applicationId, processGroupName).set(status.getFlowFilesReceived()); 85 | 86 | AMOUNT_BYTES_TOTAL.labels("sent", applicationId, processGroupName).set(status.getBytesSent()); 87 | AMOUNT_BYTES_TOTAL.labels("read", applicationId, processGroupName).set(status.getBytesRead()); 88 | AMOUNT_BYTES_TOTAL.labels("written", applicationId, processGroupName).set(status.getBytesWritten()); 89 | AMOUNT_BYTES_TOTAL.labels("received", applicationId, processGroupName).set(status.getBytesReceived()); 90 | AMOUNT_BYTES_TOTAL.labels("transferred", applicationId, processGroupName).set(status.getBytesTransferred()); 91 | 92 | SIZE_CONTENT_TOTAL.labels("output", applicationId, processGroupName).set(status.getOutputContentSize()); 93 | SIZE_CONTENT_TOTAL.labels("input", applicationId, processGroupName).set(status.getInputContentSize()); 94 | SIZE_CONTENT_TOTAL.labels("queued", applicationId, processGroupName).set(status.getQueuedContentSize()); 95 | 96 | AMOUNT_ITEMS.labels("output", applicationId, processGroupName).set(status.getOutputCount()); 97 | AMOUNT_ITEMS.labels("input", applicationId, processGroupName).set(status.getInputCount()); 98 | AMOUNT_ITEMS.labels("queued", applicationId, processGroupName).set(status.getQueuedCount()); 99 | 100 | AMOUNT_THREADS_TOTAL.labels("nano", applicationId, processGroupName).set(status.getActiveThreadCount()); 101 | 102 | return NIFI_METRICS_REGISTRY; 103 | } 104 | 105 | public static CollectorRegistry createJvmMetrics(VirtualMachineMetrics jvmMetrics) { 106 | JVM_HEAP.labels("used").set(jvmMetrics.heapUsed()); 107 | JVM_HEAP.labels("usage").set(jvmMetrics.heapUsage()); 108 | JVM_HEAP.labels("non_usage").set(jvmMetrics.nonHeapUsage()); 109 | 110 | JVM_THREAD.labels("count").set(jvmMetrics.threadCount()); 111 | JVM_THREAD.labels("daemon_count").set(jvmMetrics.daemonThreadCount()); 112 | 113 | JVM_STATUS.labels("uptime").set(jvmMetrics.uptime()); 114 | JVM_STATUS.labels("file_descriptor").set(jvmMetrics.fileDescriptorUsage()); 115 | JVM_STATUS.labels("total_init").set(jvmMetrics.totalInit()); 116 | JVM_STATUS.labels("total_max").set(jvmMetrics.totalMax()); 117 | JVM_STATUS.labels("total_committed").set(jvmMetrics.totalCommitted()); 118 | JVM_STATUS.labels("total_used").set(jvmMetrics.totalUsed()); 119 | 120 | // Append thread states 121 | jvmMetrics.threadStatePercentages() 122 | .forEach((state, usage) -> { 123 | String name = state.name().toLowerCase().replaceAll("\\s", "_"); 124 | JVM_THREAD.labels("state_" + name).set(usage); 125 | }); 126 | 127 | // Append GC stats 128 | jvmMetrics.garbageCollectors() 129 | .forEach((name, stat) -> { 130 | name = name.toLowerCase().replaceAll("\\s", "_"); 131 | JVM_GC.labels(name + "_runs").set(stat.getRuns()); 132 | JVM_GC.labels(name + "_time_ms").set(stat.getTime(TimeUnit.MILLISECONDS)); 133 | }); 134 | 135 | // Append pool stats 136 | jvmMetrics.memoryPoolUsage() 137 | .forEach((name, usage) -> { 138 | name = name.toLowerCase().replaceAll("\\s", "_"); 139 | JVM_POOL.labels("mem_pool_" + name).set(usage); 140 | }); 141 | jvmMetrics.getBufferPoolStats() 142 | .forEach((name, stat) -> { 143 | name = name.toLowerCase().replaceAll("\\s", "_"); 144 | JVM_POOL.labels("buff_pool_" + name + "_count").set(stat.getCount()); 145 | JVM_POOL.labels("buff_pool_" + name + "_mem_used").set(stat.getMemoryUsed()); 146 | JVM_POOL.labels("buff_pool_" + name + "_capacity").set(stat.getTotalCapacity()); 147 | }); 148 | 149 | return JVM_REGISTRY; 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /nifi-prometheus-reporting-task/src/main/java/org/apache/nifi/reporting/prometheus/PrometheusReportingTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.apache.nifi.reporting.prometheus; 18 | 19 | import java.io.IOException; 20 | import java.util.ArrayList; 21 | import java.util.Arrays; 22 | import java.util.Collections; 23 | import java.util.List; 24 | import java.util.Map; 25 | import java.util.Objects; 26 | import java.util.regex.Pattern; 27 | 28 | import com.yammer.metrics.core.VirtualMachineMetrics; 29 | import io.prometheus.client.exporter.BasicAuthHttpConnectionFactory; 30 | import io.prometheus.client.exporter.PushGateway; 31 | import org.apache.nifi.annotation.configuration.DefaultSchedule; 32 | import org.apache.nifi.annotation.documentation.CapabilityDescription; 33 | import org.apache.nifi.annotation.documentation.Tags; 34 | import org.apache.nifi.components.PropertyDescriptor; 35 | import org.apache.nifi.components.PropertyValue; 36 | import org.apache.nifi.controller.status.ProcessGroupStatus; 37 | import org.apache.nifi.expression.ExpressionLanguageScope; 38 | import org.apache.nifi.processor.util.StandardValidators; 39 | import org.apache.nifi.reporting.AbstractReportingTask; 40 | import org.apache.nifi.reporting.ReportingContext; 41 | import org.apache.nifi.reporting.prometheus.api.PrometheusMetricsFactory; 42 | import org.apache.nifi.scheduling.SchedulingStrategy; 43 | 44 | /** 45 | * ReportingTask to send metrics from Nifi and JVM to Prometheus PushGateway. 46 | */ 47 | @Tags({"reporting", "prometheus", "metrics"}) 48 | @CapabilityDescription("Sends JVM-metrics as well as Nifi-metrics to a Prometheus PushGateway." + 49 | "Nifi-metrics can be either configured global or on process-group level.") 50 | @DefaultSchedule(strategy = SchedulingStrategy.TIMER_DRIVEN, period = "1 min") 51 | public class PrometheusReportingTask extends AbstractReportingTask { 52 | 53 | private static final String JVM_JOB_NAME = "jvm_global"; 54 | 55 | static final PropertyDescriptor METRICS_COLLECTOR_URL = new PropertyDescriptor.Builder() 56 | .name("Prometheus PushGateway") 57 | .description("The URL of the Prometheus PushGateway Service") 58 | .required(true) 59 | .expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY) 60 | .defaultValue("http://localhost:9091") 61 | .addValidator(StandardValidators.URL_VALIDATOR) 62 | .build(); 63 | static final PropertyDescriptor APPLICATION_ID = new PropertyDescriptor.Builder() 64 | .name("Application ID") 65 | .description("The Application ID to be included in the metrics sent to Prometheus") 66 | .required(true) 67 | .expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY) 68 | .defaultValue("nifi") 69 | .addValidator(StandardValidators.NON_EMPTY_VALIDATOR) 70 | .build(); 71 | static final PropertyDescriptor INSTANCE_ID = new PropertyDescriptor.Builder() 72 | .name("Instance ID") 73 | .description("Id of this NiFi instance to be included in the metrics sent to Prometheus") 74 | .required(true) 75 | .expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY) 76 | .defaultValue("${hostname(true)}") 77 | .addValidator(StandardValidators.NON_EMPTY_VALIDATOR) 78 | .build(); 79 | static final PropertyDescriptor PROCESS_GROUP_IDS = new PropertyDescriptor.Builder() 80 | .name("Process group ID(s)") 81 | .description("If specified, the reporting task will send metrics the configured ProcessGroup(s) only. Multiple IDs should be separated by a comma. If" 82 | + " none of the group-IDs could be found or no IDs are defined, the Nifi-Flow-ProcessGroup is used and global metrics are sent.") 83 | .required(false) 84 | .expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY) 85 | .addValidator(StandardValidators 86 | .createListValidator(true, true 87 | , StandardValidators.createRegexMatchingValidator(Pattern.compile("[0-9a-z-]+")))) 88 | .build(); 89 | static final PropertyDescriptor JOB_NAME = new PropertyDescriptor.Builder() 90 | .name("The job name") 91 | .description("The name of the exporting job") 92 | .defaultValue("nifi_reporting_job") 93 | .expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY) 94 | .addValidator(StandardValidators.NON_EMPTY_VALIDATOR) 95 | .build(); 96 | static final PropertyDescriptor SEND_JVM_METRICS = new PropertyDescriptor.Builder() 97 | .name("Send JVM-metrics") 98 | .description("Send JVM-metrics in addition to the Nifi-metrics") 99 | .allowableValues("true", "false") 100 | .defaultValue("false") 101 | .required(true) 102 | .build(); 103 | static final PropertyDescriptor USE_AUTHENTICATION = new PropertyDescriptor.Builder() 104 | .name("Use URL authentication") 105 | .description("Whether to use URL authentication or not") 106 | .allowableValues("true", "false") 107 | .defaultValue("false") 108 | .required(true) 109 | .build(); 110 | static final PropertyDescriptor AUTH_USERNAME = new PropertyDescriptor.Builder() 111 | .name("Auth username") 112 | .description("Username that is used for URL authentication.") 113 | .addValidator(StandardValidators.NON_EMPTY_VALIDATOR) 114 | .defaultValue("user") 115 | .required(false) 116 | .build(); 117 | static final PropertyDescriptor AUTH_PASSWORD = new PropertyDescriptor.Builder() 118 | .name("Auth password") 119 | .description("Password that is used for URL authentication.") 120 | .addValidator(StandardValidators.NON_EMPTY_VALIDATOR) 121 | .defaultValue("password") 122 | .required(false) 123 | .sensitive(true) 124 | .build(); 125 | 126 | @Override 127 | protected List getSupportedPropertyDescriptors() { 128 | final List properties = new ArrayList<>(); 129 | properties.add(METRICS_COLLECTOR_URL); 130 | properties.add(APPLICATION_ID); 131 | properties.add(INSTANCE_ID); 132 | properties.add(PROCESS_GROUP_IDS); 133 | properties.add(JOB_NAME); 134 | properties.add(SEND_JVM_METRICS); 135 | properties.add(USE_AUTHENTICATION); 136 | properties.add(AUTH_USERNAME); 137 | properties.add(AUTH_PASSWORD); 138 | return properties; 139 | } 140 | 141 | @Override 142 | public void onTrigger(final ReportingContext context) { 143 | final String metricsCollectorUrl = context.getProperty(METRICS_COLLECTOR_URL) 144 | .evaluateAttributeExpressions().getValue() 145 | .replace("http://", ""); 146 | 147 | final String applicationId = context.getProperty(APPLICATION_ID).evaluateAttributeExpressions().getValue(); 148 | final String jobName = context.getProperty(JOB_NAME).getValue(); 149 | final String instance = context.getProperty(INSTANCE_ID).evaluateAttributeExpressions().getValue(); 150 | final Map groupingKey = Collections.singletonMap("instance", instance); 151 | 152 | // Init PushGateway 153 | final PushGateway pushGateway = new PushGateway(metricsCollectorUrl); 154 | if(context.getProperty(USE_AUTHENTICATION).asBoolean()){ 155 | final String username = context.getProperty(AUTH_USERNAME).getValue(); 156 | final String password = context.getProperty(AUTH_PASSWORD).getValue(); 157 | pushGateway.setConnectionFactory(new BasicAuthHttpConnectionFactory(username, password)); 158 | } 159 | 160 | try { 161 | if (context.getProperty(SEND_JVM_METRICS).asBoolean()) { 162 | pushGateway.pushAdd(PrometheusMetricsFactory.createJvmMetrics(VirtualMachineMetrics.getInstance()), JVM_JOB_NAME, groupingKey); 163 | } 164 | } catch (IOException e) { 165 | getLogger().error("Failed pushing JVM-metrics to Prometheus PushGateway due to {}; routing to failure", e); 166 | } 167 | 168 | for (ProcessGroupStatus status : searchProcessGroups(context, context.getProperty(PROCESS_GROUP_IDS))) { 169 | try { 170 | pushGateway.pushAdd(PrometheusMetricsFactory.createNifiMetrics(status, applicationId), jobName, groupingKey); 171 | } catch (IOException e) { 172 | getLogger().error("Failed pushing Nifi-metrics to Prometheus PushGateway due to {}; routing to failure", e); 173 | } 174 | } 175 | } 176 | 177 | /** 178 | * Searches all ProcessGroups defined in a PropertyValue as a comma-separated list of ProcessorGroup-IDs. 179 | * Therefore blanks are trimmed and new-line characters are removed! Processors that can not be found are ignored. 180 | * 181 | * @return List of all ProcessorGroups that were found. 182 | * If no groupIDs are defined or none of them could be found an array containing the root-DataFlow will be returned. 183 | */ 184 | private ProcessGroupStatus[] searchProcessGroups(final ReportingContext context, PropertyValue value) { 185 | if (value.isSet()) { 186 | String content = value.evaluateAttributeExpressions().getValue(); 187 | 188 | ProcessGroupStatus[] groups = Arrays 189 | .stream(content.replace("\n", "").split(",")) 190 | .map(String::trim) 191 | .map(context.getEventAccess()::getGroupStatus) 192 | .filter(Objects::nonNull) 193 | .toArray(ProcessGroupStatus[]::new); 194 | 195 | return groups.length > 0 ? groups : new ProcessGroupStatus[]{context.getEventAccess().getControllerStatus()}; 196 | } else { 197 | return new ProcessGroupStatus[]{context.getEventAccess().getControllerStatus()}; 198 | } 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2017 nifi 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /nifi-prometheus-reporting-task/nifi-prometheus-reporting-task.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /.idea/shelf/current_testing/shelved.patch: -------------------------------------------------------------------------------- 1 | Index: nifi-prometheus-reporting-task/src/main/java/org/apache/nifi/reporting/prometheus/PrometheusReportingTask.java 2 | IDEA additional info: 3 | Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP 4 | <+>/*\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.apache.nifi.reporting.prometheus;\n\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.regex.Pattern;\n\nimport com.yammer.metrics.core.VirtualMachineMetrics;\nimport io.prometheus.client.exporter.BasicAuthHttpConnectionFactory;\nimport io.prometheus.client.exporter.PushGateway;\nimport org.apache.nifi.annotation.configuration.DefaultSchedule;\nimport org.apache.nifi.annotation.documentation.CapabilityDescription;\nimport org.apache.nifi.annotation.documentation.Tags;\nimport org.apache.nifi.components.PropertyDescriptor;\nimport org.apache.nifi.components.PropertyValue;\nimport org.apache.nifi.controller.status.ProcessGroupStatus;\nimport org.apache.nifi.expression.ExpressionLanguageScope;\nimport org.apache.nifi.processor.util.StandardValidators;\nimport org.apache.nifi.reporting.AbstractReportingTask;\nimport org.apache.nifi.reporting.ReportingContext;\nimport org.apache.nifi.reporting.prometheus.api.PrometheusMetricsFactory;\nimport org.apache.nifi.scheduling.SchedulingStrategy;\n\n/**\n * ReportingTask to send metrics from Nifi and JVM to Prometheus PushGateway.\n *\n * Author: Daniel-Seifert\n */\n@Tags({\"reporting\", \"prometheus\", \"metrics\"})\n@CapabilityDescription(\"Sends JVM-metrics as well as Nifi-metrics to a Prometheus PushGateway.\" +\n \"Nifi-metrics can be either configured global or on process-group level.\")\n@DefaultSchedule(strategy = SchedulingStrategy.TIMER_DRIVEN, period = \"1 min\")\npublic class PrometheusReportingTask extends AbstractReportingTask {\n\n private static final String JVM_JOB_NAME = \"jvm_global\";\n\n static final PropertyDescriptor METRICS_COLLECTOR_URL = new PropertyDescriptor.Builder()\n .name(\"Prometheus PushGateway\")\n .description(\"The URL of the Prometheus PushGateway Service\")\n .required(true)\n .expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)\n .defaultValue(\"http://localhost:9091\")\n .addValidator(StandardValidators.URL_VALIDATOR)\n .build();\n static final PropertyDescriptor APPLICATION_ID = new PropertyDescriptor.Builder()\n .name(\"Application ID\")\n .description(\"The Application ID to be included in the metrics sent to Prometheus\")\n .required(true)\n .expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)\n .defaultValue(\"nifi\")\n .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)\n .build();\n static final PropertyDescriptor INSTANCE_ID = new PropertyDescriptor.Builder()\n .name(\"Instance ID\")\n .description(\"Id of this NiFi instance to be included in the metrics sent to Prometheus\")\n .required(true)\n .expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)\n .defaultValue(\"${hostname(true)}\")\n .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)\n .build();\n static final PropertyDescriptor PROCESS_GROUP_IDS = new PropertyDescriptor.Builder()\n .name(\"Process group ID(s)\")\n .description(\"If specified, the reporting task will send metrics the configured ProcessGroup(s) only. Multiple IDs should be separated by a comma. If\"\n + \" none of the group-IDs could be found or no IDs are defined, the Nifi-Flow-ProcessGroup is used and global metrics are sent.\")\n .required(false)\n .expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)\n .addValidator(StandardValidators\n .createListValidator(true, true\n , StandardValidators.createRegexMatchingValidator(Pattern.compile(\"[0-9a-z-]+\"))))\n .build();\n static final PropertyDescriptor JOB_NAME = new PropertyDescriptor.Builder()\n .name(\"The job name\")\n .description(\"The name of the exporting job\")\n .defaultValue(\"nifi_reporting_job\")\n .expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)\n .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)\n .build();\n static final PropertyDescriptor SEND_JVM_METRICS = new PropertyDescriptor.Builder()\n .name(\"Send JVM-metrics\")\n .description(\"Send JVM-metrics in addition to the Nifi-metrics\")\n .allowableValues(\"true\", \"false\")\n .defaultValue(\"false\")\n .required(true)\n .build();\n static final PropertyDescriptor USE_AUTHENTICATION = new PropertyDescriptor.Builder()\n .name(\"Use URL authentication\")\n .description(\"Whether to use URL authentication or not\")\n .allowableValues(\"true\", \"false\")\n .defaultValue(\"false\")\n .required(true)\n .build();\n static final PropertyDescriptor AUTH_USERNAME = new PropertyDescriptor.Builder()\n .name(\"Auth username\")\n .description(\"Username that is used for URL authentication.\")\n .required(false)\n .build();\n static final PropertyDescriptor AUTH_PASSWORD = new PropertyDescriptor.Builder()\n .name(\"Auth password\")\n .description(\"Password that is used for URL authentication.\")\n .required(false)\n .sensitive(true)\n .build();\n\n @Override\n protected List getSupportedPropertyDescriptors() {\n final List properties = new ArrayList<>();\n properties.add(METRICS_COLLECTOR_URL);\n properties.add(APPLICATION_ID);\n properties.add(INSTANCE_ID);\n properties.add(PROCESS_GROUP_IDS);\n properties.add(JOB_NAME);\n properties.add(SEND_JVM_METRICS);\n properties.add(USE_AUTHENTICATION);\n properties.add(AUTH_USERNAME);\n properties.add(AUTH_PASSWORD);\n return properties;\n }\n\n @Override\n public void onTrigger(final ReportingContext context) {\n final String metricsCollectorUrl = context.getProperty(METRICS_COLLECTOR_URL)\n .evaluateAttributeExpressions().getValue()\n .replace(\"http://\", \"\");\n\n final String applicationId = context.getProperty(APPLICATION_ID).evaluateAttributeExpressions().getValue();\n final String jobName = context.getProperty(JOB_NAME).getValue();\n final String instance = context.getProperty(INSTANCE_ID).evaluateAttributeExpressions().getValue();\n final String username = context.getProperty(AUTH_USERNAME).getValue();\n final String password = context.getProperty(AUTH_PASSWORD).getValue();\n final Map groupingKey = Collections.singletonMap(\"instance\", instance);\n\n // Init PushGateway\n final PushGateway pushGateway = new PushGateway(metricsCollectorUrl);\n if(context.getProperty(USE_AUTHENTICATION).asBoolean()){\n pushGateway.setConnectionFactory(new BasicAuthHttpConnectionFactory(username, password));\n }\n\n try {\n if (context.getProperty(SEND_JVM_METRICS).asBoolean()) {\n pushGateway.pushAdd(PrometheusMetricsFactory.createJvmMetrics(VirtualMachineMetrics.getInstance()), JVM_JOB_NAME, groupingKey);\n }\n } catch (IOException e) {\n getLogger().error(\"Failed pushing JVM-metrics to Prometheus PushGateway due to {}; routing to failure\", e);\n }\n\n for (ProcessGroupStatus status : searchProcessGroups(context, context.getProperty(PROCESS_GROUP_IDS))) {\n try {\n pushGateway.pushAdd(PrometheusMetricsFactory.createNifiMetrics(status, applicationId), jobName, groupingKey);\n } catch (IOException e) {\n getLogger().error(\"Failed pushing Nifi-metrics to Prometheus PushGateway due to {}; routing to failure\", e);\n }\n }\n }\n\n /**\n * Searches all ProcessGroups defined in a PropertyValue as a comma-separated list of ProcessorGroup-IDs.\n * Therefore blanks are trimmed and new-line characters are removed! Processors that can not be found are ignored.\n *\n * @return List of all ProcessorGroups that were found.\n * If no groupIDs are defined or none of them could be found an array containing the root-DataFlow will be returned.\n */\n private ProcessGroupStatus[] searchProcessGroups(final ReportingContext context, PropertyValue value) {\n if (value.isSet()) {\n String content = value.evaluateAttributeExpressions().getValue();\n\n ProcessGroupStatus[] groups = Arrays\n .stream(content.replace(\"\\n\", \"\").split(\",\"))\n .map(String::trim)\n .map(context.getEventAccess()::getGroupStatus)\n .filter(Objects::nonNull)\n .toArray(ProcessGroupStatus[]::new);\n\n return groups.length > 0 ? groups : new ProcessGroupStatus[]{context.getEventAccess().getControllerStatus()};\n } else {\n return new ProcessGroupStatus[]{context.getEventAccess().getControllerStatus()};\n }\n }\n}\n 5 | Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP 6 | <+>UTF-8 7 | =================================================================== 8 | --- nifi-prometheus-reporting-task/src/main/java/org/apache/nifi/reporting/prometheus/PrometheusReportingTask.java (date 1533023184000) 9 | +++ nifi-prometheus-reporting-task/src/main/java/org/apache/nifi/reporting/prometheus/PrometheusReportingTask.java (date 1533023858000) 10 | @@ -145,13 +145,13 @@ 11 | final String applicationId = context.getProperty(APPLICATION_ID).evaluateAttributeExpressions().getValue(); 12 | final String jobName = context.getProperty(JOB_NAME).getValue(); 13 | final String instance = context.getProperty(INSTANCE_ID).evaluateAttributeExpressions().getValue(); 14 | - final String username = context.getProperty(AUTH_USERNAME).getValue(); 15 | - final String password = context.getProperty(AUTH_PASSWORD).getValue(); 16 | final Map groupingKey = Collections.singletonMap("instance", instance); 17 | 18 | // Init PushGateway 19 | final PushGateway pushGateway = new PushGateway(metricsCollectorUrl); 20 | if(context.getProperty(USE_AUTHENTICATION).asBoolean()){ 21 | + final String username = context.getProperty(AUTH_USERNAME).getValue(); 22 | + final String password = context.getProperty(AUTH_PASSWORD).getValue(); 23 | pushGateway.setConnectionFactory(new BasicAuthHttpConnectionFactory(username, password)); 24 | } 25 | 26 | Index: nifi-prometheus-reporting-task/src/test/java/org/apache/nifi/reporting/prometheus/TestPrometheusReportingTask.java 27 | IDEA additional info: 28 | Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP 29 | <+>/*\n * Licensed to the Apache Software Foundation (ASF) under one or more\n * contributor license agreements. See the NOTICE file distributed with\n * this work for additional information regarding copyright ownership.\n * The ASF licenses this file to You under the Apache License, Version 2.0\n * (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage org.apache.nifi.reporting.prometheus;\n\nimport org.apache.nifi.controller.status.ProcessGroupStatus;\nimport org.apache.nifi.controller.status.ProcessorStatus;\nimport org.apache.nifi.logging.ComponentLog;\nimport org.apache.nifi.reporting.EventAccess;\nimport org.apache.nifi.reporting.InitializationException;\nimport org.apache.nifi.reporting.ReportingContext;\nimport org.apache.nifi.reporting.ReportingInitializationContext;\nimport org.apache.nifi.util.MockPropertyValue;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.mockito.Matchers;\nimport org.mockito.Mockito;\n\nimport javax.ws.rs.client.Client;\nimport javax.ws.rs.client.Entity;\nimport javax.ws.rs.client.Invocation;\nimport javax.ws.rs.client.WebTarget;\nimport javax.ws.rs.core.Response;\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.UUID;\n\npublic class TestPrometheusReportingTask {\n\n private ProcessGroupStatus status;\n\n @Before\n public void setup() {\n status = new ProcessGroupStatus();\n status.setId(\"1234\");\n status.setName(\"localTest\");\n status.setFlowFilesReceived(5);\n status.setFlowFilesSent(10);\n status.setFlowFilesTransferred(10);\n status.setBytesReceived(10000);\n status.setBytesSent(20000);\n status.setBytesTransferred(10000);\n status.setBytesRead(60000L);\n status.setBytesWritten(80000L);\n status.setQueuedCount(100);\n status.setQueuedContentSize(1024L);\n status.setActiveThreadCount(5);\n status.setInputCount(10);\n status.setOutputCount(20);\n status.setQueuedCount(30);\n status.setInputContentSize(Integer.toUnsignedLong(0));\n status.setOutputContentSize(Integer.toUnsignedLong(0));\n status.setOutputContentSize(Integer.toUnsignedLong(0));\n\n\n // create a processor status with processing time\n ProcessorStatus procStatus = new ProcessorStatus();\n procStatus.setProcessingNanos(123456789);\n\n Collection processorStatuses = new ArrayList<>();\n processorStatuses.add(procStatus);\n status.setProcessorStatus(processorStatuses);\n\n // create a group status with processing time\n ProcessGroupStatus groupStatus = new ProcessGroupStatus();\n groupStatus.setProcessorStatus(processorStatuses);\n\n Collection groupStatuses = new ArrayList<>();\n groupStatuses.add(groupStatus);\n status.setProcessGroupStatus(groupStatuses);\n }\n\n @Test\n public void testOnTrigger() throws InitializationException, IOException {\n final String metricsUrl = \"http://localhost:9091\";\n final String applicationId = \"nifi\";\n final String hostName = \"localhost\";\n final String jobName = \"nifi_reporting_job\";\n final boolean jvmMetrics = true;\n\n // create the jersey client mocks for handling the post\n final Client client = Mockito.mock(Client.class);\n final WebTarget target = Mockito.mock(WebTarget.class);\n final Invocation.Builder builder = Mockito.mock(Invocation.Builder.class);\n\n final Response response = Mockito.mock(Response.class);\n Mockito.when(response.getStatus()).thenReturn(200);\n\n Mockito.when(client.target(metricsUrl)).thenReturn(target);\n Mockito.when(target.request()).thenReturn(builder);\n Mockito.when(builder.post(Matchers.any(Entity.class))).thenReturn(response);\n\n // mock the ReportingInitializationContext for initialize(...)\n final ComponentLog logger = Mockito.mock(ComponentLog.class);\n final ReportingInitializationContext initContext = Mockito.mock(ReportingInitializationContext.class);\n Mockito.when(initContext.getIdentifier()).thenReturn(UUID.randomUUID().toString());\n Mockito.when(initContext.getLogger()).thenReturn(logger);\n\n\n // mock the ReportingContext for onTrigger(...)\n final ReportingContext context = Mockito.mock(ReportingContext.class);\n Mockito.when(context.getProperty(PrometheusReportingTask.METRICS_COLLECTOR_URL))\n .thenReturn(new MockPropertyValue(metricsUrl));\n Mockito.when(context.getProperty(PrometheusReportingTask.APPLICATION_ID))\n .thenReturn(new MockPropertyValue(applicationId));\n Mockito.when(context.getProperty(PrometheusReportingTask.INSTANCE_ID))\n .thenReturn(new MockPropertyValue(hostName));\n Mockito.when(context.getProperty(PrometheusReportingTask.PROCESS_GROUP_IDS))\n .thenReturn(new MockPropertyValue(\"1234\"));\n Mockito.when(context.getProperty(PrometheusReportingTask.JOB_NAME))\n .thenReturn(new MockPropertyValue(jobName));\n Mockito.when(context.getProperty(PrometheusReportingTask.SEND_JVM_METRICS))\n .thenReturn(new MockPropertyValue(Boolean.toString(jvmMetrics)));\n\n final EventAccess eventAccess = Mockito.mock(EventAccess.class);\n Mockito.when(context.getEventAccess()).thenReturn(eventAccess);\n Mockito.when(eventAccess.getControllerStatus()).thenReturn(status);\n Mockito.when(eventAccess.getGroupStatus(\"1234\")).thenReturn(status);\n\n // create a testable instance of the reporting task\n final PrometheusReportingTask task = new PrometheusReportingTask();\n task.initialize(initContext);\n task.onTrigger(context);\n }\n}\n 30 | Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP 31 | <+>UTF-8 32 | =================================================================== 33 | --- nifi-prometheus-reporting-task/src/test/java/org/apache/nifi/reporting/prometheus/TestPrometheusReportingTask.java (date 1533023184000) 34 | +++ nifi-prometheus-reporting-task/src/test/java/org/apache/nifi/reporting/prometheus/TestPrometheusReportingTask.java (date 1533024049000) 35 | @@ -91,6 +91,7 @@ 36 | final String hostName = "localhost"; 37 | final String jobName = "nifi_reporting_job"; 38 | final boolean jvmMetrics = true; 39 | + final boolean authentication = false; 40 | 41 | // create the jersey client mocks for handling the post 42 | final Client client = Mockito.mock(Client.class); 43 | @@ -125,6 +126,8 @@ 44 | .thenReturn(new MockPropertyValue(jobName)); 45 | Mockito.when(context.getProperty(PrometheusReportingTask.SEND_JVM_METRICS)) 46 | .thenReturn(new MockPropertyValue(Boolean.toString(jvmMetrics))); 47 | + Mockito.when(context.getProperty(PrometheusReportingTask.USE_AUTHENTICATION)) 48 | + .thenReturn(new MockPropertyValue(Boolean.toString(authentication))); 49 | 50 | final EventAccess eventAccess = Mockito.mock(EventAccess.class); 51 | Mockito.when(context.getEventAccess()).thenReturn(eventAccess); 52 | --------------------------------------------------------------------------------