Metrics 서비스
Metrics 서비스 (alpha)
Metrics 서비스는 Backstage 백엔드 플러그인에서 애플리케이션 수준 지표를 내보내기 위한 통합 인터페이스를 제공해요. 이 서비스는 OpenTelemetry Meter API를 감싸고, OpenTelemetry Instrumentation Scope를 사용해 각 플러그인의 지표를 자동으로 범위를 지정해서 텔레메트리 백엔드가 어떤 플러그인이 어떤 지표를 생성했는지 식별할 수 있게 해줘요.
출처: 문서
본문
Metrics 서비스는 Backstage 백엔드 플러그인에서 애플리케이션 수준 지표를 내보내기 위한 통합 인터페이스를 제공해요. 이 서비스는 OpenTelemetry Meter API를 감싸고, OpenTelemetry Instrumentation Scope를 사용해 각 플러그인의 지표를 자동으로 범위를 지정해서 텔레메트리 백엔드가 어떤 플러그인이 어떤 지표를 생성했는지 식별할 수 있게 해줘요.
참고
이 서비스는 현재 alpha 단계이며 @backstage/backend-plugin-api/alpha에서 가져와요. API는 향후 릴리스에서 변경될 수 있어요.
OpenTelemetry 설정하기
Metrics 서비스는 OpenTelemetry SDK를 직접 구성하지 않아요. exporter, 리소스 속성, 뷰 등을 포함해 OpenTelemetry Node SDK를 Backstage 백엔드를 시작하기 전에 직접 초기화해야 해요. 자세한 내용은 튜토리얼을 참고하세요.
OpenTelemetry 자동 계측과의 관계
Metrics 서비스는 자동 계측(auto-instrumentation)을 대체하기보다 보완해요. 자동 계측은 HTTP 요청 수, 지속 시간 같은 인프라 수준 신호를 자동으로 캡처해요. Metrics 서비스는 플러그인이 제공할 수 있는 애플리케이션 수준 지표, 즉 처리된 엔티티 수, 완료된 작업 수, 활성 세션 수 같은 것을 위한 것이에요.
// Auto-instrumentation provides automatically:
// http.server.request.duration{method="GET", route="/catalog/entities"}
// MetricsService provides manually:
const processed = metrics.createCounter('entities.processed.total', {
description: 'Total entities processed during refresh',
});
processed.add(entities.length, { operation: 'refresh' });
서비스 사용하기
Metrics 서비스는 alpha API이므로 서비스 참조는 coreServices 대신 @backstage/backend-plugin-api/alpha에서 가져와요.
import { createBackendPlugin } from '@backstage/backend-plugin-api';
import { metricsServiceRef } from '@backstage/backend-plugin-api/alpha';
createBackendPlugin({
pluginId: 'todos',
register(env) {
env.registerInit({
deps: {
metrics: metricsServiceRef,
},
async init({ metrics }) {
const todoCount = metrics.createCounter('todos.total', {
description: 'Total number of todos',
});
// Later, when adding a todo:
todoCount.add(1, { 'todo.category': 'personal' });
},
});
},
});
계측 유형
이 서비스는 OpenTelemetry 사양에 따라 동기(synchronous)와 관측형(observable, 비동기) 계측 유형을 모두 제공해요.
동기 계측(Synchronous Instruments)
동기 계측은 측정이 발생하는 위치에서 인라인으로 사용돼요.
| Method | Description | Example Use Case | |
|---|---|---|---|
createCounter |
Monotonically increasing sum (non-negative increments) | Total requests, entities processed | |
createUpDownCounter |
Sum that can increase or decrease | Active connections, queue depth | |
createHistogram |
Distribution of values (e.g. durations, sizes) | Request latency, payload sizes | |
createGauge |
Point-in-time value | CPU usage, memory utilization |
const counter = metrics.createCounter('todos.completed.total', {
description: 'Total todos completed',
});
counter.add(1, { 'todo.status': 'completed' });
const histogram = metrics.createHistogram('todo.duration', {
description: 'Time spent processing a todo',
unit: 'seconds',
advice: { explicitBucketBoundaries: [0.01, 0.05, 0.1, 0.5, 1, 5] },
});
histogram.record(durationInSeconds, {
'todo.category': 'personal',
'todo.status': 'completed',
});
const upDown = metrics.createUpDownCounter('todos.in_flight', {
description: 'Number of todos currently in flight',
});
upDown.add(1);
// ... later
upDown.add(-1);
관측형 계측(Observable Instruments)
관측형 계측은 지표 수집이 발생할 때 호출되는 콜백을 사용해요. 이는 계산 비용이 크거나 데이터베이스 같은 외부 소스에서 오는 지표에 유용해요.
| Method | Description | Example Use Case | |
|---|---|---|---|
createObservableCounter |
Monotonically increasing sum, reported via callback | Total items ingested from external API | |
createObservableUpDownCounter |
Sum that can go up or down, reported via callback | Connection pool size | |
createObservableGauge |
Point-in-time value, reported via callback | Row counts, cache hit ratios |
const entityCount = metrics.createObservableGauge('catalog.entities.count', {
description: 'Total amount of entities in the catalog',
});
entityCount.addCallback(async gauge => {
const results = await getEntityCountsByKind();
for (const { kind, count } of results) {
gauge.observe(count, { kind });
}
});
지표 옵션(Metric Options)
모든 create* 메서드는 선택적 MetricOptions 객체를 받아들여요.
| Property | Type | Description | |
|---|---|---|---|
description |
string |
Human-readable description of the metric | |
unit |
string |
Unit of measurement (e.g. 'seconds', '{entity}', 'bytes') |
|
advice |
object |
Aggregation hints, such as explicitBucketBoundaries for histograms |
타입 안전 속성(Type-Safe Attributes)
지표 계측은 add, record, observe에 전달되는 속성을 제한하는 일반 타입 매개변수를 받아들여요.
interface TodoAttributes {
'todo.category': string;
'todo.status': 'completed' | 'in_progress' | 'blocked';
}
const completed = metrics.createCounter<TodoAttributes>(
'todos.completed.total',
{ description: 'Total todos completed' },
);
// Type-safe attributes are enforced
completed.add(1, { 'todo.category': 'personal', 'todo.status': 'completed' });
고급 구성
이 서비스는 app-config.yaml의 backend.metrics.plugin.<pluginId>.meter에서 선택적 구성을 읽어요. 이를 통해 운영자는 코드 변경 없이 특정 플러그인의 OpenTelemetry Instrumentation Scope를 덮어쓸 수 있어요.
팁
각 플러그인은 backstage-plugin-<pluginId>라는 이름의 meter를 자동으로 받아요. 보통은 이걸 구성할 필요가 없어요.
backend:
metrics:
plugin:
catalog:
meter:
name: 'custom-catalog-meter'
version: '2.0.0'
schemaUrl: 'https://example.com/schema'
| Property | Type | Default | Description | |
|---|---|---|---|---|
name |
string |
backstage-plugin-<pluginId> |
Name of the OpenTelemetry meter | |
version |
string |
— | Version string for the meter | |
schemaUrl |
string |
— | Schema URL for the meter |