Cannot access $dci from script

Started by rgkordia, August 22, 2018, 08:30:47 AM

Previous topic - Next topic

rgkordia

Hi,

I want to read the DCI's name from a script, and I've seen other posts referencing the $dci->name (or similar) variables.  But when I attempt to access $dci my script was crashing.  Very basically, I was trying to execute trace(1, "dciname=".$dci->name);

To test this I created a very simple script in the script library:

sub main()
{
    if ($dci == null)
        trace(1, "dci is null");
    else
        trace(1, "dci is not null");
}

I then created a DCI on an existing router node, set the type to "script" and selected the above script.

In my logs it shows "dci is null".

How can I get the DCI's name from within my script.

I'm running v2.1 on Windows.

Thanks,
Richard

Victor Kirhenshtein

Hi,

$dci is not set for data collection script, only for transformation and threshold scripts.

Best regards,
Victor

Tatjana Dubrovica

You can use Internal "Dummy" DCI and make all scripting in transformation script section.

rgkordia

Ok.

So I have a script in my library derived from the 95th percentile example on the wiki.  It runs once per day and works by finding a DCI from the current node based on the DCI's name, pulling the past 24 hours of values, then calculates the 95th percentile and populates the result in the DCI that called the script (i.e. the script "returns" the calculated 95th percentile).  This script gets called across multiple devices, and sometimes there are multiple instances per device if I need 95th values for more than 1 interface.  This latter use case means I need a way to dynamically work out which DCI to pull the values from.

I therefore need a way to pass a parameter to the script so that it knows which DCI to search for.  Is there a way to do this - maybe a parameter to main()?  I was planning on including a string in the calling DCI's name that I can extract and construct the DCI name to search for, but as $dci is not set I cannot use this approach.

Here's the code of what I'm trying to do (obviously not working because of $dci).


sub main()
{
    array inValues;
    array outValues;
    collectionPeriod = 24 * 60 * 60;
   
    // Calculate the DCI name dynamically based on the name of the DCI object calling us.
    // $dci->name should be formatted "<sometext>: <interfacename>" (the ": " is important and must be unique).
    InputPrefix = "Input Bandwidth (bps) on ";
    OutputPrefix = "Output Bandwidth (bps) on ";
    WANname = "";
    if (index($dci->name, ": ") > 0)
        WANname = substr($dci->name, index($dci->name, ": ") + 2);
   
    // Get DCI's for input/output
    inDCIid = FindDCIByDescription($node, InputPrefix . WANname);
    outDCIid = FindDCIByDescription($node, OutputPrefix . WANname);

    // If DCI ID was determined, obtain array of all values for the past "collectionPeriod" seconds
    if (inDCIid > 0)
        inValues = GetDCIValues($node, inDCIid, time() - collectionPeriod, time());
    if (outDCIid > 0)
        outValues = GetDCIValues($node, outDCIid, time() - collectionPeriod, time());

    // Get the 95th percentile reading for each array
    in95th = calc95th(inValues);
    out95th = calc95th(outValues);

    // Utilisation is the max of any of the calculated 95th percentile values
    utilisation = max((in95th != null ? in95th : 0),
                      (out95th != null ? out95th : 0));

    return utilisation;
}


I guess I could create a script for every single interface, but that's a pain to maintain.

Rich

Tursiops

If you are looking for a 95th percentile for all interfaces you are collecting data for, you can probably use the same type of instance discovery you are using for monitoring those interfaces to create the 95th DCIs. As part of that 95th instance discovery, you can pass parameters to the script. For example if your script is called "myScript" you could call it as "myScript("{instance}")" to pass the instance value through.
That should allow you to locate the DCI to pull the data for the calculation from.

Alternatively, you can configure a custom attribute on each node that lists all interfaces you care about.
You can then read in that custom attribute in your script.