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.

10 konumun ilgili değerlerini gösteren on renkli sütunun bulunduğu sütun grafiğinin ekran görüntüsü.

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, bazı başlangıç saatleriyle yanlış durdurma zamanlarıyla eşleşen bir saatlik bölmeleri otomatik olarak 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_ .

Başlangıç zamanı, istemci IP adresi, süre, şehir ve her istemci/başlangıç zamanı birleşimi için en erken durak sütunlarını içeren sonuçları listeleyen tablonun ekran görüntüsü.

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

Belirtilen aralıklardaki sürelerle oturum sayısını gösteren sütun grafiğinin ekran görüntüsü.

Tam örnek

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

wabitrace
| where Timestamp >= datetime(2015-01-12 11:00:00Z)
| where Timestamp < datetime(2015-01-12 13:00:00Z)
| where 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
| where Tenant == 'DevDiv' and Environment == 'RollupDev2'
| where TotalLaunchedMaps > 0
| summarize sum(TotalMapsSeconds) by UnitOfWorkId
| extend JobMapsSeconds = sum_TotalMapsSeconds * 1
| project UnitOfWorkId, JobMapsSeconds
| join (
wabitrace
| where Timestamp >= datetime(2015-01-12 11:00:00Z)
| where Timestamp < datetime(2015-01-12 13:00:00Z)
| where 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
| where Tenant == 'DevDiv' and Environment == 'RollupDev2'
| where TotalLaunchedReducers > 0
| summarize sum(TotalReducesSeconds) by UnitOfWorkId
| extend JobReducesSeconds = sum_TotalReducesSeconds * 1
| project UnitOfWorkId, JobReducesSeconds )
on UnitOfWorkId
| join (
wabitrace
| where Timestamp >= datetime(2015-01-12 11:00:00Z)
| where Timestamp < datetime(2015-01-12 13:00:00Z)
| where 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)
| where 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)

Çıkış

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şmiyor.

Belirli bir Bing çıkarımları 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 dilimini 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

Çıkış

Sayısı_ Message
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

Çıkış

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()

Çıkış

Count Yüzde (%) Bileşen Küme Message
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 modeli kullanmaktan kolay bir ada nasıl değiştireceğini gösterir. 

Dinamik sözlük kullanarak eşleme

Bir dinamik sözlük ve dinamik erişimciler kullanarak eşleme gerçekleştirebilirsiniz. Ö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

Çıkış

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 da eşleme gerçekleştirebilirsiniz.

  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

Aşağıda biraz daha karmaşık bir örnek verilmiştir:

// 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 sütun
  • timestamp Satır için zaman başvurusu sağlayan sütun
  • Diğer sütunlar

Sütunun her değeri ID için en son iki kaydı döndüren bir sorgu oluşturmak için en üstteki iç içe işlecini kullanabilirsiniz; 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 karşılık gelir):

  1. , datatable tanıtım amacıyla bazı test verileri oluşturmanın bir yoludur. Normalde burada gerçek verileri kullanırsınız.
  2. Bu satır temelde değerinin idtüm benzersiz değerlerini döndüreceği anlamına gelir.
  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 hesaplamanın yüzdesine göre genişletme

Sayısal sütun içeren bir 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 tablosu:

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 = iff(_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) take 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 "uzatır" (yineler). 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üne bölme (ile göreli olarak _start).
  2. Kayıt başına aralığın sonunu belirleyin: _bin + 7d, değer ve _endaralığının _start dışında değilse, bu durumda ayarlanır.
  3. Her kayıt için, geçerli kaydın gününden başlayarak yedi günlük (zaman damgaları) bir dizi oluşturun.
  4. mv-expand dizisini kullanarak her kaydı birbirinden bir gün ayrı olarak yedi kayda çoğaltabilir.
  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 süresi 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 hala B'den eski olan kaydı) 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

Çıkış

Zaman damgası ID OlayB
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 EventA
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

Çıktı

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

Kusto Sorgu Dili bir öğreticide ilerleyin.

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 dizilerinden 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 dizilerinden 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 Öğelerden hiçbirine eşit değildir Yes "bca" !in ("123", "345", "abc")

countof

Bir alt dizenin dize içindeki oluşumlarını sayar. Düz dizeleri eşleştirebilir 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şmek için düz dize veya regex
  • kind: normal | regex (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 bir 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, isteğe bağlı olarak öğesine dönüştürülür typeLiteral. 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 timespanyayınlanı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

  • 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: isnotempty.
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

parse_url

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

parse_url(urlstring)

Örnek

print parse_url("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"
}

replace_regex

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

replace_regex(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 tüm eşleşmelerin yerine geçen regex. Tüm eşleşmeye 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_regex(@"(\d+) -", @"Activity ID \1: ", Activity)

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

Etkinlik Değiştirilir
4663 - 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 Sayısı_
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.

count

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 :

Performans kaydı eğilim çizgisini beş dakikalık aralıklarla gösteren çizgi grafiğin ekran görüntüsü.

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

Çıkış

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 make_list . Ö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 make_list(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]
... ...

make_list , 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 make_set oluşturabilirsiniz:

Event
| where TimeGenerated > ago(12h)
| order by TimeGenerated desc
| summarize make_set(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 make_list, make_set sıralı verilerle de çalışır. komutu, make_set içine geçirilen satırların sırasına göre diziler oluşturur.

Listeleri genişletme

veya öğesinin make_list ters işlemidirmv-expand.make_set 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 make_list . Çıktıda, çözüm başına bilgisayar listesini görebilirsiniz:

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

Heartbeat
| where TimeGenerated > ago(1h)
| project Computer, split(Solutions, ",")
| mv-expand Solutions
| summarize make_list(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 Sayısı_
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:

Category Sayısı_ 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 eşleşen zaman damgası "2017-06-06T19:00:00.0000000Z" şeklindedir. Ancak, bu dizi biçimini okumak zordur. Dizileri genişletmek ve tarafından summarizeoluşturulanla aynı biçim çıkışını oluşturmak 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 Sayısı_
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, make_set, toscalar, in

Yaygın bir senaryo, belirli varlıkların adlarını bir ölçüt kümesine göre 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 make_set(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ütunla TargetLogonIdilişkilendirilir. Çıkış, hem oturum açma hem de oturum kapatma süresine sahip 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 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ıldı.

Not

Performansı geliştirmek için işlecini kullanarak project yalnızca birleştirilmiş veri kümelerinin ilgili sütunlarını 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 ulaşılabilir 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 Sayısı_
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, dizideki veya anahtar-değer çiftlerinin eşlemindeki 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 veya extract_json() kullanınextractjson. 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 = extract_json("$.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 = extract_json("$['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 atamak için kullanın parsejson . JSON'yi dinamik bir türe dönüştürdükten sonra, verileri çözümlemek 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

array_length

Dizideki öğelerin sayısını saymak için kullanın array_length :

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=array_length(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]

Konum, durum ve oran değerlerinin bulunduğu hosts_0 gösteren ekran görüntüsü.

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:

Tablodaki sorgu sonuçlarını gösteren ekran görüntüsü.

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:

Pasta grafikte sorgu sonuçlarını gösteren ekran görüntüsü.

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:

Çok serili çizgi grafiği gösteren ekran görüntüsü.

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 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

Eşik başvuru çizgisine sahip çok serili çizgi grafiği gösteren ekran görüntüsü.

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ış sütun grafiği gösterilmektedir EventID . Boyutlar türünde string olmalıdır. Bu örnekte EventID , değeri olarak stringatılır:

EventID sütununu temel alan bir çubuk grafiği gösteren ekran görüntüsü.

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

AccountType sütununu temel alan ve sütun seçicinin görünür olduğu çubuk grafiği gösteren ekran görüntüsü.

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 örnekleri içerir. Azure Uygulaması Insights tarafından izlenen kendi uygulamalarınızı analiz etmek için bu örnekleri kullanabilir veya diğer verilerde benzer analizler 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 kullanmalarından sonraki beş hafta içinde tamamladıkları etkinlik 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:

Etkinliği temel alan kohort tablosunu gösteren ekran görüntüsü.

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

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, özel olaylar aracılığıyla kullanıcıların etkinliklerini 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 make_list(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:

Bir ayın her günü etkin kullanıcıları gösteren grafiğin ekran görüntüsü.

Aşağıdaki örnek, önceki sorguyu yeniden kullanılabilir bir işleve dönüştürür. Örnek daha sonra sıralı kullanıcı yapışkanlığını 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 make_list(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:

Zaman içindeki kullanıcı yapışkanlığını gösteren grafiğin ekran görüntüsü.

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 çizgili doğrusal regresyonla zaman serisi analizini kullanarak gelişmiş adım atlama algılaması 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=take_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

Kusto Sorgu Dili öğreticisini inceleyin.