diff --git a/evennia/server/evennia_launcher.py b/evennia/server/evennia_launcher.py index 5e2dc065c2..a9fc76e767 100644 --- a/evennia/server/evennia_launcher.py +++ b/evennia/server/evennia_launcher.py @@ -489,7 +489,7 @@ def print_info(portal_info_dict, server_info_dict): info = pstr + ("\n\n" + sstr if sstr else "") maxwidth = max(len(line) for line in info.split("\n")) - top_border = "-" * (maxwidth - 11) + " Evennia " + "--" + top_border = "-" * (maxwidth - 11) + " Evennia " + "---" border = "-" * (maxwidth + 1) print(top_border + "\n" + info + '\n' + border) diff --git a/evennia/server/portal/amp_server.py b/evennia/server/portal/amp_server.py index 98e93e7a24..ed51b8952a 100644 --- a/evennia/server/portal/amp_server.py +++ b/evennia/server/portal/amp_server.py @@ -35,6 +35,10 @@ class AMPServerFactory(protocol.ServerFactory): """ noisy = False + def logPrefix(self): + "How this is named in logs" + return "AMP" + def __init__(self, portal): """ Initialize the factory. This is called as the Portal service starts. @@ -282,7 +286,7 @@ class AMPServerProtocol(amp.AMPMultiConnectionProtocol): _, server_connected, _, _, _, _ = self.get_status() - logger.log_msg("Evennia Launcher->Portal operation %s received" % (ord(operation))) + # logger.log_msg("Evennia Launcher->Portal operation %s received" % (ord(operation))) if operation == amp.SSTART: # portal start #15 # first, check if server is already running diff --git a/evennia/server/portal/portal.py b/evennia/server/portal/portal.py index edd71e163c..db054c0e36 100644 --- a/evennia/server/portal/portal.py +++ b/evennia/server/portal/portal.py @@ -14,6 +14,8 @@ import os from twisted.application import internet, service from twisted.internet import protocol, reactor +from twisted.python.log import ILogObserver + import django django.setup() from django.conf import settings @@ -23,6 +25,7 @@ evennia._init() from evennia.utils.utils import get_evennia_version, mod_import, make_iter from evennia.server.portal.portalsessionhandler import PORTAL_SESSIONS +from evennia.utils import logger from evennia.server.webserver import EvenniaReverseProxyResource from django.db import connection @@ -180,6 +183,11 @@ class Portal(object): # what to execute from. application = service.Application('Portal') +# custom logging +logfile = logger.WeeklyLogFile(os.path.basename(settings.PORTAL_LOG_FILE), + os.path.dirname(settings.PORTAL_LOG_FILE)) +application.setComponent(ILogObserver, logger.PortalLogObserver(logfile).emit) + # The main Portal server program. This sets up the database # and is where we store all the other services. PORTAL = Portal(application) @@ -219,7 +227,7 @@ if TELNET_ENABLED: ifacestr = "-%s" % interface for port in TELNET_PORTS: pstring = "%s:%s" % (ifacestr, port) - factory = protocol.ServerFactory() + factory = telnet.TelnetServerFactory() factory.noisy = False factory.protocol = telnet.TelnetProtocol factory.sessionhandler = PORTAL_SESSIONS @@ -242,7 +250,7 @@ if SSL_ENABLED: ifacestr = "-%s" % interface for port in SSL_PORTS: pstring = "%s:%s" % (ifacestr, port) - factory = protocol.ServerFactory() + factory = ssl.SSLServerFactory() factory.noisy = False factory.sessionhandler = PORTAL_SESSIONS factory.protocol = ssl.SSLProtocol @@ -313,7 +321,12 @@ if WEBSERVER_ENABLED: if w_interface not in ('0.0.0.0', '::') or len(WEBSERVER_INTERFACES) > 1: w_ifacestr = "-%s" % interface port = WEBSOCKET_CLIENT_PORT - factory = protocol.ServerFactory() + + class Websocket(protocol.ServerFactory): + "Only here for better naming in logs" + pass + + factory = Websocket() factory.noisy = False factory.protocol = webclient.WebSocketClient factory.sessionhandler = PORTAL_SESSIONS @@ -325,6 +338,7 @@ if WEBSERVER_ENABLED: INFO_DICT["webclient"].append(webclientstr) web_root = Website(web_root, logPath=settings.HTTP_LOG_FILE) + web_root.is_portal = True proxy_service = internet.TCPServer(proxyport, web_root, interface=interface) diff --git a/evennia/server/portal/ssh.py b/evennia/server/portal/ssh.py index 7dde511637..3920c795d9 100644 --- a/evennia/server/portal/ssh.py +++ b/evennia/server/portal/ssh.py @@ -39,7 +39,7 @@ from twisted.conch.ssh import common from twisted.conch.insults import insults from twisted.conch.manhole_ssh import TerminalRealm, _Glue, ConchFactory from twisted.conch.manhole import Manhole, recvline -from twisted.internet import defer +from twisted.internet import defer, protocol from twisted.conch import interfaces as iconch from twisted.python import components from django.conf import settings @@ -59,6 +59,15 @@ CTRL_BACKSLASH = '\x1c' CTRL_L = '\x0c' +# not used atm +class SSHServerFactory(protocol.ServerFactory): + "This is only to name this better in logs" + noisy = False + + def logPrefix(self): + return "SSH" + + class SshProtocol(Manhole, session.Session): """ Each account connecting over ssh gets this protocol assigned to diff --git a/evennia/server/portal/ssl.py b/evennia/server/portal/ssl.py index 8b638ed23d..c2c6284c93 100644 --- a/evennia/server/portal/ssl.py +++ b/evennia/server/portal/ssl.py @@ -7,6 +7,7 @@ from __future__ import print_function import os import sys +from twisted.internet import protocol try: import OpenSSL from twisted.internet import ssl as twisted_ssl @@ -50,6 +51,14 @@ example (linux, using the openssl program): """ +class SSLServerFactory(protocol.ServerFactory): + "This is only to name this better in logs" + noisy = False + + def logPrefix(self): + return "SSL" + + class SSLProtocol(TelnetProtocol): """ Communication is the same as telnet, except data transfer diff --git a/evennia/server/portal/telnet.py b/evennia/server/portal/telnet.py index a1877d15ee..357b20c81b 100644 --- a/evennia/server/portal/telnet.py +++ b/evennia/server/portal/telnet.py @@ -8,6 +8,7 @@ sessions etc. """ import re +from twisted.internet import protocol from twisted.internet.task import LoopingCall from twisted.conch.telnet import Telnet, StatefulTelnetProtocol from twisted.conch.telnet import IAC, NOP, LINEMODE, GA, WILL, WONT, ECHO, NULL @@ -26,6 +27,14 @@ _RE_SCREENREADER_REGEX = re.compile(r"%s" % settings.SCREENREADER_REGEX_STRIP, r _IDLE_COMMAND = settings.IDLE_COMMAND + "\n" +class TelnetServerFactory(protocol.ServerFactory): + "This is only to name this better in logs" + noisy = False + + def logPrefix(self): + return "Telnet" + + class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session): """ Each player connecting over telnet (ie using most traditional mud diff --git a/evennia/server/server.py b/evennia/server/server.py index 3830f3c84a..1ce422d19b 100644 --- a/evennia/server/server.py +++ b/evennia/server/server.py @@ -16,6 +16,7 @@ from twisted.web import static from twisted.application import internet, service from twisted.internet import reactor, defer from twisted.internet.task import LoopingCall +from twisted.python.log import ILogObserver import django django.setup() @@ -32,6 +33,7 @@ from evennia.server.models import ServerConfig from evennia.server import initial_setup from evennia.utils.utils import get_evennia_version, mod_import, make_iter +from evennia.utils import logger from evennia.comms import channelhandler from evennia.server.sessionhandler import SESSIONS @@ -531,6 +533,11 @@ ServerConfig.objects.conf("server_starting_mode", True) # what to execute from. application = service.Application('Evennia') +# custom logging +logfile = logger.WeeklyLogFile(os.path.basename(settings.PORTAL_LOG_FILE), + os.path.dirname(settings.PORTAL_LOG_FILE)) +application.setComponent(ILogObserver, logger.ServerLogObserver(logfile).emit) + # The main evennia server program. This sets up the database # and is where we store all the other services. EVENNIA = Evennia(application) @@ -577,6 +584,7 @@ if WEBSERVER_ENABLED: web_root = WEB_PLUGINS_MODULE.at_webserver_root_creation(web_root) web_site = Website(web_root, logPath=settings.HTTP_LOG_FILE) + web_site.is_portal = False INFO_DICT["webserver"] = "" for proxyport, serverport in WEBSERVER_PORTS: diff --git a/evennia/server/webserver.py b/evennia/server/webserver.py index 260b38071d..b1912bf120 100644 --- a/evennia/server/webserver.py +++ b/evennia/server/webserver.py @@ -212,6 +212,12 @@ class Website(server.Site): """ noisy = False + def logPrefix(self): + "How to be named in logs" + if hasattr(self, "is_portal") and self.is_portal: + return "Webserver-proxy" + return "Webserver" + def log(self, request): """Conditional logging""" if _DEBUG: diff --git a/evennia/utils/logger.py b/evennia/utils/logger.py index a8bcfb00e7..f288f533d6 100644 --- a/evennia/utils/logger.py +++ b/evennia/utils/logger.py @@ -20,6 +20,7 @@ import time from datetime import datetime from traceback import format_exc from twisted.python import log, logfile +from twisted.python import util as twisted_util from twisted.internet.threads import deferToThread @@ -29,6 +30,58 @@ _TIMEZONE = None _CHANNEL_LOG_NUM_TAIL_LINES = None +class WeeklyLogFile(logfile.DailyLogFile): + """ + Log file that rotates once per week + + """ + day_rotation = 7 + + def shouldRotate(self): + """Rotate when the date has changed since last write""" + # all dates here are tuples (year, month, day) + now = self.toDate() + then = self.lastDate + return now[0] > then[0] or now[1] > then[1] or now[2] > (then[2] + self.day_rotation) + + def write(self, data): + "Write data to log file" + logfile.BaseLogFile.write(self, data) + self.lastDate = max(self.lastDate, self.toDate()) + + +class PortalLogObserver(log.FileLogObserver): + """ + Reformat logging + """ + timeFormat = None + prefix = '[P]' + + def emit(self, eventDict): + """ + Copied from Twisted parent, to change logging output + + """ + text = log.textFromEventDict(eventDict) + if text is None: + return + + timeStr = self.formatTime(eventDict["time"]) + if timeStr.startswith("20"): + timeStr = timeStr[2:] + fmtDict = { + "text": text.replace("\n", "\n\t")} + + msgStr = log._safeFormat("%(text)s\n", fmtDict) + + twisted_util.untilConcludes(self.write, timeStr + " %s " % self.prefix + msgStr) + twisted_util.untilConcludes(self.flush) + + +class ServerLogObserver(PortalLogObserver): + prefix = "|S|" + + def timeformat(when=None): """ This helper function will format the current time in the same