@apio/express-prometheus
Version:
Express middleware to provide basic metrics to Prometheus.
227 lines (196 loc) • 6.5 kB
JavaScript
const supertest = require('supertest')
const express = require('express')
const expressPrometheus = require('./index')
describe('index', () => {
let sut
describe('options', () => {
beforeEach(() => {
sut = express()
})
test('When not given url, should default to metrics', () => {
// Arrange
expressPrometheus.instrument(sut)
// Act
return supertest(sut)
.get('/metrics')
.then(result => {
// Assert
expect(result.statusCode).toBe(200)
})
})
test('When given url, should default to url value', () => {
// Arrange
const options = {
url: '/metric-route'
}
expressPrometheus.instrument(sut, options)
// Act
return supertest(sut)
.get(options.url)
.then(result => {
// Assert
expect(result.statusCode).toBe(200)
})
})
})
describe('metrics', () => {
let agent
beforeEach(() => {
sut = express()
expressPrometheus.instrument(sut)
sut.get('/resource', (req, res) => {
res.send()
})
sut.get('/resource/:id', (req, res) => {
res.send()
})
agent = supertest.agent(sut)
})
describe('http_requests_processing', () => {
test('Given metrics are running, should include http_requests_processing', () => {
// Arrange
// Act
return agent.get('/resource').then(() => {
return agent.get('/metrics').then(result => {
expect(result.statusCode).toBe(200)
expect(result.headers['content-type']).toBe(
'text/plain; charset=utf-8'
)
expect(result.text).toContain('http_requests_processing 0')
})
})
})
})
describe('http_requests_total', () => {
test('Given resource has been request, should being included in http_requests_total', () => {
// Arrange
// Act
return agent.get('/resource').then(() => {
return agent.get('/metrics').then(result => {
expect(result.statusCode).toBe(200)
expect(result.headers['content-type']).toBe(
'text/plain; charset=utf-8'
)
expect(result.text).toContain(
'http_requests_total{method="GET",path="/resource",status="200"} 2'
)
})
})
})
test('Given resource/:id has been request, should being included in http_requests_total', () => {
// Arrange
const id = 8
// Act
return agent.get(`/resource/${id}`).then(() => {
return agent.get('/metrics').then(result => {
expect(result.statusCode).toBe(200)
expect(result.headers['content-type']).toBe(
'text/plain; charset=utf-8'
)
expect(result.text).toContain(
'http_requests_total{method="GET",path="/resource/:id",status="200"} 1'
)
})
})
})
})
describe('http_request_duration_seconds', () => {
test('Given resource has been request, should being included in http_request_duration_seconds', () => {
// Arrange
// Act
return agent.get('/resource').then(() => {
return agent.get('/metrics').then(result => {
expect(result.statusCode).toBe(200)
expect(result.headers['content-type']).toBe(
'text/plain; charset=utf-8'
)
expect(result.text).toContain(
'http_request_duration_seconds_bucket{le="10",method="GET",path="/resource",status="200"} 3'
)
})
})
})
test('Given resource/:id has been request, should being included in http_request_duration_seconds', () => {
// Arrange
const id = 3
// Act
return agent.get(`/resource/${id}`).then(() => {
return agent.get('/metrics').then(result => {
expect(result.statusCode).toBe(200)
expect(result.headers['content-type']).toBe(
'text/plain; charset=utf-8'
)
expect(result.text).toContain(
'http_request_duration_seconds_bucket{le="10",method="GET",path="/resource/:id",status="200"} 2'
)
})
})
})
})
describe('third party metrics', () => {
test('Given metrics running, should include default node metrics', () => {
// Arrange
// Act
return agent.get('/metrics').then(result => {
// Assert
expect(result.text).toContain('nodejs_active_handles_total')
expect(result.text).toContain('nodejs_active_requests_total')
expect(result.text).toContain('nodejs_external_memory_bytes')
})
})
})
})
describe('labels', () => {
let agent
beforeEach(() => {
sut = express()
expressPrometheus.instrument(sut)
const router = express.Router()
router.get('/', (req, res) => {
res.send()
})
router.get('/:id', (req, res) => {
res.send()
})
sut.use('/resource-1', router)
sut.use('/resource-2', router)
sut.get('/resource-3/', (req, res) => {
res.send()
})
sut.get('/resource-3/:id', (req, res) => {
res.send()
})
agent = supertest.agent(sut)
})
test('Given a router route is called, should calculate path correctly', () => {
// Arrange
// Act
return agent.get('/resource-1/id-thing').then(() => {
return agent.get('/metrics').then(result => {
expect(result.statusCode).toBe(200)
expect(result.headers['content-type']).toBe(
'text/plain; charset=utf-8'
)
expect(result.text).toContain(
'http_requests_total{method="GET",path="/resource-1/:id",status="200"} 1'
)
})
})
})
test('Given a app route is called, should calculate path correctly', () => {
// Arrange
// Act
return agent.get('/resource-3/id-thing-3').then(() => {
return agent.get('/metrics').then(result => {
expect(result.statusCode).toBe(200)
expect(result.headers['content-type']).toBe(
'text/plain; charset=utf-8'
)
expect(result.text).toContain(
'http_requests_total{method="GET",path="/resource-3/:id",status="200"} 1'
)
})
})
})
})
})