Call Data

Data and metadata can specify template actions that will be parsed and evaluated at every request. Each request gets a new instance of the data. The available variables / actions are:

  1. // CallData represents contextualized data available for templating
  2. type CallData struct {
  3. // unique worker ID
  4. WorkerID string
  5. // unique incremented request number for each call
  6. RequestNumber int64
  7. // fully-qualified name of the method call
  8. FullyQualifiedName string
  9. // shorter call method name
  10. MethodName string
  11. // the service name
  12. ServiceName string
  13. // name of the input message type
  14. InputName string
  15. // name of the output message type
  16. OutputName string
  17. // whether this call is client streaming
  18. IsClientStreaming bool
  19. // whether this call is server streaming
  20. IsServerStreaming bool
  21. // timestamp of the call in RFC3339 format
  22. Timestamp string
  23. // timestamp of the call as unix time in seconds
  24. TimestampUnix int64
  25. // timestamp of the call as unix time in milliseconds
  26. TimestampUnixMilli int64
  27. // timestamp of the call as unix time in nanoseconds
  28. TimestampUnixNano int64
  29. // UUID v4 for each call
  30. UUID string
  31. }

Template Functions

There are also template functions available:

func newUUID() string
Generates a new UUID for each invocation.

func randomString(length int) string
Generates a new random string for each incovation. Accepts a length parameter. If the argument is <= 0 then a random string is generated with a random length between length of 2 and 16.

func randomInt(min, max int) int
Generates a new non-negative pseudo-random number in range [min, max).

Examples

This can be useful to inject variable information into the message data JSON or metadata JSON payloads for each request, such as timestamp or unique request number. For example:

  1. -m '{"request-id":"{{.RequestNumber}}", "timestamp":"{{.TimestampUnix}}"}'

Would result in server getting the following metadata map represented here in JSON:

  1. {
  2. "user-agent": "grpc-go/1.11.1",
  3. "request-id": "1",
  4. "timestamp": "1544890252"
  5. }
  1. -d '{"order_id":"{{newUUID}}", "item_id":"{{newUUID}}", "sku":"{{randomString 8 }}", "product_name":"{{randomString 0}}"}'

Would result in data with JSON representation:

  1. {
  2. "order_id": "3974e7b3-5946-4df5-bed3-8c3dc9a0be19",
  3. "item_id": "cd9c2604-cd9b-43a8-9cbb-d1ad26ca93a4",
  4. "sku": "HlFTAxcm",
  5. "product_name": "xg3NEC"
  6. }

See example calls for some more usage examples.

Data Function API

When using the ghz/runner package programmatically, we can dynamically create data for each request using WithBinaryDataFunc() API:

  1. func dataFunc(mtd *desc.MethodDescriptor, cd *runner.CallData) []byte {
  2. msg := &helloworld.HelloRequest{}
  3. msg.Name = cd.WorkerID
  4. binData, err := proto.Marshal(msg)
  5. return binData
  6. }
  7. report, err := runner.Run(
  8. "helloworld.Greeter.SayHello",
  9. "0.0.0.0:50051",
  10. runner.WithProtoFile("./testdata/greeter.proto", []string{}),
  11. runner.WithInsecure(true),
  12. runner.WithBinaryDataFunc(dataFunc),
  13. )