New Relic
フルスタック可観測性プラットフォーム。APM、インフラ監視、ブラウザ監視、モバイル監視を統合。リアルタイム性能分析とAI支援による問題解決機能。
監視サーバー
New Relic
概要
New Relicはフルスタック可観測性プラットフォームです。APM、インフラ監視、ブラウザ監視、モバイル監視を統合し、リアルタイム性能分析とAI支援による問題解決機能を提供します。APM分野での老舗プロバイダーとして、AI支援による自動化機能、フルスタック可観測性でデジタル変革を支援し、クラウドファースト戦略で成長を続ける包括的監視ソリューションです。
詳細
New Relicは2008年にLew Cirrneによって設立され、APM分野での老舗プロバイダーとして長年の実績を持ちます。AI支援による自動化機能、フルスタック可観測性でデジタル変革を支援し、クラウドファースト戦略で継続的な成長を遂げています。統一された可観測性プラットフォームとして、開発・運用チームの生産性向上とシステムの信頼性確保に貢献しています。
主要な技術的特徴
- フルスタック可観測性: アプリケーションからインフラまで統合監視
- AI支援分析: 機械学習による自動異常検知と根本原因分析
- リアルタイム分析: 高頻度データ収集とリアルタイム分析
- 統一ダッシュボード: 全レイヤーの情報を統合した可視化
- 豊富なインテグレーション: 主要プラットフォーム・ツールとの統合
用途
- アプリケーション性能監視(APM)
- インフラストラクチャ監視
- ブラウザ・モバイルアプリ監視
- サーバーレス監視
- デジタルカスタマーエクスペリエンス監視
メリット・デメリット
メリット
- 包括的監視: フルスタック可観測性の統一プラットフォーム
- AI/ML機能: 高度な異常検知と予測分析
- 豊富な経験: APM分野での長年の実績と知見
- リアルタイム分析: 高頻度データ収集による即座の洞察
- スケーラビリティ: エンタープライズ規模での高い信頼性
- 統合プラットフォーム: 開発から運用まで一元管理
デメリット
- 高コスト: エンタープライズ向けの高額な料金体系
- 複雑性: 豊富な機能による習得の複雑さ
- ベンダーロックイン: プラットフォーム依存のリスク
- 設定複雑性: 最適な設定のための専門知識が必要
- データボリューム制限: 大量データでのコスト増加
参考ページ
書き方の例
New Relic Agent設定
# newrelic.ini
[newrelic]
license_key = YOUR_LICENSE_KEY_HERE
app_name = My Python Application
# ログ設定
log_file = /var/log/newrelic/python-agent.log
log_level = info
# 監視設定
monitor_mode = true
ssl = true
high_security = false
# パフォーマンス設定
agent_limits.data_collector_timeout = 30.0
agent_limits.transaction_tracer_timeout = 10.0
# トランザクション設定
transaction_tracer.enabled = true
transaction_tracer.transaction_threshold = apdex_f
transaction_tracer.record_sql = obfuscated
transaction_tracer.stack_trace_threshold = 0.5
transaction_tracer.explain_enabled = true
transaction_tracer.explain_threshold = 0.5
# エラー設定
error_collector.enabled = true
error_collector.ignore_errors =
error_collector.ignore_status_codes = 404
# ブラウザ監視
browser_monitoring.auto_instrument = true
# データベース設定
datastore_tracer.instance_reporting.enabled = true
datastore_tracer.database_name_reporting.enabled = true
# 分散トレーシング
distributed_tracing.enabled = true
# カスタムインサイト
custom_insights_events.enabled = true
# セキュリティ設定
capture_params = false
ignored_params = credit_card, ssn, password
# 属性設定
attributes.enabled = true
attributes.exclude = request.headers.cookie
attributes.exclude = request.headers.authorization
attributes.exclude = request.headers.proxy-authorization
attributes.exclude = request.headers.x-*
# ラベル設定
labels = Environment:Production;Team:Backend;Region:US-East
Python アプリケーション統合
# app.py
import newrelic.agent
import logging
import time
from flask import Flask, request, jsonify
from sqlalchemy import create_engine, text
import redis
# New Relic初期化
newrelic.agent.initialize('/path/to/newrelic.ini')
app = Flask(__name__)
# データベース接続
engine = create_engine('postgresql://user:pass@localhost/mydb')
# Redis接続
redis_client = redis.Redis(host='localhost', port=6379, db=0)
# ログ設定
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
@newrelic.agent.function_trace()
def get_user_from_db(user_id):
"""データベースからユーザー情報を取得"""
with engine.connect() as conn:
result = conn.execute(
text("SELECT * FROM users WHERE id = :user_id"),
user_id=user_id
)
return result.fetchone()
@newrelic.agent.function_trace()
def get_user_from_cache(user_id):
"""キャッシュからユーザー情報を取得"""
cache_key = f"user:{user_id}"
cached_data = redis_client.get(cache_key)
if cached_data:
newrelic.agent.add_custom_attribute('cache_hit', True)
return cached_data.decode('utf-8')
newrelic.agent.add_custom_attribute('cache_hit', False)
return None
@app.route('/user/<int:user_id>')
@newrelic.agent.function_trace()
def get_user(user_id):
"""ユーザー情報取得エンドポイント"""
# カスタム属性追加
newrelic.agent.add_custom_attribute('user_id', user_id)
newrelic.agent.add_custom_attribute('endpoint', 'get_user')
try:
# キャッシュ確認
cached_user = get_user_from_cache(user_id)
if cached_user:
newrelic.agent.record_custom_metric('Custom/Cache/Hit', 1)
return jsonify({"user": cached_user, "source": "cache"})
# データベースアクセス
with newrelic.agent.BackgroundTask(application=newrelic.agent.application(), name='get_user_db'):
user = get_user_from_db(user_id)
if user:
# キャッシュに保存
cache_key = f"user:{user_id}"
redis_client.setex(cache_key, 300, str(user))
newrelic.agent.record_custom_metric('Custom/Cache/Miss', 1)
newrelic.agent.record_custom_metric('Custom/User/Retrieved', 1)
return jsonify({"user": dict(user), "source": "database"})
else:
newrelic.agent.record_custom_metric('Custom/User/NotFound', 1)
return jsonify({"error": "User not found"}), 404
except Exception as e:
# エラーの記録
newrelic.agent.record_exception()
newrelic.agent.add_custom_attribute('error_type', type(e).__name__)
newrelic.agent.record_custom_metric('Custom/Error/Database', 1)
logger.error(f"Error retrieving user {user_id}: {e}")
return jsonify({"error": "Internal server error"}), 500
@app.route('/health')
def health_check():
"""ヘルスチェック"""
newrelic.agent.add_custom_attribute('endpoint', 'health_check')
# 外部依存関係チェック
health_status = {
"status": "healthy",
"timestamp": time.time(),
"checks": {}
}
# データベース接続確認
try:
with engine.connect() as conn:
conn.execute(text("SELECT 1"))
health_status["checks"]["database"] = "healthy"
except Exception as e:
health_status["checks"]["database"] = "unhealthy"
health_status["status"] = "unhealthy"
newrelic.agent.record_custom_metric('Custom/Health/Database/Failure', 1)
# Redis接続確認
try:
redis_client.ping()
health_status["checks"]["redis"] = "healthy"
except Exception as e:
health_status["checks"]["redis"] = "unhealthy"
health_status["status"] = "unhealthy"
newrelic.agent.record_custom_metric('Custom/Health/Redis/Failure', 1)
newrelic.agent.record_custom_metric('Custom/Health/Check', 1)
return jsonify(health_status)
@app.route('/api/orders', methods=['POST'])
@newrelic.agent.function_trace()
def create_order():
"""注文作成エンドポイント"""
start_time = time.time()
try:
order_data = request.get_json()
# カスタム属性
newrelic.agent.add_custom_attribute('order_value', order_data.get('total', 0))
newrelic.agent.add_custom_attribute('user_id', order_data.get('user_id'))
newrelic.agent.add_custom_attribute('items_count', len(order_data.get('items', [])))
# ビジネスロジック処理
order_id = process_order(order_data)
# 処理時間記録
processing_time = time.time() - start_time
newrelic.agent.record_custom_metric('Custom/Order/ProcessingTime', processing_time)
newrelic.agent.record_custom_metric('Custom/Order/Created', 1)
return jsonify({
"order_id": order_id,
"status": "created",
"processing_time": processing_time
}), 201
except Exception as e:
newrelic.agent.record_exception()
newrelic.agent.record_custom_metric('Custom/Order/Failed', 1)
return jsonify({"error": "Order creation failed"}), 500
@newrelic.agent.function_trace()
def process_order(order_data):
"""注文処理ロジック"""
# 在庫確認
with newrelic.agent.FunctionTrace(name='check_inventory'):
time.sleep(0.1) # 処理シミュレーション
# 支払い処理
with newrelic.agent.FunctionTrace(name='process_payment'):
time.sleep(0.2) # 処理シミュレーション
# 配送手配
with newrelic.agent.FunctionTrace(name='arrange_shipping'):
time.sleep(0.05) # 処理シミュレーション
return "ORD-" + str(int(time.time()))
# カスタムイベント送信
@app.route('/event')
def send_custom_event():
"""カスタムイベント送信"""
newrelic.agent.record_custom_event('CustomEvent', {
'eventType': 'user_action',
'action': 'button_click',
'user_id': 12345,
'page': '/dashboard',
'timestamp': time.time()
})
return jsonify({"message": "Custom event sent"})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
Kubernetes統合設定
# newrelic-infrastructure.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: newrelic-infra
namespace: newrelic
labels:
app: newrelic-infra
spec:
selector:
matchLabels:
app: newrelic-infra
template:
metadata:
labels:
app: newrelic-infra
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8001"
spec:
serviceAccountName: newrelic
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
containers:
- name: newrelic-infra
image: newrelic/infrastructure-k8s:2.13.0
resources:
limits:
memory: 300M
cpu: 150m
requests:
memory: 150M
cpu: 100m
volumeMounts:
- mountPath: /host
name: host-root
readOnly: true
- mountPath: /var/run/docker.sock
name: host-docker-socket
env:
- name: NRIA_LICENSE_KEY
valueFrom:
secretKeyRef:
name: newrelic-license
key: license
- name: NRIA_CLUSTER_NAME
value: "production-cluster"
- name: NRIA_DISPLAY_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
- name: NRK8S_NODE_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
- name: NRIA_CUSTOM_ATTRIBUTES
value: '{"environment":"production","team":"devops"}'
- name: NRIA_PASSTHROUGH_ENVIRONMENT
value: "KUBERNETES_SERVICE_HOST,KUBERNETES_SERVICE_PORT,CLUSTER_NAME,CADVISOR_PORT,NRK8S_NODE_NAME,KUBE_STATE_METRICS_URL,KUBE_STATE_METRICS_POD_LABEL"
- name: CADVISOR_PORT
value: "4194"
- name: KUBE_STATE_METRICS_URL
value: "http://kube-state-metrics.kube-system.svc.cluster.local:8080"
- name: KUBE_STATE_METRICS_POD_LABEL
value: "app.kubernetes.io/name=kube-state-metrics"
- name: TIMEOUT
value: "20"
- name: NRIA_VERBOSE
value: "1"
volumes:
- name: host-root
hostPath:
path: /
- name: host-docker-socket
hostPath:
path: /var/run/docker.sock
tolerations:
- effect: NoSchedule
operator: Exists
- effect: NoExecute
operator: Exists
---
apiVersion: v1
kind: Secret
metadata:
name: newrelic-license
namespace: newrelic
type: Opaque
data:
license: <BASE64_ENCODED_LICENSE_KEY>
ブラウザ監視設定
<!-- Browser Agent設定 -->
<!DOCTYPE html>
<html>
<head>
<title>My Application</title>
<!-- New Relic Browser Agent -->
<script type="text/javascript">
window.NREUM||(NREUM={});
NREUM.loader_config={
accountID:"YOUR_ACCOUNT_ID",
trustKey:"YOUR_TRUST_KEY",
agentID:"YOUR_AGENT_ID",
licenseKey:"YOUR_LICENSE_KEY",
applicationID:"YOUR_APP_ID"
};
NREUM.info={
beacon:"bam.nr-data.net",
errorBeacon:"bam.nr-data.net",
sa:1
};
</script>
<script src="https://js-agent.newrelic.com/nr-loader-rum-1.260.0.min.js"></script>
</head>
<body>
<div id="app">
<h1>My Application</h1>
<button id="actionButton">Click Me</button>
<div id="content"></div>
</div>
<script>
// カスタムページアクション
function trackCustomAction(actionName, attributes = {}) {
if (typeof newrelic !== 'undefined') {
newrelic.addPageAction(actionName, attributes);
}
}
// カスタム属性追加
function addCustomAttributes() {
if (typeof newrelic !== 'undefined') {
newrelic.setCustomAttribute('userType', 'premium');
newrelic.setCustomAttribute('experimentGroup', 'A');
newrelic.setCustomAttribute('feature_flags', JSON.stringify({
newDashboard: true,
betaFeature: false
}));
}
}
// エラー追跡
function trackCustomError(error, attributes = {}) {
if (typeof newrelic !== 'undefined') {
newrelic.noticeError(error, attributes);
}
}
// ユーザーアクション追跡
document.getElementById('actionButton').addEventListener('click', function() {
const startTime = Date.now();
// APIコール
fetch('/api/data')
.then(response => {
const responseTime = Date.now() - startTime;
trackCustomAction('api_call_completed', {
endpoint: '/api/data',
responseTime: responseTime,
status: response.status
});
return response.json();
})
.then(data => {
document.getElementById('content').innerHTML = JSON.stringify(data);
trackCustomAction('content_updated', {
dataSize: JSON.stringify(data).length
});
})
.catch(error => {
trackCustomError(error, {
context: 'api_call',
endpoint: '/api/data'
});
});
});
// ページロード時の設定
document.addEventListener('DOMContentLoaded', function() {
addCustomAttributes();
trackCustomAction('page_loaded', {
timestamp: Date.now(),
userAgent: navigator.userAgent
});
});
// Single Page Application (SPA) ルート変更追跡
function trackRouteChange(from, to) {
if (typeof newrelic !== 'undefined') {
newrelic.interaction().setName(to);
trackCustomAction('route_change', {
from: from,
to: to,
timestamp: Date.now()
});
}
}
// パフォーマンス測定
function measurePerformance(name, fn) {
const start = performance.now();
const result = fn();
if (result instanceof Promise) {
return result.finally(() => {
const duration = performance.now() - start;
trackCustomAction('custom_timing', {
name: name,
duration: duration
});
});
} else {
const duration = performance.now() - start;
trackCustomAction('custom_timing', {
name: name,
duration: duration
});
return result;
}
}
</script>
</body>
</html>
Infrastructure as Code (Terraform)
# newrelic.tf
terraform {
required_providers {
newrelic = {
source = "newrelic/newrelic"
version = "~> 3.0"
}
}
}
provider "newrelic" {
account_id = var.newrelic_account_id
api_key = var.newrelic_api_key
region = "US"
}
# アプリケーション作成
resource "newrelic_application" "app" {
name = "My Production App"
language = "python"
app_apdex_threshold = 0.5
end_user_apdex_threshold = 7
enable_real_user_monitoring = true
}
# アラートポリシー
resource "newrelic_alert_policy" "production_policy" {
name = "Production Alerts"
incident_preference = "PER_POLICY"
}
# レスポンス時間アラート
resource "newrelic_alert_condition" "response_time" {
policy_id = newrelic_alert_policy.production_policy.id
name = "High Response Time"
type = "apm_app_metric"
entities = [newrelic_application.app.id]
metric = "response_time_web"
runbook_url = "https://docs.example.com/runbooks/high-response-time"
term {
duration = 5
operator = "above"
priority = "critical"
threshold = "2.0"
time_function = "all"
}
term {
duration = 3
operator = "above"
priority = "warning"
threshold = "1.0"
time_function = "all"
}
}
# エラー率アラート
resource "newrelic_alert_condition" "error_rate" {
policy_id = newrelic_alert_policy.production_policy.id
name = "High Error Rate"
type = "apm_app_metric"
entities = [newrelic_application.app.id]
metric = "error_percentage"
term {
duration = 5
operator = "above"
priority = "critical"
threshold = "5.0"
time_function = "all"
}
}
# インフラアラート
resource "newrelic_infra_alert_condition" "high_cpu" {
policy_id = newrelic_alert_policy.production_policy.id
name = "High CPU Usage"
type = "infra_metric"
event = "SystemSample"
select = "cpuPercent"
comparison = "above"
where = "environment = 'production'"
critical {
duration = 5
value = 80
time_function = "all"
}
warning {
duration = 3
value = 70
time_function = "all"
}
}
# 通知チャンネル
resource "newrelic_alert_channel" "slack" {
name = "slack-alerts"
type = "slack"
config {
url = var.slack_webhook_url
channel = "#alerts"
}
}
# ポリシーとチャンネルの関連付け
resource "newrelic_alert_policy_channel" "alert_policy_slack" {
policy_id = newrelic_alert_policy.production_policy.id
channel_ids = [newrelic_alert_channel.slack.id]
}
# Synthetics監視
resource "newrelic_synthetics_monitor" "website_monitor" {
name = "Website Monitor"
type = "SIMPLE"
frequency = 5
status = "ENABLED"
locations = ["AWS_US_EAST_1", "AWS_EU_WEST_1"]
uri = "https://example.com"
validation_string = "Welcome"
verify_ssl = true
bypass_head_request = false
treat_redirect_as_failure = false
}
# ダッシュボード
resource "newrelic_dashboard" "production_dashboard" {
title = "Production Dashboard"
widget {
title = "Response Time"
row = 1
column = 1
width = 1
height = 1
visualization = "faceted_line_chart"
nrql = "SELECT average(duration) FROM Transaction WHERE appName = '${newrelic_application.app.name}' TIMESERIES"
}
widget {
title = "Error Rate"
row = 1
column = 2
width = 1
height = 1
visualization = "gauge"
nrql = "SELECT percentage(count(*), WHERE error IS true) FROM Transaction WHERE appName = '${newrelic_application.app.name}'"
threshold_red = 5.0
threshold_yellow = 2.0
}
widget {
title = "Throughput"
row = 2
column = 1
width = 2
height = 1
visualization = "line_chart"
nrql = "SELECT rate(count(*), 1 minute) FROM Transaction WHERE appName = '${newrelic_application.app.name}' TIMESERIES"
}
}
# カスタムイベント用のWorkflow
resource "newrelic_workflow" "production_workflow" {
name = "Production Incident Workflow"
muting_rules_handling = "NOTIFY_ALL_ISSUES"
issues_filter {
name = "Filter-name"
type = "FILTER"
predicate {
attribute = "labels.policyIds"
operator = "EXACTLY_MATCHES"
values = [newrelic_alert_policy.production_policy.id]
}
}
destination {
channel_id = newrelic_alert_channel.slack.id
}
}