├── .gitignore
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── SECURITY.md
├── alertmanager
├── .env
├── Makefile
├── README.md
├── alert.png
├── alertmanager
│ └── alertmanager.yml
├── amtool
│ ├── Dockerfile
│ └── config.yml
├── docker-compose.yml
├── hello
│ ├── Dockerfile
│ ├── go.mod
│ ├── go.sum
│ └── main.go
├── prometheus
│ ├── alert.rules
│ └── prometheus.yml
└── webhook
│ ├── Dockerfile
│ ├── go.mod
│ ├── go.sum
│ └── main.go
├── blackbox-exporter
├── .env
├── Makefile
├── README.md
├── blackbox
│ └── blackbox.yml
├── docker-compose.yml
├── prometheus
│ └── prometheus.yml
└── web
│ ├── Dockerfile
│ ├── go.mod
│ └── main.go
├── cadvisor
├── .env
├── Makefile
├── README.md
├── docker-compose.yml
└── prometheus
│ └── prometheus.yml
├── federation
├── .env
├── Makefile
├── README.md
├── docker-compose.yml
└── prometheus
│ └── prometheus.yml
├── file-sd
├── .env
├── Makefile
├── README.md
├── docker-compose.yml
├── myservice
│ ├── Dockerfile
│ ├── go.mod
│ ├── go.sum
│ └── main.go
└── prometheus
│ ├── prometheus.yml
│ └── targets.json
├── go-app
├── .env
├── .gitignore
├── Makefile
├── README.md
├── docker-compose.yml
├── myapp
│ ├── Dockerfile
│ ├── go.mod
│ ├── go.sum
│ └── main.go
└── prometheus
│ └── prometheus.yml
├── haproxy
├── .env
├── Makefile
├── README.md
├── certs
│ └── cert.pem
├── docker-compose.yml
├── haproxy
│ └── haproxy.cfg
└── prometheus
│ └── prometheus.yml
├── nginx
├── .env
├── Makefile
├── README.md
├── certs
│ ├── example.com.crt
│ └── example.com.key
├── docker-compose.yml
├── nginx
│ ├── .htpasswd
│ └── nginx.conf
└── prometheus
│ └── prometheus.yml
├── node-exporter
├── .env
├── Makefile
├── README.md
├── docker-compose.yml
└── prometheus
│ └── prometheus.yml
└── python-flask-app
├── .env
├── Makefile
├── README.md
├── docker-compose.yml
├── myapp
├── Dockerfile
├── requirements.txt
└── server.py
└── prometheus
└── prometheus.yml
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor/
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Prometheus Community Code of Conduct
2 |
3 | Prometheus follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md).
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # The Prometheus Playground
2 |
3 | This repo houses a variety of [Docker-Compose](https://docs.docker.com/compose)-based "sandbox" projects showcasing the [Prometheus](https://prometheus.io) monitoring system. All projects are "turnkey" and require just a single `docker-compose up` command to run.
4 |
5 | Each sandbox project has a `README` with an explanation of the project, a `docker-compose.yml` configuration file for Docker Compose, and other necessary resources (config files, `Dockerfile`s, etc.). To run a project, navigate to the appropriate directory and run `make run` (which is just an alias for `docker-compose up --build`). This will run the project in the *foreground*. To run the project in detached mode, use `make run-detached`.
6 |
7 | ## Prerequisites
8 |
9 | In order to run the sandbox projects you'll need to install [Docker](https://docker.com) and [Docker Compose](https://docs.docker.com/compose) and have a Docker daemon running locally.
10 |
11 | ## Projects
12 |
13 | Directory | Scenario
14 | :---------|:--------
15 | [`alertmanager`](./alertmanager) | Prometheus monitors a basic web service and notifies [Alertmanager](https://prometheus.io/docs/alerting/alertmanager/) if the service is down; Alertmanager, in turns, notifies a web service via webhook
16 | [`blackbox-exporter`](./blackbox-exporter) | A [BlackBox prober exporter](https://github.com/prometheus/blackbox_exporter) probes a simple web service and provides probe-based metrics to Prometheus
17 | [`cadvisor`](./cadvisor) | Prometheus scrapes [cAdvisor](https://github.com/google/cadvisor)-gathered metrics for several containers
18 | [`federation`](./federation) | Three Prometheus instances run together as a single federation
19 | [`file-sd`](./file-sd) | A Prometheus instance discovers a simple instrumented web service via file-based service discovery
20 | [`go-app`](./go-app) | An instrumented Go application using the Prometheus [Go client](https://github.com/prometheus/client_golang)
21 | [`haproxy`](./haproxy) | Prometheus runs behind [HAProxy](https://haproxy.org/), which acts as a reverse proxy and provides basic auth and TLS encryption
22 | [`nginx`](./nginx) | Prometheus runs behind [nginx](https://nginx.org), which acts as a reverse proxy and provides basic auth and TLS encryption
23 | [`node-exporter`](./node-exporter) | Prometheus scrapes Linux host metrics from a [Node Exporter](https://prometheus.io/docs/guides/node-exporter/)
24 | [`python-flask-app`](./python-flask-app) | An instrumented [Flask](https://flask.pocoo.org) application demonstrating the Prometheus [Python client](https://github.com/prometheus/client_python)
25 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Reporting a security issue
2 |
3 | The Prometheus security policy, including how to report vulnerabilities, can be
4 | found here:
5 |
6 |
7 |
--------------------------------------------------------------------------------
/alertmanager/.env:
--------------------------------------------------------------------------------
1 | PROMETHEUS_TAG=v2.5.0
2 | ALERTMANAGER_TAG=v0.15.3
3 |
--------------------------------------------------------------------------------
/alertmanager/Makefile:
--------------------------------------------------------------------------------
1 | run:
2 | docker-compose up --build
3 |
4 | run-detached:
5 | docker-compose up --build --detach
6 |
7 | kill:
8 | docker-compose kill
9 |
--------------------------------------------------------------------------------
/alertmanager/README.md:
--------------------------------------------------------------------------------
1 | # Alertmanager sandbox
2 |
3 | In this sandbox, a Prometheus [Alertmanager](https://github.com/prometheus/alertmanager) handles alerts thrown by a running Prometheus instance. The Alertmanager in this example is configured with one alert (specified in an [`alert.rules`](./prometheus/alert.rules) file) that Prometheus fires whenever the [`hello`](./hello/main.go) service—a simple web service—is down for more than 10 seconds. If Prometheus alerts the Alertmanager that the `hello` service is down, it will `POST` a webhook to the [`webhook`](./webhook/main.go) service, which will then log the alert sent by the Alertmanager to stdout.
4 |
5 | ## Usage
6 |
7 | To start the sandbox:
8 |
9 | ```bash
10 | # In the foreground
11 | make run # docker-compose up --build
12 |
13 | # In detached mode
14 | make run-detached # docker-compose up --build --detach
15 | ```
16 |
17 | This will start up five services:
18 |
19 | Service | Description
20 | :-------|:-----------
21 | `prometheus` | A Prometheus instance that's [configured](./prometheus/alert.rules) to alert the Alertmanager whenever the `hello` web service has been down for more than 10 seconds
22 | `alertmanager` | An Alertmanager instance that's configured to `POST` an alert message to the `webhook` service whenever Prometheus alerts Alertmanager that the `hello` service is down
23 | `amtool` | [amtool](https://github.com/prometheus/alertmanager#amtool) is a CLI utility for interacting with the Alertmanager. This service is a utility container that enables you to run amtool against the Alertmanager instance included in the sandbox.
24 | `hello` | A simple [web service](./hello/main.go) written in Go. The `hello` web service has just two endpoints: a `/hello` endpoint that returns a `{"hello":"world"}` JSON object and a `/metrics` endpoint for Prometheus instrumentation
25 | `webhook` | A simple [web service](./webhook/main.go) written in Go. The `webhook` web service has just one `/alert` endpoint to which Alertmanager alerts are `POST`ed
26 |
27 | ## Creating an alert
28 |
29 | When you first start up the containers, there's no alert-worthy behavior because the `hello` service is running as expected. You can verify this in the [Prometheus expression browser](http://localhost:9090/graph) using the [`up{job="hello"}`](http://localhost:9090/graph?g0.range_input=1h&g0.expr=up%7Bjob%3D%22hello%22%7D&g0.tab=1) expression, which should have a value of 1.
30 |
31 | To create an alert, stop the service:
32 |
33 | ```bash
34 | docker-compose stop hello
35 | ```
36 |
37 | Wait about 10 seconds and you should see something like this in the Docker Compose logs:
38 |
39 | ```
40 | webhook_1 | 2018/07/23 19:31:28 Webhook received: {"receiver":"webhook","status":"firing","alerts":[{"status":"firing","labels":{"alertname":"InstanceDown","instance":"hello:2112","job":"hello","severity":"page"},"annotations":{"description":"Instance hello:2112 of job hello has been down for more than 30 seconds","summary":"Instance hello:2112 down"},"startsAt":"2018-07-23T19:31:18.893055177Z","endsAt":"0001-01-01T00:00:00Z","generatorURL":"http://e192da4eb26f:9090/graph?g0.expr=up%7Bjob%3D%22hello%22%7D+%3D%3D+0\u0026g0.tab=1"}],"groupLabels":{"alertname":"InstanceDown"},"commonLabels":{"alertname":"InstanceDown","instance":"hello:2112","job":"hello","severity":"page"},"commonAnnotations":{"description":"Instance hello:2112 of job hello has been down for more than 30 seconds","summary":"Instance hello:2112 down"},"externalURL":"http://98c322df76cb:9093","version":"4","groupKey":"{}:{alertname=\"InstanceDown\"}"}
41 | ```
42 |
43 | This indicates that Alertmanager has `POST`ed a webhook to the running [`webhook`](./webhook/main.go) service. You can also read the webhook service logs directly:
44 |
45 | ```bash
46 | docker-compose logs webhook
47 | ```
48 |
49 | You can also see the alert in the [Alertmanager UI](http://localhost:9093/#/alerts). It should look like this:
50 |
51 | 
52 |
53 | In the Prometheus expression browser, [`up{job="hello"}`](http://localhost:9090/graph?g0.range_input=1h&g0.expr=up%7Bjob%3D%22hello%22%7D&g0.tab=1) should now have a value of 0.
54 |
55 | ## amtool
56 |
57 | The `amtool` service can be used as a proxy for the [amtool](https://github.com/prometheus/alertmanager#amtool) CLI utility. For ease of use, you can alias `amtool` to the container:
58 |
59 | ```bash
60 | alias amtool='docker-compose run amtool amtool'
61 | ```
62 |
63 | Now you can use amtool commands like this:
64 |
65 | ```bash
66 | amtool alert
67 | ```
--------------------------------------------------------------------------------
/alertmanager/alert.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/prometheus-community/prometheus-playground/HEAD/alertmanager/alert.png
--------------------------------------------------------------------------------
/alertmanager/alertmanager/alertmanager.yml:
--------------------------------------------------------------------------------
1 | global:
2 | resolve_timeout: 5m
3 |
4 | route:
5 | group_by: ['alertname']
6 | group_wait: 10s
7 | group_interval: 10s
8 | repeat_interval: 1h
9 | receiver: webhook
10 | receivers:
11 | - name: webhook
12 | webhook_configs:
13 | - url: http://webhook:5001/alert
--------------------------------------------------------------------------------
/alertmanager/amtool/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM golang:1.11beta1-alpine3.7
2 |
3 | RUN apk update \
4 | && apk upgrade \
5 | && apk add --no-cache git \
6 | && go get github.com/prometheus/alertmanager/cmd/amtool \
7 | && apk del git
--------------------------------------------------------------------------------
/alertmanager/amtool/config.yml:
--------------------------------------------------------------------------------
1 | alertmanager.url: http://alertmanager:9093
--------------------------------------------------------------------------------
/alertmanager/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.2'
2 | services:
3 | alertmanager:
4 | image: prom/alertmanager:${ALERTMANAGER_TAG}
5 | ports:
6 | - 9093:9093
7 | command:
8 | - --config.file=/etc/alertmanager/alertmanager.yml
9 | volumes:
10 | - ./alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
11 | prometheus:
12 | image: prom/prometheus:${PROMETHEUS_TAG}
13 | ports:
14 | - 9090:9090
15 | command:
16 | - --config.file=/etc/prometheus/prometheus.yml
17 | volumes:
18 | - ./prometheus:/etc/prometheus:ro
19 | amtool:
20 | build:
21 | context: amtool
22 | volumes:
23 | - ./amtool/config.yml:/etc/amtool/config.yml:ro
24 | hello:
25 | build:
26 | context: hello
27 | args:
28 | goPackage: github.com/prometheus-community/prometheus-playground/alertmanager/hello
29 | goVersion: 1.11
30 | cache_from:
31 | - golang:1.11
32 | - scratch
33 | ports:
34 | - 2112:2112
35 | webhook:
36 | build:
37 | context: webhook
38 | args:
39 | goPackage: github.com/prometheus-community/prometheus-playground/alertmanager/webhook
40 | goVersion: 1.11
41 | cache_from:
42 | - golang:1.11
43 | - scratch
44 | ports:
45 | - 5001:5001
--------------------------------------------------------------------------------
/alertmanager/hello/Dockerfile:
--------------------------------------------------------------------------------
1 | # Args
2 | ARG goVersion
3 | ARG goPackage
4 |
5 | FROM golang:${goVersion} AS builder
6 |
7 | # Copy the code from the host and compile it
8 | WORKDIR /home
9 | COPY . ./
10 | RUN go mod vendor
11 | RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix nocgo -o /app .
12 |
13 | FROM scratch
14 | COPY --from=builder /app ./
15 | ENTRYPOINT ["./app"]
--------------------------------------------------------------------------------
/alertmanager/hello/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/prometheus-community/prometheus-playground/alertmanager/hello
2 |
3 | require (
4 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 // indirect
5 | github.com/go-chi/chi v3.3.2+incompatible
6 | github.com/golang/protobuf v1.1.0 // indirect
7 | github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
8 | github.com/prometheus/client_golang v0.8.0
9 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 // indirect
10 | github.com/prometheus/common v0.0.0-20180518154759-7600349dcfe1 // indirect
11 | github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273 // indirect
12 | github.com/unrolled/render v0.0.0-20171102162132-65450fb6b2d3
13 | )
14 |
--------------------------------------------------------------------------------
/alertmanager/hello/go.sum:
--------------------------------------------------------------------------------
1 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
2 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
3 | github.com/go-chi/chi v3.3.2+incompatible h1:uQNcQN3NsV1j4ANsPh42P4ew4t6rnRbJb8frvpp31qQ=
4 | github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
5 | github.com/golang/protobuf v1.1.0 h1:0iH4Ffd/meGoXqF2lSAhZHt8X+cPgkfn/cb6Cce5Vpc=
6 | github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
7 | github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
8 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
9 | github.com/prometheus/client_golang v0.8.0 h1:1921Yw9Gc3iSc4VQh3PIoOqgPCZS7G/4xQNVUp8Mda8=
10 | github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
11 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8=
12 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
13 | github.com/prometheus/common v0.0.0-20180518154759-7600349dcfe1 h1:osmNoEW2SCW3L7EX0km2LYM8HKpNWRiouxjE3XHkyGc=
14 | github.com/prometheus/common v0.0.0-20180518154759-7600349dcfe1/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
15 | github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273 h1:agujYaXJSxSo18YNX3jzl+4G6Bstwt+kqv47GS12uL0=
16 | github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
17 | github.com/unrolled/render v0.0.0-20171102162132-65450fb6b2d3 h1:ZsIlNwu/G0zbChIZaWOeZ2TPGNmKMt46jZLXi3e8LFc=
18 | github.com/unrolled/render v0.0.0-20171102162132-65450fb6b2d3/go.mod h1:tu82oB5W2ykJRVioYsB+IQKcft7ryBr7w12qMBUPyXg=
19 |
--------------------------------------------------------------------------------
/alertmanager/hello/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "log"
6 | "net/http"
7 |
8 | "github.com/go-chi/chi"
9 | "github.com/prometheus/client_golang/prometheus/promhttp"
10 | "github.com/unrolled/render"
11 | )
12 |
13 | const (
14 | port = 2112
15 | )
16 |
17 | var (
18 | renderer = render.New()
19 | address = fmt.Sprintf(":%d", port)
20 | )
21 |
22 | func hello(w http.ResponseWriter, r *http.Request) {
23 | renderer.JSON(w, http.StatusOK, map[string]string{"hello": "world"})
24 | }
25 |
26 | func main() {
27 | router := chi.NewRouter()
28 |
29 | router.Get("/hello", hello)
30 |
31 | router.Handle("/metrics", promhttp.Handler())
32 |
33 | log.Fatal(http.ListenAndServe(address, router))
34 | }
35 |
--------------------------------------------------------------------------------
/alertmanager/prometheus/alert.rules:
--------------------------------------------------------------------------------
1 | groups:
2 | - name: node.rules
3 | rules:
4 | - alert: InstanceDown
5 | expr: up{job="hello"} == 0
6 | for: 10s
7 | labels:
8 | severity: page
9 | annotations:
10 | summary: "Instance {{ $labels.instance }} down"
11 | description: "Instance {{ $labels.instance }} of job {{ $labels.job }} has been down for more than 30 seconds"
12 |
--------------------------------------------------------------------------------
/alertmanager/prometheus/prometheus.yml:
--------------------------------------------------------------------------------
1 | global:
2 | scrape_interval: 15s
3 | evaluation_interval: 15s
4 |
5 | rule_files:
6 | - /etc/prometheus/alert.rules
7 |
8 | alerting:
9 | alertmanagers:
10 | - scheme: http
11 | static_configs:
12 | - targets:
13 | - alertmanager:9093
14 |
15 | scrape_configs:
16 | - job_name: prometheus
17 | scrape_interval: 5s
18 | static_configs:
19 | - targets:
20 | - localhost:9090
21 | - job_name: hello
22 | scrape_interval: 5s
23 | static_configs:
24 | - targets:
25 | - hello:2112
--------------------------------------------------------------------------------
/alertmanager/webhook/Dockerfile:
--------------------------------------------------------------------------------
1 | # Args
2 | ARG goVersion
3 | ARG goPackage
4 |
5 | FROM golang:${goVersion} AS builder
6 |
7 | # Copy the code from the host and compile it
8 | WORKDIR /home
9 | COPY . ./
10 | RUN go mod vendor
11 | RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix nocgo -o /app .
12 |
13 | FROM scratch
14 | COPY --from=builder /app ./
15 | ENTRYPOINT ["./app"]
--------------------------------------------------------------------------------
/alertmanager/webhook/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/prometheus-community/prometheus-playground/alertmanager/webhook
2 |
3 | require (
4 | github.com/go-chi/chi v3.3.2+incompatible
5 | github.com/unrolled/render v0.0.0-20171102162132-65450fb6b2d3
6 | )
7 |
--------------------------------------------------------------------------------
/alertmanager/webhook/go.sum:
--------------------------------------------------------------------------------
1 | github.com/go-chi/chi v3.3.2+incompatible h1:uQNcQN3NsV1j4ANsPh42P4ew4t6rnRbJb8frvpp31qQ=
2 | github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
3 | github.com/unrolled/render v0.0.0-20171102162132-65450fb6b2d3 h1:ZsIlNwu/G0zbChIZaWOeZ2TPGNmKMt46jZLXi3e8LFc=
4 | github.com/unrolled/render v0.0.0-20171102162132-65450fb6b2d3/go.mod h1:tu82oB5W2ykJRVioYsB+IQKcft7ryBr7w12qMBUPyXg=
5 |
--------------------------------------------------------------------------------
/alertmanager/webhook/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "io/ioutil"
6 | "log"
7 | "net/http"
8 |
9 | "github.com/go-chi/chi"
10 | "github.com/unrolled/render"
11 | )
12 |
13 | const (
14 | port = 5001
15 | )
16 |
17 | var (
18 | renderer = render.New()
19 |
20 | address = fmt.Sprintf(":%d", port)
21 | )
22 |
23 | func getRequestBody(r *http.Request) string {
24 | body, err := ioutil.ReadAll(r.Body)
25 | if err != nil {
26 | log.Fatalf("Could not read webhook body: %v", err)
27 | }
28 | defer r.Body.Close()
29 |
30 | return string(body)
31 | }
32 |
33 | func webhookHandler(w http.ResponseWriter, r *http.Request) {
34 | requestBody := getRequestBody(r)
35 |
36 | msg := fmt.Sprintf("Webhook received: %s", requestBody)
37 |
38 | log.Print(msg)
39 |
40 | renderer.Text(w, http.StatusAccepted, "")
41 | }
42 |
43 | func main() {
44 | router := chi.NewRouter()
45 |
46 | router.Post("/alert", webhookHandler)
47 |
48 | log.Fatal(http.ListenAndServe(address, router))
49 | }
50 |
--------------------------------------------------------------------------------
/blackbox-exporter/.env:
--------------------------------------------------------------------------------
1 | PROMETHEUS_TAG=v2.5.0
2 | BLACKBOX_EXPORTER_TAG=v0.12.0
3 |
--------------------------------------------------------------------------------
/blackbox-exporter/Makefile:
--------------------------------------------------------------------------------
1 | run:
2 | docker-compose up --build
3 |
4 | run-detached:
5 | docker-compose up --build --detach
6 |
7 | kill:
8 | docker-compose kill
9 |
--------------------------------------------------------------------------------
/blackbox-exporter/README.md:
--------------------------------------------------------------------------------
1 | # Blackbox prober exporter sandbox
2 |
3 | In this sandbox, the [Blackbox prober exporter](https://github.com/prometheus/blackbox_exporter) probes a [simple web service](./web/main.go), while Prometheus scrapes `probe_*` metrics from the Blackbox exporter.
4 |
5 | ## Usage
6 |
7 | To start the sandbox:
8 |
9 | ```bash
10 | # In the foreground
11 | make run # docker-compose up --build
12 |
13 | # In detached mode
14 | make run-detached # docker-compose up --build --detach
15 | ```
16 |
17 | This will start up three services:
18 |
19 | Service | Description
20 | :-------|:-----------
21 | `blackbox` | A Prometheus Blackbox exporter running on port 9115, which runs probes against the `web` service using the [`http_2xx` module](./blackbox/blackbox.yml).
22 | `prometheus` | A Prometheus instance configured to scrape the Blackbox exporter and collect a wide variety of metrics (prefaced by `probe_`).
23 | `web` | A simple web service with two endpoints: `/hello` returns a `{"hello": "world"}` JSON object and `/health` returns an HTTP `200 OK` indicating that the service is running. The `web` service
24 |
25 | Things to check out:
26 |
27 | * The Blackbox exporter dashboard at http://localhost:9115. You'll see a **Recent Probes** table listing all probes, including the following information for each probe: module, target, result, and a link to debugging logs.
28 | * The results of the most recent probe of the `web` service at http://localhost:9115/probe?target=web:2112/health&module=http_2xx. If the value of `probe_success` metric is 1, then the service is running properly (otherwise the value will be 0).
29 | * The `probe_success` metric on Prometheus at http://localhost:9090/graph?g0.range_input=1h&g0.expr=probe_success%7Binstance%3D%22web%3A2112%2Fhealth%22%7D&g0.tab=1.
30 |
31 | At first, the `web` service will be running normally, which means that the Blackbox probes of that service's `/health` will succeed. This will change if you shut down the service:
32 |
33 | ```bash
34 | docker-compose stop web
35 | ```
36 |
37 | Now you can navigate back to the most recent [probe result](http://localhost:9115/probe?target=web:2112/health&module=http_2xx) and see that `probe_success` now has a value of 0. If you navigate back to the Prometheus [expression browser](http://localhost:9090/graph?g0.range_input=1h&g0.expr=probe_success%7Binstance%3D%22web%3A2112%2Fhealth%22%7D&g0.tab=1) you can see that `probe_success` for the `web` service now returns 0 as well (the scrape interval is 5 seconds, so you may need to wait a bit and hit refresh).
38 |
39 | If you restart the `web` service, the probes will once again be successful:
40 |
41 | ```bash
42 | docker-compose start web
43 | ```
44 |
45 | ## Assets
46 |
47 | Folder | Assets
48 | :------|:------
49 | [`prometheus`](./prometheus) | A [`prometheus.yml`](./prometheus/prometheus.yml) configuration file for Prometheus
50 | [`blackbox`](./blackbox) | A [`blackbox.yml`](./blackbox/blackbox.yml) configuration file for the Blackbox exporter
51 | [`web`](./web) | Source files for the simple web server (written in Go)
--------------------------------------------------------------------------------
/blackbox-exporter/blackbox/blackbox.yml:
--------------------------------------------------------------------------------
1 | modules:
2 | http_2xx:
3 | prober: http
4 | timeout: 5s
5 | http:
6 | method: GET
--------------------------------------------------------------------------------
/blackbox-exporter/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.2'
2 | services:
3 | blackbox:
4 | image: prom/blackbox-exporter:${BLACKBOX_EXPORTER_TAG}
5 | ports:
6 | - 9115:9115
7 | command:
8 | - --config.file=/etc/blackbox/blackbox.yml
9 | volumes:
10 | - ./blackbox/blackbox.yml:/etc/blackbox/blackbox.yml
11 | depends_on:
12 | - web
13 | prometheus:
14 | image: prom/prometheus:${PROMETHEUS_TAG}
15 | ports:
16 | - 9090:9090
17 | command:
18 | - --config.file=/etc/prometheus/prometheus.yml
19 | volumes:
20 | - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
21 | depends_on:
22 | - blackbox
23 | web:
24 | build:
25 | context: web
26 | args:
27 | goPackage: github.com/prometheus-community/prometheus-playground/blackbox-exporter/web
28 | goVersion: 1.11
29 | cache_from:
30 | - golang:1.11
31 | - scratch
32 | ports:
33 | - 2112:2112
34 |
--------------------------------------------------------------------------------
/blackbox-exporter/prometheus/prometheus.yml:
--------------------------------------------------------------------------------
1 | scrape_configs:
2 | - job_name: prometheus
3 | scrape_interval: 5s
4 | static_configs:
5 | - targets:
6 | - prometheus:9090
7 | - job_name: blackbox
8 | metrics_path: /probe
9 | scrape_interval: 5s
10 | params:
11 | module: [http_2xx]
12 | static_configs:
13 | - targets:
14 | - prometheus:9090
15 | - web:2112/health
16 | relabel_configs:
17 | - source_labels: [__address__]
18 | target_label: __param_target
19 | - source_labels: [__param_target]
20 | target_label: instance
21 | - target_label: __address__
22 | replacement: blackbox:9115
23 |
--------------------------------------------------------------------------------
/blackbox-exporter/web/Dockerfile:
--------------------------------------------------------------------------------
1 | # Args
2 | ARG goVersion
3 | ARG goPackage
4 |
5 | FROM golang:${goVersion} AS builder
6 |
7 | # Copy the code from the host and compile it
8 | WORKDIR /home
9 | COPY . ./
10 | RUN go mod vendor
11 | RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix nocgo -o /app .
12 |
13 | FROM scratch
14 | COPY --from=builder /app ./
15 | ENTRYPOINT ["./app"]
--------------------------------------------------------------------------------
/blackbox-exporter/web/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/prometheus-community/prometheus-playground/blackbox-exporter/web
2 |
3 | require (
4 | github.com/go-chi/chi v3.3.2+incompatible
5 | github.com/unrolled/render v0.0.0-20171102162132-65450fb6b2d3
6 | )
7 |
--------------------------------------------------------------------------------
/blackbox-exporter/web/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 | "net/http"
6 |
7 | "github.com/go-chi/chi"
8 | "github.com/unrolled/render"
9 | )
10 |
11 | var (
12 | renderer = render.New()
13 | )
14 |
15 | func health(w http.ResponseWriter, r *http.Request) {
16 | renderer.Text(w, http.StatusOK, "")
17 | }
18 |
19 | func hello(w http.ResponseWriter, r *http.Request) {
20 | renderer.JSON(w, http.StatusOK, map[string]string{"hello": "world"})
21 | }
22 |
23 | func main() {
24 | router := chi.NewRouter()
25 |
26 | router.Get("/health", health)
27 |
28 | router.Get("/hello", hello)
29 |
30 | log.Fatal(http.ListenAndServe(":2112", router))
31 | }
32 |
--------------------------------------------------------------------------------
/cadvisor/.env:
--------------------------------------------------------------------------------
1 | PROMETHEUS_TAG=v2.5.0
2 | CADVISOR_TAG=v0.32.0
3 | REDIS_TAG=5-alpine3.8
4 |
--------------------------------------------------------------------------------
/cadvisor/Makefile:
--------------------------------------------------------------------------------
1 | run:
2 | docker-compose up --build
3 |
4 | run-detached:
5 | docker-compose up --build --detach
6 |
7 | kill:
8 | docker-compose kill
9 |
--------------------------------------------------------------------------------
/cadvisor/README.md:
--------------------------------------------------------------------------------
1 | # cAdvisor sandbox
2 |
3 | In this sandbox, [cAdvisor](https://github.com/google/cadvisor) gathers metrics for three running containers:
4 |
5 | * Its own container
6 | * A container running [Redis](https://redis.io)
7 | * A container running [Prometheus](https://prometheus.io)
8 |
9 | The Prometheus instance scrapes metrics from cAdvisor and makes them accessible via the Prometheus [expression browser](https://prometheus.io/docs/visualization/browser).
10 |
11 | ## Usage
12 |
13 | To start the sandbox:
14 |
15 | ```bash
16 | # In the foreground
17 | make run # docker-compose up --build
18 |
19 | # In detached mode
20 | make run-detached # docker-compose up --build --detach
21 | ```
22 |
23 | This will start up the three containers mentioned above.
24 |
25 | > To kill the sandbox, run `make kill` (alias for `docker-compose kill`).
26 |
27 | Open up `http://localhost:9090/graph` to access the Prometheus expression browser. Some example metrics to explore:
28 |
29 | * [`rate(container_cpu_usage_seconds_total{name="redis"}[1m])`](http://localhost:9090/graph?g0.range_input=1h&g0.expr=rate(container_cpu_usage_seconds_total%7Bname%3D%22redis%22%7D%5B1m%5D)&g0.tab=1)
30 | * [`container_memory_usage_bytes{name="redis"}`](http://localhost:9090/graph?g0.range_input=1h&g0.expr=container_memory_usage_bytes%7Bname%3D%22redis%22%7D&g0.tab=1)
31 | * [`rate(container_network_transmit_bytes_total[1m])`](http://localhost:9090/graph?g0.range_input=1h&g0.expr=rate(container_network_transmit_bytes_total%5B1m%5D)&g0.tab=1)
32 | * [`rate(container_network_receive_bytes_total[1m])`](http://localhost:9090/graph?g0.range_input=1h&g0.expr=rate(container_network_receive_bytes_total%5B1m%5D)&g0.tab=1)
33 |
34 | ## Assets
35 |
36 | Folder | Assets
37 | :------|:------
38 | [`prometheus`](./prometheus) | A [`prometheus.yml`](./prometheus/prometheus.yml) configuration file for Prometheus
--------------------------------------------------------------------------------
/cadvisor/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.2'
2 | services:
3 | prometheus:
4 | image: prom/prometheus:${PROMETHEUS_TAG}
5 | ports:
6 | - 9090:9090
7 | command:
8 | - --config.file=/etc/prometheus/prometheus.yml
9 | volumes:
10 | - ./prometheus:/etc/prometheus
11 | links:
12 | - cadvisor:cadvisor
13 | depends_on:
14 | - cadvisor
15 | cadvisor:
16 | image: google/cadvisor:${CADVISOR_TAG}
17 | ports:
18 | - 8080:8080
19 | volumes:
20 | - /:/rootfs:ro
21 | - /var/run:/var/run:rw
22 | - /sys:/sys:ro
23 | - /var/lib/docker/:/var/lib/docker:ro
24 | depends_on:
25 | - redis
26 | redis:
27 | image: redis:${REDIS_TAG}
28 | ports:
29 | - 6379:6379
30 |
--------------------------------------------------------------------------------
/cadvisor/prometheus/prometheus.yml:
--------------------------------------------------------------------------------
1 | global:
2 | scrape_interval: 15s
3 | evaluation_interval: 15s
4 | scrape_timeout: 10s
5 |
6 | scrape_configs:
7 | - job_name: cadvisor
8 | scrape_interval: 5s
9 | static_configs:
10 | - targets:
11 | - cadvisor:8080
--------------------------------------------------------------------------------
/federation/.env:
--------------------------------------------------------------------------------
1 | PROMETHEUS_TAG=v2.5.0
2 | NODE_EXPORTER_TAG=v0.16.0
3 |
--------------------------------------------------------------------------------
/federation/Makefile:
--------------------------------------------------------------------------------
1 | run:
2 | docker-compose up --build
3 |
4 | run-detached:
5 | docker-compose up --build --detach
6 |
7 | kill:
8 | docker-compose kill
9 |
--------------------------------------------------------------------------------
/federation/README.md:
--------------------------------------------------------------------------------
1 | # Federation sandbox
2 |
3 | In this sandbox, three Prometheus instances are run as a single Prometheus [federation](https://prometheus.io/docs/prometheus/latest/federation). All three instances scrape metrics from a single [Node Exporter](../node-exporter).
4 |
5 | ## Usage
6 |
7 | To start the sandbox:
8 |
9 | ```bash
10 | # In the foreground
11 | make run # docker-compose up --build
12 |
13 | # In detached mode
14 | make run-detached # docker-compose up --build --detach
15 | ```
16 |
17 | This will start up three Prometheus services (`prometheus1`, `prometheus2`, and `prometheus3`) and a `node_exporter` service.
18 |
19 | Service | Description
20 | :-------|:-----------
21 | `prometheus1`, `prometheus2`, `prometheus3` | Standard Prometheus instances [configured](./prometheus/prometheus.yml#L10-L14) to run as a single federation
22 | `node_exporter` | A Node Exporter instance that gathers and exposes Linux host metrics to be scraped by the Prometheus federation
23 |
24 | > To kill the sandbox, run `make kill` (alias for `docker-compose kill`).
25 |
26 | Open up `http://localhost:9090/graph` to access the Prometheus [expression browser](https://prometheus.io/docs/visualization/browser). The expression browser is actually available via all three Prometheus instances (ports 9090, 9091, and 9092).
27 |
--------------------------------------------------------------------------------
/federation/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.2'
2 | services:
3 | prometheus1:
4 | image: prom/prometheus:${PROMETHEUS_TAG}
5 | ports:
6 | - 9090:9090
7 | command:
8 | - --config.file=/etc/prometheus/prometheus.yml
9 | volumes:
10 | - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
11 | prometheus2:
12 | image: prom/prometheus:${PROMETHEUS_TAG}
13 | ports:
14 | - 9091:9091
15 | command:
16 | - --config.file=/etc/prometheus/prometheus.yml
17 | - --web.listen-address=0.0.0.0:9091
18 | volumes:
19 | - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
20 | prometheus3:
21 | image: prom/prometheus:${PROMETHEUS_TAG}
22 | ports:
23 | - 9092:9092
24 | command:
25 | - --config.file=/etc/prometheus/prometheus.yml
26 | - --web.listen-address=0.0.0.0:9092
27 | volumes:
28 | - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
29 | node_exporter:
30 | image: prom/node-exporter:${NODE_EXPORTER_TAG}
31 | ports:
32 | - 9100:9100
33 |
--------------------------------------------------------------------------------
/federation/prometheus/prometheus.yml:
--------------------------------------------------------------------------------
1 | scrape_configs:
2 | - job_name: federate
3 | scrape_interval: 15s
4 | honor_labels: true
5 | metrics_path: '/federate'
6 | params:
7 | 'match[]':
8 | - '{job="prometheus"}'
9 | - '{__name__=~"job:.*"}'
10 | static_configs:
11 | - targets:
12 | - prometheus1:9090
13 | - prometheus2:9091
14 | - prometheus3:9092
15 | - job_name: node
16 | scrape_interval: 5s
17 | static_configs:
18 | - targets:
19 | - node_exporter:9100
20 |
--------------------------------------------------------------------------------
/file-sd/.env:
--------------------------------------------------------------------------------
1 | PROMETHEUS_TAG=v2.5.0
2 |
--------------------------------------------------------------------------------
/file-sd/Makefile:
--------------------------------------------------------------------------------
1 | run:
2 | docker-compose up --build
3 |
4 | run-detached:
5 | docker-compose up --build --detach
6 |
7 | kill:
8 | docker-compose kill
9 |
--------------------------------------------------------------------------------
/file-sd/README.md:
--------------------------------------------------------------------------------
1 | # File-based service discovery sandbox
2 |
3 | In this sandbox, a simple [web service](./myservice) running on the `myservice` host is scraped by a Prometheus instance. Prometheus discovers that host via [file-based service discovery](https://www.robustperception.io/using-json-file-service-discovery-with-prometheus).
4 |
5 | ## Usage
6 |
7 | To start the sandbox:
8 |
9 | ```bash
10 | # In the foreground
11 | make run # docker-compose up --build
12 |
13 | # In detached mode
14 | make run-detached # docker-compose up --build --detach
15 | ```
16 |
17 | This will start up two services:
18 |
19 | Service | Description
20 | :-------|:-----------
21 | `prometheus` | A Prometheus instance configured to use the [`targets.json`](./prometheus/targets.json) file for file-based service discovery (see the [`dummy`](./prometheus/prometheus.yml#L2-L5) job configuration)
22 | `myservice1` and `myservice2` | A basic web service that exposes a `/metrics` endpoint for Prometheus metrics and one custom metric: [`myservice_processed_ops_total`](./myservice/main.go#L20-L24). Two instances of this service are run.
23 |
24 | > To kill the sandbox, run `make kill` (alias for `docker-compose kill`).
25 |
26 | Once the sandbox is up and running, you can verify that the `myservice_processed_ops_total` metric is being scraped—and thus that the `myservice1` and `myservice2` services have been properly discovered by Prometheus—you can see the current value in the [expression browser](http://localhost:9090/graph?g0.range_input=1h&g0.expr=myservice_processed_ops_total&g0.tab=1).
--------------------------------------------------------------------------------
/file-sd/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.2'
2 | services:
3 | prometheus:
4 | image: prom/prometheus:${PROMETHEUS_TAG}
5 | ports:
6 | - 9090:9090
7 | command:
8 | - --config.file=/etc/prometheus/prometheus.yml
9 | volumes:
10 | - ./prometheus:/etc/prometheus:ro
11 | myservice1: &myservice
12 | build:
13 | context: myservice
14 | args:
15 | goPackage: github.com/prometheus-community/prometheus-playground/file-sd/myservice
16 | goVersion: 1.11
17 | environment:
18 | - PORT=1234
19 | ports:
20 | - 1234:1234
21 | myservice2:
22 | << : *myservice
23 | environment:
24 | - PORT=4321
25 | ports:
26 | - 4321:4321
--------------------------------------------------------------------------------
/file-sd/myservice/Dockerfile:
--------------------------------------------------------------------------------
1 | # Args
2 | ARG goVersion
3 | ARG goPackage
4 |
5 | FROM golang:${goVersion} AS builder
6 |
7 | # Copy the code from the host and compile it
8 | WORKDIR /home
9 | COPY . ./
10 | RUN go mod vendor
11 | RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix nocgo -o /app .
12 |
13 | FROM scratch
14 | COPY --from=builder /app ./
15 | ENTRYPOINT ["./app"]
--------------------------------------------------------------------------------
/file-sd/myservice/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/prometheus-community/prometheus-playground/file-sd/myservice
2 |
3 | require (
4 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973
5 | github.com/golang/protobuf v1.1.0
6 | github.com/matttproud/golang_protobuf_extensions v1.0.1
7 | github.com/prometheus/client_golang v0.0.0-20180713201052-bcbbc08eb2dd
8 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910
9 | github.com/prometheus/common v0.0.0-20180518154759-7600349dcfe1
10 | github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273
11 | )
12 |
--------------------------------------------------------------------------------
/file-sd/myservice/go.sum:
--------------------------------------------------------------------------------
1 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
2 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
3 | github.com/golang/protobuf v1.1.0 h1:0iH4Ffd/meGoXqF2lSAhZHt8X+cPgkfn/cb6Cce5Vpc=
4 | github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
5 | github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
6 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
7 | github.com/prometheus/client_golang v0.0.0-20180713201052-bcbbc08eb2dd h1:T6Y9DkTZlfcCB1qlrwQFCiAcLhTjmkjxW8EP3ZhV7Ts=
8 | github.com/prometheus/client_golang v0.0.0-20180713201052-bcbbc08eb2dd/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
9 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8=
10 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
11 | github.com/prometheus/common v0.0.0-20180518154759-7600349dcfe1 h1:osmNoEW2SCW3L7EX0km2LYM8HKpNWRiouxjE3XHkyGc=
12 | github.com/prometheus/common v0.0.0-20180518154759-7600349dcfe1/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
13 | github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273 h1:agujYaXJSxSo18YNX3jzl+4G6Bstwt+kqv47GS12uL0=
14 | github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
15 |
--------------------------------------------------------------------------------
/file-sd/myservice/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "log"
6 | "net/http"
7 | "os"
8 | "time"
9 |
10 | "github.com/prometheus/client_golang/prometheus/promauto"
11 |
12 | "github.com/prometheus/client_golang/prometheus"
13 | "github.com/prometheus/client_golang/prometheus/promhttp"
14 | )
15 |
16 | var (
17 | port = os.Getenv("PORT")
18 |
19 | processedOps = promauto.NewCounter(prometheus.CounterOpts{
20 | Name: "processed_ops_total",
21 | Help: "The total number of processed events",
22 | Namespace: "myservice",
23 | })
24 | )
25 |
26 | func recordMetrics() {
27 | go func() {
28 | for {
29 | processedOps.Inc()
30 | time.Sleep(2 * time.Second)
31 | }
32 | }()
33 | }
34 |
35 | func main() {
36 | address := fmt.Sprintf(":%s", port)
37 |
38 | recordMetrics()
39 |
40 | http.Handle("/metrics", promhttp.Handler())
41 | log.Fatal(http.ListenAndServe(address, nil))
42 | }
43 |
--------------------------------------------------------------------------------
/file-sd/prometheus/prometheus.yml:
--------------------------------------------------------------------------------
1 | global:
2 | scrape_interval: 5s
3 |
4 | scrape_configs:
5 | - job_name: dummy
6 | file_sd_configs:
7 | - files:
8 | - targets.json
9 |
--------------------------------------------------------------------------------
/file-sd/prometheus/targets.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "targets": [
4 | "myservice1:1234",
5 | "myservice2:4321"
6 | ],
7 | "labels": {
8 | "env": "development",
9 | "job": "myservice"
10 | }
11 | }
12 | ]
13 |
--------------------------------------------------------------------------------
/go-app/.env:
--------------------------------------------------------------------------------
1 | PROMETHEUS_TAG=v2.5.0
2 |
3 |
--------------------------------------------------------------------------------
/go-app/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/go-app/Makefile:
--------------------------------------------------------------------------------
1 | run:
2 | docker-compose up --build
3 |
4 | run-detached:
5 | docker-compose up --build --detach
6 |
7 | kill:
8 | docker-compose kill
9 |
--------------------------------------------------------------------------------
/go-app/README.md:
--------------------------------------------------------------------------------
1 | # Instrumented Go application
2 |
3 | In this sandbox, a Prometheus intance scrapes metrics from a simple [Go](https://golang.org) web application.
4 |
5 | ## Usage
6 |
7 | To start the sandbox:
8 |
9 | ```bash
10 | # In the foreground
11 | make run # docker-compose up --build
12 |
13 | # In detached mode
14 | make run-detached # docker-compose up --build --detach
15 | ```
16 |
17 | This will start up two services:
18 |
19 | Service | Description
20 | :-------|:-----------
21 | `prometheus` | A Prometheus instance that's [configured](./prometheus/prometheus.yml) to scrape metrics from the Go application running on port 2112
22 | `myapp` | A simple Go web application that pretty much only exports a simple metric (a [`myapp_processed_ops_total`](./myapp/main.go#L20-L24) counter that is [incremented](./myapp/main.go#L27-L34) every 2 seconds)
23 |
24 | Once the sandbox is up and running, navigate to http://localhost:9090/graph in your browser and enter `myapp_processed_ops_total` into the expression bar to see the most up-to-date value of the counter.
25 |
26 | You can also see this metrics by "scraping" the Go web server's `/metrics` endpoint:
27 |
28 | ```bash
29 | curl localhost:2112/metrics | grep myapp_processed_ops_total
30 | # HELP myapp_processed_ops_total The total number of processed events
31 | # TYPE myapp_processed_ops_total counter
32 | myapp_processed_ops_total 4
33 | ```
--------------------------------------------------------------------------------
/go-app/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.2'
2 | services:
3 | myapp:
4 | build:
5 | context: myapp
6 | args:
7 | goPackage: github.com/prometheus-community/prometheus-playground/go-app/myapp
8 | goVersion: 1.11
9 | cache_from:
10 | - golang:1.11
11 | - scratch
12 | ports:
13 | - 2112:2112
14 | prometheus:
15 | image: prom/prometheus:${PROMETHEUS_TAG}
16 | ports:
17 | - 9090:9090
18 | command:
19 | - --config.file=/etc/prometheus/prometheus.yml
20 | volumes:
21 | - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
22 |
--------------------------------------------------------------------------------
/go-app/myapp/Dockerfile:
--------------------------------------------------------------------------------
1 | # Args
2 | ARG goVersion
3 | ARG goPackage
4 |
5 | FROM golang:${goVersion} AS builder
6 |
7 | # Copy the code from the host and compile it
8 | WORKDIR /home
9 | COPY . ./
10 | RUN go mod vendor
11 | RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix nocgo -o /app .
12 |
13 | FROM scratch
14 | COPY --from=builder /app ./
15 | ENTRYPOINT ["./app"]
--------------------------------------------------------------------------------
/go-app/myapp/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/prometheus-community/prometheus-playground/go-app/myapp
2 |
3 | require (
4 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 // indirect
5 | github.com/golang/protobuf v1.1.0 // indirect
6 | github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
7 | github.com/prometheus/client_golang v0.0.0-20180713201052-bcbbc08eb2dd
8 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 // indirect
9 | github.com/prometheus/common v0.0.0-20180518154759-7600349dcfe1 // indirect
10 | github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273 // indirect
11 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f // indirect
12 | )
13 |
--------------------------------------------------------------------------------
/go-app/myapp/go.sum:
--------------------------------------------------------------------------------
1 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
2 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
3 | github.com/golang/protobuf v1.1.0 h1:0iH4Ffd/meGoXqF2lSAhZHt8X+cPgkfn/cb6Cce5Vpc=
4 | github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
5 | github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
6 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
7 | github.com/prometheus/client_golang v0.0.0-20180713201052-bcbbc08eb2dd h1:T6Y9DkTZlfcCB1qlrwQFCiAcLhTjmkjxW8EP3ZhV7Ts=
8 | github.com/prometheus/client_golang v0.0.0-20180713201052-bcbbc08eb2dd/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
9 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8=
10 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
11 | github.com/prometheus/common v0.0.0-20180518154759-7600349dcfe1 h1:osmNoEW2SCW3L7EX0km2LYM8HKpNWRiouxjE3XHkyGc=
12 | github.com/prometheus/common v0.0.0-20180518154759-7600349dcfe1/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
13 | github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273 h1:agujYaXJSxSo18YNX3jzl+4G6Bstwt+kqv47GS12uL0=
14 | github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
15 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ=
16 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
17 |
--------------------------------------------------------------------------------
/go-app/myapp/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "log"
6 | "net/http"
7 | "time"
8 |
9 | "github.com/prometheus/client_golang/prometheus/promauto"
10 |
11 | "github.com/prometheus/client_golang/prometheus"
12 | "github.com/prometheus/client_golang/prometheus/promhttp"
13 | )
14 |
15 | const (
16 | port = 2112
17 | )
18 |
19 | var (
20 | processedOps = promauto.NewCounter(prometheus.CounterOpts{
21 | Name: "processed_ops_total",
22 | Help: "The total number of processed events",
23 | Namespace: "myapp",
24 | })
25 | )
26 |
27 | func recordMetrics() {
28 | go func() {
29 | for {
30 | processedOps.Inc()
31 | time.Sleep(2 * time.Second)
32 | }
33 | }()
34 | }
35 |
36 | func main() {
37 | address := fmt.Sprintf(":%d", port)
38 |
39 | recordMetrics()
40 |
41 | http.Handle("/metrics", promhttp.Handler())
42 | log.Fatal(http.ListenAndServe(address, nil))
43 | }
44 |
--------------------------------------------------------------------------------
/go-app/prometheus/prometheus.yml:
--------------------------------------------------------------------------------
1 | global:
2 | scrape_interval: 10s
3 |
4 | scrape_configs:
5 | - job_name: myapp
6 | static_configs:
7 | - targets:
8 | - myapp:2112
--------------------------------------------------------------------------------
/haproxy/.env:
--------------------------------------------------------------------------------
1 | PROMETHEUS_TAG=v2.5.0
2 | HAPROXY_TAG=1.8
3 |
--------------------------------------------------------------------------------
/haproxy/Makefile:
--------------------------------------------------------------------------------
1 | run:
2 | docker-compose up --build
3 |
4 | run-detached:
5 | docker-compose up --build --detach
6 |
7 | kill:
8 | docker-compose kill
9 |
--------------------------------------------------------------------------------
/haproxy/README.md:
--------------------------------------------------------------------------------
1 | # haproxy sandbox
2 |
3 | In this sandbox, [HAProxy](http://www.haproxy.org/) acts as a reverse proxy for Prometheus, enforcing both [TLS encryption](https://prometheus.io/docs/guides/tls-encryption) and [basic auth](https://prometheus.io/docs/guides/basic-auth). All Prometheus endpoints are available behind https://example.com/prometheus. The [expression browser](https://prometheus.io/docs/visualization/browser), for example, is available at https://example.com/prometheus/graph.
4 |
5 | > To access Prometheus in this sandbox, two username/password combos are possible: `admin1`/`password1` and `admin2`/`password2`.
6 |
7 | ## Usage
8 |
9 | To start the sandbox:
10 |
11 | ```bash
12 | # In the foreground
13 | make run # docker-compose up --build
14 |
15 | # In detached mode
16 | make run-detached # docker-compose up --build --detach
17 | ```
18 |
19 | This will start up an `haproxy` container and a `prometheus` container.
20 |
21 | The `haproxy` container is available on `localhost` port 443 but the example will only work if you map `localhost` to `example.com`. You can do so by modifying your `/etc/hosts` file to include a line like this:
22 |
23 | ```conf
24 | 127.0.0.1 localhost example.com
25 | ```
26 |
27 | As HAProxy enforces both TLS encryption and basic auth, this will result in a self-signed certificate error:
28 |
29 | ```bash
30 | curl https://example.com/prometheus/metrics
31 | ```
32 |
33 | If you disable cert checking using `--insecure`/`-k` you'll get a `401 Unauthorized` error:
34 |
35 | ```bash
36 | curl -ik https://example.com/prometheus/graph
37 | ```
38 |
39 | You'll need to supply an valid username and password to access Prometheus through the proxy:
40 |
41 | ```bash
42 | curl -ik -u admin1:password1 https://example.com/prometheus/metrics
43 | ```
44 |
45 | Open up `https://admin1:password1@example.com/prometheus/graph` to access the Prometheus [expression browser](https://prometheus.io/docs/visualization/browser).
46 |
47 | ## Assets
48 |
49 | Folder | Assets
50 | :------|:------
51 | [`certs`](./certs) | An SSL cert and key generated by [OpenSSL](https://www.openssl.org/)
52 | [`haproxy`](./haproxy) | An [`haproxy.cfg`](./haproxy/haproxy.cfg) configuration file
53 | [`prometheus`](./prometheus) | A [`prometheus.yml`](./prometheus/prometheus.yml) configuration file for Prometheus
54 |
55 | The haproxy cert was created using these commands:
56 |
57 | ```bash
58 | openssl req -newkey rsa:4096 -nodes -keyout certs/key.pem -x509 -out certs/certificate.pem \
59 | -subj "/C=US/ST=OR/L=Portland/O=CNCF/OU=Developer advocacy/CN=example.com"
60 | cat certs/{certificate,key}.pem > certs/cert.pem
61 | rm certs/{certificate,key}.pem
62 | ```
63 |
64 | The hashed passwords in [`haproxy.cfg`](./haproxy/haproxy.cfg) were created using these commands:
65 |
66 | ```bash
67 | mkpasswd -m sha-512 password1
68 | mkpasswd -m sha-512 password2
69 | ```
--------------------------------------------------------------------------------
/haproxy/certs/cert.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIFWjCCA0ICCQC0XYj4xhiLfzANBgkqhkiG9w0BAQsFADBvMQswCQYDVQQGEwJV
3 | UzELMAkGA1UECAwCT1IxETAPBgNVBAcMCFBvcnRsYW5kMQ0wCwYDVQQKDARDTkNG
4 | MRswGQYDVQQLDBJEZXZlbG9wZXIgYWR2b2NhY3kxFDASBgNVBAMMC2V4YW1wbGUu
5 | Y29tMB4XDTE4MDcyMTE1NTM0MVoXDTE4MDgyMDE1NTM0MVowbzELMAkGA1UEBhMC
6 | VVMxCzAJBgNVBAgMAk9SMREwDwYDVQQHDAhQb3J0bGFuZDENMAsGA1UECgwEQ05D
7 | RjEbMBkGA1UECwwSRGV2ZWxvcGVyIGFkdm9jYWN5MRQwEgYDVQQDDAtleGFtcGxl
8 | LmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDcXcV2PgqRVOhG
9 | z1ZgfupjyMhxnzIz7fjoTi1Uh+0TXTPtxLFEQ6ENBU338eCnL2sTShEue9o8O9lk
10 | p5fFYNWZRfvw3wDABbS/3yYnkJ37uo3XtRhDJPfgkbjj/XnwNVdbis4Uz9vBOIER
11 | oS2WfMzVK9aATNjUTNPX6yCqOZ2ZkSlGxQZgIT6PYCMcqgyaK0SnIDFqWZv9mUNi
12 | YsFbeUvE2EvohbqVhMZsgFIH/J6IWmcyXOjdquskmEVwTsU8sV2KVa2sd0T0Bni9
13 | vd1BReqreqQ8P6lQRmPvDL9gww3rOnNRWYnWlbLaYEjkAqa4pcxfeTzsw97D3y3C
14 | a7nVvaGbWrDrDLbi53h84+qH7pa1u4YPGXEDnRDtQvkRcuC8X14NLsZtRieUqjRw
15 | TYv+iPsfQ0FtZeim3w5A4DnriHRZopDRdAJ3BfCORWwWWCs16ofyckh2wRuIlaxt
16 | OWc+BWc/mxvDiZ89qGQLLAZ5xnVZqmcDAeljK/WW3nE1Yl+nknTjFe3mpwU5hGzE
17 | t8YAurjQyfzXjVaS4xgIR+adza01AzQUWg1ovBjQ5Bv9Ii5Yg/JycIiCKqVdB+fQ
18 | n1GOg1VjKmTmrOBIpRSvJKDNl1/DBRIKQJhToLTmbxVhrgjlqtijIHMXR0Sr5Z+t
19 | NcF88tcNlpIqO3HHd1NGqI5LLQFFAgMBAAEwDQYJKoZIhvcNAQELBQADggIBADWc
20 | GQwlxZVU4SVODJas2rtr8Tot4T7E3S16KjIwOepn8Iso6ApTr2MoVstjIxeF2zA0
21 | wYu0xWeiO5kKll2jZGFaEHXimBggJP3Zvg0PKo1VNDF93H28xuqbfI3PX6IUBGjK
22 | Bd0uRZ7/88r9cr7JzrnYN6CjLGqteDn+cl62dR7eRMzkk6ff6xOfsT21Y1DcEpra
23 | HBQOY4JP0p95z9UEQJz5iHhzJWL/leQXZ5iv5FLeY0AuXxN4u+wPaEAPQvVi6o8l
24 | WH8zvgt6fzjwYQWION37bPJC/UafwzWTSKktsGl9PvTHTq+wBKPjGfN98to+Y9mW
25 | NMAEHm76nEBc+ql2qvStz7N4Ip5tSdSfvmcmqPO1AjfEQzdHnOEG6VEQrz+b63I8
26 | VTktyGhn0gEWxzIHhwmBsGUm+w/h1PqvxShkxmMbK7nvGzeQ4hB0PlXi1zK4FNPv
27 | HJ3OqO2Q40nAVQczW2W7FGqlrT1vOV9pI/jTklBFXVHKQ5ecKgSmONdN/lXpobei
28 | w1IHld8G4nBuOWD8HNkzDLJTCQmxSSEEowFV6qf53mliYRM4TbD8I2aQVwufKpl/
29 | qD+AZGf03wWJrGFCPDntsjzRbwbhLnmY07CHO9tjh+ULRkgl5QO1ljyWL45UTr8L
30 | QvmvA9pt43283OdzBLTp8ODPqNBxUbKjLt0zxpKQ
31 | -----END CERTIFICATE-----
32 | -----BEGIN PRIVATE KEY-----
33 | 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
82 | vHWj7+Gw/wjBwlQd2c7jKr9trEqPDw==
83 | -----END PRIVATE KEY-----
84 |
--------------------------------------------------------------------------------
/haproxy/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.2'
2 | services:
3 | haproxy:
4 | image: haproxy:${HAPROXY_TAG}
5 | ports:
6 | - 443:443
7 | volumes:
8 | - ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
9 | - ./certs:/etc/ssl/certs:ro
10 | depends_on:
11 | - prometheus
12 | prometheus:
13 | image: prom/prometheus:${PROMETHEUS_TAG}
14 | expose:
15 | - 9090
16 | command:
17 | - --config.file=/etc/prometheus/prometheus.yml
18 | - --web.route-prefix=/prometheus
19 | - --web.external-url=http://example.com
20 | volumes:
21 | - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
--------------------------------------------------------------------------------
/haproxy/haproxy/haproxy.cfg:
--------------------------------------------------------------------------------
1 | userlist admin_users
2 | group admins users admin1,admin2
3 | user admin1 password $6$Mz3hA8lfZL2A06kQ$IQEFAIVBVhlqZT01fasZh6PHrZ0YrzvDSpZ0hY91r3fSoCsE1/vPYULV6CPVeBN/9bku18y6tF4TKgFSMsE.w1
4 | user admin2 password $6$m4JR4Q28pz6M1NrX$DqNQYI3XdvVya3fZJlCmi7MapRMXq1e/FOeX3p9bqNvkygX8fg4BQc6A8OkKYTZxDwX/CHpwnXdAzetG4HO64.
5 |
6 | defaults
7 | mode http
8 | balance roundrobin
9 | timeout connect 5000
10 | timeout client 10000
11 | timeout server 10000
12 |
13 | frontend proxy
14 | bind 0.0.0.0:443 ssl crt /etc/ssl/certs/cert.pem
15 | acl url_prometheus path_beg /prometheus
16 | acl is_admin http_auth(admin_users)
17 | http-request allow if is_admin
18 | http-request deny
19 | use_backend prometheus if url_prometheus is_admin
20 |
21 | backend prometheus
22 | server prom1 prometheus:9090 check
23 |
--------------------------------------------------------------------------------
/haproxy/prometheus/prometheus.yml:
--------------------------------------------------------------------------------
1 | scrape_configs:
2 | - job_name: prometheus
3 | scrape_interval: 5s
4 | static_configs:
5 | - targets:
6 | - localhost:9090
--------------------------------------------------------------------------------
/nginx/.env:
--------------------------------------------------------------------------------
1 | PROMETHEUS_TAG=v2.5.0
2 | NGINX_TAG=1.15.7-alpine
3 |
--------------------------------------------------------------------------------
/nginx/Makefile:
--------------------------------------------------------------------------------
1 | run:
2 | docker-compose up --build
3 |
4 | run-detached:
5 | docker-compose up --build --detach
6 |
7 | kill:
8 | docker-compose kill
9 |
--------------------------------------------------------------------------------
/nginx/README.md:
--------------------------------------------------------------------------------
1 | # nginx sandbox
2 |
3 | In this sandbox, [nginx](https://nginx.org) acts as a reverse proxy for Prometheus, enforcing both [TLS encryption](https://prometheus.io/docs/guides/tls-encryption) and [basic auth](https://prometheus.io/docs/guides/basic-auth). All Prometheus endpoints are available behind https://example.com/prometheus. The [expression browser](https://prometheus.io/docs/visualization/browser), for example, is available at https://example.com/prometheus/graph.
4 |
5 | > To access Prometheus in this sandbox, the proper username/password combo is `admin`/`password`.
6 |
7 | ## Usage
8 |
9 | To start the sandbox:
10 |
11 | ```bash
12 | # In the foreground
13 | make run # docker-compose up --build
14 |
15 | # In detached mode
16 | make run-detached # docker-compose up --build --detach
17 | ```
18 |
19 | This will start up an `nginx` container and a `prometheus` container.
20 |
21 | > To kill the sandbox, run `make kill` (alias for `docker-compose kill`).
22 |
23 | The `nginx` container is available on `localhost` port 443 but the example will only work if you map `localhost` to `example.com`. You can do so by modifying your `/etc/hosts` file to include a line like this:
24 |
25 | ```conf
26 | 127.0.0.1 localhost example.com
27 | ```
28 |
29 | As nginx enforces both TLS encryption and basic auth, this will result in a self-signed certificate error:
30 |
31 | ```bash
32 | curl https://example.com/prometheus/metrics
33 | ```
34 |
35 | If you disable cert checking using `--insecure`/`-k` you'll get a `401 Unauthorized` error:
36 |
37 | ```bash
38 | curl -ik https://example.com/prometheus/metrics
39 | ```
40 |
41 | You'll need to supply the username and password to access Prometheus through the proxy:
42 |
43 | ```bash
44 | curl -ik -u admin:password https://example.com/prometheus/metrics
45 | ```
46 |
47 | Open up `https://admin:password@example.com/prometheus/graph` to access the Prometheus [expression browser](https://prometheus.io/docs/visualization/browser).
48 |
49 | ## Assets
50 |
51 | Folder | Assets
52 | :------|:------
53 | [`certs`](./certs) | An SSL cert and key generated by [OpenSSL](https://www.openssl.org/)
54 | [`haproxy`](./haproxy) | An [`haproxy.cfg`](./haproxy/haproxy.cfg) configuration file and [`.htpasswd`](./nginx/.htpasswd) password file
55 | [`prometheus`](./prometheus) | A [`prometheus.yml`](./prometheus/prometheus.yml) configuration file for Prometheus
56 |
57 | The nginx certs were created using this command:
58 |
59 | ```bash
60 | openssl req -newkey rsa:4096 -nodes -keyout certs/example.com.key -x509 -out certs/example.com.crt \
61 | -subj "/C=US/ST=OR/L=Portland/O=CNCF/OU=Developer advocacy/CN=example.com"
62 | ```
--------------------------------------------------------------------------------
/nginx/certs/example.com.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | 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
32 | -----END CERTIFICATE-----
33 |
--------------------------------------------------------------------------------
/nginx/certs/example.com.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | 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
51 | 6azFFyoB+Fu9hArTbj1llPI+4zDujQY=
52 | -----END PRIVATE KEY-----
53 |
--------------------------------------------------------------------------------
/nginx/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.2'
2 | services:
3 | nginx:
4 | image: nginx:${NGINX_TAG}
5 | volumes:
6 | - ./nginx:/etc/nginx:ro
7 | - ./certs:/root/certs/example.com
8 | ports:
9 | - 443:443
10 | links:
11 | - prometheus:prometheus
12 | depends_on:
13 | - prometheus
14 | prometheus:
15 | image: prom/prometheus:${PROMETHEUS_TAG}
16 | ports:
17 | - 9090:9090
18 | command:
19 | - --config.file=/etc/prometheus/prometheus.yml
20 | - --web.route-prefix=/
21 | - --web.external-url=http://example.com/prometheus
22 | volumes:
23 | - ./prometheus:/etc/prometheus
24 |
--------------------------------------------------------------------------------
/nginx/nginx/.htpasswd:
--------------------------------------------------------------------------------
1 | admin:$apr1$Ps6FCt9l$trPwM2uLDcu3Tedmz/3dp/
2 |
--------------------------------------------------------------------------------
/nginx/nginx/nginx.conf:
--------------------------------------------------------------------------------
1 | events {}
2 |
3 | http {
4 | server {
5 | listen 443 ssl;
6 | ssl_certificate /root/certs/example.com/example.com.crt;
7 | ssl_certificate_key /root/certs/example.com/example.com.key;
8 |
9 | location /prometheus/ {
10 | auth_basic "Prometheus";
11 | auth_basic_user_file /etc/nginx/.htpasswd;
12 | proxy_pass http://prometheus:9090/;
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/nginx/prometheus/prometheus.yml:
--------------------------------------------------------------------------------
1 | scrape_configs:
2 | - job_name: prometheus
3 | scrape_interval: 5s
4 | static_configs:
5 | - targets:
6 | - localhost:9090
--------------------------------------------------------------------------------
/node-exporter/.env:
--------------------------------------------------------------------------------
1 | PROMETHEUS_TAG=v2.5.0
2 | NODE_EXPORTER_TAG=v0.16.0
3 |
--------------------------------------------------------------------------------
/node-exporter/Makefile:
--------------------------------------------------------------------------------
1 | run:
2 | docker-compose up --build
3 |
4 | run-detached:
5 | docker-compose up --build --detach
6 |
7 | kill:
8 | docker-compose kill
9 |
--------------------------------------------------------------------------------
/node-exporter/README.md:
--------------------------------------------------------------------------------
1 | # Node Exporter sandbox
2 |
3 | In this sandbox, [Prometheus](https://prometheus.io) scrapes Linux host metrics from a [Node Exporter](https://prometheus.io/docs/guides/node-exporter).
4 |
5 | ## Usage
6 |
7 | To start the sandbox:
8 |
9 | ```bash
10 | # In the foreground
11 | make run # docker-compose up --build
12 |
13 | # In detached mode
14 | make run-detached # docker-compose up --build --detach
15 | ```
16 |
17 | This will start up a `node_exporter` container and a `prometheus` container.
18 |
19 | > To kill the sandbox, run `make kill` (alias for `docker-compose kill`).
20 |
21 | Open up `http://localhost:9090/graph` to access the Prometheus [expression browser](https://prometheus.io/docs/visualization/browser). Here are some example metrics to explore:
22 |
23 | * [`rate(node_cpu_seconds_total{mode="system"}[1m])`](http://localhost:9090/graph?g0.range_input=1h&g0.expr=rate(node_cpu_seconds_total%7Bmode%3D%22system%22%7D%5B1m%5D)&g0.tab=1)
24 | * [`node_filesystem_avail_bytes`](http://localhost:9090/graph?g0.range_input=1h&g0.expr=node_filesystem_avail_bytes&g0.tab=1)
25 | * [`rate(node_network_receive_bytes_total[1m])`](http://localhost:9090/graph?g0.range_input=1h&g0.expr=rate(node_network_receive_bytes_total%5B1m%5D)&g0.tab=1)
26 |
27 | ## Assets
28 |
29 | Folder | Assets
30 | :------|:------
31 | [`prometheus`](./prometheus) | A [`prometheus.yml`](./prometheus/prometheus.yml) configuration file for Prometheus
--------------------------------------------------------------------------------
/node-exporter/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.2'
2 | services:
3 | node_exporter:
4 | image: prom/node-exporter:${NODE_EXPORTER_TAG}
5 | ports:
6 | - 9100:9100
7 | prometheus:
8 | image: prom/prometheus:${PROMETHEUS_TAG}
9 | ports:
10 | - 9090:9090
11 | command:
12 | - --config.file=/etc/prometheus/prometheus.yml
13 | volumes:
14 | - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
15 | depends_on:
16 | - node_exporter
17 |
--------------------------------------------------------------------------------
/node-exporter/prometheus/prometheus.yml:
--------------------------------------------------------------------------------
1 | global:
2 | scrape_interval: 15s
3 | evaluation_interval: 15s
4 |
5 | scrape_configs:
6 | - job_name: prometheus
7 | static_configs:
8 | - targets:
9 | - localhost:9090
10 | - job_name: node
11 | static_configs:
12 | - targets:
13 | - node_exporter:9100
--------------------------------------------------------------------------------
/python-flask-app/.env:
--------------------------------------------------------------------------------
1 | PROMETHEUS_TAG=v2.5.0
2 |
--------------------------------------------------------------------------------
/python-flask-app/Makefile:
--------------------------------------------------------------------------------
1 | run:
2 | docker-compose up --build
3 |
4 | run-detached:
5 | docker-compose up --build --detach
6 |
7 | kill:
8 | docker-compose kill
9 |
--------------------------------------------------------------------------------
/python-flask-app/README.md:
--------------------------------------------------------------------------------
1 | # Instrumented Python Flask application
2 |
3 | In this sandbox, a Prometheus instance scrapes metrics from a simple Python [Flask](http://flask.pocoo.org/) web application.
4 |
5 | ## Usage
6 |
7 | To start the sandbox:
8 |
9 | ```bash
10 | # In the foreground
11 | make run # docker-compose up --build
12 |
13 | # In detached mode
14 | make run-detached # docker-compose up --build --detach
15 | ```
16 |
17 | This will start up two services:
18 |
19 | Service | Description
20 | :-------|:-----------
21 | `prometheus` | A Prometheus instance that's [configured](./prometheus/prometheus.yml) to scrape metrics from the Go application running on port 2112
22 | `myapp` | A simple Python Flask web application exports a [`LATENCY_HISTOGRAM`](./myapp/server.py#L6) and a [`REQUEST_COUNTER`](./myapp/server.py#L7)
23 |
24 | Create some example web traffic to the app:
25 |
26 | ```shell
27 | for n in {1..100}; do
28 | curl http://localhost:5000/test-endpoint
29 | done
30 | ```
31 |
32 | Once the sandbox is up and running, navigate to http://localhost:9090/graph in your browser and enter `myapp_request_count_total` into the expression bar to see the most up-to-date value of the counter.
33 |
34 | You can also see this metrics by "scraping" the Flask web server's `/metrics` endpoint:
35 |
36 | ```bash
37 | curl localhost:5000/metrics | grep myapp_request_count_total
38 | # HELP myapp_request_count_total myapp HTTP request count
39 | # TYPE myapp_request_count_total counter
40 | myapp_request_count_total{endpoint="/metrics",method="GET",status="200"} 17.0
41 | ```
42 |
43 | Here are some example metrics to explore in the Prometheus [expression browser](https://prometheus.io/docs/visualization/browser):
44 |
45 | * [`myapp_request_count_total{endpoint="/test-endpoint"}`](http://localhost:9090/graph?g0.range_input=1h&g0.expr=myapp_request_count_total%7Bendpoint%3D%22%2Ftest-endpoint%22%7D&g0)
46 | * [`myapp_request_latency_seconds_bucket{endpoint="/test-endpoint",le="0.1"}`](http://localhost:9090/graph?g0.range_input=1h&g0.expr=myapp_request_latency_seconds_bucket%7Bendpoint%3D%22%2Ftest-endpoint%22%2Cle%3D%220.1%22%7D&g0)
47 |
--------------------------------------------------------------------------------
/python-flask-app/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.2'
2 | services:
3 | prometheus:
4 | image: prom/prometheus:${PROMETHEUS_TAG}
5 | ports:
6 | - 9090:9090
7 | command:
8 | - --config.file=/etc/prometheus/prometheus.yml
9 | volumes:
10 | - ./prometheus:/etc/prometheus:ro
11 | myapp:
12 | build:
13 | context: myapp
14 | cache_from:
15 | - python:3.7.0-alpine3.8
16 | ports:
17 | - 5000:5000
--------------------------------------------------------------------------------
/python-flask-app/myapp/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.7.0-alpine3.8
2 |
3 | WORKDIR /usr/src/myapp
4 |
5 | COPY server.py requirements.txt ./
6 |
7 | RUN pip install -r requirements.txt
8 |
9 | EXPOSE 5000
10 |
11 | CMD ["python", "server.py"]
--------------------------------------------------------------------------------
/python-flask-app/myapp/requirements.txt:
--------------------------------------------------------------------------------
1 | Flask==1.0.2
2 | prometheus_client==0.4.2
--------------------------------------------------------------------------------
/python-flask-app/myapp/server.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | from flask import Flask, Response, jsonify, request
4 | from prometheus_client import Counter, Histogram, generate_latest, CONTENT_TYPE_LATEST
5 |
6 | LATENCY_HISTOGRAM = Histogram('myapp_request_latency_seconds', 'myapp request latency', ['method', 'endpoint'])
7 | REQUEST_COUNTER = Counter('myapp_request_count', 'myapp HTTP request count', ['method', 'endpoint', 'status'])
8 |
9 | app = Flask(__name__)
10 |
11 | def before_request():
12 | request.start_time = time.time()
13 |
14 | def after_request(response):
15 | request_latency = time.time() - request.start_time
16 | LATENCY_HISTOGRAM.labels(request.method, request.path).observe(request_latency)
17 | REQUEST_COUNTER.labels(request.method, request.path, response.status_code).inc()
18 | return response
19 |
20 | @app.route("/metrics")
21 | def metrics():
22 | return generate_latest(), 200
23 |
24 | @app.route("/")
25 | def other_routes(path):
26 | return "Hello world", 200
27 |
28 | if __name__ == '__main__':
29 | app.before_request(before_request)
30 | app.after_request(after_request)
31 | app.run(host='0.0.0.0')
--------------------------------------------------------------------------------
/python-flask-app/prometheus/prometheus.yml:
--------------------------------------------------------------------------------
1 | global:
2 | scrape_interval: 10s
3 |
4 | scrape_configs:
5 | - job_name: myapp
6 | static_configs:
7 | - targets:
8 | - myapp:5000
--------------------------------------------------------------------------------