mirror of https://github.com/kortix-ai/suna.git
feat(sentry): enhance Sentry integration with user tracking and error handling improvements
This commit is contained in:
parent
eac741e867
commit
03c95fa346
|
@ -1,6 +1,7 @@
|
|||
from fastapi import FastAPI, Request
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import JSONResponse
|
||||
import sentry
|
||||
from contextlib import asynccontextmanager
|
||||
from agentpress.thread_manager import ThreadManager
|
||||
from services.supabase import DBConnection
|
||||
|
@ -12,18 +13,6 @@ from utils.logger import logger
|
|||
import uuid
|
||||
import time
|
||||
from collections import OrderedDict
|
||||
import sentry_sdk
|
||||
import os
|
||||
|
||||
sentry_dsn = os.getenv("SENTRY_DSN", None)
|
||||
if sentry_dsn:
|
||||
sentry_sdk.init(
|
||||
dsn=sentry_dsn,
|
||||
send_default_pii=True,
|
||||
_experiments={
|
||||
"enable_logs": True,
|
||||
},
|
||||
)
|
||||
|
||||
# Import the agent API module
|
||||
from agent import api as agent_api
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import sentry
|
||||
import asyncio
|
||||
import json
|
||||
import traceback
|
||||
|
@ -56,6 +57,8 @@ async def run_agent_background(
|
|||
"""Run the agent in the background using Redis for state."""
|
||||
await initialize()
|
||||
|
||||
sentry.sentry.set_tag("thread_id", thread_id)
|
||||
|
||||
logger.info(f"Starting background agent run: {agent_run_id} for thread: {thread_id} (Instance: {instance_id})")
|
||||
logger.info(f"🚀 Using model: {model_name} (thinking: {enable_thinking}, reasoning_effort: {reasoning_effort})")
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
import sentry_sdk
|
||||
from sentry_sdk.integrations.dramatiq import DramatiqIntegration
|
||||
import os
|
||||
|
||||
sentry_dsn = os.getenv("SENTRY_DSN", None)
|
||||
if sentry_dsn:
|
||||
sentry_sdk.init(
|
||||
dsn=sentry_dsn,
|
||||
integrations=[DramatiqIntegration()],
|
||||
traces_sample_rate=0.1,
|
||||
send_default_pii=True,
|
||||
_experiments={
|
||||
"enable_logs": True,
|
||||
},
|
||||
)
|
||||
|
||||
sentry = sentry_sdk
|
|
@ -1,3 +1,4 @@
|
|||
import sentry
|
||||
from fastapi import HTTPException, Request
|
||||
from typing import Optional
|
||||
import jwt
|
||||
|
@ -46,6 +47,7 @@ async def get_current_user_id_from_jwt(request: Request) -> str:
|
|||
headers={"WWW-Authenticate": "Bearer"}
|
||||
)
|
||||
|
||||
sentry.sentry.set_user({ "id": user_id })
|
||||
return user_id
|
||||
|
||||
except PyJWTError:
|
||||
|
@ -119,6 +121,7 @@ async def get_user_id_from_stream_auth(
|
|||
# For Supabase JWT, we just need to decode and extract the user ID
|
||||
payload = jwt.decode(token, options={"verify_signature": False})
|
||||
user_id = payload.get('sub')
|
||||
sentry.sentry.set_user({ "id": user_id })
|
||||
if user_id:
|
||||
return user_id
|
||||
except Exception:
|
||||
|
|
|
@ -24,6 +24,8 @@ RUN npm install
|
|||
# Copy the frontend code
|
||||
COPY . .
|
||||
|
||||
ENV NEXT_PUBLIC_VERCEL_ENV production
|
||||
|
||||
RUN npm run build
|
||||
|
||||
EXPOSE 3000
|
||||
|
|
|
@ -13,6 +13,7 @@ import { checkApiHealth } from '@/lib/api';
|
|||
import { MaintenancePage } from '@/components/maintenance/maintenance-page';
|
||||
import { DeleteOperationProvider } from '@/contexts/DeleteOperationContext';
|
||||
import { StatusOverlay } from '@/components/ui/status-overlay';
|
||||
import { VSentry } from '@/components/sentry';
|
||||
|
||||
interface DashboardLayoutProps {
|
||||
children: React.ReactNode;
|
||||
|
@ -99,6 +100,7 @@ export default function DashboardLayout({ children }: DashboardLayoutProps) {
|
|||
onOpenChange={setShowMaintenanceAlert}
|
||||
closeable={true}
|
||||
/>
|
||||
<VSentry />
|
||||
|
||||
{/* Status overlay for deletion operations */}
|
||||
<StatusOverlay />
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
const SENTRY_URL = new URL(
|
||||
process.env.NEXT_PUBLIC_SENTRY_DSN ?? 'https://example.com/abc',
|
||||
);
|
||||
const SENTRY_HOST = SENTRY_URL.hostname;
|
||||
const SENTRY_PROJECT_ID = SENTRY_URL.pathname.split('/').pop();
|
||||
|
||||
export const POST = async (req: Request) => {
|
||||
try {
|
||||
if (!process.env.NEXT_PUBLIC_SENTRY_DSN) {
|
||||
return Response.json(
|
||||
{ error: 'Sentry is not configured' },
|
||||
{ status: 500 },
|
||||
);
|
||||
}
|
||||
|
||||
const envelopeBytes = await req.arrayBuffer();
|
||||
const envelope = new TextDecoder().decode(envelopeBytes);
|
||||
const piece = envelope.split('\n')[0];
|
||||
const header = JSON.parse(piece) as { dsn: string };
|
||||
const dsn = new URL(header.dsn);
|
||||
const project_id = dsn.pathname.replace('/', '');
|
||||
|
||||
if (dsn.hostname !== SENTRY_HOST) {
|
||||
throw new Error(`Invalid sentry hostname: ${dsn.hostname}`);
|
||||
}
|
||||
|
||||
if (project_id !== SENTRY_PROJECT_ID) {
|
||||
throw new Error(`Invalid sentry project id: ${project_id}`);
|
||||
}
|
||||
|
||||
const upstream_sentry_url = `https://${SENTRY_HOST}/api/${project_id}/envelope/`;
|
||||
const response = await fetch(upstream_sentry_url, {
|
||||
body: envelopeBytes,
|
||||
method: 'POST',
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (e) {
|
||||
console.error('error tunneling to sentry', e);
|
||||
return Response.json(
|
||||
{ error: 'error tunneling to sentry' },
|
||||
{ status: 500 },
|
||||
);
|
||||
}
|
||||
};
|
|
@ -0,0 +1,17 @@
|
|||
'use client';
|
||||
|
||||
import { useEffect } from 'react';
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
import { useAuth } from '../AuthProvider';
|
||||
|
||||
export const VSentry: React.FC = () => {
|
||||
const { user } = useAuth();
|
||||
useEffect(() => {
|
||||
if (!document) return;
|
||||
const scope = Sentry.getCurrentScope();
|
||||
if (!user) scope.setUser(null);
|
||||
else scope.setUser({ email: user.email, id: user.id });
|
||||
}, [user]);
|
||||
|
||||
return null;
|
||||
};
|
|
@ -1,5 +1,11 @@
|
|||
export const SentryConfig = {
|
||||
import { consoleLoggingIntegration, type init } from '@sentry/nextjs';
|
||||
|
||||
type SentryConfig = Parameters<typeof init>[0];
|
||||
|
||||
export const SentryConfig: SentryConfig = {
|
||||
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
|
||||
tracesSampleRate: 1,
|
||||
tracesSampleRate: 0.1,
|
||||
debug: false,
|
||||
_experiments: { enableLogs: true },
|
||||
integrations: [consoleLoggingIntegration()],
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue