Forum Discussion

SteveDahlberg's avatar
5 months ago
Solved

New to LM: How do I refer to the local filesystem in an embedded PowerShell script of a DataSource?

How do I refer to the local filesystem in an embedded PowerShell script of a DataSource? The below works fine from a PowerShell session console on a Collector server, but fails when running embedded in LogicMonitor. The Active Directory LogicMonitor service account is in the local Administrators group on the Resource server (a LM Collector server in this), same as my admin account using the PowerShell session. It also has explicit NTFS "Full Control" rights on the folder in the path variable below. 

Do I have to use the Get-PSDrive cmndlet? Or is there a simple way to do it when running embedded in the LogicMonitor environment?

$textFilePath = 'C:\ps\LM-custom_list.txt' $localList = Get-Content -Path $textFilePath

-Steve

  • Yes, and you see it worked for me in my screenshot with a full path. The only thing I'm aware of that LM will do to a powershell script is do a search-and-replace of ##TOKEN## but I didn't see any of that in your code. Even your error message isn't show the path getting screwed up and it's powershell telling you the file doesn't exist there.

    I would 100% make sure the script is actually running on the server you think it's running on. Does "Write-Output $env:computername" show the name of the server with the file?

  • I think you need a step back a bit a get a better understanding of how Script and BatchScript DataSources works. I suggest watching some of the videos in LM Academy like https://academy.logicmonitor.com/introduction-to-datasources and reading over the docs like https://www.logicmonitor.com/support/logicmodules/datasources/data-collection-methods/scripted-data-collection-overview and  https://www.logicmonitor.com/support/logicmodules/datasources/data-collection-methods/batchscript-data-collection and https://www.logicmonitor.com/support/logicmodules/datasources/data-collection-methods/scripted-data-collection-overview. Also highly suggest you look at existing DataSources to understand how it works like Microsoft_DHCP_IPv4Scopes. Look at the examples at https://www.logicmonitor.com/support/terminology-syntax/scripting-support/embedded-powershell-scripting

    Suggest working out answers to questions like:

    • What is the difference between a Script and BatchScript DataSource?
    • How do I know what device/resource LogicMonitor wants data on?

    For example LogicMonitor will tell you what device it wants information on, you don't tell it.

    Here is an example of a BatchScript DataSource, if you wanted to implement getting disk usage of all the drives on a device.

    ActiveDiscovery: Get the name of the device from LM by looking at ##SYSTEM.HOSTNAME## and sent a query to that device asking for the list of all drives. Output something like this:

    C##C Drive
    D##D Drive

    Collection: Get the name of the device from LM by looking at ##SYSTEM.HOSTNAME## and send a query to that device asking for the list of all drives along with the usage information. Output something like this:

    C.totalspace=1000
    C.freespace=10
    C.usedspace=900
    D.totalspace=2000
    D.freespace=50
    D.usedspace=1950
    

    When LM later on wants to get the information for the free space of the D: drive, it will set the ##WILDVALUE## to "D" and extract all the lines that start with "D." then pull the totalspace, freespace, and usedspace.

    Your script should only provide output for the device that LM is requesting data on. You would get that information from a line like this:

    #Get the hostname the LM wants data on
    $Hostname = '##SYSTEM.HOSTNAME##';
    

     

  • Mike, you've been so helpful; I really appreciate it. Quick question about your last example, which relates to one of the two general questions I have below: What are the implications of having the DataSource setting "Use Wildvalue as Unique Identifier" enabled in the context of your example?

    ---

    Two very general questions right now (keep in mind I only dove into all of this starting a few weeks ago; I didn't even know what a DataSource was, lol, but now I've built and re-built the one I'm working on several time, have complex datapoints going in this multi-instance DataSource, etc):

    1. Regarding the DataSource setting "Use Wildvalue as Unique Identifier", I wish I could turn it off for this module, but I understand you cannot once it's enabled (due to dependencies or something?). I tried cloning the DataSource but I still couldn't disable it in the clone. But at this point, with the DataSource fairly developed, I cringe at the thought of having to recreate it from scratch just to change that one thing. What do people normally do in this situation?

    2. I wonder what the mechanics are behind the WILDALIAS token not being available for use in custom alert messages? The list of available tokens is quite extensive, but WILDALIAS isn't one of them, which I discovered when I tried to use it but it always just came back as text "##WILDALIAS##".

     

    • Mike_Moniz's avatar
      Mike_Moniz
      Icon for Professor rankProfessor

      You can try exporting the DataSource, edit the json directly, then delete/re-import. I normally would just rebuild, but when I'm developing I save the datapoints and graphs for last, so normally it's not to bad to do some copy/pasting.

      In the context of my example, it wouldn't matter what that option is set to since neither WildValue or WildAlias will change on multiple calls.

      I guess I didn't really pay that much attention to that "Use Wildvalue as Unique Identifier" and that seems to work backwards then I thought. WildValue is suppose to be the ID with the WildAlias as the "display name" of the instance. That option didn't exist when I started doing DSes so that's kinda confusing why it's saying that alias was the id. But really I don't dynamically change either value so for me I might have never noticed it. I would suggest using WildValue as the ID.

      I think ##INSTANCE## would be equivalent to ##WILDALIAS##.

  • Thanks, Mike. Yes, I may just have to have the old and new DataSource up in adjacent tabs and just bludgeon my way through it. Hey, I haven't tried using ##INSTANCE##, I will definitely investigate that! I've got it working in the meantime by populating the instance Description field in the Active Discovery script with the literal path (to the textfile) and then referencing ##DESCRIPTION## in the custom alert messages. But if I can you ##INSTANCE##, it seems less kludgy that using the description field for that.

     

  • For some reason I'm unable to start a new discussion right now, just says:

    Cannot add message
    Something went wrong, please try again,

    But I've been stumped on the following issue and it's driving me nuts:

    How do I read the values of instance-level properties in an embedded PowerShell DataSource Collection script? Or resource-level properties in an embedded PowerShell PropertySource? I understand how to write properties and their values in the Active Discovery script with something like 

    Write-Host "<instanceID>##<instanceName>##<instanceDescription>####auto.AssignedCollectorDeviceName=$AssignedCollectorDeviceName"

    I have an instance-level custom property "auto.AssignedCollectorDeviceName" on a resource instance that I would like to check the value of during Collection script execution, and create my key-value pair for script output based on that value. But I can't for the life of me figure out how to reference and check the host resource's properties while the script is running.  

    Also, my first thought was to have the custom property ("AssignedCollectorDeviceName" in that case) at the resource level, and check it while the Collection scripts runs, but realized I (don't think) I can read a resource-level property in that case, only instance-level properties, but I can't even figure out how to do that (without using the API). So in addition to using the auto property at the instance-level, maybe a PropertySource would be better? I'd like to learn how to make and use one, but in its script I think I would have the same problem of reading the value of resource property in order to do the logic to form the script output.

    • Mike_Moniz's avatar
      Mike_Moniz
      Icon for Professor rankProfessor

      The forum are having more problems :P

      You should be able to read any resource property from either AD or Collection script by doing $Prop = '##auto.AssignedCollectorDeviceName##' just like you can use $Host = '##SYSTEM.HOSTNAME##'. Just note that if the property does not exist, it will not get replaced, so you might want to add code that looks something like this

      $CollectorDev = '##auto.AssignedCollectorDeviceName##'
      if ($CollectorDev.SubString(0,2) -eq '##') { $CollectorDev = $null }
      

      But for an instance property, I haven't tried to pull that myself. If I needed the same information that the AD script had, I would just put the same code into the Collection script. Since 90% of the DataSources scripts I've done has been BatchScripts, many times the AD and Collector scripts are identical except that it has an "IsAD" true/false flag that branches what it outputs at the end.

       

      In general, you should only put in items related to the specific instance into the instance property. If you have information that is specific to the device itself, I do suggest you use a PropertySource instead.

      For example, for a disk space check, you might want to have auto.filesystem=ntfs or auto.removable=true at the instance-level since they can change per instance. But if you want to set something like auto.TotalSataPorts=4 would be better to put in a ProperySource since it's about the device and not each drive.

      • SteveDahlberg's avatar
        SteveDahlberg
        Icon for Neophyte rankNeophyte

        Thanks, Mike. And yes, that stumped me for the longest time, but a few weeks ago when looking through other DataSource scripts in LM, I saw that they just used a flag at top, and that's what I've been doing for a while now.

        Most of this I had questions about is working, but right when it seems so close, I'm trying to force a new datapoint to alert based on a key-value pair with value=1 (like I use in some other datapoints in this DataSource that work fine), but it isn't working.

        On the raw data page for the instance in question, "Poll Now", it clearly shows it's sending a 1 to this new datapoint and NaN to the rest, but when I close that and look at the Raw Data table, it shows "NoData" in the column for that datapoint. Any idea what could cause that? It's configured identically to similar datapoints in the DataSource, but what could be changing the value from 1 to NoData between "Poll Now" and the Raw Data table?

        - Steve

         

  • Wow, it's really acting up. Maybe it will post my comment this time. I missed whatever answer you gave because it just showed up as "undefined" (like my previous attempt did a minute ago). I will say this, though:

    I have it working with the ###auto.whateverproperty notation in Active Discovery and in reading property values (at the instance level). Even though I can't set a resource-level property when processing instances in the script, is it possible to read those properties' values?

    But my bigger question right now is: Is there any way to manually create and populate an instance-level custom auto property on an existing instance prior to the script updating it, or (without API calls) can it only be created/updated from the Active Discovery script?

    • SteveDahlberg's avatar
      SteveDahlberg
      Icon for Neophyte rankNeophyte

      Argh, it should have been:  ####auto.whateverproperty in the Active Discovery output.

       

  • One HUGE unresolved question for me is, in a DataSource definition, when you set Active Discovery "Discovery Schedule" setting to "Only when host/DataSource added or changed", does "changed" mean when you run Manual Discovery on the resource ( my assumption) and NEVER anytime else? Or does "changed" mean that it can sense when the DataSource has been updated and that triggers it to run even in the Manual setting?

    • Mike_Moniz's avatar
      Mike_Moniz
      Icon for Professor rankProfessor

      The documentation seems to only say "it can be configured to execute only when the DataSource is initially applied to a device, or when the Datasource (or the device it applies to) is updated in some way."

      I would take that as more than just manually kicking off AD, and likely covers things like updating the device's ip, name, categories, and such. But that is a guess as I never tested that myself. I would assume it might just run as some random time and not rely on it not running.

      • SteveDahlberg's avatar
        SteveDahlberg
        Icon for Neophyte rankNeophyte

        Our LM person who handed this task over to me (and I'm glad for it because I've learned a ton about LM in the past weeks), was strongly under the impression that the setting was that AD would run ONLY if the user manually ran it, and therefore I thought the same, and the wording of the option is compatible with that. However, once I got into creating this DataSource, I definitely noticed felt it had run unexpectedly a few times, so I realized that technically that setting wording could also be interpreted more ambiguously.

        So it's interesting to hear you say that. I wish I knew for sure about the items you mention, but primarily also whether any of the following could potentially trigger Active Discovery even with that setting applied:

        A script updating a property on a resource-level or instance-level property?

        Manually creating or editing a resource's property?

        Saving changes to the script in the DataSource, but not running "Force DataSource Re-Match" or "Run Active Discovery"?

        Same but with doing the "Force DataSource Re-Match" but not "Run Active Discovery"?

        -Steve