Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/common/core/constants.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
DEFAULT_PROMETHEUS_MULTIPROC_DIR = "/tmp/flagsmith-prometheus"
DEFAULT_PROMETHEUS_MULTIPROC_DIR_NAME = "flagsmith-prometheus"
18 changes: 4 additions & 14 deletions src/common/core/main.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import contextlib
import logging
import os
import shutil
import sys
import typing

Expand All @@ -10,7 +9,7 @@
)

from common.core.cli import healthcheck
from common.core.constants import DEFAULT_PROMETHEUS_MULTIPROC_DIR
from common.prometheus.multiprocessing import prepare_prom_multiproc_dir

logger = logging.getLogger(__name__)

Expand All @@ -35,6 +34,9 @@ def ensure_cli_env() -> typing.Generator[None, None, None]:

# TODO @khvn26 Move logging setup to here

# Prometheus multiproc support
prepare_prom_multiproc_dir()

# Currently we don't install Flagsmith modules as a package, so we need to add
# $CWD to the Python path to be able to import them
sys.path.append(os.getcwd())
Expand All @@ -43,18 +45,6 @@ def ensure_cli_env() -> typing.Generator[None, None, None]:
# without resorting to it being set outside of the application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings.dev")

# Set up Prometheus' multiprocess mode
prometheus_multiproc_dir_name = os.environ.setdefault(
"PROMETHEUS_MULTIPROC_DIR",
DEFAULT_PROMETHEUS_MULTIPROC_DIR,
)
shutil.rmtree(prometheus_multiproc_dir_name, ignore_errors=True)
os.makedirs(prometheus_multiproc_dir_name, exist_ok=True)
logger.info(
"Re-created %s for Prometheus multi-process mode",
prometheus_multiproc_dir_name,
)

if "docgen" in sys.argv:
os.environ["DOCGEN_MODE"] = "true"

Expand Down
17 changes: 15 additions & 2 deletions src/common/prometheus/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
from common.prometheus.utils import Histogram
from typing import Any

__all__ = ("Histogram",)
_utils = ("Histogram",)


def __getattr__(name: str) -> Any:
"""
Since utils imports django.conf.settings, we lazy load any objects that
we want to import to prevent django.core.exceptions.ImproperlyConfigured
due to settings not being configured.
"""
if name in _utils:
from common.prometheus import utils

return getattr(utils, name)
raise AttributeError(name)
Comment on lines -1 to +16
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is pretty ugly, but might actually save us pain in the future, as well as fixing the pain I experienced. There are a couple of alternatives:

  1. In utils.py, use a factory instead of subclassing Histogram, and perform a local import of django.conf.settings
  2. Take a slightly different approach and just split up the logical pieces of prepare_prom_multiproc_dir into generic functions where necessary like clear_sub_dirs(dir: str), and just call it step by step in ensure_cli_env

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've implemented option 2 in #120

36 changes: 36 additions & 0 deletions src/common/prometheus/multiprocessing.py
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't love that this code can't live in utils itself, but see comment in __init__.py for reasoning.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps the more logical answer here would be to move Histogram out of utils and keep this function in there?

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import os
import pathlib
import shutil
from tempfile import gettempdir

from common.core.constants import DEFAULT_PROMETHEUS_MULTIPROC_DIR_NAME


def prepare_prom_multiproc_dir() -> None:
prom_dir = pathlib.Path(
os.environ.setdefault(
"PROMETHEUS_MULTIPROC_DIR",
os.path.join(gettempdir(), DEFAULT_PROMETHEUS_MULTIPROC_DIR_NAME),
)
)

if prom_dir.exists():
for p in prom_dir.rglob("*"):
try:
# Ensure that the cleanup doesn't silently fail on
# files and subdirs created by other users.
p.chmod(0o777)
except Exception: # pragma: no cover
pass

shutil.rmtree(prom_dir, ignore_errors=True)

prom_dir.mkdir(parents=True, exist_ok=True)

# While `mkdir` sets mode=0o777 by default, this can be affected by umask resulting in
# lesser permissions for other users. This step ensures the directory is writable for
# all users.
try:
prom_dir.chmod(0o777)
except PermissionError:
pass
2 changes: 1 addition & 1 deletion src/task_processor/processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ def _run_task(
"result": result.lower(),
}

timer.labels(**labels) # type: ignore[no-untyped-call]
timer.labels(**labels)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really know why mypy pulled me up on this in this PR given that I've not touched this file, or any related code...

ctx.close()

metrics.flagsmith_task_processor_finished_tasks_total.labels(**labels).inc()
Expand Down