Integrated an option to download the monkey island log files from the Log page in the web app.

This commit is contained in:
maor.rayzin 2018-05-30 18:30:56 +03:00
parent 13fa4fa6a4
commit 6aeaf0f857
9 changed files with 802 additions and 410 deletions

View File

@ -14,6 +14,7 @@ from cc.resources.client_run import ClientRun
from cc.resources.edge import Edge
from cc.resources.local_run import LocalRun
from cc.resources.log import Log
from cc.resources.island_logs import IslandLog
from cc.resources.monkey import Monkey
from cc.resources.monkey_configuration import MonkeyConfiguration
from cc.resources.monkey_download import MonkeyDownload
@ -104,5 +105,6 @@ def init_app(mongo_url):
api.add_resource(Report, '/api/report', '/api/report/')
api.add_resource(TelemetryFeed, '/api/telemetry-feed', '/api/telemetry-feed/')
api.add_resource(Log, '/api/log', '/api/log/')
api.add_resource(IslandLog, '/api/log/island/download', '/api/log/island/download/')
return app

View File

@ -1,7 +1,11 @@
import json
import logging
import standard
import aws
logger = logging.getLogger(__name__)
ENV_DICT = {
'standard': standard.StandardEnvironment,
'aws': aws.AwsEnvironment
@ -19,5 +23,5 @@ try:
__env_type = load_env_from_file()
env = ENV_DICT[__env_type]()
except Exception:
print('Failed initializing environment: %s' % __env_type)
logger.error('Failed initializing environment', exc_info=True)
raise

View File

@ -3,6 +3,9 @@ import json
import logging.config
__author__ = 'Maor.Rayzin'
def json_setup_logging(default_path='logging.json', default_level=logging.INFO, env_key='LOG_CFG'):
"""
Setup the logging configuration

View File

@ -38,6 +38,6 @@
"root": {
"level": "INFO",
"handlers": ["console", "info_file_handler", "error_file_handler"]
"handlers": ["console", "info_file_handler"]
}
}

View File

@ -0,0 +1,19 @@
import flask_restful
import logging
from cc.auth import jwt_required
from cc.services.island_logs import IslandLogService
__author__ = "Maor.Rayzin"
logger = logging.getLogger(__name__)
class IslandLog(flask_restful.Resource):
@jwt_required()
def get(self):
try:
return IslandLogService.get_log_file()
except Exception as e:
logger.error('Monkey Island logs failed to download', exc_info=True)

View File

@ -1,4 +1,5 @@
import json
import logging
import traceback
import copy
from datetime import datetime
@ -17,6 +18,9 @@ from cc.encryptor import encryptor
__author__ = 'Barak'
logger = logging.getLogger(__name__)
class Telemetry(flask_restful.Resource):
@jwt_required()
def get(self, **kw):
@ -52,10 +56,9 @@ class Telemetry(flask_restful.Resource):
if telem_type in TELEM_PROCESS_DICT:
TELEM_PROCESS_DICT[telem_type](telemetry_json)
else:
print('Got unknown type of telemetry: %s' % telem_type)
logger.info('Got unknown type of telemetry: %s' % telem_type)
except Exception as ex:
print("Exception caught while processing telemetry: %s" % str(ex))
traceback.print_exc()
logger.error("Exception caught while processing telemetry", exc_info=True)
telem_id = mongo.db.telemetry.insert(telemetry_json)
return mongo.db.telemetry.find_one_or_404({"_id": telem_id})

View File

@ -0,0 +1,32 @@
import logging
__author__ = "Maor.Rayzin"
logger = logging.getLogger(__name__)
class IslandLogService:
def __init__(self):
pass
@staticmethod
def get_log_file():
"""
This static function is a helper function for the monkey island log download function.
It finds the logger handlers and checks if one of them is a fileHandler of any kind by checking if the handler
has the property handler.baseFilename.
:return:
a dict with the log file content.
"""
logger_handlers = logger.parent.handlers
for handler in logger_handlers:
if hasattr(handler, 'baseFilename'):
logger.info('Log file found: {0}'.format(handler.baseFilename))
log_file_path = handler.baseFilename
with open(log_file_path, 'rt') as f:
log_file = f.read()
return {
'log_file': log_file
}
logger.warning('No log file could be found, check logger config.')
return None

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,9 @@
import React from 'react';
import {Col} from 'react-bootstrap';
import {Button, Col} from 'react-bootstrap';
import JSONTree from 'react-json-tree'
import {DataTable} from 'react-data-components';
import AuthComponent from '../AuthComponent';
import download from 'downloadjs'
const renderJson = (val) => <JSONTree data={val} level={1} theme="eighties" invertTheme={true} />;
const renderTime = (val) => val.split('.')[0];
@ -28,21 +29,47 @@ class TelemetryPageComponent extends AuthComponent {
.then(res => this.setState({data: res.objects}));
};
downloadIslandLog = () => {
this.authFetch('/api/log/island/download')
.then(res => res.json())
.then(res => {
let filename = 'Island_log'
let logContent = (res['log_file']);
download(logContent, filename, 'text/plain');
});
};
render() {
return (
<Col xs={12} lg={8}>
<h1 className="page-title">Log</h1>
<div className="data-table-container">
<DataTable
keys="name"
columns={columns}
initialData={this.state.data}
initialPageLength={20}
initialSortBy={{ prop: 'timestamp', order: 'descending' }}
pageLengthOptions={[ 20, 50, 100 ]}
/>
</div>
</Col>
<div>
<div>
<Col xs={12} lg={8}>
<h1 className="page-title">Log</h1>
<div className="data-table-container">
<DataTable
keys="name"
columns={columns}
initialData={this.state.data}
initialPageLength={20}
initialSortBy={{ prop: 'timestamp', order: 'descending' }}
pageLengthOptions={[ 20, 50, 100 ]}
/>
</div>
</Col>
</div>
<div>
<Col xs={12} lg={8}>
<h1 className="page-title"> Monkey Island Logs </h1>
<div className="text-center" style={{marginBottom: '20px'}}>
<p style={{'marginBottom': '2em', 'fontSize': '1.2em'}}> Download Monkey Island internal log file </p>
<Button bsSize="large" onClick={()=> {
this.downloadIslandLog();
}}>
<i className="glyphicon glyphicon-download"/> Download </Button>
</div>
</Col>
</div>
</div>
);
}
}