Core metrics prometheus collector

This commit is contained in:
Diana Corbacho 2019-03-04 12:29:47 +00:00
commit 0490a43f17
11 changed files with 8084 additions and 0 deletions

17
deps/rabbitmq_prometheus/.gitignore vendored Normal file
View File

@ -0,0 +1,17 @@
.sw?
.*.sw?
*.beam
*~
\#*
.#*
*.d
/.erlang.mk/
/cover/
/deps/
/doc/
/ebin/
/logs/
/plugins/
/rabbitmq_management_metrics.d
erl_crash.dump

View File

@ -0,0 +1,44 @@
# Contributor Code of Conduct
As contributors and maintainers of this project, and in the interest of fostering an open
and welcoming community, we pledge to respect all people who contribute through reporting
issues, posting feature requests, updating documentation, submitting pull requests or
patches, and other activities.
We are committed to making participation in this project a harassment-free experience for
everyone, regardless of level of experience, gender, gender identity and expression,
sexual orientation, disability, personal appearance, body size, race, ethnicity, age,
religion, or nationality.
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery
* Personal attacks
* Trolling or insulting/derogatory comments
* Public or private harassment
* Publishing other's private information, such as physical or electronic addresses,
without explicit permission
* Other unethical or unprofessional conduct
Project maintainers have the right and responsibility to remove, edit, or reject comments,
commits, code, wiki edits, issues, and other contributions that are not aligned to this
Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors
that they deem inappropriate, threatening, offensive, or harmful.
By adopting this Code of Conduct, project maintainers commit themselves to fairly and
consistently applying these principles to every aspect of managing this project. Project
maintainers who do not follow or enforce the Code of Conduct may be permanently removed
from the project team.
This Code of Conduct applies both within project spaces and in public spaces when an
individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by
contacting a project maintainer at [info@rabbitmq.com](mailto:info@rabbitmq.com). All complaints will
be reviewed and investigated and will result in a response that is deemed necessary and
appropriate to the circumstances. Maintainers are obligated to maintain confidentiality
with regard to the reporter of an incident.
This Code of Conduct is adapted from the
[Contributor Covenant](http://contributor-covenant.org), version 1.3.0, available at
[contributor-covenant.org/version/1/3/0/](http://contributor-covenant.org/version/1/3/0/)

View File

@ -0,0 +1,99 @@
Thank you for using RabbitMQ and for taking the time to contribute to the project.
This document has two main parts:
* when and how to file GitHub issues for RabbitMQ projects
* how to submit pull requests
They intend to save you and RabbitMQ maintainers some time, so please
take a moment to read through them.
## Overview
### GitHub issues
The RabbitMQ team uses GitHub issues for _specific actionable items_ that
engineers can work on. This assumes the following:
* GitHub issues are not used for questions, investigations, root cause
analysis, discussions of potential issues, etc (as defined by this team)
* Enough information is provided by the reporter for maintainers to work with
The team receives many questions through various venues every single
day. Frequently, these questions do not include the necessary details
the team needs to begin useful work. GitHub issues can very quickly
turn into a something impossible to navigate and make sense
of. Because of this, questions, investigations, root cause analysis,
and discussions of potential features are all considered to be
[mailing list][rmq-users] material. If you are unsure where to begin,
the [RabbitMQ users mailing list][rmq-users] is the right place.
Getting all the details necessary to reproduce an issue, make a
conclusion or even form a hypothesis about what's happening can take a
fair amount of time. Please help others help you by providing a way to
reproduce the behavior you're observing, or at least sharing as much
relevant information as possible on the [RabbitMQ users mailing
list][rmq-users].
Please provide versions of the software used:
* RabbitMQ server
* Erlang
* Operating system version (and distribution, if applicable)
* All client libraries used
* RabbitMQ plugins (if applicable)
The following information greatly helps in investigating and reproducing issues:
* RabbitMQ server logs
* A code example or terminal transcript that can be used to reproduce
* Full exception stack traces (a single line message is not enough!)
* `rabbitmqctl report` and `rabbitmqctl environment` output
* Other relevant details about the environment and workload, e.g. a traffic capture
* Feel free to edit out hostnames and other potentially sensitive information.
To make collecting much of this and other environment information, use
the [`rabbitmq-collect-env`][rmq-collect-env] script. It will produce an archive with
server logs, operating system logs, output of certain diagnostics commands and so on.
Please note that **no effort is made to scrub any information that may be sensitive**.
### Pull Requests
RabbitMQ projects use pull requests to discuss, collaborate on and accept code contributions.
Pull requests is the primary place of discussing code changes.
Here's the recommended workflow:
* [Fork the repository][github-fork] or repositories you plan on contributing to. If multiple
repositories are involved in addressing the same issue, please use the same branch name
in each repository
* Create a branch with a descriptive name in the relevant repositories
* Make your changes, run tests (usually with `make tests`), commit with a
[descriptive message][git-commit-msgs], push to your fork
* Submit pull requests with an explanation what has been changed and **why**
* Submit a filled out and signed [Contributor Agreement][ca-agreement] if needed (see below)
* Be patient. We will get to your pull request eventually
If what you are going to work on is a substantial change, please first
ask the core team for their opinion on the [RabbitMQ users mailing list][rmq-users].
## Code of Conduct
See [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md).
## Contributor Agreement
If you want to contribute a non-trivial change, please submit a signed
copy of our [Contributor Agreement][ca-agreement] around the time you
submit your pull request. This will make it much easier (in some
cases, possible) for the RabbitMQ team at Pivotal to merge your
contribution.
## Where to Ask Questions
If something isn't clear, feel free to ask on our [mailing list][rmq-users].
[rmq-collect-env]: https://github.com/rabbitmq/support-tools/blob/master/scripts/rabbitmq-collect-env
[git-commit-msgs]: https://chris.beams.io/posts/git-commit/
[rmq-users]: https://groups.google.com/forum/#!forum/rabbitmq-users
[ca-agreement]: https://cla.pivotal.io/sign/rabbitmq
[github-fork]: https://help.github.com/articles/fork-a-repo/

21
deps/rabbitmq_prometheus/Makefile vendored Normal file
View File

@ -0,0 +1,21 @@
PROJECT = rabbitmq_prometheus
PROJECT_MOD = rabbit_prometheus_app
dep_prometheus = hex 3.5.1
dep_prometheus_httpd = hex 2.1.8
dep_accept = hex 0.3.3
dep_prometheus_cowboy = hex 0.1.4
DEPS = rabbit_common rabbit prometheus prometheus_httpd accept prometheus_cowboy rabbitmq_web_dispatch
DEP_EARLY_PLUGINS = rabbit_common/mk/rabbitmq-early-plugin.mk
DEP_PLUGINS = rabbit_common/mk/rabbitmq-plugin.mk
# FIXME: Use erlang.mk patched for RabbitMQ, while waiting for PRs to be
# reviewed and merged.
ERLANG_MK_REPO = https://github.com/rabbitmq/erlang.mk.git
ERLANG_MK_COMMIT = rabbitmq-tmp
include rabbitmq-components.mk
include erlang.mk

39
deps/rabbitmq_prometheus/README.md vendored Normal file
View File

@ -0,0 +1,39 @@
# RabbitMQ Prometheus.io core metrics exporter
## Getting Started
This is an Prometheus.io core metrics exporter plugin for RabbitMQ.
The plugin is included in the RabbitMQ distribution. To enable
it, use [rabbitmq-plugins](http://www.rabbitmq.com/man/rabbitmq-plugins.1.man.html):
rabbitmq-plugins enable rabbitmq_prometheus
Default port used by the plugin is `15673`.
## Configuration
This exporter supports the following options via `rabbitmq_prometheus` app env:
- `path` - scrape endpoint. Default is `"metrics"`.
- `ssl_config`
- `tcp_config`
Sample `/etc/rabbitmq/rabbitmq.config`:
```erlang
[
{rabbitmq_exporter, [
{path, "/mymetrics"},
{tcp_config, [{port, 15673}]}
]}
].
```
## Contributing
See [CONTRIBUTING.md](https://github.com/rabbitmq/rabbitmq-prometheus/blob/master/CONTRIBUTING.md).
## Copyright
(c) Pivotal Software Inc., 2007-2019.

7080
deps/rabbitmq_prometheus/erlang.mk vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,320 @@
ifeq ($(.DEFAULT_GOAL),)
# Define default goal to `all` because this file defines some targets
# before the inclusion of erlang.mk leading to the wrong target becoming
# the default.
.DEFAULT_GOAL = all
endif
# PROJECT_VERSION defaults to:
# 1. the version exported by rabbitmq-server-release;
# 2. the version stored in `git-revisions.txt`, if it exists;
# 3. a version based on git-describe(1), if it is a Git clone;
# 4. 0.0.0
PROJECT_VERSION := $(RABBITMQ_VERSION)
ifeq ($(PROJECT_VERSION),)
PROJECT_VERSION := $(shell \
if test -f git-revisions.txt; then \
head -n1 git-revisions.txt | \
awk '{print $$$(words $(PROJECT_DESCRIPTION) version);}'; \
else \
(git describe --dirty --abbrev=7 --tags --always --first-parent \
2>/dev/null || echo rabbitmq_v0_0_0) | \
sed -e 's/^rabbitmq_v//' -e 's/^v//' -e 's/_/./g' -e 's/-/+/' \
-e 's/-/./g'; \
fi)
endif
# --------------------------------------------------------------------
# RabbitMQ components.
# --------------------------------------------------------------------
# For RabbitMQ repositories, we want to checkout branches which match
# the parent project. For instance, if the parent project is on a
# release tag, dependencies must be on the same release tag. If the
# parent project is on a topic branch, dependencies must be on the same
# topic branch or fallback to `stable` or `master` whichever was the
# base of the topic branch.
dep_amqp_client = git_rmq rabbitmq-erlang-client $(current_rmq_ref) $(base_rmq_ref) master
dep_amqp10_client = git_rmq rabbitmq-amqp1.0-client $(current_rmq_ref) $(base_rmq_ref) master
dep_amqp10_common = git_rmq rabbitmq-amqp1.0-common $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbit = git_rmq rabbitmq-server $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbit_common = git_rmq rabbitmq-common $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_amqp1_0 = git_rmq rabbitmq-amqp1.0 $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_auth_backend_amqp = git_rmq rabbitmq-auth-backend-amqp $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_auth_backend_cache = git_rmq rabbitmq-auth-backend-cache $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_auth_backend_http = git_rmq rabbitmq-auth-backend-http $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_auth_backend_ldap = git_rmq rabbitmq-auth-backend-ldap $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_auth_mechanism_ssl = git_rmq rabbitmq-auth-mechanism-ssl $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_aws = git_rmq rabbitmq-aws $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_boot_steps_visualiser = git_rmq rabbitmq-boot-steps-visualiser $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_cli = git_rmq rabbitmq-cli $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_codegen = git_rmq rabbitmq-codegen $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_consistent_hash_exchange = git_rmq rabbitmq-consistent-hash-exchange $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_ct_client_helpers = git_rmq rabbitmq-ct-client-helpers $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_ct_helpers = git_rmq rabbitmq-ct-helpers $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_delayed_message_exchange = git_rmq rabbitmq-delayed-message-exchange $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_dotnet_client = git_rmq rabbitmq-dotnet-client $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_event_exchange = git_rmq rabbitmq-event-exchange $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_federation = git_rmq rabbitmq-federation $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_federation_management = git_rmq rabbitmq-federation-management $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_java_client = git_rmq rabbitmq-java-client $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_jms_client = git_rmq rabbitmq-jms-client $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_jms_cts = git_rmq rabbitmq-jms-cts $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_jms_topic_exchange = git_rmq rabbitmq-jms-topic-exchange $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_lvc_exchange = git_rmq rabbitmq-lvc-exchange $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_management = git_rmq rabbitmq-management $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_management_agent = git_rmq rabbitmq-management-agent $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_management_exchange = git_rmq rabbitmq-management-exchange $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_management_themes = git_rmq rabbitmq-management-themes $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_message_timestamp = git_rmq rabbitmq-message-timestamp $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_metronome = git_rmq rabbitmq-metronome $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_mqtt = git_rmq rabbitmq-mqtt $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_objc_client = git_rmq rabbitmq-objc-client $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_peer_discovery_aws = git_rmq rabbitmq-peer-discovery-aws $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_peer_discovery_common = git_rmq rabbitmq-peer-discovery-common $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_peer_discovery_consul = git_rmq rabbitmq-peer-discovery-consul $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_peer_discovery_etcd = git_rmq rabbitmq-peer-discovery-etcd $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_peer_discovery_k8s = git_rmq rabbitmq-peer-discovery-k8s $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_random_exchange = git_rmq rabbitmq-random-exchange $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_recent_history_exchange = git_rmq rabbitmq-recent-history-exchange $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_routing_node_stamp = git_rmq rabbitmq-routing-node-stamp $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_rtopic_exchange = git_rmq rabbitmq-rtopic-exchange $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_server_release = git_rmq rabbitmq-server-release $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_sharding = git_rmq rabbitmq-sharding $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_shovel = git_rmq rabbitmq-shovel $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_shovel_management = git_rmq rabbitmq-shovel-management $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_stomp = git_rmq rabbitmq-stomp $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_toke = git_rmq rabbitmq-toke $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_top = git_rmq rabbitmq-top $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_tracing = git_rmq rabbitmq-tracing $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_trust_store = git_rmq rabbitmq-trust-store $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_test = git_rmq rabbitmq-test $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_web_dispatch = git_rmq rabbitmq-web-dispatch $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_web_stomp = git_rmq rabbitmq-web-stomp $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_web_stomp_examples = git_rmq rabbitmq-web-stomp-examples $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_web_mqtt = git_rmq rabbitmq-web-mqtt $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_web_mqtt_examples = git_rmq rabbitmq-web-mqtt-examples $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_website = git_rmq rabbitmq-website $(current_rmq_ref) $(base_rmq_ref) live master
dep_toke = git_rmq toke $(current_rmq_ref) $(base_rmq_ref) master
dep_rabbitmq_public_umbrella = git_rmq rabbitmq-public-umbrella $(current_rmq_ref) $(base_rmq_ref) master
# Third-party dependencies version pinning.
#
# We do that in this file, which is copied in all projects, to ensure
# all projects use the same versions. It avoids conflicts and makes it
# possible to work with rabbitmq-public-umbrella.
dep_cowboy = hex 2.6.1
dep_cowlib = hex 2.7.0
dep_jsx = hex 2.9.0
dep_lager = hex 3.6.5
dep_ra = git https://github.com/rabbitmq/ra.git master
dep_ranch = hex 1.7.1
dep_recon = hex 2.3.6
dep_sysmon_handler = hex 1.1.0
RABBITMQ_COMPONENTS = amqp_client \
amqp10_common \
amqp10_client \
rabbit \
rabbit_common \
rabbitmq_amqp1_0 \
rabbitmq_auth_backend_amqp \
rabbitmq_auth_backend_cache \
rabbitmq_auth_backend_http \
rabbitmq_auth_backend_ldap \
rabbitmq_auth_mechanism_ssl \
rabbitmq_aws \
rabbitmq_boot_steps_visualiser \
rabbitmq_cli \
rabbitmq_codegen \
rabbitmq_consistent_hash_exchange \
rabbitmq_ct_client_helpers \
rabbitmq_ct_helpers \
rabbitmq_delayed_message_exchange \
rabbitmq_dotnet_client \
rabbitmq_event_exchange \
rabbitmq_federation \
rabbitmq_federation_management \
rabbitmq_java_client \
rabbitmq_jms_client \
rabbitmq_jms_cts \
rabbitmq_jms_topic_exchange \
rabbitmq_lvc_exchange \
rabbitmq_management \
rabbitmq_management_agent \
rabbitmq_management_exchange \
rabbitmq_management_themes \
rabbitmq_message_timestamp \
rabbitmq_metronome \
rabbitmq_mqtt \
rabbitmq_objc_client \
rabbitmq_peer_discovery_aws \
rabbitmq_peer_discovery_common \
rabbitmq_peer_discovery_consul \
rabbitmq_peer_discovery_etcd \
rabbitmq_peer_discovery_k8s \
rabbitmq_random_exchange \
rabbitmq_recent_history_exchange \
rabbitmq_routing_node_stamp \
rabbitmq_rtopic_exchange \
rabbitmq_server_release \
rabbitmq_sharding \
rabbitmq_shovel \
rabbitmq_shovel_management \
rabbitmq_stomp \
rabbitmq_toke \
rabbitmq_top \
rabbitmq_tracing \
rabbitmq_trust_store \
rabbitmq_web_dispatch \
rabbitmq_web_mqtt \
rabbitmq_web_mqtt_examples \
rabbitmq_web_stomp \
rabbitmq_web_stomp_examples \
rabbitmq_website
# Several components have a custom erlang.mk/build.config, mainly
# to disable eunit. Therefore, we can't use the top-level project's
# erlang.mk copy.
NO_AUTOPATCH += $(RABBITMQ_COMPONENTS)
ifeq ($(origin current_rmq_ref),undefined)
ifneq ($(wildcard .git),)
current_rmq_ref := $(shell (\
ref=$$(LANG=C git branch --list | awk '/^\* \(.*detached / {ref=$$0; sub(/.*detached [^ ]+ /, "", ref); sub(/\)$$/, "", ref); print ref; exit;} /^\* / {ref=$$0; sub(/^\* /, "", ref); print ref; exit}');\
if test "$$(git rev-parse --short HEAD)" != "$$ref"; then echo "$$ref"; fi))
else
current_rmq_ref := master
endif
endif
export current_rmq_ref
ifeq ($(origin base_rmq_ref),undefined)
ifneq ($(wildcard .git),)
possible_base_rmq_ref := master
ifeq ($(possible_base_rmq_ref),$(current_rmq_ref))
base_rmq_ref := $(current_rmq_ref)
else
base_rmq_ref := $(shell \
(git rev-parse --verify -q master >/dev/null && \
git rev-parse --verify -q $(possible_base_rmq_ref) >/dev/null && \
git merge-base --is-ancestor $$(git merge-base master HEAD) $(possible_base_rmq_ref) && \
echo $(possible_base_rmq_ref)) || \
echo master)
endif
else
base_rmq_ref := master
endif
endif
export base_rmq_ref
# Repository URL selection.
#
# First, we infer other components' location from the current project
# repository URL, if it's a Git repository:
# - We take the "origin" remote URL as the base
# - The current project name and repository name is replaced by the
# target's properties:
# eg. rabbitmq-common is replaced by rabbitmq-codegen
# eg. rabbit_common is replaced by rabbitmq_codegen
#
# If cloning from this computed location fails, we fallback to RabbitMQ
# upstream which is GitHub.
# Macro to transform eg. "rabbit_common" to "rabbitmq-common".
rmq_cmp_repo_name = $(word 2,$(dep_$(1)))
# Upstream URL for the current project.
RABBITMQ_COMPONENT_REPO_NAME := $(call rmq_cmp_repo_name,$(PROJECT))
RABBITMQ_UPSTREAM_FETCH_URL ?= https://github.com/rabbitmq/$(RABBITMQ_COMPONENT_REPO_NAME).git
RABBITMQ_UPSTREAM_PUSH_URL ?= git@github.com:rabbitmq/$(RABBITMQ_COMPONENT_REPO_NAME).git
# Current URL for the current project. If this is not a Git clone,
# default to the upstream Git repository.
ifneq ($(wildcard .git),)
git_origin_fetch_url := $(shell git config remote.origin.url)
git_origin_push_url := $(shell git config remote.origin.pushurl || git config remote.origin.url)
RABBITMQ_CURRENT_FETCH_URL ?= $(git_origin_fetch_url)
RABBITMQ_CURRENT_PUSH_URL ?= $(git_origin_push_url)
else
RABBITMQ_CURRENT_FETCH_URL ?= $(RABBITMQ_UPSTREAM_FETCH_URL)
RABBITMQ_CURRENT_PUSH_URL ?= $(RABBITMQ_UPSTREAM_PUSH_URL)
endif
# Macro to replace the following pattern:
# 1. /foo.git -> /bar.git
# 2. /foo -> /bar
# 3. /foo/ -> /bar/
subst_repo_name = $(patsubst %/$(1)/%,%/$(2)/%,$(patsubst %/$(1),%/$(2),$(patsubst %/$(1).git,%/$(2).git,$(3))))
# Macro to replace both the project's name (eg. "rabbit_common") and
# repository name (eg. "rabbitmq-common") by the target's equivalent.
#
# This macro is kept on one line because we don't want whitespaces in
# the returned value, as it's used in $(dep_fetch_git_rmq) in a shell
# single-quoted string.
dep_rmq_repo = $(if $(dep_$(2)),$(call subst_repo_name,$(PROJECT),$(2),$(call subst_repo_name,$(RABBITMQ_COMPONENT_REPO_NAME),$(call rmq_cmp_repo_name,$(2)),$(1))),$(pkg_$(1)_repo))
dep_rmq_commits = $(if $(dep_$(1)), \
$(wordlist 3,$(words $(dep_$(1))),$(dep_$(1))), \
$(pkg_$(1)_commit))
define dep_fetch_git_rmq
fetch_url1='$(call dep_rmq_repo,$(RABBITMQ_CURRENT_FETCH_URL),$(1))'; \
fetch_url2='$(call dep_rmq_repo,$(RABBITMQ_UPSTREAM_FETCH_URL),$(1))'; \
if test "$$$$fetch_url1" != '$(RABBITMQ_CURRENT_FETCH_URL)' && \
git clone -q -n -- "$$$$fetch_url1" $(DEPS_DIR)/$(call dep_name,$(1)); then \
fetch_url="$$$$fetch_url1"; \
push_url='$(call dep_rmq_repo,$(RABBITMQ_CURRENT_PUSH_URL),$(1))'; \
elif git clone -q -n -- "$$$$fetch_url2" $(DEPS_DIR)/$(call dep_name,$(1)); then \
fetch_url="$$$$fetch_url2"; \
push_url='$(call dep_rmq_repo,$(RABBITMQ_UPSTREAM_PUSH_URL),$(1))'; \
fi; \
cd $(DEPS_DIR)/$(call dep_name,$(1)) && ( \
$(foreach ref,$(call dep_rmq_commits,$(1)), \
git checkout -q $(ref) >/dev/null 2>&1 || \
) \
(echo "error: no valid pathspec among: $(call dep_rmq_commits,$(1))" \
1>&2 && false) ) && \
(test "$$$$fetch_url" = "$$$$push_url" || \
git remote set-url --push origin "$$$$push_url")
endef
# --------------------------------------------------------------------
# Component distribution.
# --------------------------------------------------------------------
list-dist-deps::
@:
prepare-dist::
@:
# --------------------------------------------------------------------
# Umbrella-specific settings.
# --------------------------------------------------------------------
# If this project is under the Umbrella project, we override $(DEPS_DIR)
# to point to the Umbrella's one. We also disable `make distclean` so
# $(DEPS_DIR) is not accidentally removed.
ifneq ($(wildcard ../../UMBRELLA.md),)
UNDER_UMBRELLA = 1
else ifneq ($(wildcard UMBRELLA.md),)
UNDER_UMBRELLA = 1
endif
ifeq ($(UNDER_UMBRELLA),1)
ifneq ($(PROJECT),rabbitmq_public_umbrella)
DEPS_DIR ?= $(abspath ..)
endif
ifneq ($(filter distclean distclean-deps,$(MAKECMDGOALS)),)
SKIP_DEPS = 1
endif
endif

View File

@ -0,0 +1,261 @@
%% The contents of this file are subject to the Mozilla Public License
%% Version 1.1 (the "License"); you may not use this file except in
%% compliance with the License. You may obtain a copy of the License at
%% http://www.mozilla.org/MPL/
%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
%% License for the specific language governing rights and limitations
%% under the License.
%%
%% The Original Code is RabbitMQ.
%%
%% The Initial Developer of the Original Code is GoPivotal, Inc.
%% Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
%%
-module(prometheus_rabbitmq_core_metrics_collector).
-export([register/0,
register/1,
deregister_cleanup/1,
collect_mf/2,
collect_metrics/2]).
-import(prometheus_model_helpers, [create_mf/4,
create_mf/5,
label_pairs/1,
gauge_metrics/1,
gauge_metric/1,
gauge_metric/2,
counter_metric/1,
counter_metric/2,
untyped_metric/1,
untyped_metric/2]).
-include_lib("prometheus/include/prometheus.hrl").
-include_lib("rabbit_common/include/rabbit.hrl").
-behaviour(prometheus_collector).
-define(METRIC_NAME_PREFIX, "rabbitmq_core_").
-define(METRICS,
[
{connection_coarse_metrics, [{2, connection_recv_oct, counter, "Count of octects received on the connection."},
{3, connection_send_oct, counter, "Count of octects sent on the connection."},
{4, connection_reductions, counter, "Count of reductions that take place on the queue process."}
]},
{queue_coarse_metrics, [{2, queue_messages_ready, gauge, "Number of messages ready to be delivered to clients."},
{3, queue_messages_unacknowledge, gauge, "Number of messages delivered to clients but not yet acknowledged."},
{4, queue_messages, gauge, "Sum of ready and unacknowledged messages (queue depth)."},
{5, queue_reductions, counter, "Count of reductions that take place on the queue process."}
]},
{channel_exchange_metrics, [{2, channel_exchange_publish, gauge, "Count of messages published."},
{3, channel_exchange_confirm, gauge, "Count of messages confirmed."},
{4, channel_exchange_return_unroutable, gauge, "Count of messages returned to publisher as unroutable."}
]},
{channel_process_metrics, [{2, channel_process_reductions, counter, "Count of reductions that take place on the channel process."}
]},
{queue_metrics, [{2, queue_disk_reads, gauge, "Total number of times messages have been read from disk by this queue.", disk_reads},
{2, queue_disk_writes, gauge, "Total number of times messages have been written to disk by this queue.", disk_writes}
]},
{node_persister_metrics,
[{2, node_io_read_count, counter, "Read operations since node start.", io_read_count},
{2, node_io_read_bytes, gauge, "Bytes read since node start.", io_read_bytes},
{2, node_io_read_time, gauge, "Total time of read operations.", io_read_time},
{2, node_io_write_count, counter, "Write operations since node start.", io_write_count},
{2, node_io_write_bytes, gauge, "Bytes written since node start.", io_write_bytes},
{2, node_io_write_time, gauge, "Total time of write operations.", io_write_time},
{2, node_io_sync_count, counter, "Sync operations since node start.", io_sync_count},
{2, node_io_sync_time, gauge, "Total time of sync operations.", io_sync_time},
{2, node_io_seek_count, counter, "Seek operations since node start.", io_seek_count},
{2, node_io_seek_time, gauge, "Total time of seek operations.", io_seek_time},
{2, node_io_reopen_count, counter, "Times files have been reopened by the file handle cache.", io_reopen_count},
{2, node_mnesia_ram_tx_count, counter, "Mnesia transactions in RAM since node start.",
mnesia_ram_tx_count},
{2, node_mnesia_disk_tx_count, counter, "Mnesia transactions in disk since node start.",
mnesia_disk_tx_count},
{2, node_msg_store_read_count, counter, "Read operations in the message store since node start.",
msg_store_read_count},
{2, node_msg_store_write_count, counter, "Write operations in the message store since node start.",
msg_store_write_count},
{2, queue_index_journal_write_count, counter, "Write operations in the queue index journal since node start.", queue_index_journal_write_count},
{2, queue_index_write_count, counter, "Queue index write operations since node start.", index_write_count},
{2, queue_index_read_count, counter, "Queue index read operations since node start.", index_read_count},
{2, queue_io_file_handle_open_attempt_count, counter, "File descriptor open attempts.",
io_file_handle_open_attempt_count},
{2, queue_io_file_handle_open_attempt_time, gauge, "Total time of file descriptor open attempts.",
io_file_handle_open_attempt_time}
]},
{node_coarse_metrics,
[{2, node_fd_used, gauge, "File descriptors used.", fd_used},
{2, node_sockets_used, gauge, "Sockets used.", sockets_used},
{2, node_mem_used, gauge, "Memory used in bytes.", mem_used},
{2, node_disk_free, gauge, "Disk free in bytes.", disk_free},
{2, node_proc_used, gauge, "Erlang processes used.", proc_used},
{2, node_gc_num, counter, "GC runs.", gc_num},
{2, node_gc_bytes_reclaimed, counter, "Bytes reclaimed by GC.", gc_bytes_reclaimed},
{2, node_context_switches, counter, "Context switches since node start.", context_switches}
]},
{connection_churn_metrics,
[{2, connection_created, counter, "Connections created."},
{3, connection_closed, counter, "Connections closed."},
{4, channel_created, counter, "Channels created."},
{5, channel_closed, counter, "Channels closed."},
{6, queue_declared, counter, "Queues declared."},
{7, queue_deleted, counter, "Queues deleted."}
]},
{node_node_metrics,
[{2, node_node_send_bytes, counter, "Count of bytes sent to node.", send_bytes},
{2, node_node_recv_bytes, counter, "Count of bytes received from node.", recv_bytes}
]},
{channel_queue_metrics,
[{2, channel_queue_get, counter, "Count of messages delivered in acknowledgement mode in response to basic.get."},
{3, channel_queue_get_no_ack, counter, "Count of messages delivered in no-acknowledgement mode in response to basic.get."},
{4, channel_queue_deliver, counter, "Count of messages delivered in acknowledgement mode to consumers."},
{5, channel_queue_deliver_no_ack, counter, "Count of messages delivered in no-acknowledgement mode to consumers."},
{6, channel_queue_redeliver, counter, "Count of subset of delivered messages which had the redelivered flag set."},
{7, channel_queue_ack, counter, "Count of messages acknowledged."},
{8, channel_queue_get_empty, counter, "Count of basic.get operations on empty queues."}
]},
{channel_metrics,
[{2, channel_consumer_count, gauge, "Consumers count.", consumer_count},
{2, channel_messages_unacknowledged, gauge, "Count of messages unacknowledged.", messages_unacknowledged},
{2, channel_messages_unconfirmed, gauge, "Count of messages unconfirmed.", messages_unconfirmed},
{2, channel_messages_uncommited, gauge, "Count of messages uncommited.", messages_uncommited},
{2, channel_messages_prefetch_count, gauge, "Limit to the number of unacknowledged messages on every connection on a channel.", prefetch_count},
{2, channel_messages_global_prefetch_count, gauge, "Global limit to the number of unacknowledged messages shared between all connections on a channel.", global_prefetch_count}
]},
{connection_metrics,
[{2, connection_recv_count, counter, "Count of bytes received on the connection.", recv_count},
{2, connection_send_count, counter, "Count of bytes send on the connection.", send_count}
]},
{node_metrics,
[{2, node_fd_total, gauge, "File descriptors available.", fd_total},
{2, node_sockets_total, gauge, "Sockets available.", sockets_total},
{2, node_mem_limit, gauge, "Memory usage high watermark.", mem_limit},
{2, node_disk_free_limit, gauge, "Free disk space low watermark.", disk_free_limit},
{2, node_proc_total, gauge, "Erlang processes limit.", proc_total},
{2, node_uptime, gauge, "Time in milliseconds since node start.", uptime},
{2, node_run_queue, gauge, "Runtime run queue.", run_queue},
{2, node_processors, gauge, "Logical processors.", processors},
{2, node_net_ticktime, gauge, "Periodic tick interval between all pairs of nodes to maintain the connections and to detect disconnections.", net_ticktime}
]},
{channel_queue_exchange_metrics,
[{2, channel_queue_exchange_publish, counter, "Count of messages published."}
]}
]).
-define(TOTALS, [
{connection_created, connections, gauge, "RabbitMQ Connections count."},
{channel_created, channels, gauge, "RabbitMQ Channels count."},
{consumer_created, consumers, gauge, "RabbitMQ Consumers count."},
{queue_metrics, queues, gauge, "RabbitMQ Queues count."}
]).
%%====================================================================
%% Collector API
%%====================================================================
register() ->
register(default).
register(Registry) ->
ok = prometheus_registry:register_collector(Registry, ?MODULE).
deregister_cleanup(_) -> ok.
collect_mf(_Registry, Callback) ->
[begin
Data = ets:tab2list(Table),
mf(Callback, Contents, Data)
end || {Table, Contents} <- ?METRICS],
[begin
Size = ets:info(Table, size),
mf_totals(Callback, Name, Type, Help, Size)
end || {Table, Name, Type, Help} <- ?TOTALS],
ok.
mf(Callback, Contents, Data) ->
[begin
Fun = fun(D) -> element(Index, D) end,
Callback(create_mf(?METRIC_NAME(Name), Help, catch_boolean(Type), ?MODULE,
{Type, Fun, Data}))
end || {Index, Name, Type, Help} <- Contents],
[begin
Fun = fun(D) -> proplists:get_value(Key, element(Index, D)) end,
Callback(create_mf(?METRIC_NAME(Name), Help, catch_boolean(Type), ?MODULE,
{Type, Fun, Data}))
end || {Index, Name, Type, Help, Key} <- Contents].
mf_totals(Callback, Name, Type, Help, Size) ->
Callback(create_mf(?METRIC_NAME(Name), Help, catch_boolean(Type), Size)).
collect_metrics(_, {Type, Fun, Items}) ->
[metric(Type, labels(Item), Fun(Item)) || Item <- Items].
labels(Item) ->
label(element(1, Item)).
label(A) when is_atom(A) ->
%% Don't need node label
[];
label(L) ->
label0(L).
label0(#resource{virtual_host = VHost, kind = exchange, name = Name}) ->
[{vhost, VHost}, {exchange, Name}];
label0(#resource{virtual_host = VHost, kind = queue, name = Name}) ->
[{vhost, VHost}, {queue, Name}];
label0({P, {#resource{virtual_host = QVHost, kind = queue, name = QName},
#resource{virtual_host = EVHost, kind = exchange, name = EName}}}) when is_pid(P) ->
%% channel_queue_exchange_metrics {channel_id, {queue_id, exchange_id}}
[{channel, P}, {queue_vhost, QVHost}, {queue_name, QName},
{exchange_vhost, EVHost}, {exchange_name, EName}];
label0({A1, A2}) when is_atom(A1) and is_atom(A2) ->
%% node_node_metrics, only need the remote node
[{node, A2}];
label0({I1, I2}) ->
label(I1) ++ label(I2);
label0(P) when is_pid(P) ->
[{channel, P}].
metric(counter, Labels, Value) ->
emit_counter_metric_if_defined(Labels, Value);
metric(gauge, Labels, Value) ->
emit_gauge_metric_if_defined(Labels, Value);
metric(untyped, Labels, Value) ->
untyped_metric(Labels, Value);
metric(boolean, Labels, Value0) ->
Value = case Value0 of
true -> 1;
false -> 0;
undefined -> undefined
end,
untyped_metric(Labels, Value).
%%====================================================================
%% Private Parts
%%====================================================================
catch_boolean(boolean) ->
untyped;
catch_boolean(T) ->
T.
emit_counter_metric_if_defined(Labels, Value) ->
case Value of
undefined -> undefined;
'' ->
counter_metric(Labels, undefined);
Value ->
counter_metric(Labels, Value)
end.
emit_gauge_metric_if_defined(Labels, Value) ->
case Value of
undefined -> undefined;
'' ->
gauge_metric(Labels, undefined);
Value ->
gauge_metric(Labels, Value)
end.

View File

@ -0,0 +1,124 @@
%% The contents of this file are subject to the Mozilla Public License
%% Version 1.1 (the "License"); you may not use this file except in
%% compliance with the License. You may obtain a copy of the License at
%% http://www.mozilla.org/MPL/
%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
%% License for the specific language governing rights and limitations
%% under the License.
%%
%% The Original Code is RabbitMQ.
%%
%% The Initial Developer of the Original Code is GoPivotal, Inc.
%% Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
%%
-module(rabbit_prometheus_app).
-behaviour(application).
-export([start/2, stop/1, reset_dispatcher/1]).
-behaviour(supervisor).
-export([init/1]).
-define(TCP_CONTEXT, rabbitmq_prometheus_tcp).
-define(TLS_CONTEXT, rabbitmq_prometheus_tls).
-define(DEFAULT_PORT, 15673).
start(_Type, _StartArgs) ->
%% TCP listener uses prometheus.tcp.*.
%% TLS listener uses prometheus.ssl.*
start_configured_listener(true),
supervisor:start_link({local,?MODULE},?MODULE,[]).
stop(_State) ->
unregister_all_contexts(),
ok.
init(_) ->
{ok, {{one_for_one, 3, 10}, []}}.
reset_dispatcher(_IgnoreApps) ->
unregister_all_contexts(),
start_configured_listener(false).
-spec start_configured_listener(boolean()) -> ok.
start_configured_listener(NeedLogStartup) ->
Listeners = case {has_configured_tcp_listener(),
has_configured_tls_listener()} of
{false, false} ->
%% nothing is configured
[get_tcp_listener()];
{false, true} ->
[get_tls_listener()];
{true, false} ->
[get_tcp_listener()];
{true, true} ->
[get_tcp_listener(),
get_tls_listener()]
end,
[ start_listener(Listener, NeedLogStartup)
|| Listener <- Listeners ].
has_configured_tcp_listener() ->
has_configured_listener(tcp_config).
has_configured_tls_listener() ->
has_configured_listener(ssl_config).
has_configured_listener(Key) ->
case application:get_env(rabbitmq_prometheus, Key, undefined) of
undefined -> false;
_ -> true
end.
get_tls_listener() ->
{ok, Listener0} = application:get_env(rabbitmq_prometheus, ssl_config),
[{ssl, true} | Listener0].
get_tcp_listener() ->
application:get_env(rabbitmq_prometheus, tcp_config, []).
start_listener(Listener, NeedLogStartup) ->
{Type, ContextName} = case is_tls(Listener) of
true -> {tls, ?TLS_CONTEXT};
false -> {tcp, ?TCP_CONTEXT}
end,
{ok, _} = register_context(ContextName, Listener),
case NeedLogStartup of
true -> log_startup(Type, Listener);
false -> ok
end,
ok.
register_context(ContextName, Listener0) ->
M0 = maps:from_list(Listener0),
%% include default port if it's not provided in the config
%% as Cowboy won't start if the port is missing
M1 = maps:merge(#{port => ?DEFAULT_PORT}, M0),
rabbit_web_dispatch:register_context_handler(
ContextName, maps:to_list(M1), "",
rabbit_prometheus_dispatcher:build_dispatcher(),
"RabbitMQ Prometheus").
unregister_all_contexts() ->
rabbit_web_dispatch:unregister_context(?TCP_CONTEXT),
rabbit_web_dispatch:unregister_context(?TLS_CONTEXT).
log_startup(tcp, Listener) ->
rabbit_log:info("Prometheus metrics: HTTP (non-TLS) listener started on port ~w", [port(Listener)]);
log_startup(tls, Listener) ->
rabbit_log:info("Prometheus metrics: HTTPS listener started on port ~w", [port(Listener)]).
port(Listener) ->
proplists:get_value(port, Listener, ?DEFAULT_PORT).
is_tls(Listener) ->
case proplists:get_value(ssl, Listener) of
undefined -> false;
false -> false;
_ -> true
end.

View File

@ -0,0 +1,37 @@
%% The contents of this file are subject to the Mozilla Public License
%% Version 1.1 (the "License"); you may not use this file except in
%% compliance with the License. You may obtain a copy of the License at
%% http://www.mozilla.org/MPL/
%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
%% License for the specific language governing rights and limitations
%% under the License.
%%
%% The Original Code is RabbitMQ.
%%
%% The Initial Developer of the Original Code is GoPivotal, Inc.
%% Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
%%
-module(rabbit_prometheus_dispatcher).
-export([build_dispatcher/0]).
-define(DEFAULT_PATH, "/metrics").
build_dispatcher() ->
{ok, _} = application:ensure_all_started(prometheus),
maybe_register_collectors(),
prometheus_http_impl:setup(),
cowboy_router:compile([{'_', dispatcher()}]).
dispatcher() ->
[{path() ++ "/[:registry]", rabbit_prometheus_handler, []}].
maybe_register_collectors() ->
prometheus_registry:register_collectors([prometheus_rabbitmq_core_metrics_collector]).
path() ->
Config = application:get_env(rabbitmq_prometheus, path, []),
proplists:get_value(path, Config, ?DEFAULT_PATH).

View File

@ -0,0 +1,42 @@
%% The contents of this file are subject to the Mozilla Public License
%% Version 1.1 (the "License"); you may not use this file except in
%% compliance with the License. You may obtain a copy of the License at
%% http://www.mozilla.org/MPL/
%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
%% License for the specific language governing rights and limitations
%% under the License.
%%
%% The Original Code is RabbitMQ.
%%
%% The Initial Developer of the Original Code is GoPivotal, Inc.
%% Copyright (c) 2007-2019 Pivotal Software, Inc. All rights reserved.
%%
-module(rabbit_prometheus_handler).
-export([init/2]).
-export([generate_response/2, content_types_provided/2, is_authorized/2]).
%% ===================================================================
%% Cowboy Handler Callbacks
%% ===================================================================
init(Req, _State) ->
{cowboy_rest, Req, #{}}.
content_types_provided(ReqData, Context) ->
{[
{<<"*/*">>, generate_response}
], ReqData, Context}.
is_authorized(ReqData, Context) ->
{true, ReqData, Context}.
%% ===================================================================
%% Private functions
%% ===================================================================
generate_response(ReqData, Context) ->
{ok, Response, undefined} = prometheus_cowboy2_handler:init(ReqData, Context),
{stop, Response, Context}.