はじめに: 導入は終わりではなく、始まりです
完璧な CI/CD パイプラインであっても、デプロイ後に何が起こるかが分からなければ役に立ちません。 実際のユーザーは、さまざまなデバイスで、予測できない方法でアプリケーションを操作します。 さまざまな接続が可能です。の 監視 そして警告中 DevOps サイクルを終了します。ユーザーから報告される前に問題を検出できるようになります。 そして、何か問題が起きたときにすぐに対応すること。
このシリーズの最後の記事では フロントエンド開発者のためのDevOps、 フロントエンド監視の 3 つのカテゴリ (エラー追跡、パフォーマンス監視) を検討します。 そしてユーザーの行動分析。 Angular でエラー追跡用に Sentry を構成し、実装します。 Web-Vitals を使用して実際のユーザーを監視し、効果的なアラート戦略を定義します。
この記事で学べること
- フロントエンド監視の 3 つのカテゴリ (エラー、パフォーマンス、ユーザーの動作)
- Sentry を Angular アプリケーションに統合する方法
- リアル ユーザー モニタリング (RUM) を実装する方法
- 合成監視(稼働時間チェック)の設定方法
- Web-Vitals ライブラリを使用してパフォーマンスを監視する方法
- Angular でカスタム エラー ハンドラーを作成する方法
- 本番環境でデバッグするためにソース マップをロードする方法
- 効果的なアラート戦略
- 監視ダッシュボードの設定方法
- 最も人気のある監視ツールの比較
1. フロントエンド監視の 3 つのカテゴリ
フロントエンド監視は 3 つの補完的な領域に分割され、それぞれに目的とツールがあります 具体的に:
監視カテゴリ
| カテゴリ | 監視対象 | 代表的なツール | 優先度 |
|---|---|---|---|
| エラー追跡 | JavaScript 例外、HTTP エラー、アプリケーションのクラッシュ | セントリー、バグスナッグ、ロールバー | 批判 |
| パフォーマンスの監視 | コア ウェブ バイタル、読み込み時間、ネットワーク メトリクス | ウェブバイタル、SpeedCurve、Datadog RUM | 高い |
| ユーザーの行動 | ナビゲーション、インタラクション、コンバージョンファネル | Google アナリティクス、ミックスパネル、振幅 | 平均 |
2. Sentry によるエラー追跡
セントリー フロントエンドの世界で最も使用されているエラー追跡プラットフォームです。 JavaScript 例外を自動的にキャッチし、ブラウザーのコンテキストで例外を強化します それらをタイプ別にグループ化することで、デバッグが大幅に容易になります。
基本的なインストールと構成
# Installare il pacchetto Sentry per Angular
npm install @sentry/angular @sentry/browser
# Oppure con il wizard automatico
npx @sentry/wizard@latest -i angular
// main.ts - Inizializzazione di Sentry
import * as Sentry from '@sentry/angular';
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { appConfig } from './app/app.config';
// Inizializzare Sentry PRIMA del bootstrap dell'applicazione
Sentry.init({
dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0',
environment: 'production',
release: 'my-app@1.0.0',
// Tracciamento delle performance
tracesSampleRate: 0.2, // 20% delle transazioni
// Replay delle sessioni con errori
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,
integrations: [
Sentry.browserTracingIntegration(),
Sentry.replayIntegration(),
],
// Filtrare errori non rilevanti
ignoreErrors: [
'ResizeObserver loop limit exceeded',
'Non-Error exception captured',
/Loading chunk [\d]+ failed/,
],
// Informazioni aggiuntive per ogni evento
beforeSend(event) {
// Rimuovere dati sensibili
if (event.request?.cookies) {
delete event.request.cookies;
}
return event;
},
});
bootstrapApplication(AppComponent, appConfig);
プロバイダーを使用したAngular構成
// app.config.ts - Registrare i provider Sentry
import { ApplicationConfig, ErrorHandler } from '@angular/core';
import { provideRouter, Router } from '@angular/router';
import * as Sentry from '@sentry/angular';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
// Error Handler personalizzato che invia a Sentry
{
provide: ErrorHandler,
useValue: Sentry.createErrorHandler({
showDialog: false, // Non mostrare il dialog di Sentry agli utenti
logErrors: true, // Loggare anche nella console
}),
},
// Tracciamento delle navigazioni Angular
{
provide: Sentry.TraceService,
deps: [Router],
},
],
};
サンプルレートに注意してください
Il tracesSampleRate Sentry に送信されるトランザクションの数を決定します。
の値 1.0 (100%) 開発には便利ですが、本番環境ではコストがかかりすぎます
交通量が多い。から始める 0.1 o 0.2 必要に応じて増加します。
のために replaysOnErrorSampleRate、 維持する 1.0 捕獲する
エラーが発生したときは常にセッションです。
3. Angular のカスタム エラー ハンドラー
エラーをより細かく制御するには、カスタム エラー ハンドラーを作成できます。 Sentry と追加のロジックを組み合わせたものです。
// custom-error-handler.ts
import { ErrorHandler, Injectable, inject } from '@angular/core';
import * as Sentry from '@sentry/angular';
@Injectable()
export class CustomErrorHandler implements ErrorHandler {
handleError(error: unknown): void {
// Classificare l'errore
const errorInfo = this.classifyError(error);
// Inviare a Sentry con contesto aggiuntivo
Sentry.withScope((scope) => {
scope.setTag('error.type', errorInfo.type);
scope.setTag('error.severity', errorInfo.severity);
scope.setLevel(errorInfo.severity as Sentry.SeverityLevel);
if (errorInfo.type === 'http') {
scope.setContext('http', {
status: (error as any)?.status,
url: (error as any)?.url,
});
}
Sentry.captureException(error);
});
// Loggare nella console in development
console.error('[CustomErrorHandler]', error);
}
private classifyError(error: unknown): { type: string; severity: string } {
if (error instanceof TypeError) {
return { type: 'type-error', severity: 'error' };
}
if ((error as any)?.status !== undefined) {
const status = (error as any).status;
if (status >= 500) return { type: 'http', severity: 'error' };
if (status >= 400) return { type: 'http', severity: 'warning' };
}
if (error instanceof Error && error.message?.includes('ChunkLoadError')) {
return { type: 'chunk-load', severity: 'warning' };
}
return { type: 'unknown', severity: 'error' };
}
}
4. リアルユーザーモニタリング (RUM)
Il 実際のユーザーのモニタリング ユーザーが知覚するパフォーマンスを測定する
シミュレートされた環境ではなく、実際の環境です。図書館 web-vitals Google と標準の
ユーザーのブラウザから直接 Core Web Vitals を収集します。
# Installare web-vitals
npm install web-vitals
// web-vitals.service.ts
import { Injectable } from '@angular/core';
import { onCLS, onFCP, onINP, onLCP, onTTFB } from 'web-vitals';
import type { Metric } from 'web-vitals';
@Injectable({ providedIn: 'root' })
export class WebVitalsService {
initializeTracking(): void {
// Core Web Vitals
onCLS(this.reportMetric.bind(this));
onINP(this.reportMetric.bind(this));
onLCP(this.reportMetric.bind(this));
// Metriche supplementari
onFCP(this.reportMetric.bind(this));
onTTFB(this.reportMetric.bind(this));
}
private reportMetric(metric: Metric): void {
const data = {
name: metric.name,
value: metric.value,
rating: metric.rating, // 'good' | 'needs-improvement' | 'poor'
delta: metric.delta,
id: metric.id,
navigationType: metric.navigationType,
};
// Inviare a un endpoint di analisi
this.sendToAnalytics(data);
// Inviare a Sentry come breadcrumb
this.sendToSentry(data);
// Log in console per debugging
console.log(`[Web Vital] ${metric.name}: ${metric.value} (${metric.rating})`);
}
private sendToAnalytics(data: Record<string, unknown>): void {
// Inviare a Google Analytics
if (typeof gtag !== 'undefined') {
gtag('event', data['name'] as string, {
value: Math.round(data['value'] as number),
event_category: 'Web Vitals',
event_label: data['rating'] as string,
non_interaction: true,
});
}
}
private sendToSentry(data: Record<string, unknown>): void {
import('@sentry/angular').then((Sentry) => {
Sentry.addBreadcrumb({
category: 'web-vital',
message: `${data['name']}: ${data['value']} (${data['rating']})`,
level: data['rating'] === 'poor' ? 'warning' : 'info',
data: data,
});
});
}
}
ルートコンポーネントでのトラッキングの初期化
// app.component.ts
import { Component, OnInit, inject, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import { WebVitalsService } from './services/web-vitals.service';
@Component({
selector: 'app-root',
template: '<router-outlet />',
})
export class AppComponent implements OnInit {
private webVitals = inject(WebVitalsService);
private platformId = inject(PLATFORM_ID);
ngOnInit(): void {
// Web Vitals funziona solo nel browser, non in SSR
if (isPlatformBrowser(this.platformId)) {
this.webVitals.initializeTracking();
}
}
}
5. 合成モニタリング (稼働時間チェック)
Il 合成モニタリング 定期的に自動チェックを実行して、 サイトがアクセス可能で機能していることを確認してください。 RUMと違って依存しない ユーザー トラフィックから: 誰もサイトにアクセスしていない午前 3 時でも問題を検出します。
# GitHub Actions per uptime monitoring
name: Uptime Check
on:
schedule:
- cron: '*/15 * * * *' # Ogni 15 minuti
jobs:
check:
runs-on: ubuntu-latest
steps:
- name: Check site availability
run: |
STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://example.com)
RESPONSE_TIME=$(curl -s -o /dev/null -w "%{time_total}" https://example.com)
echo "Status: $STATUS"
echo "Response time: ${RESPONSE_TIME}s"
if [ "$STATUS" != "200" ]; then
echo "ALERT: Site returned status $STATUS"
exit 1
fi
# Controllare il tempo di risposta
THRESHOLD="3.0"
if (( $(echo "$RESPONSE_TIME > $THRESHOLD" | bc -l) )); then
echo "WARNING: Response time ${RESPONSE_TIME}s exceeds threshold ${THRESHOLD}s"
fi
総合監視サービス
- アップタイムロボット:50モニターの無料プラン、5分ごとにチェック
- ピンダム: 統合された RUM 分析による高度なモニタリング
- チェックリー: Playwrightによるブラウザチェック、複雑なフローに最適
- 稼働時間の向上: 公開ステータス ページによるインシデント管理
- Googleクラウドモニタリング: GCP エコシステムと統合された稼働時間チェック
6. デバッグ用のソース マップのアップロード
運用環境では、JavaScript コードは縮小され、判読できなくなります。の ソースマップ Sentry が変数名と番号を含む元のスタック トレースを表示できるようにします ソースコード行。これらを Sentry にアップロードすることは必須ですが、公開することはできません。
# Upload delle source map nella pipeline CI/CD
- name: Build with source maps
run: npx ng build --configuration=production --source-map
- name: Upload source maps to Sentry
uses: getsentry/action-release@v1
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: my-organization
SENTRY_PROJECT: my-angular-app
with:
environment: production
version: ${{ github.sha }}
sourcemaps: './dist/my-app/browser'
url_prefix: '~/'
- name: Remove source maps before deploy
run: find dist/my-app/browser -name "*.map" -delete
運用環境ではソース マップを決して提供しない
ソース マップには、アプリケーションの完全なソース コードが含まれています。公に奉仕する これにより、誰でもビジネス ロジックを読み、脆弱性を特定できるようになり、 内部アーキテクチャを理解します。これらを Sentry にアップロードし、ディレクトリから削除します。 展開します。
7. アラート戦略
警報のない監視システムであり、サイレンのない火災警報器のようなものです。 しかし、アラートが多すぎると、チームが通知を無視する「アラート疲れ」が発生します。鍵となるのは インテリジェントなしきい値を定義します。
推奨される警戒レベル
| レベル | トリガー | チャネル | 答え |
|---|---|---|---|
| クリティカル (P0) | サイトが完全にダウン、エラー > 50% | SMS + Slack + PagerDuty | 即時(15分以内) |
| 高(P1) | 重要な機能が壊れています、エラー率 > 10% | スラック + メール | 1時間以内 |
| 中(P2) | パフォーマンスの低下、重大ではないエラー > 5% | スラック | 4時間以内 |
| 低 (P3) | 警告、指標は負の傾向にあります | 週報 | 次のスプリント |
Sentry のアラート設定
Configurazione Alert Sentry:
Alert 1: Spike di Errori
Condizione: Quando il numero di eventi > 100 in 1 ora
Azione: Notifica Slack #alerts + email team lead
Frequenza: Max 1 notifica ogni 30 minuti
Alert 2: Nuovo Errore in Produzione
Condizione: Prima occorrenza di un nuovo issue
Azione: Notifica Slack #errors
Frequenza: Ogni nuovo issue
Alert 3: Regressione
Condizione: Issue precedentemente risolto riappare
Azione: Notifica Slack #alerts + assegna all'ultimo resolver
Frequenza: Ogni regressione
Alert 4: Performance Budget
Condizione: LCP p95 > 4 secondi
Azione: Notifica Slack #performance
Frequenza: Max 1 notifica ogni 2 ore
8. モニタリングダッシュボード
効果的なダッシュボードは、アプリケーションの健全性の概要を即座に提供します。 含めるべき重要な指標は次のとおりです。
必須のダッシュボード
+----------------------------------------------------------+
| Application Health |
+----------------------------------------------------------+
| |
| Uptime: 99.97% Error Rate: 0.3% Avg LCP: 1.8s |
| |
+----------------------------------------------------------+
| Core Web Vitals (p75) |
| +--------+ +--------+ +--------+ |
| | LCP | | INP | | CLS | |
| | 1.8s | | 120ms | | 0.05 | |
| | (good) | | (good) | | (good) | |
| +--------+ +--------+ +--------+ |
+----------------------------------------------------------+
| Errori Ultimi 7 Giorni | Top Errori |
| +-----------------------------+ | 1. TypeError: null |
| | Mon Tue Wed Thu Fri Sat Sun | | 2. ChunkLoadError |
| | 5 3 8 2 12 1 0 | | 3. HttpError 500 |
| +-----------------------------+ | 4. NetworkError |
+----------------------------------------------------------+
9. 監視ツールの比較
監視ツールの比較
| 楽器 | タイプ | 無料プラン | 強みポイント | 理想的な用途 |
|---|---|---|---|---|
| セントリー | エラー追跡 + パフォーマンス | 5,000 イベント/月 | エラーのグループ化、ソースマップ | すべてのプロジェクト |
| Datadog RUM | フルスタック監視 | 限定 | フロントエンドとバックエンドの相関関係 | 企業 |
| ログロケット | セッションリプレイ + エラー追跡 | 1,000 セッション/月 | セッションのビデオリプレイ | UX デバッグ |
| New Relic ブラウザ | RUM + エラー追跡 | 100GB/月 | カスタマイズ可能なダッシュボード | 運用チーム |
| バグスナッグ | エラー追跡 | 7.5K イベント/月 | リリーストラッキングの安定性 | モバイル + ウェブ |
10. 完全な実装: チェックリスト
以下は、Angular プロジェクトでモニタリングを実装するための完全なチェックリストです。
// monitoring-setup.ts - Configurazione centralizzata
import { Injectable, inject, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
@Injectable({ providedIn: 'root' })
export class MonitoringService {
private platformId = inject(PLATFORM_ID);
initialize(): void {
if (!isPlatformBrowser(this.platformId)) return;
// 1. Error Tracking (Sentry già configurato nel main.ts)
// 2. Web Vitals
this.setupWebVitals();
// 3. Custom error boundary per errori non gestiti
this.setupGlobalErrorHandlers();
// 4. Network monitoring
this.setupNetworkMonitoring();
}
private async setupWebVitals(): Promise<void> {
const { onCLS, onINP, onLCP, onFCP, onTTFB } = await import('web-vitals');
const report = (metric: any) => {
console.log(`[Vital] ${metric.name}: ${metric.value}`);
};
onCLS(report);
onINP(report);
onLCP(report);
onFCP(report);
onTTFB(report);
}
private setupGlobalErrorHandlers(): void {
// Catturare promise non gestite
window.addEventListener('unhandledrejection', (event) => {
console.error('[Unhandled Rejection]', event.reason);
});
// Catturare errori di caricamento risorse
window.addEventListener('error', (event) => {
if (event.target instanceof HTMLScriptElement) {
console.error('[Script Load Error]', event);
}
}, true);
}
private setupNetworkMonitoring(): void {
// Monitorare i cambiamenti di connessione
const connection = (navigator as any).connection;
if (connection) {
connection.addEventListener('change', () => {
console.log('[Network]', {
effectiveType: connection.effectiveType,
downlink: connection.downlink,
rtt: connection.rtt,
});
});
}
}
}
稼働開始監視チェックリスト
- Sentry が構成され、カスタム エラー ハンドラーで実行されています
- ソース マップが Sentry にアップロードされた (およびデプロイメントから削除された)
- Web Vitals の追跡がアクティブになり、Google Analytics に送信されます
- 稼働時間監視が構成されています (5 分ごとにチェック)
- 重大なエラーに対して設定されたアラート (Slack、電子メール)
- 重要なメトリクスを使用して作成されたダッシュボード
- セントリー トークン ローテーション プランが設定されました
- 文書化されたインシデント対応手順
- SSR 互換性を確認済み (isPlatformBrowser)
- トラフィック量に合わせて最適化されたサンプルレート
結論
この記事でシリーズを終了します フロントエンド開発者のためのDevOps。 GitHub Actions を使用した CI/CD パイプラインの構築から、 Dockerによるコンテナ化、Firebaseによる自動デプロイ、シークレット管理、 Lighthouse CI によるパフォーマンス監視から、本番環境の監視まで セントリーとウェブバイタル。
実稼働環境でのモニタリングにより DevOps ループが終了します: データは実際のユーザーから収集されます これらは、開発上の意思決定、バグ修正の優先順位、パフォーマンスの最適化を促進します。 これはオプションのコンポーネントではなく、信頼性の高いアプリケーションを構築し、改善するための基礎となります。 ユーザーエクスペリエンスを継続的に向上させます。
フロントエンド DevOps とプログレッシブ イテレーションで成功するための鍵: 実装しない すべて一度に実行しますが、基本 (CI/CD + エラー追跡) から始めて追加します。 徐々に高度なコンポーネント (パフォーマンス バジェット、合成モニタリング、 プロジェクトとチームが成熟するにつれて、構造化されたアラート)が必要になります。







