Repository: hyperjumptech/monika
Pull request #863 (2022-08-25 04:19:19)

Refactor the probes
# Monika Pull Request (PR)  

## Before PR
1. Probes are mixed between drivers and loggers
2. Difficult to add new probes

## After PR
1. Should be easier to add new probes
2. Code cleaned up
3. Better separation of responsibilities 

## How did you implement / how did you fix it  
1. Refactored the interface between driver and dispatcher
2. Detach drivers from logger and decoding of errors/status codes

## How to test  
1. Run `npm run test` should all pass
2. Use the following test config yaml for local test
```yaml
probes:
  # http checks
  - id: http-probe-01
    name: 'test status 400'
    interval: 5

    requests:
      - url: http://httpbin.org/status/400
        method: GET
        timeout: 5000
        saveBody: false
        headers:
          Content-Type: application/json; charset=utf-8
    alerts:
      - query: response.status != 400
        message: Http Response status code is not 200!
      - query: response.time > 10000
        message: Yo too slow!
    incidentThreshold: 2
    recoveryThreshold: 2

  - id: http-probe-02
    name: 'test good github.com'
    interval: 10

    requests:
      - url: https://github.com
    alerts:
      - query: response.status != 200
        message: Http Response status code is not 200!
      - query: response.time > 10000
        message: Yo too slow!
    incidentThreshold: 2
    recoveryThreshold: 2

# tcp check
  - id: tcp-check-01
    name: bad-tcp-ip
    alerts:
      - query: response.status == 500
        message: response status message
    incidentThreshold: 1
    recoveryThreshold: 1
    socket:
      host: 1.2.3.4
      port: 3333
      data: Hello from Monika

  - id: tcp-check-02
    name: checking ssh tcp
    alerts:
      - query: response.status == 500
        message: response status message
    incidentThreshold: 1
    recoveryThreshold: 1

    socket:
      host: 1.2.3.4 # please user your valid ssh ip
      port: 22
      data: hello

# icmp check
  - id: ping-01
    name: bad-ping-check
    description: check-ping-result
    interval: 10
    incidentThreshold: 3
    recoveryThreshold: 3
    requests:
      - method: GET
        url: cloudflare.net
        timeout: 5000
        saveBody: false
        ping: true

    alerts:
      - query: response.status != 200
        message: no ping

  - id: ping-02
    name: good-ping-check
    description: check-ping-nonexistent
    interval: 10
    incidentThreshold: 3
    recoveryThreshold: 3
    requests:
      - method: GET
        url: hyperjump.co.net
        timeout: 5000
        saveBody: false
        ping: true

    alerts:
      - query: response.status != 200
        message: no ping

notifications:
  - id: unique-id-desktop
    type: desktop
```
3. Run monika with the above config: `bin/bin-run -c monika.yaml -s -1`

## Screenshot



codecov[bot]: # [Codecov](https://codecov.io/gh/hyperjumptech/monika/pull/863?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperjumptech) Report
> Merging [#863](https://codecov.io/gh/hyperjumptech/monika/pull/863?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperjumptech) (8a1a4da) into [main](https://codecov.io/gh/hyperjumptech/monika/commit/f0607431176b9ac67f28cc00886610ed2c9b73fe?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperjumptech) (f060743) will **decrease** coverage by `0.05%`.
> The diff coverage is `23.52%`.

```diff
@@            Coverage Diff             @@
##             main     #863      +/-   ##
==========================================
- Coverage   49.09%   49.03%   -0.06%     
==========================================
  Files          69       70       +1     
  Lines        2365     2376      +11     
  Branches      466      467       +1     
==========================================
+ Hits         1161     1165       +4     
- Misses       1025     1032       +7     
  Partials      179      179              
```


| [Impacted Files](https://codecov.io/gh/hyperjumptech/monika/pull/863?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperjumptech) | Coverage Δ | |
|---|---|---|
| [src/components/config/validate.ts](https://codecov.io/gh/hyperjumptech/monika/pull/863/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperjumptech#diff-c3JjL2NvbXBvbmVudHMvY29uZmlnL3ZhbGlkYXRlLnRz) | `62.57% <ø> (ø)` | |
| [src/components/logger/request-log.ts](https://codecov.io/gh/hyperjumptech/monika/pull/863/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperjumptech#diff-c3JjL2NvbXBvbmVudHMvbG9nZ2VyL3JlcXVlc3QtbG9nLnRz) | `6.38% <0.00%> (+0.38%)` | :arrow_up: |
| [src/plugins/validate-response/checkers/index.ts](https://codecov.io/gh/hyperjumptech/monika/pull/863/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperjumptech#diff-c3JjL3BsdWdpbnMvdmFsaWRhdGUtcmVzcG9uc2UvY2hlY2tlcnMvaW5kZXgudHM=) | `64.28% <ø> (+8.03%)` | :arrow_up: |
| [...ins/validate-response/checkers/query-expression.ts](https://codecov.io/gh/hyperjumptech/monika/pull/863/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperjumptech#diff-c3JjL3BsdWdpbnMvdmFsaWRhdGUtcmVzcG9uc2UvY2hlY2tlcnMvcXVlcnktZXhwcmVzc2lvbi50cw==) | `100.00% <ø> (ø)` | |
| [src/components/icmp-request/index.ts](https://codecov.io/gh/hyperjumptech/monika/pull/863/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperjumptech#diff-c3JjL2NvbXBvbmVudHMvaWNtcC1yZXF1ZXN0L2luZGV4LnRz) | `13.04% <13.04%> (ø)` | |
| [src/components/config/index.ts](https://codecov.io/gh/hyperjumptech/monika/pull/863/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperjumptech#diff-c3JjL2NvbXBvbmVudHMvY29uZmlnL2luZGV4LnRz) | `64.53% <50.00%> (-0.21%)` | :arrow_down: |
| [src/components/probe/index.ts](https://codecov.io/gh/hyperjumptech/monika/pull/863/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperjumptech#diff-c3JjL2NvbXBvbmVudHMvcHJvYmUvaW5kZXgudHM=) | `14.28% <50.00%> (ø)` | |
| [src/components/probe/probing.ts](https://codecov.io/gh/hyperjumptech/monika/pull/863/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperjumptech#diff-c3JjL2NvbXBvbmVudHMvcHJvYmUvcHJvYmluZy50cw==) | `73.25% <50.00%> (+6.94%)` | :arrow_up: |
| [src/components/tcp-request/index.ts](https://codecov.io/gh/hyperjumptech/monika/pull/863/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperjumptech#diff-c3JjL2NvbXBvbmVudHMvdGNwLXJlcXVlc3QvaW5kZXgudHM=) | `10.34% <100.00%> (ø)` | |
| [src/jobs/tls-check.ts](https://codecov.io/gh/hyperjumptech/monika/pull/863/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperjumptech#diff-c3JjL2pvYnMvdGxzLWNoZWNrLnRz) | `25.92% <100.00%> (ø)` | |

:mega: We’re building smart automated test selection to slash your CI/CD build times. [Learn more](https://about.codecov.io/iterative-testing/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hyperjumptech)


Patch:
diff --git a/src/components/config/validate.ts b/src/components/config/validate.ts
index cb07575d..7a3ea479 100644
--- a/src/components/config/validate.ts
+++ b/src/components/config/validate.ts
@@ -379,6 +379,7 @@ export const validateConfig = (configuration: Config): Validation => {
         const subject = ''
 
         if (alert === 'status-not-2xx') {
+          // This is temporary, TODO: remove support later
           query = 'response.status < 200 or response.status > 299'
           message = 'HTTP Status is {{ response.status }}, expecting 200'
         } else if (alert.startsWith('response-time-greater-than-')) {
diff --git a/src/components/icmp-request/index.ts b/src/components/icmp-request/index.ts
new file mode 100644
index 00000000..2ab648a0
--- /dev/null
+++ b/src/components/icmp-request/index.ts
@@ -0,0 +1,97 @@
+/**********************************************************************************
+ * MIT License                                                                    *
+ *                                                                                *
+ * Copyright (c) 2022 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 { sendPing } from '../../utils/ping'
+import { ProbeRequestResponse } from '../../interfaces/request'
+
+type icmpParams = {
+  host: string // target to ping
+}
+
+// icmp specific responses from the library
+type icmpResponse = {
+  host?: string // host name
+  numericHost?: string // resolved host ip
+  isAlive?: boolean // is the host alive?
+  min?: string // minimum round trip time ms
+  max?: string // max round trip time in ms
+  average?: number // average time in ms
+  packetLoss?: number // packet loss%
+  output?: string // driver output
+}
+
+export async function icmpRequest(
+  params: icmpParams
+): Promise<ProbeRequestResponse> {
+  const icmpResp: icmpResponse = {
+    isAlive: false, // initialize to off and packet loss
+    packetLoss: 100,
+    average: 0,
+  }
+
+  const baseResponse: ProbeRequestResponse = {
+    data: '',
+    body: '',
+    status: 0,
+    headers: '',
+    responseTime: 0,
+  }
+
+  try {
+    const resp = await sendPing(params.host)
+
+    icmpResp.host = resp.inputHost
+    icmpResp.average = resp.avg === 'unknown' ? 0 : resp.avg // map response time to the average ping time
+    icmpResp.isAlive = resp.alive
+    icmpResp.packetLoss = resp.packetLoss
+    icmpResp.numericHost = resp.numeric_host
+    icmpResp.output = resp.output
+
+    return processICMPRequstResult(icmpResp)
+  } catch (error: any) {
+    console.error('icmp got errror:', error)
+    baseResponse.data = error // map error to data
+  }
+
+  return baseResponse
+}
+
+// translates icmp specific response to base monika response
+export function processICMPRequstResult(
+  params: icmpResponse
+): ProbeRequestResponse {
+  // build log message
+  const aliveMsg = params.isAlive ? 'alive' : 'dead'
+  const packetLossMsg = params.isAlive ? params.packetLoss : '100%'
+  const msg = `PING:${aliveMsg} host:${params.host} avg:${params.average}ms packetLoss:${packetLossMsg}`
+
+  return {
+    requestType: 'ICMP',
+    data: params.output, // map output to response data
+    status: params.isAlive ? 200 : 0, // TO IMPROVE: this is a monkey patch to map ping return status to http status. Should not need it!
+    body: msg,
+    headers: {},
+    responseTime: params.average || 0,
+  }
+}
diff --git a/src/components/logger/request-log.ts b/src/components/logger/request-log.ts
index ed6bb0c3..6d364a8a 100644
--- a/src/components/logger/request-log.ts
+++ b/src/components/logger/request-log.ts
@@ -101,21 +101,10 @@ export class RequestLog {
     // generate probe result messages
     let probeMsg = ''
 
-    probeMsg = `${this.iteration} id:${this.probe.id} ${
-      this.response?.status || '-'
-    } ${this.request.method} ${this.request.url} ${
-      this.response?.responseTime || '-'
-    }ms`
-    // generate logs from ping request or probe request
+    // TODO: make this more generic not probe dependent
     probeMsg = this.request?.ping
-      ? `${this.iteration} id:${this.probe.id} PING:${
-          this.response?.alive ? 'alive' : 'dead'
-        } ${this.request?.url} ${
-          this.response?.alive ? this.response?.responseTime : '-'
-        }ms packetLoss:${
-          this.response?.alive ? this.response?.packetLoss : '-'
-        }%`
-      : `${this.iteration} id:${this.probe.id} ${
+      ? `${this.iteration} id:${this.probe.id} ${this.response?.body}`
+      : `${this.iteration} id:${this.probe.id} status:${
           this.response?.status || '-'
         } ${this.request?.method} ${this.request?.url} ${
           this.response?.responseTime || '-'
diff --git a/src/components/probe/index.ts b/src/components/probe/index.ts
index a6aa5528..c2fd96f6 100644
--- a/src/components/probe/index.ts
+++ b/src/components/probe/index.ts
@@ -35,9 +35,9 @@ import { log } from '../../utils/pino'
 import { RequestLog } from '../logger'
 import { sendAlerts } from '../notification'
 import { processThresholds } from '../notification/process-server-status'
-import { probing } from './probing'
+import { probingHTTP } from './probing'
 import { logResponseTime } from '../logger/response-time-log'
-import { check } from '../tcp-request'
+import { tcpRequest } from '../tcp-request'
 import { getContext } from '../../context'
 
 // TODO: move this to interface file?
@@ -153,31 +153,63 @@ export async function doProbe({
     const { id, socket } = probe
     const { host, port, data } = socket
     const url = `${host}:${port}`
-    const tcpRequestID = `tcp-${id}`
-    const { duration, status } = await check({ host, port, data })
+
+    const probeRes = await tcpRequest({ host, port, data })
+
     const timeNow = new Date().toISOString()
-    const logMessage = `${timeNow} ${checkOrder} id:${id} [TCP] ${url} ${duration}ms`
-    const isAlertTriggered = status === 'DOWN'
+    const logMessage = `${timeNow} ${checkOrder} id:${id} tcp:${url} ${probeRes.responseTime}ms msg:${probeRes.body}`
+
+    const isAlertTriggered = probeRes.status !== 200
 
     isAlertTriggered ? log.warn(logMessage) : log.info(logMessage)
-    logResponseTime(duration)
 
     // let TCPrequestIndex = 0 // are there multiple tcp requests?
     // TCPrequestIndex < probe?.requests?.length;  // multiple tcp request, for later support
     // TCPrequestIndex++                           // for later supported
     const TCPrequestIndex = 0
 
-    processTCPRequestResult({
-      probe: probe,
-      tcpRequestID,
-      responseTime: duration,
-      isAlertTriggered,
-      notifications: notifications,
+    const validatedResponse = validateResponse(
+      probe.socket?.alerts || [
+        {
+          query: 'response.status < 200 or response.status > 299',
+          message: 'TCP server cannot be accessed',
+        },
+      ],
+      probeRes
+    )
+    const requestLog = new RequestLog(probe, 0, 0)
+
+    requestLog.addAlerts(
+      validatedResponse
+        .filter((item) => item.isAlertTriggered)
+        .map((item) => item.alert)
+    )
+    const statuses = processThresholds({
+      probe,
       requestIndex: TCPrequestIndex,
-      verboseLogs: flags.verboseLogs,
-    }).catch((error) => log.error(error.message))
+      validatedResponse,
+    })
+
+    requestLog.setResponse(probeRes)
+    checkThresholdsAndSendAlert(
+      {
+        probe,
+        statuses,
+        notifications,
+        requestIndex: TCPrequestIndex,
+        validatedResponseStatuses: validatedResponse,
+      },
+      requestLog
+    ).catch((error) => {
+      requestLog.addError(error.message)
+    })
+
+    if (flags.verboseLogs || requestLog.hasIncidentOrRecovery) {
+      requestLog.saveToDatabase().catch((error) => log.error(error.message))
+    }
   }
 
+  // sending multiple http-type requests
   for (
     let requestIndex = 0;
     requestIndex < probe?.requests?.length;
@@ -189,7 +221,7 @@ export async function doProbe({
     try {
       // intentionally wait for a request to finish before processing next request in loop
       // eslint-disable-next-line no-await-in-loop
-      const probeRes: ProbeRequestResponse = await probing({
+      const probeRes: ProbeRequestResponse = await probingHTTP({
         requestConfig: request,
         responses,
       })
@@ -207,14 +239,13 @@ export async function doProbe({
 
       requestLog.setResponse(probeRes)
 
-      // store request error log
+      // TODO: MOVE THIS DECODING TO THE PROBE/DRIVERS
       if ([0, 1, 2, 3, 4, 599].includes(probeRes.status)) {
         const errorMessageMap: Record<number, string> = {
           0: 'URI not found', // axios error
           1: 'Connection reset', // axios error
           2: 'Connection refused', // axios error
           3: 'Unknown error', // axios error
-          4: 'Ping timed out', // ping error
           599: 'Request Timed out', // axios error
         }
 
@@ -223,7 +254,7 @@ export async function doProbe({
 
       // combine global probe alerts with all individual request alerts
       const probeAlerts = probe.alerts ?? []
-      const combinedAlerts = probeAlerts.concat(...(request.alerts || []))
+      const combinedAlerts = [...probeAlerts, ...(request.alerts || [])]
 
       // Responses have been processed and validated
       const validatedResponse = validateResponse(combinedAlerts, probeRes)
@@ -282,70 +313,3 @@ export async function doProbe({
     }
   }
 }
-
-type ProcessTCPRequestResult = {
-  probe: Probe
-  tcpRequestID: string
-  responseTime: number
-  isAlertTriggered: boolean
-  notifications: Array<Notification>
-  requestIndex: number // to support multiple tcp requests/chaining
-  verboseLogs: boolean
-}
-
-async function processTCPRequestResult({
-  probe,
-  responseTime,
-  isAlertTriggered,
-  notifications,
-  requestIndex,
-  verboseLogs,
-}: ProcessTCPRequestResult) {
-  const probeRes: ProbeRequestResponse = {
-    requestType: 'tcp',
-    data: '',
-    body: '',
-    status: isAlertTriggered ? 0 : 200, // set to 0 if down, and 200 if ok
-    headers: {},
-    responseTime,
-  }
-  const validatedResponse = validateResponse(
-    probe.socket?.alerts || [
-      {
-        query: 'response.status < 200 or response.status > 299',
-        message: 'TCP server cannot be accessed',
-      },
-    ],
-    probeRes
-  )
-  const requestLog = new RequestLog(probe, 0, 0)
-
-  requestLog.addAlerts(
-    validatedResponse
-      .filter((item) => item.isAlertTriggered)
-      .map((item) => item.alert)
-  )
-  const statuses = processThresholds({
-    probe,
-    requestIndex,
-    validatedResponse,
-  })
-
-  requestLog.setResponse(probeRes)
-  checkThresholdsAndSendAlert(
-    {
-      probe,
-      statuses,
-      notifications,
-      requestIndex,
-      validatedResponseStatuses: validatedResponse,
-    },
-    requestLog
-  ).catch((error) => {
-    requestLog.addError(error.message)
-  })
-
-  if (verboseLogs || requestLog.hasIncidentOrRecovery) {
-    requestLog.saveToDatabase().catch((error) => log.error(error.message))
-  }
-}
diff --git a/src/components/probe/probing.ts b/src/components/probe/probing.ts
index 35b95368..763d6d2b 100644
--- a/src/components/probe/probing.ts
+++ b/src/components/probe/probing.ts
@@ -28,16 +28,17 @@ import FormData from 'form-data'
 import YAML from 'yaml'
 import { ProbeRequestResponse, RequestConfig } from '../../interfaces/request'
 import * as qs from 'querystring'
-import { sendPing, PING_TIMEDOUT } from '../../utils/ping'
+
 import http from 'http'
 import https from 'https'
 import { getContext } from '../../context'
+import { icmpRequest } from '../icmp-request'
 import registerFakes from '../../utils/fakes'
 
 // Register Handlebars helpers
 registerFakes(Handlebars)
 
-// Keep the agenst alive to reduce the overhead of DNS queries and creating TCP connection.
+// Keep the agents alive to reduce the overhead of DNS queries and creating TCP connection.
 // More information here: https://rakshanshetty.in/nodejs-http-keep-alive/
 const httpAgent = new http.Agent({ keepAlive: true })
 const httpsAgent = new https.Agent({ keepAlive: true })
@@ -55,7 +56,7 @@ type probingParams = {
  * @param {obj} parameter as input object
  * @returns ProbeRequestResponse, response to the probe request
  */
-export async function probing({
+export async function probingHTTP({
   requestConfig,
   responses,
 }: probingParams): Promise<ProbeRequestResponse> {
@@ -150,30 +151,7 @@ export async function probing({
   try {
     // is this a request for ping?
     if (newReq.ping === true) {
-      const pingResp = await sendPing(renderedURL)
-
-      const requestType = 'ICMP'
-
-      const responseTime = pingResp.avg // map response time to the average ping time
-      const alive = pingResp.alive
-      const data = pingResp.output
-      const headers = {}
-      const packetLoss = pingResp.packetLoss
-      const numericHost = pingResp.numericHost
-
-      const status = alive ? 200 : PING_TIMEDOUT
-
-      return {
-        requestType,
-        data,
-        body: data,
-        status,
-        headers,
-        responseTime,
-        alive,
-        numericHost,
-        packetLoss,
-      }
+      return icmpRequest({ host: renderedURL })
     }
 
     // Do the request using compiled URL and compiled headers (if exists)
diff --git a/src/components/tcp-request/index.ts b/src/components/tcp-request/index.ts
index 78337836..a28ba315 100644
--- a/src/components/tcp-request/index.ts
+++ b/src/components/tcp-request/index.ts
@@ -24,6 +24,7 @@
 
 import net from 'net'
 import { differenceInMilliseconds } from 'date-fns'
+import { ProbeRequestResponse } from '../../interfaces/request'
 
 type TCPRequest = {
   host: string
@@ -32,19 +33,40 @@ type TCPRequest = {
   timeout?: number
 }
 
-type Result = {
+type TCPResult = {
   duration: number
   status: 'UP' | 'DOWN'
   message: string
   responseData: Buffer | null
 }
 
-export async function check(tcpRequest: TCPRequest): Promise<Result> {
+// tcpRequest sends out the tcp request and returns a monika standard request response
+export async function tcpRequest(
+  param: TCPRequest
+): Promise<ProbeRequestResponse<any>> {
+  const { host, port, data, timeout } = param
+
+  let baseResponse: ProbeRequestResponse = {
+    requestType: 'tcp',
+    data: '',
+    body: '',
+    status: 0,
+    headers: '',
+    responseTime: 0,
+  }
+
+  const tcpResp = await tcpCheck({ host, port, data, timeout })
+  baseResponse = processTCPRequestResult(tcpResp)
+
+  return baseResponse
+}
+
+async function tcpCheck(tcpRequest: TCPRequest): Promise<TCPResult> {
   const { host, port, data, timeout } = tcpRequest
 
   try {
     const startTime = new Date()
-    const resp = await send({ host, port, data, timeout })
+    const resp = await sendTCP({ host, port, data, timeout })
     const endTime = new Date()
     const duration = differenceInMilliseconds(endTime, startTime)
 
@@ -64,7 +86,7 @@ export async function check(tcpRequest: TCPRequest): Promise<Result> {
   }
 }
 
-async function send(tcpRequest: TCPRequest): Promise<any> {
+async function sendTCP(tcpRequest: TCPRequest): Promise<any> {
   const { host, port, data, timeout } = tcpRequest
 
   return new Promise((resolve, reject) => {
@@ -96,3 +118,22 @@ async function send(tcpRequest: TCPRequest): Promise<any> {
     })
   })
 }
+
+// map tcp request result to monika base response
+function processTCPRequestResult({
+  duration,
+  status,
+  message,
+  responseData,
+}: TCPResult) {
+  const baseResp: ProbeRequestResponse = {
+    requestType: 'tcp',
+    data: '',
+    body: responseData || message || '-', // map tcp response data or any message into "http body" to be displayed
+    status: status === 'DOWN' ? 0 : 200, // set to 0 if down, and 200 if ok
+    headers: {},
+    responseTime: duration,
+  }
+
+  return baseResp
+}
diff --git a/src/interfaces/request.ts b/src/interfaces/request.ts
index 55c4c11c..e12156b1 100644
--- a/src/interfaces/request.ts
+++ b/src/interfaces/request.ts
@@ -33,13 +33,10 @@ export interface ProbeRequestResponse<T = any> {
   requestType?: RequestTypes // is this for http (default) or icmp  or others
   data: T
   body: T
-  status: number // todo: Improve status management. Status as number is pretty limiting here if we want to support other protocols other than http
+  status: number // TODO: Improve status management. Status as number is pretty limiting here if we want to support other protocols other than http
+  // statusMsg: string // string messge of the satus code
   headers: any
   responseTime: number
-
-  numericHost?: string
-  alive?: boolean
-  packetLoss?: number
 }
 
 // ProbeRequest is used to define the requests that is being made.
diff --git a/src/jobs/tls-check.ts b/src/jobs/tls-check.ts
index addc6a0d..b968df69 100644
--- a/src/jobs/tls-check.ts
+++ b/src/jobs/tls-check.ts
@@ -30,7 +30,7 @@ import { Notification } from '../interfaces/notification'
 import type { ValidatedResponse } from '../plugins/validate-response'
 import { log } from '../utils/pino'
 
-export function tlsChecker() {
+export function tlsChecker(): void {
   const config = getConfig()
   const isCertificateConfigEmpty =
     config?.certificate && config?.certificate?.domains.length > 0
diff --git a/src/plugins/validate-response/checkers/index.ts b/src/plugins/validate-response/checkers/index.ts
index ad4baf31..54d2a348 100644
--- a/src/plugins/validate-response/checkers/index.ts
+++ b/src/plugins/validate-response/checkers/index.ts
@@ -43,20 +43,17 @@ export const parseAlertStringTime = (str: string): number => {
   return number
 }
 
+// resonseChecker checks some result and returns ()
 const responseChecker = (
   alert: ProbeAlert,
   res: ProbeRequestResponse
 ): boolean => {
+  // TODO: improve the flag/alert triggers away from axios centric status
   // if status is 599 : timeout or uri is not found (0), worth reporting so return true for alert
   if (res.status === 599 || res.status === 0 || res.status === 1) {
     return true
   }
 
-  // if a ping request is not connected, or timed out, return an alert
-  if (res.alive === false || res.status === 4) {
-    return true
-  }
-
   return queryExpression(res, alert.query)
 }
 
diff --git a/src/plugins/validate-response/checkers/query-expression.ts b/src/plugins/validate-response/checkers/query-expression.ts
index 98671f6c..17fba2ca 100644
--- a/src/plugins/validate-response/checkers/query-expression.ts
+++ b/src/plugins/validate-response/checkers/query-expression.ts
@@ -27,9 +27,9 @@ import { ProbeRequestResponse } from '../../../interfaces/request'
 
 /**
  * queryExpression runs a query against probe results
- * @param {object} res is the axios response objet
+ * @param {object} res is the axios response object
  * @param {string} query is the query string to operate on the res object
- * @returns {boolean} true or false result of the query a
+ * @returns {boolean} true or false result of the query against the object
  */
 const queryExpression = (res: ProbeRequestResponse, query: string): boolean => {
   const object = {


Test patch:
diff --git a/src/components/probe/probing.test.ts b/src/components/probe/probing.test.ts
index b3754526..c2e4118a 100644
--- a/src/components/probe/probing.test.ts
+++ b/src/components/probe/probing.test.ts
@@ -1,4 +1,3 @@
-/* eslint-disable max-depth */
 /**********************************************************************************
  * MIT License                                                                    *
  *                                                                                *
@@ -30,9 +29,9 @@ import { RequestInterceptor } from 'node-request-interceptor'
 import withDefaultInterceptors from 'node-request-interceptor/lib/presets/default'
 import { setContext } from '../../context'
 import { RequestConfig } from '../../interfaces/request'
-import { probing } from './probing'
+import { probingHTTP } from './probing'
 
-describe('Probing', () => {
+describe('probingHTTP', () => {
   let interceptor: any
   beforeEach(() => {
     interceptor = new RequestInterceptor(withDefaultInterceptors)
@@ -40,7 +39,7 @@ describe('Probing', () => {
   afterEach(() => {
     interceptor.restore()
   })
-  describe('probing function', () => {
+  describe('probingHTTP function', () => {
     it('should render correct headers', async () => {
       let verifyHeader: any = {}
       let tokens = ['1', '2']
@@ -97,7 +96,7 @@ describe('Probing', () => {
         for (let j = 0; j < requests.length; j++) {
           try {
             // eslint-disable-next-line no-await-in-loop
-            const resp = await probing({
+            const resp = await probingHTTP({
               requestConfig: requests[j],
               responses,
             })
@@ -139,7 +138,7 @@ describe('Probing', () => {
 
       const flag: { followRedirects: number } = { followRedirects: 0 }
       setContext({ flags: flag })
-      const result = await probing({
+      const result = await probingHTTP({
         requestConfig: request,
         responses: [],
       })
@@ -176,7 +175,7 @@ describe('Probing', () => {
       setContext({ flags: flag })
       // act
       server.listen()
-      const res = await probing({
+      const res = await probingHTTP({
         requestConfig: request,
         responses: [],
       })
@@ -217,7 +216,7 @@ describe('Probing', () => {
       server.listen()
       const flag: { followRedirects: number } = { followRedirects: 0 }
       setContext({ flags: flag })
-      const res = await probing({
+      const res = await probingHTTP({
         requestConfig: request,
         responses: [],
       })
@@ -258,7 +257,7 @@ describe('Probing', () => {
       server.listen()
       const flag: { followRedirects: number } = { followRedirects: 0 }
       setContext({ flags: flag })
-      const res = await probing({
+      const res = await probingHTTP({
         requestConfig: request,
         responses: [],
       })
@@ -300,7 +299,7 @@ describe('Probing', () => {
       server.listen()
       const flag: { followRedirects: number } = { followRedirects: 0 }
       setContext({ flags: flag })
-      const res = await probing({
+      const res = await probingHTTP({
         requestConfig: request,
         responses: [],
       })