Azure Functions

サーバーレスMicrosoft Azure.NETPythonJavaScriptJava

プラットフォーム

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; }
}