Version: 0.21.0This documentation is for Spitfire 0.21.0.
gRPC
What it does
A gRPC step calls a method of a gRPC service: unary (one request, one response), server streaming, client streaming and bidirectional (bidi) streaming. You write the request message as JSON; Spitfire uses the schema to turn it into protobuf. The schema comes from one of two places: the server's server reflection service, or .proto files you upload to the connection.
When to use it
- When your microservices talk gRPC to each other and you want to measure one service's latency under load.
- When you want to see, for streaming methods, the time to the first message, the per-message latency and the time between messages.
Creating the connection
- Click Connections → Add connection and pick gRPC as the Type.
- Give it a Name (e.g.
orders-grpc). - Enter the service address in Address (host:port), for example
orders.internal:50051. Required. - If needed:
- Authority: when the
:authorityheader must differ from the address (e.g. a virtual host behind a proxy). - Bearer token: sent on every call as
authorization: Bearer <token>metadata. A secret. - Separate connection per VU: each VU opens its own HTTP/2 connection.
- Shared connections (per runner): with Separate connection per VU off, the VUs of a runner share this many connections (default 8). A single connection would queue calls behind the server's concurrent stream limit (often 100–128) and count that wait as latency, and would send every call to one backend behind an L4 load balancer; hence several connections.
- Authority: when the
- Schema source:
- If reflection is on, upload nothing; the list shows The schema comes from server reflection.
- If reflection is off, choose the service's
.protofiles together with the files they import in .proto files (you can select several). The controller compiles them when you save; a compile error refuses the save and shows the error.
- If TLS is needed, expand TLS and tick Use TLS (see TLS settings).
- Save, then Test.
Adding a step
- In the test editor click Add step → pick gRPC as the Protocol.
- Pick your gRPC connection in Connection.
- The Method list is filled from the schema (Pick a method…). Streaming methods show their kind next to them: server stream, client stream or bidi stream. If the schema cannot be read, Couldn't read the schema; type the method appears; type the method as
package.Service/Method(e.g.shop.v1.Orders/GetOrder). - Write the message in Request message (JSON). Fill in the template inserts an empty JSON skeleton with the selected method's fields. You can use
{{variables}}in the fields. - Add Metadata if needed (e.g.
x-tenant: demo). - For a streaming method, set the stream settings (below).
- Verify the status in the Checks tab: the Status check accepts the gRPC status name (
OK,NOT_FOUND, case-insensitive) or its numeric code. - Send one iteration with Try it, then Save.
{"id": "get-order", "name": "Get order", "protocol": "grpc", "connection": "orders-grpc",
"grpc": {"method": "shop.v1.Orders/GetOrder", "message": "{\"id\": \"{{$uuid}}\"}",
"metadata": [{"key": "x-tenant", "value": "demo"}]},
"checks": [{"type": "status", "value": "OK"}]}Streaming settings
When you pick a streaming method, the Streaming method section opens. One step is one stream.
| Setting | Description |
|---|---|
| Messages to send | For client and bidi streaming: Repeat the message (the same message Count times; {{__MSG}} is the message's number, from 0) or Message list (messages sent in order, added with Add message). Server streaming sends its message once. |
| Interval between messages | The wait between two messages (e.g. 100ms). |
| Keep the sending side open after the last message | Bidi: for servers that end the stream when the client closes its side. Set a response count or duration with it. |
| Responses to wait for | The stream ends after this many responses. Empty: until the server ends the stream. If the server ends it earlier, the step fails as incomplete. |
| Stream duration | The client ends the stream after this; not an error. |
| Timeout (deadline) | Default: the test's request timeout plus this step's pacing. Exceeding it is a DEADLINE_EXCEEDED error. |
| Checks and extraction see | the last response (default) or every response, as a JSON array ($[0].id, $[9].text…). |
A bidi stream that sends ten messages, waits for ten responses and verifies the tenth:
{"id": "chat", "name": "Chat", "protocol": "grpc", "connection": "orders-grpc",
"grpc": {"method": "shop.v1.Chat/Talk", "message": "{\"text\": \"selam {{__MSG}}\"}",
"stream": {"count": 10, "interval": "100ms", "receive": 10, "body": "all"}},
"checks": [{"type": "jsonPath", "path": "$[9].text", "value": "selam 9"}]}The counts of sent and received messages are also in the grpc-messages-sent / grpc-messages-received headers; you can use them in checks.
Metrics it produces
| Metric | Unary | Streaming | Meaning |
|---|---|---|---|
req_duration |
Yes | Yes | Unary: the call; streaming: the whole stream |
req_failed |
Yes | Yes | Rate of calls whose gRPC status is not OK |
grpc_time_to_first_message |
Yes | From opening the stream to the first response | |
grpc_message_latency |
Bidi | Each response is paired with the oldest unanswered message; right for servers that answer each message in order | |
grpc_message_gap |
Yes | For responses that pair with nothing (server streaming, extra pushes): time since the previous response | |
grpc_messages_sent, grpc_messages_received |
Yes | Counters |
On the run page, streaming steps appear in the gRPC streams table (Messages sent, Messages received, First message p95, Message latency p95, Time between messages p95). Threshold example: {"metric": "grpc_time_to_first_message", "expr": "p(95)<300"}.
Common problems
Symptom: The method list is empty, Couldn't read the schema; type the method or Could not read the gRPC schema.
Cause: Server reflection is off and no .proto files are uploaded; or the address/TLS setting is wrong, so the controller cannot reach the server.
Fix: First confirm the connection with Test. If it is green, upload the .proto files with their imports.
Symptom: Uploading .proto files refuses the save with not found / could not resolve import.
Cause: An imported file is missing.
Fix: Select every file in the import chain together (e.g. a shared common.proto).
Symptom: Unavailable, connection refused or transport: authentication handshake failed.
Cause: Wrong port, the service is down, or the TLS setting does not match the server (plain connection to a TLS server or the other way round).
Fix: Check Address (host:port) and Use TLS; add a CA certificate for a private CA.
Symptom: UNAUTHENTICATED or PERMISSION_DENIED.
Cause: Missing or wrong token.
Fix: Type the Bearer token again and save, or send the right header in the step's Metadata.
Symptom: DEADLINE_EXCEEDED on a streaming step.
Cause: The stream did not end before the timeout (the server does not close it, or responses are slow).
Fix: Set Responses to wait for or Stream duration; raise Timeout (deadline) if needed.
Symptom: The step fails with incomplete.
Cause: The server ended the stream before Responses to wait for was reached.
Fix: Set the count to what the server really sends, or leave it empty.
Symptom: p95 rises in steps as load grows while the server's CPU is low. Cause: Many VUs share few HTTP/2 connections and wait at the server's stream limit. Fix: Raise Shared connections (per runner) or tick Separate connection per VU.