From 50fd2b5b068bb3907810df20d3c79575c31e4abb Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Fri, 25 Mar 2022 15:29:28 +0100 Subject: [PATCH] refactor metric collection --- backend/bang/game.py | 14 +++++--------- backend/metrics.py | 28 ++++++++++++++++++++++++++++ backend/server.py | 32 ++++++++++---------------------- 3 files changed, 43 insertions(+), 31 deletions(-) create mode 100644 backend/metrics.py diff --git a/backend/bang/game.py b/backend/bang/game.py index 7a8592a..53da6f2 100644 --- a/backend/bang/game.py +++ b/backend/bang/game.py @@ -1,5 +1,3 @@ -import time -import os import json from typing import List, Set, Dict, Tuple, Optional import random @@ -15,14 +13,13 @@ import bang.expansions.fistful_of_cards.card_events as ce import bang.expansions.high_noon.card_events as ceh import bang.expansions.gold_rush.shop_cards as grc import bang.expansions.gold_rush.characters as grch -import datadog +from metrics import Metrics class Game: - def __init__(self, name, sio:socketio, dd_api:datadog.api = None): + def __init__(self, name, sio:socketio): super().__init__() self.sio = sio self.name = name - self.dd_api = dd_api self.players: List[pl.Player] = [] self.spectators: List[pl.Player] = [] self.deck: Deck = None @@ -451,8 +448,7 @@ class Game: if not self.someone_won: self.someone_won = True self.sio.emit('chat_message', room=self.name, data=f'_won|{p.name}|{p.role.name}') - if self.dd_api: - self.dd_api.Metric.send(metric='player_win', points=[(int(time.time()), 1)], tags=["server:backend", f"host:{os.environ['HOST']}", f"char:{p.character.name}", f"role:{p.role.name}"]) + Metrics.send_metric('player_win', points=[1], tags=[f"char:{p.character.name}", f"role:{p.role.name}"]) p.notify_self() if hasattr(self.sio, 'is_fake'): print('announces_winners(): Running for tests, you will have to call reset manually!') @@ -610,8 +606,8 @@ class Game: self.is_handling_death = True import bang.expansions.dodge_city.characters as chd print(f'{self.name}: the killer is {player.attacker}') - if self.dd_api and player.character and player.role: - self.dd_api.Metric.send(metric='player_death', points=[(int(time.time()), 1)], tags=["server:backend", f"host:{os.environ['HOST']}", f"char:{player.character.name}", f"role:{player.role.name}"]) + if player.character and player.role: + Metrics.send_metric('player_death', points=[1], tags=[f"char:{player.character.name}", f"role:{player.role.name}"]) if len([c for c in player.gold_rush_equipment if isinstance(c, grc.Ricercato)]) > 0 and player.attacker and player.attacker in self.players: player.attacker.gold_nuggets += 1 player.attacker.hand.append(self.deck.draw(True)) diff --git a/backend/metrics.py b/backend/metrics.py new file mode 100644 index 0000000..93dbbaa --- /dev/null +++ b/backend/metrics.py @@ -0,0 +1,28 @@ +import os +import time +from datadog import initialize, api + +class Metrics: + send_metrics = False + + @classmethod + def init(cls): + if "DATADOG_API_KEY" in os.environ and "DATADOG_APP_KEY" in os.environ and "HOST" in os.environ: + Metrics.send_metrics = True + initialize() + api.Event.create(title="Backend start", text="", tags=["server:backend", f"host:{os.environ['HOST']}"], alert_type="info") + else: + print("Datadog not configured") + + @classmethod + def send_metric(cls, metric_name, **kwargs): + if Metrics.send_metrics: + kwargs['tags'] = ["server:backend", f"host:{os.environ['HOST']}"] + kwargs.get('tags', []) + kwargs['points'][0] = (int(time.time()) , kwargs['points'][0]) + api.Metric.send(metric=metric_name, **kwargs) + + @classmethod + def send_event(cls, event_name, event_data, **kwargs): + if Metrics.send_metrics: + kwargs['tags'] = ["server:backend", f"host:{os.environ['HOST']}"] + kwargs.get('tags', []) + api.Event.create(title=event_name, text=event_data, tags=kwargs['tags'], alert_type=kwargs.get('alert_type', "info")) diff --git a/backend/server.py b/backend/server.py index 408b0bb..bf725de 100644 --- a/backend/server.py +++ b/backend/server.py @@ -1,3 +1,4 @@ +import imp import os import json import time @@ -11,17 +12,10 @@ from bang.players import Player, PendingAction import requests from discord_webhook import DiscordWebhook -from datadog import initialize, api +from metrics import Metrics -send_metrics = False -if "DATADOG_API_KEY" in os.environ and "DATADOG_APP_KEY" in os.environ: - initialize() - send_metrics = True - api.Event.create(title="Backend start", text="", tags=["server:backend", f"host:{os.environ['HOST']}"], alert_type="info") -else: - print("Datadog not configured") - +Metrics.init() import sys sys.setrecursionlimit(10**6) # this should prevents bots from stopping @@ -55,8 +49,7 @@ blacklist: List[str] = [] def advertise_lobbies(): sio.emit('lobbies', room='lobby', data=[{'name': g.name, 'players': len(g.players), 'locked': g.password != ''} for g in games if not g.started and len(g.players) < 10 and not g.is_hidden]) sio.emit('spectate_lobbies', room='lobby', data=[{'name': g.name, 'players': len(g.players), 'locked': g.password != ''} for g in games if g.started]) - if send_metrics: - api.Metric.send(metric='lobbies', points=[(int(time.time()), len(games))], tags=["server:backend", "type:lobbies", f"host:{os.environ['HOST']}"]) + Metrics.send_metric('lobbies', points=[len(games)]) @sio.event def connect(sid, environ): @@ -65,8 +58,7 @@ def connect(sid, environ): print('connect ', sid) sio.enter_room(sid, 'lobby') sio.emit('players', room='lobby', data=online_players) - if send_metrics: - api.Metric.send(metric='online_players', points=[(int(time.time()), online_players)], tags=["server:backend", f"host:{os.environ['HOST']}"]) + Metrics.send_metric('online_players', points=[online_players]) @sio.event def get_online_players(sid): @@ -89,8 +81,7 @@ def report(sid, text): sio.emit('chat_message', room=sid, data={'color': f'green','text':f'Report OK'}) else: print("WARNING: DISCORD_WEBHOOK not found") - if send_metrics: - api.Event.create(title="BUG REPORT", text=data, tags=["server:backend", f"host:{os.environ['HOST']}"]) + Metrics.send_event('BUG_REPORT', event_data=text) print(f'New bug report, replay at https://www.toptal.com/developers/hastebin/{key}') @sio.event @@ -174,8 +165,7 @@ def disconnect(sid): games.pop(games.index(sio.get_session(sid).game)) print('disconnect ', sid) advertise_lobbies() - if send_metrics: - api.Metric.send(metric='online_players', points=[(int(time.time()), online_players)], tags=["server:backend", f"host:{os.environ['HOST']}"]) + Metrics.send_metric('online_players', points=[online_players]) @sio.event def create_room(sid, room_name): @@ -184,7 +174,7 @@ def create_room(sid, room_name): room_name += f'_{random.randint(0,100)}' sio.leave_room(sid, 'lobby') sio.enter_room(sid, room_name) - g = Game(room_name, sio, api if send_metrics else None) + g = Game(room_name, sio) g.add_player(sio.get_session(sid)) if room_name in blacklist: g.is_hidden = True @@ -283,15 +273,13 @@ def start_game(sid): ses: Player = sio.get_session(sid) ses.game.start_game() advertise_lobbies() - if send_metrics: - api.Metric.send(metric='start_game', points=[(int(time.time()), 1)], tags=(["server:backend", f"host:{os.environ['HOST']}"] + [f"exp:{e}" for e in ses.game.expansions])) + Metrics.send_metric('start_game', points=[1], tags=[f"exp:{e}" for e in ses.game.expansions]) @sio.event def set_character(sid, name): ses: Player = sio.get_session(sid) ses.game.rpc_log.append(f'{ses.name};set_character;{name}') - if send_metrics: - api.Metric.send(metric='set_character', points=[(int(time.time()), 1)], tags=["server:backend", f"host:{os.environ['HOST']}", f"char:{name}"]) + Metrics.send_metric('set_character', points=[1], tags=[f"char:{name}"]) ses.set_character(name) @sio.event