Skip to main content

Integration Points


Module: Lens Version: 1.0.0-RELEASE Last Updated: October 25, 2025


Overview​

Lens integrates with 8 external systems:

  1. Snowflake (primary analytics database)
  2. MongoDB (document storage)
  3. MySQL (transactional data)
  4. Redis (caching layer)
  5. RabbitMQ (message queue)
  6. AWS SDK (Cost Explorer, Pricing APIs)
  7. Spring Cloud Config Server (configuration)
  8. authX Module (JWT authentication)

1. Snowflake Integration​

Purpose: Query massive cost and usage data

Connection:

snowflake.url=jdbc:snowflake://account.snowflakecomputing.com
snowflake.warehouse=LENS_WH
snowflake.database=COST_DB
snowflake.schema=CUSTOMER_{customerId} # Multi-tenant

Usage Pattern:

// Query cost data
String sql = "SELECT SERVICE, SUM(COST) FROM COST_DAILY WHERE ACCOUNT_ID = ? GROUP BY SERVICE";
`List<CostDTO>` costs = snowflakeJdbcTemplate.query(sql, rowMapper, accountId);

Performance Optimizations:

  • Clustering: Tables clustered by DATE
  • Result Cache: 24-hour cache for identical queries
  • Auto-suspend: Warehouse auto-suspends after 60 seconds idle
  • Connection Pool: HikariCP with max 20 connections

2. MongoDB Integration​

Purpose: Store flexible documents (saved reports, filters)

Connection:

spring:
data:
mongodb:
uri: mongodb://${MONGODB_HOST}:27017/lens
database: lens

Usage Pattern:

// Save report
SavedReportDocument report = new SavedReportDocument();
report.setCustomerId(customerId);
report.setReportName("Monthly EC2 Costs");
savedReportRepository.save(report);

// Query reports
`List<SavedReportDocument>` reports =
savedReportRepository.findByCustomerId(customerId);

Collections:

  • saved_reports - User-saved report configurations
  • filter_metadata - Filter dropdown values (cached)
  • custom_queries - User-defined custom SQL queries

3. MySQL Integration​

Purpose: Transactional data (users, accounts, billing metadata)

Connection:

spring.datasource.url=jdbc:mysql://${MYSQL_HOST}:3306/lens
spring.datasource.hikari.maximum-pool-size=20

Usage Pattern:

// JPA repository
@Repository
public interface AccountRepository extends JpaRepository<Account, String> {
`List<Account>` findByCustomerId(String customerId);
}

// Usage
`List<Account>` accounts = accountRepository.findByCustomerId(customerId);

4. Redis Integration​

Purpose: High-speed caching for frequently accessed data

Connection:

spring:
redis:
host: ${REDIS_HOST}
port: 6379
lettuce:
pool:
max-active: 8

Usage Pattern:

@Cacheable(value = "dashboardQueries", key = "#customerId + ':' + #dateRange", ttl = 900)
public DashboardDTO getDashboardData(String customerId, String dateRange) {
return dao.queryDashboard(customerId, dateRange);
}

Cache Configurations:

  • dashboardQueries: 15-minute TTL
  • filterMetadata: 1-hour TTL
  • riUtilization: 1-hour TTL

5. RabbitMQ Integration​

Purpose: Asynchronous event processing

Connection:

spring:
rabbitmq:
host: ${RABBITMQ_HOST}
port: 5672
virtual-host: /lens

Exchanges & Queues:

// Exchange declaration
@Bean
public TopicExchange lensEventsExchange() {
return new TopicExchange("lens.events");
}

// Queue declaration
@Bean
public Queue costUpdateQueue() {
return new Queue("lens.cost.update");
}

// Binding
@Bean
public Binding costUpdateBinding() {
return BindingBuilder.bind(costUpdateQueue())
.to(lensEventsExchange())
.with("cost.update.*");
}

Message Publishing:

rabbitTemplate.convertAndSend("lens.events", "cost.update.CUST-123", costUpdateEvent);

Message Consumption:

@RabbitListener(queues = "lens.cost.update")
public void handleCostUpdate(CostUpdateEvent event) {
// Invalidate cache
cacheManager.getCache("dashboardQueries").clear();
}

6. AWS SDK Integration​

Purpose: Fetch recommendations, pricing data

Services Used:

  • AWS Cost Explorer API
  • AWS Pricing API
  • AWS Organizations API

Configuration:

@Bean
public AmazonCostExplorer costExplorerClient() {
return AmazonCostExplorerClientBuilder.standard()
.withRegion(Regions.US_EAST_1)
.withCredentials(new DefaultAWSCredentialsProviderChain())
.build();
}

Usage - Get RI Recommendations:

GetReservationPurchaseRecommendationRequest request =
new GetReservationPurchaseRecommendationRequest()
.withService("Amazon Elastic Compute Cloud - Compute")
.withLookbackPeriodInDays("THIRTY_DAYS");

GetReservationPurchaseRecommendationResult result =
costExplorerClient.getReservationPurchaseRecommendation(request);

Rate Limiting: 5 req/sec (AWS limit), exponential backoff on throttling


7. Spring Cloud Config Server​

Purpose: Externalized configuration

Bootstrap Configuration:

spring:
cloud:
config:
uri: http://cloudonomic-spring-config.uat.cloudonomic.net
name: lens
label: prod
fail-fast: true

Fetched Properties:

  • Database credentials
  • AWS credentials (if not using IAM roles)
  • Feature flags
  • Cache TTLs
  • External service URLs

Refresh:

# Trigger config refresh without restart
curl -X POST http://localhost:8080/actuator/refresh

8. authX Module (JWT Authentication)​

Purpose: Authenticate and authorize API requests

Integration:

@Secured(key = "LENS_AWSVSACTUALCOSTCONTROLLER")
public class AwsVsActualCostController {
// All endpoints require valid JWT with specific permission
}

JWT Validation Flow:

  1. Client sends JWT in Authorization: Bearer <token> header
  2. authX interceptor validates JWT signature
  3. authX extracts customer ID and permissions from JWT
  4. authX checks user has required permission key
  5. Request proceeds or 403 Forbidden returned

Integration Dependencies​

Gradle dependencies:

// Internal modules
api project(":snowplug") // Snowflake integration
api project(":monitoring") // Prometheus metrics
api project(":errorhandler") // Exception handling
api project(":loggerutil") // Structured logging

// External integrations
implementation 'net.snowflake:snowflake-jdbc:3.13.27'
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.springframework.boot:spring-boot-starter-amqp'
implementation 'com.amazonaws:aws-java-sdk:1.12.324'

Error Handling & Resilience​

Retry Strategy​

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

Circuit Breaker (Optional)​

@CircuitBreaker(name = "snowflake", fallbackMethod = "fallbackGetCosts")
public `List<CostDTO>` getCosts(RequestDTO request) {
return dao.queryCosts(request);
}

public `List<CostDTO>` fallbackGetCosts(RequestDTO request, Throwable ex) {
return cacheService.getCachedCosts(request); // Return stale data
}

Summary​

8 External Integrations: Snowflake, MongoDB, MySQL, Redis, RabbitMQ, AWS SDK, Config Server, authX

Connection Pooling: HikariCP for databases (max 20 connections)

Resilience: Retry logic (3 attempts, exponential backoff)

Caching: Redis with configurable TTLs (15min - 1hour)

Messaging: RabbitMQ topic exchange with event-driven architecture

Authentication: JWT via authX module


Document Version: 1.0 Last Updated: October 25, 2025