2 * collectd - src/pyvalues.c
3 * Copyright (C) 2009 Sven Trenkel
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
24 * Sven Trenkel <collectd at semidefinite.de>
28 #include <structmember.h>
35 static char time_doc[] = "This is the Unix timestap of the time this value was read.\n"
36 "For dispatching values this can be set to 0 which means \"now\".\n"
37 "This means the time the value is actually dispatched, not the time\n"
40 static char host_doc[] = "The hostname of the host this value was read from.\n"
41 "For dispatching this can be set to an empty string which means\n"
42 "the local hostname as defined in the collectd.conf.";
44 static char type_doc[] = "The type of this value. This type has to be defined\n"
45 "in your types.db. Attempting to set it to any other value will\n"
46 "raise a TypeError exception.\n"
47 "Assigning a type is mandetory, calling dispatch without doing\n"
48 "so will raise a RuntimeError exception.";
50 static char type_instance_doc[] = "";
52 static char plugin_doc[] = "The name of the plugin that read the data. Setting this\n"
53 "member to an empty string will insert \"python\" upon dispatching.";
55 static char plugin_instance_doc[] = "";
57 static char PluginData_doc[] = "This is an internal class that is the base for Values\n"
58 "and Notification. It is pretty useless by itself and was therefore not\n"
59 "exported to the collectd module.";
61 static PyObject *PluginData_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
64 self = (PluginData *) type->tp_alloc(type, 0);
71 self->plugin_instance[0] = 0;
73 self->type_instance[0] = 0;
74 return (PyObject *) self;
77 static int PluginData_init(PyObject *s, PyObject *args, PyObject *kwds) {
78 PluginData *self = (PluginData *) s;
80 const char *type = "", *plugin_instance = "", *type_instance = "", *plugin = "", *host = "";
81 static char *kwlist[] = {"type", "plugin_instance", "type_instance",
82 "plugin", "host", "time", NULL};
84 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sssssd", kwlist, &type,
85 &plugin_instance, &type_instance, &plugin, &host, &time))
88 if (type[0] != 0 && plugin_get_ds(type) == NULL) {
89 PyErr_Format(PyExc_TypeError, "Dataset %s not found", type);
93 sstrncpy(self->host, host, sizeof(self->host));
94 sstrncpy(self->plugin, plugin, sizeof(self->plugin));
95 sstrncpy(self->plugin_instance, plugin_instance, sizeof(self->plugin_instance));
96 sstrncpy(self->type, type, sizeof(self->type));
97 sstrncpy(self->type_instance, type_instance, sizeof(self->type_instance));
103 static PyObject *PluginData_repr(PyObject *s) {
104 PluginData *self = (PluginData *) s;
106 return PyString_FromFormat("collectd.Values(type='%s%s%s%s%s%s%s%s%s',time=%lu)", self->type,
107 *self->type_instance ? "',type_instance='" : "", self->type_instance,
108 *self->plugin ? "',plugin='" : "", self->plugin,
109 *self->plugin_instance ? "',plugin_instance='" : "", self->plugin_instance,
110 *self->host ? "',host='" : "", self->host,
111 (long unsigned) self->time);
114 static PyMemberDef PluginData_members[] = {
115 {"time", T_DOUBLE, offsetof(PluginData, time), 0, time_doc},
119 static PyObject *PluginData_getstring(PyObject *self, void *data) {
120 const char *value = ((char *) self) + (intptr_t) data;
122 return PyString_FromString(value);
125 static int PluginData_setstring(PyObject *self, PyObject *value, void *data) {
130 PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
133 new = PyString_AsString(value);
134 if (new == NULL) return -1;
135 old = ((char *) self) + (intptr_t) data;
136 sstrncpy(old, new, DATA_MAX_NAME_LEN);
140 static int PluginData_settype(PyObject *self, PyObject *value, void *data) {
145 PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
148 new = PyString_AsString(value);
149 if (new == NULL) return -1;
151 if (plugin_get_ds(new) == NULL) {
152 PyErr_Format(PyExc_TypeError, "Dataset %s not found", new);
156 old = ((char *) self) + (intptr_t) data;
157 sstrncpy(old, new, DATA_MAX_NAME_LEN);
161 static PyGetSetDef PluginData_getseters[] = {
162 {"host", PluginData_getstring, PluginData_setstring, host_doc, (void *) offsetof(PluginData, host)},
163 {"plugin", PluginData_getstring, PluginData_setstring, plugin_doc, (void *) offsetof(PluginData, plugin)},
164 {"plugin_instance", PluginData_getstring, PluginData_setstring, plugin_instance_doc, (void *) offsetof(PluginData, plugin_instance)},
165 {"type_instance", PluginData_getstring, PluginData_setstring, type_instance_doc, (void *) offsetof(PluginData, type_instance)},
166 {"type", PluginData_getstring, PluginData_settype, type_doc, (void *) offsetof(PluginData, type)},
170 PyTypeObject PluginDataType = {
171 PyObject_HEAD_INIT(NULL)
173 "collectd.PluginData", /* tp_name */
174 sizeof(PluginData), /* tp_basicsize */
175 0, /* Will be filled in later */
181 PluginData_repr, /* tp_repr */
182 0, /* tp_as_number */
183 0, /* tp_as_sequence */
184 0, /* tp_as_mapping */
190 0, /* tp_as_buffer */
191 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE /*| Py_TPFLAGS_HAVE_GC*/, /*tp_flags*/
192 PluginData_doc, /* tp_doc */
195 0, /* tp_richcompare */
196 0, /* tp_weaklistoffset */
200 PluginData_members, /* tp_members */
201 PluginData_getseters, /* tp_getset */
204 0, /* tp_descr_get */
205 0, /* tp_descr_set */
206 0, /* tp_dictoffset */
207 PluginData_init, /* tp_init */
209 PluginData_new /* tp_new */
212 static char interval_doc[] = "The interval is the timespan in seconds between two submits for\n"
213 "the same data source. This value has to be a positive integer, so you can't\n"
214 "submit more than one value per second. If this member is set to a\n"
215 "non-positive value, the default value as specified in the config file will\n"
216 "be used (default: 10).\n"
218 "If you submit values more often than the specified interval, the average\n"
219 "will be used. If you submit less values, your graphs will have gaps.";
221 static char values_doc[] = "These are the actual values that get dispatched to collectd.\n"
222 "It has to be a sequence (a tuple or list) of numbers.\n"
223 "The size of the sequence and the type of its content depend on the type\n"
224 "member your types.db file. For more information on this read the types.db\n"
227 "If the sequence does not have the correct size upon dispatch a RuntimeError\n"
228 "exception will be raised. If the content of the sequence is not a number,\n"
229 "a TypeError exception will be raised.";
231 static char dispatch_doc[] = "dispatch([type][, values][, plugin_instance][, type_instance]"
232 "[, plugin][, host][, time][, interval]) -> None. Dispatch a value list.\n"
234 "Dispatch this instance to the collectd process. The object has members\n"
235 "for each of the possible arguments for this method. For a detailed explanation\n"
236 "of these parameters see the member of the same same.\n"
238 "If you do not submit a parameter the value saved in its member will be submitted.\n"
239 "If you do provide a parameter it will be used instead, without altering the member.";
241 static char write_doc[] = "write([destination][, type][, values][, plugin_instance][, type_instance]"
242 "[, plugin][, host][, time][, interval]) -> None. Dispatch a value list.\n"
244 "Write this instance to a single plugin or all plugins if 'destination' is obmitted.\n"
245 "This will bypass the main collectd process and all filtering and caching.\n"
246 "Other than that it works similar to 'dispatch'. In most cases 'dispatch' should be\n"
247 "used instead of 'write'.\n";
249 static char Values_doc[] = "A Values object used for dispatching values to collectd and receiving values from write callbacks.";
251 static PyObject *Values_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
254 self = (Values *) PluginData_new(type, args, kwds);
258 self->values = PyList_New(0);
260 return (PyObject *) self;
263 static int Values_init(PyObject *s, PyObject *args, PyObject *kwds) {
264 Values *self = (Values *) s;
265 int interval = 0, ret;
267 PyObject *values = NULL, *tmp;
268 const char *type = "", *plugin_instance = "", *type_instance = "", *plugin = "", *host = "";
269 static char *kwlist[] = {"type", "values", "plugin_instance", "type_instance",
270 "plugin", "host", "time", "interval", NULL};
272 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sOssssdi", kwlist,
273 &type, &values, &plugin_instance, &type_instance,
274 &plugin, &host, &time, &interval))
277 tmp = Py_BuildValue("sssssd", type, plugin_instance, type_instance, plugin, host, time);
280 ret = PluginDataType.tp_init(s, tmp, NULL);
285 if (values == NULL) {
286 values = PyList_New(0);
293 self->values = values;
296 self->interval = interval;
300 static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
302 const data_set_t *ds;
305 value_list_t value_list = VALUE_LIST_INIT;
306 PyObject *values = self->values;
307 double time = self->data.time;
308 int interval = self->interval;
309 const char *host = self->data.host;
310 const char *plugin = self->data.plugin;
311 const char *plugin_instance = self->data.plugin_instance;
312 const char *type = self->data.type;
313 const char *type_instance = self->data.type_instance;
315 static char *kwlist[] = {"type", "values", "plugin_instance", "type_instance",
316 "plugin", "host", "time", "interval", NULL};
317 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sOssssdi", kwlist,
318 &type, &values, &plugin_instance, &type_instance,
319 &plugin, &host, &time, &interval))
323 PyErr_SetString(PyExc_RuntimeError, "type not set");
326 ds = plugin_get_ds(type);
328 PyErr_Format(PyExc_TypeError, "Dataset %s not found", type);
331 if (values == NULL || (PyTuple_Check(values) == 0 && PyList_Check(values) == 0)) {
332 PyErr_Format(PyExc_TypeError, "values must be list or tuple");
335 size = (int) PySequence_Length(values);
336 if (size != ds->ds_num) {
337 PyErr_Format(PyExc_RuntimeError, "type %s needs %d values, got %i", type, ds->ds_num, size);
340 value = malloc(size * sizeof(*value));
341 for (i = 0; i < size; ++i) {
342 PyObject *item, *num;
343 item = PySequence_GetItem(values, i);
344 if (ds->ds->type == DS_TYPE_COUNTER) {
345 num = PyNumber_Long(item);
347 value[i].counter = PyLong_AsUnsignedLongLong(num);
348 } else if (ds->ds->type == DS_TYPE_GAUGE) {
349 num = PyNumber_Float(item);
351 value[i].gauge = PyFloat_AsDouble(num);
352 } else if (ds->ds->type == DS_TYPE_DERIVE) {
353 /* This might overflow without raising an exception.
354 * Not much we can do about it */
355 num = PyNumber_Long(item);
357 value[i].derive = PyLong_AsLongLong(num);
358 } else if (ds->ds->type == DS_TYPE_ABSOLUTE) {
359 /* This might overflow without raising an exception.
360 * Not much we can do about it */
361 num = PyNumber_Long(item);
363 value[i].absolute = PyLong_AsUnsignedLongLong(num);
366 PyErr_Format(PyExc_RuntimeError, "unknown data type %d for %s", ds->ds->type, type);
369 if (PyErr_Occurred() != NULL) {
374 value_list.values = value;
375 value_list.values_len = size;
376 value_list.time = time;
377 value_list.interval = interval;
378 sstrncpy(value_list.host, host, sizeof(value_list.host));
379 sstrncpy(value_list.plugin, plugin, sizeof(value_list.plugin));
380 sstrncpy(value_list.plugin_instance, plugin_instance, sizeof(value_list.plugin_instance));
381 sstrncpy(value_list.type, type, sizeof(value_list.type));
382 sstrncpy(value_list.type_instance, type_instance, sizeof(value_list.type_instance));
383 value_list.meta = NULL;
384 if (value_list.host[0] == 0)
385 sstrncpy(value_list.host, hostname_g, sizeof(value_list.host));
386 if (value_list.plugin[0] == 0)
387 sstrncpy(value_list.plugin, "python", sizeof(value_list.plugin));
388 Py_BEGIN_ALLOW_THREADS;
389 ret = plugin_dispatch_values(&value_list);
390 Py_END_ALLOW_THREADS;
392 PyErr_SetString(PyExc_RuntimeError, "error dispatching values, read the logs");
399 static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
401 const data_set_t *ds;
404 value_list_t value_list = VALUE_LIST_INIT;
405 PyObject *values = self->values;
406 double time = self->data.time;
407 int interval = self->interval;
408 const char *host = self->data.host;
409 const char *plugin = self->data.plugin;
410 const char *plugin_instance = self->data.plugin_instance;
411 const char *type = self->data.type;
412 const char *type_instance = self->data.type_instance;
413 const char *dest = NULL;
415 static char *kwlist[] = {"destination", "type", "values", "plugin_instance", "type_instance",
416 "plugin", "host", "time", "interval", NULL};
417 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sOssssdi", kwlist,
418 &type, &values, &plugin_instance, &type_instance,
419 &plugin, &host, &time, &interval))
423 PyErr_SetString(PyExc_RuntimeError, "type not set");
426 ds = plugin_get_ds(type);
428 PyErr_Format(PyExc_TypeError, "Dataset %s not found", type);
431 if (values == NULL || (PyTuple_Check(values) == 0 && PyList_Check(values) == 0)) {
432 PyErr_Format(PyExc_TypeError, "values must be list or tuple");
435 size = (int) PySequence_Length(values);
436 if (size != ds->ds_num) {
437 PyErr_Format(PyExc_RuntimeError, "type %s needs %d values, got %i", type, ds->ds_num, size);
440 value = malloc(size * sizeof(*value));
441 for (i = 0; i < size; ++i) {
442 PyObject *item, *num;
443 item = PySequence_GetItem(values, i);
444 if (ds->ds->type == DS_TYPE_COUNTER) {
445 num = PyNumber_Long(item);
447 value[i].counter = PyLong_AsUnsignedLongLong(num);
448 } else if (ds->ds->type == DS_TYPE_GAUGE) {
449 num = PyNumber_Float(item);
451 value[i].gauge = PyFloat_AsDouble(num);
452 } else if (ds->ds->type == DS_TYPE_DERIVE) {
453 /* This might overflow without raising an exception.
454 * Not much we can do about it */
455 num = PyNumber_Long(item);
457 value[i].derive = PyLong_AsLongLong(num);
458 } else if (ds->ds->type == DS_TYPE_ABSOLUTE) {
459 /* This might overflow without raising an exception.
460 * Not much we can do about it */
461 num = PyNumber_Long(item);
463 value[i].absolute = PyLong_AsUnsignedLongLong(num);
466 PyErr_Format(PyExc_RuntimeError, "unknown data type %d for %s", ds->ds->type, type);
469 if (PyErr_Occurred() != NULL) {
474 value_list.values = value;
475 value_list.values_len = size;
476 value_list.time = time;
477 value_list.interval = interval;
478 sstrncpy(value_list.host, host, sizeof(value_list.host));
479 sstrncpy(value_list.plugin, plugin, sizeof(value_list.plugin));
480 sstrncpy(value_list.plugin_instance, plugin_instance, sizeof(value_list.plugin_instance));
481 sstrncpy(value_list.type, type, sizeof(value_list.type));
482 sstrncpy(value_list.type_instance, type_instance, sizeof(value_list.type_instance));
483 value_list.meta = NULL;
484 if (value_list.host[0] == 0)
485 sstrncpy(value_list.host, hostname_g, sizeof(value_list.host));
486 if (value_list.plugin[0] == 0)
487 sstrncpy(value_list.plugin, "python", sizeof(value_list.plugin));
488 Py_BEGIN_ALLOW_THREADS;
489 ret = plugin_write(dest, NULL, &value_list);
490 Py_END_ALLOW_THREADS;
492 PyErr_SetString(PyExc_RuntimeError, "error dispatching values, read the logs");
499 static PyObject *Values_repr(PyObject *s) {
500 PyObject *ret, *valuestring = NULL;
501 Values *self = (Values *) s;
503 if (self->values != NULL)
504 valuestring = PyObject_Repr(self->values);
505 if (valuestring == NULL)
508 ret = PyString_FromFormat("collectd.Values(type='%s%s%s%s%s%s%s%s%s',time=%lu,interval=%i,values=%s)", self->data.type,
509 *self->data.type_instance ? "',type_instance='" : "", self->data.type_instance,
510 *self->data.plugin ? "',plugin='" : "", self->data.plugin,
511 *self->data.plugin_instance ? "',plugin_instance='" : "", self->data.plugin_instance,
512 *self->data.host ? "',host='" : "", self->data.host,
513 (long unsigned) self->data.time, self->interval,
514 valuestring ? PyString_AsString(valuestring) : "[]");
515 Py_XDECREF(valuestring);
519 static int Values_traverse(PyObject *self, visitproc visit, void *arg) {
520 Values *v = (Values *) self;
525 static int Values_clear(PyObject *self) {
526 Values *v = (Values *) self;
531 static void Values_dealloc(PyObject *self) {
533 self->ob_type->tp_free(self);
536 static PyMemberDef Values_members[] = {
537 {"interval", T_INT, offsetof(Values, interval), 0, interval_doc},
538 {"values", T_OBJECT_EX, offsetof(Values, values), 0, values_doc},
542 static PyMethodDef Values_methods[] = {
543 {"dispatch", (PyCFunction) Values_dispatch, METH_VARARGS | METH_KEYWORDS, dispatch_doc},
544 {"write", (PyCFunction) Values_write, METH_VARARGS | METH_KEYWORDS, write_doc},
548 PyTypeObject ValuesType = {
549 PyObject_HEAD_INIT(NULL)
551 "collectd.Values", /* tp_name */
552 sizeof(Values), /* tp_basicsize */
553 0, /* Will be filled in later */
554 Values_dealloc, /* tp_dealloc */
559 Values_repr, /* tp_repr */
560 0, /* tp_as_number */
561 0, /* tp_as_sequence */
562 0, /* tp_as_mapping */
568 0, /* tp_as_buffer */
569 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
570 Values_doc, /* tp_doc */
571 Values_traverse, /* tp_traverse */
572 Values_clear, /* tp_clear */
573 0, /* tp_richcompare */
574 0, /* tp_weaklistoffset */
577 Values_methods, /* tp_methods */
578 Values_members, /* tp_members */
582 0, /* tp_descr_get */
583 0, /* tp_descr_set */
584 0, /* tp_dictoffset */
585 Values_init, /* tp_init */
587 Values_new /* tp_new */
590 static char severity_doc[] = "The severity of this notification. Assign or compare to\n"
591 "NOTIF_FAILURE, NOTIF_WARNING or NOTIF_OKAY.";
593 static char message_doc[] = "Some kind of description what's going on and why this Notification was generated.";
595 static char Notification_doc[] = "The Notification class is a wrapper around the collectd notification.\n"
596 "It can be used to notify other plugins about bad stuff happening. It works\n"
597 "similar to Values but has a severity and a message instead of interval\n"
599 "Notifications can be dispatched at any time and can be received with register_notification.";
601 static int Notification_init(PyObject *s, PyObject *args, PyObject *kwds) {
602 Notification *self = (Notification *) s;
604 int severity = 0, ret;
606 const char *message = "";
607 const char *type = "", *plugin_instance = "", *type_instance = "", *plugin = "", *host = "";
608 static char *kwlist[] = {"type", "message", "plugin_instance", "type_instance",
609 "plugin", "host", "time", "severity", NULL};
611 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ssssssdi", kwlist,
612 &type, &message, &plugin_instance, &type_instance,
613 &plugin, &host, &time, &severity))
616 tmp = Py_BuildValue("sssssd", type, plugin_instance, type_instance, plugin, host, time);
619 ret = PluginDataType.tp_init(s, tmp, NULL);
624 sstrncpy(self->message, message, sizeof(self->message));
625 self->severity = severity;
629 static PyObject *Notification_dispatch(Notification *self, PyObject *args, PyObject *kwds) {
631 const data_set_t *ds;
632 notification_t notification;
633 double t = self->data.time;
634 int severity = self->severity;
635 const char *host = self->data.host;
636 const char *plugin = self->data.plugin;
637 const char *plugin_instance = self->data.plugin_instance;
638 const char *type = self->data.type;
639 const char *type_instance = self->data.type_instance;
640 const char *message = self->message;
642 static char *kwlist[] = {"type", "message", "plugin_instance", "type_instance",
643 "plugin", "host", "time", "severity", NULL};
644 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ssssssdi", kwlist,
645 &type, &message, &plugin_instance, &type_instance,
646 &plugin, &host, &t, &severity))
650 PyErr_SetString(PyExc_RuntimeError, "type not set");
653 ds = plugin_get_ds(type);
655 PyErr_Format(PyExc_TypeError, "Dataset %s not found", type);
659 notification.time = t;
660 notification.severity = severity;
661 sstrncpy(notification.message, message, sizeof(notification.message));
662 sstrncpy(notification.host, host, sizeof(notification.host));
663 sstrncpy(notification.plugin, plugin, sizeof(notification.plugin));
664 sstrncpy(notification.plugin_instance, plugin_instance, sizeof(notification.plugin_instance));
665 sstrncpy(notification.type, type, sizeof(notification.type));
666 sstrncpy(notification.type_instance, type_instance, sizeof(notification.type_instance));
667 notification.meta = NULL;
668 if (notification.time < 1)
669 notification.time = time(0);
670 if (notification.host[0] == 0)
671 sstrncpy(notification.host, hostname_g, sizeof(notification.host));
672 if (notification.plugin[0] == 0)
673 sstrncpy(notification.plugin, "python", sizeof(notification.plugin));
674 Py_BEGIN_ALLOW_THREADS;
675 ret = plugin_dispatch_notification(¬ification);
676 Py_END_ALLOW_THREADS;
678 PyErr_SetString(PyExc_RuntimeError, "error dispatching notification, read the logs");
684 static PyObject *Notification_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
687 self = (Notification *) PluginData_new(type, args, kwds);
691 self->message[0] = 0;
693 return (PyObject *) self;
696 static int Notification_setstring(PyObject *self, PyObject *value, void *data) {
701 PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
704 new = PyString_AsString(value);
705 if (new == NULL) return -1;
706 old = ((char *) self) + (intptr_t) data;
707 sstrncpy(old, new, NOTIF_MAX_MSG_LEN);
711 static PyObject *Notification_repr(PyObject *s) {
713 Notification *self = (Notification *) s;
715 ret = PyString_FromFormat("collectd.Values(type='%s%s%s%s%s%s%s%s%s%s%s',time=%lu,interval=%i)", self->data.type,
716 *self->data.type_instance ? "',type_instance='" : "", self->data.type_instance,
717 *self->data.plugin ? "',plugin='" : "", self->data.plugin,
718 *self->data.plugin_instance ? "',plugin_instance='" : "", self->data.plugin_instance,
719 *self->data.host ? "',host='" : "", self->data.host,
720 *self->message ? "',message='" : "", self->message,
721 (long unsigned) self->data.time, self->severity);
725 static PyMethodDef Notification_methods[] = {
726 {"dispatch", (PyCFunction) Notification_dispatch, METH_VARARGS | METH_KEYWORDS, dispatch_doc},
730 static PyMemberDef Notification_members[] = {
731 {"severity", T_INT, offsetof(Notification, severity), 0, severity_doc},
735 static PyGetSetDef Notification_getseters[] = {
736 {"message", PluginData_getstring, Notification_setstring, message_doc, (void *) offsetof(Notification, message)},
740 PyTypeObject NotificationType = {
741 PyObject_HEAD_INIT(NULL)
743 "collectd.Notification", /* tp_name */
744 sizeof(Notification), /* tp_basicsize */
745 0, /* Will be filled in later */
751 Notification_repr, /* tp_repr */
752 0, /* tp_as_number */
753 0, /* tp_as_sequence */
754 0, /* tp_as_mapping */
760 0, /* tp_as_buffer */
761 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
762 Notification_doc, /* tp_doc */
765 0, /* tp_richcompare */
766 0, /* tp_weaklistoffset */
769 Notification_methods, /* tp_methods */
770 Notification_members, /* tp_members */
771 Notification_getseters, /* tp_getset */
774 0, /* tp_descr_get */
775 0, /* tp_descr_set */
776 0, /* tp_dictoffset */
777 Notification_init, /* tp_init */
779 Notification_new /* tp_new */