Skip to content

Commit

Permalink
Merge pull request #315 from mendix/UPV4-160-Latency-between-app-and-…
Browse files Browse the repository at this point in the history
…database

Add metric to measure TCP latency between app and database
  • Loading branch information
svanderburg authored May 25, 2020
2 parents 027416b + 38e4113 commit 599aa07
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 13 deletions.
9 changes: 3 additions & 6 deletions bin/bootstrap-python
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,9 @@ PIP_WORKDIR="${CACHE_PATH}/pip/build"
# Set the correct Python site-packages directory to install to
SITE_PACKAGES_PATH="${BUILD_PATH}/$(python3 -m site --user-site | cut -d '/' -f4-)"

if [[ ! -d $PIP_WHEELDIR ]]
then
echo " ---> Copying included wheels to cache...";
mkdir -p $PIP_WHEELDIR;
cp -rf $WHEELS_PATH/* $PIP_WHEELDIR/;
fi
echo " ---> Copying included wheels to cache...";
mkdir -p $PIP_WHEELDIR;
cp -rf $WHEELS_PATH/* $PIP_WHEELDIR/;

echo " ---> Bootstrapping pip and setuptools..."
$PIP_CMD install --user --no-warn-script-location --no-index --find-links=$PIP_WHEELDIR --build=$PIP_WORKDIR pip setuptools
Expand Down
50 changes: 44 additions & 6 deletions buildpack/runtime_components/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
import json
import logging
import os
import socket
import sys
import threading
import time
from abc import ABCMeta, abstractmethod
from timeit import default_timer as timer

import psycopg2
import requests
Expand Down Expand Up @@ -235,6 +237,9 @@ def _inject_database_stats(self, stats):
if mutations_stats:
database_stats.update(mutations_stats)
stats["database"] = database_stats
tcp_latency = self._get_database_tcp_latency()
if tcp_latency:
database_stats["tcp_latency"] = tcp_latency
return stats

def _get_database_storage(self):
Expand All @@ -244,6 +249,34 @@ def _get_database_storage(self):
except ValueError:
return None

def _get_database_tcp_latency(self, timeout: float = 5):
db_config = database.get_config()
host, port = self._get_db_host_and_port(db_config["DatabaseHost"])
# New Socket and Time out
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(timeout)

# Start a timer
s_start = timer()

# Try to Connect
try:
sock.connect((host, int(port)))
sock.shutdown(socket.SHUT_RD)
sock.close()

# If something bad happens, the latency is None
except socket.timeout:
return None
except OSError:
return None

# Stop Timer
s_stop = timer()
s_runtime = "%.2f" % (1000 * (s_stop - s_start))

return s_runtime

def _get_database_mutations(self):
conn = self._get_db_conn()
db_config = database.get_config()
Expand Down Expand Up @@ -357,12 +390,7 @@ def _get_db_conn(self):
% db_config["DatabaseType"]
)

host_and_port = db_config["DatabaseHost"].split(":")
host = host_and_port[0]
if len(host_and_port) > 1:
port = int(host_and_port[1])
else:
port = 5432
host, port = self._get_db_host_and_port(db_config["DatabaseHost"])
self.db = psycopg2.connect(
"options='-c statement_timeout=60s'",
database=db_config["DatabaseName"],
Expand All @@ -377,6 +405,16 @@ def _get_db_conn(self):
)
return self.db

@staticmethod
def _get_db_host_and_port(database_host):
host_and_port = database_host.split(":")
host = host_and_port[0]
if len(host_and_port) > 1:
port = int(host_and_port[1])
else:
port = 5432
return host, port


class PaidAppsMetricsEmitterThread(BaseMetricsEmitterThread):
@property
Expand Down
2 changes: 1 addition & 1 deletion buildpack/start.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
from buildpack.runtime_components import security
from lib.m2ee import M2EE as m2ee_class

BUILDPACK_VERSION = "4.5.2"
BUILDPACK_VERSION = "4.5.3"

m2ee = None
app_is_restarting = False
Expand Down
1 change: 1 addition & 0 deletions tests/integration/test_emit_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def test_read_metrics_in_logs(self):
self.assert_string_in_recent_logs("storage")
self.assert_string_in_recent_logs("number_of_files")
self.assert_string_in_recent_logs("critical_logs_count")
self.assert_string_in_recent_logs("tcp_latency")

def test_free_apps_metrics(self):
self.setUpCF(
Expand Down

0 comments on commit 599aa07

Please sign in to comment.