Kusto Sorguları için Örnekler

Bu makalede, yaygın sorgular ve bunları karşılamak için Kusto Sorgu Dili nasıl kullanabileceğiniz tanımlanır.

Sütun grafiği görüntüleme

İki veya daha fazla sütunu yansıtmak ve sonra sütunları grafiğin x ekseni ve y ekseni olarak kullanmak için:

StormEvents
| where isnotempty(EndLocation) 
| summarize event_count=count() by EndLocation
| top 10 by event_count
| render columnchart
  • İlk sütun x eksenini oluşturur. Sayısal, tarih-saat veya dize olabilir.
  • Görüntülediğiniz veri hacmini sınırlamak için , summarizeve top kullanınwhere.
  • X ekseninin sırasını tanımlamak için sonuçları sıralayın.

Screenshot of a column chart, with ten colored columns that depict the respective values of 10 locations.

Başlangıç ve durdurma olaylarından oturum alma

Bir olay günlüğünde, bazı olaylar genişletilmiş etkinliğin veya oturumun başlangıcını veya sonunu işaretler.

Name Şehir SessionId Zaman damgası
Başlangıç Londra 2817330 2015-12-09T10:12:02.32
Game Londra 2817330 2015-12-09T10:12:52.45
Başlangıç Manchester 4267667 2015-12-09T10:14:02.23
Durdur Londra 2817330 2015-12-09T10:23:43.18
İptal Manchester 4267667 2015-12-09T10:27:26.29
Durdur Manchester 4267667 2015-12-09T10:28:31.72

Her olayın bir oturum kimliği (SessionId) vardır. Sınama, başlatma ve durdurma olaylarını bir oturum kimliğiyle eşleştirmektir.

Örnek:

let Events = MyLogTable | where ... ;
Events
| where Name == "Start"
| project Name, City, SessionId, StartTime=timestamp
| join (Events 
        | where Name="Stop"
        | project StopTime=timestamp, SessionId) 
    on SessionId
| project City, SessionId, StartTime, StopTime, Duration = StopTime - StartTime

Başlatma ve durdurma olaylarını oturum kimliğiyle eşleştirmek için:

  1. Birleştirmeye başlamadan önce mümkün olduğunca aşağı doğru ayrıştırılan tablonun projeksiyonunu adlandırmak için let komutunu kullanın.
  2. Zaman damgalarının adlarını hem başlangıç saati hem de durdurma zamanı sonuçlarda görünecek şekilde değiştirmek için project kullanın. project ayrıca sonuçlarda görüntülemek üzere diğer sütunları seçer.
  3. Aynı etkinliğin başlangıç ve durdurma girdileriyle eşleştirmek için birleştirmeyi kullanın. Her etkinlik için bir satır oluşturulur.
  4. Etkinliğin süresini göstermek üzere bir sütun eklemek için yeniden kullanın project .

Çıktı aşağıda verilmiştir:

Şehir SessionId StartTime Stoptime Süre
Londra 2817330 2015-12-09T10:12:02.32 2015-12-09T10:23:43.18 00:11:40.46
Manchester 4267667 2015-12-09T10:14:02.23 2015-12-09T10:28:31.72 00:14:29.49

Oturum kimliği kullanmadan oturum alma

Başlangıç ve durdurma olaylarının kolayca eşleştirebileceğimiz bir oturum kimliğine sahip olmadığını varsayalım. Ancak, oturumun gerçekleştiği istemcinin IP adresine sahibiz. Her istemci adresinin aynı anda yalnızca bir oturum yürüttüğü varsayıldığında, her başlangıç olayını aynı IP adresinden bir sonraki durdurma olayıyla eşleştirebiliriz:

Örnek:

Events 
| where Name == "Start" 
| project City, ClientIp, StartTime = timestamp
| join  kind=inner
    (Events
    | where Name == "Stop" 
    | project StopTime = timestamp, ClientIp)
    on ClientIp
| extend duration = StopTime - StartTime 
    // Remove matches with earlier stops:
| where  duration > 0  
    // Pick out the earliest stop for each start and client:
| summarize arg_min(duration, *) by bin(StartTime,1s), ClientIp

Her join başlangıç saatini aynı istemci IP adresinden gelen tüm durdurma zamanlarıyla eşleştirir. Örnek kod:

  • Önceki durdurma süreleriyle eşleşmeleri kaldırır.
  • Her oturum için bir grup almak için başlangıç zamanına ve IP adresine göre gruplar.
  • parametresi için StartTime bir bin işlev sağlar. Bu adımı gerçekleştirmezseniz, Kusto otomatik olarak bazı başlangıç saatleriyle yanlış durdurma zamanlarıyla eşleşen bir saatlik bölmeler kullanır.

arg_min her gruptaki en küçük süreye sahip satırı bulur ve * parametresi diğer tüm sütunlardan geçer.

Bağımsız değişken her sütun adına ön ek ekler min_ .

Screenshot of a table that lists the results, with columns for the start time, client IP, duration, city, and earliest stop for each client/start time combination.

Uygun boyuttaki bölmelerde süreleri saymak için kod ekleyin. Bu örnekte, çubuk grafiğin tercihi nedeniyle, zaman çizelgelerini sayılara dönüştürmek için ölçütüne bölün 1s :

    // Count the frequency of each duration:
    | summarize count() by duration=bin(min_duration/1s, 10) 
      // Cut off the long tail:
    | where duration < 300
      // Display in a bar chart:
    | sort by duration asc | render barchart 

Screenshot of a column chart that depicts the number of sessions, with durations in specified ranges.

Tam örnek

Logs  
| filter ActivityId == "ActivityId with Blablabla" 
| summarize max(Timestamp), min(Timestamp)  
| extend Duration = max_Timestamp - min_Timestamp 

wabitrace  
| filter Timestamp >= datetime(2015-01-12 11:00:00Z)  
| filter Timestamp < datetime(2015-01-12 13:00:00Z)  
| filter EventText like "NotifyHadoopApplicationJobPerformanceCounters"  	 
| extend Tenant = extract("tenantName=([^,]+),", 1, EventText) 
| extend Environment = extract("environmentName=([^,]+),", 1, EventText)  
| extend UnitOfWorkId = extract("unitOfWorkId=([^,]+),", 1, EventText)  
| extend TotalLaunchedMaps = extract("totalLaunchedMaps=([^,]+),", 1, EventText, typeof(real))  
| extend MapsSeconds = extract("mapsMilliseconds=([^,]+),", 1, EventText, typeof(real)) / 1000 
| extend TotalMapsSeconds = MapsSeconds  / TotalLaunchedMaps 
| filter Tenant == 'DevDiv' and Environment == 'RollupDev2'  
| filter TotalLaunchedMaps > 0 
| summarize sum(TotalMapsSeconds) by UnitOfWorkId  
| extend JobMapsSeconds = sum_TotalMapsSeconds * 1 
| project UnitOfWorkId, JobMapsSeconds 
| join ( 
wabitrace  
| filter Timestamp >= datetime(2015-01-12 11:00:00Z)  
| filter Timestamp < datetime(2015-01-12 13:00:00Z)  
| filter EventText like "NotifyHadoopApplicationJobPerformanceCounters"  
| extend Tenant = extract("tenantName=([^,]+),", 1, EventText) 
| extend Environment = extract("environmentName=([^,]+),", 1, EventText)  
| extend UnitOfWorkId = extract("unitOfWorkId=([^,]+),", 1, EventText)   
| extend TotalLaunchedReducers = extract("totalLaunchedReducers=([^,]+),", 1, EventText, typeof(real)) 
| extend ReducesSeconds = extract("reducesMilliseconds=([^,]+)", 1, EventText, typeof(real)) / 1000 
| extend TotalReducesSeconds = ReducesSeconds / TotalLaunchedReducers 
| filter Tenant == 'DevDiv' and Environment == 'RollupDev2'  
| filter TotalLaunchedReducers > 0 
| summarize sum(TotalReducesSeconds) by UnitOfWorkId  
| extend JobReducesSeconds = sum_TotalReducesSeconds * 1 
| project UnitOfWorkId, JobReducesSeconds ) 
on UnitOfWorkId 
| join ( 
wabitrace  
| filter Timestamp >= datetime(2015-01-12 11:00:00Z)  
| filter Timestamp < datetime(2015-01-12 13:00:00Z)  
| filter EventText like "NotifyHadoopApplicationJobPerformanceCounters"  
| extend Tenant = extract("tenantName=([^,]+),", 1, EventText) 
| extend Environment = extract("environmentName=([^,]+),", 1, EventText)  
| extend JobName = extract("jobName=([^,]+),", 1, EventText)  
| extend StepName = extract("stepName=([^,]+),", 1, EventText)  
| extend UnitOfWorkId = extract("unitOfWorkId=([^,]+),", 1, EventText)  
| extend LaunchTime = extract("launchTime=([^,]+),", 1, EventText, typeof(datetime))  
| extend FinishTime = extract("finishTime=([^,]+),", 1, EventText, typeof(datetime)) 
| extend TotalLaunchedMaps = extract("totalLaunchedMaps=([^,]+),", 1, EventText, typeof(real))  
| extend TotalLaunchedReducers = extract("totalLaunchedReducers=([^,]+),", 1, EventText, typeof(real)) 
| extend MapsSeconds = extract("mapsMilliseconds=([^,]+),", 1, EventText, typeof(real)) / 1000 
| extend ReducesSeconds = extract("reducesMilliseconds=([^,]+)", 1, EventText, typeof(real)) / 1000 
| extend TotalMapsSeconds = MapsSeconds  / TotalLaunchedMaps  
| extend TotalReducesSeconds = (ReducesSeconds / TotalLaunchedReducers / ReducesSeconds) * ReducesSeconds  
| extend CalculatedDuration = (TotalMapsSeconds + TotalReducesSeconds) * time(1s) 
| filter Tenant == 'DevDiv' and Environment == 'RollupDev2') 
on UnitOfWorkId 
| extend MapsFactor = TotalMapsSeconds / JobMapsSeconds 
| extend ReducesFactor = TotalReducesSeconds / JobReducesSeconds 
| extend CurrentLoad = 1536 + (768 * TotalLaunchedMaps) + (1536 * TotalLaunchedMaps) 
| extend NormalizedLoad = 1536 + (768 * TotalLaunchedMaps * MapsFactor) + (1536 * TotalLaunchedMaps * ReducesFactor) 
| summarize sum(CurrentLoad), sum(NormalizedLoad) by  JobName  
| extend SaveFactor = sum_NormalizedLoad / sum_CurrentLoad 

Zaman içindeki eş zamanlı oturumları grafiği oluşturma

Bir etkinlik tablonuz olduğunu ve bunların başlangıç ve bitiş saatlerine sahip olduğunuzu varsayalım. Zaman içinde eşzamanlı olarak çalıştırılacak etkinlik sayısını gösteren bir grafik gösterebilirsiniz.

Aşağıda adlı Xbir örnek giriş verilmişti:

SessionId StartTime Stoptime
a 10:01:03 10:10:08
b 10:01:29 10:03:10
c 10:03:02 10:05:20

Bir dakikalık bölmelerdeki bir grafik için, her bir dakikalık aralıkta çalışan her etkinliği saymak istiyorsunuz.

Ara bir sonuç aşağıdadır:

X | extend samples = range(bin(StartTime, 1m), StopTime, 1m)

range belirtilen aralıklarda bir değer dizisi oluşturur:

SessionId StartTime Stoptime Örnekleri
a 10:01:33 10:06:31 [10:01:00,10:02:00,... 10:06:00]
b 10:02:29 10:03:45 [10:02:00,10:03:00]
c 10:03:12 10:04:30 [10:03:00,10:04:00]

Bu dizileri tutmak yerine mv-expand kullanarak genişletin:

X | mv-expand samples = range(bin(StartTime, 1m), StopTime , 1m)
SessionId StartTime Stoptime Örnekleri
a 10:01:33 10:06:31 10:01:00
a 10:01:33 10:06:31 10:02:00
a 10:01:33 10:06:31 10:03:00
a 10:01:33 10:06:31 10:04:00
a 10:01:33 10:06:31 10:05:00
a 10:01:33 10:06:31 10:06:00
b 10:02:29 10:03:45 10:02:00
b 10:02:29 10:03:45 10:03:00
c 10:03:12 10:04:30 10:03:00
c 10:03:12 10:04:30 10:04:00

Şimdi, sonuçları örnek zamana göre gruplandırın ve her etkinliğin oluşumlarını sayın:

X
| mv-expand samples = range(bin(StartTime, 1m), StopTime , 1m)
| summarize count_SessionId = count() by bin(todatetime(samples),1m)
  • mv-expand, dinamik türdeki bir sütunda sonuçladığı için kullanıntodatetime().
  • Kullanın bin() çünkü sayısal değerler ve tarihler için aralık belirtmezseniz varsayılan summarize aralığı kullanarak her zaman bir bin() işlev uygular.

Çıktı aşağıda verilmiştir:

count_SessionId Örnekleri
1 10:01:00
2 10:02:00
3 10:03:00
2 10:04:00
1 10:05:00
1 10:06:00

Sonuçları işlemek için çubuk grafik veya zaman çizelgesi kullanabilirsiniz.

Özetlemek için null bölmeler ekleme

summarize İşleç, tarih-saat sütunundan oluşan bir grup anahtarına uygulandığında, bu değerleri sabit genişlikli bölmelere bindirin:

let StartTime=ago(12h);
let StopTime=now()
T
| where Timestamp > StartTime and Timestamp <= StopTime 
| where ...
| summarize Count=count() by bin(Timestamp, 5m)

Bu örnek, beş dakikalık her bölmeye giren satır grubu başına tek bir satırı T olan bir tablo oluşturur.

Kodun gerçekleştirmediği şey , ile arasında StartTimeStopTime karşılık gelen satır Tbulunmayan zaman bölmesi değerleri için "null bölmeler" (satırlar) eklemektir. Masayı bu bölmelerle "doldurmak" iyi bir fikirdir. Bunu şu şekilde yapabilirsiniz:

let StartTime=ago(12h);
let StopTime=now()
T
| where Timestamp > StartTime and Timestamp <= StopTime 
| summarize Count=count() by bin(Timestamp, 5m)
| where ...
| union ( // 1
  range x from 1 to 1 step 1 // 2
  | mv-expand Timestamp=range(StartTime, StopTime, 5m) to typeof(datetime) // 3
  | extend Count=0 // 4
  )
| summarize Count=sum(Count) by bin(Timestamp, 5m) // 5 

Önceki sorgunun adım adım açıklaması aşağıdadır:

  1. Tabloya union daha fazla satır eklemek için işlecini kullanın. Bu satırlar ifade tarafından union oluşturulur.
  2. işleci, range tek satır ve sütuna sahip bir tablo oluşturur. Tablo üzerinde çalışmak dışında hiçbir şey için mv-expand kullanılmaz.
  3. mv-expand işlevinin range üzerindeki işleç, ile EndTimearasında StartTime beş dakikalık bölmeler olduğu kadar çok satır oluşturur.
  4. bir Count kullanın 0.
  5. summarize işleci, özgün (sol veya dış) bağımsız değişkendeki bölmeleri ile gruplandırıyorunion. İşleç ayrıca iç bağımsız değişkenden buna bölmeler (null bölme satırları). Bu işlem, çıkışın depo gözü başına değeri sıfır veya özgün sayı olan bir satırı olmasını sağlar.

Makine öğrenmesi ile Kusto kullanarak verilerinizden daha fazlasını elde edin

Birçok ilginç kullanım örneği makine öğrenmesi algoritmalarını kullanır ve telemetri verilerinden ilginç içgörüler elde eder. Bu algoritmalar genellikle giriş olarak kesin olarak yapılandırılmış bir veri kümesi gerektirir. Ham günlük verileri genellikle gerekli yapı ve boyutla eşleşmez.

Belirli bir Bing çıkarım hizmetinin hata oranındaki anomalileri arayarak başlayın. Günlükler tablosunda 65 milyar kayıt var. Aşağıdaki temel sorgu 250.000 hatayı filtreler ve ardından series_decompose_anomalies anomali algılama işlevini kullanan bir hata sayısı zaman serisi oluşturur. Anomaliler Kusto hizmeti tarafından algılanır ve zaman serisi grafiğinde kırmızı noktalar olarak vurgulanır.

Logs
| where Timestamp >= datetime(2015-08-22) and Timestamp < datetime(2015-08-23) 
| where Level == "e" and Service == "Inferences.UnusualEvents_Main" 
| summarize count() by bin(Timestamp, 5min)
| render anomalychart 

Hizmet, şüpheli hata oranlarına sahip birkaç zaman demeti tanımladı. Bu zaman çerçevesini yakınlaştırmak için Kusto kullanın. Ardından, sütunda Message toplayan bir sorgu çalıştırın. En çok karşılaşılan hataları bulmayı deneyin.

İletinin tüm yığın izlemesinin ilgili bölümleri kırpılır, böylece sonuçlar sayfaya daha iyi sığar.

İlk sekiz hatanın başarılı bir şekilde tanımlanmasını görebilirsiniz. Ancak, hata iletisi değişen verileri içeren bir biçim dizesi kullanılarak oluşturulduğundan, sonraki uzun bir hata serisidir:

Logs
| where Timestamp >= datetime(2015-08-22 05:00) and Timestamp < datetime(2015-08-22 06:00)
| where Level == "e" and Service == "Inferences.UnusualEvents_Main"
| summarize count() by Message 
| top 10 by count_ 
| project count_, Message 
count_ İleti
7125 'RunCycleFromInterimData' yöntemi için ExecuteAlgorithmMethod başarısız oldu...
7125 InferenceHostService çağrısı başarısız oldu.. System.NullReferenceException: Nesne başvurusu bir nesnenin örneğine ayarlanmadı...
7124 Beklenmeyen Çıkarım Sistemi hatası.. System.NullReferenceException: Nesne başvurusu bir nesnenin örneğine ayarlanmadı...
5112 Beklenmeyen Çıkarım Sistemi hatası.. System.NullReferenceException: Nesne başvurusu bir nesnenin örneğine ayarlanmadı..
174 InferenceHostService çağrısı başarısız oldu.. System.ServiceModel.CommunicationException: Kanala yazılırken bir hata oluştu:...
10 'RunCycleFromInterimData' yöntemi için ExecuteAlgorithmMethod başarısız oldu...
10 Çıkarım Sistemi hatası.. Microsoft. Bing. Platform.Inferences.Service.Managers.UserInterimDataManagerException:...
3 InferenceHostService çağrısı başarısız oldu.. System.ServiceModel.CommunicationObjectFaultedException:...
1 Çıkarım Sistemi hatası... SocialGraph.BOSS.OperationResponse... AIS TraceId:8292FC561AC64BED8FA243808FE74EFD...
1 Çıkarım Sistemi hatası... SocialGraph.BOSS.OperationResponse... AIS TraceId: 5F79F7587FF943EC9B641E02E701AFBF...

Bu noktada işlecini reduce kullanmak yardımcı olur. işleci, koddaki aynı izleme izleme noktasından kaynaklanan 63 farklı hata tanımladı. reduce bu zaman penceresindeki ek anlamlı hata izlemelerine odaklanmaya yardımcı olur.

Logs
| where Timestamp >= datetime(2015-08-22 05:00) and Timestamp < datetime(2015-08-22 06:00)
| where Level == "e" and Service == "Inferences.UnusualEvents_Main"
| reduce by Message with threshold=0.35
| project Count, Pattern
Count Desen
7125 'RunCycleFromInterimData' yöntemi için ExecuteAlgorithmMethod başarısız oldu...
7125 InferenceHostService çağrısı başarısız oldu.. System.NullReferenceException: Nesne başvurusu bir nesnenin örneğine ayarlanmadı...
7124 Beklenmeyen Çıkarım Sistemi hatası.. System.NullReferenceException: Nesne başvurusu bir nesnenin örneğine ayarlanmadı...
5112 Beklenmeyen Çıkarım Sistemi hatası.. System.NullReferenceException: Nesne başvurusu bir nesnenin örneğine ayarlanmadı...
174 InferenceHostService çağrısı başarısız oldu.. System.ServiceModel.CommunicationException: Kanala yazılırken bir hata oluştu:...
63 Çıkarım Sistemi hatası.. Microsoft. Bing. Platform.Inferences.*: Object BOSS'a yazmak için * yazın.*: SocialGraph.BOSS.Reques...
10 'RunCycleFromInterimData' yöntemi için ExecuteAlgorithmMethod başarısız oldu...
10 Çıkarım Sistemi hatası.. Microsoft. Bing. Platform.Inferences.Service.Managers.UserInterimDataManagerException:...
3 InferenceHostService çağrısı başarısız oldu.. System.ServiceModel.*: ** için System.ServiceModel.Channels.*+*nesnesi *... syst...

Şimdi, algılanan anomalilere katkıda bulunan en önemli hataların iyi bir görünümüne sahipsiniz.

Bu hataların örnek sistem üzerindeki etkisini anlamak için şunları göz önünde bulundurun:

  • Tabloda Logs ve Clustergibi Component ek boyutlu veriler bulunur.
  • Yeni otomatik küme eklentisi, basit bir sorguyla bileşen ve küme içgörülerini türetebilirsiniz.

Aşağıdaki örnekte, ilk dört hatanın her birinin bir bileşene özgü olduğunu açıkça görebilirsiniz. Ayrıca, ilk üç hata DB4 kümesine özgü olsa da, dördüncü hata tüm kümelerde gerçekleşir.

Logs
| where Timestamp >= datetime(2015-08-22 05:00) and Timestamp < datetime(2015-08-22 06:00)
| where Level == "e" and Service == "Inferences.UnusualEvents_Main"
| evaluate autocluster()
Count Yüzde (%) Bileşen Küme İleti
7125 26.64 InferenceHostService DB4 ExecuteAlgorithmMethod for method...
7125 26.64 Bilinmeyen Bileşen DB4 InferenceHostService çağrısı başarısız oldu...
7124 26.64 InferenceAlgorithmExecutor DB4 Beklenmeyen Çıkarım Sistemi hatası...
5112 19.11 InferenceAlgorithmExecutor * Beklenmeyen Çıkarım Sistemi hatası...

Değerleri bir kümeden diğerine eşleme

Yaygın bir sorgu kullanım örneği, değerlerin statik eşlemesidir. Statik eşleme, sonuçların daha sunulu hale getirilebilir hale getirmesini sağlayabilir.

Örneğin, sonraki tabloda DeviceModel bir cihaz modeli belirtir. Cihaz modelini kullanmak, cihaz adına başvurmak için uygun bir biçim değildir. 

DeviceModel Count
iPhone5,1 32
iPhone3,2 432
iPhone7,2 55
iPhone5,2 66

 Kolay ad kullanmak daha kullanışlıdır:

Friendlyname Count
iPhone 5 32
iPhone 4 432
iPhone 6 55
iPhone5 66

Sonraki iki örnek, bir cihazı tanımlamak için cihaz modelini kullanmaktan kolay bir ada nasıl değiştireceğini gösterir. 

Dinamik sözlük kullanarak eşleme

Eşlemeyi gerçekleştirmek için dinamik sözlük ve dinamik erişimciler kullanabilirsiniz. Örneğin:

// Dataset definition
let Source = datatable(DeviceModel:string, Count:long)
[
  'iPhone5,1', 32,
  'iPhone3,2', 432,
  'iPhone7,2', 55,
  'iPhone5,2', 66,
];
// Query start here
let phone_mapping = dynamic(
  {
    "iPhone5,1" : "iPhone 5",
    "iPhone3,2" : "iPhone 4",
    "iPhone7,2" : "iPhone 6",
    "iPhone5,2" : "iPhone5"
  });
Source 
| project FriendlyName = phone_mapping[DeviceModel], Count
Friendlyname Count
iPhone 5 32
iPhone 4 432
iPhone 6 55
iPhone5 66

Statik tablo kullanarak eşleme

Ayrıca, kalıcı bir tablo ve join işleç kullanarak eşleme elde edebilirsiniz.

  1. Eşleme tablosunu yalnızca bir kez oluşturun:

    .create table Devices (DeviceModel: string, FriendlyName: string) 
    
    .ingest inline into table Devices 
        ["iPhone5,1","iPhone 5"]["iPhone3,2","iPhone 4"]["iPhone7,2","iPhone 6"]["iPhone5,2","iPhone5"]
    
  2. Cihaz içeriğinin tablosunu oluşturun:

    DeviceModel Friendlyname
    iPhone5,1 iPhone 5
    iPhone3,2 iPhone 4
    iPhone7,2 iPhone 6
    iPhone5,2 iPhone5
  3. Test tablosu kaynağı oluşturma:

    .create table Source (DeviceModel: string, Count: int)
    
    .ingest inline into table Source ["iPhone5,1",32]["iPhone3,2",432]["iPhone7,2",55]["iPhone5,2",66]
    
  4. Tabloları birleştirin ve projeyi çalıştırın:

    Devices  
    | join (Source) on DeviceModel  
    | project FriendlyName, Count
    

Çıktı aşağıda verilmiştir:

Friendlyname Count
iPhone 5 32
iPhone 4 432
iPhone 6 55
iPhone5 66

Sorgu zamanı boyut tabloları oluşturma ve kullanma

Genellikle sorgunun sonuçlarını veritabanında depolanmayan geçici bir boyut tablosuyla birleştirmek istersiniz. Sonucu tek bir sorgu kapsamına alınmış bir tablo olan bir ifade tanımlayabilirsiniz.

Örneğin:

// Create a query-time dimension table using datatable
let DimTable = datatable(EventType:string, Code:string)
  [
    "Heavy Rain", "HR",
    "Tornado",    "T"
  ]
;
DimTable
| join StormEvents on EventType
| summarize count() by Code

İşte biraz daha karmaşık bir örnek:

// Create a query-time dimension table using datatable
let TeamFoundationJobResult = datatable(Result:int, ResultString:string)
  [
    -1, 'None', 0, 'Succeeded', 1, 'PartiallySucceeded', 2, 'Failed',
    3, 'Stopped', 4, 'Killed', 5, 'Blocked', 6, 'ExtensionNotFound',
    7, 'Inactive', 8, 'Disabled', 9, 'JobInitializationError'
  ]
;
JobHistory
  | where PreciseTimeStamp > ago(1h)
  | where Service  != "AX"
  | where Plugin has "Analytics"
  | sort by PreciseTimeStamp desc
  | join kind=leftouter TeamFoundationJobResult on Result
  | extend ExecutionTimeSpan = totimespan(ExecutionTime)
  | project JobName, StartTime, ExecutionTimeSpan, ResultString, ResultMessage

Kimlik başına en son kayıtları (zaman damgasına göre) alma

Aşağıdakileri içeren bir tablonuz olduğunu varsayalım:

  • Kullanıcı ID kimliği veya düğüm kimliği gibi her satırın ilişkilendirildiği varlığı tanımlayan bir sütun
  • timestamp Satır için zaman başvurusu sağlayan sütun
  • Diğer sütunlar

En üst iç içe işlecini kullanarak sütunun her değeri ID için en son iki kaydı döndüren bir sorgu oluşturabilirsiniz; burada en son değeri en yüksek değerine timestampsahip olarak tanımlanır:

datatable(id:string, timestamp:datetime, bla:string)           // #1
  [
  "Barak",  datetime(2015-01-01), "1",
  "Barak",  datetime(2016-01-01), "2",
  "Barak",  datetime(2017-01-20), "3",
  "Donald", datetime(2017-01-20), "4",
  "Donald", datetime(2017-01-18), "5",
  "Donald", datetime(2017-01-19), "6"
  ]
| top-nested   of id        by dummy0=max(1),                  // #2
  top-nested 2 of timestamp by dummy1=max(timestamp),          // #3
  top-nested   of bla       by dummy2=max(1)                   // #4
| project-away dummy0, dummy1, dummy2                          // #5

Yukarıdaki sorgunun adım adım açıklaması aşağıdadır (numaralandırma, kod açıklamalarındaki sayılara başvurur):

  1. datatable, tanıtım amacıyla bazı test verileri oluşturmanın bir yoludur. Normalde burada gerçek veriler kullanırsınız.
  2. Bu satır temelde tüm benzersiz değerlerini döndürme anlamına idgelir.
  3. Bu satır daha sonra ekranı kaplayan ilk iki kayıt için şunu döndürür:
    • Sütun timestamp
    • Önceki düzeyin sütunları (burada, yalnızca id)
    • Bu düzeyde belirtilen sütun (burada, timestamp)
  4. Bu satır, önceki düzey tarafından döndürülen kayıtların her biri için sütunun değerlerini bla ekler. Tabloda ilgilendiğiniz başka sütunlar varsa, bu sütunların her biri için bu satırı yineleyebilirsiniz.
  5. Son satır, tarafından top-nestedtanıtılan "ek" sütunları kaldırmak için proje dışarıda işlecini kullanır.

Tabloyu toplam hesaplama yüzdesine göre genişletme

Sayısal bir sütun içeren tablosal ifade, toplam yüzdesi olarak değeriyle birlikte geldiğinde kullanıcı için daha kullanışlıdır.

Örneğin, bir sorgunun aşağıdaki tabloyu ürettiğini varsayalım:

SomeSeries SomeInt
Apple 100
Muz 200

Tabloyu aşağıdaki gibi göstermek istiyorsunuz:

SomeSeries SomeInt Pct
Apple 100 33.3
Muz 200 66.6

Tablonun görüntülenme biçimini değiştirmek için, sütunun toplamını SomeInt (toplamı) hesaplayın ve bu sütunun her değerini toplama bölün. Rastgele sonuçlar için as işlecini kullanın.

Örneğin:

// The following table literally represents a long calculation
// that ends up with an anonymous tabular value:
datatable (SomeInt:int, SomeSeries:string) [
  100, "Apple",
  200, "Banana",
]
// We now give this calculation a name ("X"):
| as X
// Having this name we can refer to it in the sub-expression
// "X | summarize sum(SomeInt)":
| extend Pct = 100 * bin(todouble(SomeInt) / toscalar(X | summarize sum(SomeInt)), 0.001)

Kayan pencere üzerinde toplamalar gerçekleştirme

Aşağıdaki örnekte kayan pencere kullanarak sütunların nasıl özetlediği gösterilmektedir. Sorgu için, zaman damgalarına göre meyve fiyatlarını içeren aşağıdaki tabloyu kullanın.

Yedi günlük kayan bir pencere kullanarak her meyvenin günlük en düşük, en yüksek ve toplam maliyetlerini hesaplayın. Sonuç kümesindeki her kayıt önceki yedi günü toplar ve sonuçlar analiz döneminde günlük bir kayıt içerir.

Meyve masası:

Zaman damgası Meyve Fiyat
2018-09-24 21:00:00.0000000 Muz 3
2018-09-25 20:00:00.0000000 Elma 9
2018-09-26 03:00:00.0000000 Muz 4
2018-09-27 10:00:00.0000000 Erik 8
2018-09-28 07:00:00.0000000 Muz 6
2018-09-29 21:00:00.0000000 Muz 8
2018-09-30 01:00:00.0000000 Erik 2
2018-10-01 05:00:00.0000000 Muz 0
2018-10-02 02:00:00.0000000 Muz 0
2018-10-03 13:00:00.0000000 Erik 4
2018-10-04 14:00:00.0000000 Elma 8
2018-10-05 05:00:00.0000000 Muz 2
2018-10-06 08:00:00.0000000 Erik 8
2018-10-07 12:00:00.0000000 Muz 0

Kayan pencere toplama sorgusu aşağıdadır. Sorgu sonucundan sonraki açıklamaya bakın.

let _start = datetime(2018-09-24);
let _end = _start + 13d; 
Fruits 
| extend _bin = bin_at(Timestamp, 1d, _start) // #1 
| extend _endRange = iif(_bin + 7d > _end, _end, 
                            iff( _bin + 7d - 1d < _start, _start,
                                iff( _bin + 7d - 1d < _bin, _bin,  _bin + 7d - 1d)))  // #2
| extend _range = range(_bin, _endRange, 1d) // #3
| mv-expand _range to typeof(datetime) limit 1000000 // #4
| summarize min(Price), max(Price), sum(Price) by Timestamp=bin_at(_range, 1d, _start) ,  Fruit // #5
| where Timestamp >= _start + 7d; // #6

Çıktı aşağıda verilmiştir:

Zaman damgası Meyve min_Price max_Price sum_Price
2018-10-01 00:00:00.0000000 Elma 9 9 9
2018-10-01 00:00:00.0000000 Muz 0 8 18
2018-10-01 00:00:00.0000000 Erik 2 8 10
2018-10-02 00:00:00.0000000 Muz 0 8 18
2018-10-02 00:00:00.0000000 Erik 2 8 10
2018-10-03 00:00:00.0000000 Erik 2 8 14
2018-10-03 00:00:00.0000000 Muz 0 8 14
2018-10-04 00:00:00.0000000 Muz 0 8 14
2018-10-04 00:00:00.0000000 Erik 2 4 6
2018-10-04 00:00:00.0000000 Elma 8 8 8
2018-10-05 00:00:00.0000000 Muz 0 8 10
2018-10-05 00:00:00.0000000 Erik 2 4 6
2018-10-05 00:00:00.0000000 Elma 8 8 8
2018-10-06 00:00:00.0000000 Erik 2 8 14
2018-10-06 00:00:00.0000000 Muz 0 2 2
2018-10-06 00:00:00.0000000 Elma 8 8 8
2018-10-07 00:00:00.0000000 Muz 0 2 2
2018-10-07 00:00:00.0000000 Erik 4 8 12
2018-10-07 00:00:00.0000000 Elma 8 8 8

Sorgu, giriş tablosundaki her kaydı gerçek görünümünden sonraki yedi gün boyunca "genişletir" (çoğaltır). Her kayıt aslında yedi kez görünür. Sonuç olarak, günlük toplama önceki yedi günün tüm kayıtlarını içerir.

Önceki sorgunun adım adım açıklaması aşağıdadır:

  1. Her kaydı bir gün olarak depola (ile _startilgili).
  2. Kayıt başına aralığın sonunu belirleyin: _bin + 7d, değer ve _endaralığının _start dışında olmadığı sürece, bu durumda ayarlanır.
  3. Her kayıt için, geçerli kaydın gününden başlayarak yedi günlük bir dizi (zaman damgası) oluşturun.
  4. mv-expand dizisi, böylece her kaydı birbirinden bir gün ayrı yedi kayda çoğaltarak.
  5. Her gün için toplama işlevini gerçekleştirin. #4 nedeniyle, bu adım aslında son yedi günü özetler.
  6. İlk yedi güne ait veriler eksiktir çünkü ilk yedi gün için yedi günlük bir geri arama dönemi yoktur. İlk yedi gün nihai sonucun dışında tutulur. Örnekte, yalnızca 2018-10-01 için toplamaya katılırlar.

Önceki olayı bulma

Sonraki örnek, iki veri kümesi arasında önceki bir olayın nasıl bulunduğunu gösterir.

A ve B olmak üzere iki veri kümeniz vardır. B veri kümesindeki her kayıt için, A veri kümesinde önceki olayını (yani arg_max A'daki kayıt hala B'den eski olan kayıt) bulun.

Örnek veri kümeleri şunlardır:

let A = datatable(Timestamp:datetime, ID:string, EventA:string)
[
    datetime(2019-01-01 00:00:00), "x", "Ax1",
    datetime(2019-01-01 00:00:01), "x", "Ax2",
    datetime(2019-01-01 00:00:02), "y", "Ay1",
    datetime(2019-01-01 00:00:05), "y", "Ay2",
    datetime(2019-01-01 00:00:00), "z", "Az1"
];
let B = datatable(Timestamp:datetime, ID:string, EventB:string)
[
    datetime(2019-01-01 00:00:03), "x", "B",
    datetime(2019-01-01 00:00:04), "x", "B",
    datetime(2019-01-01 00:00:04), "y", "B",
    datetime(2019-01-01 00:02:00), "z", "B"
];
A; B
Zaman damgası ID EventB
2019-01-01 00:00:00.0000000 x Ax1
2019-01-01 00:00:00.0000000 z Az1
2019-01-01 00:00:01.0000000 x Ax2
2019-01-01 00:00:02.0000000 y Ay1
2019-01-01 00:00:05.0000000 y Ay2

Zaman damgası ID OlayA
2019-01-01 00:00:03.0000000 x B
2019-01-01 00:00:04.0000000 x B
2019-01-01 00:00:04.0000000 y B
2019-01-01 00:02:00.0000000 z B

Beklenen çıktı:

ID Zaman damgası OlayB A_Timestamp EventA
x 2019-01-01 00:00:03.0000000 B 2019-01-01 00:00:01.0000000 Ax2
x 2019-01-01 00:00:04.0000000 B 2019-01-01 00:00:01.0000000 Ax2
y 2019-01-01 00:00:04.0000000 B 2019-01-01 00:00:02.0000000 Ay1
z 2019-01-01 00:02:00.0000000 B 2019-01-01 00:00:00.0000000 Az1

Bu sorun için iki farklı yaklaşım önerilir. Senaryonuza en uygun olanı bulmak için her ikisini de kendi veri kümenizde test edebilirsiniz.

Not

Her yaklaşım farklı veri kümelerinde farklı çalıştırılabilir.

Yaklaşım 1

Bu yaklaşım hem veri kümelerini kimliğe hem de zaman damgasına göre seri hale getirmektedir. Ardından, B veri kümesindeki tüm olayları A veri kümesindeki önceki tüm olaylarıyla gruplandırıyor. Son olarak, gruptaki arg_max A veri kümesindeki tüm olayları seçer.

A
| extend A_Timestamp = Timestamp, Kind="A"
| union (B | extend B_Timestamp = Timestamp, Kind="B")
| order by ID, Timestamp asc 
| extend t = iff(Kind == "A" and (prev(Kind) != "A" or prev(Id) != ID), 1, 0)
| extend t = row_cumsum(t)
| summarize Timestamp=make_list(Timestamp), EventB=make_list(EventB), arg_max(A_Timestamp, EventA) by t, ID
| mv-expand Timestamp to typeof(datetime), EventB to typeof(string)
| where isnotempty(EventB)
| project-away t

Yaklaşım 2

Sorunu çözmek için bu yaklaşım için maksimum geri arama süresi gerekir. Yaklaşım, A veri kümesindeki kaydın B veri kümesiyle ne kadar eski olabileceğini gösterir. Yöntemi daha sonra kimlik ve bu geri arama dönemine göre iki veri kümesini birleştirir.

tüm join olası adayları ve B veri kümesindeki kayıtlardan daha eski olan ve geri arama dönemi içinde bulunan tüm veri kümesi A kayıtlarını üretir. Ardından, B veri kümesine en yakın olan tarafından filtrelenmiş arg_min (TimestampB - TimestampA)olur. Geri arama süresi ne kadar kısa olursa, sorgu sonuçları o kadar iyi olur.

Aşağıdaki örnekte, geri arama dönemi olarak 1mayarlanmıştır. Kimliği z olan kaydın olayı iki dakika daha eski olduğundan A buna karşılık gelen A bir olay yoktur.

let _maxLookbackPeriod = 1m;  
let _internalWindowBin = _maxLookbackPeriod / 2;
let B_events = B 
    | extend ID = new_guid()
    | extend _time = bin(Timestamp, _internalWindowBin)
    | extend _range = range(_time - _internalWindowBin, _time + _maxLookbackPeriod, _internalWindowBin) 
    | mv-expand _range to typeof(datetime) 
    | extend B_Timestamp = Timestamp, _range;
let A_events = A 
    | extend _time = bin(Timestamp, _internalWindowBin)
    | extend _range = range(_time - _internalWindowBin, _time + _maxLookbackPeriod, _internalWindowBin) 
    | mv-expand _range to typeof(datetime) 
    | extend A_Timestamp = Timestamp, _range;
B_events
    | join kind=leftouter (
        A_events
) on ID, _range
| where isnull(A_Timestamp) or (A_Timestamp <= B_Timestamp and B_Timestamp <= A_Timestamp + _maxLookbackPeriod)
| extend diff = coalesce(B_Timestamp - A_Timestamp, _maxLookbackPeriod*2)
| summarize arg_min(diff, *) by ID
| project ID, B_Timestamp, A_Timestamp, EventB, EventA
ID B_Timestamp A_Timestamp OlayB EventA
x 2019-01-01 00:00:03.0000000 2019-01-01 00:00:01.0000000 B Ax2
x 2019-01-01 00:00:04.0000000 2019-01-01 00:00:01.0000000 B Ax2
y 2019-01-01 00:00:04.0000000 2019-01-01 00:00:02.0000000 B Ay1
z 2019-01-01 00:02:00.0000000 B

Sonraki adımlar

Bu makalede Azure İzleyici'deki yaygın sorgu gereksinimleri ve bunları karşılamak için Kusto Sorgu Dili nasıl kullanabileceğiniz tanımlanmaktadır.

Dize işlemleri

Aşağıdaki bölümlerde, Kusto Sorgu Dili kullanırken dizelerle çalışma örnekleri verilmiştir.

Dizeler ve kaçış yöntemleri

Dize değerleri tek veya çift tırnak içine alınır. Karakterin soluna ters eğik çizgi (\) ekleyerek karakterden kaçabilirsiniz: \t sekme, yeni satır, \n\' tek tırnak karakteri ve \" çift tırnak karakteri.

print "this is a 'string' literal in double \" quotes"
print 'this is a "string" literal in single \' quotes'

"\" öğesinin kaçış karakteri olarak davranmasını önlemek için dizeye ön ek olarak "@" ekleyin:

print @"C:\backslash\not\escaped\with @ prefix"

Dize karşılaştırmaları

İşleç Açıklama Duyarlı Örnek (ödemeler true)
== Eşittir Yes "aBc" == "aBc"
!= Eşit değil Yes "abc" != "ABC"
=~ Eşittir No "abc" =~ "ABC"
!~ Eşit değil No "aBc" !~ "xyz"
has Sağ taraftaki değer, sol taraftaki değerdeki terimin tamamıdır No "North America" has "america"
!has Sağ taraftaki değer, sol taraftaki değerde tam bir terim değildir No "North America" !has "amer"
has_cs Sağ taraftaki değer, sol taraftaki değerdeki terimin tamamıdır Yes "North America" has_cs "America"
!has_cs Sağ taraftaki değer, sol taraftaki değerde tam bir terim değildir Yes "North America" !has_cs "amer"
hasprefix Sağ taraftaki değer, sol taraftaki değerde bir terim ön ekidir No "North America" hasprefix "ame"
!hasprefix Sağ taraftaki değer, sol taraftaki değerde terim ön eki değildir No "North America" !hasprefix "mer"
hasprefix_cs Sağ taraftaki değer, sol taraftaki değerde bir terim ön ekidir Yes "North America" hasprefix_cs "Ame"
!hasprefix_cs Sağ taraftaki değer, sol taraftaki değerde terim ön eki değildir Yes "North America" !hasprefix_cs "CA"
hassuffix Sağ taraftaki değer, sol taraftaki değerde bir terim sonekidir No "North America" hassuffix "ica"
!hassuffix Sağ taraftaki değer, sol taraftaki değerde terim soneki değildir No "North America" !hassuffix "americ"
hassuffix_cs Sağ taraftaki değer, sol taraftaki değerde bir terim sonekidir Yes "North America" hassuffix_cs "ica"
!hassuffix_cs Sağ taraftaki değer, sol taraftaki değerde terim soneki değildir Yes "North America" !hassuffix_cs "icA"
contains Sağ taraftaki değer, sol taraftaki değerin alt dizileri olarak gerçekleşir No "FabriKam" contains "BRik"
!contains Sağ taraftaki değer sol taraftaki değerde oluşmaz No "Fabrikam" !contains "xyz"
contains_cs Sağ taraftaki değer, sol taraftaki değerin alt dizileri olarak gerçekleşir Yes "FabriKam" contains_cs "Kam"
!contains_cs Sağ taraftaki değer sol taraftaki değerde oluşmaz Yes "Fabrikam" !contains_cs "Kam"
startswith Sağ taraftaki değer, sol taraftaki değerin ilk alt dizisini oluşturur No "Fabrikam" startswith "fab"
!startswith Sağ taraftaki değer, sol taraftaki değerin ilk alt sıralarından biri değildir No "Fabrikam" !startswith "kam"
startswith_cs Sağ taraftaki değer, sol taraftaki değerin ilk alt dizisini oluşturur Yes "Fabrikam" startswith_cs "Fab"
!startswith_cs Sağ taraftaki değer, sol taraftaki değerin ilk alt sıralarından biri değildir Yes "Fabrikam" !startswith_cs "fab"
endswith Sağ taraftaki değer, sol taraftaki değerin kapanış alt dizidir No "Fabrikam" endswith "Kam"
!endswith Sağ taraftaki değer, sol taraftaki değerin kapanış alt dizileri değildir No "Fabrikam" !endswith "brik"
endswith_cs Sağ taraftaki değer, sol taraftaki değerin kapanış alt dizidir Yes "Fabrikam" endswith "Kam"
!endswith_cs Sağ taraftaki değer, sol taraftaki değerin kapanış alt dizileri değildir Yes "Fabrikam" !endswith "brik"
matches regex Sol taraftaki değer, sağ taraftaki değer için bir eşleşme içeriyor Yes "Fabrikam" matches regex "b.*k"
in Öğelerden birine eşittir Yes "abc" in ("123", "345", "abc")
!in Öğelerin hiçbirine eşit değildir Yes "bca" !in ("123", "345", "abc")

countof

Bir dize içindeki alt dizenin oluşumlarını sayar. Düz dizelerle eşleşebilir veya normal ifade (regex) kullanabilir. Düz dize eşleşmeleri çakışabilir, ancak regex eşleşmeleri çakışmaz.

countof(text, search [, kind])
  • text: Giriş dizesi
  • search: Metnin içinde eşleşecek düz dize veya regex
  • kind: normalregex | (varsayılan: normal).

Arama dizesinin kapsayıcıda kaç kez eşleştirilebileceğini döndürür. Düz dize eşleşmeleri çakışabilir, ancak regex eşleşmeleri çakışmaz.

Düz dize eşleşmeleri

print countof("The cat sat on the mat", "at");  //result: 3
print countof("aaa", "a");  //result: 3
print countof("aaaa", "aa");  //result: 3 (not 2!)
print countof("ababa", "ab", "normal");  //result: 2
print countof("ababa", "aba");  //result: 2

Regex eşleşmeleri

print countof("The cat sat on the mat", @"\b.at\b", "regex");  //result: 3
print countof("ababa", "aba", "regex");  //result: 1
print countof("abcabc", "a.c", "regex");  // result: 2

Ayıklamak

Belirli bir dizeden normal ifade için eşleşme alır. İsteğe bağlı olarak, ayıklanan alt dizeyi belirtilen türe dönüştürebilir.

extract(regex, captureGroup, text [, typeLiteral])
  • regex: Normal ifade.
  • captureGroup: Ayıklanması gereken yakalama grubunu gösteren pozitif bir tamsayı sabiti. Eşleşmenin tamamı için 0, normal ifadedeki ilk parantez () ile eşleşen değer için 1 ve sonraki parantezler için 2 veya daha fazla kullanın.
  • text - Aranacak dize.
  • typeLiteral - İsteğe bağlı bir tür değişmez değeri (örneğin, typeof(long)). Sağlanırsa, ayıklanan alt dize bu türe dönüştürülür.

belirtilen yakalama grubuyla captureGroupeşleşen alt dizeyi döndürür. İsteğe bağlı olarak öğesine typeLiteraldönüştürülür. Eşleşme yoksa veya tür dönüştürmesi başarısız olursa null döndürür.

Aşağıdaki örnek, sinyal kaydından son sekizlisini ComputerIP ayıklar:

Heartbeat
| where ComputerIP != "" 
| take 1
| project ComputerIP, last_octet=extract("([0-9]*$)", 1, ComputerIP) 

Aşağıdaki örnek son sekizliyi ayıklar, gerçek bir türe (sayı) dönüştürür ve sonraki IP değerini hesaplar:

Heartbeat
| where ComputerIP != "" 
| take 1
| extend last_octet=extract("([0-9]*$)", 1, ComputerIP, typeof(real)) 
| extend next_ip=(last_octet+1)%255
| project ComputerIP, last_octet, next_ip

Sonraki örnekte, dizenin Trace tanımı Durationarandı. Eşleşme türüne real atılır ve bir zaman sabiti (1 sn) ile çarpılır ve ardından türüne timespanatılırDuration.

let Trace="A=12, B=34, Duration=567, ...";
print Duration = extract("Duration=([0-9.]+)", 1, Trace, typeof(real));  //result: 567
print Duration_seconds =  extract("Duration=([0-9.]+)", 1, Trace, typeof(real)) * time(1s);  //result: 00:09:27

isempty, isnotempty, notempty

  • isempty bağımsız değişken boş dize veya null ise döndürür true (bkz isnull. ).
  • isnotempty bağımsız değişken boş dize veya null değilse döndürür true (bkz isnotnull. ). Diğer ad: notempty.
isempty(value)
isnotempty(value)

Örnek

print isempty("");  // result: true

print isempty("0");  // result: false

print isempty(0);  // result: false

print isempty(5);  // result: false

Heartbeat | where isnotempty(ComputerIP) | take 1  // return 1 Heartbeat record in which ComputerIP isn't empty

parseurl

Bir URL'yi protokol, konak ve bağlantı noktası gibi bölümlerine böler ve ardından bölümleri dize olarak içeren bir sözlük nesnesi döndürür.

parseurl(urlstring)

Örnek

print parseurl("http://user:pass@contoso.com/icecream/buy.aspx?a=1&b=2#tag")

Çıktı aşağıda verilmiştir:

{
	"Scheme" : "http",
	"Host" : "contoso.com",
	"Port" : "80",
	"Path" : "/icecream/buy.aspx",
	"Username" : "user",
	"Password" : "pass",
	"Query Parameters" : {"a":"1","b":"2"},
	"Fragment" : "tag"
}

Değiştirmek

Tüm regex eşleşmelerini başka bir dizeyle değiştirir.

replace(regex, rewrite, input_text)
  • regex: Eşleştirecek normal ifade. Parantez içinde yakalama grupları () içerebilir.
  • rewrite: Bir regex ile eşleştirilerek yapılan herhangi bir eşleşmenin yedek regex'i. Eşleşmenin tamamına başvurmak için \0, ilk yakalama grubu için \1, sonraki yakalama grupları için \2 vb. kullanın.
  • input_text: Aranacak giriş dizesi.

Regex'in tüm eşleşmelerini yeniden yazma değerlendirmeleriyle değiştirdikten sonra metni döndürür. Eşleşmeler çakışmaz.

Örnek

SecurityEvent
| take 1
| project Activity 
| extend replaced = replace(@"(\d+) -", @"Activity ID \1: ", Activity) 

Çıktı aşağıda verilmiştir:

Etkinlik Değiştirilir
4663 - Bir nesneye erişme girişiminde bulunuldu Etkinlik Kimliği 4663: Bir nesneye erişme girişiminde bulunuldu.

Split

Belirli bir dizeyi belirtilen sınırlayıcıya göre böler ve ardından sonuçta elde edilen alt dizelerin bir dizisini döndürür.

split(source, delimiter [, requestedIndex])
  • source: Belirtilen sınırlayıcıya göre bölünecek dize.
  • delimiter: Kaynak dizeyi bölmek için kullanılacak sınırlayıcı.
  • requestedIndex: İsteğe bağlı sıfır tabanlı dizin. Sağlanırsa, döndürülen dize dizisi yalnızca bu öğeyi (varsa) tutar.

Örnek

print split("aaa_bbb_ccc", "_");    // result: ["aaa","bbb","ccc"]
print split("aa_bb", "_");          // result: ["aa","bb"]
print split("aaa_bbb_ccc", "_", 1);	// result: ["bbb"]
print split("", "_");              	// result: [""]
print split("a__b", "_");           // result: ["a","","b"]
print split("aabbcc", "bb");        // result: ["aa","cc"]

strcat

Dize bağımsız değişkenlerini birleştirir (1-16 bağımsız değişkenlerini destekler).

strcat("string1", "string2", "string3")

Örnek

print strcat("hello", " ", "world")	// result: "hello world"

Strlen

Bir dizenin uzunluğunu döndürür.

strlen("text_to_evaluate")

Örnek

print strlen("hello")	// result: 5

Dize

Belirtilen dizinden başlayarak belirli bir kaynak dizeden bir alt dize ayıklar. İsteğe bağlı olarak, istenen alt dizenin uzunluğunu belirtebilirsiniz.

substring(source, startingIndex [, length])
  • source: Alt dizenin alındığı kaynak dize.
  • startingIndex: İstenen alt dizenin sıfır tabanlı başlangıç karakteri konumu.
  • length: Döndürülen alt dizenin istenen uzunluğunu belirtmek için kullanabileceğiniz isteğe bağlı bir parametre.

Örnek

print substring("abcdefg", 1, 2);	// result: "bc"
print substring("123456", 1);		// result: "23456"
print substring("123456", 2, 2);	// result: "34"
print substring("ABCD", 0, 2);	// result: "AB"

tolower,upper

Belirli bir dizeyi tümü küçük harfe veya tümü büyük harfe dönüştürür.

tolower("value")
toupper("value")

Örnek

print tolower("HELLO");	// result: "hello"
print toupper("hello");	// result: "HELLO"

Tarih ve saat işlemleri

Aşağıdaki bölümlerde, Kusto Sorgu Dili kullanırken tarih ve saat değerleriyle çalışma örnekleri verilmiştir.

Tarih-saat temel bilgileri

Kusto Sorgu Dili tarih ve saatlerle ilişkili iki ana veri türü vardır: datetime ve timespan. Tüm tarihler UTC olarak ifade edilir. Birden çok tarih-saat biçimi desteklense de ISO-8601 biçimi tercih edilir.

Zaman aralığı ondalık olarak ve ardından bir zaman birimi olarak ifade edilir:

Steno Zaman birimi
d gün
h saat
m dakika
s saniye
Bayan milisaniye
Microsecond Microsecond
Kene Içerir

işlecini kullanarak todatetime bir dize yayınlayarak tarih-saat değerleri oluşturabilirsiniz. Örneğin, belirli bir zaman aralığında gönderilen VM sinyallerini gözden geçirmek için işlecini between kullanarak bir zaman aralığı belirtin:

Heartbeat
| where TimeGenerated between(datetime("2018-06-30 22:46:42") .. datetime("2018-07-01 00:57:27"))

Bir diğer yaygın senaryo da tarih-saat değerini günümüzle karşılaştırmaktır. Örneğin, son iki dakikadaki tüm sinyalleri görmek için işlecini iki dakikayı now temsil eden bir zaman aralığıyla birlikte kullanabilirsiniz:

Heartbeat
| where TimeGenerated > now() - 2m

Bu işlev için bir kısayol da kullanılabilir:

Heartbeat
| where TimeGenerated > now(-2m)

En kısa ve en okunabilir yöntem işlecini ago kullanmaktır:

Heartbeat
| where TimeGenerated > ago(2m)

Başlangıç ve bitiş saatlerini bilmek yerine başlangıç saatini ve süresini bildiğinizi varsayalım. Sorguyu yeniden yazabilirsiniz:

let startDatetime = todatetime("2018-06-30 20:12:42.9");
let duration = totimespan(25m);
Heartbeat
| where TimeGenerated between(startDatetime .. (startDatetime+duration) )
| extend timeFromStart = TimeGenerated - startDatetime

Zaman birimlerini dönüştürme

Tarih-saat veya zaman aralığı değerini varsayılan değer dışında bir zaman biriminde ifade etmek isteyebilirsiniz. Örneğin, son 30 dakikadaki hata olaylarını gözden geçiriyorsanız ve olayın ne kadar önce gerçekleştiğini gösteren bir hesaplanmış sütuna ihtiyacınız varsa şu sorguyu kullanabilirsiniz:

Event
| where TimeGenerated > ago(30m)
| where EventLevelName == "Error"
| extend timeAgo = now() - TimeGenerated 

Sütun, timeAgo gibi hh:mm:ss.fffffff olarak biçimlendirilmiş değerleri 00:09:31.5118992tutar. Bu değerleri başlangıç zamanından bu yana dakika number cinsinden biçimlendirmek istiyorsanız, bu değeri 1mdeğerine bölün:

Event
| where TimeGenerated > ago(30m)
| where EventLevelName == "Error"
| extend timeAgo = now() - TimeGenerated
| extend timeAgoMinutes = timeAgo/1m 

Zaman aralıklarına göre toplamalar ve demetlemeler

Bir diğer yaygın senaryo ise belirli bir zaman birimindeki belirli bir zaman aralığına ait istatistikleri elde etme gereksinimidir. Bu senaryo için bir işleci yan bin tümcesinin summarize parçası olarak kullanabilirsiniz.

Son yarım saat içinde beş dakikada bir gerçekleşen olayların sayısını almak için aşağıdaki sorguyu kullanın:

Event
| where TimeGenerated > ago(30m)
| summarize events_count=count() by bin(TimeGenerated, 5m) 

Bu sorgu aşağıdaki tabloyu oluşturur:

TimeGenerated(UTC) events_count
2018-08-01T09:30:00 54
2018-08-01T09:35:00 41
2018-08-01T09:40:00 42
2018-08-01T09:45:00 41
2018-08-01T09:50:00 41
2018-08-01T09:55:00 16

Sonuç demetleri oluşturmanın bir diğer yolu da gibi startofdayişlevleri kullanmaktır:

Event
| where TimeGenerated > ago(4d)
| summarize events_count=count() by startofday(TimeGenerated) 

Çıktı aşağıda verilmiştir:

timestamp count_
2018-07-28T00:00:00 7,136
2018-07-29T00:00:00 12,315
2018-07-30T00:00:00 16,847
2018-07-31T00:00:00 12,616
2018-08-01T00:00:00 5,416

Saat dilimleri

Tüm tarih-saat değerleri UTC ile ifade edildiğinden, genellikle bu değerleri yerel saat dilimine dönüştürmek yararlı olur. Örneğin, UTC'yi PST saatlerine dönüştürmek için bu hesaplamayı kullanın:

Event
| extend localTimestamp = TimeGenerated - 8h

Toplamalar

Aşağıdaki bölümlerde, Kusto Sorgu Dili kullanırken bir sorgunun sonuçlarını toplamaya ilişkin örnekler verilmiştir.

Sayısı

Filtre uygulandıktan sonra sonuç kümesindeki satır sayısını sayma. Aşağıdaki örnek, tablodaki son 30 dakikadaki Perf toplam satır sayısını döndürür. Sonuçlar, sütuna belirli bir ad atamadığınız sürece adlı count_ bir sütunda döndürülür:

Perf
| where TimeGenerated > ago(30m) 
| summarize count()
Perf
| where TimeGenerated > ago(30m) 
| summarize num_of_records=count() 

Zaman çizelgesi görselleştirmeleri zaman içindeki eğilimi görmek için yararlı olabilir:

Perf 
| where TimeGenerated > ago(30m) 
| summarize count() by bin(TimeGenerated, 5m)
| render timechart

Bu örnekteki çıkış, beş dakikalık aralıklarla kayıt sayısı eğilim çizgisini gösterir Perf :

Screenshot of a line chart that shows the Perf record count trend line in five-minute intervals.

dcount, dcountif

Belirli bir sütundaki ayrı değerleri saymak için ve dcountif kullanındcount. Aşağıdaki sorgu, son bir saat içinde kaç ayrı bilgisayarın sinyal gönderdiğini değerlendirir:

Heartbeat 
| where TimeGenerated > ago(1h) 
| summarize dcount(Computer)

Yalnızca sinyal gönderen Linux bilgisayarları saymak için kullanın dcountif:

Heartbeat 
| where TimeGenerated > ago(1h) 
| summarize dcountif(Computer, OSType=="Linux")

Alt grupları değerlendirme

Verilerinizdeki alt gruplarda sayım veya diğer toplamaları gerçekleştirmek için anahtar sözcüğünü by kullanın. Örneğin, her ülkede veya bölgede sinyal gönderen ayrı Linux bilgisayarlarının sayısını saymak için şu sorguyu kullanın:

Heartbeat 
| where TimeGenerated > ago(1h) 
| summarize distinct_computers=dcountif(Computer, OSType=="Linux") by RemoteIPCountry
RemoteIPCountry distinct_computers
Birleşik Devletler 19
Kanada 3
İrlanda 0
Birleşik Krallık 0
Hollanda 2

Verilerinizin daha küçük alt gruplarını analiz etmek için bölüme by sütun adları ekleyin. Örneğin, işletim sistemi türü başına her bir ülke veya bölgeden ayrı bilgisayarları saymak isteyebilirsiniz (OSType):

Heartbeat 
| where TimeGenerated > ago(1h) 
| summarize distinct_computers=dcountif(Computer, OSType=="Linux") by RemoteIPCountry, OSType

Yüzdebirlik

Ortanca değeri bulmak için işlevini bir değerle birlikte kullanarak percentile yüzdebirlik değeri belirtin:

Perf
| where TimeGenerated > ago(30m) 
| where CounterName == "% Processor Time" and InstanceName == "_Total" 
| summarize percentiles(CounterValue, 50) by Computer

Ayrıca, her birine yönelik bir toplu sonuç almak için farklı yüzdebirlik dilimler de belirtebilirsiniz:

Perf
| where TimeGenerated > ago(30m) 
| where CounterName == "% Processor Time" and InstanceName == "_Total" 
| summarize percentiles(CounterValue, 25, 50, 75, 90) by Computer

Sonuçlar bazı bilgisayar CPU'larının benzer ortanca değerlere sahip olduğunu gösterebilir. Ancak, bazı bilgisayarlar ortanca değer etrafında sabit olsa da, diğerleri çok daha düşük ve daha yüksek CPU değerleri bildirdi. Yüksek ve düşük değerler, bilgisayarların ani artışlarla karşılaştığı anlamına gelir.

Varyans

Bir değerin varyansını doğrudan değerlendirmek için standart sapma ve varyans yöntemlerini kullanın:

Perf
| where TimeGenerated > ago(30m) 
| where CounterName == "% Processor Time" and InstanceName == "_Total" 
| summarize stdev(CounterValue), variance(CounterValue) by Computer

CPU kullanımının kararlılığını analiz etmenin iyi bir yolu, ortanca hesaplama ile birleştirmektir stdev :

Perf
| where TimeGenerated > ago(130m) 
| where CounterName == "% Processor Time" and InstanceName == "_Total" 
| summarize stdev(CounterValue), percentiles(CounterValue, 50) by Computer

Listeler ve kümeler oluşturma

Verileri belirli bir sütundaki değerlerin sırasına göre özetlerken kullanabilirsiniz makelist . Örneğin, bilgisayarlarınızda gerçekleşen en yaygın sıra olaylarını keşfetmek isteyebilirsiniz. Verileri temelde her bilgisayardaki değerlerin EventID sırasına göre özetleyebilirsiniz:

Event
| where TimeGenerated > ago(12h)
| order by TimeGenerated desc
| summarize makelist(EventID) by Computer

Çıktı aşağıda verilmiştir:

Bilgisayar list_EventID
bilgisayar1 [704,701,1501,1500,1085,704,704,701]
bilgisayar2 [326,105,302,301,300,102]
... ...

makelist , verilerin bu listeye geçirildiği sırada bir liste oluşturur. Olayları en eskiden en yeniye sıralamak için yerine deyiminde orderdesckullanınasc.

Yalnızca farklı değerlerin listesini oluşturmak yararlı olabilir. Bu listeye küme adı verilir ve komutunu kullanarak makeset oluşturabilirsiniz:

Event
| where TimeGenerated > ago(12h)
| order by TimeGenerated desc
| summarize makeset(EventID) by Computer

Çıktı aşağıda verilmiştir:

Bilgisayar list_EventID
bilgisayar1 [704,701,1501,1500,1085]
bilgisayar2 [326,105,302,301,300,102]
... ...

gibi makelist, makeset sıralı verilerle de çalışır. komutu, makeset içine geçirilen satırların sırasına göre diziler oluşturur.

Listeleri genişletme

veya öğesinin makelist ters işlemidirmv-expand.makeset komut, mv-expand değerlerin listesini genişleterek satırları ayırır. JSON ve dizi sütunları da dahil olmak üzere herhangi bir sayıda dinamik sütun arasında genişletilebilir. Örneğin, son bir saat içinde sinyal gönderen bilgisayarlardan veri gönderen çözümler için tabloya bakabilirsiniz Heartbeat :

Heartbeat
| where TimeGenerated > ago(1h)
| project Computer, Solutions

Çıktı aşağıda verilmiştir:

Bilgisayar Çözümler
bilgisayar1 "security", "updates", "changeTracking"
bilgisayar2 "security", "updates"
bilgisayar3 "antiMalware", "changeTracking"
... ...

Her değeri virgülle ayrılmış liste yerine ayrı bir satırda göstermek için kullanın mv-expand :

Heartbeat
| where TimeGenerated > ago(1h)
| project Computer, split(Solutions, ",")
| mv-expand Solutions

Çıktı aşağıda verilmiştir:

Bilgisayar Çözümler
bilgisayar1 "güvenlik"
bilgisayar1 "güncelleştirmeler"
bilgisayar1 "changeTracking"
bilgisayar2 "güvenlik"
bilgisayar2 "güncelleştirmeler"
bilgisayar3 "kötü amaçlı yazılımdan koruma"
bilgisayar3 "changeTracking"
... ...

Öğeleri birlikte gruplandırmak için kullanabilirsiniz makelist . Çıktıda, çözüm başına bilgisayar listesini görebilirsiniz:

Heartbeat
| where TimeGenerated > ago(1h)
| project Computer, split(Solutions, ",")
| mv-expand Solutions
| summarize makelist(Computer) by tostring(Solutions) 

Çıktı aşağıda verilmiştir:

Çözümler list_Computer
"güvenlik" ["bilgisayar1", "bilgisayar2"]
"güncelleştirmeler" ["bilgisayar1", "bilgisayar2"]
"changeTracking" ["bilgisayar1", "bilgisayar3"]
"kötü amaçlı yazılımdan koruma" ["bilgisayar3"]
... ...

Eksik bölmeler

uygulamasının mv-expand kullanışlı bir uygulaması eksik bölmeler için varsayılan değerleri doldurmaktır. Örneğin, belirli bir bilgisayarın sinyalini keşfederek çalışma süresini aradığınızı varsayalım. Ayrıca, sütunundaki Category sinyalin kaynağını da görmek istiyorsunuz. Normalde temel summarize bir deyim kullanırız:

Heartbeat
| where TimeGenerated > ago(12h)
| summarize count() by Category, bin(TimeGenerated, 1h)

Çıktı aşağıda verilmiştir:

Kategori TimeGenerated count_
Doğrudan Aracı 2017-06-06T17:00:00Z 15
Doğrudan Aracı 2017-06-06T18:00:00Z 60
Doğrudan Aracı 2017-06-06T20:00:00Z 55
Doğrudan Aracı 2017-06-06T21:00:00Z 57
Doğrudan Aracı 2017-06-06T22:00:00Z 60
... ... ...

Çıkışta, "2017-06-06T19:00:00Z" ile ilişkili demet eksiktir çünkü bu saat için sinyal verisi yoktur. make-series Boş demetlere varsayılan değer atamak için işlevini kullanın. Her kategori için bir satır oluşturulur. Çıkış, biri değerler ve diğeri de eşleşen zaman demetleri için iki ek dizi sütunu içerir:

Heartbeat
| make-series count() default=0 on TimeGenerated in range(ago(1d), now(), 1h) by Category 

Çıktı aşağıda verilmiştir:

Kategori count_ TimeGenerated
Doğrudan Aracı [15,60,0,55,60,57,60,...] ["2017-06-06T17:00:00.0000000Z","2017-06-06T18:00:00.0000000Z","2017-06-06T19:00:00.0000000Z","2017-06-06T20:00:00.0000000Z","2017-06-06T21:00:00.0000000Z",...]
... ... ...

count_ dizisinin üçüncü öğesi beklendiği gibi 0'dır. TimeGenerated dizisinin "2017-06-06T19:00:00.0000000Z" eşleşen zaman damgası vardır. Ancak, bu dizi biçimini okumak zordur. Dizileri genişletmek ve tarafından summarizeoluşturulanla aynı biçim çıkışını üretmek için kullanınmv-expand:

Heartbeat
| make-series count() default=0 on TimeGenerated in range(ago(1d), now(), 1h) by Category 
| mv-expand TimeGenerated, count_
| project Category, TimeGenerated, count_

Çıktı aşağıda verilmiştir:

Kategori TimeGenerated count_
Doğrudan Aracı 2017-06-06T17:00:00Z 15
Doğrudan Aracı 2017-06-06T18:00:00Z 60
Doğrudan Aracı 2017-06-06T19:00:00Z 0
Doğrudan Aracı 2017-06-06T20:00:00Z 55
Doğrudan Aracı 2017-06-06T21:00:00Z 57
Doğrudan Aracı 2017-06-06T22:00:00Z 60
... ... ...

Sonuçları bir öğe kümesine daraltın: let, makeset, toscalar, in

Yaygın bir senaryo, bir ölçüt kümesine göre belirli varlıkların adlarını seçmek ve ardından farklı bir veri kümesini bu varlık kümesine göre filtrelemektir. Örneğin, eksik güncelleştirmeleri olduğu bilinen bilgisayarları bulabilir ve bu bilgisayarların çağrıldığı IP adreslerini tanımlayabilirsiniz.

Aşağıda bir örnek verilmiştir:

let ComputersNeedingUpdate = toscalar(
    Update
    | summarize makeset(Computer)
    | project set_Computer
);
WindowsFirewall
| where Computer in (ComputersNeedingUpdate)

Birleştirmeler

Birleştirmeleri kullanarak aynı sorgudaki birden çok tablodaki verileri analiz edebilirsiniz. Birleştirme, belirtilen sütunların değerlerini eşleştirerek iki veri kümesinin satırlarını birleştirir.

Aşağıda bir örnek verilmiştir:

SecurityEvent 
| where EventID == 4624		// sign-in events
| project Computer, Account, TargetLogonId, LogonTime=TimeGenerated
| join kind= inner (
    SecurityEvent 
    | where EventID == 4634		// sign-out events
    | project TargetLogonId, LogoffTime=TimeGenerated
) on TargetLogonId
| extend Duration = LogoffTime-LogonTime
| project-away TargetLogonId1 
| top 10 by Duration desc

Örnekte, ilk veri kümesi tüm oturum açma olayları için filtrelenir. Bu veri kümesi, tüm oturum kapatma olaylarını filtreleyen ikinci bir veri kümesiyle birleştirilir. Öngörülen sütunlar , Account, TargetLogonIdve TimeGeneratedsütunlarıdırComputer. Veri kümeleri paylaşılan bir sütun TargetLogonIdolan ile ilişkilendirilir. Çıkış, hem oturum açma hem de oturum kapatma süresi olan bağıntı başına tek bir kayıttır.

Her iki veri kümesinde de aynı ada sahip sütunlar varsa, sağ taraftaki veri kümesinin sütunlarına bir dizin numarası verilir. Bu örnekte, sonuçlar sol taraftaki tablodaki değerlerle ve TargetLogonId1 sağ taraftaki tablodaki değerlerle gösterilirTargetLogonId. Bu durumda, ikinci TargetLogonId1 sütun işleci kullanılarak project-away kaldırılmıştır.

Not

Performansı artırmak için işlecini kullanarak birleştirilen veri kümelerinin yalnızca ilgili sütunlarını project tutun.

Birleştirilen anahtarın iki tablo arasında farklı bir ada sahip olduğu iki veri kümesini birleştirmek için aşağıdaki söz dizimini kullanın:

Table1
| join ( Table2 ) 
on $left.key1 == $right.key2

Arama tabloları

Birleştirmelerin yaygın kullanımlarından biri, statik değer eşlemesi için kullanmaktır datatable . kullanmak datatable , sonuçların daha sunulu hale getirilebilir olmasını sağlayabilir. Örneğin, güvenlik olayı verilerini her olay kimliği için olay adıyla zenginleştirebilirsiniz:

let DimTable = datatable(EventID:int, eventName:string)
  [
    4625, "Account activity",
    4688, "Process action",
    4634, "Account activity",
    4658, "The handle to an object was closed",
    4656, "A handle to an object was requested",
    4690, "An attempt was made to duplicate a handle to an object",
    4663, "An attempt was made to access an object",
    5061, "Cryptographic operation",
    5058, "Key file operation"
  ];
SecurityEvent
| join kind = inner
 DimTable on EventID
| summarize count() by eventName

Çıktı aşağıda verilmiştir:

eventName count_
Bir nesnenin tanıtıcısı kapatıldı 290,995
Bir nesnenin tanıtıcısı istendi 154,157
Bir tanıtıcıyı nesneye çoğaltma girişiminde bulunuldu 144,305
Bir nesneye erişme girişiminde bulunuldu 123,669
Şifreleme işlemi 153,495
Anahtar dosyası işlemi 153,496

JSON ve veri yapıları

İç içe nesneler, bir dizideki veya anahtar-değer çiftlerinin haritasındaki diğer nesneleri içeren nesnelerdir. Nesneler JSON dizeleri olarak temsil edilir. Bu bölümde verileri almak ve iç içe nesneleri analiz etmek için JSON'ı nasıl kullanabileceğiniz açıklanmaktadır.

JSON dizeleriyle çalışma

Bilinen bir yolda belirli bir JSON öğesine erişmek için kullanın extractjson . Bu işlev, aşağıdaki kuralları kullanan bir yol ifadesi gerektirir:

  • Kök klasöre başvurmak için kullanın $ .
  • Aşağıdaki örneklerde gösterildiği gibi dizinlere ve öğelere başvurmak için köşeli ayraç veya nokta gösterimini kullanın.

Öğeleri ayırmak için dizinler ve noktalar için köşeli ayraç kullanın:

let hosts_report='{"hosts": [{"location":"North_DC", "status":"running", "rate":5},{"location":"South_DC", "status":"stopped", "rate":3}]}';
print hosts_report
| extend status = extractjson("$.hosts[0].status", hosts_report)

Bu örnek benzerdir ancak yalnızca köşeli ayraç gösterimini kullanır:

let hosts_report='{"hosts": [{"location":"North_DC", "status":"running", "rate":5},{"location":"South_DC", "status":"stopped", "rate":3}]}';
print hosts_report 
| extend status = extractjson("$['hosts'][0]['status']", hosts_report)

Yalnızca bir öğe için yalnızca nokta gösterimini kullanabilirsiniz:

let hosts_report=dynamic({"location":"North_DC", "status":"running", "rate":5});
print hosts_report 
| extend status = hosts_report.status

parsejson

JSON yapınızdaki birden çok öğeye dinamik nesne olarak erişmek en kolayıdır. Metin verilerini dinamik bir nesneye göndermek için kullanın parsejson . JSON'u dinamik bir türe dönüştürdükten sonra, verileri analiz etmek için ek işlevler kullanabilirsiniz.

let hosts_object = parsejson('{"hosts": [{"location":"North_DC", "status":"running", "rate":5},{"location":"South_DC", "status":"stopped", "rate":3}]}');
print hosts_object 
| extend status0=hosts_object.hosts[0].status, rate1=hosts_object.hosts[1].rate

arraylength

Dizideki öğe sayısını saymak için kullanın arraylength :

let hosts_object = parsejson('{"hosts": [{"location":"North_DC", "status":"running", "rate":5},{"location":"South_DC", "status":"stopped", "rate":3}]}');
print hosts_object 
| extend hosts_num=arraylength(hosts_object.hosts)

mv-expand

Bir nesnenin özelliklerini ayrı satırlara bölmek için kullanın mv-expand :

let hosts_object = parsejson('{"hosts": [{"location":"North_DC", "status":"running", "rate":5},{"location":"South_DC", "status":"stopped", "rate":3}]}');
print hosts_object 
| mv-expand hosts_object.hosts[0]

Screenshot shows hosts_0 with values for location, status, and rate.

buildschema

Bir nesnenin tüm değerlerini kabul eden şemayı almak için kullanın buildschema :

let hosts_object = parsejson('{"hosts": [{"location":"North_DC", "status":"running", "rate":5},{"location":"South_DC", "status":"stopped", "rate":3}]}');
print hosts_object 
| summarize buildschema(hosts_object)

Sonuç, JSON biçiminde bir şemadır:

{
    "hosts":
    {
        "indexer":
        {
            "location": "string",
            "rate": "int",
            "status": "string"
        }
    }
}

Şema, nesne alanlarının adlarını ve eşleşen veri türlerini açıklar.

İç içe nesneler, aşağıdaki örnekte olduğu gibi farklı şemalara sahip olabilir:

let hosts_object = parsejson('{"hosts": [{"location":"North_DC", "status":"running", "rate":5},{"status":"stopped", "rate":"3", "range":100}]}');
print hosts_object 
| summarize buildschema(hosts_object)

Grafikler

Aşağıdaki bölümlerde, Kusto Sorgu Dili kullanırken grafiklerle çalışma örnekleri verilmiştir.

Sonuçların grafiğini oluşturma

Son bir saat içinde işletim sistemi başına bilgisayar sayısını gözden geçirerek başlayın:

Heartbeat
| where TimeGenerated > ago(1h)
| summarize count(Computer) by OSType  

Varsayılan olarak sonuçlar tablo olarak görüntülenir:

Screenshot that shows query results in a table.

Daha kullanışlı bir görünüm için Grafik'i seçin ve ardından pasta seçeneğini belirleyerek sonuçları görselleştirin:

Screenshot that shows query results in a pie chart.

Zaman çizelgeleri

bir saatlik bölmelerde işlemci süresinin ortalamasını ve 50. ve 95. yüzdebirlik dilimlerini gösterin.

Aşağıdaki sorgu birden çok seri oluşturur. Sonuçlarda, zaman çizelgesinde hangi serinin gösterileceğini seçebilirsiniz.

Perf
| where TimeGenerated > ago(1d) 
| where CounterName == "% Processor Time" 
| summarize avg(CounterValue), percentiles(CounterValue, 50, 95)  by bin(TimeGenerated, 1h)

Çizgi grafik görüntüleme seçeneğini belirleyin:

Screenshot that shows a multiple-series line chart.

Başvuru satırı

Başvuru satırı, ölçümün belirli bir eşiği aşıp aşmadığını kolayca belirlemenize yardımcı olabilir. Grafiğe çizgi eklemek için sabit bir sütun ekleyerek veri kümesini genişletin:

Perf
| where TimeGenerated > ago(1d) 
| where CounterName == "% Processor Time" 
| summarize avg(CounterValue), percentiles(CounterValue, 50, 95)  by bin(TimeGenerated, 1h)
| extend Threshold = 20

Screenshot that shows a multiple-series line chart with a threshold reference line.

Birden çok boyut

yan tümcesindeki bysummarize birden çok ifade, sonuçlarda birden çok satır oluşturur. Her değer bileşimi için bir satır oluşturulur.

SecurityEvent
| where TimeGenerated > ago(1d)
| summarize count() by tostring(EventID), AccountType, bin(TimeGenerated, 1h)

Sonuçları grafik olarak görüntülediğinizde, grafik yan tümcesindeki by ilk sütunu kullanır. Aşağıdaki örnekte, değeri kullanılarak oluşturulan yığılmış bir sütun grafik gösterilmektedir EventID . Boyutlar türünde string olmalıdır. Bu örnekte, EventID değeri öğesine stringyayınlanır:

Screenshot that shows a bar chart based on the EventID column.

Sütun adı için açılan oku seçerek sütunlar arasında geçiş yapabilirsiniz:

Screenshot that shows a bar chart based on AccountType column, with the column selector visible.

Akıllı analiz

Bu bölüm, kullanıcı etkinliğini analiz etmek için Azure Log Analytics'teki akıllı analiz işlevlerini kullanan örnekler içerir. Bu örnekleri kullanarak Azure Uygulaması Analizler tarafından izlenen kendi uygulamalarınızı analiz edebilir veya diğer veriler üzerinde benzer analizler yapmak için bu sorgulardaki kavramları kullanabilirsiniz.

Kohort analizi

Kohort analizi, kohort olarak bilinen belirli kullanıcı gruplarının etkinliğini izler. Kohort analizi, geri dönen kullanıcıların oranını ölçerek bir hizmetin ne kadar çekici olduğunu ölçmeye çalışır. Kullanıcılar, hizmeti ilk kullandıkları zamana göre gruplandırılır. Kohortları analiz ederken, ilk izlenen dönemlerde etkinlikte bir düşüş bulmayı bekliyoruz. Her kohort, üyelerinin ilk kez gözlemlendiği haftaya göre adlandırılır.

Aşağıdaki örnek, kullanıcıların hizmeti ilk kez kullanmalarından sonraki beş hafta boyunca tamamladıkları etkinliklerin sayısını analiz eder:

let startDate = startofweek(bin(datetime(2017-01-20T00:00:00Z), 1d));
let week = range Cohort from startDate to datetime(2017-03-01T00:00:00Z) step 7d;
// For each user, we find the first and last timestamp of activity
let FirstAndLastUserActivity = (end:datetime) 
{
    customEvents
    | where customDimensions["sourceapp"]=="ai-loganalyticsui-prod"
    // Check 30 days back to see first time activity.
    | where timestamp > startDate - 30d
    | where timestamp < end      
    | summarize min=min(timestamp), max=max(timestamp) by user_AuthenticatedId
};
let DistinctUsers = (cohortPeriod:datetime, evaluatePeriod:datetime) {
    toscalar (
    FirstAndLastUserActivity(evaluatePeriod)
    // Find members of the cohort: only users that were observed in this period for the first time.
    | where min >= cohortPeriod and min < cohortPeriod + 7d  
    // Pick only the members that were active during the evaluated period or after.
    | where max > evaluatePeriod - 7d
    | summarize dcount(user_AuthenticatedId)) 
};
week 
| where Cohort == startDate
// Finally, calculate the desired metric for each cohort. In this sample, we calculate distinct users but you can change
// this to any other metric that would measure the engagement of the cohort members.
| extend 
    r0 = DistinctUsers(startDate, startDate+7d),
    r1 = DistinctUsers(startDate, startDate+14d),
    r2 = DistinctUsers(startDate, startDate+21d),
    r3 = DistinctUsers(startDate, startDate+28d),
    r4 = DistinctUsers(startDate, startDate+35d)
| union (week | where Cohort == startDate + 7d 
| extend 
    r0 = DistinctUsers(startDate+7d, startDate+14d),
    r1 = DistinctUsers(startDate+7d, startDate+21d),
    r2 = DistinctUsers(startDate+7d, startDate+28d),
    r3 = DistinctUsers(startDate+7d, startDate+35d) )
| union (week | where Cohort == startDate + 14d 
| extend 
    r0 = DistinctUsers(startDate+14d, startDate+21d),
    r1 = DistinctUsers(startDate+14d, startDate+28d),
    r2 = DistinctUsers(startDate+14d, startDate+35d) )
| union (week | where Cohort == startDate + 21d 
| extend 
    r0 = DistinctUsers(startDate+21d, startDate+28d),
    r1 = DistinctUsers(startDate+21d, startDate+35d) ) 
| union (week | where Cohort == startDate + 28d 
| extend 
    r0 = DistinctUsers (startDate+28d, startDate+35d) )
// Calculate the retention percentage for each cohort by weeks
| project Cohort, r0, r1, r2, r3, r4,
          p0 = r0/r0*100,
          p1 = todouble(r1)/todouble (r0)*100,
          p2 = todouble(r2)/todouble(r0)*100,
          p3 = todouble(r3)/todouble(r0)*100,
          p4 = todouble(r4)/todouble(r0)*100 
| sort by Cohort asc

Çıktı aşağıda verilmiştir:

Screenshot that shows a table of cohorts based on activity.

Aylık etkin kullanıcılar ve kullanıcı sürekliliği sıralı

Aşağıdaki örnek , series_fir işleviyle zaman serisi analizini kullanır. Kayan series_fir pencere hesaplamaları için işlevini kullanabilirsiniz. İzlenen örnek uygulama, kullanıcıların etkinliğini özel olaylar aracılığıyla izleyen bir çevrimiçi mağazadır. Sorgu iki tür kullanıcı etkinliğini izler: AddToCart ve Checkout. Etkin bir kullanıcıyı, belirli bir günde en az bir kez kullanıma alma işlemi tamamlayan bir kullanıcı olarak tanımlar.

let endtime = endofday(datetime(2017-03-01T00:00:00Z));
let window = 60d;
let starttime = endtime-window;
let interval = 1d;
let user_bins_to_analyze = 28;
// Create an array of filters coefficients for series_fir(). A list of '1' in our case will produce a simple sum.
let moving_sum_filter = toscalar(range x from 1 to user_bins_to_analyze step 1 | extend v=1 | summarize makelist(v)); 
// Level of engagement. Users will be counted as engaged if they completed at least this number of activities.
let min_activity = 1;
customEvents
| where timestamp > starttime  
| where customDimensions["sourceapp"] == "ai-loganalyticsui-prod"
// We want to analyze users who actually checked out in our website.
| where (name == "Checkout") and user_AuthenticatedId <> ""
// Create a series of activities per user.
| make-series UserClicks=count() default=0 on timestamp 
	in range(starttime, endtime-1s, interval) by user_AuthenticatedId
// Create a new column that contains a sliding sum. 
// Passing 'false' as the last parameter to series_fir() prevents normalization of the calculation by the size of the window.
// For each time bin in the *RollingUserClicks* column, the value is the aggregation of the user activities in the 
// 28 days that preceded the bin. For example, if a user was active once on 2016-12-31 and then inactive throughout 
// January, then the value will be 1 between 2016-12-31 -> 2017-01-28 and then 0s. 
| extend RollingUserClicks=series_fir(UserClicks, moving_sum_filter, false)
// Use the zip() operator to pack the timestamp with the user activities per time bin.
| project User_AuthenticatedId=user_AuthenticatedId , RollingUserClicksByDay=zip(timestamp, RollingUserClicks)
// Transpose the table and create a separate row for each combination of user and time bin (1 day).
| mv-expand RollingUserClicksByDay
| extend Timestamp=todatetime(RollingUserClicksByDay[0])
// Mark the users that qualify according to min_activity.
| extend RollingActiveUsersByDay=iff(toint(RollingUserClicksByDay[1]) >= min_activity, 1, 0)
// And finally, count the number of users per time bin.
| summarize sum(RollingActiveUsersByDay) by Timestamp
// First 28 days contain partial data, so we filter them out.
| where Timestamp > starttime + 28d
// Render as timechart.
| render timechart

Çıktı aşağıda verilmiştir:

Screenshot of a chart that shows rolling active users by day over a month.

Aşağıdaki örnek, önceki sorguyu yeniden kullanılabilir bir işleve dönüştürür. Örnek daha sonra sıralı kullanıcı sürekliliğini hesaplamak için sorguyu kullanır. Bu sorgudaki etkin bir kullanıcı, belirli bir günde en az bir kez kullanıma alma işlemi tamamlayan bir kullanıcı olarak tanımlanır.

let rollingDcount = (sliding_window_size: int, event_name:string)
{
    let endtime = endofday(datetime(2017-03-01T00:00:00Z));
    let window = 90d;
    let starttime = endtime-window;
    let interval = 1d;
    let moving_sum_filter = toscalar(range x from 1 to sliding_window_size step 1 | extend v=1| summarize makelist(v));    
    let min_activity = 1;
    customEvents
    | where timestamp > starttime
    | where customDimensions["sourceapp"]=="ai-loganalyticsui-prod"
    | where (name == event_name)
    | where user_AuthenticatedId <> ""
    | make-series UserClicks=count() default=0 on timestamp 
		in range(starttime, endtime-1s, interval) by user_AuthenticatedId
    | extend RollingUserClicks=fir(UserClicks, moving_sum_filter, false)
    | project User_AuthenticatedId=user_AuthenticatedId , RollingUserClicksByDay=zip(timestamp, RollingUserClicks)
    | mv-expand RollingUserClicksByDay
    | extend Timestamp=todatetime(RollingUserClicksByDay[0])
    | extend RollingActiveUsersByDay=iff(toint(RollingUserClicksByDay[1]) >= min_activity, 1, 0)
    | summarize sum(RollingActiveUsersByDay) by Timestamp
    | where Timestamp > starttime + 28d
};
// Use the moving_sum_filter with bin size of 28 to count MAU.
rollingDcount(28, "Checkout")
| join
(
    // Use the moving_sum_filter with bin size of 1 to count DAU.
    rollingDcount(1, "Checkout")
)
on Timestamp
| project sum_RollingActiveUsersByDay1 *1.0 / sum_RollingActiveUsersByDay, Timestamp
| render timechart

Çıktı aşağıda verilmiştir:

Screenshot of a chart that shows user stickiness over time.

Regresyon analizi

Bu örnekte, yalnızca bir uygulamanın izleme günlüklerine dayalı olarak hizmet kesintileri için otomatik algılayıcının nasıl oluşturulacağı gösterilmektedir. Algılayıcı, uygulamadaki hata ve uyarı izlemelerinin göreli miktarında anormal, ani artışlar arar.

İzleme günlükleri verilerine göre hizmet durumunu değerlendirmek için iki teknik kullanılır:

  • Yarı yapılandırılmış metin izleme günlüklerini pozitif ve negatif izleme çizgileri arasındaki oranı temsil eden bir ölçüme dönüştürmek için make-series kullanın.
  • İki satırlı doğrusal regresyonla zaman serisi analizini kullanarak gelişmiş adım atlama algılama için series_fit_2lines veseries_fit_line kullanın.
let startDate = startofday(datetime("2017-02-01"));
let endDate = startofday(datetime("2017-02-07"));
let minRsquare = 0.8;  // Tune the sensitivity of the detection sensor. Values close to 1 indicate very low sensitivity.
// Count all Good (Verbose + Info) and Bad (Error + Fatal + Warning) traces, per day.
traces
| where timestamp > startDate and timestamp < endDate
| summarize 
    Verbose = countif(severityLevel == 0),
    Info = countif(severityLevel == 1), 
    Warning = countif(severityLevel == 2),
    Error = countif(severityLevel == 3),
    Fatal = countif(severityLevel == 4) by bin(timestamp, 1d)
| extend Bad = (Error + Fatal + Warning), Good = (Verbose + Info)
// Determine the ratio of bad traces, from the total.
| extend Ratio = (todouble(Bad) / todouble(Good + Bad))*10000
| project timestamp , Ratio
// Create a time series.
| make-series RatioSeries=any(Ratio) default=0 on timestamp in range(startDate , endDate -1d, 1d) by 'TraceSeverity' 
// Apply a 2-line regression to the time series.
| extend (RSquare2, SplitIdx, Variance2,RVariance2,LineFit2)=series_fit_2lines(RatioSeries)
// Find out if our 2-line is trending up or down.
| extend (Slope,Interception,RSquare,Variance,RVariance,LineFit)=series_fit_line(LineFit2)
// Check whether the line fit reaches the threshold, and if the spike represents an increase (rather than a decrease).
| project PatternMatch = iff(RSquare2 > minRsquare and Slope>0, "Spike detected", "No Match")

Sonraki adımlar