Example #1
0
function discover_processor(&$valid, $device, $processor_oid, $processor_index, $processor_type, $processor_descr, $processor_precision = 1, $value = NULL, $entPhysicalIndex = NULL, $hrDeviceIndex = NULL, $processor_returns_idle = 0)
{
    global $config;
    print_debug($device['device_id'] . " -> {$processor_oid}, {$processor_index}, {$processor_type}, {$processor_descr}, {$processor_precision}, {$value}, {$entPhysicalIndex}, {$hrDeviceIndex}");
    // Check processor description
    if (!$processor_descr) {
        print_debug("Skipped by empty description: {$processor_descr} ");
        return FALSE;
    } else {
        $processor_descr = substr($processor_descr, 0, 64);
        // Limit descr to 64 chars accordingly as in DB
    }
    // Skip discovery processor if value not numeric or null(default)
    if ($value !== NULL) {
        $value = snmp_fix_numeric($value);
    }
    // Remove unnecessary spaces
    if (!(is_numeric($value) || $value === NULL)) {
        print_debug("Skipped by not numeric value: {$value}, {$processor_descr} ");
        return FALSE;
    }
    // Check processor ignore filters
    foreach ($config['ignore_processor'] as $bi) {
        if (strcasecmp($bi, $processor_descr) == 0) {
            print_debug("Skipped by equals: {$bi}, {$processor_descr} ");
            return FALSE;
        }
    }
    foreach ($config['ignore_processor_string'] as $bi) {
        if (stripos($processor_descr, $bi) !== FALSE) {
            print_debug("Skipped by strpos: {$bi}, {$processor_descr} ");
            return FALSE;
        }
    }
    foreach ($config['ignore_processor_regexp'] as $bi) {
        if (preg_match($bi, $processor_descr) > 0) {
            print_debug("Skipped by regexp: {$bi}, {$processor_descr} ");
            return FALSE;
        }
    }
    $params = array('processor_index', 'entPhysicalIndex', 'hrDeviceIndex', 'processor_oid', 'processor_type', 'processor_descr', 'processor_precision', 'processor_returns_idle');
    //$params_state = array('processor_usage');
    $processor_db = dbFetchRow("SELECT * FROM `processors` WHERE `device_id` = ? AND `processor_index` = ? AND `processor_type` = ?", array($device['device_id'], $processor_index, $processor_type));
    if (!isset($processor_db['processor_id'])) {
        $update = array('device_id' => $device['device_id']);
        if (!$processor_precision) {
            $processor_precision = 1;
        }
        foreach ($params as $param) {
            $update[$param] = ${$param} === NULL ? array('NULL') : ${$param};
        }
        $id = dbInsert($update, 'processors');
        if ($processor_precision != 1) {
            $value = round($value / $processor_precision, 2);
        }
        // The OID returns idle value, so we subtract it from 100.
        if ($processor_returns_idle) {
            $value = 100 - $value;
        }
        $update_state = array('processor_id' => $id, 'processor_usage' => $value);
        //foreach ($params_state as $param) { $update_state[$param] = $$param; }
        dbInsert($update_state, 'processors-state');
        $GLOBALS['module_stats']['processors']['added']++;
        //echo('+');
        log_event("Processor added: index {$processor_index}, type {$processor_type}, descr {$processor_descr}", $device, 'processor', $id);
    } else {
        $update = array();
        foreach ($params as $param) {
            if (${$param} != $processor_db[$param]) {
                $update[$param] = ${$param} === NULL ? array('NULL') : ${$param};
            }
        }
        if (count($update)) {
            dbUpdate($update, 'processors', '`processor_id` = ?', array($processor_db['processor_id']));
            $GLOBALS['module_stats']['processors']['updated']++;
            //echo('U');
            log_event("Processor updated: index {$processor_index}, mib {$processor_type}, descr {$processor_descr}", $device, 'processor', $processor_db['processor_id']);
        } else {
            $GLOBALS['module_stats']['processors']['unchanged']++;
            //echo('.');
        }
    }
    $valid[$processor_type][$processor_index] = 1;
}
Example #2
0
function poll_status($device)
{
    global $config, $agent_sensors, $ipmi_sensors, $graphs, $oid_cache;
    $sql = "SELECT * FROM `status`";
    $sql .= " LEFT JOIN `status-state` USING(`status_id`)";
    $sql .= " WHERE `device_id` = ?";
    foreach (dbFetchRows($sql, array($device['device_id'])) as $status_db) {
        //print_cli_heading("Status: ".$status_db['status_descr']. "(".$status_db['poller_type'].")", 3);
        print_debug("Checking (" . $status_db['poller_type'] . ") " . $status_db['status_descr'] . " ");
        // $status_poll = $status_db;    // Cache non-humanized status array for use as new status state
        if ($status_db['poller_type'] == "snmp") {
            // Check if a specific poller file exists for this status, else collect via SNMP.
            $file = $config['install_dir'] . "/includes/polling/status/" . $status_db['status_type'] . ".inc.php";
            if (is_file($file)) {
                include $file;
            } else {
                // Take value from $oid_cache if we have it, else snmp_get it
                if (is_numeric($oid_cache[$status_db['status_oid']])) {
                    print_debug("value taken from oid_cache");
                    $status_value = $oid_cache[$status_db['status_oid']];
                } else {
                    $status_value = snmp_get($device, $status_db['status_oid'], "-OUqnv", "SNMPv2-MIB");
                }
                $status_value = snmp_fix_numeric($status_value);
            }
        } else {
            if ($status_db['poller_type'] == "agent") {
                if (isset($agent_sensors['state'])) {
                    $status_value = $agent_sensors['state'][$status_db['status_type']][$status_db['status_index']]['current'];
                } else {
                    print_warning("No agent status data available.");
                    continue;
                }
            } else {
                if ($status_db['poller_type'] == "ipmi") {
                    if (isset($ipmi_sensors['state'])) {
                        $status_value = $ipmi_sensors['state'][$status_db['status_type']][$status_db['status_index']]['current'];
                    } else {
                        print_warning("No IPMI status data available.");
                        continue;
                    }
                } else {
                    print_warning("Unknown status poller type.");
                    continue;
                }
            }
        }
        $status_polled_time = time();
        // Store polled time for current status
        // Write new value and humanize (for alert checks)
        $state_array = get_state_array($status_db['status_type'], $status_value, $status_db['poller_type']);
        $status_poll['status_value'] = $state_array['value'];
        $status_poll['status_name'] = $state_array['name'];
        if ($status_db['status_ignore'] || $status_db['status_disable']) {
            $status_poll['status_event'] = 'ignore';
        } else {
            $status_poll['status_event'] = $state_array['event'];
        }
        // If last change never set, use current time
        if (empty($status_db['status_last_change'])) {
            $status_db['status_last_change'] = $status_polled_time;
        }
        if ($status_poll['status_event'] != $status_db['status_event']) {
            // Status event changed, log and set status_last_change
            $status_poll['status_last_change'] = $status_polled_time;
            if ($status_poll['status_event'] == 'ignore') {
                print_message("[%ystatus Ignored%n]", 'color');
            } else {
                if ($status_db['status_event'] != '') {
                    // If old state not empty and new state not equals to new state
                    $msg = 'Status ';
                    switch ($status_poll['status_event']) {
                        case 'alert':
                            // New state alerted
                            $msg .= "Alert: " . $device['hostname'] . " " . $status_db['status_descr'] . " entered ALERT state: " . $status_poll['status_name'] . " (previous: " . $status_db['status_name'] . ")";
                            log_event($msg, $device, 'status', $status_db['status_id'], 'warning');
                            break;
                        case 'warning':
                            // New state warned
                            $msg .= "Warning: " . $device['hostname'] . " " . $status_db['status_descr'] . " entered WARNING state: " . $status_poll['status_name'] . " (previous: " . $status_db['status_name'] . ")";
                            log_event($msg, $device, 'status', $status_db['status_id']);
                            break;
                        case 'ok':
                            // New state ok
                            $msg .= "Ok: " . $device['hostname'] . " " . $status_db['status_descr'] . " entered OK state: " . $status_poll['status_name'] . " (previous: " . $status_db['status_name'] . ")";
                            log_event($msg, $device, 'status', $status_db['status_id'], 'warning');
                            break;
                    }
                }
            }
        } else {
            // If status not changed, leave old last_change
            $status_poll['status_last_change'] = $status_db['status_last_change'];
        }
        if (OBS_DEBUG > 1) {
            print_vars($status_poll);
        }
        // Send statistics array via AMQP/JSON if AMQP is enabled globally and for the ports module
        if ($config['amqp']['enable'] == TRUE && $config['amqp']['modules']['status']) {
            $json_data = array('value' => $status_value);
            messagebus_send(array('attribs' => array('t' => time(), 'device' => $device['hostname'], 'device_id' => $device['device_id'], 'e_type' => 'status', 'e_type' => $status_db['status_type'], 'e_index' => $status_db['status_index']), 'data' => $json_data));
        }
        // Update StatsD/Carbon
        if ($config['statsd']['enable'] == TRUE) {
            StatsD::gauge(str_replace(".", "_", $device['hostname']) . '.' . 'status' . '.' . $status_db['status_class'] . '.' . $status_db['status_type'] . '.' . $status_db['status_index'], $status_value);
        }
        // Update RRD - FIXME - can't convert to NG because filename is dynamic! new function should return index instead of filename.
        $rrd_file = get_status_rrd($device, $status_db);
        rrdtool_create($device, $rrd_file, "DS:status:GAUGE:600:-20000:U");
        rrdtool_update($device, $rrd_file, "N:{$status_value}");
        // Enable graph
        $graphs[$sensor_db['status']] = TRUE;
        // Check alerts
        $metrics = array();
        $metrics['status_value'] = $status_value;
        $metrics['status_name'] = $status_poll['status_name'];
        $metrics['status_name_uptime'] = $status_polled_time - $status_poll['status_last_change'];
        $metrics['status_event'] = $status_poll['status_event'];
        //print_cli_data("Event (State)", $status_poll['status_event'] ." (".$status_poll['status_name'].")", 3);
        $GLOBALS['table_rows'][] = array($status_db['status_descr'], $status_db['status_type'], $status_db['status_index'], $status_db['poller_type'], $status_poll['status_name'], $status_poll['status_event'], format_unixtime($status_poll['status_last_change']));
        check_entity('status', $status_db, $metrics);
        // Update SQL State
        if (is_numeric($status_db['status_polled'])) {
            dbUpdate(array('status_value' => $status_value, 'status_name' => $status_poll['status_name'], 'status_event' => $status_poll['status_event'], 'status_last_change' => $status_poll['status_last_change'], 'status_polled' => $status_polled_time), 'status-state', '`status_id` = ?', array($status_db['status_id']));
        } else {
            dbInsert(array('status_id' => $status_db['status_id'], 'status_value' => $status_value, 'status_name' => $status_poll['status_name'], 'status_event' => $status_poll['status_event'], 'status_last_change' => $status_poll['status_last_change'], 'status_polled' => $status_polled_time), 'status-state');
        }
    }
}
Example #3
0
         // Get processors count if exist for MIB
         $processor_count = snmp_get($device, $entry['oid_count'], '-OQUvs', $mib);
         if ($processor_count > 1) {
             $descr .= ' x' . $processor_count;
         }
     }
     // Idle
     $idle = isset($entry['idle']) && $entry['idle'] ? 1 : 0;
     // Precision (scale)
     $precision = 1;
     if (isset($entry['scale']) && is_numeric($entry['scale']) && $entry['scale'] != 1) {
         // FIXME, currently we support only int precision, need convert all to float scale!
         $precision = round(1 / $entry['scale'], 0);
     }
     $usage = snmp_get($device, $entry['oid'], '-OQUvs', $mib);
     $usage = snmp_fix_numeric($usage);
     if (is_numeric($usage)) {
         if (empty($entry['oid_num'])) {
             // Use snmptranslate if oid_num not set
             $entry['oid_num'] = snmp_translate($entry['oid'], $mib);
         }
         if (isset($entry['rename_rrd'])) {
             $old_rrd = 'processor-' . $entry['rename_rrd'];
             $new_rrd = 'processor-' . $entry_name . '-' . $index;
             rename_rrd($device, $old_rrd, $new_rrd);
             unset($old_rrd, $new_rrd);
         }
         discover_processor($valid['processor'], $device, $entry['oid_num'], $index, $entry_name, $descr, $precision, $usage, NULL, NULL, $idle);
         $entry['found'] = TRUE;
     }
 }
function poll_status($device)
{
    global $config, $agent_status, $ipmi_status, $graphs, $oid_cache;
    $sql = "SELECT *, `status`.`status_id` AS `status_id`";
    $sql .= " FROM  `status`";
    $sql .= " LEFT JOIN  `status-state` ON  `status`.status_id =  `status-state`.status_id";
    $sql .= " WHERE `device_id` = ?";
    foreach (dbFetchRows($sql, array($device['device_id'])) as $status_db) {
        print_debug("Checking (" . $status_db['poller_type'] . ") " . $status_db['status_descr'] . " ");
        // $status_poll = $status_db;    // Cache non-humanized status array for use as new status state
        if ($status_db['poller_type'] == "snmp") {
            // Check if a specific poller file exists for this status, else collect via SNMP.
            $file = $config['install_dir'] . "/includes/polling/status/" . $status_db['status_type'] . ".inc.php";
            if (is_file($file)) {
                include $file;
            } else {
                // Take value from $oid_cache if we have it, else snmp_get it
                if (is_numeric($oid_cache[$status_db['status_oid']])) {
                    print_debug("value taken from oid_cache");
                    $status_value = $oid_cache[$status_db['status_oid']];
                } else {
                    $status_value = snmp_fix_numeric(snmp_get($device, $status_db['status_oid'], "-OUqnv", "SNMPv2-MIB", mib_dirs()));
                }
            }
        } else {
            if ($status_db['poller_type'] == "agent") {
                if (isset($agent_status)) {
                    $status_value = $agent_status[$class][$status_db['status_type']][$status_db['status_index']]['current'];
                    // FIXME pass unit?
                } else {
                    print_warning("No agent status data available.");
                    continue;
                }
            } else {
                if ($status_db['poller_type'] == "ipmi") {
                    if (isset($ipmi_status)) {
                        $status_value = $ipmi_status[$class][$status_db['status_type']][$status_db['status_index']]['current'];
                        $unit = $ipmi_status[$class][$status_db['status_type']][$status_db['status_index']]['unit'];
                    } else {
                        print_warning("No IPMI status data available.");
                        continue;
                    }
                } else {
                    print_warning("Unknown status poller type.");
                    continue;
                }
            }
        }
        $rrd_file = get_status_rrd($device, $status_db);
        rrdtool_create($device, $rrd_file, "DS:status:GAUGE:600:-20000:U");
        echo "{$status_value} {$unit} ";
        // Write new value and humanize (for alert checks)
        $status_poll['status_value'] = $status_value;
        // Set status_event and status_name if they're not already set.
        if (isset($config['status_states'][$status_db['status_type']]) && !isset($status['status_event'])) {
            $status_poll['status_value'] = (int) $status_poll['status_value'];
            $status_poll['status_name'] = $config['status_states'][$status_db['status_type']][$status_poll['status_value']]['name'];
            if ($status_poll['status_ignore'] || $status['status_disable']) {
                $status_poll['status_event'] = 'ignore';
            } else {
                $status_poll['status_event'] = $config['status_states'][$status_db['status_type']][$status_poll['status_value']]['event'];
            }
        }
        // FIXME I left the eventlog code for now, as soon as alerts send an entry to the eventlog this can go.
        if ($status_poll['status_event'] != 'ignore') {
            if ($status_db['status_event'] != '' && $status_poll['status_event'] != $status_db['status_event']) {
                // If old state not empty and new state not equals to new state
                switch ($status_poll['status_event']) {
                    case 'alert':
                        // New state alerted
                        $msg = "Alarm: " . $device['hostname'] . " " . $status_db['status_descr'] . " entered ALERT state: " . $status_poll['status_name'] . " (previous: " . $status_db['status_name'] . ")";
                        log_event($msg, $device, 'status', $status_db['status_id'], 'warning');
                        break;
                    case 'warning':
                        // New state warned
                        $msg = "Warning: " . $device['hostname'] . " " . $status_db['status_descr'] . " entered WARNING state: " . $status_poll['status_name'] . " (previous: " . $status_db['status_name'] . ")";
                        log_event($msg, $device, 'status', $status_db['status_id']);
                        break;
                    case 'up':
                        // New state ok
                        $msg = "Up: " . $device['hostname'] . " " . $status_db['status_descr'] . " entered NORMAL state: " . $status_poll['status_name'] . " (previous: " . $status_db['status_name'] . ")";
                        log_event('Status ' . $msg, $device, 'status', $status_db['status_id'], 'warning');
                        break;
                }
            }
        } else {
            print_message("[%ystatus Ignored%n]", 'color');
        }
        print_r($status_poll);
        echo PHP_EOL;
        // Send statistics array via AMQP/JSON if AMQP is enabled globally and for the ports module
        if ($config['amqp']['enable'] == TRUE && $config['amqp']['modules']['status']) {
            $json_data = array('value' => $status_value);
            messagebus_send(array('attribs' => array('t' => time(), 'device' => $device['hostname'], 'device_id' => $device['device_id'], 'e_type' => 'status', 'e_type' => $status_db['status_type'], 'e_index' => $status_db['status_index']), 'data' => $json_data));
        }
        // Update StatsD/Carbon
        if ($config['statsd']['enable'] == TRUE) {
            StatsD::gauge(str_replace(".", "_", $device['hostname']) . '.' . 'status' . '.' . $status_db['status_class'] . '.' . $status_db['status_type'] . '.' . $status_db['status_index'], $status_value);
        }
        // Update RRD
        rrdtool_update($device, $rrd_file, "N:{$status_value}");
        // Enable graph
        $graphs[$status_db['status_class']] = TRUE;
        // Check alerts
        $metrics = array();
        $metrics['status_value'] = $status_value;
        $metrics['status_name'] = $status_poll['status_name'];
        $metrics['status_event'] = $status_poll['status_event'];
        check_entity('status', $status_db, $metrics);
        // Update SQL State
        if (is_numeric($status_db['status_polled'])) {
            dbUpdate(array('status_value' => $status_value, 'status_name' => $status_poll['status_name'], 'status_event' => $status_poll['status_event'], 'status_polled' => time()), 'status-state', '`status_id` = ?', array($status_db['status_id']));
        } else {
            dbInsert(array('status_id' => $status_db['status_id'], 'status_value' => $status_value, 'status_name' => $status_poll['status_name'], 'status_event' => $status_poll['status_event'], 'status_polled' => time()), 'status-state');
        }
    }
}
function discover_processor(&$valid, $device, $processor_oid, $processor_index, $processor_type, $processor_descr, $processor_precision = "1", $current = NULL, $entPhysicalIndex = NULL, $hrDeviceIndex = NULL)
{
    global $config;
    print_debug($device['device_id'] . " -> {$processor_oid}, {$processor_index}, {$processor_type}, {$processor_descr}, {$processor_precision}, {$current}, {$entPhysicalIndex}, {$hrDeviceIndex}");
    // Check processor description
    if (!$processor_descr) {
        print_debug("Skipped by empty description: {$processor_descr} ");
        return FALSE;
    } else {
        $processor_descr = substr($processor_descr, 0, 64);
        // Limit descr to 64 chars accordingly as in DB
    }
    // Skip discovery processor if value not numeric or null(default)
    if ($current !== NULL) {
        $current = snmp_fix_numeric($current);
    }
    // Remove unnecessary spaces
    if (!(is_numeric($current) || $current === NULL)) {
        print_debug("Skipped by not numeric value: {$current}, {$processor_descr} ");
        return FALSE;
    }
    // Check processor ignore filters
    foreach ($config['ignore_processor'] as $bi) {
        if (strcasecmp($bi, $processor_descr) == 0) {
            print_debug("Skipped by equals: {$bi}, {$processor_descr} ");
            return FALSE;
        }
    }
    foreach ($config['ignore_processor_string'] as $bi) {
        if (stripos($processor_descr, $bi) !== FALSE) {
            print_debug("Skipped by strpos: {$bi}, {$processor_descr} ");
            return FALSE;
        }
    }
    foreach ($config['ignore_processor_regexp'] as $bi) {
        if (preg_match($bi, $processor_descr) > 0) {
            print_debug("Skipped by regexp: {$bi}, {$processor_descr} ");
            return FALSE;
        }
    }
    $params = array('processor_index', 'entPhysicalIndex', 'hrDeviceIndex', 'processor_oid', 'processor_type', 'processor_descr', 'processor_precision');
    //$params_state = array('processor_usage');
    $processor_db = dbFetchRow("SELECT * FROM `processors` WHERE `device_id` = ? AND `processor_index` = ? AND `processor_type` = ?", array($device['device_id'], $processor_index, $processor_type));
    if (!isset($processor_db['processor_id'])) {
        $update = array('device_id' => $device['device_id']);
        foreach ($params as $param) {
            $update[$param] = ${$param} === NULL ? array('NULL') : ${$param};
        }
        $id = dbInsert($update, 'processors');
        $update_state = array('processor_id' => $id, 'processor_usage' => $current);
        //foreach ($params_state as $param) { $update_state[$param] = $$param; }
        dbInsert($update_state, 'processors-state');
        echo '+';
        log_event("处理器已添加: index {$processor_index}, type {$processor_type}, descr {$processor_descr}", $device, 'processor', $id);
    } else {
        $update = array();
        foreach ($params as $param) {
            if (${$param} != $processor_db[$param]) {
                $update[$param] = ${$param} === NULL ? array('NULL') : ${$param};
            }
        }
        if (count($update)) {
            dbUpdate($update, 'processors', '`processor_id` = ?', array($processor_db['processor_id']));
            echo 'U';
            log_event("处理器已更新: index {$processor_index}, mib {$processor_type}, descr {$processor_descr}", $device, 'processor', $processor_db['processor_id']);
        } else {
            echo '.';
        }
    }
    $valid[$processor_type][$processor_index] = 1;
}
Example #6
0
 *
 */
$table_rows = array();
$sql = "SELECT `processors`.*, `processors-state`.`processor_usage`, `processors-state`.`processor_polled`";
$sql .= " FROM `processors`";
$sql .= " LEFT JOIN `processors-state` USING(`processor_id`)";
$sql .= " WHERE `device_id` = ?";
foreach (dbFetchRows($sql, array($device['device_id'])) as $processor) {
    // echo("Processor " . $processor['processor_descr'] . " ");
    $file = $config['install_dir'] . "/includes/polling/processors/" . $processor['processor_type'] . ".inc.php";
    if (is_file($file)) {
        include $file;
    } else {
        $proc = snmp_get($device, $processor['processor_oid'], "-OUQnv");
    }
    $proc = snmp_fix_numeric($proc);
    if (!$processor['processor_precision']) {
        $processor['processor_precision'] = 1;
    }
    $proc = round($proc / $processor['processor_precision'], 2);
    if ($processor['processor_returns_idle'] == 1) {
        $proc = 100 - $proc;
    }
    // The OID returns idle value, so we subtract it from 100.
    $graphs['processor'] = TRUE;
    // echo($proc . "%\n");
    // Update StatsD/Carbon
    if ($config['statsd']['enable'] == TRUE) {
        StatsD::gauge(str_replace(".", "_", $device['hostname']) . '.' . 'processor' . '.' . $processor['processor_type'] . "-" . $processor['processor_index'], $proc);
    }
    // Update RRD
Example #7
0
     $descr = $sensor[$entry['oid_descr']];
 } else {
     $descr = '';
 }
 if (!$descr) {
     if (isset($entry['descr'])) {
         if (strpos($entry['descr'], '%i%') === FALSE) {
             $descr = $entry['descr'] . ' ' . $index;
         } else {
             $descr = str_replace('%i%', $i, $entry['descr']);
         }
     } else {
         $descr = 'Sensor ' . $index;
     }
 }
 $value = snmp_fix_numeric($sensor[$entry['oid']]);
 if (is_numeric($value)) {
     // Check for min/max values, when sensors report invalid data as sensor does not exist
     if (isset($entry['min']) && $value <= $entry['min'] || isset($entry['max']) && $value >= $entry['max']) {
         continue;
     }
     $options = array();
     // Check limits oids if set
     foreach (array('limit_low', 'limit_low_warn', 'limit_high_warn', 'limit_high') as $limit) {
         if (isset($entry['oid_' . $limit])) {
             if (isset($sensor[$entry['oid_' . $limit]])) {
                 $options[$limit] = $sensor[$entry['oid_' . $limit]];
             } else {
                 $options[$limit] = snmp_get($device, $entry['oid_' . $limit] . $dot_index, '-OQUvs');
             }
             // Numeric oid
Example #8
0
 /**
  * @dataProvider providerSnmpFixNumeric
  */
 public function testSnmpFixNumeric($value, $result)
 {
     $this->assertSame($result, snmp_fix_numeric($value));
 }