Hi,

I'd like to share a patch to provide JSON data from monit. It is based on the 
patch against 5.0beta7 from Paul, send previously to this mailing list.

http://www.mail-archive.com/monit-dev@nongnu.org/msg01156.html

It is updated with some of the information that was added to the XML output in 
later versions.

Attached are 2 files, one is the patch against 5.2.3 we are using at Fifthplay. 
It is thoroughly tested. The second is the patch ported to current SVN revision 
365. Both pass JSON validation (yajl).

Best regards,
Sven Möllers

PS: I am sorry in case i double-post, I sent the mail previously but was not 
subscribed with this address and it appears it did not get through.
Disclaimer

This e-mail and its attachments is intended only for the person(s) or entity to 
which it is addressed. If you receive this e-mail by mistake, please delete 
this e-mail from your system and destroy all copies of it. It may contain 
confidential and/or privileged information. You should not copy it or use it 
for any purpose nor disclose its contents to any person unless allowed by a 
written document between the sender and the addressee.
diff --git a/http/cervlet.c b/http/cervlet.c
index 6ebd985..09599fd 100644
--- a/http/cervlet.c
+++ b/http/cervlet.c
@@ -2281,6 +2281,13 @@ static void print_status(HttpRequest req, HttpResponse res, int version)
     FREE(D);
     set_content_type(res, "text/xml");
   }
+  else if(stringFormat && Util_startsWith(stringFormat, "json"))
+  {
+    char *D = status_json(NULL, level);
+    out_print(res, "%s", D);
+    FREE(D);
+    set_content_type(res, "application/json");
+  }
   else
   {
     char *uptime = Util_getUptime(Util_getProcessUptime(Run.pidfile), " ");
diff --git a/json.c b/json.c
new file mode 100644
index 0000000..c94d0a9
--- /dev/null
+++ b/json.c
@@ -0,0 +1,435 @@
+/*
+ * Copyright (C) 2009 Tildeslash Ltd. All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ *
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+
+
+#include <config.h>
+
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "monitor.h"
+#include "event.h"
+#include "process.h"
+
+
+/**
+ *  JSON routines for status and event notification message handling.
+ *
+ *  @author Martin Pala, <mart...@tildeslash.com>
+ *
+ *  @file
+ */
+
+
+
+/* -------------------------------------------------------------- Prototypes */
+
+
+static void document_head(Buffer_T *);
+static void document_foot(Buffer_T *);
+static void status_service(Service_T, Buffer_T *, short);
+static void status_servicegroup(ServiceGroup_T, Buffer_T *, short);
+static void status_event(Event_T, Buffer_T *);
+
+
+/* ------------------------------------------------------------------ Public */
+
+
+/**
+ * Return JSON formated message for event notification or general status
+ * of monitored services and resources.
+ * @param E An event object or NULL for general status
+ * @param L Status information level
+ * @return JSON document or NULL in the case of error. The caller must free
+*  the memory.
+ */
+char *status_json(Event_T E, short L) {
+
+  Buffer_T  B;
+  Service_T S;
+  ServiceGroup_T SG;
+
+  memset(&B, 0, sizeof(Buffer_T));
+
+  document_head(&B);
+
+  if(E)
+  {
+    /* there is no use for status level in the event (at least now) */
+    status_event(E, &B);
+  }
+  else
+  {
+    Util_stringbuffer(&B, ", \"services\":[ ");
+    for(S = servicelist_conf; S; S = S->next_conf)
+    {
+      status_service(S, &B, L);
+      S->next_conf ? Util_stringbuffer(&B, ", ") : Util_stringbuffer(&B, " ");
+    }
+    Util_stringbuffer(&B, " ]");
+    Util_stringbuffer(&B, ", \"servicegroups\":[ ");
+    for(SG = servicegrouplist; SG; SG = SG->next)
+    {
+      status_servicegroup(SG, &B, L);
+      SG->next ? Util_stringbuffer(&B, ", ") : Util_stringbuffer(&B, " ");
+    }
+    Util_stringbuffer(&B, " ]");
+  }
+  document_foot(&B);
+
+  return B.buf;
+
+}
+
+
+/* ----------------------------------------------------------------- Private */
+
+
+/**
+ * Prints a document header into the given buffer.
+ * @param B Buffer object
+ */
+static void document_head(Buffer_T *B) {
+
+
+  Util_stringbuffer(B,
+    "{\"monit\": "
+    "{\"server\": {"
+    "\"id\":\"%s\", "
+    "\"incarnation\":%ld, "
+    "\"version\":\"%s\", "
+    "\"uptime\":%ld, "
+    "\"poll\":%d, "
+    "\"startdelay\":%d, "
+    "\"localhostname\":\"%s\", "
+    "\"controlfile\":\"%s\"",
+   Run.id,
+   Run.incarnation,
+   VERSION,
+   (long)Util_getProcessUptime(Run.pidfile),
+   Run.polltime,
+   Run.startdelay,
+   Run.localhostname ? Run.localhostname : "",
+   Run.controlfile ? Run.controlfile : "");
+
+  if(Run.dohttpd)
+  {
+    Util_stringbuffer(B,
+      ", \"httpd\": {"
+      "\"address\":\"%s\","
+      "\"port\":%d,"
+      "\"ssl\":%d }",
+      Run.bind_addr?Run.bind_addr:"",
+      Run.httpdport,
+      Run.httpdssl);
+
+    if (Run.mmonitcredentials)
+        Util_stringbuffer(B,
+          ", \"credentials\": {"
+          "\"username\": \"%s\","
+          "\"password\": \"%s\""
+          "}",
+          Run.mmonitcredentials->uname,
+          Run.mmonitcredentials->passwd);
+
+  }
+
+  Util_stringbuffer(B,
+   "},"
+   "\"platform\": {"
+   "\"name\":\"%s\", \"release\":\"%s\", \"version\":\"%s\","
+   "\"machine\":\"%s\", \"cpu\":%d, \"memory\":%lu, \"swap\":%lu"
+   " }",
+   systeminfo.uname.sysname,
+   systeminfo.uname.release,
+   systeminfo.uname.version,
+   systeminfo.uname.machine,
+   systeminfo.cpus,
+   systeminfo.mem_kbyte_max,
+   systeminfo.swap_kbyte_max);
+
+}
+
+
+/**
+ * Prints a document footer into the given buffer.
+ * @param B Buffer object
+ */
+static void document_foot(Buffer_T *B) {
+
+  Util_stringbuffer(B, "}}"); //closing monit
+
+}
+
+
+/**
+ * Prints a service status into the given buffer.
+ * @param S Service object
+ * @param B Buffer object
+ * @param L Status information level
+ */
+static void status_service(Service_T S, Buffer_T *B, short L) {
+  Event_T E = S->eventlist;
+  Util_stringbuffer(B,
+        "{"
+        "\"type\":%d, \"collected_sec\":%ld, "
+        "\"collected_usec\":%ld, \"name\":\"%s\", \"status\":%d, \"status_hint\":%d, "
+        "\"monitor\":%d, \"monitormode\":%d, \"pendingaction\":%d",
+           S->type,
+           S->collected.tv_sec,
+           S->collected.tv_usec,
+           S->name?S->name:"",
+           S->error,
+           S->error_hint,
+           S->monitor,
+           S->mode,
+           S->doaction);
+  /* if the service is in error state, display first active error message to provide more details */
+  while (E) {
+    if (E->state == STATE_FAILED && (S->error & E->id) && E->message) {
+       Util_stringbuffer(B, ", \"status_message\":\"%s\"", E->message);
+       break;
+    }
+    E = E->next;
+  }
+  if(L == LEVEL_FULL)
+  {
+    if(Util_hasServiceStatus(S)) {
+      if(S->type == TYPE_FILE ||
+         S->type == TYPE_DIRECTORY ||
+         S->type == TYPE_FIFO ||
+         S->type == TYPE_FILESYSTEM) {
+        Util_stringbuffer(B,
+        ", \"mode\":%o, \"uid\":%d, \"gid\":%d",
+               S->inf->st_mode & 07777,
+               (int)S->inf->st_uid,
+               (int)S->inf->st_gid);
+      }
+      if(S->type == TYPE_FILE ||
+         S->type == TYPE_FIFO ||
+         S->type == TYPE_DIRECTORY)  {
+        Util_stringbuffer(B,
+               ", \"timestamp\":%ld",
+               (long)S->inf->timestamp);
+      }
+      if(S->type == TYPE_FILE) {
+        Util_stringbuffer(B,
+               ", \"size\":%llu",
+               (unsigned long long) S->inf->st_size);
+        if(S->checksum) {
+          Util_stringbuffer(B,
+                 ", \"checksum\": {\"type\": \"%s\", \"sum\":\"%s\" }",
+                 checksumnames[S->checksum->type], S->inf->cs_sum);
+        }
+      }
+      if(S->type == TYPE_FILESYSTEM) {
+        Util_stringbuffer(B,
+        ", \"flags\":%ld, "
+        "\"block\": { \"percent\":%.1f, \"usage\":\"%.1f MB\", "
+        "\"total\":\"%.1f MB\" }",
+               S->inf->flags,
+               S->inf->space_percent/10.,
+               (float)S->inf->space_total / (float)1048576 * (float)S->inf->f_bsize,
+                (float)S->inf->f_blocks / (float)1048576 * (float)S->inf->f_bsize);
+        if(S->inf->f_files > 0) {
+          Util_stringbuffer(B,
+          ", \"inode\": {"
+          "\"percent\":%.1f, \"usage\":%ld, "
+          "\"total\":%ld }",
+                 S->inf->inode_percent/10.,
+                 S->inf->inode_total,
+                  S->inf->f_files);
+        }
+      }
+      if(S->type == TYPE_PROCESS) {
+        Util_stringbuffer(B,
+        ", \"pid\":%d, \"ppid\":%d, \"uptime\":%ld",
+               S->inf->pid,
+               S->inf->ppid,
+               (long)S->inf->uptime);
+        if(Run.doprocess) {
+          Util_stringbuffer(B,
+          ", \"children\":%d, "
+          "\"memory\": {"
+          "\"percent\":%.1f, \"percenttotal\":%.1f, "
+          "\"kilobyte\":%ld, \"kilobytetotal\":%ld }, "
+          "\"cpu\": {\"percent\":%.1f, \"percenttotal\":%.1f }",
+                 S->inf->children,
+                 S->inf->mem_percent/10.0,
+                 S->inf->total_mem_percent/10.0,
+                 S->inf->mem_kbyte,
+                 S->inf->total_mem_kbyte,
+                 S->inf->cpu_percent/10.0,
+                 S->inf->total_cpu_percent/10.0);
+        }
+      }
+      if(S->type == TYPE_HOST && S->icmplist) {
+        Icmp_T i;
+        Util_stringbuffer(B, ", \"icmps\": [");
+        for(i= S->icmplist; i; i= i->next) {
+          Util_stringbuffer(B,
+          " { \"type\":\"%s\", \"responsetime\":%.3f }%s",
+                 icmpnames[i->type],
+                 i->is_available?i->response:-1.,
+          i->next?", ":" ");
+        }
+        Util_stringbuffer(B, "]");
+      }
+      if((S->type == TYPE_HOST || S->type == TYPE_PROCESS) && S-> portlist) {
+        Port_T p;
+        Util_stringbuffer(B, ", \"ports\": [");
+        for(p= S->portlist; p; p= p->next) {
+          if(p->family == AF_INET) {
+            Util_stringbuffer(B,
+            " { \"family\": \"inet\", \"protocol\":\"%s\", "
+            "\"hostname\":\"%s\", \"portnumber\":%d, \"request\":\"%s\", "
+            " \"type\":\"%s\", \"responsetime\":%.3f }%s",
+                   p->protocol->name?p->protocol->name:"",
+                   p->hostname?p->hostname:"",
+                   p->port,
+                   p->request?p->request:"",
+                   Util_portTypeDescription(p),
+                   p->is_available?p->response:-1.,
+            p->next?", ":" ");
+
+          } else if(p->family == AF_UNIX) {
+            Util_stringbuffer(B,
+            " { \"family\": \"unix\", \"protocol\":\"%s\",  "
+            "\"path\":\"%s\", \"responsetime\":%.3f }%s",
+                   p->protocol->name?p->protocol->name:"",
+                   p->pathname?p->pathname:"",
+                   p->is_available?p->response:-1.,
+            p->next?", ":" ");
+          }
+        }
+        Util_stringbuffer(B, "]");
+      }
+      if(S->type == TYPE_SYSTEM && Run.doprocess) {
+        Util_stringbuffer(B,
+            ", \"system\": {"
+            "\"load\": { \"avg01\":%.2f, \"avg05\":%.2f, "
+            "\"avg15\":%.2f }, "
+            "\"cpu\": { \"user\":%.1f, \"system\":%.1f"
+#ifdef HAVE_CPU_WAIT
+            ", \"wait\":%.1f"
+#endif
+            "}, \"memory\": {"
+            "\"percent\":%.1f, \"kilobyte\":%.ld }}",
+            systeminfo.loadavg[0],
+            systeminfo.loadavg[1],
+            systeminfo.loadavg[2],
+            systeminfo.total_cpu_user_percent/10.,
+            systeminfo.total_cpu_syst_percent/10.,
+            #ifdef HAVE_CPU_WAIT
+            systeminfo.total_cpu_wait_percent/10.,
+            #endif
+            systeminfo.total_mem_percent/10.,
+            systeminfo.total_mem_kbyte);
+      }
+    }
+  }
+  Util_stringbuffer(B, "}"); //closing service
+}
+
+/**
+ * Prints a servicegroups into the given buffer.
+ * @param SG ServiceGroup object
+ * @param B Buffer object
+ * @param L Status information level
+ */
+static void status_servicegroup(ServiceGroup_T SG, Buffer_T *B, short L) {
+  ServiceGroupMember_T SGM;
+
+  Util_stringbuffer(B, 
+    "{ \"name\": \"%s\", "
+      "\"services\": [ ",
+    SG->name);
+  for (SGM = SG->members; SGM; SGM = SGM->next) {
+    Util_stringbuffer(B, "\"%s\"", SGM->name);
+    Util_stringbuffer(B, SGM->next ? ", ": " ");
+  }
+  Util_stringbuffer(B, "]}");
+}
+
+
+/**
+ * Prints a event description into the given buffer.
+ * @param E Event object
+ * @param B Buffer object
+ */
+static void status_event(Event_T E, Buffer_T *B) {
+
+  Service_T s;
+  struct timeval *tv;
+
+  ASSERT(E);
+
+  if(!(s = Event_get_source(E)))
+    return;
+
+  tv = Event_get_collected(E);
+
+  Util_stringbuffer(B,
+    "{"
+    "\"collected_sec\":%ld, \"collected_usec\":%ld, "
+    "\"service\":\"%s\", \"type\":%d, \"id\":%d, "
+    "\"state\":%d, \"action\":%d, \"message\":\"%s\"",
+    tv->tv_sec,
+    tv->tv_usec,
+    Event_get_source_name(E),
+    Event_get_source_type(E),
+    Event_get_id(E),
+    Event_get_state(E),
+    Event_get_action(E),
+    Event_get_message(E));
+  if (s->token) {
+    Util_stringbuffer(B,
+      ", \"token\":\"%s\"",
+      s->token);
+  }
+  Util_stringbuffer(B,
+    "}");
+}
diff --git a/monitor.h b/monitor.h
index 87f9e28..2ccd9c1 100644
--- a/monitor.h
+++ b/monitor.h
@@ -967,6 +967,7 @@ void reset_procinfo(Service_T);
 int  check_service_status(Service_T);
 void printhash(char *);  
 char *status_xml(Event_T, short, int);
+char *status_json(Event_T, short);
 int  handle_mmonit(Event_T);
 int  do_wakeupcall();
 
diff --git a/http/cervlet.c b/http/cervlet.c
index 4309c84..ea96516 100644
--- a/http/cervlet.c
+++ b/http/cervlet.c
@@ -2274,6 +2274,13 @@ static void print_status(HttpRequest req, HttpResponse res, int version)
     FREE(D);
     set_content_type(res, "text/xml");
   }
+  else if(stringFormat && Util_startsWith(stringFormat, "json"))
+  {
+    char *D = status_json(NULL, level);
+    out_print(res, "%s", D);
+    FREE(D);
+    set_content_type(res, "application/json");
+  }
   else
   {
     char *uptime = Util_getUptime(Util_getProcessUptime(Run.pidfile), " ");
diff --git a/json.c b/json.c
new file mode 100644
index 0000000..ce75254
--- /dev/null
+++ b/json.c
@@ -0,0 +1,435 @@
+/*
+ * Copyright (C) 2009 Tildeslash Ltd. All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ *
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+
+
+#include <config.h>
+
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "monitor.h"
+#include "event.h"
+#include "process.h"
+
+
+/**
+ *  JSON routines for status and event notification message handling.
+ *
+ *  @author Martin Pala, <mart...@tildeslash.com>
+ *
+ *  @file
+ */
+
+
+
+/* -------------------------------------------------------------- Prototypes */
+
+
+static void document_head(Buffer_T *);
+static void document_foot(Buffer_T *);
+static void status_service(Service_T, Buffer_T *, short);
+static void status_servicegroup(ServiceGroup_T, Buffer_T *, short);
+static void status_event(Event_T, Buffer_T *);
+
+
+/* ------------------------------------------------------------------ Public */
+
+
+/**
+ * Return JSON formated message for event notification or general status
+ * of monitored services and resources.
+ * @param E An event object or NULL for general status
+ * @param L Status information level
+ * @return JSON document or NULL in the case of error. The caller must free
+*  the memory.
+ */
+char *status_json(Event_T E, short L) {
+
+  Buffer_T  B;
+  Service_T S;
+  ServiceGroup_T SG;
+
+  memset(&B, 0, sizeof(Buffer_T));
+
+  document_head(&B);
+
+  if(E)
+  {
+    /* there is no use for status level in the event (at least now) */
+    status_event(E, &B);
+  }
+  else
+  {
+    Util_stringbuffer(&B, ", \"services\":[ ");
+    for(S = servicelist_conf; S; S = S->next_conf)
+    {
+      status_service(S, &B, L);
+      S->next_conf ? Util_stringbuffer(&B, ", ") : Util_stringbuffer(&B, " ");
+    }
+    Util_stringbuffer(&B, " ]");
+    Util_stringbuffer(&B, ", \"servicegroups\":[ ");
+    for(SG = servicegrouplist; SG; SG = SG->next)
+    {
+      status_servicegroup(SG, &B, L);
+      SG->next ? Util_stringbuffer(&B, ", ") : Util_stringbuffer(&B, " ");
+    }
+    Util_stringbuffer(&B, " ]");
+  }
+  document_foot(&B);
+
+  return B.buf;
+
+}
+
+
+/* ----------------------------------------------------------------- Private */
+
+
+/**
+ * Prints a document header into the given buffer.
+ * @param B Buffer object
+ */
+static void document_head(Buffer_T *B) {
+
+
+  Util_stringbuffer(B,
+    "{\"monit\": "
+    "{\"server\": {"
+    "\"id\":\"%s\", "
+    "\"incarnation\":%ld, "
+    "\"version\":\"%s\", "
+    "\"uptime\":%ld, "
+    "\"poll\":%d, "
+    "\"startdelay\":%d, "
+    "\"localhostname\":\"%s\", "
+    "\"controlfile\":\"%s\"",
+   Run.id,
+   Run.incarnation,
+   VERSION,
+   (long)Util_getProcessUptime(Run.pidfile),
+   Run.polltime,
+   Run.startdelay,
+   Run.localhostname ? Run.localhostname : "",
+   Run.controlfile ? Run.controlfile : "");
+
+  if(Run.dohttpd)
+  {
+    Util_stringbuffer(B,
+      ", \"httpd\": {"
+      "\"address\":\"%s\","
+      "\"port\":%d,"
+      "\"ssl\":%d }",
+      Run.bind_addr?Run.bind_addr:"",
+      Run.httpdport,
+      Run.httpdssl);
+
+    if (Run.mmonitcredentials)
+        Util_stringbuffer(B,
+          ", \"credentials\": {"
+          "\"username\": \"%s\","
+          "\"password\": \"%s\""
+          "}",
+          Run.mmonitcredentials->uname,
+          Run.mmonitcredentials->passwd);
+
+  }
+
+  Util_stringbuffer(B,
+   "},"
+   "\"platform\": {"
+   "\"name\":\"%s\", \"release\":\"%s\", \"version\":\"%s\","
+   "\"machine\":\"%s\", \"cpu\":%d, \"memory\":%lu, \"swap\":%lu"
+   " }",
+   systeminfo.uname.sysname,
+   systeminfo.uname.release,
+   systeminfo.uname.version,
+   systeminfo.uname.machine,
+   systeminfo.cpus,
+   systeminfo.mem_kbyte_max,
+   systeminfo.swap_kbyte_max);
+
+}
+
+
+/**
+ * Prints a document footer into the given buffer.
+ * @param B Buffer object
+ */
+static void document_foot(Buffer_T *B) {
+
+  Util_stringbuffer(B, "}}"); //closing monit
+
+}
+
+
+/**
+ * Prints a service status into the given buffer.
+ * @param S Service object
+ * @param B Buffer object
+ * @param L Status information level
+ */
+static void status_service(Service_T S, Buffer_T *B, short L) {
+  Event_T E = S->eventlist;
+  Util_stringbuffer(B,
+        "{"
+        "\"type\":%d, \"collected_sec\":%ld, "
+        "\"collected_usec\":%ld, \"name\":\"%s\", \"status\":%d, \"status_hint\":%d, "
+        "\"monitor\":%d, \"monitormode\":%d, \"pendingaction\":%d",
+           S->type,
+           S->collected.tv_sec,
+           S->collected.tv_usec,
+           S->name?S->name:"",
+           S->error,
+           S->error_hint,
+           S->monitor,
+           S->mode,
+           S->doaction);
+  /* if the service is in error state, display first active error message to provide more details */
+  while (E) {
+    if (E->state == STATE_FAILED && (S->error & E->id) && E->message) {
+       Util_stringbuffer(B, ", \"status_message\":\"%s\"", E->message);
+       break;
+    }
+    E = E->next;
+  }
+  if(L == LEVEL_FULL)
+  {
+    if(Util_hasServiceStatus(S)) {
+      if(S->type == TYPE_FILE ||
+         S->type == TYPE_DIRECTORY ||
+         S->type == TYPE_FIFO ||
+         S->type == TYPE_FILESYSTEM) {
+        Util_stringbuffer(B,
+        ", \"mode\":%o, \"uid\":%d, \"gid\":%d",
+               S->inf->st_mode & 07777,
+               (int)S->inf->st_uid,
+               (int)S->inf->st_gid);
+      }
+      if(S->type == TYPE_FILE ||
+         S->type == TYPE_FIFO ||
+         S->type == TYPE_DIRECTORY)  {
+        Util_stringbuffer(B,
+               ", \"timestamp\":%ld",
+               (long)S->inf->timestamp);
+      }
+      if(S->type == TYPE_FILE) {
+        Util_stringbuffer(B,
+               ", \"size\":%llu",
+               (unsigned long long) S->inf->priv.file.st_size);
+        if(S->checksum) {
+          Util_stringbuffer(B,
+                 ", \"checksum\": {\"type\": \"%s\", \"sum\":\"%s\" }",
+                 checksumnames[S->checksum->type], S->inf->priv.file.cs_sum);
+        }
+      }
+      if(S->type == TYPE_FILESYSTEM) {
+        Util_stringbuffer(B,
+        ", \"flags\":%ld, "
+        "\"block\": { \"percent\":%.1f, \"usage\":\"%.1f MB\", "
+        "\"total\":\"%.1f MB\" }",
+               S->inf->priv.filesystem.flags,
+               S->inf->priv.filesystem.space_percent/10.,
+               (float)S->inf->priv.filesystem.space_total / (float)1048576 * (float)S->inf->priv.filesystem.f_bsize,
+                (float)S->inf->priv.filesystem.f_blocks / (float)1048576 * (float)S->inf->priv.filesystem.f_bsize);
+        if(S->inf->priv.filesystem.f_files > 0) {
+          Util_stringbuffer(B,
+          ", \"inode:\": {"
+          "\"percent\":%.1f, \"usage\":%ld, "
+          "\"total\":%ld }",
+                 S->inf->priv.filesystem.inode_percent/10.,
+                 S->inf->priv.filesystem.inode_total,
+                  S->inf->priv.filesystem.f_files);
+        }
+      }
+      if(S->type == TYPE_PROCESS) {
+        Util_stringbuffer(B,
+        ", \"pid\":%d, \"ppid\":%d, \"uptime\":%ld",
+               S->inf->priv.process.pid,
+               S->inf->priv.process.ppid,
+               (long)S->inf->priv.process.uptime);
+        if(Run.doprocess) {
+          Util_stringbuffer(B,
+          ", \"children\":%d, "
+          "\"memory\": {"
+          "\"percent\":%.1f, \"percenttotal\":%.1f, "
+          "\"kilobyte\":%ld, \"kilobytetotal\":%ld }, "
+          "\"cpu\": {\"percent\":%.1f, \"percenttotal\":%.1f }",
+                 S->inf->priv.process.children,
+                 S->inf->priv.process.mem_percent/10.0,
+                 S->inf->priv.process.total_mem_percent/10.0,
+                 S->inf->priv.process.mem_kbyte,
+                 S->inf->priv.process.total_mem_kbyte,
+                 S->inf->priv.process.cpu_percent/10.0,
+                 S->inf->priv.process.total_cpu_percent/10.0);
+        }
+      }
+      if(S->type == TYPE_HOST && S->icmplist) {
+        Icmp_T i;
+        Util_stringbuffer(B, ", \"icmps\": [");
+        for(i= S->icmplist; i; i= i->next) {
+          Util_stringbuffer(B,
+          " { \"type\":\"%s\", \"responsetime\":%.3f }%s",
+                 icmpnames[i->type],
+                 i->is_available?i->response:-1.,
+          i->next?", ":" ");
+        }
+        Util_stringbuffer(B, "]");
+      }
+      if((S->type == TYPE_HOST || S->type == TYPE_PROCESS) && S-> portlist) {
+        Port_T p;
+        Util_stringbuffer(B, ", \"ports\": [");
+        for(p= S->portlist; p; p= p->next) {
+          if(p->family == AF_INET) {
+            Util_stringbuffer(B,
+            " { \"family\": \"inet\", \"protocol\":\"%s\", "
+            "\"hostname\":\"%s\", \"portnumber\":%d, \"request\":\"%s\", "
+            " \"type\":\"%s\", \"responsetime\":%.3f }%s",
+                   p->protocol->name?p->protocol->name:"",
+                   p->hostname?p->hostname:"",
+                   p->port,
+                   p->request?p->request:"",
+                   Util_portTypeDescription(p),
+                   p->is_available?p->response:-1.,
+            p->next?", ":" ");
+
+          } else if(p->family == AF_UNIX) {
+            Util_stringbuffer(B,
+            " { \"family\": \"unix\", \"protocol\":\"%s\",  "
+            "\"path\":\"%s\", \"responsetime\":%.3f }%s",
+                   p->protocol->name?p->protocol->name:"",
+                   p->pathname?p->pathname:"",
+                   p->is_available?p->response:-1.,
+            p->next?", ":" ");
+          }
+        }
+        Util_stringbuffer(B, "]");
+      }
+      if(S->type == TYPE_SYSTEM && Run.doprocess) {
+        Util_stringbuffer(B,
+            ", \"system\": {"
+            "\"load\": { \"avg01\":%.2f, \"avg05\":%.2f, "
+            "\"avg15\":%.2f }, "
+            "\"cpu\": { \"user\":%.1f, \"system\":%.1f"
+#ifdef HAVE_CPU_WAIT
+            ", \"wait\":%.1f"
+#endif
+            "}, \"memory\": {"
+            "\"percent\":%.1f, \"kilobyte\":%.ld }}",
+            systeminfo.loadavg[0],
+            systeminfo.loadavg[1],
+            systeminfo.loadavg[2],
+            systeminfo.total_cpu_user_percent/10.,
+            systeminfo.total_cpu_syst_percent/10.,
+            #ifdef HAVE_CPU_WAIT
+            systeminfo.total_cpu_wait_percent/10.,
+            #endif
+            systeminfo.total_mem_percent/10.,
+            systeminfo.total_mem_kbyte);
+      }
+    }
+  }
+  Util_stringbuffer(B, "}"); //closing service
+}
+
+/**
+ * Prints a servicegroups into the given buffer.
+ * @param SG ServiceGroup object
+ * @param B Buffer object
+ * @param L Status information level
+ */
+static void status_servicegroup(ServiceGroup_T SG, Buffer_T *B, short L) {
+  ServiceGroupMember_T SGM;
+
+  Util_stringbuffer(B,
+    "{ \"name\": \"%s\", "
+      "\"services\": [ ",
+    SG->name);
+  for (SGM = SG->members; SGM; SGM = SGM->next) {
+    Util_stringbuffer(B, "\"%s\"", SGM->name);
+    Util_stringbuffer(B, SGM->next ? ", ": " ");
+  }
+  Util_stringbuffer(B, "]}");
+}
+
+
+/**
+ * Prints a event description into the given buffer.
+ * @param E Event object
+ * @param B Buffer object
+ */
+static void status_event(Event_T E, Buffer_T *B) {
+
+  Service_T s;
+  struct timeval *tv;
+
+  ASSERT(E);
+
+  if(!(s = Event_get_source(E)))
+    return;
+
+  tv = Event_get_collected(E);
+
+  Util_stringbuffer(B,
+    "{"
+    "\"collected_sec\":%ld, \"collected_usec\":%ld, "
+    "\"service\":\"%s\", \"type\":%d, \"id\":%d, "
+    "\"state\":%d, \"action\":%d, \"message\":\"%s\"",
+    tv->tv_sec,
+    tv->tv_usec,
+    Event_get_source_name(E),
+    Event_get_source_type(E),
+    Event_get_id(E),
+    Event_get_state(E),
+    Event_get_action(E),
+    Event_get_message(E));
+  if (s->token) {
+    Util_stringbuffer(B,
+      ", \"token\":\"%s\"",
+      s->token);
+  }
+  Util_stringbuffer(B,
+    "}");
+}
diff --git a/monitor.h b/monitor.h
index 117b0e5..c7e248b 100644
--- a/monitor.h
+++ b/monitor.h
@@ -970,6 +970,7 @@ void reset_procinfo(Service_T);
 int  check_service_status(Service_T);
 void printhash(char *);  
 char *status_xml(Event_T, short, int, const char *);
+char *status_json(Event_T, short);
 int  handle_mmonit(Event_T);
 int  do_wakeupcall();
 
_______________________________________________
monit-dev mailing list
monit-dev@nongnu.org
http://lists.nongnu.org/mailman/listinfo/monit-dev

Reply via email to