File: test_middleware.py

package info (click to toggle)
prometheus-fastapi-instrumentator 7.1.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 492 kB
  • sloc: python: 2,586; makefile: 5
file content (186 lines) | stat: -rw-r--r-- 5,201 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
from fastapi import FastAPI, responses, status
from fastapi.testclient import TestClient

from prometheus_fastapi_instrumentator import Instrumentator, metrics


def test_info_body_default():
    """
    Tests that `info.response.body` is empty even if response body is not empty.
    This is the expected default that can be changed with `body_handlers`.
    """

    app = FastAPI()
    client = TestClient(app)

    @app.get("/", response_class=responses.PlainTextResponse)
    def root():
        return "123456789"

    instrumentation_executed = False

    def instrumentation(info: metrics.Info) -> None:
        nonlocal instrumentation_executed
        instrumentation_executed = True
        assert len(info.response.body) == 0

    Instrumentator().instrument(app).add(instrumentation)

    client.get("/")
    assert instrumentation_executed


def test_info_body_empty():
    """
    Tests that `info.response.body` is empty if actual response is also empty.
    """

    app = FastAPI()
    client = TestClient(app)

    @app.get("/")
    def root():
        return responses.Response(status_code=status.HTTP_200_OK)

    instrumentation_executed = False

    def instrumentation(info: metrics.Info) -> None:
        nonlocal instrumentation_executed
        instrumentation_executed = True
        assert len(info.response.body) == 0

    Instrumentator(body_handlers=[r".*"]).instrument(app).add(instrumentation)

    client.get("/")
    assert instrumentation_executed


def test_info_body_stream_small():
    """
    Tests that `info.response.body` is correct if small response is streamed.
    """

    app = FastAPI()
    client = TestClient(app)

    @app.get("/")
    def root():
        return responses.StreamingResponse((str(num) + "xxx" for num in range(5)))

    instrumentation_executed = False

    def instrumentation(info: metrics.Info) -> None:
        nonlocal instrumentation_executed
        instrumentation_executed = True
        assert len(info.response.body) == 20
        assert info.response.body.decode() == "0xxx1xxx2xxx3xxx4xxx"

    Instrumentator(body_handlers=[r".*"]).instrument(app).add(instrumentation)

    response = client.get("/")
    assert instrumentation_executed
    assert len(response.content) == 20
    assert response.content.decode() == "0xxx1xxx2xxx3xxx4xxx"


def test_info_body_stream_large():
    """
    Tests that `info.response.body` is correct if large response is streamed.
    """

    app = FastAPI()
    client = TestClient(app)

    @app.get("/")
    def root():
        return responses.StreamingResponse(("x" * 1_000_000 for _ in range(5)))

    instrumentation_executed = False

    def instrumentation(info: metrics.Info) -> None:
        nonlocal instrumentation_executed
        instrumentation_executed = True
        assert len(info.response.body) == 5_000_000

    Instrumentator(body_handlers=[r".*"]).instrument(app).add(instrumentation)

    response = client.get("/")
    assert instrumentation_executed
    assert len(response.content) == 5_000_000


def test_info_body_bulk_small():
    """
    Tests that `info.response.body` is correct if small response is returned.
    """

    app = FastAPI()
    client = TestClient(app)

    @app.get("/", response_class=responses.PlainTextResponse)
    def root():
        return "123456789"

    instrumentation_executed = False

    def instrumentation(info: metrics.Info) -> None:
        print(info.response.body)
        nonlocal instrumentation_executed
        instrumentation_executed = True
        assert len(info.response.body) == 9
        assert info.response.body == b"123456789"

    Instrumentator(body_handlers=[r".*"]).instrument(app).add(instrumentation)

    response = client.get("/")
    assert instrumentation_executed
    assert len(response.content) == 9
    assert response.content == b"123456789"


def test_info_body_bulk_large():
    """
    Tests that `info.response.body` is correct if large response is returned.
    """

    app = FastAPI()
    client = TestClient(app)

    @app.get("/", response_class=responses.PlainTextResponse)
    def root():
        return "x" * 5_000_000

    instrumentation_executed = False

    def instrumentation(info: metrics.Info) -> None:
        print(info.response.body)
        nonlocal instrumentation_executed
        instrumentation_executed = True
        assert len(info.response.body) == 5_000_000

    Instrumentator(body_handlers=[r".*"]).instrument(app).add(instrumentation)

    response = client.get("/")
    assert instrumentation_executed
    assert len(response.content) == 5_000_000


def test_info_body_duration_without_streaming():
    app = FastAPI()
    client = TestClient(app)

    @app.get("/")
    def root():
        return responses.StreamingResponse(("x" * 1_000 for _ in range(5)))

    instrumentation_executed = False

    def instrumentation(info: metrics.Info) -> None:
        nonlocal instrumentation_executed
        instrumentation_executed = True
        assert info.modified_duration_without_streaming < info.modified_duration

    Instrumentator(body_handlers=[r".*"]).instrument(app).add(instrumentation)

    client.get("/")
    assert instrumentation_executed