Skip to content

Commit 88164e7

Browse files
actualwitchBrett Beutell
andauthored
Add concurrency tracking (#55)
* Add concurrency tracking * Fix concurrency tests for otel and prom trackers * Comment out opentelemetry concurrency test since gauges are not supported * Update docs * Add a test for passing objectives to autometrics then using async decorator * Update version to 0.6 --------- Co-authored-by: Brett Beutell <[email protected]>
1 parent 2412b13 commit 88164e7

File tree

16 files changed

+1094
-15
lines changed

16 files changed

+1094
-15
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1313
### Added
1414

1515
- Exemplars support (#51)
16+
- Optional concurrency tracking support (#55)
1617

1718
### Changed
1819

@@ -28,6 +29,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
2829

2930
### Fixed
3031

32+
- Fixed decorator async function handling (#55)
33+
3134
### Security
3235

3336
- Update requests, starlette, fastapi dependencies used by the examples

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ def sayHello:
4545

4646
```
4747

48+
- You can also track the number of concurrent calls to a function by using the `track_concurrency` argument: `@autometrics(track_concurrency=True)`. Note: currently only supported by the `prometheus` tracker.
49+
4850
- To access the PromQL queries for your decorated functions, run `help(yourfunction)` or `print(yourfunction.__doc__)`.
4951

5052
- To show tooltips over decorated functions in VSCode, with links to Prometheus queries, try installing [the VSCode extension](https://marketplace.visualstudio.com/items?itemName=Fiberplane.autometrics).

examples/django_example/django_example/urls.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@
1616
"""
1717
from django.urls import path
1818

19+
from .views.concurrency import ConcurrencyView
1920
from .views.latency import RandomLatencyView
2021
from .views.metrics import metrics
2122
from .views.simple import simple_handler
2223
from .views.error import ErrorOrOkView
2324

2425
urlpatterns = [
26+
path("concurrency/", ConcurrencyView.as_view()),
2527
path("latency/", RandomLatencyView.as_view()),
2628
path("error/", ErrorOrOkView.as_view()),
2729
path("simple/", simple_handler),
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import time
2+
from autometrics import autometrics
3+
from django.http import HttpResponse
4+
from django.views import View
5+
6+
7+
class ConcurrencyView(View):
8+
"""Here you can see how concurrency tracking works in autometrics.
9+
Just add the `track_concurrency=True` argument, and autometrics
10+
will track the number of concurrent requests to this endpoint."""
11+
12+
@autometrics(track_concurrency=True)
13+
def get(self, request):
14+
time.sleep(0.25)
15+
return HttpResponse("Many clients wait for a reply from this endpoint!")

examples/django_example/django_example/views/latency.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ class RandomLatencyView(View):
1010

1111
@autometrics
1212
def get(self, request):
13-
duration = random.randint(1, 500)
13+
duration = random.randint(1, 10)
1414

15-
time.sleep(duration / 1000)
15+
time.sleep(duration / 10)
1616

1717
return HttpResponse("i was waiting for {}ms!".format(duration))

examples/django_example/locustfile.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import time
2+
from locust import HttpUser, task, between
3+
4+
5+
class DjangoUser(HttpUser):
6+
wait_time = between(1, 2.5)
7+
8+
@task(10)
9+
def visit_concurrency_handler(self):
10+
self.client.get("/concurrency/")
11+
12+
@task
13+
def visit_error_handler(self):
14+
self.client.get("/error/")
15+
16+
@task
17+
def visit_simple_handler(self):
18+
self.client.get("/simple/")
19+
20+
@task
21+
def visit_latency_handler(self):
22+
self.client.get("/latency/")
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/bin/sh
2+
3+
export AUTOMETRICS_COMMIT=67a1b3a
4+
export AUTOMETRICS_VERSION=0.1.0
5+
export AUTOMETRICS_BRANCH=main
6+
export AUTOMETRICS_TRACKER=prometheus
7+
8+
# run the server itself
9+
poetry run python manage.py runserver 8080 &
10+
# run the locust load test and pipe stdout to dev/null
11+
poetry run locust --host=http://localhost:8080 --users=100 --headless &
12+
13+
# kill all child processes on exit
14+
trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT
15+
wait

poetry.lock

Lines changed: 838 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "autometrics"
3-
version = "0.5"
3+
version = "0.6"
44
description = "Easily add metrics to your system – and actually understand them using automatically customized Prometheus queries"
55
authors = ["Fiberplane <[email protected]>"]
66
license = "MIT OR Apache-2.0"
@@ -72,6 +72,7 @@ urllib3 = "1.26.15"
7272
uvicorn = "0.21.1"
7373
webencodings = "0.5.1"
7474
zipp = "3.15.0"
75+
locust = "^2.15.1"
7576

7677
[build-system]
7778
requires = ["poetry-core"]

src/autometrics/constants.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@
22

33
COUNTER_NAME = "function.calls.count"
44
HISTOGRAM_NAME = "function.calls.duration"
5+
CONCURRENCY_NAME = "function.calls.concurrent"
56
# NOTE - The Rust implementation does not use `build.info`, instead opts for just `build_info`
67
BUILD_INFO_NAME = "build_info"
78

9+
810
COUNTER_NAME_PROMETHEUS = COUNTER_NAME.replace(".", "_")
911
HISTOGRAM_NAME_PROMETHEUS = HISTOGRAM_NAME.replace(".", "_")
12+
CONCURRENCY_NAME_PROMETHEUS = CONCURRENCY_NAME.replace(".", "_")
1013

1114
COUNTER_DESCRIPTION = "Autometrics counter for tracking function calls"
1215
HISTOGRAM_DESCRIPTION = "Autometrics histogram for tracking function call duration"
16+
CONCURRENCY_DESCRIPTION = "Autometrics gauge for tracking function call concurrency"
1317
BUILD_INFO_DESCRIPTION = (
1418
"Autometrics info metric for tracking software version and build details"
1519
)

0 commit comments

Comments
 (0)