Skip to content

Commit

Permalink
conflict resolve
Browse files Browse the repository at this point in the history
  • Loading branch information
himanshu-wedensday committed Mar 20, 2024
2 parents b04a7a6 + 855511d commit 93db491
Show file tree
Hide file tree
Showing 42 changed files with 234 additions and 118 deletions.
2 changes: 1 addition & 1 deletion .config.celery
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
RESULT_EXPIRES = 200
RESULT_PERSISTENT = True
WORKER_SEND_TASK_EVENT = False
WORKER_PREFETCH_MULTIPLIER = 1
WORKER_PREFETCH_MULTIPLIER = 1
5 changes: 3 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ DB_PASSWORD=
DB_HOSTNAME=
DB_PORT=
DB_NAME=
OPENAI_API_KEY_GPT4=
OPENAI_API_KEY_WEDNESDAY=
SECRET_KEY=
REDIS_URL=
SENTRY_DSN=
Expand All @@ -16,3 +14,6 @@ OTEL_RESOURCE_ATTRIBUTES=
OTEL_EXPORTER_OTLP_ENDPOINT=
OTEL_EXPORTER_OTLP_HEADERS=
OTEL_EXPORTER_OTLP_PROTOCOL=
CACHE_ENABLED=
SENTRY_ENABLED=
SLACK_ENABLED=
2 changes: 1 addition & 1 deletion .flake8
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[flake8]
ignore = E501, W503
max-line-length = 120
exclude =
exclude =
.git,
__pycache__,
venv/
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ repos:
rev: v3.12.0
hooks:
- id: reorder-python-imports
exclude: ^(pre_commit/resources/|testing/resources/python3_hooks_repo/)
exclude: ^(pre_commit/resources/|testing/resources/python3_hooks_repo/alembic/)
args: [--py39-plus, --add-import, 'from __future__ import annotations']
- repo: https://github.com/asottile/add-trailing-comma
rev: v3.1.0
Expand Down
2 changes: 1 addition & 1 deletion README.Docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ Consult Docker's [getting started](https://docs.docker.com/go/get-started-sharin
docs for more detail on building and pushing.

### References
* [Docker's Python guide](https://docs.docker.com/language/python/)
* [Docker's Python guide](https://docs.docker.com/language/python/)
42 changes: 41 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ This repository provides a template for creating and deploying a FastAPI project
- Formatting using black
- Code quality analysis using SonarQube
- Application monitoring using Signoz

- Feature flagging added - User can enabled/disabled
- Database Monitoring using percona
### Getting Started

#### Requirements:
Expand Down Expand Up @@ -195,3 +196,42 @@ To enable logging with Signoz, follow these steps:
- Follow the instructions provided to configure log sending to Signoz.

By following these steps, you can effectively set up application monitoring and logging using Signoz for your Python FastAPI applications.
### Database Monitoring Using Percona

To monitor your database using Percona, follow these steps:

1. **Run Application Inside Docker Container:**
- Ensure that your application is running inside a Docker container.

2. **Open Dashboard:**
- Open your web browser and navigate to `https://localhost:443`.

3. **Login:**
- Use the following credentials to log in:
```shell
Username: admin
Password: admin
```

4. **Access Settings:**
- Once logged in, navigate to the settings section of the dashboard.

5. **Add Service:**
- Within the settings, locate the "Add Service" option.

6. **Select MySQL:**
- Choose MySQL as the service you want to monitor.

7. **Provide Database Details:**
- Enter the hostname, username, password, and any other necessary environment variables required to connect to your MySQL database.

8. **Finish Configuration:**
- Click add service.

By following these steps, you'll successfully configure Percona to monitor your MySQL database.
### Dashboard Links
- Percona: https://localhost:443
- flower: http://localhost:5556
- server: http://localhost:8000
- server-healthcheck: http://localhost:8000/home
2 changes: 1 addition & 1 deletion alembic/README
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Generic single-database configuration.
Generic single-database configuration.
16 changes: 9 additions & 7 deletions alembic/env.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
from __future__ import annotations

import json
import os
from logging.config import fileConfig

from app.config.base import db_settings
from dotenv import load_dotenv
from sqlalchemy import engine_from_config
from sqlalchemy import pool

from alembic import context
from alembic import context # type: ignore
from app.config.base import settings

load_dotenv()

print("==" * 50, "\n\n\n", "OS ENVIRONMENT", os.environ, "\n\n\n", "==" * 50)

HOST = db_settings.DB_HOSTNAME
PORT = db_settings.DB_PORT
DBNAME = db_settings.DB_NAME
USERNAME = db_settings.DB_USERNAME
PASSWORD = db_settings.DB_PASSWORD
HOST = settings.DB_HOSTNAME
PORT = settings.DB_PORT
DBNAME = settings.DB_NAME
USERNAME = settings.DB_USERNAME
PASSWORD = settings.DB_PASSWORD

if "PYTHON_FASTAPI_TEMPLATE_CLUSTER_SECRET" in os.environ:
print("Connecting to database on RDS..\n")
Expand Down
24 changes: 15 additions & 9 deletions app/app.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
import sentry_sdk
from __future__ import annotations

import sentry_sdk
from fastapi import FastAPI
from fastapi.exceptions import HTTPException
from fastapi.exceptions import RequestValidationError
from fastapi.middleware.cors import CORSMiddleware
from fastapi_pagination import add_pagination
from fastapi.exceptions import HTTPException, RequestValidationError
from sentry_sdk.integrations.asgi import SentryAsgiMiddleware

from app.config.base import cached_endpoints, settings
from app.config.base import cached_endpoints
from app.config.base import settings
from app.config.celery_utils import create_celery
from app.middlewares.cache_middleware import CacheMiddleware
from app.middlewares.rate_limiter_middleware import RateLimitMiddleware
from app.middlewares.request_id_injection import RequestIdInjection
from app.routes import api_router
from app.utils.exception_handler import exception_handler, validation_exception_handler, http_exception_handler
from app.utils.exception_handler import exception_handler
from app.utils.exception_handler import http_exception_handler
from app.utils.exception_handler import validation_exception_handler


# Sentry Initialization
if settings.SENTRY_DSN:
if settings.SENTRY_ENABLED:
sentry_sdk.init(
dsn=settings.SENTRY_DSN,
traces_sample_rate=1.0, # Sample rate of 100%
Expand Down Expand Up @@ -44,10 +49,11 @@
app.add_middleware(RequestIdInjection)
app.add_middleware(CacheMiddleware, cached_endpoints=cached_endpoints.CACHED_ENDPOINTS)

try:
app.add_middleware(SentryAsgiMiddleware)
except Exception as e:
print(f"Error while adding Sentry Middleware: {e}")
if settings.SENTRY_ENABLED:
try:
app.add_middleware(SentryAsgiMiddleware)
except Exception as e:
print(f"Error while adding Sentry Middleware: {e}")

# Include the routers
app.include_router(api_router, prefix="/api")
Expand Down
2 changes: 2 additions & 0 deletions app/celery_tasks/tasks.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import time

from celery import shared_task
Expand Down
32 changes: 20 additions & 12 deletions app/config/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,6 @@
from pydantic import BaseSettings


class CelerySettings(BaseSettings):
RESULT_EXPIRES: int
RESULT_PERSISTENT: bool
WORKER_SEND_TASK_EVENT: bool
WORKER_PREFETCH_MULTIPLIER: int

class Config:
env_file = ".config.celery"


class DBSettings(BaseSettings):
DB_HOSTNAME: str
DB_PORT: str
Expand All @@ -24,7 +14,16 @@ class Config:
env_file = ".env"


class Settings(BaseSettings):
class FlagFeatureSettings(BaseSettings):
CACHE_ENABLED: bool
SENTRY_ENABLED: bool = False
SLACK_ENABLED: bool = False

class Config:
env_file = ".env"


class Settings(FlagFeatureSettings, DBSettings):
SECRET_KEY: str
REDIS_URL: str
SENTRY_DSN: str | None
Expand All @@ -40,7 +39,16 @@ class CachedEndpoints(BaseSettings):
CACHED_ENDPOINTS: list = ["/cache-sample/"]


db_settings = DBSettings()
class CelerySettings(BaseSettings):
RESULT_EXPIRES: int
RESULT_PERSISTENT: bool
WORKER_SEND_TASK_EVENT: bool
WORKER_PREFETCH_MULTIPLIER: int

class Config:
env_file = ".config.celery"


settings = Settings()
celery_settings = CelerySettings()
cached_endpoints = CachedEndpoints()
4 changes: 3 additions & 1 deletion app/config/celery_config.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

from functools import lru_cache

from app.config.base import settings
Expand All @@ -16,7 +18,7 @@ class BaseConfig:
CELERY_TASK_ROUTES = (route_task,)


@lru_cache()
@lru_cache
def get_settings():
config_cls = BaseConfig
return config_cls()
Expand Down
2 changes: 2 additions & 0 deletions app/config/celery_utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

from celery import current_app as current_celery_app
from celery.result import AsyncResult

Expand Down
5 changes: 4 additions & 1 deletion app/config/redis_config.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from .base import settings
from __future__ import annotations

from redis import asyncio

from .base import settings


async def get_redis_pool():
return asyncio.from_url(settings.REDIS_URL, encoding="utf-8", decode_responses=True)
8 changes: 6 additions & 2 deletions app/constants/jwt_utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
from fastapi import HTTPException
import jwt
from __future__ import annotations

import datetime

import jwt
from fastapi import HTTPException

from app.config.base import settings


Expand Down
2 changes: 2 additions & 0 deletions app/constants/messages/users.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

user_messages = {
"CREATED_SUCCESSFULLY": "User registered successfully.",
"EMAIL_ALREADY_EXIST": "Email already registered.",
Expand Down
7 changes: 3 additions & 4 deletions app/daos/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,13 @@
from app.schemas.users.users_request import Login
from app.utils.user_utils import check_existing_field
from app.utils.user_utils import response_formatter
from app.wrappers.cache_wrappers import create_cache
from app.wrappers.cache_wrappers import retrieve_cache
from app.wrappers.cache_wrappers import CacheUtils


async def get_user(user_id: int, db_session: Session):
try:
cache_key = f"user_{user_id}"
cached_user, _ = await retrieve_cache(cache_key)
cached_user, _ = await CacheUtils.retrieve_cache(cache_key)
if cached_user:
return json.loads(cached_user)
# Check if the user already exists in the database
Expand All @@ -47,7 +46,7 @@ async def get_user(user_id: int, db_session: Session):
if not user:
raise NoUserFoundException(messages["NO_USER_FOUND_FOR_ID"])

await create_cache(json.dumps(user._asdict(), default=str), cache_key, 60)
await CacheUtils.create_cache(json.dumps(user._asdict(), default=str), cache_key, 60)
return user._asdict()
except Exception as e:
# Return a user-friendly error message to the client
Expand Down
13 changes: 11 additions & 2 deletions app/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,33 @@
from __future__ import annotations


class ExternalServiceException(Exception):
pass


class NoUserFoundException(Exception):
pass


class EmailAlreadyExistException(Exception):
pass


class MobileAlreadyExistException(Exception):
pass


class InvalidCredentialsException(Exception):
pass



class CentryTestException(Exception):
pass


class DatabaseConnectionException(Exception):
pass


class RedisUrlNotFoundException(Exception):
pass
pass
Loading

0 comments on commit 93db491

Please sign in to comment.