Skip to main content

aigbb-observability

OpenTelemetry and Application Insights observability patterns for Azure Container Apps. Cross-language instrumentation for Python (FastAPI, Gradio, Streamlit), TypeScript (Express, React), and .NET (ASP.NET Core). Covers tracing, structured logging, metrics, Azure Monitor exporter, health check endpoints, and telemetry configuration. Use when setting up monitoring, adding Application Insights, configuring OpenTelemetry, implementing health checks, or setting up structured logging. Triggers on OpenTelemetry, Application Insights, tracing, logging, metrics, health check, Azure Monitor, observability, telemetry, structured logging, log level, Winston, Serilog, Python logging.

インストールへ移動

ソース情報

リポジトリ
aiappsgbb/template
ソースの最終更新活動
2026年2月26日 21:12
検出された SKILL.md の言語
英語
スター
0
フォーク
0

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
aigbb-observability
description
OpenTelemetry and Application Insights observability patterns for Azure Container Apps. Cross-language instrumentation for Python (FastAPI, Gradio, Streamlit), TypeScript (Express, React), and .NET (ASP.NET Core). Covers tracing, structured logging, metrics, Azure Monitor exporter, health check endpoints, and telemetry configuration. Use when setting up monitoring, adding Application Insights, configuring OpenTelemetry, implementing health checks, or setting up structured logging. Triggers on OpenTelemetry, Application Insights, tracing, logging, metrics, health check, Azure Monitor, observability, telemetry, structured logging, log level, Winston, Serilog, Python logging.
# Observability & Telemetry Patterns Production-ready observability for Azure Container Apps using OpenTelemetry and Application Insights. Every application in this template includes structured logging, distributed tracing, and health checks. > **Community skills**: For additional monitoring skills, see the [microsoft/skills](https://github.com/microsoft/skills) community repository. --- ## Core Requirements Every application MUST have: 1. **Structured logging** — JSON-formatted, never `print()` / `console.log()` 2. **Health check endpoint** — `GET /health` returning 200 OK 3. **OpenTelemetry tracing** — Distributed traces exported to Application Insights 4. **Configuration via environment** — `APPLICATION_INSIGHTS_CONNECTION_STRING` and `LOG_LEVEL` --- ## 1. Python — FastAPI / Gunicorn ### Dependencies (pyproject.toml) ```toml dependencies = [ "opentelemetry-api>=1.27.0,<2.0.0", "opentelemetry-sdk>=1.27.0,<2.0.0", "opentelemetry-instrumentation-fastapi>=0.48.0,<0.49.0", "opentelemetry-instrumentation-httpx>=0.48.0,<0.49.0", "azure-monitor-opentelemetry-exporter>=1.0.0,<2.0.0", ] ``` ### Tracing Setup (utils/tracing.py) ```python import logging from opentelemetry import trace from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor from opentelemetry.sdk.resources import Resource from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor from azure.monitor.opentelemetry.exporter import AzureMonitorTraceExporter logger = logging.getLogger(__name__) def setup_tracing( service_name: str, service_version: str = "1.0.0", connection_string: str | None = None, ) -> None: """Initialize OpenTelemetry tracing with Azure Monitor export.""" resource = Resource.create({ "service.name": service_name, "service.version": service_version, }) provider = TracerProvider(resource=resource) if connection_string: exporter = AzureMonitorTraceExporter( connection_string=connection_string ) provider.add_span_processor(BatchSpanProcessor(exporter)) logger.info("Azure Monitor tracing enabled") else: logger.warning("No APPLICATION_INSIGHTS_CONNECTION_STRING — tracing to console only") trace.set_tracer_provider(provider) # Auto-instrument frameworks FastAPIInstrumentor.instrument() HTTPXClientInstrumentor.instrument() ``` ### Structured Logging (utils/logging_config.py) ```python import logging import json import sys from datetime import datetime, timezone class JsonFormatter(logging.Formatter): """JSON-formatted log output for production environments.""" def format(self, record: logging.LogRecord) -> str: log_data = { "timestamp": datetime.now(timezone.utc).isoformat(), "level": record.levelname, "logger": record.name, "message": record.getMessage(), } if record.exc_info and record.exc_info[0] is not None: log_data["exception"] = self.formatException(record.exc_info) return json.dumps(log_data) def setup_logging(log_level: str = "INFO") -> None: """Configure structured logging for the application.""" handler = logging.StreamHandler(sys.stdout) handler.setFormatter(JsonFormatter()) root_logger = logging.getLogger() root_logger.setLevel(getattr(logging, log_level.upper(), logging.INFO)) root_logger.handlers = [handler] # Quiet noisy libraries logging.getLogger("azure").setLevel(logging.WARNING) logging.getLogger("httpx").setLevel(logging.WARNING) logging.getLogger("uvicorn.access").setLevel(logging.WARNING) ``` ### Health Check (main.py) ```python from fastapi import FastAPI app = FastAPI() @app.get("/health") async def health_check(): """Health check endpoint for container orchestration.""" return {"status": "healthy", "service": "my-app"} ``` ### Application Startup (main.py) ```python import logging import os from contextlib import asynccontextmanager from fastapi import FastAPI from utils.tracing import setup_tracing from utils.logging_config import setup_logging @asynccontextmanager async def lifespan(app: FastAPI): setup_logging(os.getenv("LOG_LEVEL", "INFO")) setup_tracing( service_name="my-app", connection_string=os.getenv("APPLICATION_INSIGHTS_CONNECTION_STRING"), ) logger = logging.getLogger(__name__) logger.info("Application started") yield logger.info("Application shutting down") app = FastAPI(lifespan=lifespan) ``` --- ## 2. Python — Gradio Gradio applications use the same tracing/logging modules. Key difference: Gradio has its own server, so instrument with a custom middleware. ```python import gradio as gr import logging from utils.logging_config import setup_logging from utils.tracing import setup_tracing setup_logging(os.getenv("LOG_LEVEL", "INFO")) setup_tracing( service_name="my-gradio-app", connection_string=os.getenv("APPLICATION_INSIGHTS_CONNECTION_STRING"), ) logger = logging.getLogger(__name__) demo = gr.Blocks() with demo: gr.Markdown("# My App") # ... components ... if __name__ == "__main__": logger.info("Starting Gradio application") demo.launch( server_name="0.0.0.0", server_port=int(os.getenv("GRADIO_SERVER_PORT", "80")), ) ``` --- ## 3. Python — Streamlit Streamlit runs its own web server. Configure logging early in the entry point. ```python # streamlit_app.py import streamlit as st import logging import os from utils.logging_config import setup_logging setup_logging(os.getenv("LOG_LEVEL", "INFO")) logger = logging.getLogger(__name__) st.set_page_config(page_title="My App", layout="wide") # Health check: Streamlit exposes /_stcore/health automatically logger.info("Streamlit application loaded") ``` **Streamlit health check**: Built-in at `/_stcore/health`. No custom endpoint needed. ```dockerfile HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ CMD curl -f http://localhost:80/_stcore/health || exit 1 ``` --- ## 4. TypeScript — Express / Node.js ### Dependencies (package.json) ```json { "dependencies": { "@azure/monitor-opentelemetry": "^1.7.0", "@opentelemetry/api": "^1.9.0", "@opentelemetry/sdk-node": "^0.54.0", "@opentelemetry/instrumentation-express": "^0.42.0", "winston": "^3.14.0" } } ``` ### Tracing Setup (utils/tracing.ts) ```typescript import { useAzureMonitor, AzureMonitorOpenTelemetryOptions } from "@azure/monitor-opentelemetry"; export function setupTracing(connectionString?: string): void { if (!connectionString) { console.warn("No APPLICATION_INSIGHTS_CONNECTION_STRING — tracing disabled"); return; } const options: AzureMonitorOpenTelemetryOptions = { azureMonitorExporterOptions: { connectionString }, instrumentationOptions: { http: { enabled: true }, }, }; useAzureMonitor(options); } ``` ### Structured Logging (utils/logger.ts) ```typescript import winston from "winston"; const logger = winston.createLogger({ level: process.env.LOG_LEVEL?.toLowerCase() || "info", format: winston.format.combine( winston.format.timestamp(), winston.format.json(), ), transports: [new winston.transports.Console()], }); // Suppress verbose library logs logger.on("error", () => {}); export default logger; ``` ### Health Check (routes/health.ts) ```typescript import { Router, Request, Response } from "express"; const router = Router(); router.get("/health", (_req: Request, res: Response) => { res.json({ status: "healthy", service: "my-node-app" }); }); export default router; ``` --- ## 5. TypeScript — React (Client-side) ### Dependencies (package.json) ```json { "dependencies": { "@microsoft/applicationinsights-react-js": "^17.3.0", "@microsoft/applicationinsights-web": "^3.3.0" } } ``` ### Telemetry Service (services/telemetry.ts) ```typescript import { ApplicationInsights } from "@microsoft/applicationinsights-web"; import { ReactPlugin } from "@microsoft/applicationinsights-react-js"; const reactPlugin = new ReactPlugin(); let appInsights: ApplicationInsights | null = null; export function initializeTelemetry(connectionString: string): void { if (!connectionString || appInsights) return; appInsights = new ApplicationInsights({ config: { connectionString, extensions: [reactPlugin], enableAutoRouteTracking: true, enableCorsCorrelation: true, }, }); appInsights.loadAppInsights(); } export function trackEvent(name: string, properties?: Record<string, string>): void { appInsights?.trackEvent({ name }, properties); } export function trackException(error: Error): void { appInsights?.trackException({ exception: error }); } export { reactPlugin }; ``` ### Structured Logger (utils/logger.ts) ```typescript type LogLevel = "debug" | "info" | "warn" | "error"; const LOG_LEVELS: Record<LogLevel, number> = { debug: 0, info: 1, warn: 2, error: 3 }; const currentLevel = (import.meta.env.VITE_LOG_LEVEL?.toLowerCase() || "info") as LogLevel; function shouldLog(level: LogLevel): boolean { return LOG_LEVELS[level] >= LOG_LEVELS[currentLevel]; } export const logger = { debug: (msg: string, data?: unknown) => shouldLog("debug") && console.debug(JSON.stringify({ level: "DEBUG", msg, data, ts: new Date().toISOString() })), info: (msg: string, data?: unknown) => shouldLog("info") && console.info(JSON.stringify({ level: "INFO", msg, data, ts: new Date().toISOString() })), warn: (msg: string, data?: unknown) => shouldLog("warn") && console.warn(JSON.stringify({ level: "WARN", msg, data, ts: new Date().toISOString() })), error: (msg: string, data?: unknown) => shouldLog("error") && console.error(JSON.stringify({ level: "ERROR", msg, data, ts: new Date().toISOString() })), }; ``` --- ## 6. .NET — ASP.NET Core ### Dependencies (.csproj) ```xml <PackageReference Include="Azure.Monitor.OpenTelemetry.AspNetCore" Version="1.2.0" /> <PackageReference Include="Serilog.AspNetCore" Version="8.0.0" /> <PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" /> ``` ### Program.cs Setup ```csharp using Serilog; using Azure.Monitor.OpenTelemetry.AspNetCore; var builder = WebApplication.CreateBuilder(args); // Structured logging with Serilog builder.Host.UseSerilog((context, configuration) => configuration .ReadFrom.Configuration(context.Configuration) .WriteTo.Console(outputTemplate: "{Timestamp:yyyy-MM-ddTHH:mm:ss.fffZ} [{Level:u3}] {Message:lj}{NewLine}{Exception}") ); // OpenTelemetry with Azure Monitor builder.Services.AddOpenTelemetry() .UseAzureMonitor();
GitHubで見る
この SKILL.md は非常に大きいため、SkillsMP では最初のセクションだけを表示しています。 GitHubで見る