Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
jgillick authored Jul 13, 2023
2 parents 76fec0d + b88608b commit 60265ad
Show file tree
Hide file tree
Showing 6 changed files with 301 additions and 44 deletions.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,23 @@ Once you have made the changes, open a Pull Request and explain the issue your c

For contribution details on how to add custom notifications [see the New Notifications guide here](https://monika.hyperjump.tech/guides/new-notifications).

### How to Test Probe Locally

If you need to test a probe locally, there are predefined services in /dev/docker-compose.yaml. You are **encouraged** to add other services that can be probed by Monika. Run `cd dev && docker compose up` to run those services.

#### Available Services

##### PostgreSQL

Use the following Monika config to probe the service.

```yaml
probes:
- id: postgres
postgres:
- uri: postgres://postgres_user:postgres_password@localhost:5432/postgres_db
```
## Development References
The tools and frameworks we used in this project are listed below:
Expand Down
11 changes: 11 additions & 0 deletions dev/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
services:
postgres:
image: postgres:15-alpine
container_name: monika-postgre
ports:
- 5432:5432
environment:
POSTGRES_PASSWORD: postgres_password
POSTGRES_USER: postgres_user
POSTGRES_DB: postgres_db
restart: unless-stopped
6 changes: 5 additions & 1 deletion src/components/config/validation/validator/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,12 @@ const checkProbeRequestProperties = (
}

export const validateRequests = (
requests: RequestConfig[]
requests?: RequestConfig[]
): string | undefined => {
if (requests === undefined) {
return
}

for (const req of requests) {
if (req.timeout <= 0) {
return `The timeout in the request with id "${req.id}" should be greater than 0.`
Expand Down
2 changes: 1 addition & 1 deletion src/components/notification/alert-message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export async function getMessageForAlert({
const expectedMessage = getExpectedMessage(alert, response, isRecovery)
const bodyString = `Message: ${recoveryMessage}${expectedMessage}
URL: ${meta.url}
${meta.url ? `URL: ${meta.url}` : `Probe ID: ${probeID}`}
Time: ${meta.time}
Expand Down
188 changes: 188 additions & 0 deletions src/looper/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
/**********************************************************************************
* MIT License *
* *
* Copyright (c) 2021 Hyperjump Technology *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy *
* of this software and associated documentation files (the "Software"), to deal *
* in the Software without restriction, including without limitation the rights *
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell *
* copies of the Software, and to permit persons to whom the Software is *
* furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in all *
* copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE *
* SOFTWARE. *
**********************************************************************************/

import { expect } from 'chai'
import { DEFAULT_THRESHOLD, sanitizeProbe } from '.'
import type { Probe } from '../interfaces/probe'

describe('Looper', () => {
describe('sanitizeProbe', () => {
it('should change probe alert query to alert assertion', () => {
// arrange
const probe = {
id: 'Example',
alerts: [{ query: 'response.status < 200' }],
} as Probe

// act
const result = sanitizeProbe(false, probe)

// assert
expect(result.alerts[0].assertion).eq(probe.alerts[0].query)
})

it('should set default request method', () => {
// arrange
const probe = {
id: 'Example',
requests: [{ url: 'https://example.com' }],
} as Probe

// act
const result = sanitizeProbe(false, probe)

// assert
expect(result.requests[0].method).eq('GET')
})

it('should change request alert query to alert assertion', () => {
// arrange
const probe = {
id: 'Example',
requests: [
{ method: 'GET', alerts: [{ query: 'response.status < 200' }] },
{ alerts: [{ query: 'response.status < 200' }] },
],
} as Probe

// act
const result = sanitizeProbe(false, probe)

// assert
expect(result.requests[0]?.alerts?.[0].assertion).eq(
probe.requests[0].alerts?.[0].query
)
expect(result.requests[1]?.alerts?.[0].assertion).eq(
probe.requests[1].alerts?.[0].query
)
})

it('should add probe name', () => {
// arrange
const probe = {
id: 'Example',
requests: [
{ method: 'GET', alerts: [{ query: 'response.status < 200' }] },
],
} as Probe

// act
const result = sanitizeProbe(false, probe)

// assert
expect(result.name).eq('monika_Example')
})

it('should set default incidentThreshold', () => {
// arrange
const probe = {
id: 'Example',
requests: [
{ method: 'GET', alerts: [{ query: 'response.status < 200' }] },
],
} as Probe

// act
const result = sanitizeProbe(false, probe)

// assert
expect(result.incidentThreshold).eq(DEFAULT_THRESHOLD)
})

it('should set default recoveryThreshold', () => {
// arrange
const probe = {
id: 'Example',
requests: [
{ method: 'GET', alerts: [{ query: 'response.status < 200' }] },
],
} as Probe

// act
const result = sanitizeProbe(false, probe)

// assert
expect(result.recoveryThreshold).eq(DEFAULT_THRESHOLD)
})

it('should set default alerts for HTTP probe', () => {
// arrange
const probe = {
id: 'Example',
requests: [
{ method: 'GET', alerts: [{ query: 'response.status < 200' }] },
],
} as Probe

// act
const result = sanitizeProbe(false, probe)

// assert
expect(result.alerts).deep.eq([
{
assertion: 'response.status < 200 or response.status > 299',
message: 'HTTP Status is {{ response.status }}, expecting 200',
},
{
assertion: 'response.time > 2000',
message:
'Response time is {{ response.time }}ms, expecting less than 2000ms',
},
])
})

it('should set default alerts for non HTTP probe', () => {
// arrange
const probe = {
id: 'Example',
requests: [],
} as unknown as Probe

// act
const result = sanitizeProbe(false, probe)

// assert
expect(result.alerts).deep.eq([
{
assertion: 'response.status < 200 or response.status > 299',
message: 'Probe is not accesible',
},
])
})

it('should remove alerts on Symon mode', () => {
// arrange
const probe = {
id: 'Example',
requests: [{}],
} as Probe

// act
const result = sanitizeProbe(true, probe)

// assert
expect(result.alerts).deep.eq([])
})
})
})
Loading

0 comments on commit 60265ad

Please sign in to comment.