Startegická: Init logování API
This commit is contained in:
parent
e0d4db6dab
commit
3e9fa79305
5 changed files with 132 additions and 6 deletions
|
@ -29,6 +29,7 @@ if args.drop:
|
||||||
x = db.get_session().execute(row[0])
|
x = db.get_session().execute(row[0])
|
||||||
print(row, x)
|
print(row, x)
|
||||||
x = db.get_session().execute("DROP TYPE IF EXISTS step_mode;")
|
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.get_session().commit()
|
||||||
|
|
||||||
db.metadata.bind = db.get_engine()
|
db.metadata.bind = db.get_engine()
|
||||||
|
|
|
@ -114,6 +114,12 @@ class StepMode(MOEnum):
|
||||||
automatic = auto()
|
automatic = auto()
|
||||||
|
|
||||||
|
|
||||||
|
class Endpoint(MOEnum):
|
||||||
|
state = auto()
|
||||||
|
action = auto()
|
||||||
|
step = auto()
|
||||||
|
error = auto()
|
||||||
|
|
||||||
class Game(Base):
|
class Game(Base):
|
||||||
__tablename__ = 'games'
|
__tablename__ = 'games'
|
||||||
|
|
||||||
|
@ -187,6 +193,34 @@ class State(Base):
|
||||||
|
|
||||||
game = relationship('Game', primaryjoin='State.game_id == Game.game_id')
|
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):
|
class Move(Base):
|
||||||
__tablename__ = 'moves'
|
__tablename__ = 'moves'
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,8 @@ def init_request():
|
||||||
return
|
return
|
||||||
|
|
||||||
user = None
|
user = None
|
||||||
|
g.user = None
|
||||||
|
g.org = False
|
||||||
if path.startswith('/api/'):
|
if path.startswith('/api/'):
|
||||||
token = request.args.get('token')
|
token = request.args.get('token')
|
||||||
if token is not None:
|
if token is not None:
|
||||||
|
@ -80,7 +82,8 @@ def init_request():
|
||||||
if g.org:
|
if g.org:
|
||||||
g.menu += [
|
g.menu += [
|
||||||
MenuItem(app.url_for(pages.web_org_games.__name__), "Hry"),
|
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:
|
else:
|
||||||
g.menu += [
|
g.menu += [
|
||||||
|
@ -95,6 +98,8 @@ app.before_request(init_request)
|
||||||
def handle_exception(e):
|
def handle_exception(e):
|
||||||
path = request.path
|
path = request.path
|
||||||
if path.startswith('/api/'):
|
if path.startswith('/api/'):
|
||||||
|
ses = db.get_session()
|
||||||
|
ses.rollback()
|
||||||
response = e.get_response()
|
response = e.get_response()
|
||||||
response.data = json.dumps({
|
response.data = json.dumps({
|
||||||
"status": "error",
|
"status": "error",
|
||||||
|
@ -103,6 +108,18 @@ def handle_exception(e):
|
||||||
"http-name": e.name,
|
"http-name": e.name,
|
||||||
})
|
})
|
||||||
response.content_type = "application/json"
|
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
|
return response
|
||||||
else:
|
else:
|
||||||
return e
|
return e
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from flask import Flask, redirect, flash, render_template, session, g, request, get_flashed_messages
|
from flask import Flask, redirect, flash, render_template, session, g, request, get_flashed_messages
|
||||||
import werkzeug.exceptions
|
import werkzeug.exceptions
|
||||||
import json
|
import json
|
||||||
|
import traceback
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
import hra.config as config
|
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.web.jinja_mac as jinja_mac
|
||||||
import hra.lib as lib
|
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 json_endpoint(f):
|
||||||
def l(*arg, **kvarg):
|
def l(*arg, **kvarg):
|
||||||
x = f(*arg, **kvarg)
|
x = f(*arg, **kvarg)
|
||||||
|
@ -57,6 +75,7 @@ def api_state():
|
||||||
t = datetime.now()
|
t = datetime.now()
|
||||||
state = game.current_state()
|
state = game.current_state()
|
||||||
if state is None:
|
if state is None:
|
||||||
|
log(team, db.Endpoint.state, "working", text="wait 1")
|
||||||
ses.commit()
|
ses.commit()
|
||||||
return {
|
return {
|
||||||
"status": "working",
|
"status": "working",
|
||||||
|
@ -67,13 +86,16 @@ def api_state():
|
||||||
else:
|
else:
|
||||||
time_to_end = None
|
time_to_end = None
|
||||||
if min_round is not None and min_round > game.current_round:
|
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()
|
ses.commit()
|
||||||
return {
|
return {
|
||||||
"status": "too_early",
|
"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 = team.get_move(state.round)
|
||||||
move.reads_count += 1
|
move.reads_count += 1
|
||||||
|
log(team, db.Endpoint.state, "ok", round=game.current_round)
|
||||||
ses.commit()
|
ses.commit()
|
||||||
return {
|
return {
|
||||||
"status": "ok",
|
"status": "ok",
|
||||||
|
@ -88,6 +110,8 @@ def api_state():
|
||||||
def api_action():
|
def api_action():
|
||||||
ses = db.get_session()
|
ses = db.get_session()
|
||||||
def to_late():
|
def to_late():
|
||||||
|
log(team, db.Endpoint.action, "too_late", round=round_id)
|
||||||
|
ses.commit()
|
||||||
return {
|
return {
|
||||||
"status": "too_late",
|
"status": "too_late",
|
||||||
}
|
}
|
||||||
|
@ -106,19 +130,21 @@ def api_action():
|
||||||
warnings = game.get_logic().validate_move(state.get_state(), team_id, j, round_id)
|
warnings = game.get_logic().validate_move(state.get_state(), team_id, j, round_id)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
game = game.lock()
|
game = game.lock()
|
||||||
move = team.get_move(state.round_id)
|
move = team.get_move(state.round)
|
||||||
move.err_pushs_count += 1
|
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()
|
ses.commit()
|
||||||
return {
|
return {
|
||||||
"status": "error",
|
"status": "error",
|
||||||
"description": f"{type(e).__name__}: {e}"
|
"description": description
|
||||||
}
|
}
|
||||||
|
|
||||||
db.get_session().expire_all()
|
ses.expire_all()
|
||||||
game = game.lock()
|
game = game.lock()
|
||||||
|
|
||||||
if game.working_on_next_state or round_id < game.current_round:
|
if game.working_on_next_state or round_id < game.current_round:
|
||||||
db.get_session().commit()
|
ses.commit()
|
||||||
return to_late()
|
return to_late()
|
||||||
|
|
||||||
move = team.get_move(state.round)
|
move = team.get_move(state.round)
|
||||||
|
@ -130,6 +156,7 @@ def api_action():
|
||||||
else:
|
else:
|
||||||
move.warnings_pushs_count += 1
|
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()
|
ses.commit()
|
||||||
|
|
||||||
if warnings is not None:
|
if warnings is not None:
|
||||||
|
@ -148,6 +175,8 @@ def api_step():
|
||||||
raise werkzeug.exceptions.Forbidden("Je zakázáno krokovat tuto hru")
|
raise werkzeug.exceptions.Forbidden("Je zakázáno krokovat tuto hru")
|
||||||
|
|
||||||
lib.game_step(game.game_id)
|
lib.game_step(game.game_id)
|
||||||
|
log(team, db.Endpoint.step, "ok")
|
||||||
|
db.get_session.commit()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"status": "ok",
|
"status": "ok",
|
||||||
|
|
|
@ -503,4 +503,49 @@ def web_org_user_su(user_id):
|
||||||
flash("Uživatel vtělen!")
|
flash("Uživatel vtělen!")
|
||||||
return redirect('/')
|
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
|
from hra.web.game import get_wlogic, wlogic_by_mode
|
||||||
|
|
Loading…
Reference in a new issue