Skip to content
Snippets Groups Projects
Commit 9d2bc492 authored by anne.matthes's avatar anne.matthes
Browse files

Improve health checks to prevent manifest service from crashing

parent 19246740
No related branches found
No related tags found
No related merge requests found
......@@ -2,80 +2,5 @@
// Note: actual env vars supersede .env file and .env file supersedes .env.defaults file
require('dotenv-defaults').config()
// Ignore paths for logging, metrics and docs
const ignorePaths = ['/ready', '/healthy']
// Fast, minimalist web framework for node.
const express = require('express')
// Helmet helps you secure your Express app by setting various HTTP headers
const helmet = require('helmet')
// Very low overhead Node.js logger. Logs in json use pino-pretty for dev.
const logger = require('pino')()
// Fastest HTTP logger for Node.js in town
const httpLogger = require('pino-http')({ logger, autoLogging: { ignorePaths } })
// Readiness and liveness checks middleware
const health = require('@cloudnative/health-connect')
const healthCheck = new health.HealthChecker()
// Prometheus middleware for standard api metrics
const apiMetrics = require('prometheus-api-metrics')
// Swagger UI for api-docs
const swaggerUi = require('swagger-ui-express')
const yaml = require('js-yaml')
const fs = require('fs')
const swaggerDocument = yaml.load(fs.readFileSync('./swagger.yaml', 'utf8'))
// The app returned by express() is in fact a JavaScript Function, designed to be passed to Node’s HTTP servers as a callback to handle requests.
const app = express()
const fetch = require('node-fetch')
// Application-level middleware
app.use(httpLogger)
app.use(helmet())
app.use('/healthy', health.LivenessEndpoint(healthCheck))
app.use('/ready', health.ReadinessEndpoint(healthCheck))
app.use(apiMetrics({ excludeRoutes: ignorePaths }))
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument))
app.use('/swagger.json', (req, res) => res.json(swaggerDocument))
const urls = yaml.load(fs.readFileSync('./config/manifests/urls.yaml', 'utf8')).manifests
let manifestCache = []
let lastCached
const getManifests = async () => {
if (+new Date() < lastCached + 30000) return
const results = urls.map(url => fetch(url).then(result => {
if (!result.ok) throw new Error(`Failed to load manifest for url ${result.url} (Status: ${result.status}: ${result.statusText})`)
return result.json().catch(err => { throw new Error(`Failed to load manifest for url ${result.url}: ${err}`) })
}))
manifestCache = (await Promise.all(results)).flat()
lastCached = +new Date()
}
getManifests()
app.get('/api/manifest.json', async (req, res, next) => {
try {
getManifests()
res.json(manifestCache || [])
} catch (err) {
next(err)
}
})
app.use(function (err, req, res, next) {
logger.error(err)
res.status(500).end()
})
// Binds and listens for connections on the specified host and port
app.listen(process.env.PORT, () => {
logger.info(`manifest-service listening on port ${process.env.PORT}`)
})
const createApp = require('./src/server')
createApp()
// Ignore paths for logging, metrics and docs
const ignorePaths = ['/ready', '/healthy']
// Fast, minimalist web framework for node.
const express = require('express')
// Helmet helps you secure your Express app by setting various HTTP headers
const helmet = require('helmet')
// Very low overhead Node.js logger. Logs in json use pino-pretty for dev.
const logger = require('pino')()
// Fastest HTTP logger for Node.js in town
const httpLogger = require('pino-http')({ logger, autoLogging: { ignorePaths } })
// Readiness and liveness checks middleware
const health = require('@cloudnative/health-connect')
// Prometheus middleware for standard api metrics
const apiMetrics = require('prometheus-api-metrics')
// Swagger UI for api-docs
const swaggerUi = require('swagger-ui-express')
const yaml = require('js-yaml')
const fs = require('fs')
const fetch = require('node-fetch')
const swaggerDocument = yaml.load(fs.readFileSync('./swagger.yaml', 'utf8'))
// The app returned by express() is in fact a JavaScript Function, designed to be passed to Node’s HTTP servers as a callback to handle requests.
module.exports = () => {
const app = express()
const healthCheck = new health.HealthChecker()
// Application-level middleware
app.use(httpLogger)
app.use(helmet())
app.use('/healthy', health.LivenessEndpoint(healthCheck))
app.use('/ready', health.ReadinessEndpoint(healthCheck))
app.use(apiMetrics({ excludeRoutes: ignorePaths }))
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument))
app.use('/swagger.json', (req, res) => res.json(swaggerDocument))
const isReady = async () => {
await fetchManifest()
if (manifestCache.length === 0) throw new Error('No manifests found.')
}
const readinessCheck = new health.ReadinessCheck('readinessCheck', isReady)
healthCheck.registerReadinessCheck(readinessCheck)
const livenessCheck = new health.LivenessCheck('livenessCheck', isReady)
healthCheck.registerLivenessCheck(livenessCheck)
const urls = yaml.load(fs.readFileSync('./config/manifests/urls.yaml', 'utf8')).manifests
let manifestCache = []
let lastCached
const fetchManifest = async () => {
if (+new Date() < lastCached + 30000) return
const results = urls.map(url => fetch(url).then(result => {
if (!result.ok) throw new Error(`Failed to load manifest for url ${result.url} (Status: ${result.status}: ${result.statusText})`)
return result.json().catch(err => { throw new Error(`Failed to load manifest for url ${result.url}: ${err}`) })
}))
manifestCache = (await Promise.all(results)).flat()
lastCached = +new Date()
}
app.get('/api/manifest.json', async (req, res, next) => {
try {
await fetchManifest()
res.json(manifestCache || [])
} catch (err) {
next(err)
}
})
app.use(function (err, req, res, next) {
logger.error(err)
res.status(500).end()
})
// Binds and listens for connections on the specified host and port
app.listen(process.env.PORT, () => {
logger.info(`manifest-service listening on port ${process.env.PORT}`)
})
return app
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment