Skip to main content

🧩 Architecture & Design

High‑level system design, components, and data flow.

System Overview​

Apexium-log is a full-stack application with a Kotlin/Spring Boot backend, React/TypeScript frontend, and Docker Compose orchestrating infrastructure services. The backend periodically polls Salesforce via REST and Tooling APIs, stores data in PostgreSQL and MinIO, and caches frequently accessed data in Redis.

+----------------+ Tooling / REST API +-------------------+
| Salesforce | <----------------------------> | Kotlin Backend |
| (ApexLogs, | (Poll logs & metadata) | (Spring Boot) |
| ApexClass, | | |
| ApexTrigger, | +---------+---------+
| TraceFlag) | |
+----------------+ +---------------+---------------+
| | |
v v v
+-----------+ +-----------+ +---------------+
| PostgreSQL | | MinIO | | Redis |
| (Metadata, | | (Log Body | | (Cache, |
| History, | | Storage) | | Sessions) |
| Jobs) | | | | |
+-----------+ +-----------+ +---------------+
|
v
+---------------+
| React Frontend|
| (TypeScript) |
+---------------+

Components​

Backend (Kotlin / Spring Boot)​

Located in src/main/kotlin/com/observability/sfdc/. Organized into layered packages:

PackageResponsibility
controllerREST endpoints — AdminController, SalesforceLogController, SalesforceMetadataController, SalesforceUserController
serviceBusiness logic — ApexLogService, TraceFlagService, TraceJobService, MetadataHistoryService, ReportMetadataService, UserService
service.implConcrete implementations — OrgContextService, TraceJobService
repositoryJPA/SQL repositories for PostgreSQL access
domainEntity classes — Log, ApexClass, ApexTrigger, TraceJob, DebugLevel, Report, User
dtoData transfer objects for API requests/responses
configSpring configuration — security, scheduling, MinIO, Redis, CORS
exceptionCustom exception types
utilUtility helpers

Key services:

ServicePurpose
ApexLogServiceQuery, download, delete debug logs from Salesforce and local storage
TraceFlagServiceCRUD TraceFlags via Salesforce Tooling API
TraceJobServiceManaged trace jobs with sliding window — auto-renews flags before 24h expiry
ApexClassMetadataServiceTrack and search Apex classes
ApexTriggerMetadataServiceTrack and search Apex triggers
MetadataHistoryServiceChange timeline and body diff comparison
MetadataDetailServiceDeep details including coverage and test classes
ReportMetadataServiceReport metadata, describe, and SOQL conversion
DebugLevelMetadataServiceDebug level configurations
UserServiceSalesforce user retrieval and search
OrgContextServiceMulti-org context and Redis cache management
AuthServiceSalesforce OAuth 2.0 authentication

Frontend (React / TypeScript)​

Located in frontend/. Built with Vite. Communicates with the backend via REST API.

Infrastructure Services​

Defined in docker-compose.yml:

ServiceImagePortPurpose
appCustom build8080Kotlin/Spring Boot backend
dbpostgres:175432Structured data — logs, classes, triggers, trace jobs, metadata history
redisredis:alpine6379Caching — Salesforce tokens, metadata queries, user sessions
minioquay.io/minio/minio9000/9001Object storage — log body files, Apex class/trigger body snapshots

Data Flow​

Log Polling (every 1 minute)​

Scheduler → ApexLogService → Salesforce Tooling API → Fetch new ApexLog records
↓
Store metadata in PostgreSQL
Store log body in MinIO

Metadata Polling (every 6 hours)​

Scheduler → Metadata services → Salesforce Tooling API → Fetch ApexClass, ApexTrigger, DebugLevel
↓
Store in PostgreSQL
Snapshot bodies in MinIO
Record change history (who, when)

Trace Job Lifecycle​

User creates TraceJob → Creates TraceFlag in Salesforce
↓
Scheduler monitors expiry
↓
Before 24h limit → Deletes old flag → Creates new flag (sliding window)
↓
User cancels → Deletes flag → Marks job completed

User Request Flow​

React Frontend → REST API → Controller → Service → Salesforce API / PostgreSQL / MinIO
↓
Response to UI

Storage Design​

PostgreSQL​

TableStores
logsDebug log metadata — ID, author, class, request time, org ID
apex_classesApex class records — name, body, coverage, org ID
apex_triggersApex trigger records — name, body, org ID
trace_jobsManaged trace jobs — target user, status, schedule config
debug_levelsDebug level configurations
metadata_historyChange timeline — entity type, entity ID, changed by, changed at, body snapshot reference
reportsReport metadata
usersSalesforce user records

MinIO (S3-compatible)​

BucketStores
sfdc-bucketFull debug log body files (.gz), Apex class/trigger body snapshots for diff comparison

Redis​

Key patternStoresTTL
sf_tokens:*Salesforce OAuth access tokens1 hour
sf_metadata:*Cached metadata queries1 hour
sf_users:*Cached user lookups1 hour

Polling Configuration​

Defined in application.properties:

SettingValuePurpose
log.poll.rate1 minuteHow often to poll for new debug logs
metadata.poll.rate6 hoursHow often to poll for metadata changes
metadata.poll.batch-size200Records per metadata poll batch
log.retention.days15Days to retain logs before cleanup
log.retention.cron0 0 6 * * ?Daily cleanup schedule (6 AM)

Security​

  • OAuth 2.0 — Salesforce Connected App with Client Credentials flow
  • API Key — Optional X-API-Key header for backend access
  • CORS — Configurable allowed origins via APEXIUM_CORS_ALLOWED_ORIGINS
  • Secrets — Environment variables via .env file, never committed to repo

Tech Stack​

LayerTechnology
BackendKotlin 2.1.0, Spring Boot 4.0.6
FrontendReact 19, TypeScript, Vite
DatabasePostgreSQL 17
CacheRedis (Alpine)
Object StorageMinIO (S3-compatible)
BuildMaven (backend), npm (frontend)
OrchestrationDocker Compose
API ProtocolSalesforce REST API & Tooling API