Skip to content

Commit d33e2b9

Browse files
michael.yakmichaelyaakoby
authored andcommitted
Pyctuator should allow adding arbitrary details to the "Info" section
See examples at #50. The actual "Info" section in SBA (retreived from the `/pyctuator/info` URI is includes explicit parameters such as `app_name` and anything provided in the `additional_app_info` parameter.
1 parent c03b399 commit d33e2b9

15 files changed

+73
-12
lines changed

README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,33 @@ Once you configure build and git info, you should see them in the Details tab of
204204

205205
![Detailed Build Info](examples/images/Main_Details_BuildInfo.png)
206206

207+
### Additional Application Info
208+
In addition to adding build and git info, Pyctuator allows adding arbitrary application details to the "Info" section in SBA.
209+
210+
This is done by initializing the `additional_app_info` parameter with an arbitrary dictionary.
211+
For example, you can provide links to your application's metrics:
212+
```python
213+
Pyctuator(
214+
app,
215+
"Flask Pyctuator",
216+
app_url=f"http://172.18.0.1:5000",
217+
pyctuator_endpoint_url=f"http://172.18.0.1:5000/pyctuator",
218+
registration_url=f"http://localhost:8080/instances",
219+
app_description="Demonstrate Spring Boot Admin Integration with Flask",
220+
additional_app_info=dict(
221+
serviceLinks=dict(
222+
metrics="http://xyz/service/metrics"
223+
),
224+
podLinks=dict(
225+
metrics=["http://xyz/pod/metrics/memory", "http://xyz/pod/metrics/cpu"]
226+
)
227+
)
228+
)
229+
```
230+
231+
This will result with the following Info page in SBA:
232+
![img.png](examples/images/Additional_App_Info.png)
233+
207234
### DB Health
208235
For services that use SQL database via SQLAlchemy, Pyctuator can easily monitor and expose the connection's health
209236
using the DbHealthProvider class as demonstrated below:
75 KB
Loading

pyctuator/impl/aiohttp_pyctuator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ async def get_environment(request: web.Request) -> web.Response:
3434
return web.json_response(pyctuator_impl.get_environment(), dumps=custom_dumps)
3535

3636
async def get_info(request: web.Request) -> web.Response:
37-
return web.json_response(pyctuator_impl.app_info, dumps=custom_dumps)
37+
return web.json_response(pyctuator_impl.get_app_info(), dumps=custom_dumps)
3838

3939
async def get_health(request: web.Request) -> web.Response:
4040
return web.json_response(pyctuator_impl.get_health(), dumps=custom_dumps)

pyctuator/impl/fastapi_pyctuator.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from pyctuator.httptrace import TraceRecord, TraceRequest, TraceResponse
1616
from pyctuator.httptrace.http_tracer import Traces
1717
from pyctuator.impl import SBA_V2_CONTENT_TYPE
18-
from pyctuator.impl.pyctuator_impl import PyctuatorImpl, AppInfo
18+
from pyctuator.impl.pyctuator_impl import PyctuatorImpl
1919
from pyctuator.impl.pyctuator_router import PyctuatorRouter, EndpointsData
2020
from pyctuator.logging.pyctuator_logging import LoggersData, LoggerLevels
2121
from pyctuator.metrics.metrics_provider import Metric, MetricNames
@@ -67,8 +67,8 @@ def get_environment() -> EnvironmentData:
6767
return pyctuator_impl.get_environment()
6868

6969
@router.get("/info", include_in_schema=include_in_openapi_schema, tags=["pyctuator"])
70-
def get_info() -> AppInfo:
71-
return pyctuator_impl.app_info
70+
def get_info() -> Dict:
71+
return pyctuator_impl.get_app_info()
7272

7373
@router.get("/health", include_in_schema=include_in_openapi_schema, tags=["pyctuator"])
7474
def get_health() -> HealthSummary:

pyctuator/impl/flask_pyctuator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def get_environment() -> Any:
8181

8282
@flask_blueprint.route("/info")
8383
def get_info() -> Any:
84-
return jsonify(pyctuator_impl.app_info)
84+
return jsonify(pyctuator_impl.get_app_info())
8585

8686
@flask_blueprint.route("/health")
8787
def get_health() -> Any:

pyctuator/impl/pyctuator_impl.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1+
import dataclasses
12
from dataclasses import dataclass
23
from datetime import datetime
3-
from typing import List
4-
from typing import Mapping
5-
from typing import Optional
4+
from typing import List, Dict, Mapping, Optional
65
from urllib.parse import urlparse
76

87
from pyctuator.environment.environment_provider import EnvironmentData, EnvironmentProvider
@@ -56,9 +55,11 @@ def __init__(
5655
pyctuator_endpoint_url: str,
5756
logfile_max_size: int,
5857
logfile_formatter: str,
58+
additional_app_info: Optional[dict],
5959
):
6060
self.app_info = app_info
6161
self.pyctuator_endpoint_url = pyctuator_endpoint_url
62+
self.additional_app_info = additional_app_info
6263

6364
self.metrics_providers: List[MetricsProvider] = []
6465
self.health_providers: List[HealthProvider] = []
@@ -135,3 +136,11 @@ def get_metric_measurement(self, metric_name: str) -> Metric:
135136

136137
def get_thread_dump(self) -> ThreadDump:
137138
return self.thread_dump_provider.get_thread_dump()
139+
140+
def get_app_info(self) -> Dict:
141+
app_info_dict = {k: v for (k, v) in dataclasses.asdict(self.app_info).items() if v}
142+
143+
if self.additional_app_info:
144+
app_info_dict = {**app_info_dict, **self.additional_app_info}
145+
146+
return app_info_dict

pyctuator/impl/tornado_pyctuator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class InfoHandler(AbstractPyctuatorHandler):
5050
def get(self) -> None:
5151
assert self.pyctuator_router is not None
5252
assert self.dumps is not None
53-
self.write(self.dumps(self.pyctuator_router.pyctuator_impl.app_info))
53+
self.write(self.dumps(self.pyctuator_router.pyctuator_impl.get_app_info()))
5454

5555

5656
# GET /health

pyctuator/pyctuator.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ def __init__(
3838
logfile_max_size: int = 10000,
3939
logfile_formatter: str = default_logfile_format,
4040
auto_deregister: bool = True,
41-
metadata: Optional[dict] = None
41+
metadata: Optional[dict] = None,
42+
additional_app_info: Optional[dict] = None,
4243
) -> None:
4344
"""The entry point for integrating pyctuator with a web-frameworks such as FastAPI and Flask.
4445
@@ -74,6 +75,7 @@ def __init__(
7475
example when running in k8s so every time a new pod is created it is assigned a different IP address, resulting
7576
with SBA showing "offline" instances
7677
:param metadata: optional metadata key-value pairs that are displayed in SBA main page of an instance
78+
:param additional_app_info: additional arbitrary information to add to the application's "Info" section
7779
"""
7880

7981
self.auto_deregister = auto_deregister
@@ -85,6 +87,7 @@ def __init__(
8587
pyctuator_endpoint_url,
8688
logfile_max_size,
8789
logfile_formatter,
90+
additional_app_info,
8891
)
8992

9093
# Register default health/metrics/environment providers

tests/aiohttp_test_server.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ def __init__(self) -> None:
2525
"http://localhost:8001/register",
2626
registration_interval_sec=1,
2727
metadata=self.metadata,
28+
additional_app_info=self.additional_app_info,
2829
)
2930

3031
@self.routes.get("/logfile_test_repeater")

tests/conftest.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,14 @@ def endpoints(registration_tracker: RegistrationTrackerFixture) -> Endpoints:
157157

158158
class PyctuatorServer(ABC):
159159
metadata: Optional[dict] = {f"k{i}": f"v{i}" for i in range(random.randrange(10))}
160+
additional_app_info = dict(
161+
serviceLinks=dict(
162+
metrics="http://xyz/service/metrics",
163+
),
164+
podLinks=dict(
165+
metrics=["http://xyz/pod/metrics/memory", "http://xyz/pod/metrics/cpu"],
166+
)
167+
)
160168

161169
@abstractmethod
162170
def start(self) -> None:

0 commit comments

Comments
 (0)