139 lines
3.6 KiB
Python
139 lines
3.6 KiB
Python
import os
|
|
import datetime
|
|
import json
|
|
import hashlib
|
|
import subprocess
|
|
import logging
|
|
import logging.handlers
|
|
import threading
|
|
|
|
|
|
from .utils import b_str
|
|
|
|
mutex = threading.Lock()
|
|
|
|
|
|
class MyFileHandler(logging.handlers.TimedRotatingFileHandler):
|
|
def __init__(self, filename):
|
|
super().__init__(filename, when="midnight", utc=True)
|
|
|
|
def rotate(self, source, dest):
|
|
super().rotate(source, dest)
|
|
|
|
if os.path.exists(dest):
|
|
subprocess.Popen(["bzip2", dest])
|
|
|
|
|
|
class Tracker:
|
|
def __init__(self, logger, geoip, service, userName, userIP, clientID, userSalt):
|
|
self.__logger = logger
|
|
self.__userName = userName
|
|
self.__userSalt = userSalt
|
|
self.__logged = False
|
|
|
|
if userName:
|
|
userID = int(
|
|
hashlib.md5(b_str(userSalt + userName.lower())).hexdigest()[:8], 16
|
|
)
|
|
else:
|
|
userID = int(hashlib.md5(b_str(userSalt + userIP)).hexdigest()[:8], 16)
|
|
|
|
self.__data = {
|
|
"service": service,
|
|
"userID": userID,
|
|
"clientID": clientID,
|
|
"userEmail": None,
|
|
"auth": bool(userName),
|
|
"userLocation": {},
|
|
"created": f"{datetime.datetime.utcnow().isoformat()}Z",
|
|
}
|
|
|
|
if geoip:
|
|
self.__data["userLocation"]["country"] = geoip.country_code_by_addr(userIP)
|
|
|
|
if (
|
|
userName and userName.lower().endswith("@gfz-potsdam.de")
|
|
) or userIP.startswith("139.17."):
|
|
self.__data["userLocation"]["institution"] = "GFZ"
|
|
|
|
# pylint: disable=W0613
|
|
def line_status(
|
|
self,
|
|
start_time,
|
|
end_time,
|
|
network,
|
|
station,
|
|
channel,
|
|
location,
|
|
restricted,
|
|
net_class,
|
|
shared,
|
|
constraints,
|
|
volume,
|
|
status,
|
|
size,
|
|
message,
|
|
):
|
|
try:
|
|
trace = self.__data["trace"]
|
|
|
|
except KeyError:
|
|
trace = []
|
|
self.__data["trace"] = trace
|
|
|
|
trace.append(
|
|
{
|
|
"net": network,
|
|
"sta": station,
|
|
"loc": location,
|
|
"cha": channel,
|
|
"start": start_time.iso(),
|
|
"end": end_time.iso(),
|
|
"restricted": restricted,
|
|
"status": status,
|
|
"bytes": size,
|
|
}
|
|
)
|
|
|
|
if restricted and status == "OK":
|
|
self.__data["userEmail"] = self.__userName
|
|
|
|
# FDSNWS requests have one volume, so volume_status() is called once per request
|
|
def volume_status(self, volume, status, size, message):
|
|
self.__data["status"] = status
|
|
self.__data["bytes"] = size
|
|
self.__data["finished"] = f"{datetime.datetime.utcnow().isoformat()}Z"
|
|
|
|
def request_status(self, status, message):
|
|
with mutex:
|
|
if not self.__logged:
|
|
self.__logger.info(json.dumps(self.__data))
|
|
self.__logged = True
|
|
|
|
|
|
class RequestLog:
|
|
def __init__(self, filename, userSalt):
|
|
self.__logger = logging.getLogger("seiscomp.fdsnws.reqlog")
|
|
self.__logger.addHandler(MyFileHandler(filename))
|
|
self.__logger.setLevel(logging.INFO)
|
|
self.__userSalt = userSalt
|
|
|
|
try:
|
|
import GeoIP
|
|
|
|
self.__geoip = GeoIP.new(GeoIP.GEOIP_MEMORY_CACHE)
|
|
|
|
except ImportError:
|
|
self.__geoip = None
|
|
|
|
def tracker(self, service, userName, userIP, clientID):
|
|
return Tracker(
|
|
self.__logger,
|
|
self.__geoip,
|
|
service,
|
|
userName,
|
|
userIP,
|
|
clientID,
|
|
self.__userSalt,
|
|
)
|