api.py 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. from datetime import datetime
  2. from typing import Any, Literal
  3. from django.db.models import Avg, Count
  4. from django.http import HttpResponse
  5. from django.shortcuts import aget_object_or_404
  6. from ninja import Query, Router, Schema
  7. from ninja.pagination import paginate
  8. from apps.shared.schema.fields import RelativeDateTime
  9. from glitchtip.api.authentication import AuthHttpRequest
  10. from .models import TransactionEvent, TransactionGroup
  11. from .schema import TransactionEventSchema, TransactionGroupSchema
  12. router = Router()
  13. def get_transaction_group_queryset(
  14. organization_slug: str, start: datetime | None = None, end: datetime | None = None
  15. ):
  16. qs = TransactionGroup.objects.filter(project__organization__slug=organization_slug)
  17. filter_kwargs: dict[str, Any] = {}
  18. if start:
  19. filter_kwargs["transactionevent__start_timestamp__gte"] = start
  20. if end:
  21. filter_kwargs["transactionevent__start_timestamp__lte"] = end
  22. if filter_kwargs:
  23. qs = qs.filter(**filter_kwargs)
  24. return qs.annotate(
  25. avg_duration=Avg("transactionevent__duration"),
  26. transaction_count=Count("transactionevent"),
  27. )
  28. @router.get(
  29. "organizations/{slug:organization_slug}/transactions/",
  30. response=list[TransactionEventSchema],
  31. )
  32. @paginate
  33. async def list_transactions(
  34. request: AuthHttpRequest, response: HttpResponse, organization_slug: str
  35. ):
  36. return TransactionEvent.objects.filter(
  37. group__project__organization__slug=organization_slug
  38. ).order_by("start_timestamp")
  39. class TransactionGroupFilters(Schema):
  40. start: RelativeDateTime | None = None
  41. end: RelativeDateTime | None = None
  42. sort: Literal[
  43. "created",
  44. "-created",
  45. "avg_duration",
  46. "-avg_duration",
  47. "transaction_count",
  48. "-transaction_count",
  49. ] = "-avg_duration"
  50. environment: list[str] = []
  51. query: str | None = None
  52. @router.get(
  53. "organizations/{slug:organization_slug}/transaction-groups/",
  54. response=list[TransactionGroupSchema],
  55. by_alias=True,
  56. )
  57. @paginate
  58. async def list_transaction_groups(
  59. request: AuthHttpRequest,
  60. response: HttpResponse,
  61. filters: Query[TransactionGroupFilters],
  62. organization_slug: str,
  63. ):
  64. queryset = get_transaction_group_queryset(
  65. organization_slug, start=filters.start, end=filters.end
  66. )
  67. if filters.environment:
  68. queryset = queryset.filter(tags__environment__has_any_keys=filters.environment)
  69. return queryset.order_by(filters.sort)
  70. @router.get(
  71. "organizations/{slug:organization_slug}/transaction-groups/{int:id}/",
  72. response=TransactionGroupSchema,
  73. by_alias=True,
  74. )
  75. async def get_transaction_group(
  76. request: AuthHttpRequest, response: HttpResponse, organization_slug: str, id: int
  77. ):
  78. return await aget_object_or_404(
  79. get_transaction_group_queryset(organization_slug), id=id
  80. )