Skip to content

feat(server): New Instruments API #2068

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 28 commits into from
Mar 5, 2025
Merged

feat(server): New Instruments API #2068

merged 28 commits into from
Mar 5, 2025

Conversation

EmrysMyrddin
Copy link
Collaborator

@EmrysMyrddin EmrysMyrddin commented Feb 18, 2025

Description

This PR is the continuation of graphql-hive/envelop#2430 which introduces a new core API: The Tracer.

A plugin (and only one) can define a tracer instance that will wrap every phases of a request pipeline.

In the case of wahtwg-node, it only adds the request wrapper.

Type of change

Please delete options that are not relevant.

  • New feature (non-breaking change which adds functionality)

Summary by CodeRabbit

  • New Features

    • Introduced a new Instruments API to enhance observability within the GraphQL pipeline.
  • Chores

    • Streamlined project configuration by updating dependency management and refining build scripts.
    • Removed redundant external dependency imports for a cleaner setup.
    • Added new entries to .gitignore to prevent tracking of specific configuration files.
    • Introduced a new pre-test script for Deno build process.
    • Added a new test suite for the instruments functionality to verify request handler behavior.
    • Expanded callback return options in the iterateAsync function to include undefined or null.

Copy link
Contributor

coderabbitai bot commented Feb 18, 2025

Warning

Rate limit exceeded

@EmrysMyrddin has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 14 minutes and 26 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between cac420c and 5149d67.

📒 Files selected for processing (3)
  • .changeset/purple-buses-try.md (1 hunks)
  • .changeset/tasty-berries-film.md (1 hunks)
  • packages/server/src/index.ts (1 hunks)

Walkthrough

The pull request updates multiple configuration and code files. The .gitignore now excludes Helix and Mise configuration files. In the server adapter implementation, instrumentation logic has been added by importing utilities and enhancing the request handling with a conditional wrapper. The plugin types have been extended to support instrumentation. A new Instruments API is introduced via a changeset, and a specific dependency for instrumentation is added. Additionally, the deno.json file is cleaned up by removing several imports, and a new Deno pretest script is added to the root package.json.

Changes

File(s) Change Summary
.gitignore Added three new ignore entries: .helix/config.toml, .helix/languages.toml, and .mise.toml for configuration files.
packages/server/src/createServerAdapter.ts, packages/server/src/plugins/types.ts Introduced instrumentation in the server adapter: new imports from @envelop/instruments, added an instruments variable, updated function signatures, and added an optional instruments property in the plugin interface.
.changeset/purple-buses-try.md Introduced a new Instruments API for observability in the GraphQL pipeline.
.changeset/@whatwg-node_server-2068-dependencies.md, packages/server/package.json Added dependency @envelop/instruments at version 1.0.0.
deno.json Removed multiple external imports, leaving only @whatwg-node/fetch.
package.json Added a new script "pretest:deno": "yarn build" to run before Deno tests.
packages/server/test/instruments.spec.ts Added a new test suite for the instruments functionality with a test case validating request handler behavior.
packages/promise-helpers/src/index.ts Updated the type signature of the callback parameter in iterateAsync to allow returning undefined or null.

Sequence Diagram(s)

sequenceDiagram
    participant C as Client
    participant SA as Server Adapter
    participant Instru as Instruments
    C->>SA: Send Request
    SA->>SA: Check for instrumentation plugins
    alt Instruments available
        SA->>Instru: Wrap handleRequest using getInstrumented
        Instru-->>SA: Return instrumented handler
    else No instruments
        SA->>SA: Execute default handleRequest
    end
    SA->>C: Return Response
Loading

Suggested reviewers

  • dotansimha

Poem

I'm a hopping rabbit, in code I delight,
Skipping through changes from morning to night.
With instruments and tracers, my leaps ring true,
Configs and scripts dancing in the dew.
Cheers to each commit, shiny and bright!
🐇🌟


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

github-actions bot commented Feb 18, 2025

@benchmarks/node-fetch results (noConsumeBody)

   ✓ active_handles.................: avg=140.387537 min=12      med=140     max=186     p(90)=160     p(95)=165    
     data_received..................: 21 MB  703 kB/s
     data_sent......................: 14 MB  455 kB/s
     http_req_blocked...............: avg=2.45µs     min=631ns   med=1.34µs  max=6.14ms  p(90)=2.04µs  p(95)=2.33µs 
     http_req_connecting............: avg=467ns      min=0s      med=0s      max=3.82ms  p(90)=0s      p(95)=0s     
     http_req_duration..............: avg=21.68ms    min=3.4ms   med=20.96ms max=1.18s   p(90)=27.21ms p(95)=29.22ms
       { expected_response:true }...: avg=21.68ms    min=3.4ms   med=20.96ms max=1.18s   p(90)=27.21ms p(95)=29.22ms
     http_req_failed................: 0.00%  ✓ 0           ✗ 137846
     http_req_receiving.............: avg=33.74µs    min=9.3µs   med=22.74µs max=46.92ms p(90)=37.13µs p(95)=43.95µs
     http_req_sending...............: avg=11.08µs    min=3.33µs  med=6.26µs  max=22.39ms p(90)=9.74µs  p(95)=13.83µs
     http_req_tls_handshaking.......: avg=0s         min=0s      med=0s      max=0s      p(90)=0s      p(95)=0s     
     http_req_waiting...............: avg=21.64ms    min=3.36ms  med=20.92ms max=1.18s   p(90)=27.17ms p(95)=29.15ms
     http_reqs......................: 137846 4594.12808/s
     iteration_duration.............: avg=43.49ms    min=11.63ms med=41.67ms max=1.21s   p(90)=48.81ms p(95)=53.58ms
     iterations.....................: 68894  2296.097529/s
     vus............................: 60     min=60        max=100 
     vus_max........................: 100    min=100       max=100 

Copy link
Contributor

github-actions bot commented Feb 18, 2025

@benchmarks/node-fetch results (consumeBody)

   ✓ active_handles.................: avg=140.523623 min=11      med=141     max=193     p(90)=159     p(95)=163    
     data_received..................: 20 MB  650 kB/s
     data_sent......................: 13 MB  416 kB/s
     http_req_blocked...............: avg=2.09µs     min=691ns   med=1.38µs  max=3.02ms  p(90)=2.11µs  p(95)=2.41µs 
     http_req_connecting............: avg=240ns      min=0s      med=0s      max=2.21ms  p(90)=0s      p(95)=0s     
     http_req_duration..............: avg=23.47ms    min=2.52ms  med=22.79ms max=1.21s   p(90)=29.37ms p(95)=31.03ms
       { expected_response:true }...: avg=23.47ms    min=2.52ms  med=22.79ms max=1.21s   p(90)=29.37ms p(95)=31.03ms
     http_req_failed................: 0.00%  ✓ 0           ✗ 127393
     http_req_receiving.............: avg=35.82µs    min=9.84µs  med=26.48µs max=15.64ms p(90)=40.75µs p(95)=47.58µs
     http_req_sending...............: avg=11.5µs     min=3.6µs   med=6.96µs  max=14.5ms  p(90)=10.62µs p(95)=15µs   
     http_req_tls_handshaking.......: avg=0s         min=0s      med=0s      max=0s      p(90)=0s      p(95)=0s     
     http_req_waiting...............: avg=23.42ms    min=2.47ms  med=22.75ms max=1.21s   p(90)=29.32ms p(95)=30.97ms
     http_reqs......................: 127393 4245.992517/s
     iteration_duration.............: avg=47.06ms    min=10.06ms med=45.47ms max=1.23s   p(90)=50.72ms p(95)=56.85ms
     iterations.....................: 63666  2121.979697/s
     vus............................: 100    min=100       max=100 
     vus_max........................: 100    min=100       max=100 

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (5)
packages/server/src/createServerAdapter.ts (3)

104-104: Optional doc comment for tracer
Consider adding a brief explanation of the tracer property to clarify its optional usage and purpose.


148-155: Improve error details when multiple tracers are found
This block properly enforces the single-tracer constraint, but it might be helpful to include the plugin's identifier or name in the error message to aid in debugging.

-          throw new Error(
-            'Multiple tracers have been declared. Only one plugin with a tracer is allowed.',
-          );
+          throw new Error(
+            `Multiple tracers have been declared. Only one plugin with a tracer is allowed. Plugin: ${plugin.name || 'unknown'}`
+          );

252-262: Handle potential undefined response
If tracer.request never invokes the wrapped function, response may remain undefined. Consider providing a fallback response or throwing an error, rather than relying on the non-null assertion.

-      return isPromise(tracerPromise) ? tracerPromise.then(() => response) : response!;
+      return isPromise(tracerPromise)
+        ? tracerPromise.then(() => response ?? new Response('No response returned by tracer', { status: 500 }))
+        : (response ?? new Response('No response returned by tracer', { status: 500 }));
packages/server/src/plugins/types.ts (2)

1-1: Remove unused import or adjust usage
The imported MaybePromise is currently unused. If you plan to unify your promise signatures with MaybePromise, consider applying it to your tracer definition. Otherwise, remove the import.


53-58: Unify signature with MaybePromise
You already import MaybePromise; consider using it here for consistency, for instance:
request: (payload: { request: Request }, wrapped: () => MaybePromise<void>) => MaybePromise<void>;

-export type Tracer = {
-  request: (
-    payload: { request: Request },
-    wrapped: () => Promise<void> | void,
-  ) => Promise<void> | void;
-};
+export type Tracer = {
+  request: (
+    payload: { request: Request },
+    wrapped: () => MaybePromise<void>,
+  ) => MaybePromise<void>;
+};
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 005485d and 214e981.

📒 Files selected for processing (3)
  • .gitignore (1 hunks)
  • packages/server/src/createServerAdapter.ts (5 hunks)
  • packages/server/src/plugins/types.ts (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • .gitignore
🧰 Additional context used
🪛 Biome (1.9.4)
packages/server/src/plugins/types.ts

[error] 8-8: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

⏰ Context from checks skipped due to timeout of 90000ms (20)
  • GitHub Check: unit / node 23
  • GitHub Check: unit / node 22
  • GitHub Check: unit / deno
  • GitHub Check: unit / node 20
  • GitHub Check: unit / bun
  • GitHub Check: esm
  • GitHub Check: server (undici)
  • GitHub Check: e2e / cloudflare-modules
  • GitHub Check: server (ponyfill)
  • GitHub Check: e2e / cloudflare-workers
  • GitHub Check: unit / node 18
  • GitHub Check: lint
  • GitHub Check: e2e / azure-function
  • GitHub Check: node-fetch (consumeBody)
  • GitHub Check: prettier
  • GitHub Check: server (native)
  • GitHub Check: e2e / aws-lambda
  • GitHub Check: node-fetch (noConsumeBody)
  • GitHub Check: type check
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (3)
packages/server/src/createServerAdapter.ts (2)

3-3: Looking good for the new import of Tracer
No issues spotted with the added import statement.


176-176: Allowing re-assignment of handleRequest
Switching from const to let is correct to accommodate wrapping the request handler with tracer logic.

packages/server/src/plugins/types.ts (1)

9-13: Typo in documentation and consider making property optional

  1. "insance" should be "instance".
  2. The usage in createServerAdapter checks if plugin.tracer exists, so consider marking tracer as optional (tracer?: Tracer;).
    [nitpick, refactor_suggestion_good_to_have]
-   * A tracer insance. It can be used to wrap...
+   * A tracer instance. It can be used to wrap...

Copy link
Contributor

github-actions bot commented Feb 18, 2025

@benchmarks/server results (native)

     ✓ no-errors
     ✓ expected-result

   ✓ checks.........................: 100.00% ✓ 229368      ✗ 0     
     data_received..................: 23 MB   768 kB/s
     data_sent......................: 9.2 MB  306 kB/s
     http_req_blocked...............: avg=1.41µs   min=902ns    med=1.2µs    max=197.97µs p(90)=1.9µs    p(95)=2.05µs  
     http_req_connecting............: avg=1ns      min=0s       med=0s       max=132.93µs p(90)=0s       p(95)=0s      
     http_req_duration..............: avg=198.34µs min=144.21µs med=188.28µs max=10.42ms  p(90)=214.25µs p(95)=223.7µs 
       { expected_response:true }...: avg=198.34µs min=144.21µs med=188.28µs max=10.42ms  p(90)=214.25µs p(95)=223.7µs 
     http_req_failed................: 0.00%   ✓ 0           ✗ 114684
     http_req_receiving.............: avg=25.69µs  min=13.56µs  med=23.86µs  max=2.79ms   p(90)=31.04µs  p(95)=33.72µs 
     http_req_sending...............: avg=6.45µs   min=4.24µs   med=5.61µs   max=394.89µs p(90)=8.22µs   p(95)=8.98µs  
     http_req_tls_handshaking.......: avg=0s       min=0s       med=0s       max=0s       p(90)=0s       p(95)=0s      
     http_req_waiting...............: avg=166.19µs min=117.71µs med=156.2µs  max=10.38ms  p(90)=179.08µs p(95)=187.94µs
     http_reqs......................: 114684  3822.649812/s
     iteration_duration.............: avg=257.04µs min=186.71µs med=246.12µs max=10.51ms  p(90)=275.71µs p(95)=288.14µs
     iterations.....................: 114684  3822.649812/s
     vus............................: 1       min=1         max=1   
     vus_max........................: 1       min=1         max=1   

Copy link
Contributor

github-actions bot commented Feb 18, 2025

@benchmarks/server results (ponyfill)

     ✓ no-errors
     ✓ expected-result

   ✓ checks.........................: 100.00% ✓ 290134      ✗ 0     
     data_received..................: 29 MB   953 kB/s
     data_sent......................: 12 MB   387 kB/s
     http_req_blocked...............: avg=1.41µs   min=861ns   med=1.19µs   max=194.51µs p(90)=1.9µs    p(95)=2.08µs  
     http_req_connecting............: avg=0ns      min=0s      med=0s       max=118.99µs p(90)=0s       p(95)=0s      
     http_req_duration..............: avg=143.06µs min=95.67µs med=137.84µs max=5.96ms   p(90)=159.84µs p(95)=166.99µs
       { expected_response:true }...: avg=143.06µs min=95.67µs med=137.84µs max=5.96ms   p(90)=159.84µs p(95)=166.99µs
     http_req_failed................: 0.00%   ✓ 0           ✗ 145067
     http_req_receiving.............: avg=24.76µs  min=12.41µs med=23.12µs  max=2.91ms   p(90)=30.29µs  p(95)=32.98µs 
     http_req_sending...............: avg=6.39µs   min=4.03µs  med=5.56µs   max=498.84µs p(90)=8.17µs   p(95)=9.11µs  
     http_req_tls_handshaking.......: avg=0s       min=0s      med=0s       max=0s       p(90)=0s       p(95)=0s      
     http_req_waiting...............: avg=111.9µs  min=68.58µs med=106.38µs max=5.82ms   p(90)=125.5µs  p(95)=131.47µs
     http_reqs......................: 145067  4835.345001/s
     iteration_duration.............: avg=202.15µs min=144.4µs med=196.38µs max=6.31ms   p(90)=221.73µs p(95)=230.87µs
     iterations.....................: 145067  4835.345001/s
     vus............................: 1       min=1         max=1   
     vus_max........................: 1       min=1         max=1   

Copy link
Contributor

github-actions bot commented Feb 18, 2025

@benchmarks/server results (undici)

     ✓ no-errors
     ✓ expected-result

   ✓ checks.........................: 100.00% ✓ 221990     ✗ 0     
     data_received..................: 22 MB   744 kB/s
     data_sent......................: 8.9 MB  296 kB/s
     http_req_blocked...............: avg=1.37µs   min=902ns    med=1.16µs   max=1.11ms   p(90)=1.84µs   p(95)=2µs     
     http_req_connecting............: avg=1ns      min=0s       med=0s       max=119.03µs p(90)=0s       p(95)=0s      
     http_req_duration..............: avg=209.21µs min=153.94µs med=196.84µs max=57.37ms  p(90)=223.8µs  p(95)=233.36µs
       { expected_response:true }...: avg=209.21µs min=153.94µs med=196.84µs max=57.37ms  p(90)=223.8µs  p(95)=233.36µs
     http_req_failed................: 0.00%   ✓ 0          ✗ 110995
     http_req_receiving.............: avg=24.97µs  min=14.02µs  med=23.33µs  max=2.51ms   p(90)=30.26µs  p(95)=32.75µs 
     http_req_sending...............: avg=6.23µs   min=4.08µs   med=5.34µs   max=568.88µs p(90)=8.08µs   p(95)=8.66µs  
     http_req_tls_handshaking.......: avg=0s       min=0s       med=0s       max=0s       p(90)=0s       p(95)=0s      
     http_req_waiting...............: avg=178µs    min=131.54µs med=165.16µs max=57.3ms   p(90)=189.04µs p(95)=197.81µs
     http_reqs......................: 110995  3699.69396/s
     iteration_duration.............: avg=265.94µs min=196.43µs med=252.55µs max=57.51ms  p(90)=283.01µs p(95)=295.57µs
     iterations.....................: 110995  3699.69396/s
     vus............................: 1       min=1        max=1   
     vus_max........................: 1       min=1        max=1   

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
packages/server/src/plugins/types.ts (2)

8-12: Fix typo in JSDoc comment.

There's a typo in the JSDoc comment: "insance" should be "instance".

- * A tracer insance. It can be used to wrap the entire request handling pipeline (including the
+ * A tracer instance. It can be used to wrap the entire request handling pipeline (including the

52-57: Add JSDoc documentation and consider error handling.

The Tracer type would benefit from:

  1. JSDoc documentation explaining its purpose and usage
  2. Explicit error handling guidance for the wrapped function

Add JSDoc documentation and consider error handling:

 export type Tracer = {
+  /**
+   * Wraps a request handling operation for tracing purposes.
+   * @param payload - The payload containing the request to be traced
+   * @param wrapped - The function to be traced
+   * @throws - Document expected errors and how they should be handled
+   * @returns A promise that resolves when the traced operation completes
+   */
   request: (
     payload: { request: Request },
     wrapped: () => Promise<void> | void,
   ) => Promise<void> | void;
 };

Consider adding error handling guidance by documenting:

  1. What happens if the wrapped function throws?
  2. Should the tracer catch and log errors?
  3. Should errors be propagated or transformed?

Would you like me to propose a more detailed error handling implementation?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 214e981 and e124814.

📒 Files selected for processing (1)
  • packages/server/src/plugins/types.ts (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: unit / node 22
  • GitHub Check: unit / node 18

Copy link
Contributor

github-actions bot commented Feb 18, 2025

🚀 Snapshot Release (alpha)

The latest changes of this PR are available as alpha on npm (based on the declared changesets):

Package Version Info
@whatwg-node/promise-helpers 1.2.2-alpha-20250304145637-5149d6730561e4ebb207798aac0719737cbb7cc6 npm ↗︎ unpkg ↗︎
@whatwg-node/server 0.10.0-alpha-20250304145637-5149d6730561e4ebb207798aac0719737cbb7cc6 npm ↗︎ unpkg ↗︎
@whatwg-node/server-plugin-cookies 1.0.5-alpha-20250304145637-5149d6730561e4ebb207798aac0719737cbb7cc6 npm ↗︎ unpkg ↗︎

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
.changeset/purple-buses-try.md (1)

5-6: Expand on the Tracer API Description for Better Developer Guidance
The short description "Add new Tracer API" is clear but could benefit from additional details. Consider adding more context about the Tracer API's role (e.g., its purpose for wrapping request phases or performance monitoring) or linking to further documentation. This would help developers understand the impact and usage of the new feature.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e124814 and bb3f75a.

📒 Files selected for processing (1)
  • .changeset/purple-buses-try.md (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (13)
  • GitHub Check: unit / node 23
  • GitHub Check: unit / node 22
  • GitHub Check: unit / node 20
  • GitHub Check: unit / node 18
  • GitHub Check: type check
  • GitHub Check: server (undici)
  • GitHub Check: node-fetch (consumeBody)
  • GitHub Check: unit / deno
  • GitHub Check: server (ponyfill)
  • GitHub Check: unit / bun
  • GitHub Check: e2e / azure-function
  • GitHub Check: node-fetch (noConsumeBody)
  • GitHub Check: server (native)
🔇 Additional comments (1)
.changeset/purple-buses-try.md (1)

1-3: Ensure Consistent Version Bumping for the New Tracer API
The changeset correctly indicates a minor version update for the package @whatwg-node/server, which aligns with adding a new feature. Ensure that this update is consistent with the release strategy and that related documentation (e.g., changelogs and release notes) is updated accordingly.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/server/src/createServerAdapter.ts (1)

176-176: Consider simplifying the tracer implementation.

The tracing implementation is solid but could be more concise.

Consider this simplified version:

-if (tracer?.request) {
+if (tracer) {
   const originalRequestHandler = handleRequest;
   handleRequest = (request, initialContext) => {
     let response: Promise<Response> | Response;
-    const tracerPromise = tracer!.request!({ request }, () => {
+    const tracerPromise = tracer.request?.({ request }, () => {
       response = originalRequestHandler(request, initialContext);
       return isPromise(response) ? response.then(() => undefined) : undefined;
     });
-    return isPromise(tracerPromise) ? tracerPromise.then(() => response) : response!;
+    return tracerPromise ? tracerPromise.then(() => response) : response;
   };
 }

This version:

  1. Removes unnecessary non-null assertions
  2. Uses optional chaining more effectively
  3. Simplifies the return statement

Also applies to: 252-262

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 058be08 and de7e6d1.

📒 Files selected for processing (1)
  • packages/server/src/createServerAdapter.ts (5 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (12)
  • GitHub Check: unit / node 23
  • GitHub Check: unit / deno
  • GitHub Check: unit / node 22
  • GitHub Check: unit / node 20
  • GitHub Check: unit / bun
  • GitHub Check: server (undici)
  • GitHub Check: unit / node 18
  • GitHub Check: server (ponyfill)
  • GitHub Check: node-fetch (consumeBody)
  • GitHub Check: server (native)
  • GitHub Check: e2e / azure-function
  • GitHub Check: node-fetch (noConsumeBody)
🔇 Additional comments (2)
packages/server/src/createServerAdapter.ts (2)

3-3: LGTM!

Clean import of the Tracer type, maintaining consistency with existing imports.


104-104: LGTM! Robust tracer validation.

The implementation ensures that only one tracer can be declared, with proper error handling and clear error messages.

Also applies to: 148-155

Copy link
Owner

@ardatan ardatan left a comment

Choose a reason for hiding this comment

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

Do you think we need tests?

Copy link
Collaborator

yes!

@EmrysMyrddin
Copy link
Collaborator Author

Yes, I wanted to wait for the approbation of the design of the new API before passing time on tests and documentation :-)

Copy link
Collaborator

I think design is confirmed, no need to wait for additional approvals, we can proceed with testing 🙂

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/server/src/createServerAdapter.ts (1)

149-156: Consider improving error message for multiple tracers

Throwing an error upon finding more than one tracer is a good safeguard. Including which plugin declared the second tracer could help diagnose conflicts more quickly.

- throw new Error(
-   'Multiple tracers have been declared. Only one plugin with a tracer is allowed.',
- );
+ throw new Error(
+   `Multiple tracers have been declared. Plugin "${plugin.name ?? 'unknown'}" tried to register a second tracer.`,
+ );
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between de7e6d1 and 9627f0b.

📒 Files selected for processing (4)
  • .changeset/purple-buses-try.md (1 hunks)
  • .gitignore (1 hunks)
  • packages/server/src/createServerAdapter.ts (5 hunks)
  • packages/server/src/plugins/types.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • .changeset/purple-buses-try.md
  • .gitignore
  • packages/server/src/plugins/types.ts
⏰ Context from checks skipped due to timeout of 90000ms (13)
  • GitHub Check: unit / node 23
  • GitHub Check: unit / node 22
  • GitHub Check: unit / node 20
  • GitHub Check: unit / deno
  • GitHub Check: unit / node 18
  • GitHub Check: unit / bun
  • GitHub Check: e2e / cloudflare-modules
  • GitHub Check: type check
  • GitHub Check: e2e / cloudflare-workers
  • GitHub Check: server (ponyfill)
  • GitHub Check: e2e / azure-function
  • GitHub Check: prettier
  • GitHub Check: e2e / aws-lambda
🔇 Additional comments (4)
packages/server/src/createServerAdapter.ts (4)

4-4: Import of Tracer is valid and consistent

No issues. The import of Tracer from ./plugins/types.js aligns well with the new functionality.


105-106: Optional tracer variable looks good

Defining let tracer: Tracer | undefined; is a clean approach to conditionally store the tracer.


177-178: Reassigning handleRequest is appropriate

Changing to a let declaration allows reassigning with tracer logic. This is a valid approach.


250-260:

❓ Verification inconclusive

Verify that all tracer implementations call the callback

The tracer logic here depends on tracer.request invoking the callback to assign response. If any plugin’s tracer.request is missing its callback invocation, response remains uninitialized, causing potential runtime errors.

Below is a script to search for all tracer.request usages and confirm callback invocation:


🏁 Script executed:

#!/bin/bash
# Description: Find and inspect all calls to tracer.request in the codebase.

rg -A 5 "tracer\.request"

Length of output: 27


Manual Verification Required: Ensure Callback Invocation in All tracer.request Usages

The automated search for "tracer\.request" did not yield any additional instances beyond the snippet in question. Given this outcome, please manually verify that every implementation of tracer.request—including those in external plugins—properly invokes the callback. This is crucial because if a plugin omits the callback call, the response may remain uninitialized, potentially leading to runtime issues.

  • Action Required: Manually inspect all plugin implementations of tracer.request to confirm they call the provided callback, ensuring the assignment to response is always executed.
  • File for Reference: packages/server/src/createServerAdapter.ts (see lines 250-260)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
.changeset/@whatwg-node_server-2068-dependencies.md (1)

4-6: Resolve Markdown List Indentation Warning

Static analysis indicates that the unordered list on line 5 is indented by 2 spaces, but the standard (MD007) expects 0 spaces. Consider removing the extra indentation to satisfy markdownlint:

-  - Added dependency [`@envelop/instruments@1.0.0-alpha-20250227114734-64d7083775b6c1ee4ce365437ae5f77c33aee3a5` ↗︎](https://www.npmjs.com/package/@envelop/instruments/v/1.0.0) (to `dependencies`)
+ - Added dependency [`@envelop/instruments@1.0.0-alpha-20250227114734-64d7083775b6c1ee4ce365437ae5f77c33aee3a5` ↗︎](https://www.npmjs.com/package/@envelop/instruments/v/1.0.0) (to `dependencies`)

This adjustment will align with the project's markdown style guidelines.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

5-5: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 229f8b7 and 2f22410.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (2)
  • .changeset/@whatwg-node_server-2068-dependencies.md (1 hunks)
  • packages/server/package.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/server/package.json
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
.changeset/@whatwg-node_server-2068-dependencies.md

5-5: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)

🔇 Additional comments (1)
.changeset/@whatwg-node_server-2068-dependencies.md (1)

1-3: Verify Changeset Header Structure

The changeset header is properly formatted using the conventional YAML-like separator lines and specifies a patch update for @whatwg-node/server. This structure looks consistent with typical changeset conventions.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
.changeset/@whatwg-node_server-2068-dependencies.md (1)

5-5: Adjust Unordered List Indentation to Satisfy Markdown Linting

The unordered list item on line 5 is indented by two spaces, which is triggering the MD007 warning regarding unordered list indentation. Consider unindenting the list item to align at the start of the line (0 spaces) for compliance with markdownlint guidelines.

-  - Added dependency [`@envelop/instruments@1.0.0-alpha-20250227122402-42e2fa806ec3b7c2936e612924b153a20c8662c3` ↗︎](https://www.npmjs.com/package/@envelop/instruments/v/1.0.0) (to `dependencies`)
+ - Added dependency [`@envelop/instruments@1.0.0-alpha-20250227122402-42e2fa806ec3b7c2936e612924b153a20c8662c3` ↗︎](https://www.npmjs.com/package/@envelop/instruments/v/1.0.0) (to `dependencies`)
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

5-5: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2f22410 and 36012c9.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (2)
  • .changeset/@whatwg-node_server-2068-dependencies.md (1 hunks)
  • packages/server/package.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/server/package.json
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
.changeset/@whatwg-node_server-2068-dependencies.md

5-5: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)

🔇 Additional comments (1)
.changeset/@whatwg-node_server-2068-dependencies.md (1)

1-6: Dependency Update Documentation is Clear and Informative

The changeset entry correctly documents the addition of the new dependency @envelop/instruments@1.0.0-alpha-20250227122402-42e2fa806ec3b7c2936e612924b153a20c8662c3. The format, including the version and hyperlink to npm, provides clear context for downstream consumers of the changeset.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

5-5: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
.changeset/@whatwg-node_server-2068-dependencies.md (1)

5-6: Fix markdown list indentation.

The markdown linter has flagged an inconsistency in the list indentation. According to markdown standards, unordered lists should start at indentation level 0, but they're currently at level 2.

-  - Updated dependency [`@whatwg-node/promise-helpers@^1.2.2` ↗︎](https://www.npmjs.com/package/@whatwg-node/promise-helpers/v/1.2.2) (from `^1.0.0`, in `dependencies`)
-  - Added dependency [`@envelop/instruments@1.0.0-alpha-20250227122402-42e2fa806ec3b7c2936e612924b153a20c8662c3` ↗︎](https://www.npmjs.com/package/@envelop/instruments/v/1.0.0) (to `dependencies`)
+- Updated dependency [`@whatwg-node/promise-helpers@^1.2.2` ↗︎](https://www.npmjs.com/package/@whatwg-node/promise-helpers/v/1.2.2) (from `^1.0.0`, in `dependencies`)
+- Added dependency [`@envelop/instruments@1.0.0-alpha-20250227122402-42e2fa806ec3b7c2936e612924b153a20c8662c3` ↗︎](https://www.npmjs.com/package/@envelop/instruments/v/1.0.0) (to `dependencies`)
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

5-5: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


6-6: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)

packages/server/test/instruments.spec.ts (2)

30-31: Consider adding more request scenarios.

The test currently makes a single request and verifies the execution order. To increase confidence in the implementation, consider adding more complex scenarios such as:

  1. Testing with error conditions
  2. Testing with different request methods or parameters
  3. Testing the actual response data
 await adapter.fetch('http://whatwg-node/graphql');
 expect(results).toEqual(['pre-1', 'pre-2', 'pre-3', 'request', 'post-3', 'post-2', 'post-1']);
+
+ // Reset results for the next test
+ results.length = 0;
+ 
+ // Test with error scenario
+ const errorAdapter = createServerAdapter<unknown>(
+   () => {
+     results.push('error-request');
+     throw new Error('Test error');
+   },
+   {
+     plugins: [make('1'), make('2'), make('3')],
+   },
+ );
+
+ try {
+   await errorAdapter.fetch('http://whatwg-node/graphql');
+ } catch (error) {
+   // Error expected
+ }
+ // Verify instruments still execute in correct order even with errors
+ expect(results).toEqual(['pre-1', 'pre-2', 'pre-3', 'error-request', 'post-3', 'post-2', 'post-1']);

8-18: Consider adding type for the wrapped function parameter.

The wrapped parameter in the request instrument function doesn't have an explicit type, which might make it harder to understand what it's supposed to do. Consider adding a type annotation for clarity.

-          request: async (_, wrapped) => {
+          request: async (_, wrapped: () => Promise<void>) => {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1796ef3 and a96b225.

📒 Files selected for processing (2)
  • .changeset/@whatwg-node_server-2068-dependencies.md (1 hunks)
  • packages/server/test/instruments.spec.ts (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
packages/server/test/instruments.spec.ts

[error] 20-20: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

🪛 markdownlint-cli2 (0.17.2)
.changeset/@whatwg-node_server-2068-dependencies.md

5-5: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


6-6: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)

🔇 Additional comments (3)
.changeset/@whatwg-node_server-2068-dependencies.md (1)

1-6:

✅ Verification successful

Dependency updates look appropriate for the Tracer API.

The dependency updates align well with the PR's objective of introducing a new Tracer API, which requires the alpha version of @envelop/instruments. The patch version update is appropriate since this is a non-breaking feature addition.


🏁 Script executed:

#!/bin/bash
# Verify if the @envelop/instruments package is available and check its details

# Check if the package exists on npm
echo "Checking @envelop/instruments package details:"
npm view @envelop/instruments version description

# Check for @whatwg-node/promise-helpers to ensure it's compatible
echo "Checking @whatwg-node/promise-helpers latest version:"
npm view @whatwg-node/promise-helpers version

Length of output: 502


Dependency Updates Verified for the Tracer API Integration

  • Confirmed that @whatwg-node/promise-helpers is now at version 1.2.2 as expected.
  • Verified that the PR intentionally specifies an alpha version of @envelop/instruments (required for the new Tracer API), even though the latest stable version on npm is 5.0.3.
  • The patch update for @whatwg-node/server correctly indicates non-breaking changes.

These dependency updates align well with the PR’s objective.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

5-5: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


6-6: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)

packages/server/test/instruments.spec.ts (2)

1-33: Test coverage for the new Tracer API looks good.

The test file effectively validates the core functionality of the new Tracer API by checking that:

  1. Multiple plugins can provide instrumentation
  2. The request handlers are wrapped correctly
  3. The order of execution follows the expected pattern (first-in-last-out)

This ensures the instrumentation implementation is working as expected and composable.

🧰 Tools
🪛 Biome (1.9.4)

[error] 20-20: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)


4-33:

✅ Verification successful

Verify integration with other server adapter features.

This test ensures that the instrumentation works in isolation, but it would be valuable to verify that it integrates well with other server adapter features like middleware, error handling, etc.


🏁 Script executed:

#!/bin/bash
# Description: Check for integration with other server adapter features

# Look for other server adapter tests that might need to be updated
echo "Checking for existing server adapter tests:"
fd --type file "spec.ts|test.ts" packages/server/test/

# Check the server adapter implementation to understand integration points
echo "Server adapter implementation:"
cat packages/server/src/createServerAdapter.ts | grep -A 10 "instruments"

# Check if there are any related middleware or error handling features
echo "Looking for middleware implementations:"
fd --type file "middleware" packages/server/src/

Length of output: 3042


Integration Verification Complete – Instrumentation is Properly Chained with Core Adapter Features

The instrumentation is correctly integrated with the adapter’s plugin hooks (e.g., onRequest and onResponse) as reflected in the implementation in packages/server/src/createServerAdapter.ts, and related integration (like error handling) is indirectly verified by tests such as useErrorHandling.spec.ts. Note that no middleware implementations exist at this time, so middleware integration isn’t applicable until such features are introduced.

🧰 Tools
🪛 Biome (1.9.4)

[error] 20-20: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

};
}

const adapter = createServerAdapter<{}>(
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Replace empty object type with a more specific type.

Using {} as a type is discouraged as it means "any non-nullable value" rather than "empty object" as often expected. Consider using a more specific type or unknown if the generic type parameter isn't important for this test.

-const adapter = createServerAdapter<{}>(
+const adapter = createServerAdapter<unknown>(

Alternative solutions depending on the actual requirements:

// If you need to specify an empty object type:
const adapter = createServerAdapter<Record<string, never>>(

// Or if there's a specific context type that should be used:
const adapter = createServerAdapter<YourContextType>(
🧰 Tools
🪛 Biome (1.9.4)

[error] 20-20: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
.changeset/@whatwg-node_server-2068-dependencies.md (1)

5-6: Fix unordered list indentation

The markdown linter is flagging that the list items are indented with 2 spaces instead of being at column 0.

- dependencies updates:
-   - Updated dependency [`@whatwg-node/promise-helpers@^1.2.2` ↗︎](https://www.npmjs.com/package/@whatwg-node/promise-helpers/v/1.2.2) (from `^1.0.0`, in `dependencies`)
-   - Added dependency [`@envelop/instruments@1.0.0-alpha-20250227122402-42e2fa806ec3b7c2936e612924b153a20c8662c3` ↗︎](https://www.npmjs.com/package/@envelop/instruments/v/1.0.0) (to `dependencies`)
+ dependencies updates:
+ - Updated dependency [`@whatwg-node/promise-helpers@^1.2.2` ↗︎](https://www.npmjs.com/package/@whatwg-node/promise-helpers/v/1.2.2) (from `^1.0.0`, in `dependencies`)
+ - Added dependency [`@envelop/instruments@1.0.0-alpha-20250227122402-42e2fa806ec3b7c2936e612924b153a20c8662c3` ↗︎](https://www.npmjs.com/package/@envelop/instruments/v/1.0.0) (to `dependencies`)
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

5-5: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


6-6: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)

packages/server/test/instruments.spec.ts (1)

4-33: Consider additional test cases for comprehensive coverage

The current test covers the basic happy path for instruments. Consider adding tests for:

  1. Error handling - what happens if an instrument throws an error?
  2. Empty plugins array - does it work correctly without any instruments?
  3. Async operations in the request handler - ensure proper awaiting
  4. Return value manipulation - can instruments modify the response?
it('should handle errors in instruments gracefully', async () => {
  const results: string[] = [];
  
  function makeWithError(): ServerAdapterPlugin {
    return {
      instruments: {
        request: async (_, wrapped) => {
          results.push('pre-error');
          try {
            await wrapped();
          } catch (error) {
            results.push('caught-error');
            throw error; // re-throw to propagate
          }
        },
      },
    };
  }
  
  const errorPlugin: ServerAdapterPlugin = {
    instruments: {
      request: async () => {
        throw new Error('Test error');
      },
    },
  };
  
  const adapter = createServerAdapter<Record<string, never>>(
    () => {
      results.push('request');
      return Response.json({ message: 'Hello, World!' });
    },
    {
      plugins: [makeWithError(), errorPlugin],
    },
  );
  
  await expect(adapter.fetch('http://whatwg-node/graphql')).rejects.toThrow();
  expect(results).toEqual(['pre-error', 'caught-error']);
});
🧰 Tools
🪛 Biome (1.9.4)

[error] 20-20: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1796ef3 and a96b225.

📒 Files selected for processing (2)
  • .changeset/@whatwg-node_server-2068-dependencies.md (1 hunks)
  • packages/server/test/instruments.spec.ts (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
packages/server/test/instruments.spec.ts

[error] 20-20: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

🪛 markdownlint-cli2 (0.17.2)
.changeset/@whatwg-node_server-2068-dependencies.md

5-5: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


6-6: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)

🔇 Additional comments (3)
.changeset/@whatwg-node_server-2068-dependencies.md (1)

1-6:

❓ Verification inconclusive

Marked as patch with alpha dependency - consider versioning strategy

The changeset correctly documents the dependency updates, but I'd like to highlight that you're adding an alpha version of @envelop/instruments while marking this as a patch change. Alpha dependencies can introduce stability risks in a patch release.

For future consideration:

  • Consider whether this should be a minor rather than patch version
  • Document when you plan to update to a stable release of @envelop/instruments
  • Ensure there's a migration plan if the API changes between alpha and stable

🌐 Web query:

What are the best practices for semantic versioning when adding alpha dependencies?

💡 Result:

Semantic Versioning (SemVer) provides clear guidelines for managing software dependencies, including alpha or pre-release versions. When incorporating alpha dependencies, these best practices ensure stability and clarity:

Pre-release Version Formatting

  • Use the MAJOR.MINOR.PATCH-alpha.N format (e.g., 2.1.0-alpha.1) to denote alpha versions[1][2].
  • Append labels like -alpha, -beta, or -rc (release candidate) to distinguish pre-release builds[1][8].

Dependency Specification

  • Exact versions: Pin alpha dependencies to specific versions (e.g., 1.0.0-alpha.3) to avoid unintended updates[5][9].
  • Avoid automatic ranges: Tools like npm default to ignoring pre-releases unless explicitly included. Use 1.0.0-alpha or ^1.0.0-alpha to allow compatible pre-releases[5].

Stability and Compatibility

  • Treat alpha dependencies as unstable: They may introduce breaking changes even in minor or patch updates[1][7].
  • Isolate alpha usage: Limit alpha dependencies to non-production environments (e.g., testing, development)[9][10].

Versioning Your Own Releases

  • Minor version increments: If adding an alpha dependency introduces backward-compatible features, increment the minor version (e.g., 1.2.01.3.0)[3][9].
  • Major version increments: Required if the alpha dependency’s changes force breaking API modifications in your project[1][8].

Documentation and Communication

  • Changelogs: Clearly document alpha dependencies and their potential impact[4][10].
  • Warn users: Highlight alpha usage in release notes or README files to set expectations[6][10].

Automation and Tooling

  • CI/CD pipelines: Use tools like semantic-release to automate version bumps when integrating alpha dependencies[4].
  • Lockfiles: Employ package managers’ lockfiles (e.g., package-lock.json) to freeze dependency versions[5].

By adhering to these practices, teams can safely experiment with alpha dependencies while maintaining compatibility and transparency. Always prioritize stability in production environments and reserve alpha usage for early testing phases[7][9].

Citations:


Attention: Revisit Versioning Strategy for Alpha Dependency

The changeset accurately captures the dependency updates for @whatwg-node/server, but including the alpha release of @envelop/instruments in a patch bump raises stability concerns. Best practices for semantic versioning with pre-release (alpha) dependencies suggest that such changes may warrant a minor version bump rather than a patch. This approach better reflects the potential for instability and future API changes.

Recommendations:

  • Version Bump: Confirm if a minor release would be more appropriate given the added alpha dependency.
  • Documentation: Clearly document when you plan to transition to a stable release of @envelop/instruments.
  • Migration Plan: Ensure a robust migration plan is in place for any breaking changes that might occur as the alpha evolves.
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

5-5: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


6-6: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)

packages/server/test/instruments.spec.ts (2)

8-18: Well-structured plugin factory function

The make function creates a plugin with instruments that correctly wraps the request handling logic. The pre/post execution pattern is clean and easily demonstrates the execution flow.


30-31: Well-designed test for verifying execution order

The test effectively validates that the instrument wrappers are composed correctly - executing in order from outer to inner before the request, and then from inner to outer after the request. This matches the expected behavior of properly composed middleware.

};
}

const adapter = createServerAdapter<{}>(
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Replace empty object type with a more specific type

Using {} as a type is discouraged as it means "any non-nullable value" rather than "empty object". It's better to explicitly define the object shape or use a more appropriate type.

- const adapter = createServerAdapter<{}>(
+ const adapter = createServerAdapter<Record<string, never>>(

Alternatively, if there's a specific context type that should be used here, consider using that instead.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const adapter = createServerAdapter<{}>(
const adapter = createServerAdapter<Record<string, never>>(
🧰 Tools
🪛 Biome (1.9.4)

[error] 20-20: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
packages/promise-helpers/src/index.ts (2)

133-144: Consider adding documentation to clarify behavior with null/undefined values.

The function properly handles undefined/null values, but it would be helpful to add JSDoc comments explaining this behavior, especially since you've now explicitly updated the type signature to allow these values.

 export function iterateAsync<TInput, TOutput>(
   iterable: Iterable<TInput>,
   callback: (
     input: TInput,
     endEarly: VoidFunction,
     index: number,
   ) => MaybePromise<TOutput | undefined | null>,
   results?: TOutput[],
 ): MaybePromise<void> {
+  // If the callback returns undefined or null, the value is not added to the results array

108-147: Consider aligning iterateAsyncVoid with the updated type signature.

Since iterateAsyncVoid is an alias for iterateAsync, it inherits the updated type signature. It might be clearer to explicitly re-export with the new type or add a comment clarifying this relationship.

-export { iterateAsync as iterateAsyncVoid };
+// Re-export iterateAsync with the same signature allowing for undefined/null return values
+export { iterateAsync as iterateAsyncVoid };
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a96b225 and 04ffb29.

📒 Files selected for processing (1)
  • packages/promise-helpers/src/index.ts (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: alpha / snapshot
  • GitHub Check: e2e / cloudflare-modules
  • GitHub Check: e2e / cloudflare-workers
  • GitHub Check: server (undici)
  • GitHub Check: e2e / azure-function
  • GitHub Check: node-fetch (consumeBody)
  • GitHub Check: e2e / aws-lambda
  • GitHub Check: server (ponyfill)
  • GitHub Check: node-fetch (noConsumeBody)
  • GitHub Check: server (native)
🔇 Additional comments (2)
packages/promise-helpers/src/index.ts (2)

110-117: Explicit type signature improvement for callback return values.

The updated type signature for the callback parameter in iterateAsync now accurately reflects that the function can handle undefined or null return values. This is consistent with the existing implementation (line 136-138) which already checks if (result) before pushing to the results array.

This change improves type safety by making the API contract more explicit and is likely related to the new Tracer API implementation, where instrumentation callbacks might not always need to return a value.


136-138:

❓ Verification inconclusive

Verify impact on existing code with the type change.

The function already handles falsy return values correctly, but with the explicit type change, it's important to verify that all existing usages of this function are compatible with the updated behavior.


🏁 Script executed:

#!/bin/bash
# Description: Find all usages of iterateAsync to ensure type compatibility with the updated function signature
echo "Searching for iterateAsync usage in the codebase..."
rg "iterateAsync" --type ts --no-filename | grep -v "export function iterateAsync"

Length of output: 470


Attention: Confirm Compatibility with Explicit Type Update

The explicit type change in the function now ensuring falsy return values are properly handled has been applied. The search results show that the function is primarily used via its alias (iterateAsyncVoid), for example in hook invocations, and exported as such. Please verify that these instances of iterateAsyncVoid continue to work as expected with the updated type signatures.

  • Confirm that calls like iterateAsyncVoid(onResponseHooks, onResponseHook => …) and iterateAsyncVoid(onRequestHooks, (onRequestHook, stopEarly) => …) are fully compatible with the new explicit type.
  • Ensure that the alias export (export { iterateAsync as iterateAsyncVoid };) correctly propagates the type changes throughout the codebase.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (4)
.changeset/@whatwg-node_server-2068-dependencies.md (1)

5-6: Fix Markdown List Indentation (MD007)

The unordered list items on these lines use two spaces for indentation, but markdownlint expects no indentation (0 spaces) for list markers. Please remove the extra spaces to comply with MD007.

-  - Updated dependency [`@whatwg-node/promise-helpers@^1.2.2` ↗︎](https://www.npmjs.com/package/@whatwg-node/promise-helpers/v/1.2.2) (from `^1.0.0`, in `dependencies`)
-  - Added dependency [`@envelop/[email protected]` ↗︎](https://www.npmjs.com/package/@envelop/instruments/v/1.0.0) (to `dependencies`)
+ - Updated dependency [`@whatwg-node/promise-helpers@^1.2.2` ↗︎](https://www.npmjs.com/package/@whatwg-node/promise-helpers/v/1.2.2) (from `^1.0.0`, in `dependencies`)
+ - Added dependency [`@envelop/[email protected]` ↗︎](https://www.npmjs.com/package/@envelop/instruments/v/1.0.0) (to `dependencies`)
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

5-5: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


6-6: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)

packages/promise-helpers/src/index.ts (3)

110-117: Type signature enhancement aligns with implementation, but consider refining void usage

The expanded return type MaybePromise<TOutput | undefined | null | void> better aligns with the implementation at line 136-138 which only adds truthy results to the results array. This change provides more flexibility for callback implementations.

Consider addressing the static analysis warning by removing void from the union type:

  callback: (
    input: TInput,
    endEarly: VoidFunction,
    index: number,
-  ) => MaybePromise<TOutput | undefined | null | void>,
+  ) => MaybePromise<TOutput | undefined | null>,

void in union types can be confusing as it represents the absence of a return value rather than an actual value. Since the implementation already handles all falsy values appropriately, using just undefined and null would be more semantically correct.

🧰 Tools
🪛 Biome (1.9.4)

[error] 116-116: void is confusing inside a union type.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)


136-138: Make the result check more explicit to match the expanded return types

The current check uses a simple truthiness test, which handles undefined, null, and void returns, but also excludes falsy values like 0, '', and false, which may be valid outputs of type TOutput.

Consider making the check more explicit to specifically exclude only undefined, null, and void:

-        if (result) {
+        if (result !== undefined && result !== null) {
           results?.push(result);
         }

This change would ensure that all non-null, non-undefined values get added to the results, including falsy values like 0 or '' that might be legitimate TOutput values.


110-117: Add documentation for the expanded return type

Consider adding a JSDoc comment to document the significance of the expanded return type:

+/**
+ * Iterates over an iterable, calling the callback function for each element.
+ * 
+ * @param iterable - The iterable to iterate over
+ * @param callback - A function called for each element, can return a value to be collected 
+ *                  in the results array, or undefined/null to skip collection
+ * @param results - Optional array to collect non-null/undefined results
+ * @returns A promise that resolves when iteration is complete
+ */
export function iterateAsync<TInput, TOutput>(
  iterable: Iterable<TInput>,
  callback: (
    input: TInput,
    endEarly: VoidFunction,
    index: number,
  ) => MaybePromise<TOutput | undefined | null | void>,
  results?: TOutput[],
): MaybePromise<void> {

This documentation would help future developers understand the intent and expected behavior of the callback's return types.

🧰 Tools
🪛 Biome (1.9.4)

[error] 116-116: void is confusing inside a union type.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 84e9572 and bd9cf2e.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (3)
  • .changeset/@whatwg-node_server-2068-dependencies.md (1 hunks)
  • packages/promise-helpers/src/index.ts (1 hunks)
  • packages/server/package.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/server/package.json
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
.changeset/@whatwg-node_server-2068-dependencies.md

5-5: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


6-6: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)

🪛 Biome (1.9.4)
packages/promise-helpers/src/index.ts

[error] 116-116: void is confusing inside a union type.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)

🔇 Additional comments (1)
.changeset/@whatwg-node_server-2068-dependencies.md (1)

1-3: New Dependency Update File Structure Looks Good

This new changeset file correctly documents the dependency updates for the server package. The header and dependency update details are clearly defined.

@EmrysMyrddin EmrysMyrddin changed the title feat(server): New Tracer API feat(server): New Instruments API Mar 4, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (7)
.changeset/purple-buses-try.md (7)

5-8: Fixing Minor Typos in API Introduction
There is a typo in "Introducation" which should be "Introduction". Please review this section to ensure all descriptive text is free of misspellings.


9-12: Review Documentation Clarity and Spelling
The explanation contains several typos:

  • "intup/output" should be "input/output"
  • "araound" should be "around"
  • "incuding" should be "including"
    Consider revising these lines for clarity and professional presentation.

17-42: Improve Usage Example Formatting
The basic usage example effectively demonstrates instrumentation with Sentry. For consistency and clarity, consider updating the span name from "Graphql Operation" to "GraphQL Operation".


44-48: Correct Typos in Multiple Instruments Description
There are a few typos in this section:

  • "possilbe" should be "possible"
  • "outtermost" should be "outermost"
    Please update these to ensure the documentation reads professionally.
🧰 Tools
🪛 LanguageTool

[grammar] ~47-~47: Comparison is written ‘the same … as’.
Context: ...y composed by envelop in the same order than the plugin array (first is outtermost, ...

(THE_SAME_AS)


[misspelling] ~48-~48: This word is normally spelled as one.
Context: ...gin array (first is outtermost, last is inner most). ```ts import { createServerAdapter }...

(EN_COMPOUNDS_INNER_MOST)


50-59: Clarify Import Dependencies in Example Code
The snippet uses useSentry() and useOpentelemetry() functions without showing their import statements. It would improve clarity if you either include the relevant imports or note that these helpers are assumed to be in scope.


69-73: Fix Typos in Custom Instruments Ordering Description
There are minor issues in the description:

  • "suite" should be "suit"
  • "mannually" should be "manually"
    A quick revision will enhance the overall professionalism of the documentation.

74-87: Review Custom Instruments Ordering Code Sample
This code sample effectively demonstrates composing instruments manually using composeInstruments alongside createServerAdapter. The destructuring of sentryInstruments and otelInstruments is clear. Just ensure that, in actual usage, the import statements for useSentry and useOpentelemetry are provided.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bd9cf2e and cac420c.

📒 Files selected for processing (1)
  • .changeset/purple-buses-try.md (1 hunks)
🧰 Additional context used
🪛 LanguageTool
.changeset/purple-buses-try.md

[grammar] ~47-~47: Comparison is written ‘the same … as’.
Context: ...y composed by envelop in the same order than the plugin array (first is outtermost, ...

(THE_SAME_AS)


[misspelling] ~48-~48: This word is normally spelled as one.
Context: ...gin array (first is outtermost, last is inner most). ```ts import { createServerAdapter }...

(EN_COMPOUNDS_INNER_MOST)

⏰ Context from checks skipped due to timeout of 90000ms (17)
  • GitHub Check: unit / node 23
  • GitHub Check: unit / deno
  • GitHub Check: unit / node 22
  • GitHub Check: unit / node 20
  • GitHub Check: unit / node 18
  • GitHub Check: unit / bun
  • GitHub Check: type check
  • GitHub Check: prettier
  • GitHub Check: server (undici)
  • GitHub Check: lint
  • GitHub Check: node-fetch (consumeBody)
  • GitHub Check: alpha / snapshot
  • GitHub Check: server (ponyfill)
  • GitHub Check: esm
  • GitHub Check: node-fetch (noConsumeBody)
  • GitHub Check: server (native)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (3)
.changeset/purple-buses-try.md (3)

1-4: YAML Front Matter Format Valid!
The YAML front matter specifying the version bump for @whatwg-node/server looks correctly formatted.


61-67: Verify Sequence Diagram Accuracy
The Mermaid sequence diagram appears to correctly illustrate the interaction between Sentry, Opentelemetry, and the Server Adapter. Ensure that the depicted sequence aligns with the intended behavior in the instrumentation chain.


89-95: Confirm Custom Instruments Sequence Diagram
The final Mermaid diagram clearly depicts the interaction sequence for custom instrumentation ordering. The visualization is helpful; please verify that it remains in sync with the evolving API design.

@EmrysMyrddin EmrysMyrddin merged commit 516bf60 into master Mar 5, 2025
21 checks passed
@ardatan ardatan deleted the feat/tracer branch May 12, 2025 16:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants