CloudEvents Go SDK

repository·main·Indexed 21 days ago

https://github.com/cloudevents/sdk-go

A Go SDK for representing, serializing, and transmitting CloudEvents, supporting specifications 0.3 and 1.0. It provides protocol bindings for HTTP and other transport layers, including support for OpenTelemetry observability, distributed tracing extensions, and integration with AMQP, Kafka, and MQTT.

Tokens
50.4K
Snippets
219
Records
257
Agent score
74%

What's inside cloudevents-sdk-go

  1. Use the Message interface to abstract protocol data

    main

    The Message interface is a binding-specific abstraction that allows you to read a CloudEvent from a protocol-specific data structure.

    Key Operations

    • Conversion:
      • Wrap an Event into a Message using binding.ToMessage().
      • Convert a Message to an Event using binding.ToEvent().
    • Lifecycle Management:
      • Buffering: Some Message implementations can only be read once because the encoding process drains the message. Use the buffering module to buffer a Message if you need to consume it multiple times.
      • Cleanup: You must invoke Message.Finish() whenever the Message receiver or emitter is finished with the message to prevent resource leaks.
  2. Use OTelObservabilityService for protocol-independent instrumentation

    main

    The OTelObservabilityService implements the CloudEvents ObservabilityService interface, allowing span generation independently of the transport protocol (e.g., works for Kafka or MQTT, not just HTTP).

    When using this service:

    • Span names follow the pattern cloudevents.client.[event type] [operation name], adhering to OpenTelemetry messaging semantic conventions.
    • Span attributes are populated based on the SDK's observability keys.
    c, err := cloudevents.NewClient(p, client.WithObservabilityService(otelObs.NewOTelObservabilityService()))
  3. Write and read the CloudEvent data field

    main

    The data field contains the event payload.

    Writing Data

    Use Event.SetData(contentType, payload) to populate the data field.

    • If the payload is a []byte, the SDK writes it directly without additional encoding.
    • For other types, the SDK uses the datacodec module to encode the payload based on the provided content type.

    Reading Data

    • Use Event.Data() to access the underlying []byte directly.
    • Use Event.DataAs(target) to decode the data into a specific type. This method uses the appropriate Decoder from the datacodec module.

    Custom Codecs

    Supported formats like application/xml, application/json, and text/plain have built-in support. To support custom formats, implement the datacodec.Encoder and datacodec.Decoder interfaces and register them using datacodec.AddEncoder and datacodec.AddDecoder.

  4. How Protocol Bindings work in sdk-go

    main

    A Protocol binding in the CloudEvents Go SDK abstracts the interaction between a specific transport protocol (like HTTP, Kafka, or NATS) and the CloudEvents model.

    To implement a protocol binding, two main components are required:

    1. Data Mapping: Defining how to read and write events to/from protocol-specific data structures (e.g., converting a net/http.Request into a CloudEvent). This is achieved by implementing the Message interface and Write<DataStructure> functions.
    2. Client Interaction: Defining how the protocol interacts with the SDK Client. This is achieved by implementing specific protocol interfaces (such as Receiver, Sender, or Responder).
  5. Identify CloudEvents personas and interaction models

    main

    The SDK supports several roles (personas) and interaction patterns based on how your application handles events:

    Personas

    • Producer: An instance, process, or device that creates the CloudEvent data structure.
    • Consumer: An entity that receives the event and executes logic based on its context and data.
    • Intermediary: An entity that receives a message for the purpose of forwarding it to a Consumer or another Intermediary (e.g., a router).

    Interaction Models

    • Sender: A Producer creating and sending new events.
    • Receiver: A Consumer accepting and processing incoming events.
    • Forwarder: An Intermediary that accepts an event only after it has successfully forwarded the message to one or more Consumers.
    • Mutator: A Producer or Intermediary that blocks on a response from a Consumer and replaces the original Event with a new one.
  6. Choose your SDK investment level

    main

    The sdk-go library allows you to choose how much of the abstraction layer you want to interact with, depending on your requirements:

    • Resource Level: You only use the Event data structure to interact with CloudEvents and handle JSON marshaling/unmarshaling.
    • Message Level: You work directly with Message implementations and Write* functions to handle CloudEvents messages on the wire. You are responsible for managing connections and protocol-specific APIs manually.
    • Protocol Level: You use Protocol implementations directly to consume or produce Messages, bypassing the need to interact with protocol-specific APIs directly.
    • Client Level: The highest level of abstraction. You select a Protocol implementation and use the v2/client.Client to send and receive Events directly without managing Message objects.
  7. Understand CloudEvents Spec and SDK terms

    main

    To use the Go SDK effectively, it is important to distinguish between the CloudEvents specification terms and how they are implemented in the sdk-go library:

    • Event: The canonical data structure representing the attributes and payload of an occurrence.
    • Protocol: The messaging protocol (e.g., HTTP, AMQP, Kafka) used to transport events. In the SDK, these are implemented via interfaces in the v2/protocol module.
    • Protocol Binding: The definition of how an Event is mapped into a Message for a specific protocol. These are implemented in the v2/binding module.
    • Message: The encoded form of an Event for a specific encoding and protocol. When receiving a message, the protocol implementation wraps it in a v2/binding.Message implementation, which provides the interface to read the message.
    • Message Writer: Logic used to take a Message in a specific encoding and write it to a protocol. This can be a v2/binding.StructuredWriter, a v2/binding.BinaryWriter, or both.
    • Client: The v2/client.Client interface is the primary way to interact with a protocol implementation to send or receive events. Clients also handle protocol-agnostic features like extensions.
    • Extensions: Attributes that extend the base CloudEvents specification requirements.
  8. Run a Gin web framework CloudEvents receiver sample

    main

    This sample demonstrates how to implement a CloudEvents receiver using the Gin web framework. It specifically shows how to handle a TektonEvent.

    Setup and Execution

    1. Get dependencies: Navigate to the samples directory and fetch the required Go modules:

      cd samples/
      go get
    2. Run the application: Execute the main entry point:

      go run main.go
    3. Test with a CloudEvent: You can send a test CloudEvent using curl. This example uses HTTP headers to represent the CloudEvent attributes (following the binary mode convention):

      curl -v \
       -H "Ce-Id: e7d95c20-6eb4-4614-946d-27b0ce41c7ff" \
       -H "Ce-Source: /apis/namespaces/dimitar/clone-build-n4qhgl" \
       -H "Ce-Subject: clone-build-n4qhgl"  \
       -H "Ce-Specversion: 1.0" \
       -H "Ce-Type: dev.tekton.event.pipelinerun.started.v1" \
       -H "Content-Type: application/json"  \
       -d @event.json http://localhost:8080
    cd samples/
    go get
    go run main.go
  9. Set up an AMQP broker for samples

    main

    The AMQP samples require an AMQP 1.0 broker or router to be running.

    A recommended option is the Apache Qpid Dispatch Router. You can install it via dnf, apt, or from source. Once installed, run qdrouterd to start the router. The samples are configured to work with qdrouterd without additional configuration.

    qdrouterd
  10. Explore CloudEvents SDK Go samples

    main
    The samples/ directory provides concrete implementations of various CloudEvents SDK features. You can use these samples as templates by copying and pasting them into your own projects to implement specific messaging patterns or protocol integrations.
  11. Implement CloudEvents with HTTP

    main

    The SDK provides multiple ways to handle CloudEvents over HTTP, ranging from high-level clients to low-level handlers:

    • Standard Receiver: Receive events using the CloudEvents Client.
    • Direct Receiver: Create an http.Handler to receive events without using the CloudEvents Client.
    • Framework Integrations: Specialized receivers for Gin Gonic and Gorilla.
    • Request/Response Patterns:
      • Requester: Send request/response events with various data content types and encodings.
      • Requester with custom client: Use a custom http.Transport (e.g., for TLS configuration).
      • Responder: Receive and reply to events using the CloudEvents Client.
    • Sender Patterns:
      • Sender: Send events using the CloudEvents Client.
      • Sender with retries: Implement sending logic with retry mechanisms for failures.
    • Observability:
      • Traced receiver: Receive events with tracing enabled.
      • Receiver & Requester with metrics: Handle and request events with metrics enabled.
  12. Run a Kafka cluster for samples using Docker

    main

    To run the Kafka samples provided in this repository, you must have a running Kafka cluster. You can quickly spin up a local cluster using Docker with the following command:

    docker run --rm --net=host -e ADV_HOST=localhost -e SAMPLEDATA=0 lensesio/fast-data-dev

    This command uses the lensesio/fast-data-dev image and configures the advertised host to localhost so the samples can connect to it.