{"id":49308523,"url":"https://github.com/yeongseon/azure-functions-logging-python","last_synced_at":"2026-06-07T07:02:22.080Z","repository":{"id":343457440,"uuid":"1177811139","full_name":"yeongseon/azure-functions-logging-python","owner":"yeongseon","description":"Invocation-aware structured logging for Azure Functions Python v2 — Part of the Azure Functions Python DX Toolkit","archived":false,"fork":false,"pushed_at":"2026-04-17T14:08:21.000Z","size":1168,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-17T14:28:40.363Z","etag":null,"topics":["azure","azure-functions","dx-toolkit","logging","python","serverless"],"latest_commit_sha":null,"homepage":"https://yeongseon.github.io/azure-functions-logging-python/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yeongseon.png","metadata":{"files":{"readme":"README.ja.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":"SUPPORT.md","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-03-10T11:53:10.000Z","updated_at":"2026-04-17T14:07:03.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/yeongseon/azure-functions-logging-python","commit_stats":null,"previous_names":["yeongseon/azure-functions-logging","yeongseon/azure-functions-logging-python"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/yeongseon/azure-functions-logging-python","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yeongseon%2Fazure-functions-logging-python","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yeongseon%2Fazure-functions-logging-python/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yeongseon%2Fazure-functions-logging-python/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yeongseon%2Fazure-functions-logging-python/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yeongseon","download_url":"https://codeload.github.com/yeongseon/azure-functions-logging-python/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yeongseon%2Fazure-functions-logging-python/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32294591,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T09:34:17.070Z","status":"ssl_error","status_checked_at":"2026-04-26T09:34:00.993Z","response_time":129,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["azure","azure-functions","dx-toolkit","logging","python","serverless"],"created_at":"2026-04-26T11:01:27.936Z","updated_at":"2026-06-07T07:02:22.072Z","avatar_url":"https://github.com/yeongseon.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Azure Functions Logging\n\n\u003e **Azure Functions Python DX Toolkit** の一部 — [azure-functions-cookbook-python](https://github.com/yeongseon/azure-functions-cookbook-python) によりドッグフーディング検証済み。\n\n[![PyPI](https://img.shields.io/pypi/v/azure-functions-logging.svg)](https://pypi.org/project/azure-functions-logging/)\n[![Python Version](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-blue)](https://pypi.org/project/azure-functions-logging/)\n[![CI](https://github.com/yeongseon/azure-functions-logging-python/actions/workflows/ci-test.yml/badge.svg)](https://github.com/yeongseon/azure-functions-logging-python/actions/workflows/ci-test.yml)\n[![Release](https://github.com/yeongseon/azure-functions-logging-python/actions/workflows/publish-pypi.yml/badge.svg)](https://github.com/yeongseon/azure-functions-logging-python/actions/workflows/publish-pypi.yml)\n[![Security Scans](https://github.com/yeongseon/azure-functions-logging-python/actions/workflows/security.yml/badge.svg)](https://github.com/yeongseon/azure-functions-logging-python/actions/workflows/security.yml)\n[![codecov](https://codecov.io/gh/yeongseon/azure-functions-logging-python/branch/main/graph/badge.svg)](https://codecov.io/gh/yeongseon/azure-functions-logging-python)\n[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://pre-commit.com/)\n[![Docs](https://img.shields.io/badge/docs-gh--pages-blue)](https://yeongseon.github.io/azure-functions-logging-python/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n\n他の言語で読む: [English](README.md) | [한국어](README.ko.md) | [简体中文](README.zh-CN.md)\n\n**Azure Functions Python v2 のための、呼び出し（invocation）認識可能なオブザーバビリティ。**\n`invocation_id` を表面化し、コールドスタートを検出し、`host.json` の設定不備を警告し、Application Insights にすぐに使える構造化ログを出力します — Python 標準の `logging` を置き換えることなく。\n\n---\n\n**Azure Functions Python DX Toolkit** の一部\n→ FastAPI のような開発体験を Azure Functions にもたらします。\n\n## なぜ存在するのか\n\nAzure Functions Python のロギングには、汎用的なロギングライブラリでは扱えない固有の失敗モードがあります:\n\n| 問題 | 何が起こるか | このライブラリ |\n|------|-------------|---------------|\n| `host.json` のログレベル衝突 | `INFO` ログが Azure で静かに消える | 起動時に検出して警告 |\n| ログに `invocation_id` がない | 特定の実行とログを関連付けられない | `context` オブジェクトから自動注入 |\n| コールドスタートが見えない | 新しい worker インスタンス起動時にシグナルなし | 最初の `inject_context()` で自動検出 |\n| サードパーティロガーがうるさい | `azure-core`, `urllib3` が Application Insights を埋め尽くす | `SamplingFilter` / `RedactionFilter` |\n| ローカルとクラウドの出力不一致 | 色付き出力が本番パイプラインを壊す | 環境認識フォーマッタ自動切替 |\n| PII がログに漏洩 | extra フィールド経由で機密値が誤って記録される | キーベースの redaction を行う `RedactionFilter` |\n\n## 何をするのか\n\n- **呼び出しコンテキスト** — すべてのログに `invocation_id`, `function_name`, `cold_start` を自動注入\n- **構造化 JSON 出力** — Application Insights にそのまま使える NDJSON フォーマット\n- **ノイズ制御** — `SamplingFilter` がうるさいサードパーティロガーをレート制限\n- **PII 保護** — `RedactionFilter` が機密フィールドをログ集約に到達する前にマスキング\n\n\u003e **スコープ免責事項。** このパッケージは Python `logging` / stdout に構造化 JSON を書き込みます。これらのフィールドが Application Insights にどう現れるかは、Azure Functions host、worker、ロギング設定、および ingestion パイプラインに依存します。ライブラリは ingestion やスキーマ マッピングを所有しません — `customDimensions` にパースされる形式と、生の `message` 内に残る形式の両方が本番環境で有効です。\n\n## Before / After\n\n`azure-functions-logging` を **使わない場合** — 単純な `print()` 出力、コンテキストなし、構造なし:\n\n```python\nimport azure.functions as func\n\napp = func.FunctionApp()\n\n\n@app.route(route=\"orders\")\ndef process_order(req: func.HttpRequest) -\u003e func.HttpResponse:\n    print(\"Processing order\")        # invocation_id なし、構造なし\n    print(f\"Order: {req.get_json()}\")  # PII 漏洩可能、ログレベルなし\n    return func.HttpResponse(\"OK\")\n```\n\nターミナル出力:\n\n```\nProcessing order\nOrder: {'customer': 'Alice', 'total': 99.99}\n```\n\n\u003e Invocation ID なし。ログレベルなし。Application Insights での相関が困難。\n\n`azure-functions-logging` を **使う場合** — 構造化され、クエリ可能、本番環境対応:\n\n```python\nimport azure.functions as func\n\nfrom azure_functions_logging import JsonFormatter, get_logger, logging_context, setup_logging\n\nsetup_logging(functions_formatter=JsonFormatter())\nlogger = get_logger(__name__)\napp = func.FunctionApp()\n\n\n@app.route(route=\"orders\")\ndef process_order(req: func.HttpRequest, context: func.Context) -\u003e func.HttpResponse:\n    with logging_context(context):\n        logger.info(\"Processing order\", order_id=\"o-999\")\n        return func.HttpResponse(\"OK\")\n```\n\nスタンドアロンで実行した際 (例: `python app.py`、カラーフォーマッタ) のローカルターミナル出力:\n\n```\n10:30:00 INFO     function_app  Processing order  [invocation_id=abc-123-def, function_name=process_order, cold_start=true]\n```\n\n`func start` / Azure 環境での本番出力 (`functions_formatter` が設定されているため Application Insights 用 NDJSON が適用される):\n\n```json\n{\"timestamp\": \"2024-01-15T10:30:00+00:00\", \"level\": \"INFO\", \"logger\": \"function_app\",\n \"message\": \"Processing order\", \"invocation_id\": \"abc-123-def\",\n \"function_name\": \"process_order\", \"trace_id\": null, \"cold_start\": true,\n \"exception\": null, \"extra\": {\"order_id\": \"o-999\"}}\n```\n\n\u003e すべてのログに `invocation_id` と `cold_start` が含まれます。Application Insights でクエリ可能。`print()` 文ゼロ。\n\n\u003e **注:** 正確な Application Insights スキーマは ingestion パイプラインに依存します。一部の配置では JSON フィールドが `customDimensions` にパースされ、他の配置では JSON が `message` カラム内に残ります。両方の形式の例を以下に示します。\n\n### Application Insights でのクエリ\n\n#### JSON フィールドが `customDimensions` にパースされる場合\n\n```kql\ntraces\n| where customDimensions.invocation_id == \"abc-123-def\"\n| project timestamp, message, customDimensions.cold_start, customDimensions.function_name\n| order by timestamp asc\n```\n\n過去 1 時間のすべてのコールドスタートを検索:\n\n```kql\ntraces\n| where customDimensions.cold_start == \"true\"\n| where timestamp \u003e ago(1h)\n| summarize count() by bin(timestamp, 5m)\n```\n\n#### JSON が `message` カラムに残る場合\n\n```kql\ntraces\n| extend payload = parse_json(message)\n| where tostring(payload.invocation_id) == \"abc-123-def\"\n| project timestamp, tostring(payload.message), tostring(payload.cold_start), tostring(payload.function_name)\n| order by timestamp asc\n```\n\n過去 1 時間のすべてのコールドスタートを検索:\n\n```kql\ntraces\n| extend payload = parse_json(message)\n| where tostring(payload.cold_start) == \"true\"\n| where timestamp \u003e ago(1h)\n| summarize count() by bin(timestamp, 5m)\n```\n\n## このパッケージがしないこと\n\nこのパッケージは以下を所有しません:\n\n- **stdlib logging の置き換え** — Python 標準の `logging` をラップして強化するだけで、決して置き換えません\n- **分散トレーシング** — エンドツーエンドのトレース相関には OpenTelemetry または Application Insights SDK を使用してください\n- **API ドキュメント** — API ドキュメントと spec 生成には [`azure-functions-openapi`](https://github.com/yeongseon/azure-functions-openapi-python) を使用してください\n\n## インストール\n\n```bash\npip install azure-functions-logging\n```\n\n## Quick Start\n\n```python\nimport azure.functions as func\nfrom azure_functions_logging import get_logger, logging_context, setup_logging\n\nsetup_logging()\nlogger = get_logger(__name__)\n\napp = func.FunctionApp()\n\n@app.route(route=\"hello\")\ndef hello(req: func.HttpRequest, context: func.Context) -\u003e func.HttpResponse:\n    with logging_context(context):  # invocation_id, function_name, cold_start をバインドし、終了時に以前のコンテキストへ復元\n        logger.info(\"Request received\")\n        # ログレコードに invocation_id, function_name, cold_start が付与されます\n\n        return func.HttpResponse(\"OK\")\n```\n\n`logging_context` は推奨される主要パターンです。エンター時にコンテキストを注入し、（ハンドラが例外を発生させても）終了時に **常に** 前のコンテキストを復元するため、再利用された worker で古いコンテキストが次の呼び出しに漏れることを防ぎます。\n\n低レベル制御またはカスタムミドルウェアと統合する場合は、トークンベース復元を使用してください:\n\n```python\nfrom azure_functions_logging import inject_context, restore_context\n\n# `logger` と `context` がスコープにあると仮定 (Quick Start を参照)。\ntokens = inject_context(context)\ntry:\n    logger.info(\"Request received\")\nfinally:\n    restore_context(tokens)\n```\n\n`reset_context()` は意図的にすべてのコンテキストをクリアしたい場合 (例: テストの teardown) のみ使用してください。\n\nローカルで Functions host を起動 ([e2e サンプルアプリ](examples/e2e_app) 使用):\n\n```bash\nfunc start --script-root examples/e2e_app\n```\n\n### ローカルおよび Azure での検証\n\nデプロイ後 ([docs/deployment.md](docs/deployment.md) 参照)、同じリクエストは両環境で同じレスポンスを生成します。\n\n#### ローカル\n\n```bash\ncurl -s http://localhost:7071/api/logme?correlation_id=demo-123\n```\n\n```json\n{\"logged\": true, \"correlation_id\": \"demo-123\"}\n```\n\n#### Azure\n\n```bash\ncurl -s \"https://\u003cyour-app\u003e.azurewebsites.net/api/logme?correlation_id=demo-123\"\n```\n\n```json\n{\"logged\": true, \"correlation_id\": \"demo-123\"}\n```\n\n\u003e koreacentral リージョンの一時的な Azure Functions デプロイで検証 (Python 3.12, Consumption plan)。レスポンスをキャプチャし、URL は匿名化されています。\n\n## 呼び出しコンテキスト (Invocation Context)\n\nハンドラの実行期間中に呼び出しコンテキストをバインドするには `logging_context()` を使用します。以下を設定します:\n\n- `invocation_id` — 実行ごとに一意、1 リクエストのすべてのログを相関させる\n- `function_name` — Azure Functions の関数名\n- `trace_id` — プラットフォームからのトレースコンテキスト。有効な W3C `traceparent` ヘッダーからのみ抽出され、厳格に検証されるため不正な値は無視されます\n- `cold_start` — この worker プロセスの最初の呼び出しで `True`\n\n\u003e **`cold_start` のセマンティクス。** `cold_start=True` は *モジュールロード後にこの Python worker プロセスで観測された最初の呼び出し* を意味します。**プラットフォームレベル** のコールドスタートメトリックではなく、Azure Functions メトリクスが報告する App Service plan / instance 割当のコールドスタートには対応しません。同じ worker での後続の呼び出しは、worker がリサイクルされるまで `cold_start=False` を発行します。\n\n```python\ndef my_function(req, context):\n    with logging_context(context):\n        logger.info(\"handler started\")\n        # ここから先のすべてのログに invocation_id と cold_start が含まれる\n```\n\n低レベル制御 (例: ミドルウェア) には、`inject_context()` と `restore_context()` を使用します:\n\n```python\ntokens = inject_context(context)\ntry:\n    logger.info(\"handler started\")\nfinally:\n    restore_context(tokens)\n```\n\nコンテキスト注入なしでは、これらのフィールドはすべてのログ行で `None` です。\n\n### `with_context` デコレータ\n\nボイラープレートを減らすには、`inject_context()` を手動で呼び出す代わりに `with_context` デコレータを使用します:\n\n```python\nimport azure.functions as func\nfrom azure_functions_logging import get_logger, setup_logging, with_context\n\nsetup_logging()\nlogger = get_logger(__name__)\n\napp = func.FunctionApp()\n\n@app.route(route=\"hello\")\n@with_context\ndef hello(req: func.HttpRequest, context: func.Context) -\u003e func.HttpResponse:\n    logger.info(\"Request received\")\n    return func.HttpResponse(\"OK\")\n```\n\nデコレータは名前で `context` パラメータを見つけ、ハンドラ実行前に `inject_context()` を呼び出し、戻った後 `finally` で以前のコンテキストへ復元します。\n\nカスタムパラメータ名:\n\n```python\n@with_context(param=\"ctx\")\ndef hello(req: func.HttpRequest, ctx: func.Context) -\u003e func.HttpResponse:\n    ...\n```\n\n同期および非同期ハンドラの両方がサポートされます。\n\n### グローバル LogRecordFactory (オプトイン)\n\n`setup_logging()` の後にハンドラが追加される可能性がある、またはハンドラ/フィルタ設定に関係なく **すべての** `LogRecord` に呼び出しコンテキストを乗せたいアプリケーションでは、起動時にグローバルコンテキストファクトリを一度インストールしてください:\n\n```python\nfrom azure_functions_logging import install_context_factory, setup_logging\n\ninstall_context_factory()  # レコード生成時にコンテキストを注入\nsetup_logging()\n```\n\n有効化されると、`invocation_id`, `function_name`, `trace_id`, `cold_start` は予約された `LogRecord` 属性となります。stdlib `extra=` 経由で渡すと `KeyError` が発生します。キーを自動的にサニタイズする `FunctionLogger` を使用するか、別のキー名を選択してください。\n\n\u003e **`setup_logging()` との関係:** `setup_logging()` は引き続きデフォルトでハンドラに `ContextFilter` をインストールします。両方を呼び出しても問題ありません — 同じ値を設定するため衝突しません。`install_context_factory()` は、後で追加されたハンドラやフィルタチェーンをバイパスするロガーでもカバレッジを保証します。\n\n## 構造化 JSON 出力 (本番)\n\nログが Application Insights や任意の集約システムに流れる場合は JSON フォーマットを使用してください:\n\n\u003e **注:** `format` パラメータは、このライブラリが作成したハンドラ (ローカル開発) にのみ影響します。\n\u003e Azure Functions では host がハンドラを管理します。host が管理するハンドラに JSON 出力を設定するには\n\u003e `functions_formatter=JsonFormatter()` を使用してください。Azure で `format=\"json\"` を渡すと警告が発生します。\n\nスタンドアロンのローカル開発または CI 出力の場合:\n\n```python\nsetup_logging(format=\"json\")\n```\n\nAzure Functions / Core Tools では host がハンドラを所有します。既存の host 管理ハンドラに JSON フォーマットを強制するには:\n\n```python\nfrom azure_functions_logging import JsonFormatter, setup_logging\n\nsetup_logging(functions_formatter=JsonFormatter())\n```\n\nログ行ごとの出力 (NDJSON — 1 行 1 JSON オブジェクト):\n\n```json\n{\"timestamp\": \"2024-01-15T10:30:00+00:00\", \"level\": \"INFO\", \"logger\": \"my_module\",\n \"message\": \"order accepted\", \"invocation_id\": \"abc-123\", \"function_name\": \"OrderHandler\",\n \"cold_start\": false, \"trace_id\": \"4bf92f3577b34da6a3ce929d0e0e4736\", \"exception\": null,\n \"extra\": {\"order_id\": \"o-999\"}}\n```\n\n追加フィールドは出力される JSON の `extra` に含まれます。Application Insights で直接インデックス可能かどうかは ingestion パイプラインに依存します: JSON が `customDimensions` にパースされる場合は直接クエリ可能ですが、JSON が `message` カラムに残る場合はまず `parse_json(message)` を通す必要があります。\n\n```python\nlogger.info(\"order accepted\", order_id=\"o-999\", tenant_id=\"t-1\")\n```\n\n## host.json 衝突検出\n\n`host.json` がアプリが発行するログレベルを抑制する場合、起動時にこの警告が表示されます:\n\n```\nhost.json logLevel for default is set to 'Warning' which is more restrictive than the configured level 'INFO'. Logs below 'Warning' will be suppressed by the Azure Functions host.\n```\n\n推奨される `host.json` ベースライン:\n\n```json\n{\n  \"version\": \"2.0\",\n  \"logging\": {\n    \"logLevel\": {\n      \"default\": \"Information\",\n      \"Function\": \"Information\"\n    }\n  }\n}\n```\n\n### 探索順序\n\n`host.json` は現在の作業ディレクトリから上に向かって探索されます:\n\n1. `cwd/host.json`\n2. 各親ディレクトリ、最大 5 階層まで。\n\n最初に存在するファイルが採用されます。自動探索をバイパスするには (テストや非標準レイアウトなど)、明示的なパスを渡してください:\n\n```python\nfrom pathlib import Path\nfrom azure_functions_logging import setup_logging\n\nsetup_logging(host_json_path=Path(\"/site/wwwroot/host.json\"))\n```\n\n## ノイズ制御\n\nうるさいサードパーティロガーを削除せずに抑制します:\n\n```python\nfrom azure_functions_logging import SamplingFilter, setup_logging\nimport logging\n\nsetup_logging()\n\n# ノイズーな azure.* ロガーをサンプリング: 1 秒ウィンドウあたり最大 10 レコードを保持\n# ロガーにアタッチしたフィルターは、子ロガーから伝播されるレコードには実行されないため、\n# ルートハンドラーにアタッチし、ロガー名でスコープを限定します。\nfor handler in logging.getLogger().handlers:\n    handler.addFilter(SamplingFilter(rate=10, name=\"azure\"))\n\n# 本番で urllib3 を完全に沈黙\nlogging.getLogger(\"urllib3\").setLevel(logging.WARNING)\n```\n\n## PII Redaction\n\n機密フィールドが Application Insights に到達する前に削除します:\n\n```python\nfrom azure_functions_logging import RedactionFilter, setup_logging\nimport logging\n\nsetup_logging()\nroot = logging.getLogger()\n# 名前付きの子ロガーから出力されるレコードもリダクトされるよう、フィルタはハンドラに付与します。\nfor handler in root.handlers:\n    handler.addFilter(RedactionFilter(sensitive_keys=[\"password\", \"token\", \"secret\"]))\n```\n\nextra フィールドのキーが sensitive キーと一致するすべてのログレコードは、その値が `***` で置き換えられます。\n\n## ローカル vs クラウド\n\n| 環境 | フォーマット | 動作 |\n|------|------------|------|\n| ローカルターミナル | `color` (デフォルト) | 色付きで人間が読める形式: `HH:MM:SS LEVEL logger  message [context...]` |\n| Azure / Core Tools | host-managed | コンテキストフィルタのみインストール; host ハンドラに NDJSON を強制するには `functions_formatter=JsonFormatter()` を渡す |\n| CI / パイプライン | `json` | NDJSON、機械パース可能 |\n\n`setup_logging()` は `FUNCTIONS_WORKER_RUNTIME` を検出し、Azure Functions / Core Tools とスタンドアロンのローカル実行を区別します。Azure モードではハンドラを追加せずにコンテキストフィルタをインストールします (host パイプラインからの重複出力を回避)。\n\n## コンテキストバインディング\n\nリクエストスコープのメタデータを各呼び出しに渡すことなく、すべてのログにアタッチします:\n\n```python\ndef process_order(order_id: str) -\u003e None:\n    order_logger = logger.bind(order_id=order_id, region=\"eastus\")\n    order_logger.info(\"processing started\")   # order_id + region を含む\n    order_logger.info(\"processing complete\")  # 同じメタデータ、新しいメッセージ\n```\n\n呼び出しごとにバインドされたロガーを作成してください。モジュールレベルでキャッシュしないでください。\n\n## いつ使うか\n\n- Application Insights で構造化されクエリ可能なログが必要なとき\n- 単一リクエストのすべてのログにわたる `invocation_id` 相関が必要なとき\n- カスタム instrumentation なしでコールドスタート検出が必要なとき\n- サードパーティロガーに対して PII redaction やノイズ制御が必要なとき\n- `host.json` 設定が静かにログを抑制し、その理由がわからないとき\n\n## ドキュメント\n\n- 完全なドキュメント: [yeongseon.github.io/azure-functions-logging-python](https://yeongseon.github.io/azure-functions-logging-python/)\n- [Configuration reference](https://yeongseon.github.io/azure-functions-logging-python/configuration/)\n- [Troubleshooting guide](https://yeongseon.github.io/azure-functions-logging-python/troubleshooting/)\n- [API reference](https://yeongseon.github.io/azure-functions-logging-python/api/)\n\n## エコシステム\n\nこのパッケージは **Azure Functions Python DX Toolkit** の一部です。\n\n**設計原則:** `azure-functions-logging` は構造化ロギングと呼び出し認識オブザーバビリティを所有します。Python 標準の `logging` を強化します — 置き換えません。隣接する関心事は [`azure-functions-openapi`](https://github.com/yeongseon/azure-functions-openapi-python) (API ドキュメントと spec 生成)、[`azure-functions-validation`](https://github.com/yeongseon/azure-functions-validation-python) (リクエスト/レスポンス検証とシリアライゼーション)、[`azure-functions-langgraph`](https://github.com/yeongseon/azure-functions-langgraph-python) (LangGraph ランタイム公開) に属します。\n\n| パッケージ | 役割 |\n|----------|------|\n| [azure-functions-openapi-python](https://github.com/yeongseon/azure-functions-openapi-python) | OpenAPI spec 生成と Swagger UI |\n| [azure-functions-validation-python](https://github.com/yeongseon/azure-functions-validation-python) | リクエスト/レスポンス検証とシリアライゼーション |\n| [azure-functions-db-python](https://github.com/yeongseon/azure-functions-db-python) | SQL, PostgreSQL, MySQL, SQLite, Cosmos DB のデータベースバインディング |\n| [azure-functions-langgraph-python](https://github.com/yeongseon/azure-functions-langgraph-python) | Azure Functions 向け LangGraph デプロイアダプタ |\n| [azure-functions-scaffold-python](https://github.com/yeongseon/azure-functions-scaffold-python) | プロジェクトスキャフォールディング CLI |\n| **azure-functions-logging-python** | 構造化ロギングとオブザーバビリティ |\n| [azure-functions-doctor-python](https://github.com/yeongseon/azure-functions-doctor-python) | デプロイ前診断 CLI |\n| [azure-functions-durable-graph-python](https://github.com/yeongseon/azure-functions-durable-graph-python) | Durable Functions ベースのマニフェストファーストグラフランタイム *(experimental)* |\n| [azure-functions-knowledge-python](https://github.com/yeongseon/azure-functions-knowledge-python) | 知識検索 (RAG) デコレータ |\n| [azure-functions-cookbook-python](https://github.com/yeongseon/azure-functions-cookbook-python) | ドッグフード例 — toolkit 全体を実行する実行可能なレシピ |\n\n\n## AI コーディングアシスタント向け\n\nこのパッケージは stdlib logging に変更を加えずに Azure Functions に構造化ロギングを提供します。\n\n**LLM フレンドリーなリソース:**\n- `llms.txt` — 簡潔な API リファレンスと quick start (リポジトリルート)\n- `llms-full.txt` — 完全な API シグネチャ、パターン、設計原則 (リポジトリルート)\n\n**コード生成のための主要な実装詳細:**\n\n1. **ホスト構成を尊重** — Azure / Core Tools ではハンドラを追加せず、ルートロガーのレベルは `host.json` に委ねます。既存のルートハンドラとルートロガー自身に `ContextFilter` をインストールします（ルートロガーでの直接呼び出しはコンテキストを仲介する）。名前付きの子ロガーから伝搬されて後から追加されたハンドラへ到達するレコードにもコンテキストを保証したい場合は `install_context_factory()` を呼び出してください。ローカル単独モードでは `setup_logging(logger_name=None)` がルートロガーを構成します（レベル設定、ハンドラがなければ `StreamHandler` 追加）。\n2. **コンテキスト注入は contextvar ベース** — thread-local ではなく、asyncio で動作\n3. **冪等な setup** — `setup_logging()` を複数回呼び出しても安全\n4. **2 つの環境、2 つの動作**:\n   - Azure/Core Tools: 既存の root ハンドラと root ロガー自身に `ContextFilter` をインストールします。ハンドラの追加や root レベルの変更は行いません (`host.json` を尊重)。\n   - スタンドアロンのローカル実行: 対象/ルートロガーのレベルを設定します。**ハンドラが 1 つも存在しない場合に限り** `StreamHandler` (ColorFormatter または JsonFormatter) を追加し、そうでなければ既存のハンドラにフィルタのみ付加します。\n5. **テストフレンドリー**:\n   - `inject_context()` は任意のオブジェクトを受け入れる (azure.functions.Context への強い依存なし)\n   - `with_context` デコレータは同期および非同期ハンドラで動作\n   - 必要に応じてテスト teardown で `reset_context()` を使用\n\n**コード生成時:**\n- `azure_functions_logging` の公開 API からのみインポート (アンダースコアなし)\n- `setup_logging()` をモジュールレベルまたはハンドラ起動時に呼び出す (リクエストごとではない)\n- ハンドラでは `with logging_context(context):` を優先; 生の `inject_context(context)` は `try/finally restore_context(tokens)` とのみ併用\n- リクエストごとのフィールドには `logger.bind(key=value)` を使用 (logger.extra への直接アクセスではない)\n- 暗黙的なハンドラごとのコンテキスト注入を好む場合は `with_context` デコレータを使用\n- 関数の `@with_context` メタデータを検査するには `get_logging_metadata(func)` を呼び出す (`dict[str, Any] | None` を返却)\n- PII フィールドには `RedactionFilter`、大量ログには `SamplingFilter` を適用\n\n**例パターン:**\n```python\nfrom azure_functions_logging import get_logger, logging_context, setup_logging\n\n# モジュールレベル\nsetup_logging()\nlogger = get_logger(__name__)\n\n# ハンドラごと\ndef my_function(req: func.HttpRequest, context: func.Context) -\u003e func.HttpResponse:\n    with logging_context(context):\n        req_logger = logger.bind(correlation_id=req.params.get(\"id\"))\n        req_logger.info(\"Processing\")\n        return func.HttpResponse(\"OK\")\n```\n\n\nこのプロジェクトは独立したコミュニティプロジェクトであり、Microsoft と提携、承認、保守関係にはありません。\n\nAzure および Azure Functions は Microsoft Corporation の商標です。\n\n## ライセンス\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyeongseon%2Fazure-functions-logging-python","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyeongseon%2Fazure-functions-logging-python","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyeongseon%2Fazure-functions-logging-python/lists"}