Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ There's several steps to getting this working:

**1. Gunicorn deployment**:

The `prometheus_multiproc_dir` environment variable must be set to a directory
The `PROMETHEUS_MULTIPROC_DIR` environment variable must be set to a directory
Comment thread
marcaurele marked this conversation as resolved.
Outdated
that the client library can use for metrics. This directory must be wiped
between Gunicorn runs (before startup is recommended).

Expand Down
2 changes: 1 addition & 1 deletion prometheus_client/multiprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def _parse_key(key):
# the file is missing
continue
raise
for key, value, pos in file_values:
for key, value, _ in file_values:
metric_name, name, labels, labels_key = _parse_key(key)

metric = metrics.get(metric_name)
Expand Down
8 changes: 6 additions & 2 deletions prometheus_client/values.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import os
from threading import Lock
import warnings

from .mmap_dict import mmap_key, MmapedDict

Expand Down Expand Up @@ -64,7 +65,7 @@ def __reset(self):
file_prefix = typ
if file_prefix not in files:
filename = os.path.join(
os.environ['prometheus_multiproc_dir'],
os.environ.get('PROMETHEUS_MULTIPROC_DIR'),
Comment thread
marcaurele marked this conversation as resolved.
'{0}_{1}.db'.format(file_prefix, pid['value']))

files[file_prefix] = MmapedDict(filename)
Expand Down Expand Up @@ -108,7 +109,10 @@ def get_value_class():
# This needs to be chosen before the first metric is constructed,
# and as that may be in some arbitrary library the user/admin has
# no control over we use an environment variable.
if 'prometheus_multiproc_dir' in os.environ:
if 'prometheus_multiproc_dir' in os.environ and 'PROMETHEUS_MULTIPROC_DIR' not in os.environ:
os.environ['PROMETHEUS_MULTIPROC_DIR'] = os.environ['prometheus_multiproc_dir']
warnings.warn("You should declare the env variable in upper case PROMETHEUS_MULTIPROC_DIR'", DeprecationWarning)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks like I left a comment about the warnings in the overall comment instead of a specific one.

My inclination is to allow either lower or upper case without any deprecation warnings as both are valid. Do you have any concerns with just allowing either?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I would like to encourage people to use the upper case to follow standard practice in Unix env variables. If we don't put that in the readme, we don't say anything in the code to promote the use of the uppercase I don't see how people will move to that variable name in upper case.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

That seems reasonable, let's keep the deprecation notice. I do plan to merge your README change after I do a release with this change as well.

if 'PROMETHEUS_MULTIPROC_DIR' in os.environ:
return MultiProcessValue()
else:
return MutexValue
Expand Down
45 changes: 37 additions & 8 deletions tests/test_multiprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import shutil
import sys
import tempfile
import warnings

from prometheus_client import mmap_dict, values
from prometheus_client.core import (
Expand All @@ -13,7 +14,9 @@
from prometheus_client.multiprocess import (
mark_process_dead, MultiProcessCollector,
)
from prometheus_client.values import MultiProcessValue, MutexValue
from prometheus_client.values import (
get_value_class, MultiProcessValue, MutexValue,
)

if sys.version_info < (2, 7):
# We need the skip decorators from unittest2 on Python 2.6.
Expand All @@ -22,10 +25,36 @@
import unittest


class TestMultiProcess(unittest.TestCase):
class TestMultiProcessDeprecation(unittest.TestCase):
def setUp(self):
self.tempdir = tempfile.mkdtemp()

def tearDown(self):
del os.environ['prometheus_multiproc_dir']
del os.environ['PROMETHEUS_MULTIPROC_DIR']
shutil.rmtree(self.tempdir)

def test_deprecation_warning(self):
os.environ['prometheus_multiproc_dir'] = self.tempdir
with warnings.catch_warnings(record=True) as w:
get_value_class()
assert os.environ['PROMETHEUS_MULTIPROC_DIR'] == self.tempdir
assert len(w) == 1
assert issubclass(w[-1].category, DeprecationWarning)
assert "PROMETHEUS_MULTIPROC_DIR" in str(w[-1].message)

def test_both_variables_priority(self):
os.environ['prometheus_multiproc_dir'] = 'should not be picked'
os.environ['PROMETHEUS_MULTIPROC_DIR'] = self.tempdir
with warnings.catch_warnings(record=True) as w:
get_value_class()
assert len(w) == 0


class TestMultiProcess(unittest.TestCase):
def setUp(self):
self.tempdir = tempfile.mkdtemp()
os.environ['PROMETHEUS_MULTIPROC_DIR'] = self.tempdir
values.ValueClass = MultiProcessValue(lambda: 123)
self.registry = CollectorRegistry()
self.collector = MultiProcessCollector(self.registry, self.tempdir)
Expand All @@ -35,7 +64,7 @@ def _value_class(self):
return

def tearDown(self):
del os.environ['prometheus_multiproc_dir']
del os.environ['PROMETHEUS_MULTIPROC_DIR']
shutil.rmtree(self.tempdir)
values.ValueClass = MutexValue

Expand Down Expand Up @@ -80,7 +109,7 @@ def test_gauge_all(self):
self.assertEqual(0, self.registry.get_sample_value('g', {'pid': '456'}))
g1.set(1)
g2.set(2)
mark_process_dead(123, os.environ['prometheus_multiproc_dir'])
mark_process_dead(123, os.environ['PROMETHEUS_MULTIPROC_DIR'])
self.assertEqual(1, self.registry.get_sample_value('g', {'pid': '123'}))
self.assertEqual(2, self.registry.get_sample_value('g', {'pid': '456'}))

Expand All @@ -94,7 +123,7 @@ def test_gauge_liveall(self):
g2.set(2)
self.assertEqual(1, self.registry.get_sample_value('g', {'pid': '123'}))
self.assertEqual(2, self.registry.get_sample_value('g', {'pid': '456'}))
mark_process_dead(123, os.environ['prometheus_multiproc_dir'])
mark_process_dead(123, os.environ['PROMETHEUS_MULTIPROC_DIR'])
self.assertEqual(None, self.registry.get_sample_value('g', {'pid': '123'}))
self.assertEqual(2, self.registry.get_sample_value('g', {'pid': '456'}))

Expand Down Expand Up @@ -124,7 +153,7 @@ def test_gauge_livesum(self):
g1.set(1)
g2.set(2)
self.assertEqual(3, self.registry.get_sample_value('g'))
mark_process_dead(123, os.environ['prometheus_multiproc_dir'])
mark_process_dead(123, os.environ['PROMETHEUS_MULTIPROC_DIR'])
self.assertEqual(2, self.registry.get_sample_value('g'))

def test_namespace_subsystem(self):
Expand All @@ -151,7 +180,7 @@ def test_initialization_detects_pid_change(self):
# can not inspect the files cache directly, as it's a closure, so we
# check for the actual files themselves
def files():
fs = os.listdir(os.environ['prometheus_multiproc_dir'])
fs = os.listdir(os.environ['PROMETHEUS_MULTIPROC_DIR'])
fs.sort()
return fs

Expand Down Expand Up @@ -240,7 +269,7 @@ def add_label(key, value):
pid = 1
h.labels(**labels).observe(5)

path = os.path.join(os.environ['prometheus_multiproc_dir'], '*.db')
path = os.path.join(os.environ['PROMETHEUS_MULTIPROC_DIR'], '*.db')
files = glob.glob(path)
metrics = dict(
(m.name, m) for m in self.collector.merge(files, accumulate=False)
Expand Down