Skip to content

Commit

Permalink
Add logging to InfluxDB
Browse files Browse the repository at this point in the history
  • Loading branch information
Xarthisius committed Jan 10, 2025
1 parent cf5ce1f commit 5c153e8
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 9 deletions.
21 changes: 17 additions & 4 deletions girder_wholetale/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import jsonschema
import six
import validators
from girder import events
from girder import auditLogger, events
from girder.api import access
from girder.api.describe import Description, autoDescribeRoute, describeRoute
from girder.api.rest import RestException, boundHandler, loadmodel
Expand Down Expand Up @@ -52,9 +52,9 @@
from .lib.path_mapper import PathMapper
from .models.instance import Instance as InstanceModel
from .models.lock import Lock as LockModel
from .models.version_hierarchy import VersionHierarchyModel
from .models.session import Session as SessionModel
from .models.transfer import Transfer as TransferModel
from .models.version_hierarchy import VersionHierarchyModel
from .rest.account import Account
from .rest.dataset import Dataset
from .rest.dm import DM
Expand All @@ -77,6 +77,7 @@
external_auth_providers_schema,
repository_to_provider_schema,
)
from .utils import add_influx_handler

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -231,6 +232,10 @@ def _validateLogo(doc):
PluginSettings.CONTACT_HREF,
PluginSettings.BUG_HREF,
PluginSettings.MOUNTS,
PluginSettings.INFLUXDB_URL,
PluginSettings.INFLUXDB_TOKEN,
PluginSettings.INFLUXDB_ORG,
PluginSettings.INFLUXDB_BUCKET,
}
)
def validateHref(doc):
Expand Down Expand Up @@ -807,6 +812,7 @@ def load(self, info):

pathMapper = PathMapper()
from .lib.transfer_manager import SimpleTransferManager

transferManager = SimpleTransferManager(pathMapper)

# a GC that does nothing
Expand All @@ -825,7 +831,10 @@ def load(self, info):
LRUSortingScheme(),
),
)
from .lib.cache_manager import SimpleCacheManager # Needs models to be registered
from .lib.cache_manager import (
SimpleCacheManager,
)

cacheManager = SimpleCacheManager(
Setting(), transferManager, fileGC, pathMapper
)
Expand Down Expand Up @@ -964,7 +973,11 @@ def sessionDeleted(event):
metricsLogger.setLevel(logging.INFO)
metricsLogger.addHandler(_MetricsHandler())
VersionHierarchyModel().resetCrashedCriticalSections()

if Setting().get(PluginSettings.INFLUXDB_BUCKET):
add_influx_handler(

Check warning on line 977 in girder_wholetale/__init__.py

View check run for this annotation

Codecov / codecov/patch

girder_wholetale/__init__.py#L977

Added line #L977 was not covered by tests
auditLogger,
Setting().get(PluginSettings.INFLUXDB_BUCKET),
)
registerPluginStaticContent(
plugin="wholetale",
css=["/style.css"],
Expand Down
8 changes: 8 additions & 0 deletions girder_wholetale/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ class PluginSettings:
GC_RUN_INTERVAL = "dm.gc_run_interval"
GC_COLLECT_START_FRACTION = "dm.gc_collect_start_fraction"
GC_COLLECT_END_FRACTION = "dm.gc_collect_end_fraction"
INFLUXDB_URL = "wholetale.influxdb_url"
INFLUXDB_TOKEN = "wholetale.influxdb_token"
INFLUXDB_ORG = "wholetale.influxdb_org"
INFLUXDB_BUCKET = "wholetale.influxdb_bucket"


SettingDefault.defaults.update(
Expand Down Expand Up @@ -165,6 +169,10 @@ class PluginSettings:
PluginSettings.RUNS_DIRS_ROOT: "/tmp/wt/runs-dirs",
PluginSettings.VERSIONS_DIRS_ROOT: "/tmp/wt/versions-dirs",
PluginSettings.DAV_SERVER: False,
PluginSettings.INFLUXDB_URL: "http://images.local.xarthisius.xyz:8086",
PluginSettings.INFLUXDB_TOKEN: "",
PluginSettings.INFLUXDB_ORG: "my_org",
PluginSettings.INFLUXDB_BUCKET: "",
}
)

Expand Down
100 changes: 95 additions & 5 deletions girder_wholetale/utils.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,108 @@
import os
import datetime
import json
import logging
import os
import pathlib
import six.moves.urllib as urllib
from urllib.parse import quote_plus

from girder.utility.model_importer import ModelImporter
try:
import influxdb_client as influxdb
except ImportError:
influxdb = None

Check warning on line 11 in girder_wholetale/utils.py

View check run for this annotation

Codecov / codecov/patch

girder_wholetale/utils.py#L10-L11

Added lines #L10 - L11 were not covered by tests

import cherrypy
from girder.models.notification import Notification
from girder.models.user import User
from girder.models.setting import Setting
from girder.models.user import User
from girder.utility.model_importer import ModelImporter

from .constants import PluginSettings

NOTIFICATION_EXP_HOURS = 1
WT_EVENT_EXP_SECONDS = int(os.environ.get("GIRDER_WT_EVENT_EXP_SECONDS", 5))


class InfluxHandler(logging.Handler):
def __init__(self, bucket):
if influxdb is None:
raise ImportError("InfluxDB client not installed")

Check warning on line 28 in girder_wholetale/utils.py

View check run for this annotation

Codecov / codecov/patch

girder_wholetale/utils.py#L27-L28

Added lines #L27 - L28 were not covered by tests

super().__init__()
self.client = influxdb.InfluxDBClient(

Check warning on line 31 in girder_wholetale/utils.py

View check run for this annotation

Codecov / codecov/patch

girder_wholetale/utils.py#L30-L31

Added lines #L30 - L31 were not covered by tests
url=Setting().get(PluginSettings.INFLUXDB_URL),
token=Setting().get(PluginSettings.INFLUXDB_TOKEN),
org=Setting().get(PluginSettings.INFLUXDB_ORG),
)
self.write_api = self.client.write_api()
self.bucket = bucket

Check warning on line 37 in girder_wholetale/utils.py

View check run for this annotation

Codecov / codecov/patch

girder_wholetale/utils.py#L36-L37

Added lines #L36 - L37 were not covered by tests

@staticmethod
def _document_create(record):
return (

Check warning on line 41 in girder_wholetale/utils.py

View check run for this annotation

Codecov / codecov/patch

girder_wholetale/utils.py#L41

Added line #L41 was not covered by tests
influxdb.Point("document")
.tag("level", record.levelname)
.field("collection", record.details.get("collection"))
.field("id", str(record.details.get("id")))
.time(int(record.created * 1e9), influxdb.WritePrecision.NS)
)

@staticmethod
def _download(record):
return (

Check warning on line 51 in girder_wholetale/utils.py

View check run for this annotation

Codecov / codecov/patch

girder_wholetale/utils.py#L51

Added line #L51 was not covered by tests
influxdb.Point("download")
.tag("level", record.levelname)
.field("fileId", str(record.details.get("fileId")))
.field("startBytes", record.details.get("startBytes"))
.field("endBytes", record.details.get("endBytes"))
.field("extraParameters", record.details.get("extraParameters"))
.time(int(record.created * 1e9), influxdb.WritePrecision.NS)
)

@staticmethod
def _rest_request(record):
return (

Check warning on line 63 in girder_wholetale/utils.py

View check run for this annotation

Codecov / codecov/patch

girder_wholetale/utils.py#L63

Added line #L63 was not covered by tests
influxdb.Point("rest_request")
.tag("level", record.levelname)
.field("method", record.details.get("method"))
.field("status", record.details.get("status"))
.field("route", "/".join(record.details.get("route", "")))
.field("params", json.dumps(record.details.get("params")))
.field("message", record.getMessage())
.time(int(record.created * 1e9), influxdb.WritePrecision.NS)
)

def emit(self, record):
match record.getMessage():
case "document.create":
point = self._document_create(record)
case "file.download":
point = self._download(record)
case "rest.request":
point = self._rest_request(record)
self.write_api.write(bucket=self.bucket, record=point)

Check warning on line 82 in girder_wholetale/utils.py

View check run for this annotation

Codecov / codecov/patch

girder_wholetale/utils.py#L75-L82

Added lines #L75 - L82 were not covered by tests

def close(self):
self.write_api._write_options.write_scheduler.executor.shutdown(wait=False)
self.write_api.close()
self.client.close()
super().close()

Check warning on line 88 in girder_wholetale/utils.py

View check run for this annotation

Codecov / codecov/patch

girder_wholetale/utils.py#L85-L88

Added lines #L85 - L88 were not covered by tests


def add_influx_handler(logger, bucket):
def stop_influx_client():
for handler in logger.handlers:
if isinstance(handler, InfluxHandler):
logger.removeHandler(handler)
handler.close()

Check warning on line 96 in girder_wholetale/utils.py

View check run for this annotation

Codecov / codecov/patch

girder_wholetale/utils.py#L92-L96

Added lines #L92 - L96 were not covered by tests

stop_influx_client() # Remove any existing handlers
logger.addHandler(InfluxHandler(bucket))
stop_influx_client.priority = 10
cherrypy.engine.subscribe(

Check warning on line 101 in girder_wholetale/utils.py

View check run for this annotation

Codecov / codecov/patch

girder_wholetale/utils.py#L98-L101

Added lines #L98 - L101 were not covered by tests
"stop", stop_influx_client
) # ensure we clean up on restart


def get_tale_dir_root(tale: dict, root_path_setting: str) -> pathlib.Path:
root = Setting().get(root_path_setting)
return pathlib.Path(root) / str(tale["_id"])[0:2] / str(tale["_id"])
Expand Down Expand Up @@ -41,7 +131,7 @@ def esc(value):
:return: The escaped string
:rtype: str
"""
return urllib.parse.quote_plus(value)
return quote_plus(value)

Check warning on line 134 in girder_wholetale/utils.py

View check run for this annotation

Codecov / codecov/patch

girder_wholetale/utils.py#L134

Added line #L134 was not covered by tests


def notify_event(users, event, affectedIds):
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ httpio>=0.3.0
fs
pathvalidate
bdbag
influxdb-client
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"rdflib",
"celery[redis]",
"pathvalidate",
"influxdb-client",
"python-magic",
"requests",
"validators",
Expand Down

0 comments on commit 5c153e8

Please sign in to comment.