Writing your own custom log messages to OMS



I'm still trying to get my head round the whole OMS topic and how it really fits into our azure management/monitoring framework. As part of working that out I've today been working out how to add my own custom logs which i could then make sure of to do nice graphs and possibly build alerts off.

Largely what i did was based off this example from Stefan https://blogs.technet.microsoft.com/stefan_stranger/2016/09/05/using-the-http-oms-data-collector-api-for-real-world-scenarios-part-1/

I had trouble though as google seem to have pulled the api used in the example and it also was doing a bit more than i wanted to just to get a basic understanding - so i cut it back to the bare minimum and set something up (the powershell is pretty much directly 'borrowed' from Stefan).

So in my imaginary case i just want to log the value of some variable (lets call it test) over a period of time. In my simple case I'm just making up values and creating log entries - in reality though you could have code anywhere that is retrieving a value of some sort that you want to log and process.

So how do i go about that - how do i create somethign in OMS that i can log to and how do i get the data into that? Well actually in turned out to be easier than i thought - we essentially just have to call a rest api (which we have to authenticate to) and then just pass the variable and the value as a json object to that call - conceptually it's just something like:

https://somesite?password=xxxxx?{test=123}

In reality it's slightly more complicated of course but thats essentially what I'm doing - OMS is handling creating an object that 'holds' this data and exposing the json values as variables i can see in OMS.

So enough of the theoretical code lets see what it actually looks like - here is the powershell code from Stefan that i only very slightly altered:

It consists of 2 functions - the first is just creating a signature (essentially the authorization header to pass to the rest call). The second part is the thing actually calling to the rest api passing the header we built in the first function and the json object containing my variable.



Function New-Signature ($customerId, $sharedKey, $date, $contentLength, $method, $contentType, $resource)
{
  $xHeaders = 'x-ms-date:' + $date
  $stringToHash = $method + "`n" + $contentLength + "`n" + $contentType + "`n" + $xHeaders + "`n" + $resource

  $bytesToHash = [Text.Encoding]::UTF8.GetBytes($stringToHash)
  $keyBytes = [Convert]::FromBase64String($sharedKey)

  $sha256 = New-Object -TypeName System.Security.Cryptography.HMACSHA256
  $sha256.Key = $keyBytes
  $calculatedHash = $sha256.ComputeHash($bytesToHash)
  $encodedHash = [Convert]::ToBase64String($calculatedHash)
  $authorization = 'SharedKey {0}:{1}' -f $customerId, $encodedHash
  return $authorization
}

Function Send-OMSData($customerId, $sharedKey, $body, $logType) 
{
  $method = 'POST'
  $contentType = 'application/json'
  $resource = '/api/logs'
  $rfc1123date = [DateTime]::UtcNow.ToString('r')
  $contentLength = $body.Length
  $signature = New-Signature `
  -customerId $customerId `
  -sharedKey $sharedKey `
  -date $rfc1123date `
  -contentLength $contentLength `
  -method $method `
  -contentType $contentType `
  -resource $resource
  $uri = 'https://' + $customerId + '.ods.opinsights.azure.com' + $resource + '?api-version=2016-04-01'

  $headers = @{
    'Authorization'      = $signature
    'Log-Type'           = $logType
    'x-ms-date'          = $rfc1123date
    'time-generated-field' = ""
  }

  Write-Host $uri
  Write-Host $signature

  $response = Invoke-WebRequest -Uri $uri -Method $method -ContentType $contentType -Headers $headers -Body $body -UseBasicParsing
  return $response.StatusCode
} 

Now i just need to call that send-omsdata function passing in some parameters to post the data to OMS - a call to that looks like this:


 Send-OMSData -customerId 'workspace-id-from-oms-here' -sharedKey 'primary_key-from-oms-ending-in-==-here' -body '{test:123}' -logType 'RICH'

The workspace id and primary key can be gotten from your OMS portal shown in the screenshot below

image


The key bits of interest I'm passing here are:

-body '{test:123}'  (this is the json object with variables and values - in this case I'm just passing one)
-logType 'RICH' (this is the name to give the wrapper log object thing in OMS so i can refer to it)

If i run that powershell now it returns success and after a few minutes the data has appeared in OMS (note that it is a few minutes - this process is not instant)

So now the data is there I can query it - note though that OMS has suffixed the names i used so we have to be aware of that and use those names - so in this case the names are

RICH_CL is the OMS wrapper object (it seems _CL is the suffix always added - maybe stands for customer log - i don't know)
test_d is the variable (again not sure what the d is for - data perhaps?)

So lets query them with a very simple OMS query

search * | where Type == "RICH_CL" 

This looks like this in the GUI


If i just want to show that single variable on its own i can just run this

search *
| where Type == "RICH_CL" 
| project test_d

In tabular format in the GUI this looks like this




And adding a bit more data and calling the powershell with 2 variables (i.e. -body '{test:999,test2:456}' ) can then show us this



Anyway you get the general idea.

Now i just need to build something where this is actually useful - I'll report back when I've done that.....

Comments