Cloud Events

CloudEvents is a specification for describing event data in a common way.

Nuget packages

Example

This is based on an example from github.com/cloudevents which has been serialized as JSON (JavaScript Object Notation). I adapted the code and pushed it to github.com/carlpaton/CloudEventDemo.

This message could be sent via Amazon SQS or via another protocol

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"specversion": "1.0",
"type": "com.github.pull.create", // the type of event, a single consumer may have different handlers per event type
"source": "https://github.com/cloudevents/spec/pull", // something unique about the application that generated
"id": "b8389eed-8fdd-423d-be4f-f575fc6a537a",
"time": "2022-02-25T20:12:25.4607696+13:00", // ISO 8601
"subject" : "123", // optional string
"datacontenttype": "application/json",
"data": {
"Foo": {
"Id": "8448c50d-584c-48b1-8bbb-b9e180f4ff9c",
"Name": "Billy Goat",
"Email": "billy.goat@domain.com",
"Active": true,
"Bar": {
"448fe797-c664-406d-8d1d-d35d3bebe552": "a40dd283-8d88-41fe-bf29-60233bcc3584"
}
},
"Baz": "ccb07ad6-ae9b-48bb-a607-0e0df94905db",
"Bat": "47c7def8-024b-4bd9-b337-3bee28292788"
}
}

Attributes

Attributes are the elements in the object. When using the package CloudNative.CloudEvents we will get some attrubites for free, example

  • "specversion" : "1.0"

There are some required attributes such as

  • "id" : "8448c50d-584c-48b1-8bbb-b9e180f4ff9c"
  • "source" : "https://github.com/cloudevents/spec/pull"
  • "type" : "com.github.pull.create"

When using a serializer the datacontenttype should get set for you. Per their docs the CloudEvent class is not meant to be used with object serializers like JSON.NET.

They suggest using JsonEventFormatter but you can also use XML.

  • "datacontenttype" : "text/xml"
  • "datacontenttype" : "application/json"

The data attribute is your payload, this can be a complex object like

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"Foo": {
"Id": "8448c50d-584c-48b1-8bbb-b9e180f4ff9c",
"Name": "Billy Goat",
"Email": "billy.goat@domain.com",
"Active": true,
"Bar": {
"448fe797-c664-406d-8d1d-d35d3bebe552": "a40dd283-8d88-41fe-bf29-60233bcc3584"
}
},
"Baz": "ccb07ad6-ae9b-48bb-a607-0e0df94905db",
"Bat": "47c7def8-024b-4bd9-b337-3bee28292788"
}

Serialization

Serialization example to create a CloudEvent and serialize it to JSON as message

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using CloudNative.CloudEvents;
using CloudNative.CloudEvents.NewtonsoftJson;
using System.Text;

var dict = new Dictionary<Guid, Guid>();
dict.Add(
Guid.Parse("448fe797-c664-406d-8d1d-d35d3bebe552"),
Guid.Parse("a40dd283-8d88-41fe-bf29-60233bcc3584"));

var cloudEvent = new CloudEvent
{
Type = "com.github.pull.create",
Source = new Uri("https://github.com/cloudevents/spec/pull"),
Id = Guid.NewGuid().ToString(),
Time = DateTime.Now,
Data = new Root() {
Bat = Guid.Parse("47c7def8-024b-4bd9-b337-3bee28292788"),
Baz = Guid.Parse("ccb07ad6-ae9b-48bb-a607-0e0df94905db"),
Foo = new Foo() {
Active = true,
Bar = dict,
Email = "billy.goat@domain.com",
Id = Guid.Parse("8448c50d-584c-48b1-8bbb-b9e180f4ff9c"),
Name = "Billy Goat"
}
}
};

var messageAsByteArray = new JsonEventFormatter().EncodeStructuredModeMessage(cloudEvent, out _);
var message = Encoding.UTF8.GetString(messageAsByteArray.ToArray(), 0, messageAsByteArray.Length);

Console.WriteLine(message);

This is the Data object

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Foo
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public bool Active { get; set; }
public Dictionary<Guid, Guid> Bar { get; set; }
}

public class Root
{
public Foo Foo { get; set; }
public Guid Baz { get; set; }
public Guid Bat { get; set; }
}

Create Extension

We can add additional extension values to the cloud event.

1
2
3
4
5
6
7
8
9
10
11
12
var key = "correlationid";
var val = "5a122a96-f0ee-4d65-bfc9-760c80c870ef";

var attCorrelationId = CloudEventAttribute.CreateExtension(key, CloudEventAttributeType.String);
var knownAttribute = CloudEventAttribute.CreateExtension("string", CloudEventAttributeType.String);

cloudEvent[attCorrelationId] = knownAttribute.Format(val);

var messageAsByteArray = new JsonEventFormatter().EncodeStructuredModeMessage(cloudEvent, out _);
var message = Encoding.UTF8.GetString(messageAsByteArray.ToArray(), 0, messageAsByteArray.Length);

Console.WriteLine(message);

This adds a JSON attribute correlationid

1
2
3
4
5
6
7
8
{
"specversion": "1.0",
"type": "com.github.pull.create",
"source": "https://github.com/cloudevents/spec/pull",
"id": "9fe70f0b-e87d-4bcb-85a8-5c5e8f9457b4",
"time": "2022-02-25T20:21:41.8614013+13:00",
"correlationid": "5a122a96-f0ee-4d65-bfc9-760c80c870ef",
"datacontenttype": "application/json",

As an actual extension method this could look like

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static class CloudEventExtension
{
public static void AddCorrelationId(this CloudEvent cloudEvent, Guid correlationId)
{
if (correlationId == Guid.Empty)
{
throw new ArgumentException("Supplied correlationId cannot equal Guid.Empty");
}

var stringValue = correlationId.ToString();

var attCorrelationId = CloudEventAttribute
.CreateExtension("correlationid", CloudEventAttributeType.String);

var knownAttribute = CloudEventAttribute
.CreateExtension("string", CloudEventAttributeType.String);

cloudEvent[attCorrelationId] = knownAttribute.Format(stringValue);
}
}

References