Removed crappy logger and replaced it with a sane built in logging logger

This commit is contained in:
Kevin F 2022-09-27 17:21:00 +00:00
parent 2eea681e98
commit e9efffff34
61 changed files with 307 additions and 851 deletions

View File

@ -1,12 +0,0 @@
# Incomplete List of Contributors
Onionr is created by a team of hard working volunteers.
In no order of importance, these people make Onionr happen:
* [Beardog (Kevin Froman)](https://www.chaoswebs.net/) - Project founder, owner and core developer
* [InvisaMage](https://invisamage.com/) - Web UI Bulma design
* [Arinerron](https://arinerron.com/) - Logger and config modules, testing and other contributions
* [Anhar Ismail](https://github.com/anharismail) - Created Onionr's logo
+ Other contributors and testers

View File

@ -64,6 +64,8 @@ def sigusr_stacktrace(signum, frame):
signal.signal(signal.SIGUSR1, sigusr_stacktrace)
# Importing initailzes logging
from logger import log as logging
ran_as_script = False
if __name__ == "__main__": ran_as_script = True

View File

@ -2,7 +2,7 @@ from typing import Set
from onionrblocks import Block
import logger
from logger import log as logging
from .deleteblock import delete_block
from .getblocks import get_blocks_after_timestamp
@ -18,7 +18,7 @@ def clean_block_database():
Block(block.id, block.raw, auto_verify=True)
except ValueError: # block expired
remove_set.add(block)
if len(remove_set):
logger.info(f"Cleaning {len(remove_set)} blocks", terminal=True)
logging.info(f"Cleaning {len(remove_set)} blocks")
[i for i in map(delete_block, remove_set)]

View File

@ -6,7 +6,7 @@ import os
from json import JSONDecodeError
import ujson as json
import logger
from logger import log as logging
import filepaths
"""
@ -106,7 +106,7 @@ def save():
with open(get_config_file(), 'w', encoding="utf8") as configfile:
json.dump(get_config(), configfile, indent=2)
except JSONDecodeError:
logger.warn('Failed to write to configuration file.')
logging.warn('Failed to write to configuration file.')
def reload():
@ -117,7 +117,7 @@ def reload():
set_config(json.loads(configfile.read()))
except (FileNotFoundError, JSONDecodeError) as e:
pass
#logger.debug('Failed to parse configuration file.')
#logging.debug('Failed to parse configuration file.')
def get_config():

View File

@ -1,6 +1,7 @@
import threading
from time import sleep
from typing import TYPE_CHECKING, Set, Tuple
from logger import log as logging
if TYPE_CHECKING:
from ordered_set import OrderedSet
@ -11,7 +12,6 @@ if TYPE_CHECKING:
from onionrthreads import add_onionr_thread
import onionrplugins
import logger
from .connectpeer import connect_peer
from .client import start_gossip_client
@ -56,4 +56,4 @@ def start_gossip_threads():
sleep(60)
if len(gossip_peer_set):
return
logger.error("Could not connect to any peers :(", terminal=True)
logging.error("Could not connect to any peers :(")

View File

@ -21,7 +21,7 @@ if TYPE_CHECKING:
from ..peer import Peer
from ordered_set import OrderedSet
import logger
from logger import log as logging
import config
import onionrplugins
from ..commands import GossipCommands
@ -61,20 +61,20 @@ def block_queue_processing():
while not len(gossip_peer_set):
sleep(1)
if dandelion_phase.remaining_time() <= 15:
#logger.debug("Sleeping", terminal=True)
#logging.debug("Sleeping")
sleep(dandelion_phase.remaining_time())
if dandelion_phase.is_stem_phase() and config.get('security.dandelion.enabled', True):
logger.debug("Entering stem phase", terminal=True)
logging.debug("Entering stem phase")
try:
# Stem out blocks for (roughly) remaining epoch time
asyncio.run(stem_out(dandelion_phase))
except TimeoutError:
pass
except Exception:
logger.error(traceback.format_exc(), terminal=True)
logging.error(traceback.format_exc())
pass
else:
#logger.debug("Entering fluff phase", terminal=True)
#logging.debug("Entering fluff phase")
# Add block to primary block db, where the diffuser can read it
sleep(0.1)
store_blocks(dandelion_phase)

View File

@ -5,7 +5,7 @@ from typing import TYPE_CHECKING
if TYPE_CHECKING:
from .. import Peer
import logger
from logger import log as logging
import onionrplugins
from ..commands import GossipCommands, command_to_byte
@ -28,7 +28,7 @@ def do_announce():
sock.sendall(command_to_byte(GossipCommands.ANNOUNCE))
sock.sendall(our_transport_address)
if int.from_bytes(sock.recv(1), 'big') != 1:
logger.warn(
logging.warn(
f"Could not announce with {announce_peer.transport_address}")
sock.close()

View File

@ -11,7 +11,7 @@ from ordered_set import OrderedSet
import config
from onionrthreads import add_delayed_thread
from blockdb import add_block_to_db
import logger
from logger import log as logging
from ...constants import BLACKHOLE_EVADE_TIMER_SECS, OUTBOUND_DANDELION_EDGES
from ...commands import GossipCommands, command_to_byte
@ -45,9 +45,9 @@ async def _setup_edge(
try:
s = peer.get_socket(12)
except TimeoutError:
logger.debug(f"{peer.transport_address} timed out when trying stemout")
logging.debug(f"{peer.transport_address} timed out when trying stemout")
except Exception:
logger.debug(traceback.format_exc())
logging.debug(traceback.format_exc())
return
try:
@ -56,18 +56,18 @@ async def _setup_edge(
if s.recv(1) == dandelion.StemAcceptResult.DENY:
raise StemConnectionDenied
except TimeoutError:
logger.debug(
"Peer timed out when establishing stem connection", terminal=True)
logger.debug(traceback.format_exc())
logging.debug(
"Peer timed out when establishing stem connection")
logging.debug(traceback.format_exc())
except StemConnectionDenied:
logger.debug(
logging.debug(
"Stem connection denied (peer has too many) " +
f"{peer.transport_address}")
logger.debug(traceback.format_exc())
logging.debug(traceback.format_exc())
except Exception:
logger.warn(
logging.warn(
"Error asking peer to establish stem connection" +
traceback.format_exc(), terminal=True)
traceback.format_exc())
else:
# Return peer socket if it is in stem reception mode successfully
return s
@ -113,10 +113,10 @@ async def stem_out(d_phase: 'DandelionPhase'):
await _setup_edge(gossip_peer_set, tried_edges))
except NotEnoughEdges:
# No possible edges at this point (edges < OUTBOUND_DANDELION_EDGE)
#logger.debug(
#logging.debug(
# "Making too few edges for stemout " +
# "this is bad for anonymity if frequent.",
# terminal=True)
# )
if strict_dandelion:
not_enough_edges = True
else:
@ -133,10 +133,10 @@ async def stem_out(d_phase: 'DandelionPhase'):
else:
# Ran out of time for stem phase
if not d_phase.is_stem_phase() or d_phase.remaining_time() < 5:
logger.error(
logging.error(
"Did not stem out any blocks in time, " +
"if this happens regularly you may be under attack",
terminal=False)
)
for s in peer_sockets:
if s:
s.close()
@ -155,7 +155,7 @@ async def stem_out(d_phase: 'DandelionPhase'):
except Empty:
pass
except Exception:
logger.warn(traceback.format_exc())
logging.warn(traceback.format_exc())
else:
# stream routine exited early
pass

View File

@ -4,7 +4,7 @@ from queue import Empty
from typing import TYPE_CHECKING
import logger
from logger import log as logging
from ...constants import BLOCK_ID_SIZE, BLOCK_MAX_SIZE, BLOCK_SIZE_LEN
if TYPE_CHECKING:
@ -22,7 +22,7 @@ async def do_stem_stream(
remaining_time = d_phase.remaining_time()
my_phase_id = d_phase.phase_id
while remaining_time > 1 and my_phase_id == d_phase.phase_id:
# Primary client component that communicate's with gossip.server.acceptstem
remaining_time = d_phase.remaining_time()
@ -35,7 +35,7 @@ async def do_stem_stream(
await sleep(1)
else:
break
logger.info("Sending block over dandelion++", terminal=True)
logging.info("Sending block over dandelion++")
block_size = str(len(bl.raw)).zfill(BLOCK_SIZE_LEN)
def _send_it():

View File

@ -6,7 +6,7 @@ if TYPE_CHECKING:
from socket import socket
from onionrplugins import onionrevents
import logger
from logger import log as logging
from socks import GeneralProxyError
@ -23,9 +23,9 @@ def _do_ask_peer(peer):
try:
_ask_peer(peer)
except TimeoutError:
logger.debug("Timed out when asking for new peers")
logging.debug("Timed out when asking for new peers")
except Exception:
logger.error(format_exc(), terminal=True)
logging.error(format_exc())
def _ask_peer(peer):
s: 'socket' = peer.get_socket(12)
@ -46,14 +46,14 @@ def _ask_peer(peer):
'address': peer,
'callback': connectpeer.connect_peer
}
#logger.info("Got new peer from exchange " + peer.decode('utf-8'), terminal=True)
#logging.info("Got new peer from exchange " + peer.decode('utf-8'))
onionrevents.event('announce_rec', data=connect_data, threaded=True)
s.close()
def get_new_peers():
if not len(gossip_peer_set):
logger.debug("Peer set empty, cannot get new peers")
logging.debug("Peer set empty, cannot get new peers")
return
# Deep copy the peer list

View File

@ -22,7 +22,7 @@ if TYPE_CHECKING:
from ordered_set import OrderedSet
import logger
from logger import log as logging
import onionrblocks
from ...peerset import gossip_peer_set
@ -71,7 +71,7 @@ def stream_from_peers():
need_socket_lock.release()
return
except Exception:
logger.warn(traceback.format_exc(), terminal=True)
logging.warn(traceback.format_exc())
need_socket_lock.release()
return
try:
@ -83,7 +83,7 @@ def stream_from_peers():
while stream_times >= stream_counter:
stream_counter += 1
#logger.debug("Reading block of id in stream with " + peer.transport_address, terminal=True)
#logging.debug("Reading block of id in stream with " + peer.transport_address)
sock.settimeout(5)
block_id = sock.recv(BLOCK_ID_SIZE)
if blockdb.has_block(block_id):
@ -91,12 +91,12 @@ def stream_from_peers():
continue
sock.sendall(int(1).to_bytes(1, 'big'))
#logger.debug("Reading block size in stream", terminal=True)
#logging.debug("Reading block size in stream")
sock.settimeout(5)
block_size = int(sock.recv(BLOCK_SIZE_LEN))
if block_size > BLOCK_MAX_SIZE or block_size <= 0:
logger.warn(
logging.warn(
f"Peer {peer.transport_address} " +
"reported block size out of range")
break
@ -104,9 +104,9 @@ def stream_from_peers():
sock.settimeout(5)
block_data = sock.recv(block_size)
#logger.debug(
#logging.debug(
# "We got a block from stream, assuming it is valid",
# terminal=True)
# )
try:
blockdb.add_block_to_db(
onionrblocks.Block(
@ -120,10 +120,10 @@ def stream_from_peers():
sock.sendall(int(1).to_bytes(1, 'big'))
except (BrokenPipeError, TimeoutError, ConnectionError) as e:
pass
#logger.debug(f"{e} when streaming from peers", terminal=True)
#logger.debug(traceback.format_exc())
#logging.debug(f"{e} when streaming from peers")
#logging.debug(traceback.format_exc())
except Exception:
logger.warn(traceback.format_exc(), terminal=True)
logging.warn(traceback.format_exc())
finally:
sock.close()
need_socket_lock.release()

View File

@ -2,7 +2,7 @@ import traceback
from gossip.commands import GossipCommands, command_to_byte
from .peerset import gossip_peer_set
import logger
from logger import log as logging
def connect_peer(peer):
@ -11,12 +11,12 @@ def connect_peer(peer):
try:
s = peer.get_socket(120)
except Exception:
logger.warn(f"Could not connect to {peer.transport_address}")
logger.warn(traceback.format_exc())
logging.warn(f"Could not connect to {peer.transport_address}")
logging.warn(traceback.format_exc())
else:
with s:
s.sendall(command_to_byte(GossipCommands.PING))
if s.recv(4).decode('utf-8') == 'PONG':
gossip_peer_set.add(peer)
logger.info(f"connected to {peer.transport_address}", terminal=True)
logging.info(f"connected to {peer.transport_address}")

View File

@ -12,7 +12,7 @@ from gossip import constants
from ..connectpeer import connect_peer
from onionrplugins import onionrevents
import logger
from logger import log as logging
if TYPE_CHECKING:
from onionrblocks import Block
@ -88,9 +88,9 @@ def gossip_server():
try:
await diffuse_blocks(reader, writer)
except Exception:
logger.warn(
logging.warn(
f"Err streaming blocks\n{traceback.format_exc()}",
terminal=True)
)
case GossipCommands.PUT_BLOCKS:
# Pick block queue & append stemmed blocks to it
try:
@ -99,18 +99,18 @@ def gossip_server():
inbound_dandelion_edge_count)
except asyncio.exceptions.TimeoutError:
pass
logger.debug(
logging.debug(
"Inbound edge timed out when steming blocks to us",
terminal=True)
)
except asyncio.exceptions.IncompleteReadError:
pass
logger.debug(
logging.debug(
"Inbound edge timed out (Incomplete Read) when steming blocks to us",
terminal=True)
)
except Exception:
logger.warn(
logging.warn(
f"Err accepting stem blocks\n{traceback.format_exc()}",
terminal=True)
)
# Subtract dandelion edge, make sure >=0
inbound_dandelion_edge_count[0] = \
max(inbound_dandelion_edge_count[0] - 1, 0)

View File

@ -5,7 +5,7 @@ from asyncio import wait_for
from onionrblocks import Block
import logger
from logger import log as logging
from ..dandelion import StemAcceptResult
from ..constants import BLOCK_ID_SIZE, BLOCK_SIZE_LEN, BLOCK_MAX_SIZE
from ..constants import MAX_INBOUND_DANDELION_EDGE, MAX_STEM_BLOCKS_PER_STREAM
@ -35,13 +35,13 @@ async def accept_stem_blocks(
for _ in range(MAX_STEM_BLOCKS_PER_STREAM):
read_routine = reader.readexactly(BLOCK_ID_SIZE)
#logger.debug(f"Reading block id in stem server", terminal=True)
#logging.debug(f"Reading block id in stem server")
block_id = await wait_for(read_routine, base_wait_timeout)
block_id = block_id.decode('utf-8')
if not block_id:
break
#logger.debug(f"Reading block size in stem server", terminal=True)
#logging.debug(f"Reading block size in stem server")
block_size = (await wait_for(
reader.readexactly(BLOCK_SIZE_LEN),
base_wait_timeout)).decode('utf-8')
@ -54,14 +54,14 @@ async def accept_stem_blocks(
if block_size > BLOCK_MAX_SIZE:
raise ValueError("Max block size")
#logger.debug(f"Reading block of size {block_size} in stem server", terminal=True)
#logging.debug(f"Reading block of size {block_size} in stem server")
raw_block: bytes = await wait_for(
reader.readexactly(block_size), base_wait_timeout * 6)
if not raw_block:
break
logger.debug("Got a stem block, put into queue", terminal=True)
logging.debug("Got a stem block, put into queue")
block_queue_to_use.put(
Block(block_id, raw_block, auto_verify=True)
)

View File

@ -19,7 +19,7 @@ if TYPE_CHECKING:
from ..constants import BLOCK_MAX_SIZE, BLOCK_SIZE_LEN
from ..constants import BLOCK_STREAM_OFFSET_DIGITS
import logger
from logger import log as logging
import blockdb
from blockdb import get_blocks_after_timestamp, block_storage_observers
"""
@ -103,5 +103,5 @@ async def diffuse_blocks(reader: 'StreamReader', writer: 'StreamWriter'):
except ConnectionResetError:
pass
except Exception:
logger.warn(traceback.format_exc(), terminal=True)
logging.warn(traceback.format_exc())

View File

@ -1,71 +1,91 @@
'''
Onionr - Private P2P Communication
"""
Onionr - Private P2P Communication
This file handles all operations involving logging
'''
'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
We use built in logging but with a custom formatter for colors and such
"""
import logging
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
from filepaths import log_file
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
import sys, traceback
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
from . import colors, readline, log, raw, confirm, colors, settings
colors = colors.Colors
readline = readline.readline
log = log.log
raw = raw.raw
confirm = confirm.confirm
# credit: https://stackoverflow.com/a/384076
# license: https://creativecommons.org/licenses/by-sa/4.0/
class ConsoleFormatter(logging.Formatter):
# debug: when there is info that could be useful for debugging purposes only
def debug(data: str, error = None, timestamp = True, prompt = True, terminal = False, level = settings.LEVEL_DEBUG):
if settings.get_level() <= level:
log('/', data, timestamp = timestamp, prompt = prompt, terminal = terminal)
if not error is None:
debug('Error: ' + str(error) + parse_error())
grey = "\x1b[38;20m"
green = "\x1b[38;5;82m"
yellow = "\x1b[33;20m"
red = "\x1b[31;20m"
bold_red = "\x1b[31;1m"
reset = "\x1b[0m"
format_default = "%(levelname)s - %(message)s (%(filename)s:%(lineno)d)"
format_info = "%(message)s - (%(filename)s:%(lineno)d)"
# info: when there is something to notify the user of, such as the success of a process
def info(data: str, timestamp = False, prompt = True, terminal = False, level = settings.LEVEL_INFO):
if settings.get_level() <= level:
log('+', data, colors.fg.green, timestamp = timestamp, prompt = prompt, terminal = terminal)
FORMATS = {
logging.DEBUG: grey + format_default + reset,
logging.INFO: green + format_info + reset,
logging.WARNING: yellow + format_default + reset,
logging.ERROR: red + format_default + reset,
logging.CRITICAL: bold_red + format_default + reset
}
# warn: when there is a potential for something bad to happen
def warn(data: str, error = None, timestamp = True, prompt = True, terminal = False, level = settings.LEVEL_WARN):
if not error is None:
debug('Error: ' + str(error) + parse_error())
if settings.get_level() <= level:
log('!', data, colors.fg.orange, timestamp = timestamp, prompt = prompt, terminal = terminal)
def format(self, record):
log_fmt = self.FORMATS.get(record.levelno)
formatter = logging.Formatter(log_fmt)
return formatter.format(record)
# error: when only one function, module, or process of the program encountered a problem and must stop
def error(data: str, error = None, timestamp = True, prompt = True, terminal = False, level = settings.LEVEL_ERROR):
if settings.get_level() <= level:
log('-', data, colors.fg.red, timestamp = timestamp, fd = sys.stderr, prompt = prompt, terminal = terminal)
if not error is None:
debug('Error: ' + str(error) + parse_error())
class FileFormatter(logging.Formatter):
# fatal: when the something so bad has happened that the program must stop
def fatal(data: str, error = None, timestamp=True, prompt = True, terminal = False, level = settings.LEVEL_FATAL):
if not error is None:
debug('Error: ' + str(error) + parse_error(), terminal = terminal)
if settings.get_level() <= level:
log('#', data, colors.bg.red + colors.fg.green + colors.bold, timestamp = timestamp, fd = sys.stderr, prompt = prompt, terminal = terminal)
# returns a formatted error message
def parse_error():
details = traceback.extract_tb(sys.exc_info()[2])
output = ''
format_default = "%(levelname)s - %(message)s (%(filename)s:%(lineno)d)"
format_info = "%(message)s - (%(filename)s:%(lineno)d)"
for line in details:
output += '\n ... module %s in %s:%i' % (line[2], line[0], line[1])
FORMATS = {
logging.DEBUG: format_default,
logging.INFO: format_info,
logging.WARNING: format_default,
logging.ERROR: format_default,
logging.CRITICAL: format_default
}
return output
def format(self, record):
log_fmt = self.FORMATS.get(record.levelno)
formatter = logging.Formatter(log_fmt)
return formatter.format(record)
#logging.basicConfig(level=logging.ERROR, format='%(message)s ')
log = logging.getLogger('onionr')
log.setLevel(logging.INFO)
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
ch.setFormatter(ConsoleFormatter())
def enable_file_logging():
fh = logging.FileHandler(log_file)
fh.setLevel(logging.INFO)
fh.setFormatter(FileFormatter())
log.addHandler(fh)
def disable_console_logging():
log.removeHandler(ch)
def enable_console_logging():
log.addHandler(ch)
enable_console_logging()

View File

@ -1,60 +0,0 @@
'''
Onionr - Private P2P Communication
class to access ANSI control codes
'''
'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
import re
class Colors:
'''
This class allows you to set the color if ANSI codes are supported
'''
reset='\033[0m'
bold='\033[01m'
disable='\033[02m'
underline='\033[04m'
reverse='\033[07m'
strikethrough='\033[09m'
invisible='\033[08m'
italics='\033[3m'
class fg:
black='\033[30m'
red='\033[31m'
green='\033[32m'
orange='\033[33m'
blue='\033[34m'
purple='\033[35m'
cyan='\033[36m'
lightgrey='\033[37m'
darkgrey='\033[90m'
lightred='\033[91m'
lightgreen='\033[92m'
yellow='\033[93m'
lightblue='\033[94m'
pink='\033[95m'
lightcyan='\033[96m'
class bg:
black='\033[40m'
red='\033[41m'
green='\033[42m'
orange='\033[43m'
blue='\033[44m'
purple='\033[45m'
cyan='\033[46m'
lightgrey='\033[47m'
@staticmethod
def filter(data):
return re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]').sub('', str(data))

View File

@ -1,54 +0,0 @@
'''
Onionr - Private P2P Communication
confirm y/n cli prompt
'''
'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
import sys
from . import colors, settings
colors = colors.Colors
def confirm(default = 'y', message = 'Are you sure %s? '):
'''
Displays an "Are you sure" message, returns True for Y and False for N
message: The confirmation message, use %s for (y/n)
default: which to prefer-- y or n
'''
color = colors.fg.green + colors.bold
default = default.lower()
confirm = colors.bold
if default.startswith('y'):
confirm += '(Y/n)'
else:
confirm += '(y/N)'
confirm += colors.reset + color
output = colors.reset + str(color) + '... ' + colors.reset + str(message) + colors.reset
if not get_settings() & settings.USE_ANSI:
output = colors.filter(output)
sys.stdout.write(output.replace('%s', confirm))
inp = input().lower()
if 'y' in inp:
return True
if 'n' in inp:
return False
else:
return default == 'y'

View File

@ -1,38 +0,0 @@
'''
Onionr - Private P2P Communication
god log function
'''
'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
import sys, time
from . import colors, raw, settings
colors = colors.Colors
def log(prefix, data, color = '', timestamp=True, fd = sys.stdout, prompt = True, terminal = False):
'''
Logs the data
prefix : The prefix to the output
data : The actual data to output
color : The color to output before the data
'''
curTime = ''
if timestamp:
curTime = time.strftime("%m-%d %H:%M:%S") + ' '
output = colors.reset + str(color) + ('[' + colors.bold + str(prefix) + colors.reset + str(color) + '] ' if prompt is True else '') + curTime + str(data) + colors.reset
if not settings.get_settings() & settings.USE_ANSI:
output = colors.filter(output)
raw.raw(output, fd = fd, terminal = terminal)

View File

@ -1,54 +0,0 @@
"""Onionr - Private P2P Communication.
Output raw data to file or terminal
"""
import sys
import os
from . import settings, colors
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
colors = colors.Colors
def raw(data, fd = sys.stdout, terminal = False):
"""
Outputs raw data to console without formatting
"""
if terminal and (settings.get_settings() & settings.OUTPUT_TO_CONSOLE):
try:
ts = fd.write('%s\n' % data)
except OSError:
pass
if settings.get_settings() & settings.OUTPUT_TO_FILE:
fdata = ''
try:
for _ in range(5):
try:
with open(settings._outputfile, 'r') as file:
fdata = file.read()
except UnicodeDecodeError:
pass
else:
break
except FileNotFoundError:
pass
fdata = fdata + '\n' + data
fdata = fdata.split('\n')
if len(fdata) >= settings.MAX_LOG_FILE_LINES:
fdata.pop(0)
fdata = '\n'.join(fdata)
with open(settings._outputfile, 'w') as file:
file.write(fdata)

View File

@ -1,37 +0,0 @@
'''
Onionr - Private P2P Communication
get a line of input from stdin
'''
'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
import sys
from . import colors, settings
colors = colors.Colors
def readline(message = ''):
'''
Takes in input from the console, not stored in logs
message: The message to display before taking input
'''
color = colors.fg.green + colors.bold
output = colors.reset + str(color) + '... ' + colors.reset + str(message) + colors.reset
if not settings.get_settings() & settings.USE_ANSI:
output = colors.filter(output)
sys.stdout.write(output)
return input()

View File

@ -1,89 +0,0 @@
'''
Onionr - Private P2P Communication
logger settings
'''
'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
import os
from utils import identifyhome
import filepaths
data_home = os.environ.get('ONIONR_LOG_DIR', identifyhome.identify_home())
# Use the bitwise operators to merge these settings
USE_ANSI = 0b100
if os.name == 'nt':
USE_ANSI = 0b000
OUTPUT_TO_CONSOLE = 0b010
OUTPUT_TO_FILE = 0b001
LEVEL_DEBUG = 1
LEVEL_INFO = 2
LEVEL_WARN = 3
LEVEL_ERROR = 4
LEVEL_FATAL = 5
LEVEL_IMPORTANT = 6
MAX_LOG_FILE_LINES = 10000
_type = OUTPUT_TO_CONSOLE | USE_ANSI # the default settings for logging
_level = LEVEL_DEBUG # the lowest level to log
# the file to log to
_outputfile = filepaths.log_file
def set_settings(type):
'''
Set the settings for the logger using bitwise operators
'''
global _type
_type = type
def get_settings():
'''
Get settings from the logger
'''
return _type
def set_level(level):
'''
Set the lowest log level to output
'''
global _level
_level = level
def get_level()->int:
'''
Get the lowest log level currently being outputted
'''
return _level
def set_file(outputfile):
'''
Set the file to output to, if enabled
'''
global _outputfile
_outputfile = outputfile
def get_file():
'''
Get the file to output to
'''
return _outputfile

View File

@ -8,13 +8,14 @@ import sys
import platform
import signal
from threading import Thread
from logger import log as logging
from logger import enable_file_logging
import filenuke
import psutil
import config
import logger
from onionrplugins import onionrevents as events
from utils import identifyhome
@ -59,16 +60,19 @@ def delete_run_files():
_safe_remove(filepaths.pid_file)
def _show_info_messages():
version.version(verbosity=5, function=logger.info)
logger.debug('Python version %s' % platform.python_version())
version.version(verbosity=5, function=logging.info)
logging.debug('Python version %s' % platform.python_version())
if onionrvalues.DEVELOPMENT_MODE:
logger.warn('Development mode enabled', timestamp=False, terminal=True)
logging.warn('Development mode enabled')
def daemon():
"""Start Onionr's primary threads for communicator, API server, node, and LAN."""
if config.get('log.file.output', False):
enable_file_logging()
def _handle_sig_term(signum, frame):
sys.exit(0)
@ -83,8 +87,8 @@ def daemon():
security_level = config.get('general.security_level', 1)
_show_info_messages()
logger.info(
f"Onionr daemon is running under pid {os.getpid()}", terminal=True)
logging.info(
f"Onionr daemon is running under pid {os.getpid()}")
events.event('init', threaded=False)
events.event('afterinit', threaded=False)
events.event('daemon_start')
@ -117,33 +121,25 @@ def start(override: bool = False):
Error exit if there is and its not overridden
"""
if os.path.exists(filepaths.lock_file) and not override:
if os.path.exists(filepaths.restarting_indicator):
try:
os.remove(filepaths.restarting_indicator)
except FileNotFoundError:
pass
else:
return
with open(filepaths.lock_file, 'r') as lock_file:
try:
proc = psutil.Process(int(lock_file.read())).name()
except psutil.NoSuchProcess:
proc = ""
if not proc.startswith("python"):
logger.warn(
f"Detected stale run file, deleting {filepaths.lock_file}",
terminal=True)
logging.warn(
f"Detected stale run file, deleting {filepaths.lock_file}")
try:
os.remove(filepaths.lock_file)
except FileNotFoundError:
pass
start(override=True)
return
logger.fatal('Cannot start. Daemon is already running,'
logging.error('Cannot start. Daemon is already running,'
+ ' or it did not exit cleanly.\n'
+ ' (if you are sure that there is not a daemon running,'
+ f' delete {filepaths.lock_file} & try again).',
terminal=True)
)
else:
if not onionrvalues.DEVELOPMENT_MODE:
lock_file = open(filepaths.lock_file, 'w')

View File

@ -6,7 +6,7 @@ import os
from signal import SIGTERM
from filepaths import pid_file
import logger
from logger import log as logging
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -29,9 +29,9 @@ def kill_daemon():
with open(pid_file, 'r') as pid:
os.kill(int(pid.read()), SIGTERM)
except FileNotFoundError:
logger.error("Daemon not running/pid file missing")
logger.warn('Stopping the running daemon, if one exists...', timestamp=False,
terminal=True)
logging.error("Daemon not running/pid file missing")
logging.warn('Stopping the running daemon, if one exists...', timestamp=False,
)
kill_daemon.onionr_help = "Gracefully stops the " # type: ignore

View File

@ -5,11 +5,12 @@ Show nice logo
import os
import config
import logger
from .quotes import QUOTE
from utils.boxprint import bordered
from utils import logoheader
from utils import readstatic
import onionrvalues
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -25,28 +26,34 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def header():
if onionrvalues.DEVELOPMENT_MODE:
return
pink_ansi = '\033[95m'
green_ansi = '\033[92m'
reset_ansi = '\x1b[0m'
logo = readstatic.read_static('header.txt', ret_bin=False)
logo = logo.replace('P', pink_ansi).replace('G', green_ansi).replace('W', reset_ansi)
print(reset_ansi + logo)
def show_logo():
logger.raw('', terminal=True)
try:
terminal_size = os.get_terminal_size().columns
except OSError: # Generally thrown if not in terminal
terminal_size = 120
# print nice header thing :)
if config.get('general.display_header', True):
logoheader.header("")
header()
if terminal_size >= 120:
if QUOTE[1]: # If there is an author to show for the quote
logger.info(
"\u001b[33m\033[F" + bordered(QUOTE[0] + '\n -' + QUOTE[1]),
terminal=True)
print("\u001b[33m\033[F" + bordered(QUOTE[0] + '\n -' + QUOTE[1]))
else:
logger.info(
"\u001b[33m\033[F" + bordered(QUOTE[0]), terminal=True)
print("\u001b[33m\033[F" + bordered(QUOTE[0]))
else:
if QUOTE[1]:
logger.info("\u001b[33m\033[F" + QUOTE[0] + '\n -' + QUOTE[1],
terminal=True)
print("\u001b[33m\033[F" + QUOTE[0] + '\n -' + QUOTE[1])
else:
logger.info("\u001b[33m\033[F" + QUOTE[0], terminal=True)
print("\u001b[33m\033[F" + QUOTE[0])

View File

@ -1,141 +0,0 @@
"""Onionr - Private P2P Communication.
This module defines commands to show stats/details about the local node
"""
import os
import logger
from utils import sizeutils, getconsolewidth, identifyhome
import config
import onionrvalues
from filepaths import lock_file
import psutil
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def _is_running():
script = onionrvalues.SCRIPT_NAME
if os.path.isfile(lock_file):
for process in psutil.process_iter():
if process.name() == script:
return True
return False
def show_stats():
"""Print/log statistic info about our Onionr install."""
try:
# define stats messages here
home = identifyhome.identify_home()
messages = {
# info about local client
# This line is inaccurate if dev mode is enabled
'Onionr Daemon Status':
((logger.colors.fg.green + 'Online') \
if _is_running() \
else logger.colors.fg.red + 'Offline'),
# file and folder size stats
'div1': True, # this creates a solid line across the screen, a div
'Total Block Size':
sizeutils.human_size(sizeutils.size(home + 'blocks.db')),
'Total Plugin Size':
sizeutils.human_size(sizeutils.size(home + 'plugins/')),
'Log File Size':
sizeutils.human_size(sizeutils.size(home + 'output.log')),
# count stats
'div2': True,
'Enabled Plugins':
str(len(config.get('plugins.enabled', list()))) + ' / ' +
str(len(os.listdir(home + 'plugins/')))
}
# color configuration
colors = {
'title': logger.colors.bold,
'key': logger.colors.fg.lightgreen,
'val': logger.colors.fg.green,
'border': logger.colors.fg.lightblue,
'reset': logger.colors.reset
}
# pre-processing
maxlength = 0
width = getconsolewidth.get_console_width()
for key, val in messages.items():
if not (type(val) is bool and val is True):
maxlength = max(len(key), maxlength)
prewidth = maxlength + len(' | ')
groupsize = width - prewidth - len('[+] ')
# generate stats table
logger.info(colors['title'] + 'Onionr v%s Statistics' %
onionrvalues.ONIONR_VERSION + colors['reset'],
terminal=True)