{"slug":"azure-monitor-ingestion-py","title":"azure-monitor-ingestion-py","summary":"Azure Monitor Ingestion SDK for Python. Use for sending custom logs to Log Analytics workspace via Logs Ingestion API. Triggers: \"azure-monitor-ingestion\", \"LogsIngestionClient\", \"custom logs\", \"DCR\", \"data collection rule\", \"Log Analytics\".","platform":"GitHub Copilot","tags":[],"authorName":"Ciza","authorSlug":"ciza","score":0,"source":"github","price":null,"verified":false,"createdAt":"2026-08-12T21:05:08.70704Z","repo":{"url":"https://github.com/microsoft/skills","stars":3075,"forks":352,"license":"MIT","updatedAt":"2026-10-02T16:39:30Z"},"bodyHtml":"<hr>\n<h2>name: azure-monitor-ingestion-py\ndescription: |\nAzure Monitor Ingestion SDK for Python. Use for sending custom logs to Log Analytics workspace via Logs Ingestion API.\nTriggers: \"azure-monitor-ingestion\", \"LogsIngestionClient\", \"custom logs\", \"DCR\", \"data collection rule\", \"Log Analytics\".\nlicense: MIT\nmetadata:\nauthor: Microsoft\nversion: \"1.0.0\"\npackage: azure-monitor-ingestion</h2>\n<h1>Azure Monitor Ingestion SDK for Python</h1>\n<p>Send custom logs to Azure Monitor Log Analytics workspace using the Logs Ingestion API.</p>\n<h2>Installation</h2>\n<pre><code>pip install azure-monitor-ingestion\npip install azure-identity\n</code></pre>\n<h2>Environment Variables</h2>\n<pre><code># Data Collection Endpoint (DCE)\nAZURE_DCE_ENDPOINT=https://&lt;dce-name&gt;.&lt;region&gt;.ingest.monitor.azure.com  # Required for all auth methods\n\n# Data Collection Rule (DCR) immutable ID\nAZURE_DCR_RULE_ID=dcr-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx  # Required for all auth methods\n\n# Stream name from DCR\nAZURE_DCR_STREAM_NAME=Custom-MyTable_CL  # Required for all auth methods\nAZURE_TOKEN_CREDENTIALS=prod # Required only if DefaultAzureCredential is used in production\n</code></pre>\n<h2>Prerequisites</h2>\n<p>Before using this SDK, you need:</p>\n<ol>\n<li><strong>Log Analytics Workspace</strong> — Target for your logs</li>\n<li><strong>Data Collection Endpoint (DCE)</strong> — Ingestion endpoint</li>\n<li><strong>Data Collection Rule (DCR)</strong> — Defines schema and destination</li>\n<li><strong>Custom Table</strong> — In Log Analytics (created via DCR or manually)</li>\n</ol>\n<h2>Authentication &amp; Lifecycle</h2>\n<blockquote>\n<p><strong>\uD83D\uDD11 Two rules apply to every code sample below:</strong></p>\n<ol>\n<li><strong>Prefer <code>DefaultAzureCredential</code>.</strong> It works locally (Azure CLI / VS Code / Developer CLI) and in Azure (managed identity, workload identity) with no code change. Avoid connection strings, account/API keys — they bypass Entra audit and rotation.\n<ul>\n<li>Local dev: <code>DefaultAzureCredential</code> works as-is.</li>\n<li>Production: set <code>AZURE_TOKEN_CREDENTIALS=prod</code> (or <code>AZURE_TOKEN_CREDENTIALS=&lt;specific_credential&gt;</code>) to constrain the credential chain to production-safe credentials.</li>\n</ul>\n</li>\n<li><strong>Wrap every client in a context manager</strong> so HTTP transports, sockets, and token caches are released deterministically:\n<ul>\n<li>Sync: <code>with &lt;Client&gt;(...) as client:</code></li>\n<li>Async: <code>async with &lt;Client&gt;(...) as client:</code> <strong>and</strong> <code>async with DefaultAzureCredential() as credential:</code> (from <code>azure.identity.aio</code>)</li>\n</ul>\n</li>\n</ol>\n<p>Snippets may abbreviate this setup, but production code should always follow both rules.</p>\n</blockquote>\n<pre><code>from azure.monitor.ingestion import LogsIngestionClient\nfrom azure.identity import DefaultAzureCredential, ManagedIdentityCredential\nimport os\n\n# Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=&lt;specific_credential&gt;\ncredential = DefaultAzureCredential(require_envvar=True)\n# Or use a specific credential directly in production:\n# See https://learn.microsoft.com/python/api/overview/azure/identity-readme?view=azure-python#credential-classes\n# credential = ManagedIdentityCredential()\n\nwith LogsIngestionClient(\n    endpoint=os.environ[\"AZURE_DCE_ENDPOINT\"],\n    credential=credential\n) as client:\n    # Use `client.upload(...)` for all subsequent operations (see examples below)\n    ...\n</code></pre>\n<h2>Upload Custom Logs</h2>\n<pre><code>from azure.monitor.ingestion import LogsIngestionClient\nfrom azure.identity import DefaultAzureCredential\nimport os\n\nrule_id = os.environ[\"AZURE_DCR_RULE_ID\"]\nstream_name = os.environ[\"AZURE_DCR_STREAM_NAME\"]\n\nlogs = [\n    {\"TimeGenerated\": \"2024-01-15T10:00:00Z\", \"Computer\": \"server1\", \"Message\": \"Application started\"},\n    {\"TimeGenerated\": \"2024-01-15T10:01:00Z\", \"Computer\": \"server1\", \"Message\": \"Processing request\"},\n    {\"TimeGenerated\": \"2024-01-15T10:02:00Z\", \"Computer\": \"server2\", \"Message\": \"Connection established\"}\n]\n\nwith LogsIngestionClient(\n    endpoint=os.environ[\"AZURE_DCE_ENDPOINT\"],\n    credential=DefaultAzureCredential()\n) as client:\n    client.upload(rule_id=rule_id, stream_name=stream_name, logs=logs)\n</code></pre>\n<h2>Upload from JSON File</h2>\n<pre><code>import json\n\nwith open(\"logs.json\", \"r\") as f:\n    logs = json.load(f)\n\nclient.upload(rule_id=rule_id, stream_name=stream_name, logs=logs)\n</code></pre>\n<h2>Custom Error Handling</h2>\n<p>Handle partial failures with a callback:</p>\n<pre><code>failed_logs = []\n\ndef on_error(error):\n    print(f\"Upload failed: {error.error}\")\n    failed_logs.extend(error.failed_logs)\n\nclient.upload(\n    rule_id=rule_id,\n    stream_name=stream_name,\n    logs=logs,\n    on_error=on_error\n)\n\n# Retry failed logs\nif failed_logs:\n    print(f\"Retrying {len(failed_logs)} failed logs...\")\n    client.upload(rule_id=rule_id, stream_name=stream_name, logs=failed_logs)\n</code></pre>\n<h2>Ignore Errors</h2>\n<pre><code>def ignore_errors(error):\n    pass  # Silently ignore upload failures\n\nclient.upload(\n    rule_id=rule_id,\n    stream_name=stream_name,\n    logs=logs,\n    on_error=ignore_errors\n)\n</code></pre>\n<h2>Async Client</h2>\n<pre><code>import asyncio\nfrom azure.monitor.ingestion.aio import LogsIngestionClient\nfrom azure.identity.aio import DefaultAzureCredential\n\nasync def upload_logs():\n    async with LogsIngestionClient(\n        endpoint=endpoint,\n        credential=DefaultAzureCredential()\n    ) as client:\n        await client.upload(\n            rule_id=rule_id,\n            stream_name=stream_name,\n            logs=logs\n        )\n\nasyncio.run(upload_logs())\n</code></pre>\n<h2>Sovereign Clouds</h2>\n<pre><code>from azure.identity import AzureAuthorityHosts, DefaultAzureCredential\nfrom azure.monitor.ingestion import LogsIngestionClient\n\n# Azure Government\ncredential = DefaultAzureCredential(authority=AzureAuthorityHosts.AZURE_GOVERNMENT)\nwith LogsIngestionClient(\n    endpoint=\"https://example.ingest.monitor.azure.us\",\n    credential=credential,\n    credential_scopes=[\"https://monitor.azure.us/.default\"]\n) as client:\n    # client.upload(...)\n    ...\n</code></pre>\n<h2>Batching Behavior</h2>\n<p>The SDK automatically:</p>\n<ul>\n<li>Splits logs into chunks of 1MB or less</li>\n<li>Compresses each chunk with gzip</li>\n<li>Uploads chunks in parallel</li>\n</ul>\n<p>No manual batching needed for large log sets.</p>\n<h2>Client Types</h2>\n<table>\n<thead>\n<tr>\n<th>Client</th>\n<th>Purpose</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>LogsIngestionClient</code></td>\n<td>Sync client for uploading logs</td>\n</tr>\n<tr>\n<td><code>LogsIngestionClient</code> (aio)</td>\n<td>Async client for uploading logs</td>\n</tr>\n</tbody>\n</table>\n<h2>Key Concepts</h2>\n<table>\n<thead>\n<tr>\n<th>Concept</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>DCE</strong></td>\n<td>Data Collection Endpoint — ingestion URL</td>\n</tr>\n<tr>\n<td><strong>DCR</strong></td>\n<td>Data Collection Rule — defines schema, transformations, destination</td>\n</tr>\n<tr>\n<td><strong>Stream</strong></td>\n<td>Named data flow within a DCR</td>\n</tr>\n<tr>\n<td><strong>Custom Table</strong></td>\n<td>Target table in Log Analytics (ends with <code>_CL</code>)</td>\n</tr>\n</tbody>\n</table>\n<h2>DCR Stream Name Format</h2>\n<p>Stream names follow patterns:</p>\n<ul>\n<li><code>Custom-&lt;TableName&gt;_CL</code> — For custom tables</li>\n<li><code>Microsoft-&lt;TableName&gt;</code> — For built-in tables</li>\n</ul>\n<h2>Best Practices</h2>\n<ol>\n<li><strong>Pick sync OR async and stay consistent.</strong> Do not mix <code>azure.xxx</code> sync clients with <code>azure.xxx.aio</code> async clients in the same call path. Choose one mode per module.</li>\n<li><strong>Always use context managers for clients and async credentials.</strong> Wrap every client in <code>with Client(...) as client:</code> (sync) or <code>async with Client(...) as client:</code> (async) to ensure proper cleanup. For async <code>DefaultAzureCredential</code> from <code>azure.identity.aio</code>, also use <code>async with credential:</code> so tokens and transports are cleaned up.</li>\n<li><strong>Use <code>DefaultAzureCredential</code></strong> for code that runs locally. Use a specific token credential for code that runs in Azure.</li>\n<li><strong>Handle errors gracefully</strong> — use <code>on_error</code> callback for partial failures</li>\n<li><strong>Include TimeGenerated</strong> — Required field for all logs</li>\n<li><strong>Match DCR schema</strong> — Log fields must match DCR column definitions</li>\n<li><strong>Use async client</strong> for high-throughput scenarios</li>\n<li><strong>Batch uploads</strong> — SDK handles batching, but send reasonable chunks</li>\n<li><strong>Monitor ingestion</strong> — Check Log Analytics for ingestion status</li>\n</ol>\n<h2>Reference Files</h2>\n<table>\n<thead>\n<tr>\n<th>File</th>\n<th>Contents</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><a href=\"references/capabilities.md\">references/capabilities.md</a></td>\n<td>Additional non-hero capabilities, operation-group coverage, and production checklists.</td>\n</tr>\n<tr>\n<td><a href=\"references/non-hero-scenarios.md\">references/non-hero-scenarios.md</a></td>\n<td>Dedicated non-hero examples for secondary/advanced scenarios.</td>\n</tr>\n</tbody>\n</table>\n","files":[{"path":"references/capabilities.md","sizeBytes":1835,"isText":true},{"path":"references/non-hero-scenarios.md","sizeBytes":2114,"isText":true},{"path":"SKILL.md","sizeBytes":8043,"isText":true}],"reviewScore":null,"reviewSummary":null,"trust":{"provenance":"trusted-source-unreviewed","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow.","bodySource":null},"bodyLocked":false,"purchaseUrl":null,"sourceUrl":null,"report":{"provenance":"trusted-source-unreviewed","screen":{"ran":true,"outcome":"clean","suspicious":0,"notes":0,"hiddenCharacters":false},"virusScan":{"engine":"clamav","status":"clean","scannedAt":"2026-08-12T21:50:13.845971Z","sha256":"E8566B3E88267C4EEDE81FC9128F6F26B9224C734439A977D3D0B5FACF1A7E6D","sizeBytes":4957},"review":null,"source":{"repositoryUrl":"https://github.com/microsoft/skills","path":".github/plugins/azure-sdk-python/skills/azure-monitor-ingestion-py","license":"MIT","commit":"ce7edea90860e0c69fa36db164584c87908e09f5","subtreeSha":"037C884C587E768427A28DFE664D9BEA4B2871C2A476740C4E7D21DBC14FBC80","lastSyncedAt":"2026-10-03T15:23:32.814566Z"},"reviewedAt":"2026-08-12T21:53:02.318856Z","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow."},"install":[{"target":"skills-cli","command":"npx skills add https://github.com/microsoft/skills/tree/main/.github/plugins/azure-sdk-python/skills/azure-monitor-ingestion-py"},{"target":"claude-code","command":"claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install microsoft-skills@llmmart"},{"target":"git","command":"git clone https://github.com/microsoft/skills.git"}]}