Skip to content

Commit 0694c2c

Browse files
committed
Initial commit
0 parents  commit 0694c2c

File tree

10 files changed

+622
-0
lines changed

10 files changed

+622
-0
lines changed

README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Node.js Application Monitoring with Prometheus and Grafana
2+
3+
![](https://cdn.codersociety.com/uploads/keystone/nodejs-performance-monitoring-with-prometheus-and-grafana.png)
4+
5+
We discuss this repository in this article in detail:
6+
https://codersociety.com/blog/articles/nodejs-application-monitoring-with-prometheus-and-grafana
7+
8+
The repository contains a sample Node.js app which integrates the [Prometheus client for node.js](https://github.com/siimon/prom-client) and exposes metrics on [http://localhost:8080/metrics](http://localhost:8080/metrics). The metrics are periodically scraped by [Prometheus](https://prometheus.io) and visualized through a [Grafana](https://grafana.com/oss/grafana) monitoring dashboard.
9+
10+
## Prerequisites
11+
Make sure that you have Docker and Docker Compose installed:
12+
- [Docker Engine](https://docs.docker.com/engine)
13+
- [Docker Compose](https://docs.docker.com/compose)
14+
15+
## Getting started
16+
Clone the repository:
17+
```bash
18+
git clone https://github.com/coder-society/nodejs-monitoring-with-prometheus-and-grafana.git
19+
```
20+
21+
Navigate into the project directory:
22+
```bash
23+
cd nodejs-monitoring-with-prometheus-and-grafana
24+
```
25+
26+
Start the Docker containers:
27+
```bash
28+
docker-compose up -d
29+
```
30+
31+
## Test containers
32+
- Prometheus should be accessible via [http://localhost:9090](http://localhost:9090)
33+
- Grafana should be accessible via [http://localhost:3000](http://localhost:3000)
34+
- Example Node.js server metrics for RED monitoring should be accessible via [http://localhost:8080/metrics](http://localhost:8080/metrics)
35+
36+
## Open monitoring dashboards
37+
Open in your web browser the monitoring dashboards:
38+
- Monitoring dashboard for the Node.js app can be found on[http://localhost:3000/d/1DYaynomMk/example-service-dashboard](http://localhost:3000/d/1DYaynomMk/example-service-dashboard)

docker-compose.yml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
version: '2.1'
2+
networks:
3+
monitoring:
4+
driver: bridge
5+
volumes:
6+
prometheus_data: {}
7+
grafana_data: {}
8+
services:
9+
prometheus:
10+
image: prom/prometheus:v2.20.1
11+
container_name: prometheus
12+
volumes:
13+
- ./prometheus:/etc/prometheus
14+
- prometheus_data:/prometheus
15+
ports:
16+
- 9090:9090
17+
expose:
18+
- 9090
19+
networks:
20+
- monitoring
21+
grafana:
22+
image: grafana/grafana:7.1.5
23+
container_name: grafana
24+
volumes:
25+
- grafana_data:/var/lib/grafana
26+
- ./grafana/provisioning:/etc/grafana/provisioning
27+
environment:
28+
- GF_AUTH_DISABLE_LOGIN_FORM=true
29+
- GF_AUTH_ANONYMOUS_ENABLED=true
30+
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
31+
ports:
32+
- 3000:3000
33+
expose:
34+
- 3000
35+
networks:
36+
- monitoring
37+
example-nodejs-app:
38+
build:
39+
context: example-nodejs-app
40+
ports:
41+
- 8080:8080
42+
expose:
43+
- 8080
44+
networks:
45+
- monitoring

example-nodejs-app/Dockerfile

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
FROM node:13-alpine3.11 AS installer
2+
3+
RUN mkdir /app
4+
WORKDIR /app
5+
6+
COPY package.json /app/
7+
COPY package-lock.json /app/
8+
9+
RUN npm install
10+
11+
FROM node:13-alpine3.11
12+
13+
RUN mkdir /app
14+
WORKDIR /app
15+
16+
COPY index.js /app
17+
18+
COPY --from=installer /app/package.json .
19+
COPY --from=installer /app/node_modules ./node_modules
20+
21+
EXPOSE 8080
22+
23+
CMD npm start

example-nodejs-app/index.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
const http = require('http')
2+
const url = require('url');
3+
const client = require('prom-client')
4+
5+
const register = new client.Registry()
6+
7+
register.setDefaultLabels({
8+
app: 'example-nodejs-app'
9+
})
10+
11+
client.collectDefaultMetrics({ register })
12+
13+
const httpRequestDurationMicroseconds = new client.Histogram({
14+
name: 'http_request_duration_seconds',
15+
help: 'Duration of HTTP requests in seconds',
16+
labelNames: ['method', 'route', 'code'],
17+
buckets: [0.1, 0.3, 0.5, 0.7, 1, 3, 5, 7, 10] // 0.1 to 10 seconds
18+
})
19+
20+
register.registerMetric(httpRequestDurationMicroseconds)
21+
22+
const createOrderHandler = async (req, res) => {
23+
// return an error 1% of the time
24+
if ((Math.floor(Math.random() * 100)) === 0) {
25+
throw new Error('Internal Error')
26+
}
27+
28+
// delay for 3-6 seconds
29+
const delaySeconds = Math.floor(Math.random() * (6 - 3)) + 3
30+
await new Promise(res => setTimeout(res, delaySeconds * 1000))
31+
32+
res.end('Order created successfully');
33+
}
34+
35+
const server = http.createServer(async (req, res) => {
36+
const end = httpRequestDurationMicroseconds.startTimer();
37+
const route = url.parse(req.url).pathname;
38+
39+
try {
40+
if (route === '/metrics') {
41+
res.setHeader('Content-Type', register.contentType)
42+
res.end(register.metrics())
43+
}
44+
45+
if (route === '/order') {
46+
await createOrderHandler(req, res)
47+
}
48+
49+
} catch (error) {
50+
res.writeHead(500).end()
51+
}
52+
53+
if (!res.finished) {
54+
res.writeHead(404).end() // Default 404 handler
55+
}
56+
57+
end({ route, code: res.statusCode, method: req.method })
58+
})
59+
60+
server.listen(8080, () => {
61+
console.log('Server is running on http://localhost:8080, metrics are exposed on http://localhost:8080/metrics')
62+
})

example-nodejs-app/package-lock.json

Lines changed: 29 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

example-nodejs-app/package.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"name": "example-nodejs-app",
3+
"version": "1.0.0",
4+
"description": "Node.js Monitoring with Prometheus and Grafana",
5+
"main": "index.js",
6+
"scripts": {
7+
"start": "node index.js",
8+
"test": "echo \"Error: no test specified\" && exit 1"
9+
},
10+
"keywords": [
11+
"prometheus",
12+
"node.js",
13+
"monitoring",
14+
"grafana",
15+
"metrics"
16+
],
17+
"author": "Kentaro Wakayama",
18+
"license": "ISC",
19+
"dependencies": {
20+
"prom-client": "^12.0.0"
21+
}
22+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
apiVersion: 1
2+
3+
providers:
4+
- name: 'Prometheus'
5+
orgId: 1
6+
folder: ''
7+
type: file
8+
disableDeletion: false
9+
editable: true
10+
options:
11+
path: /etc/grafana/provisioning/dashboards

0 commit comments

Comments
 (0)