Skip to main content

Logical Architecture


Module: Lens Platform: Stormus Version: 1.0.0-RELEASE Last Updated: October 25, 2025 Document Type: Logical Architecture (Component View)


Table of Contents​

  1. Introduction
  2. Architectural Layers
  3. Component Diagram
  4. Package Structure
  5. Layer Responsibilities
  6. Communication Patterns
  7. Design Patterns
  8. Module Dependencies
  9. Cross-Cutting Concerns

Introduction​

This document describes the logical architecture of the AWS Lens module, focusing on the structural organization of components, layers, and design patterns. It provides a developer's view of how the system is organized internally.

Purpose of This Document​

  • Define architectural layers and their responsibilities
  • Document component structure and relationships
  • Explain design patterns and principles
  • Guide developers on where to add new features
  • Ensure architectural consistency

Architectural Style​

Lens follows a Layered Architecture pattern with clear separation of concerns:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Presentation Layer (Controllers) β”‚
β”‚ 40 REST Controllers β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Application Layer (Services) β”‚
β”‚ 107 Service Classes β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Data Access Layer (DAOs & Repositories) β”‚
β”‚ 47 DAO Classes + JPA Repos β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Data Transfer Layer (DTOs & Documents) β”‚
β”‚ 165 DTOs + MongoDB Documents β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Infrastructure Layer (Config, Utils) β”‚
β”‚ Configuration + Utilities + Cross-Cutting β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Architectural Layers​

Layer 1: Presentation Layer (Controllers)​

Responsibility: HTTP request handling, input validation, response formatting

Components: 40 REST Controllers

Package: com.ttn.ck.lens.controller

Key Characteristics:

  • Stateless: Controllers do not maintain state
  • Thin: Minimal business logic, delegate to service layer
  • RESTful: Follow REST API conventions
  • Secured: All endpoints annotated with @Secured
  • Validated: Input validation via @Valid and BindingResult

Controller Categories:

  1. Core Controllers (14): Base cost management endpoints
  2. Alert Controllers (5): Located in controller/alertsapi
  3. Cost Breakup Controllers (13): Located in controller/costbreakup
  4. CUDOS Controllers (3): Located in controller/cudos
  5. FinOps Controllers (1): Located in controller/finops
  6. Marketplace Controllers (1): Located in controller/marketplace
  7. Monthly Report Controllers (2): Located in controller/monthlyreport

Responsibilities:

  • Receive HTTP requests
  • Validate input using @Valid annotations
  • Call appropriate service methods
  • Wrap responses in ResponseDto (success/error)
  • Handle HTTP status codes
  • Return JSON responses

Not Responsible For:

  • Business logic execution
  • Database queries
  • External API calls
  • Complex calculations

Layer 2: Application Layer (Services)​

Responsibility: Business logic, orchestration, transaction management

Components: 107 Service Classes (interfaces + implementations)

Package: com.ttn.ck.lens.service (interfaces), com.ttn.ck.lens.service.impl (implementations)

Key Characteristics:

  • Interface-based: Services defined as interfaces, implementations separate
  • Transactional: Use @Transactional where needed
  • Orchestration: Coordinate multiple DAOs and external services
  • Business Rules: Implement all business logic
  • Testable: Easy to mock for unit testing

Service Categories:

  1. Core Services: AwsVsActualCostService, BillingConsoleService, etc.
  2. Cost Breakup Services: 12 categories (Analytics, Containers, Database, etc.)
  3. CUDOS Services: S3Dashboard, DataTransferDashboard, DatabaseDashboard
  4. Utility Services: DatesService, RecommendationService, etc.

Subpackage Structure:

service/
β”œβ”€β”€ (interfaces) # Service interfaces
β”œβ”€β”€ impl/ # Core implementations
β”‚ β”œβ”€β”€ billingsummary/ # Billing summary services
β”‚ └── costbreakup/ # Cost breakup services
β”‚ β”œβ”€β”€ analytics/
β”‚ β”œβ”€β”€ containers/
β”‚ β”œβ”€β”€ database/
β”‚ β”œβ”€β”€ datatransfer/
β”‚ β”œβ”€β”€ instance/
β”‚ β”œβ”€β”€ managementandgovernance/
β”‚ β”œβ”€β”€ media/
β”‚ β”œβ”€β”€ migrationandtransfer/
β”‚ β”œβ”€β”€ networkingandcontent/
β”‚ β”œβ”€β”€ security/
β”‚ β”œβ”€β”€ serverless/
β”‚ └── storage/

Responsibilities:

  • Execute business logic
  • Validate business rules
  • Aggregate data from multiple DAOs
  • Transform DTOs
  • Call external APIs (AWS SDK, Feign clients)
  • Cache results (when appropriate)
  • Handle exceptions and retries

Not Responsible For:

  • HTTP request/response handling
  • SQL query construction
  • Direct database access
  • UI concerns

Layer 3: Data Access Layer (DAOs & Repositories)​

Responsibility: Database queries, data persistence, external data sources

Components: 47 DAO Classes + JPA Repositories

Packages:

  • com.ttn.ck.lens.dao (interfaces)
  • com.ttn.ck.lens.dao.impl (implementations)
  • com.ttn.ck.lens.repo (JPA repositories)
  • com.ttn.ck.lens.queries (SQL query classes)

Key Characteristics:

  • Data Source Abstraction: Hide database implementation details
  • Query Optimization: Efficient SQL queries
  • Multi-Database: Support Snowflake, MongoDB, MySQL
  • Result Mapping: Map database rows to DTOs

DAO Categories:

  1. Snowflake DAOs: Cost data queries (primary data source)
  2. MongoDB Repositories: Document storage (saved reports, filters)
  3. JPA Repositories: Transactional data (MySQL)

Subpackage Structure:

dao/
β”œβ”€β”€ (interfaces) # DAO interfaces
β”œβ”€β”€ impl/ # Snowflake DAO implementations
β”œβ”€β”€ cudos/ # CUDOS-specific DAOs
└── marketplace/ # Marketplace DAOs

repo/ # JPA & Mongo repositories

queries/ # SQL query classes
β”œβ”€β”€ costbreakup/
β”œβ”€β”€ cudos/
└── marketplace/

Responsibilities:

  • Execute Snowflake SQL queries
  • Map result sets to DTOs
  • Handle database connections
  • Query optimization
  • Pagination
  • Caching query results

Not Responsible For:

  • Business logic
  • Data transformation (beyond mapping)
  • HTTP handling

Layer 4: Data Transfer Layer (DTOs & Documents)​

Responsibility: Data structures for transferring data between layers

Components: 165 DTOs + MongoDB Documents

Packages:

  • com.ttn.ck.lens.dto (Data Transfer Objects for API)
  • com.ttn.ck.lens.document (MongoDB documents)

Key Characteristics:

  • Immutability: DTOs should be immutable (use @Data for Lombok)
  • Validation Annotations: Use JSR-303 annotations (@NotNull, @Size, etc.)
  • Serializable: Support JSON serialization
  • Flat Structure: Avoid deep nesting

DTO Categories:

dto/
β”œβ”€β”€ AwsVsActualCost/ # Cost comparison DTOs
β”œβ”€β”€ accountwisebreakup/ # Account breakup DTOs
β”œβ”€β”€ billingconsole/ # Billing console DTOs
β”œβ”€β”€ billingsummary/ # Billing summary DTOs
β”œβ”€β”€ costalert/ # Cost alert DTOs
β”œβ”€β”€ costbreakup/ # Cost breakup DTOs (12 categories)
β”œβ”€β”€ costexplorer/ # Cost explorer DTOs
β”œβ”€β”€ costtrends/ # Cost trends DTOs
β”œβ”€β”€ cudos/ # CUDOS dashboard DTOs
β”œβ”€β”€ recommendation/ # Recommendation DTOs
β”œβ”€β”€ reservation/ # Reservation DTOs
β”œβ”€β”€ ricoverage/ # RI coverage DTOs
β”œβ”€β”€ riexpiry/ # RI expiry DTOs
└── GenericRequestDTO.java # Common request DTO

Responsibilities:

  • Define data contracts between layers
  • Input validation (request DTOs)
  • Response formatting (response DTOs)
  • JSON serialization/deserialization
  • Field-level validation

Not Responsible For:

  • Business logic
  • Database operations
  • HTTP handling

Layer 5: Infrastructure Layer (Config, Utils, Cross-Cutting)​

Responsibility: Configuration, utilities, cross-cutting concerns

Components: Configuration classes, utilities, caching, listeners

Packages:

  • com.ttn.ck.lens.config (Configuration classes)
  • com.ttn.ck.lens.utils (Utility classes)
  • com.ttn.ck.lens.cache (Caching logic)
  • com.ttn.ck.lens.listner (Event listeners)
  • com.ttn.ck.lens.enums (Enumerations)
  • com.ttn.ck.lens.clients (External service clients - Feign)

Key Characteristics:

  • Reusable: Used across all layers
  • Stateless: Most utilities are stateless
  • Configuration: Externalized via Spring Cloud Config

Subpackages:

config/                              # Spring configuration
β”œβ”€β”€ SnowflakeConfig.java
β”œβ”€β”€ MongoConfig.java
β”œβ”€β”€ RedisConfig.java
└── RabbitMQConfig.java

utils/ # Utility classes
β”œβ”€β”€ ApplicationConstants.java # 660+ constants
β”œβ”€β”€ ApplicationUtils.java # Common utilities
β”œβ”€β”€ ColumnNameConstants.java # Database column names
β”œβ”€β”€ QueueConstants.java # RabbitMQ constants
β”œβ”€β”€ SortUtils.java # Sorting utilities
└── AccountWiseBreakUpReportGenerator.java

cache/ # Caching logic
└── CacheConfiguration.java

listner/ # Event listeners
└── MessageQueueListener.java # RabbitMQ consumer

clients/ # Feign clients
└── AwsRecommendationClient.java # AWS Cost Explorer API

enums/ # Enumerations
β”œβ”€β”€ costbreakup/
└── cudos/

Responsibilities:

  • Application configuration
  • Common utilities (date, string, sorting)
  • Constants management
  • Caching configuration
  • Event processing (RabbitMQ listeners)
  • External API clients (Feign)

Not Responsible For:

  • Business logic
  • Direct database access

Component Diagram​

High-Level Component View​

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ LENS MODULE β”‚
β”‚ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ PRESENTATION LAYER (Controllers) β”‚ β”‚
β”‚ β”‚ β”‚ β”‚
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
β”‚ β”‚ β”‚ Core β”‚ β”‚ Alerts β”‚ β”‚ CostBreakup β”‚ β”‚ β”‚
β”‚ β”‚ β”‚ Controllers β”‚ β”‚ Controllers β”‚ β”‚ Controllers β”‚ β”‚ β”‚
β”‚ β”‚ β”‚ (14) β”‚ β”‚ (5) β”‚ β”‚ (13) β”‚ β”‚ β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ APPLICATION LAYER (Services) β”‚ β”‚ β”‚
β”‚ β”‚ β–Ό β”‚ β”‚
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚ β”‚
β”‚ β”‚ β”‚ Core β”‚ β”‚ CostBreakup β”‚ β”‚ CUDOS Services β”‚β”‚ β”‚
β”‚ β”‚ β”‚ Services β”‚ β”‚ Services β”‚ β”‚ β”‚β”‚ β”‚
β”‚ β”‚ β”‚ (20) β”‚ β”‚ (60+) β”‚ β”‚ (3) β”‚β”‚ β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚ β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ DATA ACCESS LAYER (DAOs & Repositories) β”‚ β”‚ β”‚
β”‚ β”‚ β–Ό β”‚ β”‚
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
β”‚ β”‚ β”‚ Snowflake β”‚ β”‚ MongoDB β”‚ β”‚ JPA Repos β”‚ β”‚ β”‚
β”‚ β”‚ β”‚ DAOs β”‚ β”‚ Repositories β”‚ β”‚ (MySQL) β”‚ β”‚ β”‚
β”‚ β”‚ β”‚ (35+) β”‚ β”‚ (5) β”‚ β”‚ (7) β”‚ β”‚ β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ β–Ό β–Ό β–Ό β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚
β”‚ β”‚ DATA SOURCES β”‚β”‚
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”‚β”‚
β”‚ β”‚ β”‚Snowflake β”‚ β”‚ MongoDB β”‚ β”‚ MySQL β”‚ β”‚ Redis β”‚ β”‚β”‚
β”‚ β”‚ β”‚Analytics β”‚ β”‚Documents β”‚ β”‚Transactionβ”‚ β”‚ Cache β”‚ β”‚β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚
β”‚ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚
β”‚ β”‚ EXTERNAL INTEGRATIONS β”‚β”‚
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”‚β”‚
β”‚ β”‚ β”‚ AWS SDK β”‚ β”‚ RabbitMQ β”‚ β”‚ Config β”‚ β”‚ AuthX β”‚ β”‚β”‚
β”‚ β”‚ β”‚(Feign) β”‚ β”‚ (AMQP) β”‚ β”‚ Server β”‚ β”‚ (JWT) β”‚ β”‚β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Package Structure​

Complete Package Hierarchy​

com.ttn.ck.lens/
β”‚
β”œβ”€β”€ LensApplication.java # Main Spring Boot application
β”‚
β”œβ”€β”€ controller/ # Presentation Layer (40 controllers)
β”‚ β”œβ”€β”€ AwsVsActualCostController.java
β”‚ β”œβ”€β”€ BillingConsoleController.java
β”‚ β”œβ”€β”€ BillingSummaryController.java
β”‚ β”œβ”€β”€ CostExplorerController.java
β”‚ β”œβ”€β”€ CostTrendsController.java
β”‚ β”œβ”€β”€ DatesController.java
β”‚ β”œβ”€β”€ RecommendationController.java
β”‚ β”œβ”€β”€ ReservationController.java
β”‚ β”œβ”€β”€ ReservationUtilizationController.java
β”‚ β”œβ”€β”€ RiCoverageController.java
β”‚ β”œβ”€β”€ SavedReportFilterMetaController.java
β”‚ β”œβ”€β”€ TagReportController.java
β”‚ β”œβ”€β”€ AccountWiseBreakupController.java
β”‚ β”œβ”€β”€ AccountWiseBreakupV2Controller.java
β”‚ β”‚
β”‚ β”œβ”€β”€ alertsapi/ # Alert controllers (5)
β”‚ β”‚ β”œβ”€β”€ AccountsDatesController.java
β”‚ β”‚ β”œβ”€β”€ CostAlertController.java
β”‚ β”‚ β”œβ”€β”€ DailyReportController.java
β”‚ β”‚ β”œβ”€β”€ RiExpiryAlertController.java
β”‚ β”‚ └── RiUtilizationAlertController.java
β”‚ β”‚
β”‚ β”œβ”€β”€ costbreakup/ # Cost breakup controllers (13)
β”‚ β”‚ β”œβ”€β”€ AbstractCostBreakupController.java
β”‚ β”‚ β”œβ”€β”€ AnalyticsController.java
β”‚ β”‚ β”œβ”€β”€ ContainersController.java
β”‚ β”‚ β”œβ”€β”€ DatabaseController.java
β”‚ β”‚ β”œβ”€β”€ DataTransferController.java
β”‚ β”‚ β”œβ”€β”€ InstanceCostController.java
β”‚ β”‚ β”œβ”€β”€ ManagementAndGovernanceController.java
β”‚ β”‚ β”œβ”€β”€ MediaController.java
β”‚ β”‚ β”œβ”€β”€ MigrationAndTransferController.java
β”‚ β”‚ β”œβ”€β”€ NetworkingAndContentDeliveryController.java
β”‚ β”‚ β”œβ”€β”€ SecurityController.java
β”‚ β”‚ β”œβ”€β”€ ServerlessController.java
β”‚ β”‚ └── StorageController.java
β”‚ β”‚
β”‚ β”œβ”€β”€ cudos/ # CUDOS controllers (3)
β”‚ β”‚ β”œβ”€β”€ DataTransferDashboardController.java
β”‚ β”‚ β”œβ”€β”€ S3DashboardController.java
β”‚ β”‚ └── DatabaseDashboardController.java
β”‚ β”‚
β”‚ β”œβ”€β”€ finops/ # FinOps controller (1)
β”‚ β”‚ └── FinOpsRecommendationController.java
β”‚ β”‚
β”‚ β”œβ”€β”€ marketplace/ # Marketplace controller (1)
β”‚ β”‚ └── MarketPlaceController.java
β”‚ β”‚
β”‚ └── monthlyreport/ # Monthly report controllers (2)
β”‚ β”œβ”€β”€ MonthlyReportAccountDates.java
β”‚ └── ReportRecommendationController.java
β”‚
β”œβ”€β”€ service/ # Application Layer (107 services)
β”‚ β”œβ”€β”€ (Interface files) # Service interfaces
β”‚ β”‚ β”œβ”€β”€ AwsVsActualCostService.java
β”‚ β”‚ β”œβ”€β”€ BillingConsoleService.java
β”‚ β”‚ β”œβ”€β”€ BillingSummaryService.java
β”‚ β”‚ β”œβ”€β”€ CostExplorerService.java
β”‚ β”‚ β”œβ”€β”€ CostTrendsService.java
β”‚ β”‚ β”œβ”€β”€ RecommendationService.java
β”‚ β”‚ β”œβ”€β”€ ReservationService.java
β”‚ β”‚ └── ... (20+ core service interfaces)
β”‚ β”‚
β”‚ └── impl/ # Service implementations
β”‚ β”œβ”€β”€ AwsVsActualCostServiceImpl.java
β”‚ β”œβ”€β”€ BillingConsoleServiceImpl.java
β”‚ β”œβ”€β”€ BillingSummaryServiceImpl.java
β”‚ β”œβ”€β”€ CostExplorerServiceImpl.java
β”‚ β”œβ”€β”€ CostTrendsServiceImpl.java
β”‚ β”œβ”€β”€ ... (20+ core implementations)
β”‚ β”‚
β”‚ β”œβ”€β”€ billingsummary/ # Billing summary services
β”‚ β”‚ └── ... (billing services)
β”‚ β”‚
β”‚ └── costbreakup/ # Cost breakup services (60+)
β”‚ β”œβ”€β”€ analytics/
β”‚ β”‚ β”œβ”€β”€ AnalyticsService.java
β”‚ β”‚ β”œβ”€β”€ AnalyticsServiceImpl.java
β”‚ β”‚ β”œβ”€β”€ KinesisService.java
β”‚ β”‚ └── EmrService.java
β”‚ β”‚
β”‚ β”œβ”€β”€ containers/
β”‚ β”‚ β”œβ”€β”€ ContainersService.java
β”‚ β”‚ β”œβ”€β”€ EcsService.java
β”‚ β”‚ β”œβ”€β”€ EksService.java
β”‚ β”‚ └── FargateService.java
β”‚ β”‚
β”‚ β”œβ”€β”€ database/
β”‚ β”‚ β”œβ”€β”€ DatabaseService.java
β”‚ β”‚ β”œβ”€β”€ RdsService.java
β”‚ β”‚ β”œβ”€β”€ DynamoDbService.java
β”‚ β”‚ β”œβ”€β”€ ElastiCacheService.java
β”‚ β”‚ └── RedshiftService.java
β”‚ β”‚
β”‚ β”œβ”€β”€ datatransfer/
β”‚ β”œβ”€β”€ instance/
β”‚ β”œβ”€β”€ managementandgovernance/
β”‚ β”œβ”€β”€ media/
β”‚ β”œβ”€β”€ migrationandtransfer/
β”‚ β”œβ”€β”€ networkingandcontent/
β”‚ β”œβ”€β”€ security/
β”‚ β”œβ”€β”€ serverless/
β”‚ └── storage/
β”‚
β”œβ”€β”€ dao/ # Data Access Layer (47 DAOs)
β”‚ β”œβ”€β”€ (Interface files) # DAO interfaces
β”‚ β”‚ β”œβ”€β”€ AwsVsActualCostDao.java
β”‚ β”‚ β”œβ”€β”€ BillingConsoleDao.java
β”‚ β”‚ β”œβ”€β”€ CostExplorerDao.java
β”‚ β”‚ └── ... (35+ DAO interfaces)
β”‚ β”‚
β”‚ β”œβ”€β”€ impl/ # DAO implementations
β”‚ β”‚ β”œβ”€β”€ AwsVsActualCostDaoImpl.java
β”‚ β”‚ β”œβ”€β”€ BillingConsoleDaoImpl.java
β”‚ β”‚ └── ... (35+ implementations)
β”‚ β”‚
β”‚ β”œβ”€β”€ cudos/ # CUDOS DAOs
β”‚ β”‚ β”œβ”€β”€ S3DashboardDao.java
β”‚ β”‚ β”œβ”€β”€ DataTransferDashboardDao.java
β”‚ β”‚ └── DatabaseDashboardDao.java
β”‚ β”‚
β”‚ └── marketplace/ # Marketplace DAOs
β”‚ └── MarketPlaceDao.java
β”‚
β”œβ”€β”€ queries/ # SQL Query Classes
β”‚ β”œβ”€β”€ costbreakup/
β”‚ β”‚ β”œβ”€β”€ AnalyticsQueries.java
β”‚ β”‚ β”œβ”€β”€ DatabaseQueries.java
β”‚ β”‚ β”œβ”€β”€ StorageQueries.java
β”‚ β”‚ └── ... (12 query classes)
β”‚ β”‚
β”‚ β”œβ”€β”€ cudos/
β”‚ β”‚ β”œβ”€β”€ S3Queries.java
β”‚ β”‚ β”œβ”€β”€ DataTransferQueries.java
β”‚ β”‚ └── DatabaseQueries.java
β”‚ β”‚
β”‚ └── marketplace/
β”‚ └── MarketPlaceQueries.java
β”‚
β”œβ”€β”€ dto/ # Data Transfer Layer (165 DTOs)
β”‚ β”œβ”€β”€ GenericRequestDTO.java # Common request DTO
β”‚ β”œβ”€β”€ AwsVsActualCost/
β”‚ β”œβ”€β”€ accountwisebreakup/
β”‚ β”œβ”€β”€ billingconsole/
β”‚ β”œβ”€β”€ billingsummary/
β”‚ β”œβ”€β”€ costalert/
β”‚ β”œβ”€β”€ costbreakup/ # 12 subcategories
β”‚ β”œβ”€β”€ costexplorer/
β”‚ β”œβ”€β”€ costtrends/
β”‚ β”œβ”€β”€ cudos/
β”‚ β”œβ”€β”€ recommendation/
β”‚ β”œβ”€β”€ reservation/
β”‚ β”œβ”€β”€ ricoverage/
β”‚ └── riexpiry/
β”‚
β”œβ”€β”€ document/ # MongoDB Documents
β”‚ β”œβ”€β”€ SavedReportDocument.java
β”‚ β”œβ”€β”€ FilterMetadataDocument.java
β”‚ └── CustomQueryDocument.java
β”‚
β”œβ”€β”€ repo/ # JPA & MongoDB Repositories
β”‚ β”œβ”€β”€ SavedReportRepository.java # MongoDB
β”‚ β”œβ”€β”€ FilterMetadataRepository.java # MongoDB
β”‚ └── ... (7 repositories)
β”‚
β”œβ”€β”€ config/ # Configuration Classes
β”‚ β”œβ”€β”€ SnowflakeConfig.java
β”‚ β”œβ”€β”€ MongoConfig.java
β”‚ β”œβ”€β”€ RedisConfig.java
β”‚ β”œβ”€β”€ RabbitMQConfig.java
β”‚ β”œβ”€β”€ CacheConfig.java
β”‚ └── SwaggerConfig.java
β”‚
β”œβ”€β”€ utils/ # Utility Classes
β”‚ β”œβ”€β”€ ApplicationConstants.java # 660+ constants
β”‚ β”œβ”€β”€ ApplicationUtils.java
β”‚ β”œβ”€β”€ ColumnNameConstants.java
β”‚ β”œβ”€β”€ QueueConstants.java
β”‚ β”œβ”€β”€ HourlyDataConverter.java
β”‚ β”œβ”€β”€ SequenceGenerationUtil.java
β”‚ β”œβ”€β”€ SortUtils.java
β”‚ β”œβ”€β”€ StrReplaceForMongoUtils.java
β”‚ β”œβ”€β”€ UtilityService.java
β”‚ └── AccountWiseBreakUpReportGenerator.java
β”‚
β”œβ”€β”€ cache/ # Caching Logic
β”‚ └── CacheConfiguration.java
β”‚
β”œβ”€β”€ listner/ # Event Listeners
β”‚ └── MessageQueueListener.java # RabbitMQ consumer
β”‚
β”œβ”€β”€ clients/ # External Service Clients
β”‚ └── AwsRecommendationClient.java # Feign client
β”‚
└── enums/ # Enumerations
β”œβ”€β”€ costbreakup/
β”‚ β”œβ”€β”€ AnalyticsServiceEnum.java
β”‚ β”œβ”€β”€ DatabaseServiceEnum.java
β”‚ └── ... (12 enum files)
└── cudos/
└── CudosServiceEnum.java

Layer Responsibilities​

Request Flow Through Layers​

Example: Get Cost Summary Request

1. HTTP Request
↓
2. AwsVsActualCostController.getAwsAndActualCostSummary()
- Validates input (@Valid GenericRequestDTO)
- Security check (@Secured annotation)
↓
3. AwsVsActualCostService.getCostSummary()
- Business logic: Date range validation
- Calls DAO layer
- Aggregates results
- Calculates savings percentage
↓
4. AwsVsActualCostDao.queryCostData()
- Builds Snowflake SQL query
- Executes query
- Maps ResultSet to DTOs
↓
5. Snowflake Database
- Executes query
- Returns result set
↓
6. (Return path - up the stack)
DAO β†’ Service β†’ Controller β†’ HTTP Response

Separation of Concerns:

  • Controller: "What data did the user request?" (routing)
  • Service: "How do we process this business logic?" (orchestration)
  • DAO: "How do we fetch this data?" (persistence)
  • DTO: "What does the data look like?" (structure)

Communication Patterns​

1. Synchronous Request-Response​

Pattern: Controller β†’ Service β†’ DAO β†’ Database β†’ Response

Used For: Most API endpoints (cost queries, dashboards, reports)

Example:

// Controller
@GetMapping("/cost/summary")
public ResponseDto<`List<CostSummaryDTO>`> getCostSummary(@Valid GenericRequestDTO request) {
return new SuccessResponseDto<>(awsVsActualCostService.getCostSummary(request));
}

// Service
public `List<CostSummaryDTO>` getCostSummary(GenericRequestDTO request) {
// Business logic
return awsVsActualCostDao.queryCostSummary(request);
}

// DAO
public `List<CostSummaryDTO>` queryCostSummary(GenericRequestDTO request) {
// SQL query execution
return jdbcTemplate.query(sql, rowMapper);
}

Characteristics:

  • Blocking (request waits for response)
  • Simple to debug
  • Works for fast queries (<2 seconds)

2. Asynchronous Processing​

Pattern: Controller β†’ Service β†’ @Async Method β†’ Background Thread β†’ Database

Used For: Heavy reports, large exports, batch processing

Implementation:

// LensApplication.java:12
@EnableAsync

// Service
@Async
public `CompletableFuture<File>` generateLargeReport(ReportDTO request) {
// Heavy processing in background
File report = reportGenerator.generate(request);
return CompletableFuture.completedFuture(report);
}

// Controller
@GetMapping("/export")
public `ResponseEntity<String>` exportReport(@Valid ReportDTO request) {
`CompletableFuture<File>` future = service.generateLargeReport(request);
return ResponseEntity.accepted().body("Report generation started. ID: " + jobId);
}

Characteristics:

  • Non-blocking (controller returns immediately)
  • Used for long-running operations (>5 seconds)
  • Improves user experience (no timeout)

3. Caching Pattern​

Pattern: Request β†’ Check Cache β†’ Cache Hit? β†’ Return Cached Data : Fetch from DB β†’ Store in Cache β†’ Return

Used For: Frequently accessed, slowly-changing data (filter metadata, static queries)

Implementation:

// LensApplication.java:14
@EnableCaching

// Service
@Cacheable(value = "filterMetadata", key = "#customerId")
public FilterMetadataDTO getFilterMetadata(String customerId) {
// Expensive database query
return dao.queryFilterMetadata(customerId);
}

@CacheEvict(value = "filterMetadata", key = "#customerId")
public void updateFilterMetadata(String customerId, FilterMetadataDTO metadata) {
dao.updateMetadata(customerId, metadata);
}

Cache Configuration:

  • Backend: Redis
  • TTL: 15 minutes (dashboard queries), 1 hour (filter metadata)
  • Eviction: LRU (Least Recently Used)
  • Size: 1000 entries max

Characteristics:

  • Reduces database load
  • Faster response times (cache hit: <10ms vs DB query: 500ms)
  • Cache invalidation on updates

4. Event-Driven (Message Queue)​

Pattern: Service β†’ Publish Message β†’ RabbitMQ β†’ Consumer β†’ Process Event

Used For: Cost data updates, alert generation, async notifications

Implementation:

// Publisher (Service)
public void publishCostUpdateEvent(CostUpdateDTO update) {
rabbitTemplate.convertAndSend(QueueConstants.COST_UPDATE_EXCHANGE,
QueueConstants.COST_UPDATE_ROUTING_KEY,
update);
}

// Consumer (Listener)
@RabbitListener(queues = QueueConstants.COST_UPDATE_QUEUE)
public void handleCostUpdate(CostUpdateDTO update) {
// Process cost update
// Invalidate caches
// Trigger alerts if needed
}

Queues Used:

  • cost.update - Cost data updated
  • alert.cost - Cost alert triggered
  • report.generated - Report generation complete

Characteristics:

  • Decoupled (publisher doesn't wait for consumer)
  • Reliable (messages persisted in RabbitMQ)
  • Scalable (multiple consumers)

5. Retry Pattern​

Pattern: Service β†’ Call External API β†’ Failure? β†’ Retry (exponential backoff)

Used For: External API calls (AWS SDK, Snowflake connections)

Implementation:

// LensApplication.java:13
@EnableRetry

// Service
@Retryable(
value = {SnowflakeConnectionException.class},
maxAttempts = 3,
backoff = @Backoff(delay = 1000, multiplier = 2)
)
public `List<CostDTO>` queryCostData(RequestDTO request) {
return dao.queryCostData(request);
}

@Recover
public `List<CostDTO>` recover(SnowflakeConnectionException ex, RequestDTO request) {
log.error("Failed to query cost data after 3 retries", ex);
throw new GenericException("Unable to fetch cost data. Please try again later.");
}

Retry Configuration:

  • Max Attempts: 3
  • Initial Delay: 1 second
  • Backoff Multiplier: 2x (1s, 2s, 4s)
  • Recoverable Exceptions: SnowflakeConnectionException, AwsApiThrottlingException

Characteristics:

  • Resilient to transient failures
  • Exponential backoff prevents overwhelming failed service
  • Recovery method provides graceful degradation

Design Patterns​

1. Layered Architecture​

Description: Clear separation of concerns into horizontal layers

Implementation: Controller β†’ Service β†’ DAO β†’ Database

Benefits:

  • Easy to understand
  • Easy to test (mock each layer)
  • Easy to maintain
  • Enforces separation of concerns

2. Interface-Based Design (Dependency Inversion)​

Description: Services and DAOs defined as interfaces, implementations injected

Implementation:

// Interface
public interface AwsVsActualCostService {
`List<CostSummaryDTO>` getCostSummary(GenericRequestDTO request);
}

// Implementation
@Service
public class AwsVsActualCostServiceImpl implements AwsVsActualCostService {
@Override
public `List<CostSummaryDTO>` getCostSummary(GenericRequestDTO request) {
// Implementation
}
}

// Controller (dependency injection)
@AllArgsConstructor
public class AwsVsActualCostController {
private final AwsVsActualCostService service; // Interface, not implementation
}

Benefits:

  • Easy to mock for testing
  • Easy to swap implementations
  • Loose coupling

3. DTO Pattern (Data Transfer Object)​

Description: Dedicated objects for transferring data between layers

Implementation: Separate DTO classes for request, response, database entities

Benefits:

  • Decouples layers
  • Allows different representations (API vs DB)
  • Input validation

4. Template Method Pattern (Abstract Controllers)​

Description: Abstract base class with common controller logic

Implementation:

// AbstractCostBreakupController.java
public abstract class AbstractCostBreakupController {
protected ResponseDto<CostBreakupDTO> getCostBreakup(RequestDTO request) {
// Common validation
// Common error handling
// Call abstract method
CostBreakupDTO data = fetchCostData(request);
return new SuccessResponseDto<>(data);
}

protected abstract CostBreakupDTO fetchCostData(RequestDTO request);
}

// AnalyticsController extends AbstractCostBreakupController
@Override
protected CostBreakupDTO fetchCostData(RequestDTO request) {
return analyticsService.getAnalyticsCostBreakup(request);
}

Benefits:

  • Code reuse
  • Consistent behavior across cost breakup controllers
  • Easy to add new cost breakup categories

5. Repository Pattern (JPA & MongoDB)​

Description: Abstract data access logic behind repository interfaces

Implementation:

public interface SavedReportRepository extends MongoRepository<SavedReportDocument, String> {
`List<SavedReportDocument>` findByCustomerId(String customerId);
`Optional<SavedReportDocument>` findByReportId(String reportId);
}

Benefits:

  • Standardized data access
  • Spring Data JPA generates implementations
  • Easy to switch databases

6. Strategy Pattern (Cost Breakup Services)​

Description: Different algorithms for different cost breakup categories

Implementation: Each cost breakup service (Analytics, Database, Storage) implements same interface but with different logic

Benefits:

  • Extensible (easy to add new AWS services)
  • Clean separation

7. Builder Pattern (Query Construction)​

Description: Fluent API for building complex SQL queries

Implementation:

String sql = QueryBuilder.select()
.from("COST_DAILY")
.where("ACCOUNT_ID", accountId)
.where("DATE BETWEEN", startDate, endDate)
.groupBy("SERVICE")
.orderBy("COST DESC")
.build();

Benefits:

  • Readable query construction
  • Type-safe

Module Dependencies​

Internal Module Dependencies​

Lens depends on 4 internal Stormus modules:

1. snowplug​

Purpose: Snowflake multi-tenant datasource configuration

Usage: Provides Snowflake connection pooling and multi-tenant schema routing

Dependency:

api project(":snowplug")

Integration:

@Autowired
private SnowflakeJdbcTemplate snowflakeTemplate;

public `List<CostDTO>` queryCosts(String customerId) {
// snowplug automatically routes to customer's schema
return snowflakeTemplate.query(sql, rowMapper, customerId);
}

2. monitoring​

Purpose: Prometheus metrics, application monitoring

Usage: Exposes metrics for cost query latency, cache hit rates, API calls

Dependency:

api project(":monitoring")

Integration:

@Autowired
private MeterRegistry meterRegistry;

public `List<CostDTO>` queryCosts(RequestDTO request) {
Timer.Sample sample = Timer.start(meterRegistry);
`List<CostDTO>` result = dao.queryCosts(request);
sample.stop(meterRegistry.timer("lens.query.cost.duration"));
return result;
}

Metrics Exposed:

  • lens.query.cost.duration - Cost query latency
  • lens.cache.hit.rate - Cache hit percentage
  • lens.api.requests - API request count by endpoint

3. errorhandler​

Purpose: Centralized exception handling

Usage: Consistent error responses across all Lens endpoints

Dependency:

api project(":errorhandler")

Integration:

// errorhandler provides @ControllerAdvice for global exception handling

@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(GenericException.class)
public `ResponseEntity<ErrorResponseDto>` handleGenericException(GenericException ex) {
return ResponseEntity.status(500).body(new ErrorResponseDto(ex.getMessage()));
}
}

Error Response Format:

{
"status": "error",
"code": 500,
"message": "Unable to fetch cost data",
"timestamp": "2025-10-25T18:30:00Z"
}

4. loggerutil​

Purpose: Structured logging utilities

Usage: Consistent log formatting, correlation IDs, log levels

Dependency:

api project(":loggerutil")

Integration:

import com.ttn.ck.loggerutil.Logger;

private static final Logger log = Logger.getLogger(AwsVsActualCostService.class);

public `List<CostDTO>` getCostSummary(RequestDTO request) {
log.info("Fetching cost summary for customer: {}, date range: {} - {}",
request.getCustomerId(), request.getStartDate(), request.getEndDate());
// ...
}

Log Format:

2025-10-25 18:30:00.123 INFO [lens-api] [request-id-123] [customer-456] AwsVsActualCostService - Fetching cost summary for customer: 456, date range: 2024-01-01 - 2024-01-31

External Module Dependencies​

See 04-technical-architecture for detailed external dependency information.

Key External Dependencies:

  • Snowflake JDBC (3.13.27)
  • AWS Java SDK (1.12.324)
  • Spring Boot (2.7.4)
  • Spring Cloud (2021.0.8)
  • MongoDB
  • Redis
  • RabbitMQ

Cross-Cutting Concerns​

1. Security​

Implementation: All controllers secured with @Secured annotation

Location: com.ttn.ck.authX (external module)

Mechanism: JWT token validation

Example:

@Secured(key = "LENS_AWSVSACTUALCOSTCONTROLLER")
public class AwsVsActualCostController {
// All endpoints in this controller require valid JWT with appropriate permissions
}

Security Flow:

  1. Client sends JWT token in Authorization header
  2. authX module validates token
  3. Extracts user context (customer ID, roles)
  4. Checks if user has permission for controller
  5. Allows/denies request

2. Logging​

Implementation: Structured logging via loggerutil module

Log Levels:

  • ERROR: Exceptions, failures
  • WARN: Anomalies, deprecated usage
  • INFO: Business events (queries, reports)
  • DEBUG: Detailed debug information

Correlation ID: Every request has unique ID for tracing across services


3. Monitoring​

Implementation: Prometheus metrics via monitoring module

Metrics Categories:

  • Request Metrics: Count, latency, errors
  • Cache Metrics: Hit rate, miss rate, evictions
  • Database Metrics: Query duration, connection pool usage
  • Business Metrics: Cost queries per customer, report generations

Dashboards: Grafana dashboards for real-time monitoring


4. Caching​

Implementation: Redis via Spring Cache

Cache Strategies:

  • Filter Metadata: 1 hour TTL (rarely changes)
  • Dashboard Queries: 15 minutes TTL (changes daily)
  • RI Data: 1 hour TTL (changes hourly)

Cache Eviction: Automatic on updates + scheduled cleanup


5. Error Handling​

Implementation: Global exception handler via errorhandler module

Exception Types:

  • GenericException: Business logic errors
  • SnowflakeConnectionException: Database connectivity
  • AwsApiException: AWS API failures
  • ValidationException: Input validation errors

Error Response: Consistent JSON format with status, code, message


6. Validation​

Implementation: JSR-303 Bean Validation

Location: DTO classes

Example:

public class GenericRequestDTO {
@NotNull(message = "Customer ID is required")
private String customerId;

@NotNull(message = "Start date is required")
@PastOrPresent(message = "Start date cannot be in future")
private LocalDate startDate;

@NotNull(message = "End date is required")
private LocalDate endDate;

@AssertTrue(message = "End date must be after start date")
public boolean isDateRangeValid() {
return endDate.isAfter(startDate);
}
}

7. Configuration Management​

Implementation: Spring Cloud Config

Externalized Properties:

  • Database credentials
  • API endpoints
  • Feature flags
  • Cache TTLs

Configuration Profiles: dev, uat, prod


Summary​

The AWS Lens module follows a Layered Architecture with clear separation of concerns:

  • 40 Controllers (Presentation Layer): Handle HTTP, validate input, return responses
  • 107 Services (Application Layer): Execute business logic, orchestrate DAOs
  • 47 DAOs (Data Access Layer): Query databases, map results to DTOs
  • 165 DTOs (Data Transfer Layer): Define data contracts
  • Infrastructure Layer: Configuration, utilities, cross-cutting concerns

Communication Patterns: Synchronous request-response, asynchronous processing, caching, event-driven (RabbitMQ), retry

Design Patterns: Layered Architecture, Interface-Based Design, DTO Pattern, Template Method, Repository, Strategy, Builder

Module Dependencies: 4 internal modules (snowplug, monitoring, errorhandler, loggerutil)

Cross-Cutting Concerns: Security, logging, monitoring, caching, error handling, validation, configuration


Next Steps:


Document Version: 1.0 Last Updated: October 25, 2025