K6 and Google Protobuf Any type is now accepted by k6 as of version 0.39.0. This is great news as before this version there was a problem with packing and unpacking the variable using the underlying goLang. Here is the bug fix for you to view.
Let’s get down to business. First let’s take a look at our proto file. I tried to make this as different as I can for demonstration purposes. We have here a repeated, enum, string and number.
syntax = "proto3";
package TestLogic.Any.Test;
message CoffeeInstructions {
uint32 sugerLumps = 1;
string clientName = 2;
Milk milk = 3;
repeated string ingredients= 4;
}
enum Milk {
cowsSemi = 0;
cowsFull = 1;
coconut = 2;
almond = 3;
none=4;
}
Bellow is how a request with an “any” parameter will look. The most important part of this is to ensure that K6 knows how to pack and serialise your type. To do this you need to add your proto file to the client.load method. Our calling web-service is in sum.proto and our “any” type is in the CoffeeInstructions.proto.
Next part is creating your data object which includes the payload and has the following elements:
@type definition, which is the namespace and the object you want to send. In this case “TestLogic.Any.Test” is the type and CoffeeInstructions is the object I wanted to send.
Then each of the values in the google.protobuf.any object separated by a comma.
import grpc from 'k6/net/grpc';
import { check, sleep } from 'k6';
const client = new grpc.Client();
client.load(['../proto/theBusyBean', '../proto/anyTypes'],'CoffeeInstructions.proto', 'Sum.proto');
export default () => {
client.connect('localhost:50051', {
plaintext: true,
});
const data = {
payload: {
"@type": "TestLogic.Any.Test.CoffeeInstructions",
"sugerLumps":2,
"clientName":"Fromage Macdonald",
"milk" : 1,
"ingredients":["water", "coffee", "Milk", "TakeAway"]
},
}
const response = client.invoke('Sum.SumService/CalculateSumOfAnyObject', data);
check(response, {
'status is OK': (r) => r && r.status === grpc.StatusOK,
});
console.log(JSON.stringify(response.message));
client.close();
sleep(1);
};
With the proto and the google.proto.any object and values created you can then send it to k6 using the following command.
run K6DataTypeAny.js
This is how it looks when it is sent down the wire. K6 has packed this up and this can then be unpacked using your web-service.
type_url: "TestLogic.Any.Test.CoffeeInstructions"
value: "\b\002\022\021Fromage Macdonald\030\001\"\005water\"\006coffee\"\004Milk\"\bTakeAway"
Nesting? yep you can nest any types, just remember and reference the protobuf so that it can be serialises properly. Here we have the sum.proto, which is the RPC web-service and the two google.proto.any protos, CoffeeInstructions.proto and AlmondMilk.proto.
client.load(['../proto/theBusyBean', '../proto/anyTypes'],'CoffeeInstructions.proto', 'Sum.proto', 'AlmondMilk.proto');
Let’s see what that looks like as an object inside of the K6 script. You can see there are two @type definitions and you can tell it is working correctly because if you delete the proto definition above k6 will throw an error.
const data = {
payload: {
"@type": "TestLogic.Any.Test.CoffeeInstructions",
"sugerLumps":2,
"clientName":"Fromage Macdonald",
"milk" : {
"@type":"TestLogic.Any.Test.AlmondMilk",
"mls":"5",
"Name":"Almond bonanza",
"ProcessingPlant":"Lochee, Dundee",
},
"ingredients":["water", "coffee", "Milk", "TakeAway"]
},
}
and this is how it looks down the wire. The two object are visible, but serialised.
payload {
type_url: "TestLogic.Any.Test.CoffeeInstructions"
value: "\b\002\022\021Fromage Macdonald\032C\n\035TestLogic.Any.Test.AlmondMilk\022\"\b\005\022\016Almond benanza\032\016Lochee, Dundee\"\005water\"\006coffee\"\004Milk\"\bTakeAway"
}
Why would you want to use nested google.protobuf.any. In this example you may have processing plant for artificial milk and farm for animal products. It does make things a little more obscure, so i would use with caution.
This is what the error will look like if you where to forget to define AlmondMilk.proto. This error would throw if you forgot any of the .proto definition files that you are referencing.
ERRO[0000] GoError: unable to serialise request object to protocol buffer: proto: (line 1:125): unable to resolve "TestLogic.Any.Test.AlmondMilk": "not found"
Becareful if you store you’re any protos in differing directories. If you end up with duplicate names as was the case when I was you will see an error.
K6 and Google Protobuf Any type opens k6 up to a new set of consumers. What a great addition! If you want to learn more about GRPC and K6, hop over to my other page Power-up GRPC HTTP/2, a Comprehensive K6 Review.