Skip to content

Commit

Permalink
Merge branch 'add_metrics_counter' into 'main'
Browse files Browse the repository at this point in the history
Prepare utils for metrics counters

See merge request oss/imalive!11
  • Loading branch information
idrissneumann committed Mar 10, 2024
2 parents 30b1e3d + e5693b3 commit 48f8979
Show file tree
Hide file tree
Showing 13 changed files with 74 additions and 6 deletions.
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ docker-compose -f docker-compose-local.yml up --build --abort-on-container-exit
```

Then you can try:
* the api endpoint: http://localhost:8080
* jaegger UI here for the traces: http://localhost:16686
* the opentelemetry metrics exporter endpoint: http://localhost:8889/metrics
* prometheus: http://localhost:9090
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.6.1
3.6.2
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ fastapi[all]
requests
uvicorn[standard]
fastapi-utils
asgi-correlation-id
psutil
prometheus-fastapi-instrumentator
opentelemetry-api
Expand Down
4 changes: 4 additions & 0 deletions src/exception/ImaliveHTTPException.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class ImaliveHTTPException(Exception):
def __init__(self, status_code: int, message: dict):
self.status_code = status_code
self.message = message
22 changes: 21 additions & 1 deletion src/main.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
from fastapi import FastAPI
from uuid import uuid4
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import JSONResponse
from fastapi.exception_handlers import http_exception_handler
from asgi_correlation_id import CorrelationIdMiddleware, correlation_id
from prometheus_fastapi_instrumentator import Instrumentator
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor

from restful_ressources import import_ressources
from exception.ImaliveHTTPException import ImaliveHTTPException

from utils.common import is_not_empty
from utils.cid import get_current_cid
from utils.manifests import get_manifest_as_dict
from utils.heartbit import heartbit
from utils.otel import init_otel_tracer, init_otel_metrics
Expand All @@ -22,6 +28,12 @@
description="Official Imalive API Swagger documentation"
)

app.add_middleware(
CorrelationIdMiddleware,
header_name = 'x-imalive-cid',
generator = lambda: "{}".format(uuid4())
)

instrumentator = Instrumentator()

init_otel_tracer()
Expand All @@ -35,4 +47,12 @@

FastAPIInstrumentor.instrument_app(app)

@app.exception_handler(Exception)
async def unhandled_exception_handler(request: Request, exc: Exception) -> JSONResponse:
headers = {'x-imalive-cid': get_current_cid()}

if isinstance(exc, ImaliveHTTPException):
return JSONResponse(content = exc.message, status_code = exc.status_code, headers = headers)
return await http_exception_handler(request, HTTPException(500, 'Internal server error', headers = headers))

import_ressources(app)
5 changes: 5 additions & 0 deletions src/routes/api_health.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
from fastapi import APIRouter

from utils.cid import get_current_cid
from utils.counter import create_counter, increment_counter
from utils.otel import get_otel_tracer
from utils.health import health

router = APIRouter()
_counter = create_counter("health_api_counter", "Health API counter")

@router.get("")
def get_health():
with get_otel_tracer().start_as_current_span("imalive-health-get-route"):
increment_counter(_counter, get_current_cid())
return health()

@router.post("")
def post_health():
with get_otel_tracer().start_as_current_span("imalive-health-post-route"):
increment_counter(_counter, get_current_cid())
return health()
5 changes: 4 additions & 1 deletion src/routes/api_manifest.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
from fastapi import APIRouter
from fastapi.responses import JSONResponse

from utils.cid import get_current_cid
from utils.counter import create_counter, increment_counter
from utils.otel import get_otel_tracer
from utils.manifests import get_manifest_as_dict

router = APIRouter()
_counter = create_counter("manifest_api_counter", "Health API counter")

@router.get("")
def get_manifest():
with get_otel_tracer().start_as_current_span("imalive-manifest-route"):
manifest = get_manifest_as_dict()

increment_counter(_counter, get_current_cid())
if manifest['status'] == 'error':
return JSONResponse(content=manifest, status_code=500)
else:
Expand Down
4 changes: 4 additions & 0 deletions src/routes/api_metrics.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
from fastapi import APIRouter

from utils.cid import get_current_cid
from utils.counter import create_counter, increment_counter
from utils.otel import get_otel_tracer
from utils.metrics import all_metrics

router = APIRouter()
_counter = create_counter("metrics_api_counter", "Health API counter")

@router.get("")
def get_metrics():
with get_otel_tracer().start_as_current_span("imalive-metrics-route"):
increment_counter(_counter, get_current_cid())
return all_metrics()
4 changes: 4 additions & 0 deletions src/routes/api_root.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

from utils.otel import get_otel_tracer
from utils.health import health
from utils.counter import create_counter, increment_counter
from utils.cid import get_current_cid

router = APIRouter()
_counter = create_counter("root_api_counter", "Root API counter")

@router.get("/")
def get_root():
with get_otel_tracer().start_as_current_span("imalive-root-route"):
increment_counter(_counter, get_current_cid())
return health()
13 changes: 13 additions & 0 deletions src/utils/cid.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from uuid import uuid4
from asgi_correlation_id import correlation_id

from utils.common import is_empty

def get_current_cid():
try:
cid = correlation_id.get()
if is_empty(cid):
cid = "{}".format(uuid4())
return cid
except Exception:
return "{}".format(uuid4())
11 changes: 11 additions & 0 deletions src/utils/counter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from utils.otel import get_otel_meter

def create_counter(name, description):
return get_otel_meter().create_counter(
name = name,
description = description,
unit = "1"
)

def increment_counter(counter, tid):
counter.add(1, {"tid": tid})
1 change: 0 additions & 1 deletion src/utils/heartbit.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

from time import sleep


from utils.common import is_enabled
from utils.otel import get_otel_tracer
from utils.gauge import create_gauge, set_gauge
Expand Down
7 changes: 5 additions & 2 deletions src/utils/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import sys

from datetime import datetime
from utils.cid import get_current_cid

from utils.common import is_disabled, is_enabled, is_true

Expand Down Expand Up @@ -93,15 +94,17 @@ def get_int_value_level(level):

def quiet_log_msg (log_level, message):
vdate = datetime.now().isoformat()
formatted_log = "[{}][{}][{}] {}".format(log_level, vdate, NODE_NAME, message)
cid = get_current_cid()
formatted_log = "[{}][{}][{}][{}] {}".format(log_level, vdate, NODE_NAME, cid, message)
if is_enabled(LOG_FORMAT) and LOG_FORMAT == "json":
if isinstance(message, dict):
message['level'] = log_level
message['time'] = vdate
message['node'] = NODE_NAME
message['cid'] = cid
formatted_log = json.dumps(message)
else:
formatted_log = json.dumps({"body": message, "level": log_level, "time": vdate, "node": NODE_NAME})
formatted_log = json.dumps({"body": message, "level": log_level, "time": vdate, "node": NODE_NAME, "cid": cid})

if is_debug(log_level):
logging.debug(formatted_log)
Expand Down

0 comments on commit 48f8979

Please sign in to comment.