Skip to content

Conversation

@petyosi
Copy link
Collaborator

@petyosi petyosi commented Jul 9, 2025

Rather than directly modifying the FastAPI demo, I decided to copy it, since the setup is sufficiently more complicated.

Check the README.md in the PR for more details.

Here's a loom that shows the app/tracing in action https://www.loom.com/share/35a827666b864bed99a4b06dab5c7956?sid=a5e5fdc9-263d-48c6-95ae-9bb9621977b8

@petyosi petyosi requested a review from samuelcolvin July 9, 2025 08:38
@asynccontextmanager
async def lifespan(_app: FastAPI):
global http_client, openai_client
async with AsyncClient() as _http_client:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think rather simplify the code and just create the client when needed instead of this lifespan stuff

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is fine, it matches my code.

traceUrl: url.toString(),
serviceName: 'image-generator-frontend',
serviceVersion: '0.1.0',
// for development purposes, we want to see traces as soon as they happen,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think clarify that maxExportBatchSize is the part that means that they will be sent immediately without batching. This also makes scheduledDelayMillis redundant.

return GenerateResponse(next_url=f'/static/{path}')

# Proxy to Logfire for client traces from the browser
@app.api_route('/client-traces', methods=['POST', 'OPTIONS'])

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why OPTIONS?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't the CORS middleware take care of this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you're right, it does.

@alexmojaki
Copy link

Dunno why I can't unresolve #4 (comment)

Copy link

@ChristopherGS ChristopherGS left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just tested out, demonstrates what we needed nicely, many thanks!

image
Copy link
Member

@samuelcolvin samuelcolvin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

otherwise LGTM.

@asynccontextmanager
async def lifespan(_app: FastAPI):
global http_client, openai_client
async with AsyncClient() as _http_client:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is fine, it matches my code.

Comment on lines +23 to +27
logfire_token = os.getenv('LOGFIRE_TOKEN')
logfire_base_url = os.getenv('LOGFIRE_BASE_URL')

assert logfire_token is not None, 'LOGFIRE_TOKEN is not set'
assert logfire_base_url is not None, 'LOGFIRE_BASE_URL is not set'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
logfire_token = os.getenv('LOGFIRE_TOKEN')
logfire_base_url = os.getenv('LOGFIRE_BASE_URL')
assert logfire_token is not None, 'LOGFIRE_TOKEN is not set'
assert logfire_base_url is not None, 'LOGFIRE_BASE_URL is not set'

Let's get rid of this stuff.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's used for the proxying

# Proxy to Logfire for client traces from the browser
@app.post('/client-traces')
async def client_traces(request: Request):
async with httpx.AsyncClient() as client:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use the exiting client.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the existing client is instrumented which isn't desirable

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not really a fan of how the vite react starter script creates 3 (!!!) tsconfig files, can we reduce to just one. I think it's fine for vite.config.ts to be vite.config.js.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could remove this and just put it all in the root .gitignore

@petyosi petyosi merged commit 5d389c7 into main Jul 11, 2025
@petyosi petyosi deleted the distributed-frontend-example branch July 11, 2025 10:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

5 participants