Category Archives: Zabbix

ExtJS/Zabbix Frontend

No updates for a while, mainly because I lost focus on that. The more I dug into the Zabbix API, the more horrible it was, and because PartKeepr currently takes most of my time, I decided to postpone the ExtJS/Zabbix Frontend. Sorry!

Developing a Zabbix ExtJS frontend: Part Two

After quite lots of work, I’ve now a basic editing workflow done. As I’m using RESTful methods (due to the lack of a JSON-RPC on ExtJS), I’ve written a proxy which eats RESTful methods on the ExtJS side and proxies that to JSON-RPC for Zabbix.

Honestly, this doesn’t sound pretty amazing, but was necessary to work around one limitation of the Zabbix API: Pagination. This is an emulated pagination, which processes a big result set coming from the Zabbix API, counts the records and then applies a simple array_chunk() on the result. That way, the amount of data transmitted to the client is kept at a minimum.

Regarding the amount of data transmitted: I don’t filter individual fields of each record, even if much space is wasted. This is for two reasons:

  • Performance. Even if I could remove 50% of the fields transmitted, the CPU time (and of course, development manpower) wasted would probably be more than simply transmitting the data to the client. Most Zabbix users are on corporate networks, and even people who are using Zabbix remotely often have DSL connections. Sorry for all GPRS users, but a Zabbix Sencha Touch Frontend is not even planned.
  • Object Model. As the ExtJS frontend is using models, I never know when I need which data. So it’s better to transmit all properties, which saves headaches.

That brings us to a new topic:

How to handle relations for reading and writing objects

When writing a PHP frontend, things are pretty easy: You can write very specific SQL queries, and if you are missing data, you can simply load it prior displaying the page.

When implementing remote frontends, things are a bit worse: Think of each SQL query as a request to the server. On a LAN connection, things aren’t that bad: On my development environment, queries take 20-100ms to complete, so users even won’t notice that something is being loaded. Things are different on remote connections; with requests taking an unpredictable amount of time, one wants to reduce requests to the server to an absolute minimum.

I’ll make an example using templates:¬†When I load a template, I simply request the linked templates, macros etc when loading the template. No problem here.

But the user will eventually come to a point where he needs to add additional templates or macros, which aren’t transmitted. I basically have two options here:

Keep a cache of templates on the client.

I’ve used that in the first place on PartKeepr, but with mediocre success. The advantage was that data was immediately available. The biggest disadvantage was when somebody else added something; that required the ExtJS store to load all entities in a timed interval. And often it was confusing because there was no indication when a reload appears.

This method could probably be improved by creating a checksum and only asking the server if the checksum was changed, so the client would know to reload the data. However, I don’t feel too comfortable with that approach, and lately I’m rewriting things on PartKeepr to avoid that.

Load templates on demand.

This could happen using a specific kind of drop down or even grids, complete with filtering and pagination. While this might create quite some requests on-demand, it works better than caching, because the current data is available and not a cached copy of it.

Conclusion

Data handling in the world of AJAX applications is not easy, especially if you write a full-blown AJAX frontend where you have no page reloading at all. You have to decide carefully which data with which relations you really need, and which data you better load on demand.

Developing a Zabbix ExtJS frontend: Part One

Richlv asked me to give feedback about my experiences on the Zabbix PHP code, and this is the first blog post in that series. This posting is not intented as a “rant” at all, but as feedback and discussion for the development of Zabbix.

Why another frontend isn’t needed, but most probably wanted

There is always a controversy if somebody comes up with a new idea. People argue that there’s no need for something new, but obviously they miss one point: The person who says: “I want something new” really wants something new.

The current frontend has some drawbacks. However, the main drawback is the navigation:

The workflow is sometimes very unhandy. You have to switch back and forth between menu items, and end up with many open tabs or windows to achieve a single task.

An example of this is when you create a new host and notice that you’d better put some items into a template. You would need to save the host and navigate to the templates, create a template, navigate to the items, create the items, the triggers and then get back to the host to apply the template.

The exact same issue occurs when you have an alert; you don’t have the item’s history graph at your fingertips (=one click and you see the related charts).

In theory, much usability could be added in the existing frontend, but this would need a huge effort, due to the old-style implementation of the frontend.

How can ExtJS help here?

ExtJS is a JavaScript frontend library which is implemented in an object-oriented way. This helps with code deduplication and enables developers to implement reusable components. I’ve had very good experiences while working on the PartKeepr project.

In fact, while working on PartKeepr, I enjoyed the complete separation of business logic (which goes onto the PHP side) and frontend (ExtJS side).

Now where are the problems?

There are quite a few. First of all, ExtJS doesn’t support JSON-RPC, while JSON-RPC is the only API Zabbix currently supports. I can’t really judge if JSON-RPC is common or not, but I do feel that a RESTful API is more common. I solved that by implementing a wrapper which takes RESTful requests on the one side and converts them into JSON-RPC and calls the Zabbix API from there.

Another issue is that Zabbix doesn’t really use normalized entities. There are many tables, which are re-used for different things (example: Hosts and Templates share the same table). Some fields are probably used for hosts and not for templates, and vice versa (I’m really not sure about this, I haven’t created an in-depth analysis so far). If normalized entities would exist, one could write entity classes based on that, which in turn could implement the serialize/deserialize methods. That would give the following benefits:

  • Implementing additional Web APIs is very easy, because the entities themselves handle their serializing/deserializing.
  • You could minimize the Web API call implementations to a minimum when using an ORM. Right now, each API call has 1000-2000 SLOCs and if there’s something which needs to be added, like pagination, you would need to touch every Web API call. In turn, when using an ORM and an OO model, you would only have to change a single base class to make that happen.
  • Duplicate business logic could be unified, where it doesn’t matter if the Web API or the native PHP frontend uses the entity API; the business logic would stay exactly the same.

There are probably more benefits, such as reduced code error rate and better unit testing.

Another issue is the database model: It is purely created by a set of different SQL scripts for each database type. Migrations from one version to another is achieved by running an update SQL script. There’s no real code which could aid with type migrations in order to create a normalized database model. Also, it seems that Zabbix is using inappropriate data types (e.g. using int(11) on MySQL for boolean instead of boolean and also int(11) for timestamps). Additionally, it is virtually impossible to know what each column in the database does.

Conclusion

Zabbix was first released in 2001. Since then, much has happened. However, the code could be improved in many many places; which is a virtually impossible task to achieve for a very specific version. As Zabbix is used by customers and Zabbix SIA creates revenue out of Zabbix, any code refactoring needs to be done very carefully.

As much as I’d love to create a fork and throw in modern technologies like Symfony2 and Doctrine2, this would not be practial. As the plans for Zabbix 2.0 are already settled and customers are still using PHP 5.2 due to RHEL5 and others; this is virtually a KO for Symfony2 and Doctrine2.

While implementing the ExtJS frontend, I try to give as much feedback and patches to the Zabbix Developers as I can. I am not sure if it is even possible what I have in my mind for an ExtJS frontend; however, I am sure that it can be done, even with many nasty workarounds.