はじめに
可観測性には、ログ、メトリクス、トレースの 3 つの柱があります。 Spring Boot 4 には、ヘルスチェック用の Actuator、メトリクス用の Micrometer、分散トレーシング用の Micrometer Tracing が組み込まれており、運用環境でのアプリケーションの監視とデバッグに役立ちます。
1. スプリングブーツアクチュエーター
1.1 セットアップ
// build.gradle.kts
implementation("org.springframework.boot:spring-boot-starter-actuator")
1.2 エンドポイントの構成
# application.yml
management:
endpoints:
web:
exposure:
include: health, info, metrics, prometheus, env, loggers
base-path: /actuator
endpoint:
health:
show-details: when_authorized
show-components: always
info:
env:
enabled: true
1.3 重要なエンドポイント
| エンドポイント | 説明 |
|---|---|
| /アクチュエーター/健康 | ヘルスチェック — 上/下 |
| /アクチュエーター/情報 | アプリケーション情報 |
| /アクチュエーター/メトリクス | メトリクスのリスト |
| /actuator/metrics/{名前} | 特定のメトリクスの詳細 |
| /アクチュエーター/プロメテウス | メトリクス Prometheus 形式 |
| /アクチュエーター/ロガー | ログ レベル ランタイムの表示と変更 |
1.4 カスタムヘルスインジケーター
@Component
public class DatabaseHealthIndicator implements HealthIndicator {
private final DataSource dataSource;
public DatabaseHealthIndicator(DataSource dataSource) {
this.dataSource = dataSource;
}
@Override
public Health health() {
try (Connection conn = dataSource.getConnection()) {
if (conn.isValid(2)) {
return Health.up()
.withDetail("database", "PostgreSQL")
.withDetail("connection", "valid")
.build();
}
} catch (SQLException e) {
return Health.down()
.withDetail("error", e.getMessage())
.build();
}
return Health.down().build();
}
}
1.5 ログレベルのランタイムの変更
# Xem log level hiện tại
curl http://localhost:8080/actuator/loggers/com.example.myapp
# Thay đổi log level (không cần restart)
curl -X POST http://localhost:8080/actuator/loggers/com.example.myapp \
-H "Content-Type: application/json" \
-d '{"configuredLevel": "DEBUG"}'
2. マイクロメーターの測定基準
2.1 カスタムメトリクス
@Service
public class OrderService {
private final Counter orderCounter;
private final Timer orderProcessingTimer;
private final AtomicInteger activeOrders;
public OrderService(MeterRegistry registry) {
this.orderCounter = Counter.builder("orders.created")
.description("Total orders created")
.tag("type", "web")
.register(registry);
this.orderProcessingTimer = Timer.builder("orders.processing.time")
.description("Order processing duration")
.register(registry);
this.activeOrders = registry.gauge("orders.active",
new AtomicInteger(0));
}
public OrderResponse createOrder(CreateOrderRequest request) {
return orderProcessingTimer.record(() -> {
activeOrders.incrementAndGet();
try {
OrderResponse result = processOrder(request);
orderCounter.increment();
return result;
} finally {
activeOrders.decrementAndGet();
}
});
}
}
2.2 @Timed アノテーション
@RestController
@RequestMapping("/api/v1/products")
public class ProductController {
@Timed(value = "api.products.get",
description = "Time to get product",
percentiles = {0.5, 0.95, 0.99})
@GetMapping("/{id}")
public ResponseEntity<ProductResponse> getProduct(@PathVariable Long id) {
return ResponseEntity.ok(productService.getProduct(id));
}
}
2.3 プロメテウスの統合
// build.gradle.kts
implementation("io.micrometer:micrometer-registry-prometheus")
# application.yml
management:
prometheus:
metrics:
export:
enabled: true
アクセス http://localhost:8080/actuator/prometheus → プロメテウスのメトリクス:
# HELP orders_created_total Total orders created
# TYPE orders_created_total counter
orders_created_total{type="web"} 142.0
# HELP orders_processing_time_seconds Order processing duration
orders_processing_time_seconds_count 142
orders_processing_time_seconds_sum 28.456
3. 構造化されたロギング
3.1 JSON ログの構成
# application.yml
logging:
structured:
format:
console: ecs # Elastic Common Schema
level:
com.example: DEBUG
org.springframework.web: INFO
3.2 コンテキストログ
@Service
public class OrderService {
private static final Logger log = LoggerFactory.getLogger(OrderService.class);
public OrderResponse createOrder(CreateOrderRequest request) {
log.info("Creating order for user: {}, items: {}",
request.userId(), request.items().size());
try {
Order order = processOrder(request);
log.info("Order created successfully: orderId={}, total={}",
order.getId(), order.getTotalAmount());
return OrderResponse.from(order);
} catch (Exception e) {
log.error("Failed to create order for user: {}",
request.userId(), e);
throw e;
}
}
}
4. 分散トレーシング
4.1 マイクロメータートレースのセットアップ
// build.gradle.kts
implementation("io.micrometer:micrometer-tracing-bridge-otel")
implementation("io.opentelemetry:opentelemetry-exporter-otlp")
# application.yml
management:
tracing:
sampling:
probability: 1.0 # 100% sampling (dev), production: 0.1
otlp:
tracing:
endpoint: http://localhost:4318/v1/traces
4.2 カスタムスパン
@Service
public class PaymentService {
private final ObservationRegistry observationRegistry;
public PaymentService(ObservationRegistry observationRegistry) {
this.observationRegistry = observationRegistry;
}
public PaymentResult processPayment(PaymentRequest request) {
return Observation.createNotStarted("payment.process", observationRegistry)
.lowCardinalityKeyValue("payment.method", request.method())
.observe(() -> {
// Logic xử lý payment
return doProcessPayment(request);
});
}
}
4.3 可観測性アーキテクチャ
┌─────────────────────────────────────────────┐
│ Spring Boot Application │
│ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ Logs │ │ Metrics │ │ Traces │ │
│ │ Logback │ │Micrometer│ │ OTel/Brave │ │
│ └────┬─────┘ └────┬─────┘ └──────┬───────┘ │
└───────┼────────────┼───────────────┼─────────┘
│ │ │
▼ ▼ ▼
┌────────┐ ┌──────────┐ ┌───────────┐
│ Loki │ │Prometheus│ │ Tempo │
└───┬────┘ └────┬─────┘ └─────┬─────┘
│ │ │
└────────────┼───────────────┘
▼
┌──────────┐
│ Grafana │ ← Dashboard tổng hợp
└──────────┘
5. 実稼働環境におけるアクチュエータのセキュリティ
@Bean
public SecurityFilterChain actuatorSecurity(HttpSecurity http) throws Exception {
http
.securityMatcher("/actuator/**")
.authorizeHttpRequests(auth -> auth
.requestMatchers("/actuator/health").permitAll()
.requestMatchers("/actuator/info").permitAll()
.requestMatchers("/actuator/**").hasRole("ADMIN"))
.httpBasic(Customizer.withDefaults());
return http.build();
}
概要
- アクチュエーターはヘルスチェック、メトリクス、ロガーエンドポイントを提供します - 再起動せずにランタイムログレベルを変更できます
- マイクロメーター: カスタムメトリクスのカウンター、タイマー、ゲージ、Prometheus へのエクスポート
- 構造化ロギング (JSON/ECS 形式) + 分散トレーシング (OpenTelemetry) により、完全な可観測性スタックが作成されます
- 本番環境の Secure Actuator エンドポイント: ヘルス/情報のみを公開し、残りは ADMIN ロールを必要とします。
演習
- Actuator の構成: ヘルス、メトリクス、Prometheus エンドポイントを公開します。外部 API 依存関係のカスタム状態インジケーターを作成する
- カスタムメトリクスの実装: 注文のカウント、タイマーによるリクエストの処理時間の測定、ゲージによるアクティブユーザーの表示
- 構造化ログと分散トレースをセットアップします: Prometheus + Grafana に接続します (docker-compose)