← Back to list

Azure Data Explorer: A Comprehensive Guide to Real-Time Analytics

Introduction

Mohnish Tiwari · 2025-09-29 18:43 · 4 claps · 5.4 min read
#azure-data-explorer #kql #intro-to-kql #azure #technology
Open on Medium ↗
Wiki topics: GRW · Growth & Analytics ☁️ · DevOps & Cloud

Azure Data Explorer: A Comprehensive Guide to Real-Time Analytics

Introduction

In today’s data-driven world, the ability to analyze massive volumes of data in real-time is crucial. Azure Data Explorer (ADX), also known as Kusto, is Microsoft’s fast and highly scalable data exploration service designed for log and telemetry data analysis. Whether you’re monitoring applications, analyzing IoT data, or performing security analytics, ADX provides the performance and flexibility you need.

In this article, we’ll walk through setting up Azure Data Explorer, ingesting data, and running powerful queries to extract insights from your data.

What is Azure Data Explorer?

Azure Data Explorer is a fully managed, high-performance, big data analytics platform optimized for near real-time analysis of large volumes of data streaming from applications, websites, IoT devices, and more. It uses the Kusto Query Language (KQL), a powerful and intuitive query language similar to SQL.

Key Features

  • Lightning-fast queries: Analyze petabytes of data in seconds
  • Real-time ingestion: Stream data with minimal latency
  • Rich analytics: Built-in machine learning, time series analysis, and geospatial functions
  • Flexible data formats: Support for JSON, CSV, Parquet, and more
  • Seamless integration: Works with Azure ecosystem and popular tools

Setting Up Azure Data Explorer

Prerequisites

  • An active Azure subscription
  • Azure CLI installed (optional but recommended)
  • Basic understanding of cloud services

Step 1: Create an Azure Data Explorer Cluster

Via Azure Portal

  1. Navigate to the Azure Portal (portal.azure.com)
  2. Click “Create a resource” and search for “Azure Data Explorer”
  3. Click “Create” and fill in the required details:
  • Subscription: Select your subscription
  • Resource Group: Create new or use existing
  • Cluster name: Choose a unique name (e.g., myadxcluster)
  • Region: Select your preferred region
  • Compute specification: Start with Dev/Test for learning (2 instances, D11_v2)
  1. Review and create (this takes about 10–15 minutes)

Via Azure CLI

# Login to Azure
az login
# Create a resource group
az group create --name myResourceGroup --location eastus
# Create ADX cluster
az kusto cluster create \
  --name myadxcluster \
  --resource-group myResourceGroup \
  --location eastus \
  --sku name="Dev(No SLA)_Standard_D11_v2" tier="Basic" capacity=1

Step 2: Create a Database

Once your cluster is ready, create a database:

Via Azure Portal

  1. Navigate to your ADX cluster
  2. Click “Databases” in the left menu
  3. Click “+ Add database”
  4. Enter a database name (e.g., TestDatabase)
  5. Set retention period (e.g., 365 days)
  6. Click “Create”

Via Azure CLI

az kusto database create \
  --cluster-name myadxcluster \
  --database-name TestDatabase \
  --resource-group myResourceGroup \
  --soft-delete-period P365D \
  --hot-cache-period P31D

Creating Tables and Ingesting Data

Step 1: Access the Query Interface

Navigate to your cluster in the Azure Portal and click “Query” to open the web UI, or access it directly at [https://dataexplorer.azure.com/](https://dataexplorer.azure.com/)

Step 2: Create a Table

Let’s create a table to store application logs:

.create table ApplicationLogs (
    Timestamp: datetime,
    Level: string,
    Message: string,
    UserId: string,
    RequestId: string,
    Duration: long,
    StatusCode: int,
    Region: string
)

Step 3: Create a Mapping for JSON Ingestion

.create table ApplicationLogs ingestion json mapping 'ApplicationLogsMapping'
```json
[
    {"column":"Timestamp", "path":"$.timestamp", "datatype":"datetime"},
    {"column":"Level", "path":"$.level", "datatype":"string"},
    {"column":"Message", "path":"$.message", "datatype":"string"},
    {"column":"UserId", "path":"$.userId", "datatype":"string"},
    {"column":"RequestId", "path":"$.requestId", "datatype":"string"},
    {"column":"Duration", "path":"$.duration", "datatype":"long"},
    {"column":"StatusCode", "path":"$.statusCode", "datatype":"int"},
    {"column":"Region", "path":"$.region", "datatype":"string"}
]
### Step 4: Ingest Sample Data
#### Method 1: Inline Ingestion (for testing)
```kql
.ingest inline into table ApplicationLogs <|
2025-01-15T10:30:00Z,INFO,"User login successful",user123,req-001,145,200,US-East
2025-01-15T10:31:00Z,WARNING,"Slow database query",user456,req-002,3500,200,EU-West
2025-01-15T10:32:00Z,ERROR,"Failed to connect to external API",user789,req-003,5000,500,US-West
2025-01-15T10:33:00Z,INFO,"Data export completed",user123,req-004,890,200,US-East

Method 2: Ingest from Azure Blob Storage

.ingest into table ApplicationLogs
(
    'https://mystorageaccount.blob.core.windows.net/logs/app-logs-2025-01.json?sas-token'
)
with (format='json', jsonMappingReference='ApplicationLogsMapping')

Method 3: Using Python SDK

from azure.kusto.data import KustoClient, KustoConnectionStringBuilder
from azure.kusto.ingest import QueuedIngestClient, IngestionProperties, DataFormat
# Connection string
cluster_uri = "https://myadxcluster.eastus.kusto.windows.net"
kcsb = KustoConnectionStringBuilder.with_aad_device_authentication(cluster_uri)
# Ingest client
ingest_client = QueuedIngestClient(kcsb)
# Ingestion properties
ingestion_props = IngestionProperties(
    database="TestDatabase",
    table="ApplicationLogs",
    data_format=DataFormat.JSON,
    ingestion_mapping_reference="ApplicationLogsMapping"
)
# Ingest from file
ingest_client.ingest_from_file("logs.json", ingestion_properties=ingestion_props)

Querying Data with KQL

Now comes the fun part — querying your data! KQL is incredibly powerful and expressive.

Basic Queries

View all data

ApplicationLogs
| take 10

Filter by log level

ApplicationLogs
| where Level == "ERROR"
| project Timestamp, Message, UserId, StatusCode

Time-based filtering

ApplicationLogs
| where Timestamp > ago(1h)
| where Level in ("ERROR", "WARNING")
| order by Timestamp desc

Aggregation and Analytics

Count logs by level

ApplicationLogs
| summarize Count = count() by Level
| order by Count desc

Average duration by region

ApplicationLogs
| summarize AvgDuration = avg(Duration), RequestCount = count() by Region
| order by AvgDuration desc

Time series analysis

ApplicationLogs
| where Timestamp > ago(24h)
| summarize ErrorCount = countif(Level == "ERROR") by bin(Timestamp, 1h)
| render timechart

Advanced Analytics

Percentile calculations

ApplicationLogs
| where Level == "INFO"
| summarize 
    P50 = percentile(Duration, 50),
    P95 = percentile(Duration, 95),
    P99 = percentile(Duration, 99)
    by Region

Anomaly detection

ApplicationLogs
| where Timestamp > ago(7d)
| make-series RequestCount = count() default=0 on Timestamp step 1h
| extend Anomalies = series_decompose_anomalies(RequestCount, 1.5)
| render anomalychart with (anomalycolumns=Anomalies)

User behavior analysis

ApplicationLogs
| where Timestamp > ago(1d)
| summarize 
    TotalRequests = count(),
    UniqueUsers = dcount(UserId),
    AvgDuration = avg(Duration),
    ErrorRate = 100.0 * countif(Level == "ERROR") / count()
    by bin(Timestamp, 15m), Region
| order by Timestamp desc

Data Management and Optimization

Creating Update Policies

Update policies allow you to automatically transform and aggregate data during ingestion:

.create table ApplicationLogsSummary (
    Hour: datetime,
    Region: string,
    TotalRequests: long,
    ErrorCount: long,
    AvgDuration: real
)
.alter table ApplicationLogsSummary policy update
@'[{
    "IsEnabled": true,
    "Source": "ApplicationLogs",
    "Query": "ApplicationLogs | summarize TotalRequests=count(), ErrorCount=countif(Level=='ERROR'), AvgDuration=avg(Duration) by Hour=bin(Timestamp, 1h), Region",
    "IsTransactional": false,
    "PropagateIngestionProperties": false
}]'

Data Retention Policies

.alter table ApplicationLogs policy retention
```json
{
    "SoftDeletePeriod": "365.00:00:00",
    "Recoverability": "Enabled"
}
### Caching Policy
```kql
.alter table ApplicationLogs policy caching hot = 30d

Real-World Use Cases

Use Case 1: Application Performance Monitoring

// Identify slow API endpoints
ApplicationLogs
| where Timestamp > ago(1d)
| where Duration > 1000  // Requests taking more than 1 second
| summarize 
    SlowRequestCount = count(),
    MaxDuration = max(Duration),
    P95Duration = percentile(Duration, 95)
    by Message
| order by SlowRequestCount desc
| take 10

Use Case 2: Security Monitoring

// Detect potential brute force attacks
ApplicationLogs
| where Level == "ERROR" and Message contains "login"
| summarize FailedAttempts = count() by UserId, bin(Timestamp, 5m)
| where FailedAttempts > 5
| order by FailedAttempts desc

Use Case 3: Regional Performance Comparison

ApplicationLogs
| where Timestamp > ago(7d)
| summarize 
    TotalRequests = count(),
    ErrorRate = 100.0 * countif(StatusCode >= 400) / count(),
    AvgDuration = avg(Duration)
    by Region
| extend PerformanceScore = 100 - (ErrorRate + (AvgDuration / 100))
| order by PerformanceScore desc

Integration with Other Tools

Power BI Integration

Connect ADX to Power BI for rich visualizations:

  1. Open Power BI Desktop
  2. Get Data → More → Azure → Azure Data Explorer (Kusto)
  3. Enter your cluster URI and database
  4. Write KQL queries or import tables

Grafana Integration

Use the ADX plugin for Grafana to create monitoring dashboards:

# Install Grafana ADX plugin
grafana-cli plugins install grafana-azure-data-explorer-datasource

Azure Monitor Integration

Export Azure Monitor logs directly to ADX for long-term analysis and custom queries.

Best Practices

  1. Index your data properly: Use appropriate data types and consider partitioning for large tables
  2. Use materialized views: Pre-aggregate frequently queried data
  3. Leverage caching: Keep hot data in cache for faster queries
  4. Optimize queries: Use where clauses early, limit projections, and avoid unnecessary joins
  5. Monitor costs: Use query metrics and set up alerts for cluster health
  6. Implement retention policies: Archive or delete old data to manage costs
  7. Use batch ingestion: For bulk data, batch ingestion is more efficient than individual records

Performance Tips

// Bad: Filtering after aggregation
ApplicationLogs
| summarize Count = count() by Region
| where Region == "US-East"
// Good: Filter before aggregation
ApplicationLogs
| where Region == "US-East"
| summarize Count = count()
// Bad: Using contains with wildcards
ApplicationLogs
| where Message contains "error"
// Better: Use has for token matching
ApplicationLogs
| where Message has "error"

Conclusion

Azure Data Explorer is a powerful platform for real-time analytics at scale. With its intuitive query language, fast performance, and seamless Azure integration, it’s an excellent choice for log analytics, IoT data processing, security monitoring, and much more.

The combination of flexible ingestion methods, rich analytical capabilities, and cost-effective scaling makes ADX suitable for organizations of all sizes. Whether you’re analyzing application logs, monitoring infrastructure, or building custom analytics solutions, ADX provides the tools and performance you need.

Start small with the Dev/Test tier, experiment with KQL, and gradually scale as your needs grow. The investment in learning ADX will pay dividends in your ability to extract insights from your data quickly and efficiently.


메타데이터
post_id
802876d9cdaf
slug
azure-data-explorer-a-comprehensive-guide-to-real-time-analytics-802876d9cdaf
url
https://medium.com/@mohnish1997/azure-data-explorer-a-comprehensive-guide-to-real-time-analytics-802876d9cdaf
canonical_url
https://medium.com/@mohnish1997/azure-data-explorer-a-comprehensive-guide-to-real-time-analytics-802876d9cdaf
author_url
https://medium.com/@mohnish1997
status
ok
fetched_at
2026-07-10 06:45:42