getsentry / sentry-docs

Sentry's documentation (and tools to build it)
https://docs.sentry.io
Other
336 stars 1.48k forks source link

Improve Tracing Setup #11524

Open smeubank opened 1 month ago

smeubank commented 1 month ago

SDK

JavaScript SDK

Description

I ran into a few issues while setting up my last distributed services

  1. CORS config on server
  2. adblocking -> tunnel config on python server

This should also be in onbaording more clearly too

Suggested Solution

  1. Update docs to state that sometimes it is configured directly in platforms like AWS, but others it can be configured directly in the server app
    • include examples in top platforms, maintaining such snippets for all will be cumbersome
    • fastAPI for example
from fastapi.middleware.cors import CORSMiddleware
. . .
# Configure CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # Adjust this to your specific frontend domain
    allow_credentials=True, # potentially irrelevant for sentry
    allow_methods=["*"], # adjust to what matters to you
    allow_headers=["sentry-trace", "baggage", "*"],  # Include sentry-trace and baggage
)
  1. Add a python tunnelling example here
from fastapi import FastAPI, Request, Response
from fastapi.responses import JSONResponse
import json
from urllib.parse import urlparse
import aiohttp

app = FastAPI()

# Replace with your actual Sentry host and project IDs
SENTRY_HOST = "oXXXXXX.ingest.sentry.io"
SENTRY_PROJECT_IDS = ["123456"]

@app.post("/tunnel")
async def sentry_tunnel(request: Request):
    try:
        # Read the raw bytes from the request body
        envelope_bytes = await request.body()

        # Decode bytes to string and split into lines
        envelope = envelope_bytes.decode('utf-8')
        pieces = envelope.split('\n')
        header_str = pieces[0]

        # Parse the envelope header as JSON
        header = json.loads(header_str)
        dsn = header.get('dsn', '')

        # Parse the DSN to extract hostname and project ID
        dsn_parsed = urlparse(dsn)
        hostname = dsn_parsed.hostname
        project_id = dsn_parsed.path.strip('/')

        # Validate the hostname and project ID
        if hostname != SENTRY_HOST:
            raise Exception(f"Invalid Sentry hostname: {hostname}")

        if not project_id or project_id not in SENTRY_PROJECT_IDS:
            raise Exception(f"Invalid Sentry project ID: {project_id}")

        # Construct the upstream Sentry URL
        upstream_sentry_url = f"https://{SENTRY_HOST}/api/{project_id}/envelope/"

        # Forward the envelope to Sentry
        async with aiohttp.ClientSession() as session:
            async with session.post(
                upstream_sentry_url,
                data=envelope_bytes,
                headers={'Content-Type': 'application/x-sentry-envelope'}
            ) as resp:
                if resp.status != 200:
                    raise Exception(f"Upstream Sentry returned status {resp.status}")

        # Return success response
        return Response(status_code=200)
    except Exception as e:
        print("Error tunneling to Sentry:", e)
        return JSONResponse(content={'error': 'Error tunneling to Sentry'}, status_code=500)

https://xxxx.ingest.us.sentry.io/api/xxxx/envelope/?sentry_key=xxx&sentry_version=7&sentry_client=sentry.SDK net::ERR_BLOCKED_BY_CLIENT

smeubank commented 3 weeks ago

tunneling also causes problems for replays, the above example broke replays for example. Do we provide an example anywhere or FAQ that it might happen?