nbuchwitz / icingaweb2-module-map

An openstreetmap based map module for host and service state visualization with Icinga Web 2
https://icinga.com/docs/icinga2/latest/doc/13-addons/
GNU General Public License v2.0
81 stars 17 forks source link

20 seconds to load the points. #28

Closed GrexAut closed 7 years ago

GrexAut commented 7 years ago

I updated all Hosts (>5k) via API, but unfortunately, I had to remove geolcation variable on some hosts (because this hosts are sometimes offline, and not necessary. I set geolocation to "", but this didn't worked, so I removed the affected hosts and imported them new with the API, because removing attributes is not possible.

Now the page needs 20 seconds to load the points on the map, is there any caching problem? Verions: map: 1.0.3 icinga2: 2.4.1

nbuchwitz commented 7 years ago

Everything was fine before you've had to remove the geolocation attribute from some hosts?

GrexAut commented 7 years ago

Yep, first I set geolocation to value "", this was not working and showed me no hosts on map ( I thought, maybe I don't waited 20s), so I deleted the hosts. I let the page open, and the hosts appears 20s after opening the map. The other thing is, maybe the "fullimport" from scriptfile (add the geolocation coords) was not finished, and not all hosts are showed up, maybe I have exceed any limit?

I have a snapshot, I could roll back, but before I do, I want to ask if I disable the module, delete it, and extract them to modules folder again, it would have been all "resettet" or are there any files on the system?

Thanks

nbuchwitz commented 7 years ago

It looks like a backend problem (inefficient queries). Could you test if the following url terminates with an out of time error?

YOUR_ICINGAWEB2_URL/icingaweb2/map/data/points

GrexAut commented 7 years ago

okay, it seems too many hosts :( I changed query from https://github.com/nbuchwitz/icingaweb2-module-map/blob/master/application/controllers/DataController.php#L147 to $query = $this->backend ->select() ->from('customvar', array( 'host_name', 'varvalue')) ->where('varname', 'geolocation') ->limit(100); The execution time is 373ms, I removed the limit, 12-20s :/ Ideas how to speed it up?

nbuchwitz commented 7 years ago

Not for now, but i'm on it. I will reorganize the statements and keep you updated!

GrexAut commented 7 years ago

I want to use this map, so I changed a little bit in the function, I don't know and find anything about Icinga2 Dev Documenation, how to use the query function correctly. So instead of using joins I wanted, I'm using a second query and save all host states in array $hosts. I don't need showing services on detail map, so services is empty (=> array()).

Here my little change, maybe it can help someone, it is ~10 times faster with 4235 hosts. File: application/DataController.php

    public function pointsAction() {
        // Borrowed from monitoring module
        // Handle soft and hard states
        $config = $this->config();
        $stateType = strtolower($this->params->shift('stateType', $config->get('map', 'stateType', 'soft')
        ));

        if ($stateType === 'hard') {
            $this->stateColumn = 'hard_state';
            $this->stateChangeColumn = 'last_hard_state_change';
        } else {
            $this->stateColumn = 'state';
            $this->stateChangeColumn = 'last_state_change';
        }

        $query = $this->backend
                ->select()
                ->from('customvar', array(
                    'host_name',
                    'varvalue'))
                ->where('varname', 'geolocation');

        $query_hoststatus = $this->backend
                ->select()
                ->from('hoststatus', array(
            'host_name',
            'host_display_name',
            'host_icon_image',
            'host_icon_image_alt',
            'host_acknowledged',
            'host_state' => 'host_' . $this->stateColumn,
            'host_last_state_change' => 'host_' . $this->stateChangeColumn,
            'host_in_downtime'));

        $hosts = array();
        if (count($query_hoststatus->fetchAll()) > 0) {
            foreach ($query_hoststatus as $row) {
                $hosts[$row->host_name] = (array) $row;
            }
        }

        $points = array();
        if (count($query->fetchAll()) > 0) {
            foreach ($query as $row) {
                $hostname = $row->host_name;
                $coordinates = explode(",", $row->varvalue);

//                $host = $this->hostData($hostname);
                // skip this host, if the user lacks sufficient permission to fetch host data
                if (empty($hosts[$hostname])) {
                    continue;
                }
                $point = array_merge(
                        array(
                    "coordinates" => $coordinates,
//                    "services" => $this->hostServiceData($hostname)
                    "services" => array()
                        ), $hosts[$hostname]
                );
                $points[$hostname] = $point;
            }
        }
        echo json_encode($points);
        exit;
    }

Thank you for you fast respond!

nbuchwitz commented 7 years ago

Just pushed a improved version of the data controller with massive speed improvements. I tested with about 3k hosts and everything went smoth. Happy to hear if it works for your environment.

GrexAut commented 7 years ago

Hello,

your improved version shows only hosts with services configured/applied, hosts without services are not showing on the map.

nbuchwitz commented 7 years ago

Should be reverted in current HEAD

GrexAut commented 7 years ago

@nbuchwitz nice! - Working perfectly. From 15s to 1.5s with services. Thank you for fixing so fast!