gRCP Health Check with Powershell

FJS 21 Reputation points
2022-05-08T16:38:07.973+00:00

Hello.
I am checking periodically gRPC health of several microservices, every two seconds, it is working since I got the response they are serving, the output is { "status": "SERVING" }

 while ($true) {grpcurl -d '{ \"service1\": \"name1\" }' -H "authorization: key key"  host1:port grpc.health.v1.Health/Check>> grpcurl -d '{ \"service2\": \"name2\" }' -H "authorization: key key"  host2:port grpc.health.v1.Health/Check>> grpcurl -d '{ \"service3\": \"name3\" }' -H "authorization: key key"  host3:port grpc.health.v1.Health/Check>> grpcurl -d '{ \"service4\": \"name4\" }' -H "authorization: key key"  host4:port grpc.health.v1.Health/Check>> grpcurl -d '{ \"service5\": \"name5\" }' -H "authorization: key key"  host5:port grpc.health.v1.Health/Check>> grpcurl -d '{ \"service6\": \"name6\" }' -H "authorization: key key" host6:port grpc.health.v1.Health/Check>> grpcurl -d '{ \"service7\": \"name7\" }' -H "authorization: key key" host7:port grpc.health.v1.Health/Check;start-sleep 2}

Now I need a notification if the output is not "SERVING" while the code keeps running in a loop, how can I achieve this?

Please note, one or more service can fail but other can be ok so notification should only about the ones are not answering "SERVING", thanks,

Windows Server PowerShell
Windows Server PowerShell
Windows Server: A family of Microsoft server operating systems that support enterprise-level management, data storage, applications, and communications.PowerShell: A family of Microsoft task automation and configuration management frameworks consisting of a command-line shell and associated scripting language.
5,381 questions
{count} votes

Accepted answer
  1. Rich Matheisen 45,091 Reputation points
    2022-05-10T14:49:34.68+00:00

    There are ways to make this more efficient, and to also handle those times when grpcurl doesn't return anything in STDOUT (e.g. the host cannot be contacted, authentication fails, etc.) but writes an error message to STDERR, but I'll leave that part up to you,

    Give this one a try:

    function Serving{
        param(
            $val
        )
        if ($val -isnot [array]){
            return $false
        }
        if ($val.count -ne 3){
            return $false
        }
        Try{
            $p = $val -join "" | ConvertFrom-Json -ErrorAction STOP
            if ($p.status -eq 'serving'){
                $true
            }
            else{
                $false
            }
        }
        Catch{
            Write-Host "'$p' is not JSON"
            $false
        }
    }
    while ($true) {
        $beep = $false
        [array]$response = grpcurl -d '{ \"service1\": \"name1\" }' -H "authorization: key key"  host1:port grpc.health.v1.Health/Check
        if (-Not (Serving $response)){
            Write-Host "Service1 isn't serving" -ForegroundColor Yellow
            $beep = $true
        }
        [array]$response = grpcurl -d '{ \"service2\": \"name2\" }' -H "authorization: key key"  host2:port grpc.health.v1.Health/Check
        if (-Not (Serving $response)){
            Write-Host "Service2 isn't serving" -ForegroundColor Yellow
            $beep = $true
        }
        [array]$response = grpcurl -d '{ \"service3\": \"name3\" }' -H "authorization: key key"  host3:port grpc.health.v1.Health/Check
        if (-Not (Serving $response)){
            Write-Host "Service3 isn't serving" -ForegroundColor Yellow
            $beep = $true
        }
        [array]$response = grpcurl -d '{ \"service4\": \"name4\" }' -H "authorization: key key"  host4:port grpc.health.v1.Health/Check 
        if (-Not (Serving $response)){
            Write-Host "Service4 isn't serving" -ForegroundColor Yellow
            $beep = $true
        }
        [array]$response = grpcurl -d '{ \"service5\": \"name5\" }' -H "authorization: key key"  host5:port grpc.health.v1.Health/Check
        if (-Not (Serving $response)){
            Write-Host "Service5 isn't serving" -ForegroundColor Yellow
            $beep = $true
        }
        [array]$response = grpcurl -d '{ \"service6\": \"name6\" }' -H "authorization: key key"  host6:port grpc.health.v1.Health/Check
        if (-Not (Serving $response)){
            Write-Host "Service6 isn't serving" -ForegroundColor Yellow
            $beep = $true
        }
        [array]$response = grpcurl -d '{ \"service7\": \"name7\" }' -H "authorization: key key"  host7:port grpc.health.v1.Health/Check 
        if (-Not (Serving $response)){
            Write-Host "Service7 isn't serving" -ForegroundColor Yellow
            $beep = $true
        }
        if ($beep){
            [console]::beep(500, 300)
        }
        Start-Sleep 2 
    }
    

14 additional answers

Sort by: Most helpful
  1. Rich Matheisen 45,091 Reputation points
    2022-05-09T02:28:42.937+00:00

    If the response from grpcurl is JSON, then this should get you the correct output:

    while ($true) {
        $responses = @()
        $responses += grpcurl -d '{ \"service1\": \"name1\" }' -H "authorization: key key"  host1:port grpc.health.v1.Health/Check
        $responses += grpcurl -d '{ \"service2\": \"name2\" }' -H "authorization: key key"  host2:port grpc.health.v1.Health/Check
        $responses += grpcurl -d '{ \"service3\": \"name3\" }' -H "authorization: key key"  host3:port grpc.health.v1.Health/Check 
        $responses += grpcurl -d '{ \"service4\": \"name4\" }' -H "authorization: key key"  host4:port grpc.health.v1.Health/Check 
        $responses += grpcurl -d '{ \"service5\": \"name5\" }' -H "authorization: key key"  host5:port grpc.health.v1.Health/Check 
        $responses += grpcurl -d '{ \"service6\": \"name6\" }' -H "authorization: key key"  host6:port grpc.health.v1.Health/Check 
        $responses += grpcurl -d '{ \"service7\": \"name7\" }' -H "authorization: key key"  host7:port grpc.health.v1.Health/Check 
        $ctr = 0
        [array]$bad = @()
        ForEach ($response in $responses) {
            $ctr++
            $pp = $response | ConvertFrom-Json
            if ($pp.status -ne 'SERVING') {
                $bad += $ctr
            }      
        }
        if ($bad.count -gt 0) {
            [console]::beep(500, 300)
            $bad |
                ForEach-Object {
                    Write-Host "host$($_): $($responses[$_ - 1])" -ForegroundColor Yellow
                }
    
        }
        Start-Sleep 2 
    }
    
    0 comments No comments

  2. FJS 21 Reputation points
    2022-05-09T08:17:09.71+00:00

    I am getting an error, I guess is due to expects a string and the output is

    host1: {
    host2: "status": "SERVING"
    host3: }

    • $pp = $response | ConvertFrom-Json
    • ~~~~~~~~~~~~~~~~
    • CategoryInfo : NotSpecified: (:) [ConvertFrom-Json], ArgumentException
    • FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.ConvertFromJsonCommand

  3. FJS 21 Reputation points
    2022-05-09T14:31:55.05+00:00

    I am sure, the output is always one of these four (and expect to do and action when is not "SERVING"):

    host: {
    host: "status": "SERVING"
    host: }

    host: {
    host: "status": "NOT_SERVING"
    host: }

    host: {
    host: "status": "UNKNOWN"
    host: }

    host: {
    host: "status": "SERVICE UNKNOWN "
    host: }

    0 comments No comments

  4. FJS 21 Reputation points
    2022-05-09T14:41:53.627+00:00

    wondering why ConvertFrom-Json fails it this ouput are in JSON format, is due to there are 3 lines of each output answer? and does not match the pattern?