Recommended Posts

Hey all,

I built out a datasource to monitor the COVID-19 cases and deaths per state. An API key from Finnhub.io is required to run this DataSource. The API key must be saved as a custom property on the device you want this DataSource applied to. The Custom Propery name needs to be "finhubb.api.key" with the value being the Finnhub.io API key. Finnhub.io offers a free API key teir that allows 60 queries a minute.

image.png.050f137f91eedc9618e749197d416d9e.png

Locator Code: M9WGM3

image.png.021d9157b002b10646887f0a89f67410.png

Share this post


Link to post
Share on other sites

XML;

<?xml version="1.0" encoding="UTF-8" ?>
<feed  version="1.0" hasPendingRequests="false" >
  <company></company>
  <status>200</status>
  <errmsg>OK</errmsg>
  <interval>0</interval>
    <entry type="predatasource">
        <version>1584963910</version>
        <name>Finnhub.io_COVID_19-</name>
        <displayedas>COVID 19</displayedas>
        <description>Gathers statistics about COVID-19</description>
        <collector>script</collector>
        <hasMultiInstances>true</hasMultiInstances>
        <schedule>60</schedule>
        <appliesTo>finnhub.api.key</appliesTo>
        <wildcardauto>true</wildcardauto>
        <wildcardpersist>true</wildcardpersist>
        <wildcardlinuxscript>ad_script</wildcardlinuxscript>
        <wildcardlinuxcmdline>type=&#34;powerShell&#34; </wildcardlinuxcmdline>
        <wildcardwinscript>ad_script</wildcardwinscript>
        <wildcardwincmdline>type=&#34;powerShell&#34; </wildcardwincmdline>
        <wildcardgroovyscript># API key from finnhub.io.
$Key = &#34;##finnhub.api.key##&#34;

$Uri = &#34;https://finnhub.io/api/v1/covid19/us?token=$Key&#34;
$Data = Invoke-WebRequest -Uri $Uri -Method Get -UseBasicParsing | Select-Object -ExpandProperty Content | ConvertFrom-Json


# Loop through each location and get the location names.
foreach ($instance in $Data) {
     $Location = $instance.State
     Write-Host &#34;$Location##$Location&#34;
}

# Exit PowerShell Script to ensure now active sessions are left open.
Exit 0;</wildcardgroovyscript>
        <wildcardschedule>0</wildcardschedule>
        <wildcarddisable>false</wildcarddisable>
        <wildcarddeleteinactive>true</wildcarddeleteinactive>
        <agdmethod>none</agdmethod>
        <agdparams></agdparams>
        <group></group>
        <tags></tags>
        <technology>Created by Matt Kerfoot

Must have an API key for Finnhub.io. The API key must be saved as a new custom property under the device you want to run this datasource on called, &#34;finnhub.api.key&#34; with the value being the API Key.</technology>
        <adlist><![CDATA[{"agdmethod":"none","method":"ad_script","agdparams":"","id":0,"filters":[],"params":{"type":"powerShell","groovyscript":"# API key from finnhub.io.\r\n$Key = \"##finnhub.api.key##\"\r\n\r\n$Uri = \"https://finnhub.io/api/v1/covid19/us?token=$Key\"\r\n$Data = Invoke-WebRequest -Uri $Uri -Method Get -UseBasicParsing | Select-Object -ExpandProperty Content | ConvertFrom-Json\r\n\r\n\r\n# Loop through each location and get the location names.\r\nforeach ($instance in $Data) {\r\n     $Location = $instance.State\r\n     Write-Host \"$Location##$Location\"\r\n}\r\n\r\n# Exit PowerShell Script to ensure now active sessions are left open.\r\nExit 0;"}}]]></adlist>
        <schemaVersion>2</schemaVersion>
        <dataSourceType>1</dataSourceType>
        <attributes>
        <attribute>
            <name>scripttype</name>
            <value>powerShell</value>
            <comment></comment>
        </attribute>
        <attribute>
            <name>scriptgroovy</name>
            <value># Required ASI Key from finnhub.io.
$Key = &#34;##finnhub.api.key##&#34;

# Wildvalue will such in each Location from the Active Discovery Script.
$wildvalue = &#34;##WILDVALUE##&#34;

# Retrieve Covid 19 data per each location.
$Data = Invoke-WebRequest -Method Get -Uri &#34;https://finnhub.io/api/v1/covid19/us?token=$Key&#34; -UseBasicParsing | Select-Object -ExpandProperty Content | ConvertFrom-Json
    
    # Puts Case and Death counts in variables to be written to LogicMonitor.
    $Case = ($Data | Where-Object State -eq $wildvalue).case
    $Death = ($Data | Where-Object State -eq $wildvalue).death
    
         # Writes the Case and Death counts to LogicMonitor.
         Write-Host Cases=$Case
         Write-Host Deaths=$Death

# Exit PowerShell Script to ensure now active sessions are left open.
Exit 0;</value>
            <comment></comment>
        </attribute>
        <attribute>
            <name>windowsscript</name>
            <value></value>
            <comment></comment>
        </attribute>
        <attribute>
            <name>linuxscript</name>
            <value></value>
            <comment></comment>
        </attribute>
        <attribute>
            <name>windowscmdline</name>
            <value></value>
            <comment></comment>
        </attribute>
        <attribute>
            <name>linuxcmdline</name>
            <value></value>
            <comment></comment>
        </attribute>
        </attributes>
        <datapoints>
        <datapoint>
            <name>Deaths</name>
            <dataType>7</dataType>
            <type>2</type>
            <postprocessormethod>namevalue</postprocessormethod>
            <postprocessorparam>Deaths</postprocessorparam>
            <usevalue>output</usevalue>
            <alertexpr></alertexpr>
            <alertmissing>1</alertmissing>
            <alertsubject></alertsubject>
            <alertbody></alertbody>
            <enableanomalyalertsuppression></enableanomalyalertsuppression>
            <description>Number of Deaths</description>
            <maxvalue></maxvalue>
            <minvalue></minvalue>
            <userparam1></userparam1>
            <userparam2></userparam2>
            <userparam3></userparam3>
            <iscomposite>false</iscomposite>
            <rpn></rpn>
            <alertTransitionIval>0</alertTransitionIval>
            <alertClearTransitionIval>0</alertClearTransitionIval>
        </datapoint>
        <datapoint>
            <name>Cases</name>
            <dataType>7</dataType>
            <type>2</type>
            <postprocessormethod>namevalue</postprocessormethod>
            <postprocessorparam>Cases</postprocessorparam>
            <usevalue>output</usevalue>
            <alertexpr></alertexpr>
            <alertmissing>1</alertmissing>
            <alertsubject></alertsubject>
            <alertbody></alertbody>
            <enableanomalyalertsuppression></enableanomalyalertsuppression>
            <description>Number of Covid 19 cases</description>
            <maxvalue></maxvalue>
            <minvalue></minvalue>
            <userparam1></userparam1>
            <userparam2></userparam2>
            <userparam3></userparam3>
            <iscomposite>false</iscomposite>
            <rpn></rpn>
            <alertTransitionIval>0</alertTransitionIval>
            <alertClearTransitionIval>0</alertClearTransitionIval>
        </datapoint>
        </datapoints>
        <graphs>
        <graph>
            <name>Cases</name>
            <title>Cases</title>
            <verticallabel>Number of Cases</verticallabel>
            <rigid>false</rigid>
            <maxvalue>NaN</maxvalue>
            <minvalue>0.0</minvalue>
            <displayprio>1</displayprio>
            <timescale>1day</timescale>
            <base1024>false</base1024>
            <graphdatapoints>
        <graphdatapoint>
            <name>Cases</name>
            <datapointname>Cases</datapointname>
            <cf>1</cf>
        </graphdatapoint>
            </graphdatapoints>
            <graphvirtualdatapoints>
            </graphvirtualdatapoints>
            <graphdatas>
            <graphdata>
                <type>2</type>
                <legend>Cases</legend>
                <color>silver</color>
                <datapointname>Cases</datapointname>
                <isvirtualdatapoint>false</isvirtualdatapoint>
            </graphdata>
            </graphdatas>
        </graph>
        <graph>
            <name>Deaths</name>
            <title>Deaths</title>
            <verticallabel>Number of Deaths</verticallabel>
            <rigid>false</rigid>
            <maxvalue>NaN</maxvalue>
            <minvalue>0.0</minvalue>
            <displayprio>2</displayprio>
            <timescale>1day</timescale>
            <base1024>false</base1024>
            <graphdatapoints>
        <graphdatapoint>
            <name>Deaths</name>
            <datapointname>Deaths</datapointname>
            <cf>1</cf>
        </graphdatapoint>
            </graphdatapoints>
            <graphvirtualdatapoints>
            </graphvirtualdatapoints>
            <graphdatas>
            <graphdata>
                <type>1</type>
                <legend>Deaths</legend>
                <color>red</color>
                <datapointname>Deaths</datapointname>
                <isvirtualdatapoint>false</isvirtualdatapoint>
            </graphdata>
            </graphdatas>
        </graph>
        </graphs>
        <overviewgraphs>
        <overviewgraph>
            <name>Cases Per Location</name>
            <title>Cases Per Location</title>
            <verticallabel>Number of cases</verticallabel>
            <rigid>false</rigid>
            <maxvalue>NaN</maxvalue>
            <minvalue>0.0</minvalue>
            <displayprio>1</displayprio>
            <timescale>1day</timescale>
            <base1024>false</base1024>
            <aggregated>false</aggregated>
            <datapoints>
        <overviewgraphdatapoint>
            <name>Cases</name>
            <datapointname>Cases</datapointname>
            <cf>1</cf>
            <aggregateMethod>average</aggregateMethod>
        </overviewgraphdatapoint>
            </datapoints>
            <virtualdatapoints>
            </virtualdatapoints>
            <lines>
            <overviewgraphline>
                <type>2</type>
                <legend>##INSTANCE##</legend>
                <datapointname>Cases</datapointname>
                <isvirtualdatapoint>false</isvirtualdatapoint>
                <color>silver</color>
            </overviewgraphline>
            </lines>
        </overviewgraph>
        <overviewgraph>
            <name>Deaths Per Location</name>
            <title>Deaths Per Location</title>
            <verticallabel>Number of Deaths</verticallabel>
            <rigid>false</rigid>
            <maxvalue>NaN</maxvalue>
            <minvalue>0.0</minvalue>
            <displayprio>1</displayprio>
            <timescale>1day</timescale>
            <base1024>false</base1024>
            <aggregated>false</aggregated>
            <datapoints>
        <overviewgraphdatapoint>
            <name>Deaths</name>
            <datapointname>Deaths</datapointname>
            <cf>1</cf>
            <aggregateMethod>average</aggregateMethod>
        </overviewgraphdatapoint>
            </datapoints>
            <virtualdatapoints>
            </virtualdatapoints>
            <lines>
            <overviewgraphline>
                <type>2</type>
                <legend>##INSTANCE##</legend>
                <datapointname>Deaths</datapointname>
                <isvirtualdatapoint>false</isvirtualdatapoint>
                <color>silver</color>
            </overviewgraphline>
            </lines>
        </overviewgraph>
        </overviewgraphs>
        <scripts>
        </scripts>
    </entry>
</feed>

 

Share this post


Link to post
Share on other sites

Took me a minute to notice that this requires a Windows collector since it's powershell.  With your permission, I may rewrite the scripts to groovy so they can run on either Windows or Linux.

Share this post


Link to post
Share on other sites
9 minutes ago, Stuart Weenig said:

Took me a minute to notice that this requires a Windows collector since it's powershell.  With your permission, I may rewrite the scripts to groovy so they can run on either Windows or Linux.

Have at it, @Stuart Weenig!

Share this post


Link to post
Share on other sites

Alright, try this: https://github.com/sweenig/lmcommunity/blob/master/COVID19_by_State/COVID19_by_State.xml

Besides converting to groovy, I converted it to batchscript vs. script. This means that instead of making one call per state ever poll cycle, it makes one call and parses out all the data from that one call.  Should help if finnhub ever decides to lower the api limit.

Share this post


Link to post
Share on other sites

Just had a realization. If you aren't interested in all states, you could apply a discovery filter to only include those states where your company has offices. 

Share this post


Link to post
Share on other sites
1 minute ago, Stuart Weenig said:

Just had a realization. If you aren't interested in all states, you could apply a discovery filter to only include those states where your company has offices. 

That is a good point. I found a little bug too. the API is returning "Colorado " with a space at the end which was returning NaN in the script. I did a ghetto little workaround.

Its not pretty but it works. lol

 if($wildvalue -eq "Colorado"){
    $Case = ($Data | Where-Object State -eq "Colorado ").case
    $Death = ($Data | Where-Object State -eq "Colorado ").death
    
         Write-Host Cases=$Case
         Write-Host Deaths=$Death
               }else{
     
$Data = $Return | Select-Object -ExpandProperty Content | ConvertFrom-Json
    
    $Case = ($Data | Where-Object State -eq $wildvalue).case
    $Death = ($Data | Where-Object State -eq $wildvalue).death
    
         Write-Host Cases=$Case
         Write-Host Deaths=$Death
               }
 

Share this post


Link to post
Share on other sites

Yeah, the groovy version had that problem too. I didn't notice the trailing space, but I did notice a record with a name of " " and one that had a leading space. If you look at the groovy code, you'll see a .trim() method that eliminates that.

Share this post


Link to post
Share on other sites
3 minutes ago, Stuart Weenig said:

FYI, i've started a github repo with my personal datasources, including the groovy version of this one: https://github.com/sweenig/lmcommunity. Feel free to grab anything from there.

My hero! Thanks again for all the hard work!

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.