Skip to main content

Overview

The Notify Service is Argos Mesh’s notification delivery system that consumes security alerts from the Sentinel service and delivers them to operators. It acts as the final stage in the security event pipeline, ensuring that critical alerts are properly logged and can be extended to support multiple notification channels.
Notify is designed as a lightweight, stateless service that focuses solely on alert delivery without external dependencies.

Architecture

Service Responsibilities

Alert Consumption

Listens to the alert queue for security events from Sentinel

Notification Delivery

Outputs alerts to configured notification channels (currently console)

Event Logging

Maintains a record of all security incidents

Extensibility

Designed to support email, SMS, Slack, and webhook integrations

Core Components

AlertNotifier

The AlertNotifier is the main component that processes incoming alerts:
@Service
public class AlertNotifier {

    @RabbitListener(queues = "argos.alert.queue")
    public void sendNotification(AlertInternalEvent alert) {
        System.out.println("[ Alert ] - " + alert.timeStamp());
        System.out.println("The IP: " + alert.sourceIp());
        System.out.println("Is suspicious of try an: " + alert.type());
        System.out.println("This is: " + alert.severity());
    }
}
1

Event Reception

The @RabbitListener annotation subscribes to the argos.alert.queue
2

Deserialization

RabbitMQ automatically deserializes JSON messages to AlertInternalEvent objects
3

Notification Output

Alert details are formatted and output to the console (extensible to other channels)

Event Schema

AlertInternalEvent

The service consumes alert events from the Sentinel service:
public record AlertInternalEvent(
    String type,        // "DDOs Attack" or "Suspicious behavior"
    String sourceIp,    // "127.0.0.1"
    String severity,    // "CRITICAL", "HIGH", "MEDIUM", "LOW"
    LocalDateTime timeStamp
) {}
Field Descriptions:

Alert Type

Describes the nature of the security event:
  • "Suspicious behavior" - Rate limit exceeded
  • "DDoS Attack" - Distributed denial of service attempt
  • Extensible for future threat types
alert.type() // "Suspicious behavior"

RabbitMQ Configuration

The service configures its messaging infrastructure:
@Configuration
public class RabbitMQConfig {

    public static final String QUEUE_ALERT = "argos.alert.queue";
    public static final String ALERT_EXCHANGE = "alert.exchange";
    public static final String RK_ALERT = "argos.alert.#";

    @Bean
    public Queue alertQueue() {
        return new Queue(QUEUE_ALERT, true);
    }

    @Bean
    public TopicExchange exchange() {
        return new TopicExchange(ALERT_EXCHANGE);
    }

    @Bean
    public Binding binding(Queue alertQueue, TopicExchange exchange) {
        return BindingBuilder.bind(alertQueue).to(exchange).with(RK_ALERT);
    }
}

Queue Configuration

Alert Queue

Queue Name: argos.alert.queueExchange: alert.exchange (Topic)Routing Key Pattern: argos.alert.#Durable: true (survives broker restarts)The wildcard pattern argos.alert.# allows the service to receive all alert types:
  • argos.alert.security
  • argos.alert.performance
  • argos.alert.* (future extensions)

Message Converter

The service uses Jackson for JSON deserialization:
@Bean
public ObjectMapper objectMapper() {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.registerModule(new JavaTimeModule());
    objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    return objectMapper;
}

@Bean
public MessageConverter jsonMessageConverter(ObjectMapper objectMapper) {
    return new Jackson2JsonMessageConverter(objectMapper);
}
The JavaTimeModule ensures proper serialization/deserialization of LocalDateTime fields.

Notification Output

When an alert is received, the service outputs structured information:

Example Console Output

[ Alert ] - 2026-03-05T14:23:45.123
The IP: 192.168.1.100
Is suspicious of try an: Suspicious behavior
This is: CRITICAL

Output Format

System.out.println("[ Alert ] - " + alert.timeStamp());
System.out.println("The IP: " + alert.sourceIp());
System.out.println("Is suspicious of try an: " + alert.type());
System.out.println("This is: " + alert.severity());
The current implementation uses System.out.println() for simplicity, making alerts visible in container logs.

Extension Points

The Notify service is designed to be extended with multiple notification channels:

Email Notifications

Send alerts to on-call engineers via SMTP
@Service
public class EmailNotifier {
    @Autowired
    private JavaMailSender mailSender;
    
    public void sendAlert(AlertInternalEvent alert) {
        // Email implementation
    }
}

Slack Integration

Post alerts to Slack channels using webhooks
@Service
public class SlackNotifier {
    @Value("${slack.webhook.url}")
    private String webhookUrl;
    
    public void sendAlert(AlertInternalEvent alert) {
        // Slack API call
    }
}

SMS Alerts

Send critical alerts via Twilio or AWS SNS
@Service
public class SmsNotifier {
    @Autowired
    private TwilioClient twilioClient;
    
    public void sendAlert(AlertInternalEvent alert) {
        // SMS implementation
    }
}

Webhook Integration

POST alerts to external monitoring systems
@Service
public class WebhookNotifier {
    @Autowired
    private RestTemplate restTemplate;
    
    public void sendAlert(AlertInternalEvent alert) {
        // HTTP POST to webhook
    }
}

Multi-Channel Notification Strategy

Implement a notification router based on severity:
@Service
public class NotificationRouter {
    @Autowired
    private EmailNotifier emailNotifier;
    
    @Autowired
    private SlackNotifier slackNotifier;
    
    @Autowired
    private SmsNotifier smsNotifier;
    
    @RabbitListener(queues = "argos.alert.queue")
    public void routeAlert(AlertInternalEvent alert) {
        // Always log to console
        logToConsole(alert);
        
        // Route based on severity
        switch (alert.severity()) {
            case "CRITICAL":
                smsNotifier.sendAlert(alert);
                emailNotifier.sendAlert(alert);
                slackNotifier.sendAlert(alert);
                break;
            case "HIGH":
                emailNotifier.sendAlert(alert);
                slackNotifier.sendAlert(alert);
                break;
            case "MEDIUM":
                slackNotifier.sendAlert(alert);
                break;
            case "LOW":
                // Console logging only
                break;
        }
    }
}
This pattern allows you to escalate notifications based on severity, ensuring critical alerts reach multiple channels immediately.

Configuration

The service has minimal configuration requirements:
spring.application.name=argos-notify

RabbitMQ Connection

RabbitMQ connection details are inherited from the default Spring Boot configuration:
# Add these if not using defaults
spring.rabbitmq.host=message_broker
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=admin123

Deployment

1

No External Dependencies

The service only requires RabbitMQ - no database or cache needed
2

Stateless Design

Multiple instances can run concurrently for high availability
3

Lightweight Runtime

Minimal memory footprint suitable for constrained environments
4

Container-Ready

Logs to stdout/stderr for container log aggregation

Traffic Flow

Monitoring and Observability

Track notification delivery with Spring Boot Actuator:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Metrics to Monitor

Message Consumption Rate

Track alerts processed per second

Queue Depth

Monitor argos.alert.queue backlog

Delivery Failures

Count failed notification attempts

Severity Distribution

Analyze alert severity over time

Error Handling

Implement retry logic for transient failures:
@RabbitListener(queues = "argos.alert.queue")
public void sendNotification(AlertInternalEvent alert) {
    try {
        // Notification logic
    } catch (Exception e) {
        logger.error("Failed to deliver notification for alert: {}", alert, e);
        // Consider implementing dead-letter queue for failed alerts
        throw new AmqpRejectAndDontRequeueException("Notification delivery failed", e);
    }
}
Use AmqpRejectAndDontRequeueException to send failed messages to a dead-letter queue for manual investigation.

Next Steps

Sentinel Service

Learn how Sentinel generates security alerts

RabbitMQ Configuration

Configure the message broker infrastructure

Security Features

Learn about the DDoS protection system

Deployment Guide

Deploy the complete Argos Mesh stack

Build docs developers (and LLMs) love