health check service

Kaveen Kumarasinghe 2 years ago
parent 29fb90eb7f
commit c1526b40fc

@ -417,3 +417,13 @@ This can also be run via screen/tmux or detached like a daemon.
- Copy the link generated below and paste it on the browser
- On add to server select the desired server to add the bot
- Make sure you have updated your .env file with valid values for `DEBUG_GUILD`, `DEBUG_CHANNEL` and `ALLOWED_GUILDS`, otherwise the bot will not work. Guild IDs can be found by right clicking a server and clicking `Copy ID`, similarly, channel IDs can be found by right clicking a channel and clicking `Copy ID`.
## Health Check Service
The bot has the ability to launch a HTTP endpoint at `<host>:8181/` that will return a json response of the bot's status and uptime. This is especially useful if you want to run this bot on cloud application containers, like Azure App Service.
To enable this, add `HEALTH_SERVICE_ENABLED="True"` to your `.env` file.
The health check endpoint will then be present in your bot's console when it is starting up, it will look like this, the possible HTTP urls for your health endpoint will be visible near the bottom:
<center><img src="https://i.imgur.com/RqV2xN6.png"/></center>

@ -112,7 +112,6 @@ class ModerationsService(discord.Cog, name="ModerationsService"):
async def check_and_launch_moderations(self, guild_id, alert_channel_override=None):
"""Create the moderation service"""
print("Checking and attempting to launch moderations service...")
if self.check_guild_moderated(guild_id):
Moderation.moderation_queues[guild_id] = asyncio.Queue()

@ -1,6 +1,7 @@
import os
import asyncio
import sys
import threading
import traceback
from pathlib import Path
@ -15,6 +16,7 @@ from cogs.moderations_service_cog import ModerationsService
from cogs.commands import Commands
from cogs.translation_service_cog import TranslationService
from models.deepl_model import TranslationModel
from services.health_service import HealthService
from services.pinecone_service import PineconeService
from services.deletion_service import Deletion
@ -25,7 +27,7 @@ from services.environment_service import EnvService
from models.openai_model import Model
__version__ = "8.0"
__version__ = "8.1"
if sys.platform == "win32":
@ -174,6 +176,7 @@ async def main():
# Run the bot with a token taken from an environment file.
def init():
PID_FILE = "bot.pid"
process = None
if os.path.exists(PID_FILE):
print("Process ID file already exists")
sys.exit(1)
@ -183,6 +186,13 @@ def init():
print("" "Wrote PID to f" "ile the file " + PID_FILE)
f.close()
try:
if EnvService.get_health_service_enabled():
try:
process = HealthService().get_process()
except:
traceback.print_exc()
print("The health service failed to start.")
asyncio.get_event_loop().run_until_complete(main())
except KeyboardInterrupt:
print("Caught keyboard interrupt, killing and removing PID")
@ -193,8 +203,13 @@ def init():
print("Removing PID file")
os.remove(PID_FILE)
finally:
# Kill all threads
print("Killing all subprocesses")
process.terminate()
print("Killed all subprocesses")
sys.exit(0)
if __name__ == "__main__":
sys.exit(init())

@ -28,6 +28,7 @@ dependencies = [
"pinecone-client",
"sqlitedict",
"backoff",
"flask",
]
dynamic = ["version"]
[project.scripts]

@ -7,4 +7,5 @@ pycord-multicog==1.0.2
aiofiles==22.1.0
pinecone-client==2.1.0
sqlitedict==2.1.0
backoff==2.2.1
backoff==2.2.1
flask==2.2.2

@ -221,6 +221,16 @@ class EnvService:
except Exception:
return False
@staticmethod
def get_health_service_enabled():
try:
user_input_api_keys = os.getenv("HEALTH_SERVICE_ENABLED")
if user_input_api_keys.lower().strip() == "true":
return True
return False
except Exception:
return False
@staticmethod
def get_user_key_db_path() -> Union[Path, None]:
try:

@ -0,0 +1,41 @@
import datetime
import traceback
from flask import Flask
from multiprocessing import Process
from healthcheck import HealthCheck
app = Flask(__name__)
health = HealthCheck()
start_time = datetime.datetime.now()
@app.route('/')
def health():
# Find the difference between the current time and start_time in seconds
uptime = (datetime.datetime.now() - start_time).total_seconds()
# Set the response status
status = 200
return {"status": "ok",
"uptime": uptime,
"uptime_unit": "seconds"}, status
def run_target(host, port):
try:
app.run(host=host, port=port, debug=False, use_reloader=False)
except:
pass
class HealthService:
"""
Service for health checks, for cloud services like Azure App Service.
"""
def __init__(self, host="0.0.0.0", port=8181):
self.host = host
self.port = port
print("Starting the health check service..")
self.process = Process(target=lambda: run_target(self.host, self.port))
self.process.start()
print("Health check service started!")
def get_process(self):
return self.process

@ -169,7 +169,6 @@ class Moderation:
warn_set,
delete_set,
):
print("The warn and delete sets are ", warn_set, delete_set)
while True:
try:
# If the queue is empty, sleep for a short time before checking again

Loading…
Cancel
Save