Contributing to Meshery Server Events
Meshery incorporates an internal events publication mechanism that provides users with real-time updates on the processes occurring within the Meshery server when interacting with its endpoints. It ensures that users are kept in the loop regarding the ongoing activities within the API, and guides users towards future steps to resolve issues. This guide will provide step-by-step instructions on sending events from the server, including when to trigger events and what information to include.
First, let’s take a look at how the event object is constructed,
eventBuilder := events.NewEvent() .ActedUpon(UUID) .FromUser(UUID) .FromSystem(UUID) .WithCategory(string) .WithAction(string) .WithSeverity(EventSeverity) .WithDescription(string) .WithMetadata(map[string]interface{}) .Build()
Note: events
is a package github.com/meshery/meshkit/models/events from MeshKit containing source code of event related functionality
The event mechanism utilizes builder pattern to construct event objects, events.NewEvent()
creates an instance of EventBuilder type, which functions as a builder class for constructing Event objects.
ActedUpon(UUID)
: it takes UUID of the resource being provisioned on the server, and the events are associated with that resource.FromUser()
: it takes UUID of the user initiating the HTTP request to the server. This enables the server to publish events intended for that specific user in response.FromSystem(UUID)
: it takes UUID of the running meshery instance (Handler instance contains ith.SystemID
).WithCategory
: The string argument to specify under which category this event falls, For example, when a user is provisioning a Kubernetes connection, the specified category for the event is “connection.WithAction
: The string argument to specify the type of action the server is performing, for instance, when registering a Kubernetes connection, the action would be “register”.
Note: categories and actions must be in snake case, example categories: “signup_request”, “github_artifacts”. example actions: “remove_from_organization”, “add_to_organization”.
WithSeverity
: it takes EventSeverity (underlying type is string), to specify severity of the event to bring user’s attention to the event accordingly.
Note: In certain conditions you must add some fields with specific keys:
- If the severity is “Error”, include a field in Metadata using the key
err
with the corresponding error value. -
When you want to add a link to meshery docs, include a field in Metadata using the key
doc
with the corresponding link value. WithDescription
: The string argument provides a detailed, descriptive message that depicts the specific operation or action being executed on the server.WithMetadata
: it takes a Mapmap[string]interface{}
data structure containing any supplementary information that the developer/contributor deems essential for the user to be informed about.Build
: returns the Event instance constructed upon the previously described functions and prepares it for publication through the Broadcast, which is responsible for disseminating events.
An Example in Code
func (h *Handler) KubernetesPingHandler(w http.ResponseWriter, req *http.Request, _ *models.Preference, user *models.User, provider models.Provider) { userID := uuid.FromStringOrNil(user.ID) token, ok := req.Context().Value(models.TokenCtxKey).(string) if !ok { w.WriteHeader(http.StatusInternalServerError) fmt.Fprintf(w, "failed to get the token for the user") return } connectionID := req.URL.Query().Get("connection_id") eventBuilder := events.NewEvent().FromUser(userID).FromSystem(*h.SystemID).WithCategory("connection").WithAction("ping") if connectionID != "" { // Get the context associated with this ID k8sContext, err := provider.GetK8sContext(token, connectionID) eventBuilder.ActedUpon(uuid.FromStringOrNil(connectionID)) if err != nil { eventBuilder.WithSeverity(events.Error).WithDescription(fmt.Sprintf("Encountered an issue while retrieving kubernetes context for connection ID `%s`", connectionID)). WithMetadata(map[string]interface{}{ "error": err, }) event := eventBuilder.Build() _ = provider.PersistEvent(event) go h.config.EventBroadcaster.Publish(userID, event) w.WriteHeader(http.StatusInternalServerError) fmt.Fprintf(w, "failed to get kubernetes context for the given ID") return } eventBuilder.WithSeverity(events.Success).WithDescription("Retrieved kubernetes context successfully"). WithMetadata(map[string]interface{}{ "Context Name": k8sContext.Name, "Server Address": k8sContext.Server, }) event := eventBuilder.Build() _ = provider.PersistEvent(event) go h.config.EventBroadcaster.Publish(userID, event) // Remaining code ... } }
In the given code block, the “resource” refers to the connection on which the server is performing the “ping” action. The “ActedUpon” field is supplied with the “connectionID” value obtained from the query parameter. provider.GetK8sContext
returns the K8sContext object which serves as a representation of a Kubernetes context within the Meshery. if provider.GetK8sContext
returns an error, the event is constructed with severity Error, description and enriched with metadata fields to provide the user with a complete context about the event.
If provider.GetK8sContext
succeeds, an event with a Success severity level is constructed. The event includes a success message and metadata containing the context name and the address of the Kubernetes API server, obtained from the operation. This information aims to provide users with relevant details about the successful operation.
after constructing the Event object using the Build function, event is stored into database for records and subsequently published in a new goroutine through EventBroadcaster member variable of HandlerConfig, which is part of Handler instance.
To gain a deeper understanding and examine events more closely, you can explore the source code files k8config_handler.go and design_engine_handler.go within the Meshery project’s codebase.
Suggested Reading
- Build & Release (CI) - Details of Meshery's build and release strategy.
- Contributing to Meshery Adapters - How to contribute to Meshery Adapters
- Contributing to Meshery CLI - How to contribute to Meshery Command Line Interface.
- Contributing to Meshery's End-to-End Tests using Cypress - How to contribute to End-to-End Tests using Cypress.
- Contributing to Meshery Docker Extension - How to contribute to Meshery Docker Extension
- Contributing to Meshery Docs - How to contribute to Meshery Docs.
- How to write MeshKit compatible errors - How to declare errors in Meshery components.
- Contributing to Meshery using git - How to contribute to Meshery using git
- Meshery CLI Contributing Guidelines - Design principles and code conventions.
- Contributing to Model Relationships - How to contribute to Meshery Models Relationships, Policies...
- Contributing to Models - How to contribute to Meshery Models, Components, Relationships, Policies...
- Contributing to Meshery UI - Notification Center - How to contribute to the Notification Center in Meshery's web-based UI.
- Contributing to Meshery UI - How to contribute to Meshery UI (web-based user interface).
- Contributing to Meshery Server - How to contribute to Meshery Server
- Setting up Meshery Development Environment on Windows - How to set up Meshery Development Environment on Windows