Azure Functions
プラットフォーム
Azure Functions
概要
Azure Functionsは、Microsoft Azureが提供するエンタープライズ級サーバーレスコンピューティングプラットフォームです。イベント駆動型のスケーラブルな実行環境として、.NET、Python、JavaScript、Java、Go、Rustなど多様な言語をサポートし、豊富なAzureサービスとの統合によりエンタープライズアプリケーションの構築を強力にサポートします。2025年現在、Flex Consumption Plan、冷却開始パフォーマンスの大幅改善、AI統合強化、Kafka/Event Grid新トリガー対応、そして次世代コンテナ化デプロイメント機能により、従来のサーバーレスコンピューティングの制約を突破し、大規模エンタープライズワークロードにも対応する包括的なプラットフォームとして進化しています。
詳細
Azure Functions 2025年版は、Microsoft の豊富なエンタープライズ経験とクラウドサービスの深い統合により、単なるサーバーレス実行環境を超えた包括的なアプリケーション開発プラットフォームを提供しています。特に注目すべきは、新しいFlex Consumption Planにより最大1,000インスタンスまでのスケーリング、4096MBのメモリサポート、VNet統合によるエンタープライズセキュリティ対応を実現していることです。Project Teleportによる冷却開始時間の15倍改善、Durable Functions による複雑なワークフロー管理、Visual Studio/VS Code/GitHub Actionsとの完全統合開発体験、そしてAzure OpenAI/Cognitive Servicesとの統合によるAI機能の活用により、モダンアプリケーション開発の包括的なソリューションを提供します。
主な特徴
- 多言語サポート: .NET、Python、JavaScript、Java、Go、Rust対応
- 豊富なトリガー: HTTP、Timer、Blob、Queue、Service Bus、Kafka、Event Grid等
- Azure統合: 200以上のAzureサービスとのシームレスな統合
- Durable Functions: ステートフルなワークフロー実行環境
- エンタープライズセキュリティ: Managed Identity、VNet統合、Key Vault連携
2025年の最新機能
- Flex Consumption Plan: 最大1,000インスタンス、4GB メモリ、VNet統合
- 冷却開始改善: Project Teleportによる15倍の高速化
- 新言語サポート: Go、Rust言語の正式対応
- 新トリガータイプ: Kafka、Event Grid トリガーの追加
- AI統合強化: Azure OpenAI、Cognitive Services深い統合
メリット・デメリット
メリット
- Microsoft エコシステムとの完全統合による開発効率向上
- 豊富な言語サポートと柔軟な開発環境選択
- エンタープライズ級のセキュリティとコンプライアンス機能
- Durable Functions による複雑なワークフロー処理能力
- Visual Studio/VS Codeによる優れた開発・デバッグ体験
- 豊富なAzureサービス連携によるフルスタック開発支援
- 透明性の高い料金体系と無料利用枠
デメリット
- Azureエコシステムへの依存とベンダーロックイン
- 冷却開始時間が他のプラットフォームより長い場合がある
- 複雑な設定と豊富なオプションによる学習コストの高さ
- 他のクラウドプラットフォームとの互換性の制限
- リソース制限による大規模処理の制約
- Windows中心の開発文化によるLinux/macOS開発者への障壁
参考ページ
書き方の例
セットアップと基本設定
# Azure Functions Core Toolsのインストール
npm install -g azure-functions-core-tools@4 --unsafe-perm true
# Azure CLIのインストール(Windows)
winget install Microsoft.AzureCLI
# Azure CLIのインストール(macOS)
brew install azure-cli
# Azure CLIのインストール(Linux)
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
# Azureアカウントへのログイン
az login
# 新しいFunctionアプリプロジェクトの作成
func init MyFunctionApp --worker-runtime node
cd MyFunctionApp
# 新しい関数の作成
func new --name HttpExample --template "HTTP trigger"
# ローカル開発サーバーの起動
func start
# Azureへのデプロイ(リソースグループとストレージアカウントが必要)
az group create --name myResourceGroup --location japaneast
az storage account create --name mystorageaccount --location japaneast --resource-group myResourceGroup --sku Standard_LRS
az functionapp create --resource-group myResourceGroup --consumption-plan-location japaneast --runtime node --runtime-version 18 --functions-version 4 --name MyFunctionApp --storage-account mystorageaccount
# アプリケーションのデプロイ
func azure functionapp publish MyFunctionApp
// src/functions/httpExample.js - JavaScript HTTP関数
const { app } = require('@azure/functions');
app.http('httpExample', {
methods: ['GET', 'POST'],
authLevel: 'anonymous',
handler: async (request, context) => {
context.log('JavaScript HTTP trigger function processed a request.');
// リクエストデータの取得
const name = request.query.get('name') || (await request.json())?.name || 'World';
const method = request.method;
const url = request.url;
const headers = request.headers;
// レスポンス作成
const responseMessage = {
message: `Hello, ${name}! This HTTP triggered function executed successfully.`,
timestamp: new Date().toISOString(),
method: method,
url: url,
userAgent: headers.get('user-agent'),
correlationId: context.invocationId
};
return {
status: 200,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify(responseMessage, null, 2)
};
}
});
HTTP APIとルーティング
# function_app.py - Python HTTP Functions
import azure.functions as func
import logging
import json
from datetime import datetime
app = func.FunctionApp(http_auth_level=func.AuthLevel.FUNCTION)
@app.route(route="users", methods=["GET", "POST"])
def users_api(req: func.HttpRequest) -> func.HttpResponse:
logging.info('Python HTTP trigger function processed a request.')
try:
if req.method == "GET":
# GETリクエストの処理
user_id = req.params.get('id')
if user_id:
# 特定のユーザー情報を返す
user = {
"id": user_id,
"name": f"User {user_id}",
"email": f"user{user_id}@example.com",
"created_at": datetime.utcnow().isoformat()
}
return func.HttpResponse(
json.dumps(user),
status_code=200,
mimetype="application/json"
)
else:
# 全ユーザー一覧を返す
users = [
{"id": i, "name": f"User {i}", "email": f"user{i}@example.com"}
for i in range(1, 6)
]
return func.HttpResponse(
json.dumps({"users": users, "total": len(users)}),
status_code=200,
mimetype="application/json"
)
elif req.method == "POST":
# POSTリクエストの処理
try:
req_body = req.get_json()
# 新しいユーザーの作成
new_user = {
"id": 999, # 実際の実装では適切なID生成
"name": req_body.get('name'),
"email": req_body.get('email'),
"created_at": datetime.utcnow().isoformat()
}
return func.HttpResponse(
json.dumps({
"message": "User created successfully",
"user": new_user
}),
status_code=201,
mimetype="application/json"
)
except ValueError:
return func.HttpResponse(
json.dumps({"error": "Invalid JSON"}),
status_code=400,
mimetype="application/json"
)
except Exception as e:
logging.error(f"Error processing request: {str(e)}")
return func.HttpResponse(
json.dumps({"error": "Internal server error"}),
status_code=500,
mimetype="application/json"
)
@app.route(route="health")
def health_check(req: func.HttpRequest) -> func.HttpResponse:
health_info = {
"status": "healthy",
"timestamp": datetime.utcnow().isoformat(),
"version": "1.0.0",
"environment": "production"
}
return func.HttpResponse(
json.dumps(health_info),
status_code=200,
mimetype="application/json"
)
データベース統合とデータ処理
// UserFunction.cs - C# Cosmos DB統合
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Azure.Cosmos;
using Newtonsoft.Json;
public class User
{
public string id { get; set; }
public string name { get; set; }
public string email { get; set; }
public DateTime createdAt { get; set; }
}
public class UserFunction
{
private readonly CosmosClient _cosmosClient;
private readonly Container _container;
public UserFunction(CosmosClient cosmosClient)
{
_cosmosClient = cosmosClient;
_container = _cosmosClient.GetContainer("MyDatabase", "Users");
}
[FunctionName("CreateUser")]
public async Task<IActionResult> CreateUser(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = "users")] HttpRequest req,
ILogger log)
{
log.LogInformation("CreateUser function processed a request.");
try
{
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
var user = new User
{
id = Guid.NewGuid().ToString(),
name = data?.name,
email = data?.email,
createdAt = DateTime.UtcNow
};
// Cosmos DBに保存
await _container.CreateItemAsync(user, new PartitionKey(user.id));
return new OkObjectResult(new
{
message = "User created successfully",
user = user
});
}
catch (Exception ex)
{
log.LogError($"Error creating user: {ex.Message}");
return new BadRequestObjectResult(new { error = "Failed to create user" });
}
}
[FunctionName("GetUsers")]
public async Task<IActionResult> GetUsers(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "users")] HttpRequest req,
ILogger log)
{
log.LogInformation("GetUsers function processed a request.");
try
{
var queryDefinition = new QueryDefinition("SELECT * FROM c ORDER BY c.createdAt DESC");
var query = _container.GetItemQueryIterator<User>(queryDefinition);
var users = new List<User>();
while (query.HasMoreResults)
{
var response = await query.ReadNextAsync();
users.AddRange(response);
}
return new OkObjectResult(new
{
users = users,
total = users.Count
});
}
catch (Exception ex)
{
log.LogError($"Error getting users: {ex.Message}");
return new BadRequestObjectResult(new { error = "Failed to get users" });
}
}
[FunctionName("ProcessBlobStorage")]
public async Task ProcessBlobStorage(
[BlobTrigger("uploads/{name}", Connection = "AzureWebJobsStorage")] Stream myBlob,
string name,
ILogger log)
{
log.LogInformation($"C# Blob trigger function processed blob\n Name:{name} \n Size: {myBlob.Length} Bytes");
try
{
// ファイル内容の処理
using var reader = new StreamReader(myBlob);
var content = await reader.ReadToEndAsync();
// ファイル情報をCosmos DBに保存
var fileInfo = new
{
id = Guid.NewGuid().ToString(),
fileName = name,
size = myBlob.Length,
contentPreview = content.Substring(0, Math.Min(content.Length, 100)),
processedAt = DateTime.UtcNow
};
await _container.CreateItemAsync(fileInfo, new PartitionKey(fileInfo.id));
log.LogInformation($"File {name} processed and logged to database.");
}
catch (Exception ex)
{
log.LogError($"Error processing blob {name}: {ex.Message}");
}
}
}
認証とセキュリティ
// AuthenticationFunction.cs - JWT認証システム
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using System.Threading.Tasks;
using BCrypt.Net;
public class AuthenticationFunction
{
private readonly string _jwtSecret = Environment.GetEnvironmentVariable("JWT_SECRET");
private readonly int _jwtExpiryInDays = 7;
[FunctionName("Login")]
public async Task<IActionResult> Login(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "auth/login")] HttpRequest req,
ILogger log)
{
log.LogInformation("Login function processed a request.");
try
{
var requestBody = await req.ReadAsStringAsync();
dynamic data = Newtonsoft.Json.JsonConvert.DeserializeObject(requestBody);
string email = data?.email;
string password = data?.password;
// ユーザー認証(実際の実装ではデータベースから取得)
var user = await AuthenticateUser(email, password);
if (user == null)
{
return new UnauthorizedObjectResult(new { error = "Invalid credentials" });
}
// JWTトークンの生成
var token = GenerateJwtToken(user);
return new OkObjectResult(new
{
token = token,
user = new
{
id = user.Id,
email = user.Email,
name = user.Name
},
expiresIn = TimeSpan.FromDays(_jwtExpiryInDays).TotalSeconds
});
}
catch (Exception ex)
{
log.LogError($"Login error: {ex.Message}");
return new BadRequestObjectResult(new { error = "Login failed" });
}
}
[FunctionName("ValidateToken")]
public IActionResult ValidateToken(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "auth/validate")] HttpRequest req,
ILogger log)
{
try
{
var token = req.Headers["Authorization"].ToString().Replace("Bearer ", "");
var principal = ValidateJwtToken(token);
if (principal == null)
{
return new UnauthorizedObjectResult(new { error = "Invalid token" });
}
return new OkObjectResult(new
{
valid = true,
user = new
{
id = principal.FindFirst("sub")?.Value,
email = principal.FindFirst("email")?.Value,
name = principal.FindFirst("name")?.Value
}
});
}
catch (Exception ex)
{
log.LogError($"Token validation error: {ex.Message}");
return new UnauthorizedObjectResult(new { error = "Invalid token" });
}
}
private string GenerateJwtToken(User user)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_jwtSecret);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim("sub", user.Id),
new Claim("email", user.Email),
new Claim("name", user.Name)
}),
Expires = DateTime.UtcNow.AddDays(_jwtExpiryInDays),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
private ClaimsPrincipal ValidateJwtToken(string token)
{
try
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_jwtSecret);
tokenHandler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,
ClockSkew = TimeSpan.Zero
}, out SecurityToken validatedToken);
var jwtToken = (JwtSecurityToken)validatedToken;
return new ClaimsPrincipal(new ClaimsIdentity(jwtToken.Claims));
}
catch
{
return null;
}
}
private async Task<User> AuthenticateUser(string email, string password)
{
// 実際の実装ではデータベースからユーザー情報を取得
// ここではサンプルデータ
var hashedPassword = BCrypt.Net.BCrypt.HashPassword("password123");
if (email == "[email protected]" && BCrypt.Net.BCrypt.Verify(password, hashedPassword))
{
return new User
{
Id = "user123",
Email = email,
Name = "Test User"
};
}
return null;
}
}
イベント駆動アーキテクチャ
# durable_functions.py - Durable Functions ワークフロー
import azure.functions as func
import azure.durable_functions as df
import json
import logging
from datetime import datetime, timedelta
# Orchestrator Function - ワークフロー全体の制御
@df.orchestrator_trigger(context_name="context")
def process_order_orchestrator(context: df.DurableOrchestrationContext):
"""
注文処理ワークフローのオーケストレーター
"""
try:
# 入力データの取得
order_data = context.get_input()
order_id = order_data.get("orderId")
logging.info(f"Starting order processing for order: {order_id}")
# ステップ1: 在庫確認
inventory_result = yield context.call_activity("check_inventory", order_data)
if not inventory_result["available"]:
return {"status": "failed", "reason": "insufficient_inventory"}
# ステップ2: 支払い処理
payment_result = yield context.call_activity("process_payment", order_data)
if not payment_result["success"]:
# 在庫の復旧
yield context.call_activity("restore_inventory", order_data)
return {"status": "failed", "reason": "payment_failed"}
# ステップ3: 配送準備(並行実行)
shipping_tasks = [
context.call_activity("prepare_shipping", order_data),
context.call_activity("send_confirmation_email", order_data)
]
results = yield context.task_all(shipping_tasks)
# ステップ4: 配送開始の遅延(タイマー使用)
shipping_date = context.current_utc_datetime + timedelta(hours=2)
yield context.create_timer(shipping_date)
# ステップ5: 配送開始
shipping_result = yield context.call_activity("start_shipping", order_data)
return {
"status": "completed",
"orderId": order_id,
"shippingTrackingNumber": shipping_result["trackingNumber"],
"completedAt": context.current_utc_datetime.isoformat()
}
except Exception as e:
logging.error(f"Order processing failed: {str(e)}")
return {"status": "error", "message": str(e)}
# Activity Functions - 個別のタスク実行
@df.activity_trigger(input_name="order_data")
def check_inventory(order_data: dict) -> dict:
"""在庫確認"""
logging.info(f"Checking inventory for order: {order_data['orderId']}")
# 実際の実装では在庫データベースをチェック
items = order_data.get("items", [])
for item in items:
# 在庫確認ロジック(サンプル)
if item["quantity"] > 10: # 仮の在庫制限
return {"available": False, "item": item["productId"]}
return {"available": True}
@df.activity_trigger(input_name="order_data")
def process_payment(order_data: dict) -> dict:
"""支払い処理"""
logging.info(f"Processing payment for order: {order_data['orderId']}")
# 実際の実装では支払いゲートウェイとの連携
payment_info = order_data.get("payment", {})
amount = order_data.get("totalAmount", 0)
# サンプル支払い処理
if amount > 0 and payment_info.get("cardNumber"):
return {
"success": True,
"transactionId": f"txn_{order_data['orderId']}_{datetime.utcnow().strftime('%Y%m%d%H%M%S')}"
}
return {"success": False, "error": "Invalid payment information"}
@df.activity_trigger(input_name="order_data")
def send_confirmation_email(order_data: dict) -> dict:
"""確認メール送信"""
logging.info(f"Sending confirmation email for order: {order_data['orderId']}")
# 実際の実装ではメール送信サービスを使用
customer_email = order_data.get("customerEmail")
# SendGridやAzure Communication Servicesなどを使用
return {
"sent": True,
"email": customer_email,
"sentAt": datetime.utcnow().isoformat()
}
# HTTP Trigger - ワークフローの開始
@app.route(route="orders", methods=["POST"])
@df.durable_client_input(client_name="client")
async def start_order_processing(req: func.HttpRequest, client: df.DurableOrchestrationClient) -> func.HttpResponse:
try:
req_body = req.get_json()
order_id = req_body.get("orderId")
# オーケストレーションの開始
instance_id = await client.start_new("process_order_orchestrator", None, req_body)
logging.info(f"Started orchestration with ID = {instance_id}")
# 管理URL(ステータス確認用)の生成
management_urls = client.create_check_status_response(req, instance_id)
return func.HttpResponse(
json.dumps({
"instanceId": instance_id,
"orderId": order_id,
"status": "started",
"statusQueryGetUri": management_urls.get_data()["statusQueryGetUri"]
}),
status_code=202,
mimetype="application/json"
)
except Exception as e:
logging.error(f"Error starting order processing: {str(e)}")
return func.HttpResponse(
json.dumps({"error": "Failed to start order processing"}),
status_code=500,
mimetype="application/json"
)
# Event Grid Trigger - 2025年新機能
@app.event_grid_trigger(arg_name="event")
def handle_event_grid(event: func.EventGridEvent):
"""Event Grid イベントの処理"""
logging.info(f"Received Event Grid event: {event.event_type}")
try:
event_data = event.get_json()
if event.event_type == "Microsoft.Storage.BlobCreated":
# Blob作成イベントの処理
blob_url = event_data["url"]
blob_name = event_data["subject"].split("/")[-1]
logging.info(f"New blob created: {blob_name}")
# ファイル処理ロジック(例:画像リサイズ、テキスト解析など)
elif event.event_type == "Microsoft.EventGrid.SubscriptionValidationEvent":
# サブスクリプション検証
validation_code = event_data["validationCode"]
return {"validationResponse": validation_code}
except Exception as e:
logging.error(f"Error processing Event Grid event: {str(e)}")
監視とパフォーマンス最適化
// MonitoringFunction.cs - カスタムメトリクスと監視
using System;
using System.Threading.Tasks;
using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.DataContracts;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using System.Diagnostics;
using System.Collections.Generic;
public class MonitoringFunction
{
private readonly TelemetryClient _telemetryClient;
public MonitoringFunction(TelemetryClient telemetryClient)
{
_telemetryClient = telemetryClient;
}
[FunctionName("PerformanceMonitoring")]
public async Task<IActionResult> PerformanceMonitoring(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "metrics")] HttpRequest req,
ILogger log)
{
var stopwatch = Stopwatch.StartNew();
try
{
// カスタムメトリクスの収集
var metrics = new Dictionary<string, object>
{
["timestamp"] = DateTime.UtcNow,
["environment"] = Environment.GetEnvironmentVariable("AZURE_FUNCTIONS_ENVIRONMENT") ?? "Development",
["functionApp"] = Environment.GetEnvironmentVariable("WEBSITE_SITE_NAME"),
["version"] = "1.0.0"
};
// Application Insightsにカスタムイベントを送信
_telemetryClient.TrackEvent("HealthCheck", new Dictionary<string, string>
{
["Status"] = "Healthy",
["Environment"] = metrics["environment"].ToString()
});
// パフォーマンスカウンターの収集
var performanceMetrics = new
{
memory_usage = GC.GetTotalMemory(false),
active_requests = GetActiveRequestCount(),
uptime_seconds = stopwatch.Elapsed.TotalSeconds
};
// カスタムメトリクスの送信
_telemetryClient.TrackMetric("MemoryUsage", performanceMetrics.memory_usage);
_telemetryClient.TrackMetric("ActiveRequests", performanceMetrics.active_requests);
stopwatch.Stop();
return new OkObjectResult(new
{
status = "healthy",
metrics = metrics,
performance = performanceMetrics,
execution_time_ms = stopwatch.ElapsedMilliseconds
});
}
catch (Exception ex)
{
log.LogError($"Health check failed: {ex.Message}");
// エラーメトリクスの送信
_telemetryClient.TrackException(ex, new Dictionary<string, string>
{
["FunctionName"] = "PerformanceMonitoring",
["ErrorType"] = ex.GetType().Name
});
return new ObjectResult(new { status = "unhealthy", error = ex.Message })
{
StatusCode = 500
};
}
}
[FunctionName("CustomLogging")]
public async Task<IActionResult> CustomLogging(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = "logs")] HttpRequest req,
ILogger log)
{
try
{
var requestBody = await req.ReadAsStringAsync();
dynamic data = Newtonsoft.Json.JsonConvert.DeserializeObject(requestBody);
string level = data?.level ?? "Info";
string message = data?.message ?? "No message";
string source = data?.source ?? "Unknown";
// 構造化ログの記録
using (log.BeginScope(new Dictionary<string, object>
{
["Source"] = source,
["CorrelationId"] = Guid.NewGuid().ToString(),
["Timestamp"] = DateTime.UtcNow
}))
{
switch (level.ToLower())
{
case "error":
log.LogError("Custom Error: {Message}", message);
break;
case "warning":
log.LogWarning("Custom Warning: {Message}", message);
break;
case "info":
default:
log.LogInformation("Custom Info: {Message}", message);
break;
}
}
// Application Insightsにカスタムイベント送信
_telemetryClient.TrackEvent("CustomLog", new Dictionary<string, string>
{
["Level"] = level,
["Source"] = source,
["Message"] = message
});
return new OkObjectResult(new { status = "logged", level = level });
}
catch (Exception ex)
{
log.LogError($"Custom logging failed: {ex.Message}");
return new BadRequestObjectResult(new { error = "Logging failed" });
}
}
[FunctionName("AlertingSystem")]
public async Task AlertingSystem(
[TimerTrigger("0 */5 * * * *")] TimerInfo myTimer, // 5分ごとに実行
ILogger log)
{
log.LogInformation($"Alerting system check started at: {DateTime.Now}");
try
{
// システム健全性の確認
var healthChecks = await PerformHealthChecks();
foreach (var check in healthChecks)
{
if (!check.IsHealthy)
{
// アラートの送信
await SendAlert(check, log);
// Application Insightsにアラートイベント送信
_telemetryClient.TrackEvent("HealthCheckAlert", new Dictionary<string, string>
{
["CheckName"] = check.Name,
["Status"] = "Unhealthy",
["Details"] = check.Details
});
}
}
}
catch (Exception ex)
{
log.LogError($"Alerting system error: {ex.Message}");
}
}
private async Task<List<HealthCheckResult>> PerformHealthChecks()
{
var results = new List<HealthCheckResult>();
// データベース接続チェック
results.Add(await CheckDatabaseConnection());
// 外部API接続チェック
results.Add(await CheckExternalAPIConnection());
// ストレージアカウント接続チェック
results.Add(await CheckStorageConnection());
return results;
}
private async Task<HealthCheckResult> CheckDatabaseConnection()
{
try
{
// データベース接続テスト(例:Cosmos DB)
// 実際の実装では適切なデータベースクライアントを使用
await Task.Delay(100); // シミュレーション
return new HealthCheckResult
{
Name = "Database",
IsHealthy = true,
Details = "Connection successful"
};
}
catch (Exception ex)
{
return new HealthCheckResult
{
Name = "Database",
IsHealthy = false,
Details = ex.Message
};
}
}
private async Task<HealthCheckResult> CheckExternalAPIConnection()
{
try
{
// 外部API接続テスト
using var httpClient = new System.Net.Http.HttpClient();
httpClient.Timeout = TimeSpan.FromSeconds(10);
var response = await httpClient.GetAsync("https://api.example.com/health");
return new HealthCheckResult
{
Name = "ExternalAPI",
IsHealthy = response.IsSuccessStatusCode,
Details = $"Status: {response.StatusCode}"
};
}
catch (Exception ex)
{
return new HealthCheckResult
{
Name = "ExternalAPI",
IsHealthy = false,
Details = ex.Message
};
}
}
private async Task<HealthCheckResult> CheckStorageConnection()
{
try
{
// Azure Storage接続テスト
await Task.Delay(50); // シミュレーション
return new HealthCheckResult
{
Name = "Storage",
IsHealthy = true,
Details = "Connection successful"
};
}
catch (Exception ex)
{
return new HealthCheckResult
{
Name = "Storage",
IsHealthy = false,
Details = ex.Message
};
}
}
private async Task SendAlert(HealthCheckResult check, ILogger log)
{
// アラート送信(例:Logic Apps、メール、Slackなど)
log.LogWarning($"ALERT: {check.Name} health check failed - {check.Details}");
// 実際の実装では適切なアラート送信機能を実装
await Task.CompletedTask;
}
private int GetActiveRequestCount()
{
// 実際の実装では適切なパフォーマンスカウンターを使用
return new Random().Next(1, 10); // サンプル値
}
}
public class HealthCheckResult
{
public string Name { get; set; }
public bool IsHealthy { get; set; }
public string Details { get; set; }
}