Skip to content

04. Logging & Monitoring

Instrument your Spring Boot app for production observability using Logback JSON logs, Azure Monitor, and Application Insights.

Infrastructure Context

Service: App Service (Linux, Standard S1) | Network: VNet integrated | VNet: ✅

This tutorial assumes a production-ready App Service deployment with VNet integration, private endpoints for backend services, and managed identity for authentication.

flowchart TD
    INET[Internet] -->|HTTPS| WA["Web App\nApp Service S1\nLinux Java 17"]

    subgraph VNET["VNet 10.0.0.0/16"]
        subgraph INT_SUB["Integration Subnet 10.0.1.0/24\nDelegation: Microsoft.Web/serverFarms"]
            WA
        end
        subgraph PE_SUB["Private Endpoint Subnet 10.0.2.0/24"]
            PE_KV[PE: Key Vault]
            PE_SQL[PE: Azure SQL]
            PE_ST[PE: Storage]
        end
    end

    PE_KV --> KV[Key Vault]
    PE_SQL --> SQL[Azure SQL]
    PE_ST --> ST[Storage Account]

    subgraph DNS[Private DNS Zones]
        DNS_KV[privatelink.vaultcore.azure.net]
        DNS_SQL[privatelink.database.windows.net]
        DNS_ST[privatelink.blob.core.windows.net]
    end

    PE_KV -.-> DNS_KV
    PE_SQL -.-> DNS_SQL
    PE_ST -.-> DNS_ST

    WA -.->|System-Assigned MI| ENTRA[Microsoft Entra ID]
    WA --> AI[Application Insights]

    style WA fill:#0078d4,color:#fff
    style VNET fill:#E8F5E9,stroke:#4CAF50
    style DNS fill:#E3F2FD

Prerequisites

  • Completed 02. First Deploy
  • Access to App Service and Application Insights resources
  • Deployed app with APPLICATIONINSIGHTS_CONNECTION_STRING configured

What you'll learn

  • How logback-spring.xml switches between dev and production formats
  • How to stream and query logs from App Service
  • How to run practical KQL queries for Java workloads
  • How to validate telemetry with sample endpoints

Main Content

Logging architecture for this guide

flowchart TD
    A[Spring Boot App] --> B[Console Logback Output]
    B --> C[App Service Log Stream]
    B --> D[Application Insights]
    D --> E[Log Analytics Workspace]
    E --> F[KQL Queries / Alerts]

Understand logback-spring.xml

The app uses profile-aware logging:

  • !production: human-readable pattern logs for local development
  • production: JSON logs via net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder

Relevant production fields include:

  • timestamp
  • level
  • thread
  • logger
  • message
  • exception

This shape is ideal for parsing in Azure Monitor.

Generate predictable test logs

Use the built-in endpoint:

curl "https://$APP_NAME.azurewebsites.net/api/requests/log-levels?userId=monitor-demo"
Command/Code Purpose
curl "https://$APP_NAME.azurewebsites.net/api/requests/log-levels?userId=monitor-demo" Calls the sample endpoint that emits predictable logs across multiple severities.

The endpoint emits one log per severity (DEBUG/INFO/WARN/ERROR).

Stream logs in real time

az webapp log tail \
  --resource-group "$RG" \
  --name "$APP_NAME"
Command/Code Purpose
az webapp log tail Opens the live App Service log stream.
--resource-group "$RG" Targets the resource group that contains the app.
--name "$APP_NAME" Selects the web app whose logs should be streamed.

If log stream is empty, ensure application logging is enabled.

Enable filesystem logging (short-term troubleshooting)

az webapp log config \
  --resource-group "$RG" \
  --name "$APP_NAME" \
  --application-logging filesystem \
  --level information \
  --output json
Command/Code Purpose
az webapp log config Configures App Service application logging behavior.
--application-logging filesystem Writes application logs to the local App Service filesystem.
--level information Captures logs at information level and above.
--output json Returns the logging configuration as JSON.

Production guidance

Prefer central telemetry in Application Insights for long-term analytics. Filesystem logs are best for short-lived debugging.

Query location matters

Table names differ by where you run the query. See KQL Queries Reference — Table Naming for details.

  • Application Insights → Logs: traces, requests, dependencies
  • Log Analytics Workspace → Logs: AppTraces, AppRequests, AppDependencies

KQL query: recent application logs

AppTraces
| where TimeGenerated > ago(30m)
| where AppRoleName contains "app-"
| project TimeGenerated, SeverityLevel, Message, AppRoleName
| order by TimeGenerated desc

KQL query: error distribution

AppTraces
| where TimeGenerated > ago(24h)
| where SeverityLevel >= 3
| summarize ErrorCount = count() by bin(TimeGenerated, 15m), AppRoleName
| order by TimeGenerated asc

KQL query: request latency percentiles

AppRequests
| where TimeGenerated > ago(24h)
| summarize
    RequestCount = count(),
    P50 = percentile(DurationMs, 50),
    P95 = percentile(DurationMs, 95),
    P99 = percentile(DurationMs, 99)
  by Name
| order by P95 desc

KQL query: correlate failed requests with traces

let failed = AppRequests
| where TimeGenerated > ago(6h)
| where Success == false
| project OperationId, Name, ResultCode, DurationMs, TimeGenerated;

failed
| join kind=leftouter (
    AppTraces
    | where TimeGenerated > ago(6h)
    | project OperationId, TraceMessage = Message, SeverityLevel
) on OperationId
| order by TimeGenerated desc

Alerting baseline recommendation

  • Alert on sustained 5xx rate
  • Alert on P95 latency regression
  • Alert on no heartbeat/traffic during business windows

Use synthetic probes

Add availability tests against /health and a lightweight business endpoint to catch platform and app regressions early.

Platform architecture

For platform architecture details, see Platform: How App Service Works.

Verification

  • Trigger /api/requests/log-levels
  • Confirm logs appear in az webapp log tail
  • Run KQL queries and verify rows return for the current app
  • Confirm production profile emits JSON-formatted logs

Troubleshooting

No telemetry in Application Insights

  • Confirm APPLICATIONINSIGHTS_CONNECTION_STRING exists in App Settings
  • Confirm app restarted after config change
  • Wait a few minutes for ingestion delay

Logs show only INFO and above

Adjust logger level temporarily:

az webapp config appsettings set \
  --resource-group "$RG" \
  --name "$APP_NAME" \
  --settings LOGGING_LEVEL_COM_EXAMPLE_GUIDE=DEBUG \
  --output json
Command/Code Purpose
az webapp config appsettings set Updates app settings to temporarily increase logging detail.
--settings LOGGING_LEVEL_COM_EXAMPLE_GUIDE=DEBUG Raises the sample package log level to DEBUG.
--output json Returns the updated app settings in JSON format.

KQL table names differ in your workspace

Use AppTraces/AppRequests as primary tables; in some environments, schema naming may vary by ingestion mode.

Run It in the Portal

Portal view: Application Insights Overview blade (telemetry destination for this tutorial)

Azure portal Application Insights Overview blade for ai-test-20251107 with top toolbar Application Dashboard, Getting started, Search, Logs, Monitor resource group, Feedback, Favorites, Rename, Delete and View Cost / JSON View links on the right. Essentials shows Resource group rg-test-20251107, Location Korea Central, Subscription "Visual Studio Enterprise Subscription", Subscription ID 00000000-0000-0000-0000-000000000000, Instrumentation key 00000000-0000-0000-0000-000000000000, Connection string "InstrumentationKey=00000000-...;IngestionEnd..." (truncated), Logs workspace DefaultWorkspace-00000000-0000-0000-0000-000000000000-SE, OTLP connection info "Turn on OTLP support". A "Show data for last:" tab strip shows 30 minutes / 1 hour (selected) / 6 hours / 12 hours / 1 day / 3 days / 7 days / 30 days. Four pinned tiles: Failed requests Count chart with a spike (label 10), Server response time at ~1ms (label 1.07ms), Server requests Count chart with spikes (label 15), and Availability Avg flat at 0% (label "--" because no test configured). Left nav lists Search, Overview (selected), Activity log, Access control (IAM), Tags, Diagnose and solve problems, Resource visualizer, plus collapsed group headers Investigate, Monitoring, Usage, Configure, Settings, Automation, Help.

This Application Insights Overview blade is the Portal destination for the telemetry configured in this tutorial. The Connection string shown in Essentials corresponds to the APPLICATIONINSIGHTS_CONNECTION_STRING setting that the Spring Boot Application Insights agent reads at startup. The four pinned tiles — Failed requests, Server response time, Server requests, and Availability — give a quick summary of what the app is emitting at the request and reliability level. Use the Logs button in the top toolbar to open the KQL surface, which is where the tutorial's AppTraces, AppRequests, and AppDependencies query steps run.

See Also

Sources