# Azure Monitor Setup and Configuration for AI Workloads

**Kategori:** Monitoring & Observability
**Sist oppdatert:** 2026-02-05
**Gjelder for:** Azure OpenAI, Azure AI Services, Azure AI Search, Azure AI Foundry

---

## Oversikt

Azure Monitor gir omfattende overvåkning av AI-tjenester gjennom samling av metrics, logs og activity logs. Diagnostic settings er det sentrale mekanismen for å konfigurere datainnsamling og ruting til destinasjoner som Log Analytics, Storage Account eller Event Hubs.

**Hovedkomponenter:**
- **Platform metrics** — Samles automatisk uten konfigurasjon (CPU, minne, request count)
- **Resource logs** — Krever diagnostic setting (API-kall, tokens, latency, feil)
- **Activity log** — Abonnement-nivå operasjoner (ressursendringer, deployments)

**Viktig prinsipp:** Metrics samles automatisk, men logs må eksplisitt aktiveres gjennom diagnostic settings.

---

## Diagnostic Settings — Arkitektur

### Datakilder og destinasjoner

```
┌─────────────────────┐
│   AI Service        │
│  (Azure OpenAI,     │
│   AI Search, etc.)  │
└──────────┬──────────┘
           │
           │ Diagnostic Setting
           │
    ┌──────┴────────────────────┐
    │                           │
    ▼                           ▼
┌─────────────┐         ┌──────────────┐
│Log Analytics│         │Event Hubs    │
│ Workspace   │         │(SIEM export) │
└─────────────┘         └──────────────┘
    │
    └─────────► KQL queries
                Alerts
                Workbooks
```

**Destinasjoner per diagnostic setting:**
- Maksimalt **1 av hver destinasjonstype** per setting
- Opptil **5 diagnostic settings** per ressurs
- Destinasjon kan være i annen subscription (krever RBAC)

| Destinasjon | Use case | Krav |
|-------------|----------|------|
| **Log Analytics Workspace** | KQL-queries, alerts, dashboards | Workspace må eksistere før setting opprettes |
| **Storage Account** | Langvarig arkivering, audit compliance | Må være i samme region som ressursen (regional services) |
| **Event Hubs** | Streaming til SIEM, partner-løsninger | Krever Manage/Send/Listen permissions |
| **Azure Monitor Partner Solutions** | Datadog, Elastic, Splunk | Spesialiserte integrasjoner |

---

## Konfigurasjon — Azure Portal

### Steg-for-steg oppsett for Azure OpenAI

**1. Naviger til ressursen**
```
Azure Portal → Azure OpenAI resource → Monitoring → Diagnostic settings
```

**2. Opprett ny setting**
- Klikk **"Add diagnostic setting"**
- Gi beskrivende navn (f.eks. `openai-prod-diagnostics`)

**3. Velg log-kategorier**

For Azure OpenAI:
- ✅ `allLogs` — Alle kategorier (anbefalt for initial setup)
- ✅ `audit` — Kun audit logs (data access, settings changes)
- ⚠️ `AuditEvent` — Spesifikk kategori (service-specific)

For Azure AI Search:
- `AuditLogs` — User/app interaksjoner med data
- `OperationLogs` — Search service operations
- `allLogs` — Alt (dyrt, men komplett)

**4. Velg metrics**
- ✅ `AllMetrics` — Sender platform metrics til logs (lar deg kjøre KQL på metrics)
- ⚠️ Vurder kostnader — metrics er allerede i Metrics Explorer

**5. Velg destinasjon**

**Log Analytics Workspace (anbefalt):**
- Velg eksisterende workspace eller opprett ny
- Støtter både **Azure Diagnostics** (legacy) og **Resource-specific** mode
- Resource-specific anbefales for AI services (dedikerte tabeller, bedre ytelse)

**Storage Account (optional):**
- For retention > 2 år eller compliance-krav
- Støtter immutable storage (WORM)
- ⚠️ Kan ikke aksesseres hvis VNet er aktivert (krever "Allow trusted Microsoft services")

**6. Lagre konfigurasjonen**
- Data starter å flyte innen **90 minutter**
- Tabeller opprettes automatisk ved første log entry

---

## Konfigurasjon — PowerShell

### Azure OpenAI — Send alle logs og metrics til Log Analytics

```powershell
# Hent ressurs-IDer
$resource = Get-AzResource -ResourceName "myopenai" -ResourceType "Microsoft.CognitiveServices/accounts"
$workspace = Get-AzOperationalInsightsWorkspace -ResourceGroupName "myRG" -Name "myWorkspace"

# Definer metric og log settings
$metric = New-AzDiagnosticSettingMetricSettingsObject `
    -Enabled $true `
    -Category AllMetrics

$log = New-AzDiagnosticSettingLogSettingsObject `
    -Enabled $true `
    -CategoryGroup allLogs  # Eller "audit" for kun audit logs

# Opprett diagnostic setting
New-AzDiagnosticSetting `
    -Name 'OpenAI-Diagnostics' `
    -ResourceId $resource.ResourceId `
    -WorkspaceId $workspace.ResourceId `
    -Log $log `
    -Metric $metric `
    -Verbose
```

**Forklaring:**
- `-CategoryGroup allLogs` — Samler alle log-kategorier (dynamisk oppdatert av Microsoft)
- `-Category AllMetrics` — Sender platform metrics til Log Analytics
- `-Verbose` — Viser detaljert output for debugging

### Azure AI Search — Kun audit logs, storage og Log Analytics

```powershell
$searchResource = Get-AzResource -ResourceName "mysearch" -ResourceType "Microsoft.Search/searchServices"
$storageAccount = Get-AzStorageAccount -ResourceGroupName "myRG" -Name "mystorageacct"

$log = New-AzDiagnosticSettingLogSettingsObject `
    -Enabled $true `
    -Category "AuditLogs" `
    -RetentionPolicyEnabled $true `
    -RetentionPolicyDay 90

New-AzDiagnosticSetting `
    -Name 'Search-Audit-Logs' `
    -ResourceId $searchResource.ResourceId `
    -StorageAccountId $storageAccount.Id `
    -WorkspaceId $workspace.ResourceId `
    -Log $log
```

**Retention policy:**
- `-RetentionPolicyEnabled $true` — Aktiverer automatisk sletting i storage
- `-RetentionPolicyDay 90` — Logs slettes etter 90 dager (compliance-krav)

---

## Konfigurasjon — Azure CLI

### Azure OpenAI — Multi-destination setup

```bash
# Hent ressurs-IDer
resourceId=$(az cognitiveservices account show \
    --name myopenai \
    --resource-group myRG \
    --query id -o tsv)

workspaceId=$(az monitor log-analytics workspace show \
    --resource-group myRG \
    --workspace-name myWorkspace \
    --query id -o tsv)

storageId=$(az storage account show \
    --name mystorageacct \
    --resource-group myRG \
    --query id -o tsv)

eventHubRule=$(az eventhubs namespace authorization-rule show \
    --resource-group myRG \
    --namespace-name myEventHub \
    --name RootManageSharedAccessKey \
    --query id -o tsv)

# Opprett diagnostic setting med alle destinasjoner
az monitor diagnostic-settings create \
    --name OpenAI-Multi-Destination \
    --resource $resourceId \
    --logs '[
        {"category": "Audit", "enabled": true},
        {"category": "RequestResponse", "enabled": true}
    ]' \
    --metrics '[{"category": "AllMetrics", "enabled": true}]' \
    --storage-account $storageId \
    --workspace $workspaceId \
    --event-hub-rule $eventHubRule \
    --event-hub myEventHubName \
    --export-to-resource-specific true
```

**Viktige flags:**
- `--export-to-resource-specific true` — Bruker resource-specific mode (dedikerte tabeller i Log Analytics)
- `--logs '[...]'` — JSON array med log-kategorier
- `--metrics '[...]'` — JSON array med metric-kategorier

### Azure AI Search — Scoped audit logs

```bash
searchId=$(az search service show \
    --name mysearch \
    --resource-group myRG \
    --query id -o tsv)

az monitor diagnostic-settings create \
    --name Search-Audit \
    --resource $searchId \
    --logs '[
        {"category": "AuditLogs", "enabled": true}
    ]' \
    --workspace $workspaceId
```

---

## Metrics Collection Strategies

### Automatisk samling (ingen konfigurasjon)

**Platform metrics samles alltid:**
- Azure OpenAI: `TokenTransaction`, `ProcessedPromptTokens`, `GeneratedCompletionTokens`, `ActiveTokens`, `Requests`
- Azure AI Search: `SearchQueriesPerSecond`, `ThrottledSearchQueriesPercentage`, `SearchLatency`
- Lagres i **Azure Monitor Metrics database** (93 dagers retention)
- Tilgjengelig i Metrics Explorer umiddelbart

### Ruting til Log Analytics (valgfritt)

**Hvorfor sende metrics til logs?**
- ✅ Kjøre KQL-queries på metrics (kombinere med logs)
- ✅ Retention > 93 dager (opp til 2 år i Log Analytics)
- ✅ Korrelere metrics med spesifikke API-kall
- ❌ Kostnad — dobbel lagring (Metrics + Logs)

**Best practice:**
```powershell
# Kun send metrics hvis du trenger langtidsanalyse
$metric = New-AzDiagnosticSettingMetricSettingsObject `
    -Enabled $true `
    -Category AllMetrics `
    -RetentionPolicyEnabled $true `
    -RetentionPolicyDay 730  # 2 år
```

---

## Log Ingestion Patterns

### Category Groups vs Individual Categories

**Category Groups (anbefalt):**
```json
{
  "logs": [
    {"categoryGroup": "allLogs", "enabled": true},
    {"categoryGroup": "audit", "enabled": true}
  ]
}
```

**Fordeler:**
- Microsoft oppdaterer grupper automatisk når nye log-kategorier legges til
- Enklere vedlikehold
- Mindre risk for å miste nye log-typer

**Individual Categories:**
```json
{
  "logs": [
    {"category": "AuditEvent", "enabled": true},
    {"category": "RequestResponse", "enabled": true},
    {"category": "Trace", "enabled": false}
  ]
}
```

**Bruk når:**
- Du må kontrollere kostnader nøyaktig
- Compliance krever kun spesifikke kategorier
- High-volume logs som ikke er nødvendige (f.eks. Trace)

### Collection Modes for Log Analytics

**Azure Diagnostics Mode (legacy):**
```
Alle services → samme tabell (AzureDiagnostics)
```
- ❌ Maks 500 kolonner totalt (shared across services)
- ❌ Vanskelig å query ved mange services
- ✅ Kompatibel med eldre queries

**Resource-Specific Mode (anbefalt):**
```
Azure OpenAI → AzureDiagnostics (for compatibility)
              → ACRRequestResponse
              → ACRAudit
              → ACRTrace
```
- ✅ Dedikerte tabeller per service og kategori
- ✅ Bedre query-ytelse
- ✅ Ingen kolonne-limit
- ⚠️ Ikke alle services støtter dette (sjekk dokumentasjon)

**Angi mode ved opprettelse:**
```bash
az monitor diagnostic-settings create \
    --export-to-resource-specific true  # eller false for Azure Diagnostics
```

---

## Resource Tagging for AI Workloads

### Tags for monitoring context

Bruk tags for å gruppere og filtrere AI-ressurser i queries:

```powershell
# Tag ressurser med workload-info
Set-AzResource -ResourceId $resource.ResourceId -Tag @{
    "Environment" = "Production"
    "Workload" = "CustomerSupport"
    "CostCenter" = "IT-AI"
    "DataClassification" = "Confidential"
    "ComplianceScope" = "GDPR"
} -Force

# Taggene blir automatisk tilgjengelig i Log Analytics
```

**KQL query med tags:**
```kql
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.COGNITIVESERVICES"
| where tags_s contains "Production"
| where tags_s contains "CustomerSupport"
| summarize RequestCount = count() by bin(TimeGenerated, 1h)
```

**Naming convention for diagnostic settings:**
```
{service}-{environment}-{purpose}
Eksempel: openai-prod-audit
         search-dev-allmetrics
```

---

## Log Retention and Lifecycle

### Log Analytics Workspace Retention

**Standard retention:**
- 30 dager (gratis)
- 31-730 dager (kostnad per GB retained)

**Konfigurasjon:**
```bash
az monitor log-analytics workspace update \
    --resource-group myRG \
    --workspace-name myWorkspace \
    --retention-time 90
```

### Storage Account Lifecycle Policies

**For lang-arkivering:**
```json
{
  "rules": [
    {
      "name": "ArchiveDiagnosticLogs",
      "enabled": true,
      "type": "Lifecycle",
      "definition": {
        "filters": {
          "blobTypes": ["blockBlob"],
          "prefixMatch": ["insights-logs-audit/"]
        },
        "actions": {
          "baseBlob": {
            "tierToCool": {"daysAfterModificationGreaterThan": 30},
            "tierToArchive": {"daysAfterModificationGreaterThan": 90},
            "delete": {"daysAfterModificationGreaterThan": 2555}
          }
        }
      }
    }
  ]
}
```

**Arkitektur:**
- 0-30 dager: Hot tier (Log Analytics + Storage Hot)
- 31-90 dager: Cool tier (Storage Cool)
- 91-2555 dager: Archive tier (Compliance)
- > 7 år: Automatisk slettet

---

## Kostnadsoptimalisering

### Filtrer bort unødvendige logs

**Problem:** `allLogs` kan bli dyrt for high-traffic AI services.

**Løsning — Selective categories:**
```powershell
# Kun audit og errors, dropp successful requests
$log = @(
    New-AzDiagnosticSettingLogSettingsObject -Enabled $true -Category "Audit"
    New-AzDiagnosticSettingLogSettingsObject -Enabled $true -Category "Errors"
    New-AzDiagnosticSettingLogSettingsObject -Enabled $false -Category "RequestResponse"
)
```

### Bruk sampling for high-volume scenarios

**For Azure Application Insights (AI app monitoring):**
```csharp
// Adaptive sampling — reduserer telemetry ved høy trafikk
builder.Services.AddApplicationInsightsTelemetry(options =>
{
    options.EnableAdaptiveSampling = true;
    options.AdaptiveSamplingMaxTelemetryItemsPerSecond = 5;
});
```

### Data transformation (preview)

**Filtrer data før ingestion til Log Analytics:**
```kql
// Transformation rule (DCR — Data Collection Rule)
source
| where ResultType != "Success"  // Dropp vellykkede kall
| where DurationMs > 1000         // Kun langsomme requests
| project-away SensitiveField     // Fjern PII
```

**Kostnadsreduksjon:**
- 50-80% mindre ingestion volume
- Samme pris per GB, men mindre data
- ⚠️ Preview-funksjon, ikke GA (feb 2026)

---

## Troubleshooting

### Data flyter ikke til destinasjon

**Symptom:** Ingen data i Log Analytics etter 24 timer.

**Sjekkliste:**
1. **Verifiser diagnostic setting:**
   ```bash
   az monitor diagnostic-settings show \
       --name mySettingName \
       --resource $resourceId
   ```

2. **Sjekk at logs genereres:**
   ```bash
   # Send test-request til Azure OpenAI
   curl -X POST https://myopenai.openai.azure.com/openai/deployments/gpt-4/completions \
       -H "api-key: $API_KEY" \
       -d '{"prompt": "Test", "max_tokens": 5}'
   ```

3. **Verifiser Log Analytics workspace:**
   ```kql
   // Sjekk om noen data er skrevet til workspace
   AzureDiagnostics
   | where ResourceProvider == "MICROSOFT.COGNITIVESERVICES"
   | take 10
   ```

4. **RBAC-tilgang:**
   ```bash
   # User må ha Monitoring Contributor på ressurs
   az role assignment create \
       --assignee user@domain.com \
       --role "Monitoring Contributor" \
       --scope $resourceId
   ```

### Metric category ikke støttet (error)

**Symptom:** `"Metric category 'xxxx' is not supported"`

**Løsning:**
```powershell
# Bruk kun AllMetrics (eneste gyldige kategori for de fleste services)
$metric = New-AzDiagnosticSettingMetricSettingsObject `
    -Enabled $true `
    -Category AllMetrics

# IKKE bruk custom metric names
```

### VNet-blokkering

**Symptom:** Logs når ikke Storage/Event Hub når VNet firewall er aktivert.

**Løsning:**
```bash
# Tillat trusted Microsoft services
az storage account update \
    --name mystorageacct \
    --resource-group myRG \
    --bypass AzureServices
```

### Resource-specific mode ikke tilgjengelig

**Symptom:** `--export-to-resource-specific` ikke støttet.

**Løsning:**
- Sjekk om service støtter resource-specific mode (ikke alle gjør det)
- Fallback til Azure Diagnostics mode:
  ```bash
  az monitor diagnostic-settings create \
      --export-to-resource-specific false
  ```

---

## Best Practices

### 1. Standard Diagnostic Setting per Environment

**Template-basert deployment:**
```json
{
  "type": "Microsoft.Insights/diagnosticSettings",
  "apiVersion": "2021-05-01-preview",
  "scope": "[parameters('aiResourceId')]",
  "name": "StandardAIDiagnostics",
  "properties": {
    "workspaceId": "[parameters('logAnalyticsId')]",
    "logs": [
      {"categoryGroup": "audit", "enabled": true},
      {"categoryGroup": "allLogs", "enabled": false}
    ],
    "metrics": [
      {"category": "AllMetrics", "enabled": false}
    ]
  }
}
```

**Rationale:**
- ✅ Audit logs alltid på (compliance)
- ❌ AllLogs kun i dev/test (kostnad)
- ❌ Metrics til logs kun hvis nødvendig (dobbel lagring)

### 2. Separate Settings for Separate Purposes

**Eksempel — 3 settings for samme resource:**

| Setting Name | Destinasjon | Innhold | Formål |
|--------------|-------------|---------|--------|
| `audit-compliance` | Storage (immutable) | `audit` logs | GDPR/retention |
| `operational-monitoring` | Log Analytics | `allLogs`, `AllMetrics` | Alerts, dashboards |
| `siem-integration` | Event Hubs | `allLogs` | Security monitoring (Sentinel) |

**Konfigurasjon:**
```bash
# Setting 1: Compliance
az monitor diagnostic-settings create \
    --name audit-compliance \
    --resource $resourceId \
    --logs '[{"categoryGroup": "audit", "enabled": true}]' \
    --storage-account $complianceStorageId

# Setting 2: Operational
az monitor diagnostic-settings create \
    --name operational-monitoring \
    --resource $resourceId \
    --logs '[{"categoryGroup": "allLogs", "enabled": true}]' \
    --metrics '[{"category": "AllMetrics", "enabled": true}]' \
    --workspace $operationalWorkspaceId

# Setting 3: SIEM
az monitor diagnostic-settings create \
    --name siem-integration \
    --resource $resourceId \
    --logs '[{"categoryGroup": "allLogs", "enabled": true}]' \
    --event-hub-rule $siemEventHubRule \
    --event-hub securitylogs
```

### 3. Infrastructure as Code (IaC)

**Bicep-modul for AI services:**
```bicep
param aiResourceId string
param logAnalyticsId string
param environment string

resource diagnostics 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = {
  scope: resourceId('Microsoft.CognitiveServices/accounts', aiResourceId)
  name: 'ai-diagnostics-${environment}'
  properties: {
    workspaceId: logAnalyticsId
    logs: [
      {
        categoryGroup: 'audit'
        enabled: true
      }
      {
        categoryGroup: 'allLogs'
        enabled: environment == 'dev' ? true : false
      }
    ]
    metrics: [
      {
        category: 'AllMetrics'
        enabled: false
      }
    ]
  }
}
```

### 4. Monitoring the Monitoring

**Alert på missing logs:**
```kql
// Alert hvis ingen logs siste time
let threshold = ago(1h);
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.COGNITIVESERVICES"
| where TimeGenerated > threshold
| summarize LogCount = count()
| where LogCount == 0
```

**Alert på høy log volume (kostnadskontroll):**
```kql
// Alert hvis > 10 GB logs per dag
let threshold = 10.0 * 1024 * 1024 * 1024;
AzureDiagnostics
| where TimeGenerated > ago(1d)
| summarize DataVolume = sum(_BilledSize)
| where DataVolume > threshold
```

---

## For Cosmo

**Når du vurderer Azure Monitor setup for en AI-løsning:**

1. **Start med minimal konfigurasjon:**
   - Kun `audit` logs til Log Analytics
   - Platform metrics (gratis, automatisk)
   - Utvid etter behov

2. **Cost vs. Compliance trade-off:**
   - Audit logs til immutable storage: **Må ha** (compliance)
   - AllLogs til Log Analytics: **Nice to have** (kostnad)
   - Metrics til logs: **Unngå** (redundant, dyrt)

3. **Multi-tenant scenarios:**
   - Separate Log Analytics workspaces per kunde (data isolation)
   - Azure Lighthouse for managed service providers
   - Diagnostic settings i customer subscription (RBAC)

4. **Integration points:**
   - Log Analytics → Azure Sentinel (SIEM)
   - Event Hubs → Splunk/Datadog (non-Microsoft SIEM)
   - Storage → Azure Synapse (langtidsanalyse)

5. **Valider at setup er optimal:**
   - Kjør Cost Management report (se data ingestion costs)
   - Verifiser at logs faktisk brukes (query history i Log Analytics)
   - Review unused diagnostic settings (ressurs slettet, men setting består)

6. **Advarsel — feil å unngå:**
   - ❌ Ikke send metrics til logs uten grunn (dobbel kostnad)
   - ❌ Ikke bruk `allLogs` i prod uten cost-analyse
   - ❌ Ikke glem å slette diagnostic settings ved ressurs-sletting
   - ❌ Ikke bruk samme workspace for prod og dev (cost attribution)

**Anbefalte setup per workload type:**

| Workload | Logs | Metrics | Destinasjon | Rationale |
|----------|------|---------|-------------|-----------|
| **POC** | audit | Nei | Log Analytics (30 dag retention) | Minimal kostnad, tilstrekkelig for testing |
| **Prod (low-volume)** | allLogs | Nei | Log Analytics (90 dag) + Storage (7 år) | Full observability + compliance |
| **Prod (high-volume)** | audit + errors | Nei | Log Analytics (30 dag) + Storage (7 år) | Cost-optimalisert, fokusert på kritiske events |
| **Regulated (GDPR/PCI-DSS)** | audit | Nei | Immutable Storage (10 år) | Compliance-first, kostnad sekundært |

**Huskeregel:** Metrics er gratis å samle, logs er dyre å lagre. Start lite, ekspander etter behov.
