# MCA SDK for Java

OpenTelemetry instrumentation library for healthcare ML model monitoring at Baptist Health South Florida (BHSF).

## Overview

The MCA SDK provides comprehensive observability for Java-based ML models through metrics, logs, and distributed traces. It follows idiomatic Java patterns including the Builder pattern and AutoCloseable interface.

## Requirements

- **Java**: 11 or higher
- **Build Tool**: Maven 3.6+ or Gradle 7+
- **OpenTelemetry Collector**: Running on localhost:4318 (or custom endpoint)

## Installation

### Maven

```xml
<dependency>
    <groupId>com.bhsf.mca</groupId>
    <artifactId>mca-sdk-java</artifactId>
    <version>0.3.0</version>
</dependency>
```

### Gradle

```gradle
implementation 'com.bhsf.mca:mca-sdk-java:0.3.0'
```

### Version Range (Semantic Versioning)

Maven supports version ranges for automatic updates within compatible versions:

```xml
<dependency>
    <groupId>com.bhsf.mca</groupId>
    <artifactId>mca-sdk-java</artifactId>
    <version>[0.3,1.0)</version>
</dependency>
```

This will automatically use the latest 0.x version (e.g., 0.3.1, 0.4.0) but not 1.0+ (breaking changes).

## Quick Start

```java
import com.bhsf.mca.sdk.MCAClient;
import com.bhsf.mca.sdk.RecordPredictionRequest;

public class Example {
    public static void main(String[] args) {
        // Initialize client with try-with-resources for automatic cleanup
        try (MCAClient client = new MCAClient.Builder()
                .serviceName("readmission-model")
                .modelId("mdl-001")
                .teamName("clinical-ai")
                .build()) {

            // Record a prediction
            client.recordPrediction(RecordPredictionRequest.builder()
                    .latency(0.15)
                    .attribute("model_version", "2.0")
                    .attribute("patient_age", 65)
                    .attribute("confidence", 0.92)
                    .build());

        } // Client automatically shuts down and flushes telemetry
    }
}
```

## Configuration

### Builder Pattern

The MCAClient uses a fluent Builder pattern for configuration:

```java
MCAClient client = new MCAClient.Builder()
        .serviceName("my-model")           // Required
        .modelId("mdl-123")                // Optional
        .teamName("data-science")          // Optional
        .modelVersion("1.0.0")             // Optional (default: "1.0.0")
        .otelEndpoint("http://localhost:4318")  // Optional (default: localhost:4318)
        .build();
```

### Environment Variables

Configuration can also be provided via environment variables:

- `MCA_SERVICE_NAME` - Service/model name (required if not set via builder)
- `MCA_MODEL_ID` - Model identifier
- `MCA_TEAM_NAME` - Team name
- `MCA_MODEL_VERSION` - Model version
- `MCA_OTEL_ENDPOINT` - OpenTelemetry collector endpoint

## Usage

### Recording Predictions

```java
// Basic prediction recording
client.recordPrediction(RecordPredictionRequest.builder()
        .latency(0.25)
        .build());

// With custom prediction ID
client.recordPrediction(RecordPredictionRequest.builder()
        .latency(0.18)
        .predictionId("pred-custom-123")
        .build());

// With custom attributes
client.recordPrediction(RecordPredictionRequest.builder()
        .latency(0.20)
        .attribute("model_version", "2.1")
        .attribute("feature_count", 50)
        .attribute("confidence_score", 0.95)
        .build());

// With multiple attributes from a Map
Map<String, Object> attributes = new HashMap<>();
attributes.put("environment", "production");
attributes.put("deployment_id", "dep-456");

client.recordPrediction(RecordPredictionRequest.builder()
        .latency(0.15)
        .attributes(attributes)
        .build());
```

### Thread Safety

The MCAClient is thread-safe and can be used concurrently from multiple threads:

```java
ExecutorService executor = Executors.newFixedThreadPool(10);

for (int i = 0; i < 100; i++) {
    executor.submit(() -> {
        client.recordPrediction(RecordPredictionRequest.builder()
                .latency(Math.random() * 0.5)
                .build());
    });
}

executor.shutdown();
```

### Lifecycle Management

#### Try-with-resources (Recommended)

```java
try (MCAClient client = new MCAClient.Builder()
        .serviceName("my-model")
        .build()) {

    // Use client
    client.recordPrediction(/* ... */);

} // Automatically calls close() with 30s timeout
```

#### Manual Shutdown

```java
MCAClient client = new MCAClient.Builder()
        .serviceName("my-model")
        .build();

try {
    // Use client
    client.recordPrediction(/* ... */);
} finally {
    // Shutdown with custom timeout
    client.shutdown(Duration.ofSeconds(10));
}
```

## Telemetry

The SDK emits the following telemetry:

### Metrics

- **`model.predictions.total`** (Counter): Total number of predictions
- **`model.latency.seconds`** (Histogram): Prediction latency distribution

### Logs

Structured logs with prediction details including:
- Prediction ID
- Latency
- Custom attributes
- Model metadata

### Traces

Distributed traces for request context propagation (future enhancement).

## Testing

### Running Tests

```bash
# Maven
mvn clean test

# Gradle
gradle clean test
```

### Test Coverage

```bash
# Maven with JaCoCo
mvn clean test jacoco:report

# View coverage report
open target/site/jacoco/index.html
```

Minimum coverage requirement: **85%**

## Architecture

### API Parity with Python SDK

The Java SDK provides equivalent functionality to the Python MCAClient:

| Python | Java |
|--------|------|
| `MCAClient(service_name="model")` | `new MCAClient.Builder().serviceName("model").build()` |
| `client.record_prediction(latency=0.15)` | `client.recordPrediction(RecordPredictionRequest.builder().latency(0.15).build())` |
| `client.shutdown(timeout_millis=5000)` | `client.shutdown(Duration.ofSeconds(5))` |

### OpenTelemetry Integration

The SDK uses:
- **OpenTelemetry SDK**: 1.33.0
- **OTLP/HTTP Exporter**: For metrics, logs, and traces
- **Batch Processing**: 30-second intervals for metrics, 5-second for logs/traces
- **Resource Attributes**: service.name, model.id, model.version, team.name

## Examples

See the `examples/` directory for complete working examples:

- **Internal ML Model**: Traditional ML model instrumentation
- **GenAI/LLM**: LLM-based model with token tracking
- **Vendor Bridge**: External API model monitoring

## Development

### Building from Source

```bash
# Maven
mvn clean install

# Gradle
gradle clean build
```

### Running Integration Tests

1. Start OpenTelemetry Collector:
   ```bash
   docker run -p 4318:4318 otel/opentelemetry-collector:latest
   ```

2. Run integration tests:
   ```bash
   mvn verify
   ```

## Publishing to Maven Central

This SDK is published to Maven Central. For maintainers publishing new versions:

1. See [PUBLISHING.md](PUBLISHING.md) for detailed instructions
2. Ensure you have OSSRH credentials (encrypted) and GPG key configured securely
3. Run `mvn clean deploy -P release` to build, sign, and publish
4. Artifacts are automatically released to Maven Central (autoReleaseAfterClose=true)

**Development builds** (without signing):
```bash
mvn clean install  # Local development - no GPG signing
```

**Release builds** (with signing and publishing):
```bash
mvn clean deploy -P release  # Maven Central publishing
```

## License

Apache License 2.0 - See [LICENSE](LICENSE) file for details.

Copyright 2026 Baptist Health South Florida

## Support

For issues or questions, contact the Clinical AI team at BHSF.
