Browse Source

Startegická: Init logování API

master
Jiří Kalvoda 2 years ago
parent
commit
3e9fa79305
  1. 1
      server/bin/db_init
  2. 34
      server/hra/db.py
  3. 19
      server/hra/web/__init__.py
  4. 39
      server/hra/web/api.py
  5. 45
      server/hra/web/pages.py

1
server/bin/db_init

@ -29,6 +29,7 @@ if args.drop:
x = db.get_session().execute(row[0])
print(row, x)
x = db.get_session().execute("DROP TYPE IF EXISTS step_mode;")
x = db.get_session().execute("DROP TYPE IF EXISTS endpoint;")
db.get_session().commit()
db.metadata.bind = db.get_engine()

34
server/hra/db.py

@ -114,6 +114,12 @@ class StepMode(MOEnum):
automatic = auto()
class Endpoint(MOEnum):
state = auto()
action = auto()
step = auto()
error = auto()
class Game(Base):
__tablename__ = 'games'
@ -187,6 +193,34 @@ class State(Base):
game = relationship('Game', primaryjoin='State.game_id == Game.game_id')
class Log(Base):
__tablename__= 'logs'
source_ip = Column(String(20))
log_id = Column(Integer, primary_key=True)
user_id = Column(Integer, ForeignKey('users.id'))
game_id = Column(Integer, ForeignKey('games.game_id'))
round = Column(Integer)
team_id = Column(Integer)
endpoint = Column(Enum(Endpoint, name="endpoint"), nullable=False)
url = Column(String(200), nullable=False)
get = Column(JSONB, nullable=False)
time = Column(DateTime, nullable=False)
status = Column(String(80))
data = Column(Integer, ForeignKey('bigdata.id'))
text = Column(String(500))
game = relationship('Game', primaryjoin='Log.game_id == Game.game_id')
user = relationship('User', primaryjoin='Log.user_id == User.id')
def get_data(self):
if self.data is None:
return None
return get_big_data(self.data)
class Move(Base):
__tablename__ = 'moves'

19
server/hra/web/__init__.py

@ -57,6 +57,8 @@ def init_request():
return
user = None
g.user = None
g.org = False
if path.startswith('/api/'):
token = request.args.get('token')
if token is not None:
@ -80,7 +82,8 @@ def init_request():
if g.org:
g.menu += [
MenuItem(app.url_for(pages.web_org_games.__name__), "Hry"),
MenuItem(app.url_for(pages.web_org_users.__name__), "Uživatelé")
MenuItem(app.url_for(pages.web_org_users.__name__), "Uživatelé"),
MenuItem(app.url_for(pages.web_org_logs.__name__), "Logy"),
]
else:
g.menu += [
@ -95,6 +98,8 @@ app.before_request(init_request)
def handle_exception(e):
path = request.path
if path.startswith('/api/'):
ses = db.get_session()
ses.rollback()
response = e.get_response()
response.data = json.dumps({
"status": "error",
@ -103,6 +108,18 @@ def handle_exception(e):
"http-name": e.name,
})
response.content_type = "application/json"
x = db.Log(
source_ip=request.remote_addr,
user_id=g.user.id if g.user is not None else None,
endpoint=db.Endpoint.error,
status="http-error",
text=f"{e.code} ({e.name}): {e.description}",
url=request.path,
get=request.args,
time=datetime.now(),
)
ses.add(x)
ses.commit()
return response
else:
return e

39
server/hra/web/api.py

@ -1,6 +1,7 @@
from flask import Flask, redirect, flash, render_template, session, g, request, get_flashed_messages
import werkzeug.exceptions
import json
import traceback
from datetime import datetime
import hra.config as config
@ -9,6 +10,23 @@ from hra.web import app, NeedLoginError
import hra.web.jinja_mac as jinja_mac
import hra.lib as lib
def log(team, endpoint, status, **kvarg):
x = db.Log(
source_ip=request.remote_addr,
user_id=g.user.id,
team_id=team.team_id,
game_id=team.game_id,
endpoint=endpoint,
status=status,
url=request.path,
get=request.args,
time=datetime.now(),
**kvarg
)
db.get_session().add(x)
return x
def json_endpoint(f):
def l(*arg, **kvarg):
x = f(*arg, **kvarg)
@ -57,6 +75,7 @@ def api_state():
t = datetime.now()
state = game.current_state()
if state is None:
log(team, db.Endpoint.state, "working", text="wait 1")
ses.commit()
return {
"status": "working",
@ -67,13 +86,16 @@ def api_state():
else:
time_to_end = None
if min_round is not None and min_round > game.current_round:
wait = time_to_end + 1.0 if time_to_end is not None else 3.0
log(team, db.Endpoint.state, "too_early", text=f"wait {wait}; min_round {min_round}", round=game.current_round)
ses.commit()
return {
"status": "too_early",
"wait": time_to_end + 1.0 if time_to_end is not None else 3.0,
"wait": wait,
}
move = team.get_move(state.round)
move.reads_count += 1
log(team, db.Endpoint.state, "ok", round=game.current_round)
ses.commit()
return {
"status": "ok",
@ -88,6 +110,8 @@ def api_state():
def api_action():
ses = db.get_session()
def to_late():
log(team, db.Endpoint.action, "too_late", round=round_id)
ses.commit()
return {
"status": "too_late",
}
@ -106,19 +130,21 @@ def api_action():
warnings = game.get_logic().validate_move(state.get_state(), team_id, j, round_id)
except Exception as e:
game = game.lock()
move = team.get_move(state.round_id)
move = team.get_move(state.round)
move.err_pushs_count += 1
description =f"{type(e).__name__}: {e}"
log(team, db.Endpoint.action, "error", round=round_id, text=description, data=db.new_big_data(traceback.format_exc()))
ses.commit()
return {
"status": "error",
"description": f"{type(e).__name__}: {e}"
"description": description
}
db.get_session().expire_all()
ses.expire_all()
game = game.lock()
if game.working_on_next_state or round_id < game.current_round:
db.get_session().commit()
ses.commit()
return to_late()
move = team.get_move(state.round)
@ -130,6 +156,7 @@ def api_action():
else:
move.warnings_pushs_count += 1
log(team, db.Endpoint.action, "warning" if warnings is not None else "ok", round=round_id, data=move.move)
ses.commit()
if warnings is not None:
@ -148,6 +175,8 @@ def api_step():
raise werkzeug.exceptions.Forbidden("Je zakázáno krokovat tuto hru")
lib.game_step(game.game_id)
log(team, db.Endpoint.step, "ok")
db.get_session.commit()
return {
"status": "ok",

45
server/hra/web/pages.py

@ -503,4 +503,49 @@ def web_org_user_su(user_id):
flash("Uživatel vtělen!")
return redirect('/')
@app.route("/org/log/<int:log_id>", methods=['GET'])
def web_org_log(log_id):
l = db.get_session().query(db.Log).filter_by(log_id=log_id).one_or_none()
if l is None:
raise werkzeug.exceptions.NotFound()
b = BasePage()
b.line().h2("Log ", log_id)
b.p().pre(pprint.pformat(l.get_data()))
return b.print_file()
@app.route("/org/logs", methods=['GET'])
def web_org_logs():
logs = db.get_session().query(db.Log).order_by(db.Log.log_id.desc()).all()
b = BasePage()
b.line().h2("Logy")
with b.p().table(_class="data full"):
with b.thead():
b.line().th()("Čas")
b.line().th()("Uživatel")
b.line().th()("URL")
b.line().th()("Hra")
b.line().th()("Tým")
b.line().th()("Status")
b.line().th()("Popis")
b.line().th()("GET")
b.line().th()("Akce")
for l in logs:
with b.tr():
b.line().td(l.time.strftime("%H:%M:%S"))
b.line().td(l.user.print() if l.user else None, b._br(), l.source_ip)
b.line().td(l.endpoint._name_, b._br(), l.url)
b.line().td(l.game.print() if l.game else None)
b.line().td(l.team_id)
b.line().td(l.status)
b.line().td(l.text)
with b.line().td():
for k,v in l.get.items():
b(f"{k}: {v}").br()
with b.line().td():
with b.div(_class="btn-group", role="group"):
b.a(href=app.url_for(web_org_log.__name__, log_id=l.log_id), _class="btn btn-xs btn-primary")("Podrobnosti")
return b.print_file()
from hra.web.game import get_wlogic, wlogic_by_mode

Loading…
Cancel
Save