Skip to content

Kafka Significant Events

Available since: version 7.0.1

The Kafka Significant Events are a centralized event system in the MetalSoft platform that emit structured events to Kafka for external integration. These events capture critical infrastructure changes and security actions across the platform and allow 3rd party developers and clients to develop integrations with other enterprise systems and automation solutions.

All events are published to the Kafka topic io.metalsoft.significant_event. To consume events directly from the cluster for testing purposes:

Terminal window
kubectl exec -it deploy/kafka -- kafka-console-consumer --bootstrap-server broker:29092 --topic io.metalsoft.significant_event --from-beginning
  1. Event Categories
    • Server Management: Server lifecycle events (creation, updates, deletion, registration)
    • Security: User and authentication events (login, credential changes, access modifications)
    • Network Device Management: Network infrastructure events (device registration, fabric assignments)
    • Server Health: Server health state change events, including AI monitoring agent results (available since 7.3.3)
    • Network Device Health: Switch health state change events (available since 7.4)
    • VM Pool Host Health: VM pool host health state change events (available since 7.4)
    • Instance Management: Instance and DNS lifecycle events (updates, deletions)
    • Job Events: Job lifecycle events (skipped, action issued, failed)
    • Infrastructure Deployment: Infrastructure deploy lifecycle events (started, cancelled, finished)
    • Network Fabric Deployment: Network fabric and fabric interconnect deploy lifecycle events (started, finished, accepted, rejected)

Each significant event follows the CloudEvent specification and contains the following structure:

{
"id": "unique-event-identifier",
"time": "2025-01-01T12:00:00.000Z",
"type": "dot.separated.event.type",
"source": "https://metalsoft.io/microservice-name",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
// Event-specific payload with string values
}
}

Events related to server lifecycle management.

Event TypeDescriptionData Structure
server.deletedServer permanently deleted{"serverId": "string", "serverUUID": "string", "serverClass": "string", "serverStatus": "string"}
server.updatedServer configuration updated{"serverId": "string", "userId": "string", "changes": {"previousState": {}, "currentState": {}}}
server.credentials.updatedServer credentials changed{"serverId": "string", "userId": "string", "serverManagementAddress": "string"}
server.registeredServer successfully registered{"serverId": "string", "serverStatus": "string", "serverTypeId": "string", "siteId": "string", "userId": "string"}
server.registration.initiatedServer registration process started{"serverId": "string", "managementAddress": "string", "siteId": "string"}
server.reregistration.initiatedServer re-registration started{"serverId": "string", "managementAddress": "string", "siteId": "string"}
server.production.registration.initiatedProduction server registration started{"serverId": "string", "managementAddress": "string", "siteId": "string"}
server.decommissionedServer decommissioned{"serverId": "string", "serverUUID": "string", "serverClass": "string", "serverStatus": "string", "serverTypeId": "string"}
server.production.registeredServer registered for production use{"serverId": "string", "serverStatus": "string", "serverTypeId": "string", "siteId": "string", "userId": "string"}

User and authentication-related events from the auth microservice.

Event TypeDescriptionData Structure
user.createdNew user account created{"userId": "string", "userEmail": "string", "loggedInUserId": "string", "loggedInUserEmail": "string", "message": "string"}
user.credentials.changedUser password/credentials updated{"userId": "string", "userEmail": "string", "loggedInUserId": "string", "loggedInUserEmail": "string", "message": "string"}
user.suspendedUser account suspended{"userId": "string", "userEmail": "string", "loggedInUserId": "string", "loggedInUserEmail": "string", "message": "string"}
user.unsuspendedUser account reactivated{"userId": "string", "userEmail": "string", "loggedInUserId": "string", "loggedInUserEmail": "string", "message": "string"}
user.password.reset.requestedPassword reset initiated{"userId": "string", "userEmail": "string", "loggedInUserId": "string", "loggedInUserEmail": "string", "message": "string"}
user.email.updatedUser email address changed{"userId": "string", "userEmail": "string", "loggedInUserId": "string", "loggedInUserEmail": "string", "message": "string"}
user.email.verifiedUser email address verified{"userId": "string", "userEmail": "string", "loggedInUserId": "string", "loggedInUserEmail": "string", "message": "string"}
user.api.key.regeneratedUser API key regenerated{"userId": "string", "userEmail": "string", "loggedInUserId": "string", "loggedInUserEmail": "string", "message": "string"}
user.ssh.key.createdSSH key added to user account{"userId": "string", "userEmail": "string", "loggedInUserId": "string", "loggedInUserEmail": "string", "message": "string"}
user.ssh.key.deletedSSH key removed from user account{"userId": "string", "userEmail": "string", "loggedInUserId": "string", "loggedInUserEmail": "string", "message": "string"}
user.delegate.removedUser delegate access removed{"userId": "string", "userEmail": "string", "loggedInUserId": "string", "loggedInUserEmail": "string", "message": "string"}
user.delegate.addedUser delegate access granted{"userId": "string", "userEmail": "string", "loggedInUserId": "string", "loggedInUserEmail": "string", "message": "string"}
user.unarchivedUser account restored from archive{"userId": "string", "userEmail": "string", "loggedInUserId": "string", "loggedInUserEmail": "string", "message": "string"}
user.archivedUser account archived{"userId": "string", "userEmail": "string", "loggedInUserId": "string", "loggedInUserEmail": "string", "message": "string"}
user.2fa.enabledTwo-factor authentication enabled{"userId": "string", "userEmail": "string", "loggedInUserId": "string", "loggedInUserEmail": "string", "message": "string"}
user.2fa.disabledTwo-factor authentication disabled{"userId": "string", "userEmail": "string", "loggedInUserId": "string", "loggedInUserEmail": "string", "message": "string"}
user.access.level.setUser access level changed{"userId": "string", "userEmail": "string", "loggedInUserId": "string", "loggedInUserEmail": "string", "message": "string"}

Network infrastructure events from the inventory microservice.

Event TypeDescriptionData Structure
network.device.createdNew network device added{"networkDeviceId": "string", "managementAddress": "string", "identifierString": "string", "driver": "string", "position": "string", "siteId": "string"}
network.device.deletedNetwork device permanently removed{"networkDeviceId": "string", "position": "string", "siteId": "string", "identifierString": "string", "userIdAuthenticated": "string"}
network.device.registeredNetwork device successfully registered{"networkDeviceId": "string", "managementAddress": "string", "identifierString": "string", "driver": "string", "position": "string", "siteId": "string"}
network.device.registration.initiatedNetwork device registration started{"networkDeviceId": "string", "managementAddress": "string", "serialNumber": "string", "chassisIdentifier": "string", "managementMacAddress": "string"}
network.device.archivedNetwork device archived{"networkDeviceId": "string", "userIdAuthenticated": "string"}
network.device.assigned.to.fabricDevice assigned to network fabric{"fabricId": "string", "networkDeviceIds": "string[]", "fabricName": "string"}
network.device.removed.from.fabricDevice removed from network fabric{"fabricId": "string", "networkDeviceIds": "string[]", "fabricName": "string"}
network.device.replacedNetwork device replaced with another{"oldNetworkDeviceId": "string", "newNetworkDeviceId": "string"}
network.device.credentials.updatedDevice credentials changed{"networkDeviceId": "string", "managementAddress": "string", "identifierString": "string", "driver": "string", "position": "string", "siteId": "string", "userIdAuthenticated": "string"}

Available since: version 7.3.3

Events emitted when a server’s health state changes. Each degradation emits two events — one immediately on detection and one after the AI monitoring agent has been consulted.

Event TypeDescriptionData Structure
server.health.state.degradedServer health state worsened. Emitted twice: immediately on detection (monitoringAgentPrompted: false), then again after the AI monitoring agent is consulted (monitoringAgentPrompted: true){"serverId": "string", "siteId": "string", "datacenterName": "string", "previousState": "string", "newState": "string", "healthDetails": "string[]", "infrastructureId": "string", "instanceId": "string", "monitoringAgentPrompted": "boolean", "monitoringAgentResult": "string | null"}
server.health.state.improvedServer health state recovered{"serverId": "string", "siteId": "string", "datacenterName": "string", "previousState": "string", "newState": "string", "healthDetails": "string[]", "infrastructureId": "string", "instanceId": "string"}

infrastructureId and instanceId are only present when the server is allocated to an infrastructure. monitoringAgentResult contains HTML-formatted text and is only present when monitoringAgentPrompted is true.

Available since: version 7.4

Events emitted when a switch’s health state changes.

Event TypeDescriptionData Structure
network.device.health.state.degradedSwitch health state worsened{"switchId": "string", "siteId": "string", "datacenterName": "string", "previousState": "string", "newState": "string", "healthDetails": "string[]"}
network.device.health.state.improvedSwitch health state recovered{"switchId": "string", "siteId": "string", "datacenterName": "string", "previousState": "string", "newState": "string", "healthDetails": "string[]"}

healthDetails is an array of human-readable messages describing the current health issues (e.g. "temperature is high", "port is down").

Available since: version 7.4

Events emitted when a VM pool host’s health state changes.

Event TypeDescriptionData Structure
vm.pool.host.health.state.degradedVM pool host health state worsened{"vmPoolId": "string", "vmPoolHostId": "string", "siteId": "string", "datacenterName": "string", "previousState": "string", "previousHealthStatus": "string", "newState": "string", "newHealthStatus": "string", "healthDetails": "string[]"}
vm.pool.host.health.state.improvedVM pool host health state recovered{"vmPoolId": "string", "vmPoolHostId": "string", "siteId": "string", "datacenterName": "string", "previousState": "string", "previousHealthStatus": "string", "newState": "string", "newHealthStatus": "string", "healthDetails": "string[]"}

healthDetails is an array of human-readable messages describing the current health issues.

Instance and DNS lifecycle events from the orchestrator microservice.

Event TypeDescriptionData Structure
instance.array.dns.updatedInstance array DNS records updated{"instanceArrayId": "string", "infrastructureId": "string", "dnsRecords": "object[]", "userIdAuthenticated": "string"}
instance.dns.updatedInstance DNS records updated{"instanceId": "string", "infrastructureId": "string", "dnsRecords": "object[]", "userIdAuthenticated": "string"}
instance.array.dns.deletedInstance array DNS records deleted{"instanceArrayId": "string", "infrastructureId": "string", "userIdAuthenticated": "string"}
instance.dns.deletedInstance DNS records deleted{"instanceId": "string", "infrastructureId": "string", "userIdAuthenticated": "string"}

Events related to the lifecycle of jobs.

Event TypeDescriptionData Structure
job.skippedJob skipped{"loggedInUserId": "string", "message": "string", "jobId": "string"}
job.action.issuedAn action was issued for a job{"loggedInUserId": "string", "message": "string", "action": "string", "jobId": "string"}
job.failedJob failed{"message": "string", "jobId": "string"}

Events related to infrastructure deployment lifecycle.

Event TypeDescriptionData Structure
infrastructure.deploy.startedInfrastructure deployment started{"userId": "string", "loggedInUserId": "string", "infrastructureId": "string", "message": "string"}
infrastructure.deploy.cancelledInfrastructure deployment cancelled{"userId": "string", "loggedInUserId": "string", "infrastructureId": "string", "message": "string"}
infrastructure.deploy.finishedInfrastructure deployment finished{"infrastructureId": "string", "message": "string"}

Events related to network fabric and network fabric interconnect deployment lifecycle.

Event TypeDescriptionData Structure
network.fabric.deploy.startedNetwork fabric deployment started{"loggedInUserId": "string", "networkFabricId": "string", "message": "string"}
network.fabric.deploy.finishedNetwork fabric deployment finished{"networkFabricId": "string", "message": "string"}
network.fabric.deploy.acceptedNetwork fabric deployment accepted{"loggedInUserId": "string", "networkFabricId": "string", "message": "string"}
network.fabric.deploy.rejectedNetwork fabric deployment rejected{"loggedInUserId": "string", "networkFabricId": "string", "message": "string"}
network.fabric.interconnect.deploy.startedNetwork fabric interconnect deployment started{"loggedInUserId": "string", "interconnectId": "string", "message": "string"}
network.fabric.interconnect.deploy.finishedNetwork fabric interconnect deployment finished{"interconnectId": "string", "message": "string"}
network.fabric.interconnect.deploy.acceptedNetwork fabric interconnect deployment accepted{"loggedInUserId": "string", "interconnectId": "string", "message": "string"}
network.fabric.interconnect.deploy.rejectedNetwork fabric interconnect deployment rejected{"loggedInUserId": "string", "interconnectId": "string", "message": "string"}

Note: All examples below show the complete CloudEvent format as it appears in Kafka. Each event includes the CloudEvent metadata (id, time, type, source, specversion, datacontenttype) and the event-specific data in the data field. Numeric values are serialized as strings in the JSON format.

{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "server.registration.initiated",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"serverId": "123",
"managementAddress": "192.168.1.100",
"siteId": "1"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "server.registered",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"serverId": "123",
"serverStatus": "AVAILABLE",
"serverTypeId": "25",
"siteId": "1",
"userId": "456"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "server.reregistration.initiated",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"serverId": "123",
"managementAddress": "192.168.1.100",
"siteId": "1"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "server.production.registration.initiated",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"serverId": "123",
"managementAddress": "192.168.1.100",
"siteId": "1"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "server.production.registered",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"serverId": "123",
"serverStatus": "USED",
"serverTypeId": "25",
"siteId": "1",
"userId": "456"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "server.updated",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"serverId": "123",
"userId": "456",
"changes": {
"previousState": {
"serverStatus": "UNAVAILABLE",
"serverClass": "UNKNOWN"
},
"currentState": {
"serverStatus": "AVAILABLE",
"serverClass": "BIGDATA"
}
}
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "server.credentials.updated",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"serverId": "123",
"userId": "456",
"serverManagementAddress": "192.168.1.100"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "server.decommissioned",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"serverId": "123",
"serverUUID": "550e8400-e29b-41d4-a716-446655440000",
"serverClass": "BIGDATA",
"serverStatus": "DECOMMISSIONED",
"serverTypeId": "25"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "server.deleted",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"serverId": "123",
"serverUUID": "550e8400-e29b-41d4-a716-446655440000",
"serverClass": "BIGDATA",
"serverStatus": "DECOMMISSIONED"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "user.created",
"source": "https://metalsoft.io/auth-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"userId": "123",
"userEmail": "user@example.com",
"loggedInUserId": "456",
"loggedInUserEmail": "admin@example.com",
"message": "New user account created"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "user.credentials.changed",
"source": "https://metalsoft.io/auth-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"userId": "123",
"userEmail": "user@example.com",
"loggedInUserId": "456",
"loggedInUserEmail": "admin@example.com",
"message": "User password updated successfully"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "user.password.reset.requested",
"source": "https://metalsoft.io/auth-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"userId": "123",
"userEmail": "user@example.com",
"loggedInUserId": "456",
"loggedInUserEmail": "admin@example.com",
"message": "Password reset initiated for user"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "user.suspended",
"source": "https://metalsoft.io/auth-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"userId": "123",
"userEmail": "user@example.com",
"loggedInUserId": "456",
"loggedInUserEmail": "admin@example.com",
"message": "User suspended due to policy violation"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "user.unsuspended",
"source": "https://metalsoft.io/auth-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"userId": "123",
"userEmail": "user@example.com",
"loggedInUserId": "456",
"loggedInUserEmail": "admin@example.com",
"message": "User account reactivated"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "user.email.updated",
"source": "https://metalsoft.io/auth-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"userId": "123",
"userEmail": "newemail@example.com",
"loggedInUserId": "456",
"loggedInUserEmail": "admin@example.com",
"message": "User email address changed from oldemail@example.com"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "user.email.verified",
"source": "https://metalsoft.io/auth-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"userId": "123",
"userEmail": "user@example.com",
"loggedInUserId": "123",
"loggedInUserEmail": "user@example.com",
"message": "Email address verified successfully"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "user.api.key.regenerated",
"source": "https://metalsoft.io/auth-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"userId": "123",
"userEmail": "user@example.com",
"loggedInUserId": "456",
"loggedInUserEmail": "admin@example.com",
"message": "API key regenerated for security purposes"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "user.ssh.key.created",
"source": "https://metalsoft.io/auth-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"userId": "123",
"userEmail": "user@example.com",
"loggedInUserId": "123",
"loggedInUserEmail": "user@example.com",
"message": "SSH key added to user account"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "user.ssh.key.deleted",
"source": "https://metalsoft.io/auth-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"userId": "123",
"userEmail": "user@example.com",
"loggedInUserId": "123",
"loggedInUserEmail": "user@example.com",
"message": "SSH key removed from user account"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "user.delegate.added",
"source": "https://metalsoft.io/auth-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"userId": "123",
"userEmail": "user@example.com",
"loggedInUserId": "456",
"loggedInUserEmail": "admin@example.com",
"message": "Parent user ID: 123 with email user@example.com added delegate with ID 789 with email delegate@example.com"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "user.delegate.removed",
"source": "https://metalsoft.io/auth-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"userId": "123",
"userEmail": "user@example.com",
"loggedInUserId": "456",
"loggedInUserEmail": "admin@example.com",
"message": "Delegate access revoked from user"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "user.2fa.enabled",
"source": "https://metalsoft.io/auth-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"userId": "123",
"userEmail": "user@example.com",
"loggedInUserId": "123",
"loggedInUserEmail": "user@example.com",
"message": "Two-factor authentication enabled"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "user.2fa.disabled",
"source": "https://metalsoft.io/auth-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"userId": "123",
"userEmail": "user@example.com",
"loggedInUserId": "123",
"loggedInUserEmail": "user@example.com",
"message": "Two-factor authentication disabled"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "user.access.level.set",
"source": "https://metalsoft.io/auth-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"userId": "123",
"userEmail": "user@example.com",
"loggedInUserId": "456",
"loggedInUserEmail": "admin@example.com",
"message": "User access level changed to Administrator"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "user.archived",
"source": "https://metalsoft.io/auth-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"userId": "123",
"userEmail": "user@example.com",
"loggedInUserId": "456",
"loggedInUserEmail": "admin@example.com",
"message": "User account archived"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "user.unarchived",
"source": "https://metalsoft.io/auth-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"userId": "123",
"userEmail": "user@example.com",
"loggedInUserId": "456",
"loggedInUserEmail": "admin@example.com",
"message": "User account restored from archive"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.device.created",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"networkDeviceId": "123",
"managementAddress": "192.168.1.100",
"identifierString": "switch-rack-01",
"driver": "sonic_enterprise",
"position": "leaf",
"siteId": "456"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.device.registration.initiated",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"networkDeviceId": "123",
"managementAddress": "192.168.1.100",
"serialNumber": "SN123456789",
"chassisIdentifier": "chassis-001",
"managementMacAddress": "00:1B:21:B4:6E:3A"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.device.registered",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"networkDeviceId": "123",
"managementAddress": "192.168.1.100",
"identifierString": "switch-rack-01",
"driver": "sonic_enterprise",
"position": "leaf",
"siteId": "456"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.device.assigned.to.fabric",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"fabricId": "42",
"networkDeviceIds": ["123", "124", "125"],
"fabricName": "production-fabric-1"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.device.removed.from.fabric",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"fabricId": "42",
"networkDeviceIds": ["123", "124", "125"],
"fabricName": "production-fabric-1"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.device.credentials.updated",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"networkDeviceId": "123",
"managementAddress": "192.168.1.100",
"identifierString": "switch-rack-01",
"driver": "sonic_enterprise",
"position": "leaf",
"siteId": "456",
"userIdAuthenticated": "789"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.device.replaced",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"oldNetworkDeviceId": "100",
"newNetworkDeviceId": "200"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.device.archived",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"networkDeviceId": "123",
"userIdAuthenticated": "456"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.device.deleted",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"networkDeviceId": "123",
"position": "leaf",
"siteId": "siteId":"1",
"identifierString": "switch-rack-01",
"userIdAuthenticated": "456"
}
}

Server Health State Degraded (before AI agent)

Section titled “Server Health State Degraded (before AI agent)”
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "server.health.state.degraded",
"source": "https://metalsoft.io/notification-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"serverId": "123",
"siteId": "10",
"datacenterName": "dc1",
"previousState": "healthy",
"newState": "critical_warnings_present",
"healthDetails": ["Fan failure detected on CPU 0"],
"infrastructureId": "456",
"instanceId": "789",
"monitoringAgentPrompted": false
}
}

Server Health State Degraded (after AI agent consulted)

Section titled “Server Health State Degraded (after AI agent consulted)”
{
"id": "event-id-124",
"time": "2025-01-01T12:00:05.000Z",
"type": "server.health.state.degraded",
"source": "https://metalsoft.io/notification-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"serverId": "123",
"siteId": "10",
"datacenterName": "dc1",
"previousState": "healthy",
"newState": "critical_warnings_present",
"healthDetails": ["Fan failure detected on CPU 0"],
"infrastructureId": "456",
"instanceId": "789",
"monitoringAgentPrompted": true,
"monitoringAgentResult": "<p>A fan failure was detected on CPU 0. Recommended actions: check cooling system, inspect fan headers, consider replacing the fan unit.</p>"
}
}
{
"id": "event-id-125",
"time": "2025-01-01T13:00:00.000Z",
"type": "server.health.state.improved",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"serverId": "123",
"siteId": "10",
"datacenterName": "dc1",
"previousState": "critical_warnings_present",
"newState": "healthy",
"healthDetails": [],
"infrastructureId": "456",
"instanceId": "789"
}
}
  • The server.health.state.degraded event fires twice per degradation. Consumers should correlate the two events by serverId + newState rather than treating them as duplicates. The second event (with monitoringAgentPrompted: true) always arrives a few seconds after the first.
  • monitoringAgentResult is HTML-formatted. Consumers should strip, sanitize, or convert it to Markdown depending on their rendering context.
  • The degradation event is sourced from notification-microservice; the improvement event is sourced from inventory-microservice.
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.device.health.state.degraded",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"switchId": "42",
"siteId": "10",
"datacenterName": "dc1",
"previousState": "healthy",
"newState": "degraded",
"healthDetails": ["temperature is high", "port is down"]
}
}
{
"id": "event-id-124",
"time": "2025-01-01T13:00:00.000Z",
"type": "network.device.health.state.improved",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"switchId": "42",
"siteId": "10",
"datacenterName": "dc1",
"previousState": "degraded",
"newState": "healthy",
"healthDetails": []
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "vm.pool.host.health.state.degraded",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"vmPoolId": "10",
"vmPoolHostId": "42",
"siteId": "1",
"datacenterName": "dc1",
"previousState": "active",
"previousHealthStatus": "healthy",
"newState": "active",
"newHealthStatus": "degraded",
"healthDetails": ["temperature is high", "memory errors detected"]
}
}
{
"id": "event-id-124",
"time": "2025-01-01T13:00:00.000Z",
"type": "vm.pool.host.health.state.improved",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"vmPoolId": "10",
"vmPoolHostId": "42",
"siteId": "1",
"datacenterName": "dc1",
"previousState": "active",
"previousHealthStatus": "degraded",
"newState": "active",
"newHealthStatus": "healthy",
"healthDetails": []
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "instance.array.dns.updated",
"source": "https://metalsoft.io/orchestrator-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"instanceArrayId": "123",
"infrastructureId": "456",
"dnsRecords": [
{
"hostname": "web-server-01.example.com",
"type": "A",
"value": "192.168.1.10"
}
],
"userIdAuthenticated": "789"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "instance.dns.updated",
"source": "https://metalsoft.io/orchestrator-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"instanceId": "123",
"infrastructureId": "456",
"dnsRecords": [
{
"hostname": "database-01.example.com",
"type": "A",
"value": "192.168.1.20"
}
],
"userIdAuthenticated": "789"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "instance.array.dns.deleted",
"source": "https://metalsoft.io/orchestrator-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"instanceArrayId": "123",
"infrastructureId": "456",
"userIdAuthenticated": "789"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "instance.dns.deleted",
"source": "https://metalsoft.io/orchestrator-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"instanceId": "123",
"infrastructureId": "456",
"userIdAuthenticated": "789"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "job.skipped",
"source": "https://metalsoft.io/orchestrator-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"loggedInUserId": "456",
"message": "Job skipped because a newer job supersedes it",
"jobId": "789"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "job.action.issued",
"source": "https://metalsoft.io/orchestrator-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"loggedInUserId": "456",
"message": "Retry action issued for job",
"action": "retry",
"jobId": "789"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "job.failed",
"source": "https://metalsoft.io/orchestrator-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"message": "Job failed due to a timeout while waiting for the target resource",
"jobId": "789"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "infrastructure.deploy.started",
"source": "https://metalsoft.io/orchestrator-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"userId": "123",
"loggedInUserId": "456",
"infrastructureId": "789",
"message": "Infrastructure deployment started"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "infrastructure.deploy.cancelled",
"source": "https://metalsoft.io/orchestrator-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"userId": "123",
"loggedInUserId": "456",
"infrastructureId": "789",
"message": "Infrastructure deployment cancelled by user"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "infrastructure.deploy.finished",
"source": "https://metalsoft.io/orchestrator-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"infrastructureId": "789",
"message": "Infrastructure deployment finished successfully"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.fabric.deploy.started",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"loggedInUserId": "456",
"networkFabricId": "42",
"message": "Network fabric deployment started"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.fabric.deploy.finished",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"networkFabricId": "42",
"message": "Network fabric deployment finished successfully"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.fabric.deploy.accepted",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"loggedInUserId": "456",
"networkFabricId": "42",
"message": "Network fabric deployment accepted"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.fabric.deploy.rejected",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"loggedInUserId": "456",
"networkFabricId": "42",
"message": "Network fabric deployment rejected"
}
}

Network Fabric Interconnect Deploy Started

Section titled “Network Fabric Interconnect Deploy Started”
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.fabric.interconnect.deploy.started",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"loggedInUserId": "456",
"interconnectId": "24",
"message": "Network fabric interconnect deployment started"
}
}

Network Fabric Interconnect Deploy Finished

Section titled “Network Fabric Interconnect Deploy Finished”
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.fabric.interconnect.deploy.finished",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"interconnectId": "24",
"message": "Network fabric interconnect deployment finished successfully"
}
}

Network Fabric Interconnect Deploy Accepted

Section titled “Network Fabric Interconnect Deploy Accepted”
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.fabric.interconnect.deploy.accepted",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"loggedInUserId": "456",
"interconnectId": "24",
"message": "Network fabric interconnect deployment accepted"
}
}

Network Fabric Interconnect Deploy Rejected

Section titled “Network Fabric Interconnect Deploy Rejected”
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.fabric.interconnect.deploy.rejected",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"loggedInUserId": "456",
"interconnectId": "24",
"message": "Network fabric interconnect deployment rejected"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "job.skipped",
"source": "https://metalsoft.io/orchestrator-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"loggedInUserId": "456",
"message": "Job skipped because a newer job supersedes it",
"jobId": "789"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "job.action.issued",
"source": "https://metalsoft.io/orchestrator-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"loggedInUserId": "456",
"message": "Retry action issued for job",
"action": "retry",
"jobId": "789"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "job.failed",
"source": "https://metalsoft.io/orchestrator-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"message": "Job failed due to a timeout while waiting for the target resource",
"jobId": "789"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "infrastructure.deploy.started",
"source": "https://metalsoft.io/orchestrator-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"userId": "123",
"loggedInUserId": "456",
"infrastructureId": "789",
"message": "Infrastructure deployment started"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "infrastructure.deploy.cancelled",
"source": "https://metalsoft.io/orchestrator-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"userId": "123",
"loggedInUserId": "456",
"infrastructureId": "789",
"message": "Infrastructure deployment cancelled by user"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "infrastructure.deploy.finished",
"source": "https://metalsoft.io/orchestrator-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"infrastructureId": "789",
"message": "Infrastructure deployment finished successfully"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.fabric.deploy.started",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"loggedInUserId": "456",
"networkFabricId": "42",
"message": "Network fabric deployment started"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.fabric.deploy.finished",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"networkFabricId": "42",
"message": "Network fabric deployment finished successfully"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.fabric.deploy.accepted",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"loggedInUserId": "456",
"networkFabricId": "42",
"message": "Network fabric deployment accepted"
}
}
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.fabric.deploy.rejected",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"loggedInUserId": "456",
"networkFabricId": "42",
"message": "Network fabric deployment rejected"
}
}

Network Fabric Interconnect Deploy Started

Section titled “Network Fabric Interconnect Deploy Started”
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.fabric.interconnect.deploy.started",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"loggedInUserId": "456",
"interconnectId": "24",
"message": "Network fabric interconnect deployment started"
}
}

Network Fabric Interconnect Deploy Finished

Section titled “Network Fabric Interconnect Deploy Finished”
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.fabric.interconnect.deploy.finished",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"interconnectId": "24",
"message": "Network fabric interconnect deployment finished successfully"
}
}

Network Fabric Interconnect Deploy Accepted

Section titled “Network Fabric Interconnect Deploy Accepted”
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.fabric.interconnect.deploy.accepted",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"loggedInUserId": "456",
"interconnectId": "24",
"message": "Network fabric interconnect deployment accepted"
}
}

Network Fabric Interconnect Deploy Rejected

Section titled “Network Fabric Interconnect Deploy Rejected”
{
"id": "event-id-123",
"time": "2025-01-01T12:00:00.000Z",
"type": "network.fabric.interconnect.deploy.rejected",
"source": "https://metalsoft.io/inventory-microservice",
"specversion": "1.0",
"datacontenttype": "application/json",
"data": {
"loggedInUserId": "456",
"interconnectId": "24",
"message": "Network fabric interconnect deployment rejected"
}
}

The Kafka broker runs inside the MetalSoft Kubernetes cluster and is not reachable from outside by default. This section shows how to expose the broker outside the cluster and a complete example of consuming the io.metalsoft.significant_event topic with Logstash, writing each event to a file on disk.

To make the broker reachable from outside the cluster, create a LoadBalancer Service that selects the Kafka pods. The example below assumes MetalLB provides LoadBalancer IPs; the commented-out sections show how to request a specific IP and how to define a MetalLB address pool if one does not exist yet.

Adjust namespace and app.kubernetes.io/part-ofto match the namespace of your MetalSoft deployment.

---
apiVersion: v1
kind: Service
metadata:
name: kafka-to-outside
namespace: demo-metalsoft
# annotations:
# metallb.universe.tf/allow-shared-ip: "demo-metalsoft"
## New way of requesting particular IP in MetalLB
## metallb.universe.tf/loadBalancerIPs: "x.x.x.x"
labels: &kafka-external
app.kubernetes.io/name: kafka
app.kubernetes.io/component: kafka
app.kubernetes.io/part-of: demo-metalsoft
spec:
type: LoadBalancer
# loadBalancerIP: "1.2.3.4"
externalTrafficPolicy: Local
ports:
- port: 9092
name: kafka-external
targetPort: 9092
selector: *kafka-external
# MetalLB Example Pool and L2Advertisment
# ---
# apiVersion: metallb.io/v1beta1
# kind: IPAddressPool
# metadata:
# name: pool2
# namespace: metallb-system
# spec:
# addresses:
# - 1.2.3.4-1.2.3.4
# autoAssign: true
# ---
# apiVersion: metallb.io/v1beta1
# kind: L2Advertisement
# metadata:
# name: l2-all
# namespace: metallb-system

Once applied, the external IP assigned to the Service (see kubectl get svc kafka-to-outside) is what external consumers use as their Kafka bootstrap server, on port 9092.

This example runs Logstash in Docker, consumes messages from the io.metalsoft.significant_event topic, and appends them — one per line — to a file on the host.

Directory layout:

logstash-kafka-to-file/
├── docker-compose.yml
├── pipeline/
│ └── kafka-to-file.conf # the Logstash pipeline
└── output/ # created on first run; messages.log lands here
services:
init-output-dir:
image: docker.elastic.co/logstash/logstash:8.15.3
user: root
entrypoint: ["/bin/bash", "-c", "chown -R 1000:1000 /var/log/kafka"]
volumes:
- ./output:/var/log/kafka
logstash:
image: docker.elastic.co/logstash/logstash:8.15.3
container_name: logstash-kafka-to-file
restart: unless-stopped
depends_on:
init-output-dir:
condition: service_completed_successfully
volumes:
- ./pipeline:/usr/share/logstash/pipeline:ro
- ./output:/var/log/kafka
environment:
LS_JAVA_OPTS: "-Xms512m -Xmx512m"
XPACK_MONITORING_ENABLED: "false"
# Kafka connection — any host:port
KAFKA_BOOTSTRAP_SERVERS: "broker:9092"
KAFKA_TOPIC: "io.metalsoft.significant_event"
# Replace the IP with your Kafka LoadBalancer IP. This is the only required
# change needed to get events from the MetalSoft Kafka into a local file
extra_hosts:
- "broker:203.0.113.10"
input {
kafka {
# Comma-separated list of Kafka brokers (host:port), taken from the
# KAFKA_BOOTSTRAP_SERVERS env var; the value after the first ":" is the
# default when the var is unset. Any port works, e.g. "broker:19092".
bootstrap_servers => "${KAFKA_BOOTSTRAP_SERVERS:broker:19092}"
# Topic(s) to consume from
topics => ["${KAFKA_TOPIC:my-topic}"]
# Consumer group — Kafka tracks this group's offsets, so Logstash
# resumes where it left off after a restart
group_id => "logstash-file-writer"
# Where to start when the group has no committed offsets yet:
# "earliest" = replay everything on the topic, "latest" = only new messages
auto_offset_reset => "earliest"
# Keep the raw message as-is in the "message" field.
# Switch to "json" if your messages are JSON and you want them parsed
# into individual event fields.
codec => "plain"
# Number of consumer threads; at most one per topic partition is useful
consumer_threads => 1
# Attach Kafka metadata (topic, partition, offset, key, timestamp)
# under [@metadata][kafka]
decorate_events => "basic"
}
}
filter {
# Nothing needed for plain pass-through. Example if messages are JSON:
# json { source => "message" }
}
output {
file {
# Appends by default; the directory must be writable by the logstash user.
# Supports field references, e.g. "/var/log/kafka/%{[@metadata][kafka][topic]}.log"
# to get one file per topic.
path => "/var/log/kafka/messages.log"
# Write just the raw message text, one per line.
# Remove the codec line entirely to write full events as JSON lines instead.
codec => line { format => "%{message}" }
# Flush to disk after every event (set higher, e.g. 64, for throughput)
flush_interval => 0
}
# Uncomment while testing to also see events on the console:
# stdout { codec => rubydebug }
}

Broker and topic are read from environment variables, set in docker-compose.yml (or exported in the shell for a native install):

  • KAFKA_BOOTSTRAP_SERVERS — broker(s) as host:port, e.g. "broker:9092" or "kafka1:9092,kafka2:9092"
  • KAFKA_TOPIC — the topic to consume, here io.metalsoft.significant_event

The extra_hosts entry in docker-compose.yml maps the hostname broker to the Kafka machine’s IP — adjust the IP there (and the port in KAFKA_BOOTSTRAP_SERVERS) to match your exposed broker. This also covers brokers whose advertised listener is a hostname the container can’t otherwise resolve.

Everything else lives in pipeline/kafka-to-file.conf:

  • topics — turn into a list there if you need more than one topic
  • path in the file output — where to append messages (in the Docker setup, /var/log/kafka/ inside the container is mapped to ./output/ on the host)

By default the raw message text is written verbatim, one line per message. Two common variations:

  • Full event as JSON lines (includes @timestamp, Kafka metadata, etc.): delete the codec => line {...} line from the file output.
  • Parse JSON messages into fields: uncomment the json filter and set the input codec to "json".

If Kafka requires authentication (SASL/TLS), add to the kafka input block, e.g.:

security_protocol => "SASL_SSL"
sasl_mechanism => "PLAIN"
sasl_jaas_config => 'org.apache.kafka.common.security.plain.PlainLoginModule required username="USER" password="PASS";'
Terminal window
cd logstash-kafka-to-file
docker compose up -d
tail -f output/messages.log

The init-output-dir service runs once before Logstash and chowns ./output to UID/GID 1000 (the container’s logstash user), so no manual permission setup is needed on the host.

Terminal window
# Debian/Ubuntu package install:
sudo cp pipeline/kafka-to-file.conf /etc/logstash/conf.d/
sudo mkdir -p /var/log/kafka && sudo chown logstash: /var/log/kafka
sudo systemctl restart logstash

Or run it in the foreground for a quick test:

Terminal window
/usr/share/logstash/bin/logstash -f pipeline/kafka-to-file.conf

The Kafka input plugin ships with Logstash by default — no extra plugin install needed.

  • Offsets are committed under the consumer group logstash-file-writer, so restarts resume where they left off; change group_id to re-read independently.
  • auto_offset_reset => "earliest" replays the whole topic on first run; set to "latest" for only new messages.
  • flush_interval => 0 flushes every event immediately — safest, but for high throughput raise it (seconds) to batch writes.
  • One file per topic: set the path to "/var/log/kafka/%{[@metadata][kafka][topic]}.log".