Svelte 可観測性の実装:Sentry/OpenTelemetry/Web Vitals 連携ガイド
Web アプリケーションを本番環境で運用する際、ユーザー体験を最適化し、問題を迅速に発見・解決するために可観測性(Observability)の実装が欠かせません。Svelte アプリケーションでも同様に、エラー追跡、パフォーマンス監視、分散トレーシングを統合的に実装することで、アプリケーションの健全性を維持できます。
本記事では、Sentry によるエラートラッキング ON、OpenTelemetry による分散トレーシング、そして Web Vitals によるパフォーマンス計測を、Svelte アプリケーションに統合する実践的な方法をご紹介します。これらのツールを組み合わせることで、フロントエンドからバックエンドまで一貫した監視体制を構築できるでしょう。
背景
可観測性とは
可観測性とは、システムの内部状態を外部から観察・理解できる能力を指します。従来の監視(Monitoring)が「問題が発生したことを知る」ことに焦点を当てるのに対し、可観測性は「なぜ問題が発生したのか」を理解することを目的としています。
可観測性は、以下の 3 つの柱(Three Pillars of Observability)で構成されますね。
| # | 柱 | 説明 | 具体例 |
|---|---|---|---|
| 1 | メトリクス | 数値データの時系列変化 | CPU 使用率、リクエスト数、エラー率 |
| 2 | ログ | イベントの詳細記録 | エラーメッセージ、デバッグ情報 |
| 3 | トレース | リクエストの処理経路 | 分散システムでの処理フロー |
以下の図は、可観測性の 3 つの柱がどのように連携してシステム全体を監視するかを示しています。
mermaidflowchart TB
app["Svelte<br/>アプリケーション"]
metrics["メトリクス<br/>Web Vitals"]
logs["ログ<br/>エラー情報"]
traces["トレース<br/>処理経路"]
app --> metrics
app --> logs
app --> traces
metrics --> observe["可観測性<br/>プラットフォーム"]
logs --> observe
traces --> observe
observe --> insight["インサイト<br/>問題の発見と解決"]
図で理解できる要点:
- アプリケーションから 3 種類のデータを収集
- すべてのデータが統合されて分析可能
- 問題の原因特定が迅速化
Svelte における可観測性の重要性
Svelte は、コンパイル時に最適化された JavaScript を生成するフレームワークです。そのため、ランタイムオーバーヘッドが少なく、高速なアプリケーションを構築できます。しかし、本番環境では予期せぬエラーやパフォーマンス問題が発生する可能性があります。
特に Svelte アプリケーションでは、以下の点で可観測性が重要になりますね。
リアクティブな状態管理により、複雑な状態遷移が発生しやすく、デバッグが困難になることがあります。コンパイル後のコードは最適化されているため、エラーの発生箇所を特定しにくいことがあるでしょう。
SSR(Server-Side Rendering)や SPA(Single Page Application)の両方に対応できるため、監視対象が多岐にわたります。
課題
Svelte アプリケーションの監視における課題
Svelte アプリケーションを本番環境で運用する際、いくつかの課題に直面します。
エラーの可視性不足
開発環境では気づかないエラーが、本番環境で発生することがあります。特に以下のような問題が顕在化しにくいですね。
ユーザー環境固有のエラー(特定のブラウザやデバイスでのみ発生)、非同期処理でのエラー(Promise 拒否、タイムアウト)、サードパーティライブラリとの統合エラーなどが挙げられます。
パフォーマンス問題の特定困難
ユーザー体験に直結するパフォーマンス問題を、開発環境で再現することは困難です。以下のような指標を本番環境で計測する必要があります。
| # | 指標 | 説明 | 重要性 |
|---|---|---|---|
| 1 | LCP | Largest Contentful Paint - 最大コンテンツの描画時間 | ★★★ |
| 2 | FID | First Input Delay - 最初の入力遅延 | ★★★ |
| 3 | CLS | Cumulative Layout Shift - 累積レイアウトシフト | ★★★ |
| 4 | TTFB | Time to First Byte - 最初のバイトまでの時間 | ★★ |
| 5 | FCP | First Contentful Paint - 最初のコンテンツ描画時間 | ★★ |
分散システムでのトレーシング不足
モダンな Web アプリケーションは、フロントエンド、API、データベース、サードパーティサービスなど、複数のコンポーネントで構成されています。問題が発生した際、どのコンポーネントがボトルネックになっているのかを特定するのは容易ではありません。
以下の図は、分散システムにおけるトレーシングの課題を示しています。
mermaidflowchart LR
user["ユーザー"] -->|リクエスト| svelte["Svelte<br/>フロントエンド"]
svelte -->|API呼び出し| api["REST API"]
api -->|クエリ| db[("データベース")]
api -->|認証| auth["認証<br/>サービス"]
api -->|外部API| external["サードパーティ"]
svelte -.->|どこが遅い?| question["?"]
api -.->|どこが遅い?| question
db -.->|どこが遅い?| question
図で理解できる要点:
- リクエストが複数のサービスを経由
- ボトルネックの特定が困難
- エンドツーエンドの可視性が必要
解決策
統合可観測性アーキテクチャ
これらの課題を解決するために、Sentry、OpenTelemetry、Web Vitals を組み合わせた統合可観測性アーキテクチャを構築します。それぞれのツールが異なる役割を担当し、補完し合うことで、包括的な監視体制を実現できますね。
以下の表は、各ツールの役割と特徴をまとめたものです。
| # | ツール | 主な役割 | 対象データ | 強み |
|---|---|---|---|---|
| 1 | Sentry | エラー追跡 | ログ、エラー | リアルタイム通知、スタックトレース |
| 2 | OpenTelemetry | 分散トレーシング | トレース、スパン | 標準化された計装、ベンダー中立 |
| 3 | Web Vitals | パフォーマンス計測 | メトリクス | Google の推奨指標、UX 重視 |
アーキテクチャ全体像
以下の図は、3 つのツールがどのように連携するかを示しています。
mermaidflowchart TB
browser["ブラウザ<br/>Svelteアプリ"]
subgraph monitoring["監視レイヤー"]
sentry["Sentry SDK"]
otel["OpenTelemetry<br/>SDK"]
vitals["web-vitals<br/>ライブラリ"]
end
browser --> sentry
browser --> otel
browser --> vitals
sentry -->|エラー| sentrycloud["Sentry<br/>クラウド"]
otel -->|トレース| collector["OpenTelemetry<br/>Collector"]
vitals -->|メトリクス| analytics["分析<br/>プラットフォーム"]
collector --> backend["バックエンド<br/>トレーシング"]
sentrycloud --> dashboard["統合<br/>ダッシュボード"]
collector --> dashboard
analytics --> dashboard
図で理解できる要点:
- フロントエンドで 3 種類の SDK を統合
- それぞれが専用のバックエンドに送信
- 統合ダッシュボードで一元管理
ツール選定の理由
Sentry を選ぶ理由
Sentry は、エラートラッキングのデファクトスタンダードです。以下の特徴により、Svelte アプリケーションとの相性が良いですね。
公式の Svelte SDK が提供されており、簡単に統合できます。ソースマップに対応しており、ミニファイされたコードのエラーも正確に特定できるでしょう。リリース追跡機能により、どのバージョンでエラーが発生したかを把握できます。
OpenTelemetry を選ぶ理由
OpenTelemetry は、CNCF(Cloud Native Computing Foundation)のプロジェクトであり、可観測性の標準となっています。ベンダーロックインを避けられ、複数のバックエンド(Jaeger、Zipkin、Datadog など)に対応できます。
フロントエンドとバックエンドで同じ標準を使用でき、エンドツーエンドのトレーシングが可能です。自動計装と手動計装の両方をサポートし、柔軟な実装ができますね。
Web Vitals を選ぶ理由
Web Vitals は、Google が推奨するユーザー体験指標です。SEO にも影響するため、測定と改善が重要になります。
軽量なライブラリで、パフォーマンスへの影響が最小限です。リアルユーザーモニタリング(RUM)により、実際のユーザー体験を把握できるでしょう。
具体例
環境構築とセットアップ
まず、必要なパッケージをインストールします。Yarn を使用してプロジェクトに依存関係を追加しましょう。
パッケージのインストール
以下のコマンドで、可観測性に必要なすべてのパッケージをインストールします。
bash# Sentry SDK
yarn add @sentry/svelte @sentry/vite-plugin
# OpenTelemetry SDK
yarn add @opentelemetry/api \
@opentelemetry/sdk-trace-web \
@opentelemetry/instrumentation-fetch \
@opentelemetry/instrumentation-document-load \
@opentelemetry/exporter-trace-otlp-http
# Web Vitals
yarn add web-vitals
それぞれのパッケージの役割を理解しておきましょう。@sentry/svelteは Svelte 専用の Sentry SDK、@opentelemetry/apiは OpenTelemetry のコア API です。
Sentry の統合
Sentry の初期化
Svelte アプリケーションのエントリーポイントで、Sentry を初期化します。src/main.tsまたはsrc/main.jsで以下のように設定しましょう。
typescript// src/main.ts
import { init } from '@sentry/svelte';
import App from './App.svelte';
// Sentry初期化 - エラー追跡の開始
init({
dsn: 'YOUR_SENTRY_DSN', // SentryプロジェクトのDSN
environment: import.meta.env.MODE, // 環境識別(development/production)
release: `my-svelte-app@${
import.meta.env.VITE_APP_VERSION
}`, // リリースバージョン
});
この設定により、アプリケーション全体でエラーが自動的にキャプチャされます。
Sentry の詳細設定
本番環境では、より詳細な設定を行うことで、有用な情報を収集できますね。
typescript// src/lib/sentry.ts
import {
init,
BrowserTracing,
Replay,
} from '@sentry/svelte';
// エラー追跡とパフォーマンス監視の統合設定
init({
dsn: 'YOUR_SENTRY_DSN',
environment: import.meta.env.MODE,
release: `my-svelte-app@${
import.meta.env.VITE_APP_VERSION
}`,
// トレーシング設定
integrations: [
new BrowserTracing({
// ルーティングトランザクションの自動作成
tracingOrigins: [
'localhost',
'your-production-domain.com',
],
// XMLHttpRequestとFetch APIの自動計装
traceFetch: true,
traceXHR: true,
}),
],
// サンプリング設定
tracesSampleRate: 1.0, // 本番環境では0.1〜0.3程度に調整
});
tracesSampleRateは、パフォーマンストランザクションの送信率を制御します。本番環境ではコストを抑えるため、10〜30%程度に設定するのが一般的でしょう。
Vite プラグインの設定
ソースマップを Sentry にアップロードすることで、ミニファイされたコードのエラーも正確に特定できます。
typescript// vite.config.ts
import { defineConfig } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';
import { sentryVitePlugin } from '@sentry/vite-plugin';
export default defineConfig({
plugins: [
svelte(),
// ビルド時のソースマップアップロード
sentryVitePlugin({
org: 'your-org-slug',
project: 'your-project-slug',
authToken: process.env.SENTRY_AUTH_TOKEN,
}),
],
build: {
sourcemap: true, // ソースマップ生成を有効化
},
});
環境変数SENTRY_AUTH_TOKENは、Sentry の設定画面から取得できます。
エラー境界の実装
Svelte コンポーネントでエラーが発生した際に、適切にキャプチャするためのエラー境界を実装しましょう。
svelte<!-- src/lib/components/ErrorBoundary.svelte -->
<script lang="ts">
import { captureException } from '@sentry/svelte';
import { onMount, onDestroy } from 'svelte';
// エラーハンドリング用の状態
let error: Error | null = null;
let errorInfo: any = null;
// グローバルエラーハンドラーの登録
function handleError(event: ErrorEvent) {
error = event.error;
errorInfo = { message: event.message };
captureException(event.error); // Sentryにエラー送信
}
onMount(() => {
window.addEventListener('error', handleError);
});
onDestroy(() => {
window.removeEventListener('error', handleError);
});
</script>
{#if error}
<!-- エラー表示UI -->
<div class="error-boundary">
<h2>エラーが発生しました</h2>
<p>問題が報告されました。しばらくしてから再度お試しください。</p>
</div>
{:else}
<!-- 通常のコンテンツ -->
<slot />
{/if}
この実装により、予期せぬエラーが発生してもアプリケーションがクラッシュせず、ユーザーに適切なメッセージを表示できますね。
OpenTelemetry の統合
OpenTelemetry の初期化
OpenTelemetry の初期化は、Sentry よりも複雑ですが、柔軟な設定が可能です。
typescript// src/lib/telemetry.ts
import { WebTracerProvider } from '@opentelemetry/sdk-trace-web';
import { registerInstrumentations } from '@opentelemetry/instrumentation';
import { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch';
import { DocumentLoadInstrumentation } from '@opentelemetry/instrumentation-document-load';
// トレーサープロバイダーの作成
const provider = new WebTracerProvider({
resource: {
attributes: {
'service.name': 'svelte-frontend', // サービス名の識別
'service.version': import.meta.env.VITE_APP_VERSION,
},
},
});
WebTracerProviderは、ブラウザ環境でのトレーシングを管理する中核的なクラスです。
プロセッサーとエクスポーターの設定
収集したトレースデータを適切に処理し、バックエンドに送信する設定を行います。
typescript// src/lib/telemetry.ts(続き)
import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
// トレースデータのエクスポーター設定
const exporter = new OTLPTraceExporter({
url: 'https://your-otel-collector.com/v1/traces', // OpenTelemetry Collectorのエンドポイント
headers: {
Authorization: `Bearer ${
import.meta.env.VITE_OTEL_TOKEN
}`,
},
});
// バッチ処理でパフォーマンス向上
provider.addSpanProcessor(new BatchSpanProcessor(exporter));
// グローバルプロバイダーとして登録
provider.register();
BatchSpanProcessorは、スパンをまとめて送信することで、ネットワークリクエストを削減し、パフォーマンスへの影響を最小化します。
自動計装の設定
Fetch API やドキュメント読み込みを自動的に計装することで、手動でコードを追加する必要がなくなりますね。
typescript// src/lib/telemetry.ts(続き)
// 自動計装の登録
registerInstrumentations({
instrumentations: [
// Fetch APIの自動トレーシング
new FetchInstrumentation({
// トレース対象のURLを指定
propagateTraceHeaderCorsUrls: [
/^https:\/\/api\.your-domain\.com\/.*/,
],
// リクエスト/レスポンスフックで追加情報を記録
applyCustomAttributesOnSpan: (
span,
request,
result
) => {
span.setAttribute(
'http.request_content_length',
request.headers.get('content-length') || 0
);
},
}),
// ページ読み込みの自動トレーシング
new DocumentLoadInstrumentation(),
],
});
この設定により、すべての Fetch リクエストとページ読み込みが自動的にトレースされます。
手動スパンの作成
特定の処理を詳細にトレースしたい場合は、手動でスパンを作成できます。
typescript// src/lib/api/user.ts
import { trace } from '@opentelemetry/api';
// トレーサーの取得
const tracer = trace.getTracer('user-api');
// ユーザーデータ取得関数
export async function fetchUserData(userId: string) {
// スパンの開始 - 処理の開始を記録
const span = tracer.startSpan('fetchUserData');
try {
// カスタム属性の追加
span.setAttribute('user.id', userId);
span.setAttribute('operation.type', 'read');
// API呼び出し
const response = await fetch(`/api/users/${userId}`);
const data = await response.json();
// 成功を記録
span.setStatus({ code: 1 }); // SpanStatusCode.OK
return data;
} catch (error) {
// エラーを記録
span.setStatus({
code: 2, // SpanStatusCode.ERROR
message: error.message,
});
throw error;
} finally {
// スパンの終了 - 処理時間が自動計算される
span.end();
}
}
手動スパンを使用することで、ビジネスロジックの詳細なパフォーマンス分析が可能になるでしょう。
Web Vitals の統合
Web Vitals の計測
Web Vitals ライブラリを使用して、主要なパフォーマンス指標を計測します。
typescript// src/lib/vitals.ts
import {
onCLS,
onFID,
onLCP,
onFCP,
onTTFB,
} from 'web-vitals';
// Web Vitalsメトリクスの送信関数
function sendToAnalytics(metric: any) {
// メトリクスデータの構造化
const body = JSON.stringify({
name: metric.name, // メトリクス名(LCP, FID, CLSなど)
value: metric.value, // 計測値
rating: metric.rating, // 評価(good, needs-improvement, poor)
delta: metric.delta, // 前回からの変化量
id: metric.id, // ページ読み込みごとの一意ID
navigationType: metric.navigationType, // ナビゲーションタイプ
});
// 分析エンドポイントに送信
navigator.sendBeacon('/api/analytics/web-vitals', body);
}
sendBeaconを使用することで、ページ遷移時でも確実にデータを送信できます。
メトリクスの監視開始
各メトリクスの監視を開始し、値が利用可能になったら送信します。
typescript// src/lib/vitals.ts(続き)
// メトリクス監視の初期化
export function initWebVitals() {
// LCP(Largest Contentful Paint)- 最大コンテンツ描画時間
// 2.5秒以下が良好、4秒以上は改善が必要
onLCP(sendToAnalytics);
// FID(First Input Delay)- 最初の入力遅延
// 100ms以下が良好、300ms以上は改善が必要
onFID(sendToAnalytics);
// CLS(Cumulative Layout Shift)- 累積レイアウトシフト
// 0.1以下が良好、0.25以上は改善が必要
onCLS(sendToAnalytics);
// FCP(First Contentful Paint)- 最初のコンテンツ描画
onFCP(sendToAnalytics);
// TTFB(Time to First Byte)- 最初のバイト受信時間
onTTFB(sendToAnalytics);
}
これらの指標を継続的に監視することで、パフォーマンスの劣化を早期に発見できますね。
Svelte コンポーネントでの利用
アプリケーションのエントリーポイントで、Web Vitals の監視を開始します。
svelte<!-- src/App.svelte -->
<script lang="ts">
import { onMount } from 'svelte';
import { initWebVitals } from './lib/vitals';
// コンポーネントマウント時にWeb Vitals監視を開始
onMount(() => {
initWebVitals();
});
</script>
<main>
<!-- アプリケーションのコンテンツ -->
<slot />
</main>
この実装により、すべてのページで Web Vitals が自動的に計測されます。
バックエンドとの統合
API エンドポイントの実装
フロントエンドから送信された Web Vitals データを受け取る API エンドポイントを実装しましょう。
typescript// src/routes/api/analytics/web-vitals/+server.ts
import type { RequestHandler } from './$types';
// Web Vitalsデータの受信エンドポイント
export const POST: RequestHandler = async ({ request }) => {
// リクエストボディの解析
const metric = await request.json();
// データベースまたは分析プラットフォームに保存
await saveMetric({
timestamp: new Date(),
metric_name: metric.name,
value: metric.value,
rating: metric.rating,
page_url: request.headers.get('referer'),
user_agent: request.headers.get('user-agent'),
});
return new Response(null, { status: 204 });
};
収集したデータは、時系列データベース(InfluxDB、TimescaleDB など)に保存すると分析しやすいでしょう。
OpenTelemetry コンテキスト伝播
フロントエンドからバックエンドへのトレースコンテキスト伝播を設定し、エンドツーエンドのトレーシングを実現します。
typescript// src/lib/api/client.ts
import { context, propagation } from '@opentelemetry/api';
// トレースコンテキストを含むFetchラッパー
export async function tracedFetch(
url: string,
options: RequestInit = {}
) {
// 現在のコンテキストを取得
const currentContext = context.active();
// トレースヘッダーの注入
const headers = new Headers(options.headers);
propagation.inject(currentContext, headers, {
set: (carrier, key, value) => {
carrier.set(key, value);
},
});
// トレース情報を含むリクエスト送信
return fetch(url, {
...options,
headers,
});
}
この実装により、フロントエンドのトレース ID がバックエンドに伝播され、一連のリクエストを追跡できます。
統合ダッシュボードの構築
Grafana での可視化
OpenTelemetry データを Grafana で可視化する設定例です。
yaml# docker-compose.yml
version: '3.8'
services:
# OpenTelemetry Collector
otel-collector:
image: otel/opentelemetry-collector-contrib:latest
command: ['--config=/etc/otel-collector-config.yaml']
volumes:
- ./otel-collector-config.yaml:/etc/otel-collector-config.yaml
ports:
- '4318:4318' # OTLP HTTP receiver
- '8889:8889' # Prometheus metrics exporter
# Grafana
grafana:
image: grafana/grafana:latest
ports:
- '3000:3000'
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana-storage:/var/lib/grafana
この Docker Compose 設定により、ローカル環境で簡単に可観測性スタックを構築できますね。
OpenTelemetry Collector の設定
収集したテレメトリーデータを適切に処理し、複数のバックエンドに送信する設定です。
yaml# otel-collector-config.yaml
receivers:
otlp:
protocols:
http:
endpoint: 0.0.0.0:4318 # フロントエンドからのデータ受信
processors:
batch:
timeout: 10s # 10秒ごとにバッチ送信
send_batch_size: 1024 # 1024スパンごとに送信
exporters:
prometheus:
endpoint: '0.0.0.0:8889' # Prometheusメトリクス公開
otlp:
endpoint: jaeger:4317 # Jaegerへトレース送信
tls:
insecure: true
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlp]
metrics:
receivers: [otlp]
processors: [batch]
exporters: [prometheus]
この設定により、フロントエンドからのデータを効率的に処理し、適切なバックエンドに振り分けられます。
エラー処理とデバッグ
Sentry 統合のデバッグ
Sentry が正しく動作しているかを確認するためのテストコードです。
typescript// src/lib/debug/sentry-test.ts
import * as Sentry from '@sentry/svelte';
// Sentry動作確認用の関数
export function testSentryIntegration() {
try {
// テストエラーの送出
throw new Error('Test error from Svelte app');
} catch (error) {
// Sentryにエラーを手動送信
Sentry.captureException(error);
console.log('Test error sent to Sentry');
}
// ブレッドクラムのテスト(ユーザーアクション記録)
Sentry.addBreadcrumb({
category: 'test',
message: 'Test breadcrumb added',
level: 'info',
});
}
開発環境でこの関数を実行し、Sentry ダッシュボードにエラーが表示されることを確認しましょう。
よくあるエラーと解決方法
統合時に遭遇する可能性のあるエラーと、その解決方法をまとめます。
エラー 1: CORS(Cross-Origin Resource Sharing)エラー
plaintextError: Access to fetch at 'https://otel-collector.com/v1/traces'
from origin 'http://localhost:5173' has been blocked by CORS policy
発生条件: OpenTelemetry Collector が CORS ヘッダーを適切に返していない場合に発生します。
解決方法:
- OpenTelemetry Collector の設定に CORS ヘッダーを追加します
yaml# otel-collector-config.yaml
receivers:
otlp:
protocols:
http:
endpoint: 0.0.0.0:4318
cors:
allowed_origins:
- 'http://localhost:5173'
- 'https://your-production-domain.com'
allowed_headers:
- '*'
- または、プロキシを使用して CORS 問題を回避します
typescript// vite.config.ts
export default defineConfig({
server: {
proxy: {
'/otel': {
target: 'https://otel-collector.com',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/otel/, ''),
},
},
},
});
エラー 2: ソースマップアップロード失敗
plaintextError: Unable to upload source maps to Sentry
Error 401: Invalid authentication token
発生条件: Sentry の認証トークンが無効、または権限が不足している場合です。
解決方法:
- 有効な Auth トークンを生成します(Sentry → Settings → Auth Tokens)
- 環境変数に正しく設定します
bash# .env.local
SENTRY_AUTH_TOKEN=your_valid_token_here
- トークンに必要な権限(
project:releases、org:read)が付与されていることを確認します
エラー 3: Web Vitals データが送信されない
plaintextTypeError: Cannot read property 'sendBeacon' of undefined
発生条件: 古いブラウザや特定の環境でnavigator.sendBeaconが利用できない場合です。
解決方法: フォールバック実装を追加します
typescript// src/lib/vitals.ts(修正版)
function sendToAnalytics(metric: any) {
const body = JSON.stringify(metric);
// sendBeaconが利用可能か確認
if (navigator.sendBeacon) {
navigator.sendBeacon('/api/analytics/web-vitals', body);
} else {
// フォールバック: 通常のfetchを使用
fetch('/api/analytics/web-vitals', {
method: 'POST',
body,
headers: { 'Content-Type': 'application/json' },
keepalive: true, // ページ遷移後も送信継続
}).catch(console.error);
}
}
パフォーマンス最適化
可観測性ツールの導入により、アプリケーションのパフォーマンスに影響を与える可能性があります。以下の最適化を実施しましょう。
遅延初期化
必須でない計装は、アプリケーション起動後に遅延して初期化します。
typescript// src/lib/observability.ts
// 遅延初期化による初期ロード時間の短縮
export async function initObservabilityLazy() {
// ページ読み込み完了を待機
if (document.readyState === 'complete') {
await initializeTools();
} else {
window.addEventListener('load', initializeTools);
}
}
async function initializeTools() {
// 非同期でツールを初期化(並列実行)
await Promise.all([
import('./telemetry').then((m) =>
m.initOpenTelemetry()
),
import('./vitals').then((m) => m.initWebVitals()),
]);
}
この方法により、初期ページ読み込み時間への影響を最小化できますね。
サンプリングの調整
すべてのイベントを送信するのではなく、適切なサンプリング率を設定します。
typescript// src/lib/sentry.ts(最適化版)
import { init } from '@sentry/svelte';
init({
dsn: 'YOUR_SENTRY_DSN',
// 本番環境でのサンプリング設定
tracesSampleRate: import.meta.env.PROD ? 0.1 : 1.0, // 本番10%、開発100%
// エラーサンプリング(特定エラーを除外)
beforeSend(event, hint) {
// 開発環境のエラーは送信しない
if (import.meta.env.DEV) {
return null;
}
// 特定のエラーを除外(例:ネットワークエラー)
if (
event.exception?.values?.[0]?.value?.includes(
'Network Error'
)
) {
return null;
}
return event;
},
});
適切なサンプリング率により、コストとデータの有用性のバランスを取れるでしょう。
まとめ
Svelte アプリケーションにおける可観測性の実装は、ユーザー体験の向上と運用の効率化に不可欠です。本記事では、Sentry、OpenTelemetry、Web Vitals という 3 つの強力なツールを統合し、包括的な監視体制を構築する方法をご紹介しました。
Sentry によるエラートラッキングで、本番環境の問題を迅速に発見・解決できます。OpenTelemetry による分散トレーシングで、フロントエンドからバックエンドまでのリクエストフローを可視化できますね。Web Vitals によるパフォーマンス計測で、実際のユーザー体験を定量的に把握できます。
これらのツールを適切に組み合わせることで、以下の効果が期待できるでしょう。
| # | 効果 | 説明 |
|---|---|---|
| 1 | 問題の早期発見 | ユーザーが気づく前にエラーを検知 |
| 2 | 迅速なデバッグ | 詳細なトレース情報で原因特定が容易 |
| 3 | パフォーマンス改善 | データに基づいた最適化が可能 |
| 4 | ユーザー満足度向上 | 安定した高速なアプリケーションを提供 |
可観測性の実装は一度で完了するものではなく、継続的な改善が重要です。収集したデータを定期的に分析し、アプリケーションの品質向上に活用していきましょう。
また、チーム全体で可観測性の重要性を共有し、新機能開発時にも計装を忘れずに実施することが成功の鍵となります。本記事で紹介した実装パターンを基盤として、プロジェクトの特性に合わせてカスタマイズし、最適な監視体制を構築してください。
関連リンク
articleSvelte 可観測性の実装:Sentry/OpenTelemetry/Web Vitals 連携ガイド
articleSvelte URL ドリブン設計:検索パラメータとストアの同期パターン
articleSvelte ストア速見表:writable/derived/readable/custom の実用スニペット
articlesvelte-preprocess 導入ガイド:SCSS・PostCSS・TypeScript を安全に共存
articleSvelteKit アダプタ比較:Node/Vercel/Cloudflare/Netlify の速度と制約
articleSvelte ストアエラー「store is not a function」を解決:writable/derived の落とし穴
article本番計測とトレース:Zustand の更新頻度・差分サイズを可視化して改善サイクル化
articleSvelte 可観測性の実装:Sentry/OpenTelemetry/Web Vitals 連携ガイド
article【緊急警告】React/Next.js の RSC 機能に CVSS 10.0 の RCE 脆弱性「CVE-2025-55182」が発覚
articleWebSocket Close コード早見表:正常終了・プロトコル違反・ポリシー違反の実務対応
articleStorybook 品質ゲート運用:Lighthouse/A11y/ビジュアル差分を PR で自動承認
articleWebRTC で高精細 1080p/4K 画面共有:contentHint「detail」と DPI 最適化
blogiPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
blogGoogleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
blog【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
blogGoogleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
blogPixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
blogフロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
review今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
reviewついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
review愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
review週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
review新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
review科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来