Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 69 additions & 10 deletions app/api/logs.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from datetime import datetime
from datetime import datetime
from app.root_logger import get_root_logger
from ast import literal_eval

import inspect
from flask import Blueprint, request

from app.lti_session_passback.auth_checkers import check_admin
Expand All @@ -11,7 +11,6 @@
logger = get_root_logger()



@api_logs.route('/api/logs/', methods=['GET'])
def get_logs() -> (dict, int):
"""
Expand All @@ -26,13 +25,15 @@ def get_logs() -> (dict, int):
try:
limit = request.args.get('limit', default=None, type=int)
except Exception as e:
logger.info('Limit value {} is invalid.\n{}'.format(request.args.get('limit'), e))
logger.info('Limit value {} is invalid.\n{}'.format(
request.args.get('limit'), e))
limit = None

try:
offset = request.args.get('offset', default=None, type=int)
except Exception as e:
logger.info('Offset value {} is invalid.\n{}'.format(request.args.get('offset', default=None), e))
logger.info('Offset value {} is invalid.\n{}'.format(
request.args.get('offset', default=None), e))
offset = None

raw_filters = request.args.get('filter', default=None)
Expand All @@ -42,7 +43,8 @@ def get_logs() -> (dict, int):
if not isinstance(filters, dict):
filters = None
except Exception as e:
logger.info('Filter value {} is invalid.\n{}'.format(raw_filters, e))
logger.info(
'Filter value {} is invalid.\n{}'.format(raw_filters, e))
filters = None
else:
filters = raw_filters
Expand All @@ -52,18 +54,22 @@ def get_logs() -> (dict, int):
try:
ordering = literal_eval(raw_ordering)
if not isinstance(ordering, list) or not all(map(lambda x: x[1] in [-1, 1], ordering)):
logger.info('Ordering value {} is invalid.'.format(raw_ordering))
logger.info(
'Ordering value {} is invalid.'.format(raw_ordering))
ordering = None
except Exception as e:
logger.info('Ordering value {} is invalid.\n{}'.format(request.args.get('ordering', default=None), e))
logger.info('Ordering value {} is invalid.\n{}'.format(
request.args.get('ordering', default=None), e))
ordering = None
else:
ordering = raw_ordering

try:
logs = LogsDBManager().get_logs_filtered(filters=filters, limit=limit, offset=offset, ordering=ordering)
logs = LogsDBManager().get_logs_filtered(
filters=filters, limit=limit, offset=offset, ordering=ordering)
except Exception as e:
message = 'Incorrect get_logs_filtered execution, {}: {}.'.format(e.__class__, e)
message = 'Incorrect get_logs_filtered execution, {}: {}.'.format(
e.__class__, e)
logger.warning(message)
return {'message': message}, 404

Expand All @@ -84,3 +90,56 @@ def get_logs() -> (dict, int):
logs_json['logs'][str(_id)] = current_log_json
logs_json['message'] = 'OK'
return logs_json, 200


@api_logs.route('/logs', methods=['POST'])
def create_log():
"""
Endpoint to receive client logs.
Expected JSON:
{
"timestamp": "...",
"message": "..."
}
"""
# logger.info("Received client log")
frame = inspect.currentframe() # кадр
caller = frame.f_back # кадр вызывающей функции
pathname = caller.f_code.co_filename # путь к файлу вызвывающей функции
filename = pathname.split('/')[-1] # имя файла
funcName = caller.f_code.co_name # имя функции
lineno = caller.f_lineno # номер строки
try:
data = request.get_json(force=True)
if not data:
return {"message": "Invalid json"}, 400

timestamp = data.get("timestamp")
message = data.get("message")

if message is None:
return {"message": "message field is required"}, 400

if timestamp:
timestamp = datetime.fromisoformat(
timestamp.replace("Z", "+00:00"))
else:
timestamp = datetime.now()

LogsDBManager().add_log(
timestamp=timestamp,
serviceName="client",
levelname="INFO",
levelno=20,
message=message,
pathname=pathname,
filename=filename,
funcName=funcName,
lineno=lineno
)

return {"message": "log received"}, 201

except Exception as e:
logger.warning(f"Client log creation failed: {e}")
return {"message": "Internal server error"}, 500
23 changes: 23 additions & 0 deletions app/static/js/logWrapper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
(function () {
// враппер над логами
window.logWrapper = function (...args) {
// стандартное логирование
console.log(...args);

// отправка на роут
try {
fetch('/logs', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
timestamp: new Date().toISOString(),
message: args.map(a => a.toString()).join(' ')
})
});
} catch (e) {
console.error('Log send error', e);
}
}
})();
10 changes: 5 additions & 5 deletions app/static/js/recording.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ let gumStream,
timer;

function startRecording() {
console.log("call startRecording(). Try to call navigator.mediaDevices.getUserMedia");
console.log("navigator", navigator);
console.log("navigator.mediaDevices", navigator.mediaDevices);
logWrapper("call startRecording(). Try to call navigator.mediaDevices.getUserMedia");
logWrapper("navigator", navigator);
logWrapper("navigator.mediaDevices", navigator.mediaDevices);
$("#alert").hide()
$("#record-contain").show();
navigator.mediaDevices.getUserMedia({audio: true, video: false}).then(function (stream) {
Expand Down Expand Up @@ -82,8 +82,8 @@ function startRecording() {
$("#record")[0].disabled = true;
$("#done")[0].disabled = false;
}).catch( err => {
console.log('Error on calling avigator.mediaDevices.getUserMedia')
console.log(err)
logWrapper('Error on calling avigator.mediaDevices.getUserMedia')
logWrapper(err)
$("#alert").show();
$("#error-text").html("Микрофон не доступен!");
});
Expand Down
2 changes: 1 addition & 1 deletion app/static/js/show_all_trainings.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ function buildAllTrainingsTable(trainingsJson) {
allTrainingsTable.appendChild(currentTrainingRowElement);
});
})
.catch(err => console.log(err));
.catch(err => logWrapper(err));
}

const REF_PAGE_COUNT = document.getElementById('ref-page-count');
Expand Down
2 changes: 1 addition & 1 deletion app/static/js/show_all_trainings_filters.js
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ function createFilter(filterCode, initialValues = "") {
*/
function removeAllFiltersUI() {
for (const key of Object.keys(currentFilters)) {
// console.log($("#" + key + "-filter"))
// logWrapper($("#" + key + "-filter"))
$("#" + key + "-filter").remove();
}
}
Expand Down
4 changes: 2 additions & 2 deletions app/static/js/training_statistics.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ function configureAudio(info) {
if (this.currentTime > info[info.length-1])
setPage(info.length, info);
changeURLByParam('time', this.currentTime.toFixed(1));
console.log(this.currentTime);
logWrapper(this.currentTime);
}
)
}
Expand Down Expand Up @@ -114,7 +114,7 @@ function setCriteriaResults(s) {
}

function setRecognizedInfo(slides){
console.log(slides)
logWrapper(slides)
}

function renderPageButtons(info){
Expand Down
2 changes: 1 addition & 1 deletion app/static/js/upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ function fileLoadingOnChange() {
const file = $("#file-loading").prop("files")[0];
let parts = file.name.split(".");
let extension = parts.pop().toLowerCase();
console.log(`File extension ${extension}`)
logWrapper(`File extension ${extension}`)
/* TODO: use list with user-allowed extensions */
if (parts.length < 1 || !user_formats.includes(extension)) {
$("#alert").show();
Expand Down
30 changes: 15 additions & 15 deletions app/static/js/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,24 @@ function buildTitleRow(columns) {
return titleRowElement;
}

function recheck(trainingId){
function recheck(trainingId) {
fetch('/api/sessions/admin')
.then(response => response.json())
.then(res => {
if (res.admin) {
fetch(`/api/trainings/${trainingId}/`, {method: "POST"})
.then(response => response.json())
.then(innerResponseJson => {
if (innerResponseJson["message"] === "OK") {
window.open(`/trainings/statistics/${trainingId}/`);
//location.href = `/trainings/statistics/${trainingId}/`;
}
});
}
});
.then(response => response.json())
.then(res => {
if (res.admin) {
fetch(`/api/trainings/${trainingId}/`, { method: "POST" })
.then(response => response.json())
.then(innerResponseJson => {
if (innerResponseJson["message"] === "OK") {
window.open(`/trainings/statistics/${trainingId}/`);
//location.href = `/trainings/statistics/${trainingId}/`;
}
});
}
});
}

function strtobool(val, onError= false) {
function strtobool(val, onError = false) {
try {
val = val.toLowerCase();
if (['y', 'yes', 't', 'true', 'on', '1'].includes(val)) {
Expand Down
1 change: 1 addition & 0 deletions app/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ <h1>{{ page_title }}</h1>
{% block content %} {% endblock %}
<!--{% include "bug_reports.html" %}-->
{% block footer %} {% include "footer.html" %} {% endblock %}
<script src="{{ url_for('static', filename='js/logWrapper.js') }}" defer></script>
<script src="{{ url_for('static', filename='js/base.js') }}"></script>
</body>

Expand Down
4 changes: 2 additions & 2 deletions app/templates/dumps.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@
window.location.reload();
}
else{
console.log(data["message"]);
logWrapper(data["message"]);
alert('{{ t("Ошибка создания архива.")}}' + '\n' + data["message"])
}
})
.catch(error => {
console.log(error);
logWrapper(error);
alert('{{ t("Ошибка создания архива.") + t("Попробуйте позже или обратитесь к администратору") }}')
});
})
Expand Down