Assure1::Metrics Perl library

Description

Implements the functions for Metric rules.

Synopsis

use Assure1::Metrics;

Functions

AddCollectionToPolicy

Adds collection to consolidation policy.

AddCollectionToPolicy(\%options)

Options

DBH          -> Unified Assurance Database Handle Reference (i.e. \$DBH)
PolicyID     -> Consolidation Policy
CollectionID -> Collection

Returns

1. ErrorFlag   (0 Good, 1 Bad)
2. Message     (String)

Synopsis

my ($ErrorFlag, $Message) = AddCollectionToPolicy({
    DBH          => \$DBH,
    PolicyID     => $PolicyID,
    CollectionID => $CollectionID
});

AddDisplayInstance

Adds display instance.

AddDisplayInstance(\%options)

Options

DBH        -> Unified Assurance Database Handle Reference (i.e. \$DBH)
DeviceID   -> Display Device ID
InstanceID -> Source Metric Instance ID
CustomName -> Display Label

Returns

1. ErrorFlag   (0 Good, 1 Bad)
2. Message     (String)
3. DisplayID   (int) undef on error

Synopsis

my ($ErrorFlag, $Message, $DisplayID) = AddDisplayInstance({
    DBH        => \$DBH,
    DeviceID   => $DeviceID,
    InstanceID => $InstanceID,
    CustomName => $CustomName
});

AddMetricToCollection

Adds metric ID to collection.

AddMetricToCollection(\%options)

Options

DBH          -> Unified Assurance Database Handle Reference (i.e. \$DBH)
CollectionID -> Collection ID
MetricID     -> Metric ID

Returns

1. ErrorFlag   (0 Good, 1 Bad)
2. Message     (String)

Synopsis

my ($ErrorFlag, $Message) = AddMetricToCollection({
    DBH          => \$DBH,
    CollectionID => $CollectionID,
    MetricID     => $MetricID
});

AddThresholdToMetric

Adds threshold to metric.

AddThresholdToMetric(\%options)

Options

DBH         -> Unified Assurance Database Handle Reference (i.e. \$DBH)
MetricID    -> Metric
ThresholdID -> Threshold

Returns

1. ErrorFlag   (0 Good, 1 Bad)
2. Message     (String)

Synopsis

my ($ErrorFlag, $Message) = AddThresholdToMetric({
    DBH         => \$DBH,
    MetricID    => $MetricID,
    ThresholdID => $ThresholdID
});

CreateMeasurementFromMetricType

Helper function to convert Unified Assurance MetricTypeName to Influx Measurement.

CreateMeasurementFromMetricType($MetricType)

Arguments

MetricType -> Unified Assurance Metric Type Name

Returns

1. Influx Measurement

Synopsis

my $Measurement = CreateMeasurementFromMetricType($MetricType);

FindCollectionID

Find Collection by Name. If Create option set to true (1), will create automatically if not found.

FindCollectionID(\%options)

Options

DBH         -> Unified Assurance Database Handle Reference (i.e. \$DBH)
StorageHash -> Cache (i.e. $StorageHash)
Name        -> Collection Name
Description -> (Optional) Description
Create      -> (Optional) Create Flag (0=don't create if not found, 1=create if not found)

Returns

1. ErrorFlag      (0 Good, 1 Bad)
2. Message        (String)
3. Collection ID  (Integer) or undef if not created

Synopsis

my ($ErrorFlag, $Message, $CollectionID) = FindCollectionID({
    DBH         => \$DBH,
    StorageHash => $StorageHash,
    Name        => "My Collection",
    Description => "",
    Create      => 1
});

if (!$CollectionID) {
    $Log->Message('ERROR', "Error Finding Collection: $Message");
}

OR

my $CollectionID = FindCollectionID({
    DBH         => \$DBH,
    StorageHash => $StorageHash,
    Name        => "My Collection",
    Description => "",
    Create      => 1
});

if (!$CollectionID) {
    $Log->Message('ERROR', "Error Finding Collection");
}

FindInstanceID

Find Instance by Name and Type. If Create option set to true (1), will create instance automatically if not found.

FindInstanceID(\%options)

Options

DBH           -> Unified Assurance Database Handle Reference (i.e. \$DBH)
StorageHash   -> Cache (i.e. $StorageHash)
DeviceID      -> Device
Name          -> Instance Name
TypeID        -> Instance Type
                    0 - Unknown - N/A
                    1 - SNMP Interface
                    2 - SNMP Custom
                    3 - SNMP IPSLA
                    4 - Transaction
                    5 - Custom
                    6 - Service
Create        -> (Optional) Create Flag (0=don't create if not found, 1=create if not found)

Returns

1. ErrorFlag      (0 Good, 1 Bad)
2. Message        (String)
3. Instance ID (Integer) or undef if not created/updated

Synopsis

my ($ErrorFlag, $Message, $InstanceID) = FindInstanceID({
    DBH         => \$DBH,
    StorageHash => $StorageHash,
    Name        => "My Instance",
    DeviceID    => $DeviceID,
    TypeID      => 5,
    Create      => 1
});

if (!$InstanceID) {
    $Log->Message('ERROR', "Error Finding Instance: $Message");
}

OR

my $InstanceID = FindInstanceID({
    DBH         => \$DBH,
    StorageHash => $StorageHash,
    Name        => "My Instance",
    DeviceID    => $DeviceID,
    TypeID      => 5,
    Create      => 1
});

if (!$InstanceID) {
    $Log->Message('ERROR', "Error Finding Instance");
}

FindInstanceByIfIndex

Find Instance by Interface Index and returns ID. SNMP Interface Discovery Agent must be run to store DeviceInterfaces in order to find the Instance by IfIndex.

FindInstanceByIfIndex(\%options)

Options

DBH         -> Unified Assurance Database Handle Reference (i.e. \$DBH)
StorageHash -> Cache (i.e. $StorageHash)
DeviceID    -> Device
IfIndex     -> Interface Index

Returns

1. ErrorFlag    (0 Good, 1 Bad)
2. Message      (String)
3. Instance ID  (Integer) or undef if not created/updated

Synopsis

my ($ErrorFlag, $Message, $InstanceID) = FindInstanceByIfIndex({
    DBH         => \$DBH,
    StorageHash => $StorageHash,
    DeviceID    => $DeviceID,
    IfIndex     => $IfIndex
});

if (!$InstanceID) {
    $Log->Message('ERROR', "Error Finding Instance: $Message");
}

OR

my $InstanceID = FindInstanceByIfIndex({
    DBH         => \$DBH,
    StorageHash => $StorageHash,
    DeviceID    => $DeviceID,
    IfIndex     => $IfIndex
});

if (!$InstanceID) {
    $Log->Message('ERROR', "Error Finding Instance");
}

FindMetricID

Finds metric and returns ID. Will add metric if not found.

FindMetricID(\%options)

Options

DBH          -> Unified Assurance Database Handle Reference (i.e. \$DBH)
StorageHash  -> Cache (i.e. $StorageHash)
DeviceID     -> Device
InstanceID   -> Instance
MetricTypeID -> Metric Type
Factor       -> Metric Factor (1)
Max          -> (Optional) Metric Maximum
PollInterval -> Poll Interval
Create       -> (Optional) Create Flag (0=don't create if not found, 1=create if not found)

Returns

1. ErrorFlag   (0 Good, 1 Bad)
2. Message     (String)
3. Metric ID   (Integer) or undef if not created

Synopsis

my ($ErrorFlag, $Message, $MetricID) = FindMetricID({
    DBH          => \$DBH,
    StorageHash  => $StorageHash,
    DeviceID     => $DeviceID,
    InstanceID   => $InstanceID,
    MetricTypeID => $MetricTypeID,
    Factor       => 1,
    Max          => 0,
    PollInterval => 300,
    Create       => 1
});
if (!$MetricID) {
    $Log->Message('ERROR', "Error Finding Metric: $Message");
}

OR

my $MetricID = FindMetricID({
    DBH          => \$DBH,
    StorageHash  => $StorageHash,
    DeviceID     => $DeviceID,
    InstanceID   => $InstanceID,
    MetricTypeID => $MetricTypeID,
    Factor       => 1,
    Max          => 0,
    PollInterval => 300,
    Create       => 1
});
if (!$MetricID) {
    $Log->Message('ERROR', "Error Finding Metric");
}

FindMetricTypeID

Find metric type by Name. If Create option set to true (1), will create metric type automatically if not found.

FindMetricTypeID(\%options)

Options

DBH           -> Unified Assurance Database Handle Reference (i.e. \$DBH)
StorageHash   -> Cache (i.e. $StorageHash)
Name          -> Metric Type Name
Measurement   -> Measurement
FormatID      -> Format:
                    0 = integer
                    1 = float
Direction     -> TopN sort:
                    0 = Desc
                    1 = Asc
Unit          -> Unit Label (i.e. Bytes/sec)
UnitDivision  -> What number to rollup (i.e. 1024 = Bytes -> MegaBytes etc.)
Abbreviation  -> Abbreviation on Graph
MaxDefault    -> MaxDefault
TopNTypeID    -> Top N Type
TopNScopeID   -> Top N Scope
MetricGroupID -> (Optional) Metric Group to assign
Create        -> (Optional) Create Flag (0=don't create if not found, 1=create if not found)

Returns

1. ErrorFlag      (0 Good, 1 Bad)
2. Message        (String)
3. Metric Type ID (Integer) or undef if not created/updated

Synopsis

my ($ErrorFlag, $Message, $MetricTypeID) = FindMetricTypeID({
    DBH          => \$DBH,
    StorageHash  => $StorageHash,
    Name         => "My Metric Type",
    Measurement  => $Measurement,
    FormatID     => 0,
    Direction    => 0,
    Unit         => "Bytes/sec",
    UnitDivision => 1024,
    Abbreviation => "bps",
    MaxDefault   => $MaxDefault,
    TopNTypeID   => $TopNType,
    TopNScopeID  => $TypNScope,
    Create       => 1
});
if (!$MetricTypeID) {
    $Log->Message('ERROR', "Error Finding Metric Type: $Message");
}

OR

my $MetricTypeID = FindMetricTypeID({
    DBH          => \$DBH,
    StorageHash  => $StorageHash,
    Name         => "My Metric Type",
    Measurement  => $Measurement,
    FormatID     => 0,
    Direction    => 0,
    Unit         => "Bytes/sec",
    UnitDivision => 1024,
    Abbreviation => "bps",
    MaxDefault   => $MaxDefault,
    TopNTypeID   => $TopNType,
    TopNScopeID  => $TypNScope,
    Create       => 1
});
if (!$MetricTypeID) {
    $Log->Message('ERROR', "Error Finding Metric Type");
}

FindMetricSeries

Find metricSeries by MetricID.

FindMetricSeries(\%options)

Options

DBH           -> Unified Assurance Database Handle Reference (i.e. \$DBH)
StorageHash   -> Cache (i.e. $StorageHash)
MetricID      -> MetricID

Returns

1. ErrorFlag         (0 Good, 1 Bad)
2. Message           (String)
3. MetricSeriesKey   (String: Measurement | DeviceHost | InstanceName | DeviceZoneID)

Synopsis

my ($ErrorFlag, $Message, $MetricSeriesKey) = FindMetricSeries({
    DBH          => \$DBH,
    StorageHash  => $StorageHash,
    MetricID     => $MetricID
});

if (!$MetricSeriesKey) {
    $Log->Message('ERROR', "Error Finding Metric Series: $Message");
}

OR

my $MetricSeriesKey = FindMetricSeries({
    DBH          => \$DBH,
    StorageHash  => $StorageHash,
    MetricID     => $MetricID
});

if (!$MetricSeriesKey) {
    $Log->Message('ERROR', "Error Finding Metric Series");
}

FindMetricMax

Find MetricMax by MetricID.

FindMetricMax(\%options)

Options

DBH          -> Unified Assurance Database Handle Reference (i.e. \$DBH)
StorageHash  -> Cache (i.e. $StorageHash)
MetricID     -> MetricID

Returns

1. ErrorFlag      (0 Good, 1 Bad)
2. Message        (String)
3. Metric ID      (Integer)

Synopsis

my ($ErrorFlag, $Message, $MetricMax) = FindMetricMax({
    DBH          => \$DBH,
    StorageHash  => $StorageHash,
    MetricID     => $MetricID
});
if (!$MetricMax) {
    $Log->Message('ERROR', "Error Finding Metric Max: $Message");
}

OR

my $MetricMax = FindMetricMax({
    DBH          => \$DBH,
    StorageHash  => $StorageHash,
    MetricID     => $MetricID
});
if (!$MetricMax) {
    $Log->Message('ERROR', "Error Finding Metric Max");
}

FindShardID

Find ShardID by DeviceID.

FindShardID(\%options)

Options

DBH           -> Unified Assurance Database Handle Reference (i.e. \$DBH)
StorageHash   -> Cache (i.e. $StorageHash) stores in $StorageHash->{'DeviceShard'} OR $StorageHash->{'MetricShard'} based on lookup option used
DeviceID      -> DeviceID to lookup shard
 OR
MetricID      -> **DEPRECATED** MetricID to lookup shard

Returns

1. ErrorFlag      (0 Good, 1 Bad)
2. Message        (String)
3. ShardID        (Integer) or undef if error

Synopsis

my $ShardID = FindShardID({
    DBH          => \$DBH,
    StorageHash  => $StorageHash,
    DeviceID     => $DeviceID
});

if (!$ShardID) {
    $Log->Message('ERROR', "Error Finding ShardID for DeviceID=$DeviceID");
}

OR

DEPRECATED

my ($ErrorFlag, $Msg, $ShardID) = FindShardID({
    DBH          => \$DBH,
    StorageHash  => $StorageHash,
    MetricID     => $MetricID
});

if (!$ShardID) {
    $Log->Message('ERROR', "Error Finding ShardID for MetricID=$MetricID: $Msg");
}

FindDeviceIDFromMetricID

Find deviceID by MetricID.

FindDeviceIDFromMetricID(\%options)

Options

DBH           -> Unified Assurance Database Handle Reference (i.e. \$DBH)
MetricID      -> MetricID to lookup shard

Returns

1. ErrorFlag      (0 Good, 1 Bad)
2. Message        (String)
3. DeviceID        (Integer) or undef if error

Synopsis

my ($ErrorFlag, $Msg, $DeviceID) = FindDeviceIDFromMetricID({
    DBH          => \$DBH,
    StorageHash  => $StorageHash,
    MetricID     => $MetricID
});

if (!$DeviceID) {
    $Log->Message('ERROR', "Error Finding DeviceID for MetricID=$MetricID: $Msg");
}

FindThresholdID

Finds threshold and returns ID. Will add threshold if not found.

FindThresholdID(\%options)

Options

DBH               -> Unified Assurance Database Handle Reference (i.e. \$DBH)
StorageHash       -> Cache (i.e. $StorageHash)
Name              -> Threshold Name
Create            -> (Optional) Create Flag (0=don't create if not found, 1=create if not found)
Message           -> Notification Message
Measurement       -> Measurement
ThresholdTypeID   -> Threshold Type:
                        (Used by Standard Threshold Engine)
                        1 - Standard

                        (Used by Trend Threshold Engine)
                        10 - Trend %
                        20 - Trend Prediction

                        (Used by Abnormal Threshold Engine)
                        14 - Abnormal

                        (Used by Missing Data Threshold Engine)
                        16 - Missing Data
MetricField       -> InfluxDB field name
                        availability
                        utilization
                        value
TimeRange         -> (Unless Abnormal Thresholds) Period of time where data points will be retrieved and evaluated.
                     Relative time (s, m, h, d)
Frequency         -> (Standard Thresholds Only) How often the threshold is being checked by the threshold engine.
                     Relative time (s, m, h, d)
Offset            -> (Standard Thresholds Only) Offset to apply to TimeRange  by the threshold engine.
                     Relative time (s, m, h, d)
Function          -> (Standard Thresholds Only) What function to apply when calculating if a threshold is breached.
                     ThresholdFunctionID:
                        1 - Mean (default)
                        2 - Minimum
                        3 - Maximum
                        4 - Standard Deviation
                        5 - 95th Percentile
                        6 - Count
StatusID          -> Status (0=disabled, 1=enabled)
WarningOperator   -> (Unless Abnormal Thresholds) WarningOperator:
                        0 - equal (=)
                        1 - greater than (>)
                        2 - greater than or equal (>=)
                        3 - less than (<)
                        4 - less than or equal (<=)
                        5 - not equal (!=)
WarningValue      -> (Unless Abnormal Thresholds) WarningValue
WarningSeverity   -> WarningSeverity
CriticalOperator  -> (Unless Abnormal Thresholds) CriticalOperator:
                        0 - equal (=)
                        1 - greater than (>)
                        2 - greater than or equal (>=)
                        3 - less than (<)
                        4 - less than or equal (<=)
                        5 - not equal (!=)
CriticalValue     -> (Unless Abnormal Thresholds) CriticalValue
CriticalSeverity  -> (Unless Abnormal Thresholds) CriticalSeverity
ForecastTimeRange -> (Trend Prediction Only) Relative time (h, d ,w, m)
AbnormalProfileID -> (Abnormal Profiles Only) Abnormal Profile
CheckLocation     -> (Standard Thresholds Only) Location of threshold checking:
                        1 - Threshold Engine (default)
                        2 - Application

**DEPRECATED**

MetricTypeID      -> Metric Type
MetricPeriod      -> Metric Data Period
                     Daily   => All Threshold types (default)
                     Weekly  => All except 1, 2, 3
                     Monthly => Only 16, 20, 21, 22 types
                     Yearly  => Only 16, 20, 21, 22 types
Operator          -> Operator:
                        0 - equal (=)
                        1 - greater than (>)
                        2 - greater than or equal (>=)
                        3 - less than (<)
                        4 - less than or equal (<=)
                        5 - not equal (!=)
SampleRate        -> How many times a violation must occur before threshold is tripped
ThresholdValue    -> Threshold value
ViolationTypeID   -> Violation Type:
                        0 - Normal
                        1 - Warning
                        2 - Critical

Returns

1. ErrorFlag      (0 Good, 1 Bad)
2. Message        (String)
3. Threshold ID   (Integer) or undef if not found/created

Synopsis

my ($ErrorFlag, $Message, $ThresholdID) = FindThresholdID({
    DBH               => \$DBH,
    StorageHash       => $StorageHash,
    Name              => "My Threshold",
    Create            => 1,
    StatusID          => 1,
    TimeRange         => '15m',
    Frequency         => '5m',
    Offset            => '0m',
    Function          => 1,
    Message           => $Message,
    Measurement       => $Measurement,
    ThresholdTypeID   => 1,
    WarningOperator   => '',
    WarningValue      => '',
    WarningSeverity   => '',
    CriticalOperator  => '==',
    CriticalValue     => 0,
    CriticalSeverity  => 3,
    ForecastTimeRange => '15m',
    AbnormalProfileID => 0,
    CheckLocation     => 1
});

if (!$ThresholdID) {
    $Log->Message('ERROR', "Error Finding Threshold: $Message");
}

OR

my $ThresholdID = FindThresholdID({
    DBH               => \$DBH,
    StorageHash       => $StorageHash,
    Name              => "My Threshold",
    Create            => 1,
    StatusID          => 1,
    TimeRange         => '15m',
    Frequency         => '5m',
    Offset            => '0m',
    Function          => 1,
    Message           => $Message,
    Measurement       => $Measurement,
    ThresholdTypeID   => 1,
    WarningOperator   => '',
    WarningValue      => '',
    WarningSeverity   => '',
    CriticalOperator  => '==',
    CriticalValue     => 0,
    CriticalSeverity  => 3,
    ForecastTimeRange => '15m',
    AbnormalProfileID => 0,
    CheckLocation     => 1
});

if (!$ThresholdID) {
    $Log->Message('ERROR', "Error Finding Threshold");
}

ProcessCounter

Interpolates counter value. Returns the difference between Previous and Current values

ProcessCounter(\%options)

Options

StorageHash  -> Cache (i.e. $StorageHash)
MetricID     -> Metric
CurrentValue -> Current Value
SNMPIndex    -> OID Index

Returns

1. Counter Difference

Synopsis

my $Value = ProcessCounter({
    StorageHash  => $StorageHash,
    MetricID     => MetricID,
    CurrentValue => $Value,
    SNMPIndex    => $Index
});

SetMetricShardID

Deprecated

Applications no longer honor shards defined on metrics, only devices now

Sets the Metric ShardID. Updates definition only, does NOT migrate associated metric data to the new shard

SetMetricShardID(\%options)

Options

DBH        -> Unified Assurance Database Handle Reference (i.e. \$DBH)
MetricID   -> Metric definition to update
ShardID    -> ShardID to set

Returns

1. ErrorFlag   (0 Good, 1 Bad)
2. Message     (String)

Synopsis

my ($ErrorFlag, $Message) = SetMetricShardID({
    DBH      => \$DBH,
    MetricID => $MetricID,
    ShardID  => 2
});

UpdateDisplayInstance

Updated display instance name.

UpdateDisplayInstance(\%options)

Options

DBH        -> Unified Assurance Database Handle Reference (i.e. \$DBH)
DeviceID   -> Device
InstanceID -> Metric Instance
CustomName -> Display Name

Returns

1. ErrorFlag   (0 Good, 1 Bad)
2. Message     (String)

Synopsis

my ($ErrorFlag, $Message) = UpdateDisplayInstance({
    DBH        => \$DBH,
    DeviceID   => $DeviceID,
    InstanceID => $InstanceID,
    CustomName => $CustomName
});

if ($ErrorFlag) {
    $Log->Message('ERROR', "Error Updating Display Instance: $Message");
}

UpdateMethodOnMetric

Updated metric configuration method.

UpdateMethodOnMetric(\%options)

Options

DBH      -> Unified Assurance Database Handle Reference (i.e. \$DBH)
MetricID -> Metric
MethodID -> Method:
            0 = NA
            1 = SNMP
            2 = WMI
            3 = Other
            4 = Transaction

Returns

1. ErrorFlag   (0 Good, 1 Bad)
2. Message     (String)

Synopsis

my ($ErrorFlag, $Message) = UpdateMethodOnMetric({
    DBH      => \$DBH,
    MetricID => $MetricID,
    MethodID => $MethodID
});

if ($ErrorFlag) {
    $Log->Message('ERROR', "Error Setting Method: $Message");
}

UpdateMetricMaximum

Update metric configuration maximum.

UpdateMetricMaximum(\%options)

Options

DBH      -> Unified Assurance Database Handle Reference (i.e. \$DBH)
MetricID -> Metric
Maximum  -> New Maximum

Returns

1. ErrorFlag   (0 Good, 1 Bad)
2. Message     (String)

Synopsis

my ($ErrorFlag, $Message) = UpdateMetricMaximum({
    DBH      => \$DBH,
    MetricID => $MetricID,
    Maximum  => $Max
});

if ($ErrorFlag) {
    $Log->Message('ERROR', "Error Setting Maximum: $Message");
}

UpdateMetricCustomMaximum

Update metric configuration custom maximum (overrides gathered maximum).

UpdateMetricCustomMaximum(\%options)

Options

DBH      -> Unified Assurance Database Handle Reference (i.e. \$DBH)
MetricID -> Metric
Maximum  -> New Maximum

Returns

1. ErrorFlag   (0 Good, 1 Bad)
2. Message     (String)

Synopsis

my ($ErrorFlag, $Message) = UpdateMetricCustomMaximum({
    DBH      => \$DBH,
    MetricID => $MetricID,
    Maximum  => $Max
});

if ($ErrorFlag) {
    $Log->Message('ERROR', "Error Setting Maximum: $Message");
}

FindMetricFromSeries

Find MetricID by metricSeries.

FindMetricFromSeries(\%options)

Options

DBH           -> Unified Assurance Database Handle Reference (i.e. \$DBH)
StorageHash   -> Cache (i.e. $StorageHash)
DeviceHost    -> Device
InstanceName  -> Instance
Measurement   -> Measurement
DeviceZoneID  -> DeviceZone

Returns

1. ErrorFlag         (0 Good, 1 Bad)
2. Message           (String)
3. MetricID          (Integer) or undef if not created

Synopsis

my ($ErrorFlag, $Message, $MetricID) = FindMetricFromSeries({
    DBH           => \$DBH,
    StorageHash   => $StorageHash,
    DeviceHost    => $DeviceHost
    InstanceName  => $InstanceName
    Measurement   => $Measurement
    DeviceZoneID  => $DeviceZoneID
});

if (!$MetricID) {
    $Log->Message('ERROR', "Error Finding MetricID: $Message");
}

OR

my $MetricID  = FindMetricFromSeries({
    DBH           => \$DBH,
    StorageHash   => $StorageHash,
    DeviceHost    => $DeviceHost
    InstanceName  => $InstanceName
    Measurement   => $Measurement
    DeviceZoneID  => $DeviceZoneID
});

if (!$MetricID) {
    $Log->Message('ERROR', "Error Finding MetricID");
}