Add Sentry integration for error tracking; update requirements and configuration files. Introduce new Alembic migration for missing indexes and constraints in the database schema.
This commit is contained in:
parent
9583aa4bab
commit
18f759aa7c
@ -0,0 +1,60 @@
|
||||
"""add_missing_indexes_and_constraints
|
||||
|
||||
Revision ID: 7c26d62e8005
|
||||
Revises: bc37e9c7ae19
|
||||
Create Date: 2025-05-13 21:44:46.408395
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '7c26d62e8005'
|
||||
down_revision: Union[str, None] = 'bc37e9c7ae19'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_index('ix_expense_splits_user_id', 'expense_splits', ['user_id'], unique=False)
|
||||
op.create_index(op.f('ix_expenses_group_id'), 'expenses', ['group_id'], unique=False)
|
||||
op.create_index(op.f('ix_expenses_list_id'), 'expenses', ['list_id'], unique=False)
|
||||
op.create_index(op.f('ix_expenses_paid_by_user_id'), 'expenses', ['paid_by_user_id'], unique=False)
|
||||
op.create_index(op.f('ix_settlements_group_id'), 'settlements', ['group_id'], unique=False)
|
||||
op.create_index(op.f('ix_settlements_paid_by_user_id'), 'settlements', ['paid_by_user_id'], unique=False)
|
||||
op.create_index(op.f('ix_settlements_paid_to_user_id'), 'settlements', ['paid_to_user_id'], unique=False)
|
||||
|
||||
# Add check constraints
|
||||
op.create_check_constraint(
|
||||
'chk_expense_context',
|
||||
'expenses',
|
||||
'(item_id IS NOT NULL) OR (list_id IS NOT NULL) OR (group_id IS NOT NULL)'
|
||||
)
|
||||
op.create_check_constraint(
|
||||
'chk_settlement_different_users',
|
||||
'settlements',
|
||||
'paid_by_user_id != paid_to_user_id'
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
# Drop check constraints
|
||||
op.drop_constraint('chk_settlement_different_users', 'settlements', type_='check')
|
||||
op.drop_constraint('chk_expense_context', 'expenses', type_='check')
|
||||
|
||||
op.drop_index(op.f('ix_settlements_paid_to_user_id'), table_name='settlements')
|
||||
op.drop_index(op.f('ix_settlements_paid_by_user_id'), table_name='settlements')
|
||||
op.drop_index(op.f('ix_settlements_group_id'), table_name='settlements')
|
||||
op.drop_index(op.f('ix_expenses_paid_by_user_id'), table_name='expenses')
|
||||
op.drop_index(op.f('ix_expenses_list_id'), table_name='expenses')
|
||||
op.drop_index(op.f('ix_expenses_group_id'), table_name='expenses')
|
||||
op.drop_index('ix_expense_splits_user_id', table_name='expense_splits')
|
||||
# ### end Alembic commands ###
|
@ -11,6 +11,7 @@ logger = logging.getLogger(__name__)
|
||||
class Settings(BaseSettings):
|
||||
DATABASE_URL: str | None = None
|
||||
GEMINI_API_KEY: str | None = None
|
||||
SENTRY_DSN: str | None = None # Sentry DSN for error tracking
|
||||
|
||||
# --- JWT Settings ---
|
||||
SECRET_KEY: str # Must be set via environment variable
|
||||
|
@ -3,6 +3,8 @@ import logging
|
||||
import uvicorn
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
import sentry_sdk
|
||||
from sentry_sdk.integrations.fastapi import FastApiIntegration
|
||||
|
||||
from app.api.api_router import api_router
|
||||
from app.config import settings
|
||||
@ -10,6 +12,20 @@ from app.core.api_config import API_METADATA, API_TAGS
|
||||
# Import database and models if needed for startup/shutdown events later
|
||||
# from . import database, models
|
||||
|
||||
# Initialize Sentry
|
||||
sentry_sdk.init(
|
||||
dsn=settings.SENTRY_DSN,
|
||||
integrations=[
|
||||
FastApiIntegration(),
|
||||
],
|
||||
# Set traces_sample_rate to 1.0 to capture 100% of transactions for performance monitoring.
|
||||
# We recommend adjusting this value in production.
|
||||
traces_sample_rate=1.0,
|
||||
# If you wish to associate users to errors (assuming you are using
|
||||
# FastAPI's users system) you may enable sending PII data.
|
||||
send_default_pii=True
|
||||
)
|
||||
|
||||
# --- Logging Setup ---
|
||||
logging.basicConfig(
|
||||
level=getattr(logging, settings.LOG_LEVEL),
|
||||
|
@ -19,7 +19,8 @@ from sqlalchemy import (
|
||||
func,
|
||||
text as sa_text,
|
||||
Text, # <-- Add Text for description
|
||||
Numeric # <-- Add Numeric for price
|
||||
Numeric, # <-- Add Numeric for price
|
||||
CheckConstraint
|
||||
)
|
||||
from sqlalchemy.orm import relationship, backref
|
||||
|
||||
@ -184,15 +185,15 @@ class Expense(Base):
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
description = Column(String, nullable=False)
|
||||
total_amount = Column(Numeric(10, 2), nullable=False)
|
||||
currency = Column(String, nullable=False, default="USD") # Consider making this an Enum too if few currencies
|
||||
currency = Column(String, nullable=False, default="USD")
|
||||
expense_date = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
|
||||
split_type = Column(SAEnum(SplitTypeEnum, name="splittypeenum", create_type=True), nullable=False)
|
||||
|
||||
# Foreign Keys
|
||||
list_id = Column(Integer, ForeignKey("lists.id"), nullable=True)
|
||||
group_id = Column(Integer, ForeignKey("groups.id"), nullable=True) # If not list-specific but group-specific
|
||||
item_id = Column(Integer, ForeignKey("items.id"), nullable=True) # If the expense is for a specific item
|
||||
paid_by_user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
|
||||
list_id = Column(Integer, ForeignKey("lists.id"), nullable=True, index=True)
|
||||
group_id = Column(Integer, ForeignKey("groups.id"), nullable=True, index=True)
|
||||
item_id = Column(Integer, ForeignKey("items.id"), nullable=True)
|
||||
paid_by_user_id = Column(Integer, ForeignKey("users.id"), nullable=False, index=True)
|
||||
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
|
||||
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False)
|
||||
@ -206,27 +207,25 @@ class Expense(Base):
|
||||
splits = relationship("ExpenseSplit", back_populates="expense", cascade="all, delete-orphan")
|
||||
|
||||
__table_args__ = (
|
||||
# Example: Ensure either list_id or group_id is present if item_id is null
|
||||
# CheckConstraint('(item_id IS NOT NULL) OR (list_id IS NOT NULL) OR (group_id IS NOT NULL)', name='chk_expense_context'),
|
||||
# Ensure at least one context is provided
|
||||
CheckConstraint('(item_id IS NOT NULL) OR (list_id IS NOT NULL) OR (group_id IS NOT NULL)', name='chk_expense_context'),
|
||||
)
|
||||
|
||||
class ExpenseSplit(Base):
|
||||
__tablename__ = "expense_splits"
|
||||
__table_args__ = (UniqueConstraint('expense_id', 'user_id', name='uq_expense_user_split'),)
|
||||
__table_args__ = (
|
||||
UniqueConstraint('expense_id', 'user_id', name='uq_expense_user_split'),
|
||||
Index('ix_expense_splits_user_id', 'user_id'), # For looking up user's splits
|
||||
)
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
expense_id = Column(Integer, ForeignKey("expenses.id", ondelete="CASCADE"), nullable=False)
|
||||
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
|
||||
|
||||
owed_amount = Column(Numeric(10, 2), nullable=False) # For EQUAL or EXACT_AMOUNTS
|
||||
# For PERCENTAGE split (value from 0.00 to 100.00)
|
||||
owed_amount = Column(Numeric(10, 2), nullable=False)
|
||||
share_percentage = Column(Numeric(5, 2), nullable=True)
|
||||
# For SHARES split (e.g., user A has 2 shares, user B has 3 shares)
|
||||
share_units = Column(Integer, nullable=True)
|
||||
|
||||
# is_settled might be better tracked via actual Settlement records or a reconciliation process
|
||||
# is_settled = Column(Boolean, default=False, nullable=False)
|
||||
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
|
||||
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False)
|
||||
|
||||
@ -234,14 +233,13 @@ class ExpenseSplit(Base):
|
||||
expense = relationship("Expense", back_populates="splits")
|
||||
user = relationship("User", foreign_keys=[user_id], back_populates="expense_splits")
|
||||
|
||||
|
||||
class Settlement(Base):
|
||||
__tablename__ = "settlements"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
group_id = Column(Integer, ForeignKey("groups.id"), nullable=False) # Settlements usually within a group
|
||||
paid_by_user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
|
||||
paid_to_user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
|
||||
group_id = Column(Integer, ForeignKey("groups.id"), nullable=False, index=True)
|
||||
paid_by_user_id = Column(Integer, ForeignKey("users.id"), nullable=False, index=True)
|
||||
paid_to_user_id = Column(Integer, ForeignKey("users.id"), nullable=False, index=True)
|
||||
amount = Column(Numeric(10, 2), nullable=False)
|
||||
settlement_date = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
|
||||
description = Column(Text, nullable=True)
|
||||
@ -257,7 +255,7 @@ class Settlement(Base):
|
||||
|
||||
__table_args__ = (
|
||||
# Ensure payer and payee are different users
|
||||
# CheckConstraint('paid_by_user_id <> paid_to_user_id', name='chk_settlement_payer_ne_payee'),
|
||||
CheckConstraint('paid_by_user_id != paid_to_user_id', name='chk_settlement_different_users'),
|
||||
)
|
||||
|
||||
# Potential future: PaymentMethod model, etc.
|
@ -10,3 +10,4 @@ passlib[bcrypt]>=1.7.4
|
||||
python-jose[cryptography]>=3.3.0
|
||||
pydantic[email]
|
||||
google-generativeai>=0.5.0
|
||||
sentry-sdk[fastapi]>=1.39.0
|
182
fe/package-lock.json
generated
182
fe/package-lock.json
generated
@ -8,6 +8,8 @@
|
||||
"name": "fe",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@sentry/tracing": "^7.120.3",
|
||||
"@sentry/vue": "^7.120.3",
|
||||
"@supabase/auth-js": "^2.69.1",
|
||||
"@supabase/supabase-js": "^2.49.4",
|
||||
"@vueuse/core": "^13.1.0",
|
||||
@ -3825,6 +3827,162 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@sentry-internal/feedback": {
|
||||
"version": "7.120.3",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.120.3.tgz",
|
||||
"integrity": "sha512-ewJJIQ0mbsOX6jfiVFvqMjokxNtgP3dNwUv+4nenN+iJJPQsM6a0ocro3iscxwVdbkjw5hY3BUV2ICI5Q0UWoA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/core": "7.120.3",
|
||||
"@sentry/types": "7.120.3",
|
||||
"@sentry/utils": "7.120.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/replay-canvas": {
|
||||
"version": "7.120.3",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-7.120.3.tgz",
|
||||
"integrity": "sha512-s5xy+bVL1eDZchM6gmaOiXvTqpAsUfO7122DxVdEDMtwVq3e22bS2aiGa8CUgOiJkulZ+09q73nufM77kOmT/A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/core": "7.120.3",
|
||||
"@sentry/replay": "7.120.3",
|
||||
"@sentry/types": "7.120.3",
|
||||
"@sentry/utils": "7.120.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/tracing": {
|
||||
"version": "7.120.3",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.120.3.tgz",
|
||||
"integrity": "sha512-Ausx+Jw1pAMbIBHStoQ6ZqDZR60PsCByvHdw/jdH9AqPrNE9xlBSf9EwcycvmrzwyKspSLaB52grlje2cRIUMg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/core": "7.120.3",
|
||||
"@sentry/types": "7.120.3",
|
||||
"@sentry/utils": "7.120.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/browser": {
|
||||
"version": "7.120.3",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.120.3.tgz",
|
||||
"integrity": "sha512-i9vGcK9N8zZ/JQo1TCEfHHYZ2miidOvgOABRUc9zQKhYdcYQB2/LU1kqlj77Pxdxf4wOa9137d6rPrSn9iiBxg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry-internal/feedback": "7.120.3",
|
||||
"@sentry-internal/replay-canvas": "7.120.3",
|
||||
"@sentry-internal/tracing": "7.120.3",
|
||||
"@sentry/core": "7.120.3",
|
||||
"@sentry/integrations": "7.120.3",
|
||||
"@sentry/replay": "7.120.3",
|
||||
"@sentry/types": "7.120.3",
|
||||
"@sentry/utils": "7.120.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/core": {
|
||||
"version": "7.120.3",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.120.3.tgz",
|
||||
"integrity": "sha512-vyy11fCGpkGK3qI5DSXOjgIboBZTriw0YDx/0KyX5CjIjDDNgp5AGgpgFkfZyiYiaU2Ww3iFuKo4wHmBusz1uA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/types": "7.120.3",
|
||||
"@sentry/utils": "7.120.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/integrations": {
|
||||
"version": "7.120.3",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.120.3.tgz",
|
||||
"integrity": "sha512-6i/lYp0BubHPDTg91/uxHvNui427df9r17SsIEXa2eKDwQ9gW2qRx5IWgvnxs2GV/GfSbwcx4swUB3RfEWrXrQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/core": "7.120.3",
|
||||
"@sentry/types": "7.120.3",
|
||||
"@sentry/utils": "7.120.3",
|
||||
"localforage": "^1.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/replay": {
|
||||
"version": "7.120.3",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.120.3.tgz",
|
||||
"integrity": "sha512-CjVq1fP6bpDiX8VQxudD5MPWwatfXk8EJ2jQhJTcWu/4bCSOQmHxnnmBM+GVn5acKUBCodWHBN+IUZgnJheZSg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry-internal/tracing": "7.120.3",
|
||||
"@sentry/core": "7.120.3",
|
||||
"@sentry/types": "7.120.3",
|
||||
"@sentry/utils": "7.120.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/tracing": {
|
||||
"version": "7.120.3",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.120.3.tgz",
|
||||
"integrity": "sha512-B7bqyYFgHuab1Pn7w5KXsZP/nfFo4VDBDdSXDSWYk5+TYJ3IDruO3eJFhOrircfsz4YwazWm9kbeZhkpsHDyHg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry-internal/tracing": "7.120.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/types": {
|
||||
"version": "7.120.3",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.120.3.tgz",
|
||||
"integrity": "sha512-C4z+3kGWNFJ303FC+FxAd4KkHvxpNFYAFN8iMIgBwJdpIl25KZ8Q/VdGn0MLLUEHNLvjob0+wvwlcRBBNLXOow==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/utils": {
|
||||
"version": "7.120.3",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.120.3.tgz",
|
||||
"integrity": "sha512-UDAOQJtJDxZHQ5Nm1olycBIsz2wdGX8SdzyGVHmD8EOQYAeDZQyIlQYohDe9nazdIOQLZCIc3fU0G9gqVLkaGQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/types": "7.120.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/vue": {
|
||||
"version": "7.120.3",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/vue/-/vue-7.120.3.tgz",
|
||||
"integrity": "sha512-YKKLGx6VNk5OTz5JqIsjIqOgaU8u88Q1OBfLZgOpm55vhrvpZGGc+rHyh8XtXxh4DfC+6vTRTrAngvdPOG9Oxw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/browser": "7.120.3",
|
||||
"@sentry/core": "7.120.3",
|
||||
"@sentry/types": "7.120.3",
|
||||
"@sentry/utils": "7.120.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "2.x || 3.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@sindresorhus/merge-streams": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz",
|
||||
@ -7440,6 +7598,12 @@
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/immediate": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
||||
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/immutable": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.2.tgz",
|
||||
@ -8413,6 +8577,24 @@
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lie": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
|
||||
"integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"immediate": "~3.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/localforage": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
|
||||
"integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"lie": "3.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/locate-path": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
||||
|
@ -17,6 +17,8 @@
|
||||
"format": "prettier --write src/"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sentry/tracing": "^7.120.3",
|
||||
"@sentry/vue": "^7.120.3",
|
||||
"@supabase/auth-js": "^2.69.1",
|
||||
"@supabase/supabase-js": "^2.49.4",
|
||||
"@vueuse/core": "^13.1.0",
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { createApp } from 'vue';
|
||||
import { createPinia } from 'pinia';
|
||||
import * as Sentry from '@sentry/vue';
|
||||
import { BrowserTracing } from '@sentry/tracing';
|
||||
import App from './App.vue';
|
||||
import router from './router';
|
||||
// import { createI18n } from 'vue-i18n';
|
||||
@ -33,6 +35,23 @@ const app = createApp(App);
|
||||
const pinia = createPinia();
|
||||
app.use(pinia);
|
||||
|
||||
// Initialize Sentry
|
||||
Sentry.init({
|
||||
app,
|
||||
dsn: import.meta.env.VITE_SENTRY_DSN,
|
||||
integrations: [
|
||||
new BrowserTracing({
|
||||
routingInstrumentation: Sentry.vueRouterInstrumentation(router),
|
||||
tracingOrigins: ['localhost', /^\//],
|
||||
}),
|
||||
],
|
||||
// Set tracesSampleRate to 1.0 to capture 100% of transactions for performance monitoring.
|
||||
// We recommend adjusting this value in production
|
||||
tracesSampleRate: 1.0,
|
||||
// Set environment
|
||||
environment: import.meta.env.MODE,
|
||||
});
|
||||
|
||||
// Initialize auth state before mounting the app
|
||||
const authStore = useAuthStore();
|
||||
if (authStore.accessToken) {
|
||||
|
Loading…
Reference in New Issue
Block a user