Skip to content

feat: add metrics=timings preference to prefer header#3507

Draft
taimoorzaeem wants to merge 1 commit intoPostgREST:mainfrom
taimoorzaeem:prefer/metrics
Draft

feat: add metrics=timings preference to prefer header#3507
taimoorzaeem wants to merge 1 commit intoPostgREST:mainfrom
taimoorzaeem:prefer/metrics

Conversation

@taimoorzaeem
Copy link
Copy Markdown
Member

@taimoorzaeem taimoorzaeem commented May 11, 2024

Closes #3410.

  • Implementation
  • Tests
  • Docs

@taimoorzaeem taimoorzaeem force-pushed the prefer/metrics branch 2 times, most recently from 953a808 to 0da1e8c Compare May 12, 2024 20:21
@laurenceisla
Copy link
Copy Markdown
Member

laurenceisla commented May 20, 2024

What exactly do I need to do to deprecate the server-timings-enabled config? Should I just remove it from the codebase?

Deprecating the config does not mean to remove it from the code (right now), only that it's not recommended anymore (could be removed in the future). It should be mentioned in comments and in the docs that it's deprecated in favor of the new feature. See, for example: 6c3d7a9 and https://postgrest.org/en/latest/references/api/preferences.html#single-json-object-as-function-parameter

Comment thread src/PostgREST/App.hs Outdated
Comment on lines +147 to +149
-- the preference metrics=timings cant be used before it is parsed, hence
-- parseTime will be calculated for all requests
(parseTime, apiReq@ApiRequest{..}) <- withTiming True $ liftEither . mapLeft Error.ApiRequestError $ ApiRequest.userApiRequest conf req body sCache
Copy link
Copy Markdown
Member

@laurenceisla laurenceisla May 20, 2024

Choose a reason for hiding this comment

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

Ah, so it's not possible to disable ALL timings with Prefer: metrics=timings, without parsing the headers first. So it's not a perfect replacement for server-timings-enabled = false, since some timings will be calculated even if the header is not sent: the "jwt" and "parse" timings as far as I can see.

Not sure if it's OK to always calculate these timings, I believe it will still affect the performance as mentioned in the issue. cc: @steve-chavez

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hm, so here we're forcing to always calculate the time for parsing? That would defeat the whole purpose of #3410

But I understand that we first need to parse to get the header. I guess we would need to do this in a step separate from userApiRequest, but that's messy.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So far the parse and response timings (ref) have not been that useful because they're always fast.

Another option could be to omit the parse timing when doing Prefer: metrics=timings or we could just remove support for the above mentioned. Then we wouldn't have this problem.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I was thinking to do a breaking change and remove the parse time now. But then I thought: wouldn't it be simpler to omit the parse time when Prefer: metric=timings is requested?

It would just be:

Server-Timing: jwt;dur=14.9, plan;dur=109.0, transaction;dur=353.2, response;dur=4.4

We could point that out in the docs.

@taimoorzaeem I believe that should unblock this feature.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes, that would be much simpler. Let's implement it this way.

@taimoorzaeem taimoorzaeem marked this pull request as draft April 14, 2025 11:54
@taimoorzaeem taimoorzaeem force-pushed the prefer/metrics branch 2 times, most recently from 57a6f25 to 00cca6c Compare April 30, 2025 18:55
@taimoorzaeem taimoorzaeem changed the title feat: add metrics=timings to prefer header feat: add metrics=timings preference to prefer header Apr 30, 2025
@taimoorzaeem taimoorzaeem marked this pull request as ready for review April 30, 2025 18:57
Comment thread CHANGELOG.md Outdated

### Deprecated

- #3410, The config `server-timing-enabled` is deprecated. Use `metrics=timings` prefer header instead - @taimoorzaeem
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Now that server-timing-enabled has different functionality than Prefer: metrics=timings, I don't think we can deprecate it/remove it in the future. At least for now.

steve-chavez added a commit to steve-chavez/postgrest that referenced this pull request May 2, 2025
This allows obtaining the preferences header before doing the full parse
on userApiRequest. Which is needed by PostgREST#3507.
Comment thread docs/references/api/preferences.rst Outdated
Comment on lines +289 to +291
.. note::

When timings are requested with this header, we can't tell the ``parse`` stage timings. This is because we are past the "parse" stage when this preference itself is parsed.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This didn't look good. So I thought of a simpler way: #4057.

With this, we won't measure the parse time of the Preferences header, but that's fine as its parsing is simple and its input small.

The bulk of the parse stage is really in QueryParams.parse (URL query string parsing) which is still maintained.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

To be clear, once you rebase on top of #4057, the Prefer: metric=timings resposne now should contain the same information as when the server-timing-enabled config is set.

steve-chavez added a commit that referenced this pull request May 3, 2025
This allows obtaining the preferences header before doing the full parse
on userApiRequest. Which is needed by #3507.
@taimoorzaeem taimoorzaeem marked this pull request as draft May 3, 2025 06:37
Comment thread src/PostgREST/Auth.hs
Comment on lines +166 to +167
-- Now that we also calculate the timings when Prefer: metrics=timings,
-- how do we get that preference here?
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@steve-chavez We need the preference here too. I am not sure about this but I think we should think about storing the ApiRequest result in AppState. This way it would be easier to access already parsed request information at any stage in the code.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think we should just refactor to remove the Auth.middleware approach. I've never liked that one as it hides side effects and obscures logic. It might allow us to remove the unsafePerformIO from Auth.hs too:

authResultKey :: Vault.Key (Either Error AuthResult)
authResultKey = unsafePerformIO Vault.newKey
{-# NOINLINE authResultKey #-}
getResult :: Wai.Request -> Maybe (Either Error AuthResult)
getResult = Vault.lookup authResultKey . Wai.vault
jwtDurKey :: Vault.Key Double
jwtDurKey = unsafePerformIO Vault.newKey

Once that's done you should be able to use/get the prefer value value before validating the JWT.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Agreed. Let me refactor this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

On-demand server-timing

3 participants