Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate lower-case 'prometheus_multiproc_dir' #42

Closed
wants to merge 1 commit into from
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
185 changes: 111 additions & 74 deletions docs/instrumentation.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ <h1 class="title">Module <code>prometheus_fastapi_instrumentator.instrumentation
import gzip
import os
import re
import warnings
from timeit import default_timer
from typing import Callable, List, Optional, Pattern, Tuple

Expand Down Expand Up @@ -261,7 +262,7 @@ <h1 class="title">Module <code>prometheus_fastapi_instrumentator.instrumentation
kwargs: Will be passed to FastAPI route annotation.

Raises:
ValueError: If `prometheus_multiproc_dir` env var is found but
ValueError: If `PROMETHEUS_MULTIPROC_DIR` env var is found but
doesn&#39;t point to a valid directory.

Returns:
Expand All @@ -282,14 +283,26 @@ <h1 class="title">Module <code>prometheus_fastapi_instrumentator.instrumentation
multiprocess,
)

if &#34;prometheus_multiproc_dir&#34; in os.environ:
pmd = os.environ[&#34;prometheus_multiproc_dir&#34;]
if (
&#34;prometheus_multiproc_dir&#34; in os.environ
and &#34;PROMETHEUS_MULTIPROC_DIR&#34; not in os.environ
):
os.environ[&#34;PROMETHEUS_MULTIPROC_DIR&#34;] = os.environ[
&#34;prometheus_multiproc_dir&#34;
]
warnings.warn(
&#34;prometheus_multiproc_dir variable has been deprecated in favor of the \
upper case naming PROMETHEUS_MULTIPROC_DIR&#34;,
DeprecationWarning,
)
if &#34;PROMETHEUS_MULTIPROC_DIR&#34; in os.environ:
pmd = os.environ[&#34;PROMETHEUS_MULTIPROC_DIR&#34;]
if os.path.isdir(pmd):
registry = CollectorRegistry()
multiprocess.MultiProcessCollector(registry)
else:
raise ValueError(
f&#34;Env var prometheus_multiproc_dir=&#39;{pmd}&#39; not a directory.&#34;
f&#34;Env var PROMETHEUS_MULTIPROC_DIR=&#39;{pmd}&#39; not a directory.&#34;
)
else:
registry = REGISTRY
Expand Down Expand Up @@ -656,7 +669,7 @@ <h2 id="args">Args</h2>
kwargs: Will be passed to FastAPI route annotation.

Raises:
ValueError: If `prometheus_multiproc_dir` env var is found but
ValueError: If `PROMETHEUS_MULTIPROC_DIR` env var is found but
doesn&#39;t point to a valid directory.

Returns:
Expand All @@ -677,14 +690,26 @@ <h2 id="args">Args</h2>
multiprocess,
)

if &#34;prometheus_multiproc_dir&#34; in os.environ:
pmd = os.environ[&#34;prometheus_multiproc_dir&#34;]
if (
&#34;prometheus_multiproc_dir&#34; in os.environ
and &#34;PROMETHEUS_MULTIPROC_DIR&#34; not in os.environ
):
os.environ[&#34;PROMETHEUS_MULTIPROC_DIR&#34;] = os.environ[
&#34;prometheus_multiproc_dir&#34;
]
warnings.warn(
&#34;prometheus_multiproc_dir variable has been deprecated in favor of the \
upper case naming PROMETHEUS_MULTIPROC_DIR&#34;,
DeprecationWarning,
)
if &#34;PROMETHEUS_MULTIPROC_DIR&#34; in os.environ:
pmd = os.environ[&#34;PROMETHEUS_MULTIPROC_DIR&#34;]
if os.path.isdir(pmd):
registry = CollectorRegistry()
multiprocess.MultiProcessCollector(registry)
else:
raise ValueError(
f&#34;Env var prometheus_multiproc_dir=&#39;{pmd}&#39; not a directory.&#34;
f&#34;Env var PROMETHEUS_MULTIPROC_DIR=&#39;{pmd}&#39; not a directory.&#34;
)
else:
registry = REGISTRY
Expand Down Expand Up @@ -836,7 +861,7 @@ <h2 id="args">Args</h2>
<h2 id="raises">Raises</h2>
<dl>
<dt><code>ValueError</code></dt>
<dd>If <code>prometheus_multiproc_dir</code> env var is found but
<dd>If <code>PROMETHEUS_MULTIPROC_DIR</code> env var is found but
doesn't point to a valid directory.</dd>
</dl>
<h2 id="returns">Returns</h2>
Expand All @@ -848,84 +873,96 @@ <h2 id="returns">Returns</h2>
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def expose(
self,
app: FastAPI,
should_gzip: bool = False,
endpoint: str = &#34;/metrics&#34;,
include_in_schema: bool = True,
tags: Optional[List[str]] = None,
**kwargs,
):
&#34;&#34;&#34;Exposes endpoint for metrics.
<pre><code class="python"> def expose(
self,
app: FastAPI,
should_gzip: bool = False,
endpoint: str = &#34;/metrics&#34;,
include_in_schema: bool = True,
tags: Optional[List[str]] = None,
**kwargs,
):
&#34;&#34;&#34;Exposes endpoint for metrics.

Args:
app: FastAPI app instance. Endpoint will be added to this app.
Args:
app: FastAPI app instance. Endpoint will be added to this app.

should_gzip: Should the endpoint return compressed data? It will
also check for `gzip` in the `Accept-Encoding` header.
Compression consumes more CPU cycles. In most cases it&#39;s best
to just leave this option off since network bandwith is usually
cheaper than CPU cycles. Defaults to `False`.
should_gzip: Should the endpoint return compressed data? It will
also check for `gzip` in the `Accept-Encoding` header.
Compression consumes more CPU cycles. In most cases it&#39;s best
to just leave this option off since network bandwith is usually
cheaper than CPU cycles. Defaults to `False`.

endpoint: Endpoint on which metrics should be exposed.
endpoint: Endpoint on which metrics should be exposed.

include_in_schema: Should the endpoint show up in the documentation?
include_in_schema: Should the endpoint show up in the documentation?

tags (List[str], optional): If you manage your routes with tags.
Defaults to None.
tags (List[str], optional): If you manage your routes with tags.
Defaults to None.

kwargs: Will be passed to FastAPI route annotation.
kwargs: Will be passed to FastAPI route annotation.

Raises:
ValueError: If `prometheus_multiproc_dir` env var is found but
doesn&#39;t point to a valid directory.
Raises:
ValueError: If `PROMETHEUS_MULTIPROC_DIR` env var is found but
doesn&#39;t point to a valid directory.

Returns:
self: Instrumentator. Builder Pattern.
&#34;&#34;&#34;
Returns:
self: Instrumentator. Builder Pattern.
&#34;&#34;&#34;

if (
self.should_respect_env_var
and os.environ.get(self.env_var_name, &#34;false&#34;) != &#34;true&#34;
):
return self
if (
self.should_respect_env_var
and os.environ.get(self.env_var_name, &#34;false&#34;) != &#34;true&#34;
):
return self

from prometheus_client import (
CONTENT_TYPE_LATEST,
REGISTRY,
CollectorRegistry,
generate_latest,
multiprocess,
)

if &#34;prometheus_multiproc_dir&#34; in os.environ:
pmd = os.environ[&#34;prometheus_multiproc_dir&#34;]
if os.path.isdir(pmd):
registry = CollectorRegistry()
multiprocess.MultiProcessCollector(registry)
else:
raise ValueError(
f&#34;Env var prometheus_multiproc_dir=&#39;{pmd}&#39; not a directory.&#34;
from prometheus_client import (
CONTENT_TYPE_LATEST,
REGISTRY,
CollectorRegistry,
generate_latest,
multiprocess,
)

if (
&#34;prometheus_multiproc_dir&#34; in os.environ
and &#34;PROMETHEUS_MULTIPROC_DIR&#34; not in os.environ
):
os.environ[&#34;PROMETHEUS_MULTIPROC_DIR&#34;] = os.environ[
&#34;prometheus_multiproc_dir&#34;
]
warnings.warn(
&#34;prometheus_multiproc_dir variable has been deprecated in favor of the \
upper case naming PROMETHEUS_MULTIPROC_DIR&#34;,
DeprecationWarning,
)
else:
registry = REGISTRY

@app.get(endpoint, include_in_schema=include_in_schema, tags=tags, **kwargs)
def metrics(request: Request):
&#34;&#34;&#34;Endpoint that serves Prometheus metrics.&#34;&#34;&#34;

if should_gzip and &#34;gzip&#34; in request.headers.get(&#34;Accept-Encoding&#34;, &#34;&#34;):
resp = Response(content=gzip.compress(generate_latest(registry)))
resp.headers[&#34;Content-Type&#34;] = CONTENT_TYPE_LATEST
resp.headers[&#34;Content-Encoding&#34;] = &#34;gzip&#34;
return resp
if &#34;PROMETHEUS_MULTIPROC_DIR&#34; in os.environ:
pmd = os.environ[&#34;PROMETHEUS_MULTIPROC_DIR&#34;]
if os.path.isdir(pmd):
registry = CollectorRegistry()
multiprocess.MultiProcessCollector(registry)
else:
raise ValueError(
f&#34;Env var PROMETHEUS_MULTIPROC_DIR=&#39;{pmd}&#39; not a directory.&#34;
)
else:
resp = Response(content=generate_latest(registry))
resp.headers[&#34;Content-Type&#34;] = CONTENT_TYPE_LATEST
return resp
registry = REGISTRY

return self</code></pre>
@app.get(endpoint, include_in_schema=include_in_schema, tags=tags, **kwargs)
def metrics(request: Request):
&#34;&#34;&#34;Endpoint that serves Prometheus metrics.&#34;&#34;&#34;

if should_gzip and &#34;gzip&#34; in request.headers.get(&#34;Accept-Encoding&#34;, &#34;&#34;):
resp = Response(content=gzip.compress(generate_latest(registry)))
resp.headers[&#34;Content-Type&#34;] = CONTENT_TYPE_LATEST
resp.headers[&#34;Content-Encoding&#34;] = &#34;gzip&#34;
return resp
else:
resp = Response(content=generate_latest(registry))
resp.headers[&#34;Content-Type&#34;] = CONTENT_TYPE_LATEST
return resp

return self</code></pre>
</details>
</dd>
<dt id="prometheus_fastapi_instrumentator.instrumentation.PrometheusFastApiInstrumentator.instrument"><code class="name flex">
Expand Down
21 changes: 17 additions & 4 deletions prometheus_fastapi_instrumentator/instrumentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import gzip
import os
import re
import warnings
from timeit import default_timer
from typing import Callable, List, Optional, Pattern, Tuple

Expand Down Expand Up @@ -233,7 +234,7 @@ def expose(
kwargs: Will be passed to FastAPI route annotation.

Raises:
ValueError: If `prometheus_multiproc_dir` env var is found but
ValueError: If `PROMETHEUS_MULTIPROC_DIR` env var is found but
doesn't point to a valid directory.

Returns:
Expand All @@ -254,14 +255,26 @@ def expose(
multiprocess,
)

if "prometheus_multiproc_dir" in os.environ:
pmd = os.environ["prometheus_multiproc_dir"]
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(
"prometheus_multiproc_dir variable has been deprecated in favor of the \
upper case naming PROMETHEUS_MULTIPROC_DIR",
DeprecationWarning,
)
if "PROMETHEUS_MULTIPROC_DIR" in os.environ:
pmd = os.environ["PROMETHEUS_MULTIPROC_DIR"]
if os.path.isdir(pmd):
registry = CollectorRegistry()
multiprocess.MultiProcessCollector(registry)
else:
raise ValueError(
f"Env var prometheus_multiproc_dir='{pmd}' not a directory."
f"Env var PROMETHEUS_MULTIPROC_DIR='{pmd}' not a directory."
)
else:
registry = REGISTRY
Expand Down
4 changes: 2 additions & 2 deletions run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ function _test_slow {

function _test_multiproc {
mkdir -p /tmp/test_multiproc
export prometheus_multiproc_dir=/tmp/test_multiproc
export PROMETHEUS_MULTIPROC_DIR=/tmp/test_multiproc
poetry run pytest -k test_multiprocess --cov-append --cov=./ --cov-report=xml
rm -rf /tmp/test_multiproc
unset prometheus_multiproc_dir
unset PROMETHEUS_MULTIPROC_DIR
}

function _test {
Expand Down
22 changes: 11 additions & 11 deletions tests/test_instrumentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,17 +73,17 @@ def create_item(item: Dict[Any, Any]):


def expose_metrics(app: FastAPI) -> None:
if "prometheus_multiproc_dir" in os.environ:
pmd = os.environ["prometheus_multiproc_dir"]
print(f"Env var prometheus_multiproc_dir='{pmd}' detected.")
if "PROMETHEUS_MULTIPROC_DIR" in os.environ:
pmd = os.environ["PROMETHEUS_MULTIPROC_DIR"]
print(f"Env var PROMETHEUS_MULTIPROC_DIR='{pmd}' detected.")
if os.path.isdir(pmd):
print(f"Env var prometheus_multiproc_dir='{pmd}' is a dir.")
print(f"Env var PROMETHEUS_MULTIPROC_DIR='{pmd}' is a dir.")
from prometheus_client import CollectorRegistry, multiprocess

registry = CollectorRegistry()
multiprocess.MultiProcessCollector(registry)
else:
raise ValueError(f"Env var prometheus_multiproc_dir='{pmd}' not a directory.")
raise ValueError(f"Env var PROMETHEUS_MULTIPROC_DIR='{pmd}' not a directory.")
else:
registry = REGISTRY

Expand Down Expand Up @@ -531,8 +531,8 @@ def test_rounding():


def is_prometheus_multiproc_set():
if "prometheus_multiproc_dir" in os.environ:
pmd = os.environ["prometheus_multiproc_dir"]
if "PROMETHEUS_MULTIPROC_DIR" in os.environ:
pmd = os.environ["PROMETHEUS_MULTIPROC_DIR"]
if os.path.isdir(pmd):
return True
else:
Expand All @@ -543,10 +543,10 @@ def is_prometheus_multiproc_set():
# imported. That is why we cannot simply use `tempfile` or the fixtures
# provided by pytest. Test with:
# mkdir -p /tmp/test_multiproc;
# export prometheus_multiproc_dir=/tmp/test_multiproc;
# export PROMETHEUS_MULTIPROC_DIR=/tmp/test_multiproc;
# pytest -k test_multiprocess_reg;
# rm -rf /tmp/test_multiproc;
# unset prometheus_multiproc_dir
# unset PROMETHEUS_MULTIPROC_DIR


@pytest.mark.skipif(
Expand Down Expand Up @@ -577,7 +577,7 @@ def test_multiprocess_reg():

@pytest.mark.skipif(is_prometheus_multiproc_set() is True, reason="Will never work.")
def test_multiprocess_reg_is_not(monkeypatch, tmp_path):
monkeypatch.setenv("prometheus_multiproc_dir", str(tmp_path))
monkeypatch.setenv("PROMETHEUS_MULTIPROC_DIR", str(tmp_path))

app = create_app()
Instrumentator(excluded_handlers=["/metrics"]).add(metrics.latency()).instrument(
Expand All @@ -597,7 +597,7 @@ def test_multiprocess_reg_is_not(monkeypatch, tmp_path):
is_prometheus_multiproc_set() is True, reason="Just test handling of env detection."
)
def test_multiprocess_env_folder(monkeypatch, tmp_path):
monkeypatch.setenv("prometheus_multiproc_dir", "DOES/NOT/EXIST")
monkeypatch.setenv("PROMETHEUS_MULTIPROC_DIR", "DOES/NOT/EXIST")

app = create_app()
with pytest.raises(Exception):
Expand Down