saleor-apps-redis_apl/apps/monitoring/backend/monitoring/app.py
Przemysław Łada b33bfd35af
Add Saleor Monitoring app (#189)
* initial commit

* Remove pre-commit-config

* Update gitignore

* Update README

* Add better config for monitoring app (#190)

---------

Co-authored-by: Lukasz Ostrowski <lukasz.ostrowski@saleor.io>
2023-02-22 12:23:04 +01:00

131 lines
3.9 KiB
Python

import logging
from fastapi import Depends, FastAPI, Request, status
from starlette.middleware.cors import CORSMiddleware
from .api import graphql_app
from .apl import AplEntity, apl_client
from .deps import (
ApiDependencies,
WebhookDependencies,
saleor_api_url_header,
verify_saleor_api_url,
)
from .integrations.datadog import DataDogClientError
from .logs import configure_logging
from .payload import OBSERVABILITY_EVENTS
from .saleor.client import GraphQLError, SaleorClient
from .saleor.common import InstallData, LazyUrl
from .settings import manifest, settings
from .utils import get_base_url
logger = logging.getLogger(__name__)
configure_logging(settings.debug)
apl_client.setup(settings.apl_url)
app = FastAPI(openapi_url="/api/openapi.json")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_headers=["*"],
allow_methods=["OPTIONS", "GET", "POST", "DELETE"],
)
@app.get("/manifest", status_code=status.HTTP_200_OK, tags=["installation-handshake"])
async def show_manifest(request: Request):
manifest_copy = manifest.copy()
for name, field in manifest_copy:
if isinstance(field, LazyUrl):
setattr(manifest_copy, name, field(request))
for extension in manifest_copy.extensions:
if isinstance(extension.url, LazyUrl):
extension.url = extension.url(request)
for webhook in manifest_copy.webhooks:
if isinstance(webhook.target_url, LazyUrl):
webhook.target_url = webhook.target_url(request)
return manifest_copy
@app.post(
"/install",
status_code=status.HTTP_200_OK,
tags=["installation-handshake"],
name="install",
)
async def install(
data: InstallData,
request: Request,
api_url=Depends(saleor_api_url_header),
_valid=Depends(verify_saleor_api_url),
):
client = SaleorClient(api_url, "test", data.auth_token)
try:
app_info = await client.app_info()
target_url = get_base_url(request).replace(path="webhooks")
await client.create_webhook(
target_url=str(target_url),
events=["OBSERVABILITY"],
name="OBSERVABILITY",
)
jwks = await client.get_jwks()
entity = AplEntity(
saleor_api_url=api_url,
app_id=app_info.id,
app_token=data.auth_token,
jwks=jwks,
)
await apl_client.set(api_url, entity)
except GraphQLError:
return {"error": {"message": "Wrong app token"}}
return {}
@app.post(
"/webhooks",
status_code=status.HTTP_200_OK,
tags=["webhooks"],
name="webhooks",
)
async def handle_observability_events(
payloads: list[OBSERVABILITY_EVENTS],
commons: WebhookDependencies = Depends(),
):
metadata = await commons.manager.get_metadata()
if not metadata.datadog or not metadata.datadog.active:
logger.warning(
"DataDog integration inactive or not configured. Dropping %s events",
len(payloads),
)
return
credentials = metadata.datadog.credentials
try:
logger.info("Sending %s events to DataDog", len(payloads))
await commons.datadog_client.send_logs(
commons.saleor_data.saleor_api_url, credentials, payloads
)
except DataDogClientError:
logger.warning("Sending logs to DataDog failed. Deactivating integration")
metadata.datadog.active = False
metadata.datadog.error = "Wrong credentials. Integration deactivated"
await commons.manager.save_private_metadata(metadata)
@app.get("/health", status_code=status.HTTP_200_OK, tags=["health"], name="health")
async def health():
return {"status": "ok"}
@app.get("/graphql")
async def graphiql(request: Request):
return await graphql_app.render_playground(request)
@app.post("/graphql")
async def graphql(request: Request, commons: ApiDependencies = Depends()):
request.state.api_context = commons
return await graphql_app.graphql_http_server(request)