Skip to content

Commit

Permalink
Add logging system
Browse files Browse the repository at this point in the history
  • Loading branch information
Gustry committed Jun 5, 2024
1 parent 64f4783 commit ba278eb
Show file tree
Hide file tree
Showing 3 changed files with 189 additions and 0 deletions.
12 changes: 12 additions & 0 deletions wfsOutputExtension/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
__license__ = 'GPL version 3'
__email__ = '[email protected]'

from wfsOutputExtension.logging import Logger
from wfsOutputExtension.plausible import Plausible


# noinspection PyPep8Naming
def classFactory(iface):
Expand Down Expand Up @@ -39,6 +42,15 @@ class WfsOutputExtensionServer:

def __init__(self, server_iface):
self.serverIface = server_iface
self.logger = Logger()

# noinspection PyBroadException
try:
self.plausible = Plausible()
self.plausible.request_stat_event()
except Exception as e:
self.logger.log_exception(e)
self.logger.critical('Error while calling the API stats')

from .wfs_filter import WFSFilter # NOQA ABS101
server_iface.registerFilter(WFSFilter(server_iface), 50)
Expand Down
133 changes: 133 additions & 0 deletions wfsOutputExtension/plausible.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
__copyright__ = 'Copyright 2024, 3Liz'
__license__ = 'GPL version 3'
__email__ = '[email protected]'

import json
import os
import platform

from qgis.core import Qgis, QgsNetworkAccessManager
from qgis.PyQt.QtCore import QByteArray, QDateTime, QUrl
from qgis.PyQt.QtNetwork import QNetworkReply, QNetworkRequest

from wfsOutputExtension.logging import Logger
from wfsOutputExtension.tools import to_bool, version

MIN_SECONDS = 3600
ENV_SKIP_STATS = "3LIZ_SKIP_STATS"

PLAUSIBLE_DOMAIN_PROD = "plugin.server.lizmap.com"
PLAUSIBLE_URL_PROD = "https://bourbon.3liz.com/api/event"

PLAUSIBLE_DOMAIN_TEST = PLAUSIBLE_DOMAIN_PROD
PLAUSIBLE_URL_TEST = "https://plausible.snap.3liz.net/api/event"


# For testing purpose, to test.
# Similar to QGIS dashboard https://feed.qgis.org/metabase/public/dashboard/df81071d-4c75-45b8-a698-97b8649d7228
# We only collect data listed in the list below
# and the country according to IP address.
# The IP is not stored by Plausible Community Edition https://github.com/plausible/analytics
# Plausible is GDPR friendly https://plausible.io/data-policy
# The User-Agent is set by QGIS Desktop itself

class Plausible:

def __init__(self):
""" Constructor. """
self.previous_date = None

def request_stat_event(self) -> bool:
""" Request to send an event to the API. """
if to_bool(os.getenv(ENV_SKIP_STATS), default_value=False):
# Disabled by environment variable
return False

if to_bool(os.getenv("CI"), default_value=False):
# If running on CI, do not send stats
return False

current = QDateTime().currentDateTimeUtc()
if self.previous_date and self.previous_date.secsTo(current) < MIN_SECONDS:
# Not more than one request per hour
# It's done at plugin startup anyway
return False

if self._send_stat_event():
self.previous_date = current
return True

return False

@staticmethod
def _send_stat_event() -> bool:
""" Send stats event to the API. """
# Only turn ON for debug purpose, temporary !
debug = False
extra_debug = False

plugin_version = version()
if plugin_version in ('master', 'dev'):
# Dev versions of the plugin, it's a kind of debug
debug = True

plausible_url = PLAUSIBLE_URL_TEST if debug else PLAUSIBLE_URL_PROD

is_lizcloud = "lizcloud" in os.getenv("QGIS_SERVER_APPLICATION_NAME", "").lower()
if is_lizcloud:
plausible_domain = os.getenv("QGIS_SERVER_PLAUSIBLE_DOMAIN_NAME", PLAUSIBLE_DOMAIN_PROD)
else:
plausible_domain = PLAUSIBLE_DOMAIN_TEST if debug else PLAUSIBLE_DOMAIN_PROD

request = QNetworkRequest()
# noinspection PyArgumentList
request.setUrl(QUrl(plausible_url))
if extra_debug:
request.setRawHeader(b"X-Debug-Request", b"true")
request.setRawHeader(b"X-Forwarded-For", b"127.0.0.1")
request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json")

# Qgis.QGIS_VERSION → 3.34.6-Prizren
# noinspection PyUnresolvedReferences
qgis_version_full = Qgis.QGIS_VERSION.split('-')[0]
# qgis_version_full → 3.34.6
qgis_version_branch = '.'.join(qgis_version_full.split('.')[0:2])
# qgis_version_branch → 3.34

python_version_full = platform.python_version()
# python_version_full → 3.10.12
python_version_branch = '.'.join(python_version_full.split('.')[0:2])
# python_version_branch → 3.10

data = {
"name": "wfsOutputExtension-server",
"props": {
# Plugin version
"plugin-version": plugin_version,
# QGIS
"qgis-version-full": qgis_version_full,
"qgis-version-branch": qgis_version_branch,
# Python
"python-version-full": python_version_full,
"python-version-branch": python_version_branch,
# OS
"os-name": platform.system(),
},
"url": plausible_url,
"domain": plausible_domain,
}

# noinspection PyArgumentList
r: QNetworkReply = QgsNetworkAccessManager.instance().post(request, QByteArray(str.encode(json.dumps(data))))
if not is_lizcloud:
return True

logger = Logger()
message = (
f"Request HTTP OS process '{os.getpid()}' sent to '{plausible_url}' with domain '{plausible_domain} : ")
if r.error() == QNetworkReply.NoError:
logger.info(message + "OK")
else:
logger.warning("{} {}".format(message, r.error()))

return True
44 changes: 44 additions & 0 deletions wfsOutputExtension/tools.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
__copyright__ = 'Copyright 2024, 3Liz'
__license__ = 'GPL version 3'
__email__ = '[email protected]'

import configparser

from pathlib import Path
from typing import Dict, Tuple, Union

from qgis.core import Qgis, QgsMessageLog

from atlasprint.logger import Logger


def version() -> str:
""" Returns the Lizmap current version. """
file_path = Path(__file__).parent.joinpath('metadata.txt')
config = configparser.ConfigParser()
try:
config.read(file_path, encoding='utf8')
except UnicodeDecodeError:
# Issue LWC https://github.com/3liz/lizmap-web-client/issues/1908
# Maybe a locale issue ?
# Do not use logger here, circular import
# noinspection PyTypeChecker
QgsMessageLog.logMessage(
"Error, an UnicodeDecodeError occurred while reading the metadata.txt. Is the locale "
"correctly set on the server ?",
"WfsOutputExtension", Qgis.Critical)
return 'NULL'
else:
return config["general"]["version"]


def to_bool(val: Union[str, int, float, bool], default_value: bool = True) -> bool:
""" Convert config value to boolean """
if isinstance(val, str):
# For string, compare lower value to True string
return val.lower() in ('yes', 'true', 't', '1')
elif not val:
# For value like False, 0, 0.0, None, empty list or dict returns False
return False
else:
return default_value

0 comments on commit ba278eb

Please sign in to comment.