generated from ministryofjustice/hmpps-template-typescript
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* HAAR-335: ⬆️ upgrade dependencies * HAAR-335: Resolving type conflicts Co-authored-by: Jon Brighton <[email protected]>
- Loading branch information
1 parent
569f570
commit 4193a88
Showing
12 changed files
with
14,996 additions
and
864 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { createClient } from 'redis' | ||
|
||
import config from '../config' | ||
|
||
export type RedisClient = ReturnType<typeof createClient> | ||
|
||
const url = | ||
config.redis.tls_enabled === 'true' | ||
? `rediss://${config.redis.host}:${config.redis.port}` | ||
: `redis://${config.redis.host}:${config.redis.port}` | ||
|
||
export const createRedisClient = (legacyMode = false): RedisClient => { | ||
return createClient({ | ||
url, | ||
password: config.redis.password, | ||
legacyMode, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import superagent from 'superagent' | ||
import { | ||
restClientMetricsMiddleware, | ||
normalizePath, | ||
requestHistogram, | ||
timeoutCounter, | ||
} from './restClientMetricsMiddleware' | ||
|
||
describe('restClientMetricsMiddleware', () => { | ||
afterEach(() => { | ||
jest.clearAllMocks() | ||
}) | ||
|
||
describe('normalizePath', () => { | ||
it('removes the query params from the URL path', () => { | ||
const result = normalizePath('https://httpbin.org/?foo=bar') | ||
expect(result).toBe('/') | ||
}) | ||
|
||
it('normalises recall ids', () => { | ||
const result = normalizePath( | ||
'https://manage-recalls-dev.hmpps.service.justice.gov.uk/recalls/15e4cccf-cc7b-4946-aa22-a82086735ec2/view-recall' | ||
) | ||
expect(result).toBe('/recalls/#val/view-recall') | ||
}) | ||
|
||
it('normalises nomis ids', () => { | ||
const result = normalizePath('https://manage-recalls-dev.hmpps.service.justice.gov.uk/prisoner/A7826DY') | ||
expect(result).toBe('/prisoner/#val') | ||
}) | ||
}) | ||
|
||
describe('request timers', () => { | ||
it('times the whole request', async () => { | ||
const requestHistogramLabelsSpy = jest.spyOn(requestHistogram, 'labels').mockReturnValue(requestHistogram) | ||
const requestHistogramStartSpy = jest.spyOn(requestHistogram, 'observe') | ||
|
||
let code: number | ||
|
||
await superagent | ||
.get('https://httpbin.org/') | ||
.use(restClientMetricsMiddleware) | ||
.set('accept', 'json') | ||
.then(res => { | ||
code = res.statusCode | ||
}) | ||
|
||
expect(code).toBe(200) | ||
expect(requestHistogramLabelsSpy).toHaveBeenCalledTimes(1) | ||
expect(requestHistogramLabelsSpy).toHaveBeenCalledWith('httpbin.org', 'GET', '/', '200') | ||
expect(requestHistogramStartSpy).toHaveBeenCalledTimes(1) | ||
}) | ||
}) | ||
|
||
describe('timeout errors', () => { | ||
// FIXME: For some reason this test just doesn't work, but the code really does count the timeouts... | ||
it.skip('increment the timeoutCounter', async () => { | ||
const timeoutCounterLabelsSpy = jest.spyOn(timeoutCounter, 'labels').mockReturnValue(timeoutCounter) | ||
const timeoutCounterIncSpy = jest.spyOn(timeoutCounter, 'inc') | ||
|
||
await superagent | ||
.get('https://httpbin.org/delay/5') // implements a delay of 5 seconds | ||
.use(restClientMetricsMiddleware) | ||
.set('accept', 'json') | ||
.timeout(100) // Wait 100ms for the server to start sending | ||
.end() | ||
|
||
expect(timeoutCounterLabelsSpy).toHaveBeenCalledWith('httpbin.org', 'GET', '/delay/5') | ||
expect(timeoutCounterIncSpy).toHaveBeenCalledTimes(1) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import { Socket } from 'net' | ||
import promClient from 'prom-client' | ||
import { Response, SuperAgentRequest } from 'superagent' | ||
import UrlValueParser from 'url-value-parser' | ||
|
||
const requestHistogram = new promClient.Histogram({ | ||
name: 'http_client_requests_seconds', | ||
help: 'Timings and counts of http client requests', | ||
buckets: [0.5, 0.75, 0.95, 0.99, 1], | ||
labelNames: ['clientName', 'method', 'uri', 'status'], | ||
}) | ||
|
||
const timeoutCounter = new promClient.Counter({ | ||
name: 'http_client_requests_timeout_total', | ||
help: 'Count of http client request timeouts', | ||
labelNames: ['clientName', 'method', 'uri'], | ||
}) | ||
|
||
function restClientMetricsMiddleware(agent: SuperAgentRequest) { | ||
agent.on('request', ({ req }) => { | ||
const { hostname } = new URL(agent.url) | ||
const normalizedPath = normalizePath(agent.url) | ||
const startTime = Date.now() | ||
|
||
req.on('socket', (socket: Socket) => { | ||
socket.on('timeout', () => { | ||
timeoutCounter.labels(hostname, req.method, normalizedPath).inc() | ||
}) | ||
}) | ||
|
||
req.on('response', (res: Response, err: Error) => { | ||
res.on('end', () => { | ||
const responseTime = Date.now() - startTime | ||
requestHistogram.labels(hostname, req.method, normalizedPath, String(res.statusCode)).observe(responseTime) | ||
}) | ||
}) | ||
}) | ||
|
||
return agent | ||
} | ||
|
||
function normalizePath(url: string) { | ||
const { pathname } = new URL(url) | ||
const urlPathReplacement = '#val' | ||
const urlValueParser = new UrlValueParser({ extraMasks: [/^[A-Z|0-9]+/] }) | ||
return urlValueParser.replacePathValues(pathname, urlPathReplacement) | ||
} | ||
|
||
export { restClientMetricsMiddleware, normalizePath, requestHistogram, timeoutCounter } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.