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 cpy_string_to_unicode_or_bytes(value);
125 static int PluginData_setstring(PyObject *self, PyObject *value, void *data) {
130 PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
134 new = cpy_unicode_or_bytes_to_string(&value);
139 old = ((char *) self) + (intptr_t) data;
140 sstrncpy(old, new, DATA_MAX_NAME_LEN);
145 static int PluginData_settype(PyObject *self, PyObject *value, void *data) {
150 PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
154 new = cpy_unicode_or_bytes_to_string(&value);
160 if (plugin_get_ds(new) == NULL) {
161 PyErr_Format(PyExc_TypeError, "Dataset %s not found", new);
166 old = ((char *) self) + (intptr_t) data;
167 sstrncpy(old, new, DATA_MAX_NAME_LEN);
172 static PyGetSetDef PluginData_getseters[] = {
173 {"host", PluginData_getstring, PluginData_setstring, host_doc, (void *) offsetof(PluginData, host)},
174 {"plugin", PluginData_getstring, PluginData_setstring, plugin_doc, (void *) offsetof(PluginData, plugin)},
175 {"plugin_instance", PluginData_getstring, PluginData_setstring, plugin_instance_doc, (void *) offsetof(PluginData, plugin_instance)},
176 {"type_instance", PluginData_getstring, PluginData_setstring, type_instance_doc, (void *) offsetof(PluginData, type_instance)},
177 {"type", PluginData_getstring, PluginData_settype, type_doc, (void *) offsetof(PluginData, type)},
181 PyTypeObject PluginDataType = {
183 "collectd.PluginData", /* tp_name */
184 sizeof(PluginData), /* tp_basicsize */
185 0, /* Will be filled in later */
191 0/*PluginData_repr*/, /* tp_repr */
192 0, /* tp_as_number */
193 0, /* tp_as_sequence */
194 0, /* tp_as_mapping */
200 0, /* tp_as_buffer */
201 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE /*| Py_TPFLAGS_HAVE_GC*/, /*tp_flags*/
202 PluginData_doc, /* tp_doc */
205 0, /* tp_richcompare */
206 0, /* tp_weaklistoffset */
210 PluginData_members, /* tp_members */
211 PluginData_getseters, /* tp_getset */
214 0, /* tp_descr_get */
215 0, /* tp_descr_set */
216 0, /* tp_dictoffset */
217 PluginData_init, /* tp_init */
219 PluginData_new /* tp_new */
222 static char interval_doc[] = "The interval is the timespan in seconds between two submits for\n"
223 "the same data source. This value has to be a positive integer, so you can't\n"
224 "submit more than one value per second. If this member is set to a\n"
225 "non-positive value, the default value as specified in the config file will\n"
226 "be used (default: 10).\n"
228 "If you submit values more often than the specified interval, the average\n"
229 "will be used. If you submit less values, your graphs will have gaps.";
231 static char values_doc[] = "These are the actual values that get dispatched to collectd.\n"
232 "It has to be a sequence (a tuple or list) of numbers.\n"
233 "The size of the sequence and the type of its content depend on the type\n"
234 "member your types.db file. For more information on this read the types.db\n"
237 "If the sequence does not have the correct size upon dispatch a RuntimeError\n"
238 "exception will be raised. If the content of the sequence is not a number,\n"
239 "a TypeError exception will be raised.";
241 static char dispatch_doc[] = "dispatch([type][, values][, plugin_instance][, type_instance]"
242 "[, plugin][, host][, time][, interval]) -> None. Dispatch a value list.\n"
244 "Dispatch this instance to the collectd process. The object has members\n"
245 "for each of the possible arguments for this method. For a detailed explanation\n"
246 "of these parameters see the member of the same same.\n"
248 "If you do not submit a parameter the value saved in its member will be submitted.\n"
249 "If you do provide a parameter it will be used instead, without altering the member.";
251 static char write_doc[] = "write([destination][, type][, values][, plugin_instance][, type_instance]"
252 "[, plugin][, host][, time][, interval]) -> None. Dispatch a value list.\n"
254 "Write this instance to a single plugin or all plugins if 'destination' is obmitted.\n"
255 "This will bypass the main collectd process and all filtering and caching.\n"
256 "Other than that it works similar to 'dispatch'. In most cases 'dispatch' should be\n"
257 "used instead of 'write'.\n";
259 static char Values_doc[] = "A Values object used for dispatching values to collectd and receiving values from write callbacks.";
261 static PyObject *Values_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
264 self = (Values *) PluginData_new(type, args, kwds);
268 self->values = PyList_New(0);
270 return (PyObject *) self;
273 static int Values_init(PyObject *s, PyObject *args, PyObject *kwds) {
274 Values *self = (Values *) s;
275 int interval = 0, ret;
277 PyObject *values = NULL, *tmp;
278 const char *type = "", *plugin_instance = "", *type_instance = "", *plugin = "", *host = "";
279 static char *kwlist[] = {"type", "values", "plugin_instance", "type_instance",
280 "plugin", "host", "time", "interval", NULL};
282 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sOssssdi", kwlist,
283 &type, &values, &plugin_instance, &type_instance,
284 &plugin, &host, &time, &interval))
287 tmp = Py_BuildValue("sssssd", type, plugin_instance, type_instance, plugin, host, time);
290 ret = PluginDataType.tp_init(s, tmp, NULL);
295 if (values == NULL) {
296 values = PyList_New(0);
303 self->values = values;
306 self->interval = interval;
310 static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
312 const data_set_t *ds;
315 value_list_t value_list = VALUE_LIST_INIT;
316 PyObject *values = self->values;
317 double time = self->data.time;
318 int interval = self->interval;
319 const char *host = self->data.host;
320 const char *plugin = self->data.plugin;
321 const char *plugin_instance = self->data.plugin_instance;
322 const char *type = self->data.type;
323 const char *type_instance = self->data.type_instance;
325 static char *kwlist[] = {"type", "values", "plugin_instance", "type_instance",
326 "plugin", "host", "time", "interval", NULL};
327 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sOssssdi", kwlist,
328 &type, &values, &plugin_instance, &type_instance,
329 &plugin, &host, &time, &interval))
333 PyErr_SetString(PyExc_RuntimeError, "type not set");
336 ds = plugin_get_ds(type);
338 PyErr_Format(PyExc_TypeError, "Dataset %s not found", type);
341 if (values == NULL || (PyTuple_Check(values) == 0 && PyList_Check(values) == 0)) {
342 PyErr_Format(PyExc_TypeError, "values must be list or tuple");
345 size = (int) PySequence_Length(values);
346 if (size != ds->ds_num) {
347 PyErr_Format(PyExc_RuntimeError, "type %s needs %d values, got %i", type, ds->ds_num, size);
350 value = malloc(size * sizeof(*value));
351 for (i = 0; i < size; ++i) {
352 PyObject *item, *num;
353 item = PySequence_GetItem(values, i);
354 if (ds->ds->type == DS_TYPE_COUNTER) {
355 num = PyNumber_Long(item);
357 value[i].counter = PyLong_AsUnsignedLongLong(num);
358 } else if (ds->ds->type == DS_TYPE_GAUGE) {
359 num = PyNumber_Float(item);
361 value[i].gauge = PyFloat_AsDouble(num);
362 } else if (ds->ds->type == DS_TYPE_DERIVE) {
363 /* This might overflow without raising an exception.
364 * Not much we can do about it */
365 num = PyNumber_Long(item);
367 value[i].derive = PyLong_AsLongLong(num);
368 } else if (ds->ds->type == DS_TYPE_ABSOLUTE) {
369 /* This might overflow without raising an exception.
370 * Not much we can do about it */
371 num = PyNumber_Long(item);
373 value[i].absolute = PyLong_AsUnsignedLongLong(num);
376 PyErr_Format(PyExc_RuntimeError, "unknown data type %d for %s", ds->ds->type, type);
379 if (PyErr_Occurred() != NULL) {
384 value_list.values = value;
385 value_list.values_len = size;
386 value_list.time = time;
387 value_list.interval = interval;
388 sstrncpy(value_list.host, host, sizeof(value_list.host));
389 sstrncpy(value_list.plugin, plugin, sizeof(value_list.plugin));
390 sstrncpy(value_list.plugin_instance, plugin_instance, sizeof(value_list.plugin_instance));
391 sstrncpy(value_list.type, type, sizeof(value_list.type));
392 sstrncpy(value_list.type_instance, type_instance, sizeof(value_list.type_instance));
393 value_list.meta = NULL;
394 if (value_list.host[0] == 0)
395 sstrncpy(value_list.host, hostname_g, sizeof(value_list.host));
396 if (value_list.plugin[0] == 0)
397 sstrncpy(value_list.plugin, "python", sizeof(value_list.plugin));
398 Py_BEGIN_ALLOW_THREADS;
399 ret = plugin_dispatch_values(&value_list);
400 Py_END_ALLOW_THREADS;
402 PyErr_SetString(PyExc_RuntimeError, "error dispatching values, read the logs");
409 static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
411 const data_set_t *ds;
414 value_list_t value_list = VALUE_LIST_INIT;
415 PyObject *values = self->values;
416 double time = self->data.time;
417 int interval = self->interval;
418 const char *host = self->data.host;
419 const char *plugin = self->data.plugin;
420 const char *plugin_instance = self->data.plugin_instance;
421 const char *type = self->data.type;
422 const char *type_instance = self->data.type_instance;
423 const char *dest = NULL;
425 static char *kwlist[] = {"destination", "type", "values", "plugin_instance", "type_instance",
426 "plugin", "host", "time", "interval", NULL};
427 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sOssssdi", kwlist,
428 &type, &values, &plugin_instance, &type_instance,
429 &plugin, &host, &time, &interval))
433 PyErr_SetString(PyExc_RuntimeError, "type not set");
436 ds = plugin_get_ds(type);
438 PyErr_Format(PyExc_TypeError, "Dataset %s not found", type);
441 if (values == NULL || (PyTuple_Check(values) == 0 && PyList_Check(values) == 0)) {
442 PyErr_Format(PyExc_TypeError, "values must be list or tuple");
445 size = (int) PySequence_Length(values);
446 if (size != ds->ds_num) {
447 PyErr_Format(PyExc_RuntimeError, "type %s needs %d values, got %i", type, ds->ds_num, size);
450 value = malloc(size * sizeof(*value));
451 for (i = 0; i < size; ++i) {
452 PyObject *item, *num;
453 item = PySequence_GetItem(values, i);
454 if (ds->ds->type == DS_TYPE_COUNTER) {
455 num = PyNumber_Long(item);
457 value[i].counter = PyLong_AsUnsignedLongLong(num);
458 } else if (ds->ds->type == DS_TYPE_GAUGE) {
459 num = PyNumber_Float(item);
461 value[i].gauge = PyFloat_AsDouble(num);
462 } else if (ds->ds->type == DS_TYPE_DERIVE) {
463 /* This might overflow without raising an exception.
464 * Not much we can do about it */
465 num = PyNumber_Long(item);
467 value[i].derive = PyLong_AsLongLong(num);
468 } else if (ds->ds->type == DS_TYPE_ABSOLUTE) {
469 /* This might overflow without raising an exception.
470 * Not much we can do about it */
471 num = PyNumber_Long(item);
473 value[i].absolute = PyLong_AsUnsignedLongLong(num);
476 PyErr_Format(PyExc_RuntimeError, "unknown data type %d for %s", ds->ds->type, type);
479 if (PyErr_Occurred() != NULL) {
484 value_list.values = value;
485 value_list.values_len = size;
486 value_list.time = time;
487 value_list.interval = interval;
488 sstrncpy(value_list.host, host, sizeof(value_list.host));
489 sstrncpy(value_list.plugin, plugin, sizeof(value_list.plugin));
490 sstrncpy(value_list.plugin_instance, plugin_instance, sizeof(value_list.plugin_instance));
491 sstrncpy(value_list.type, type, sizeof(value_list.type));
492 sstrncpy(value_list.type_instance, type_instance, sizeof(value_list.type_instance));
493 value_list.meta = NULL;
494 if (value_list.host[0] == 0)
495 sstrncpy(value_list.host, hostname_g, sizeof(value_list.host));
496 if (value_list.plugin[0] == 0)
497 sstrncpy(value_list.plugin, "python", sizeof(value_list.plugin));
498 Py_BEGIN_ALLOW_THREADS;
499 ret = plugin_write(dest, NULL, &value_list);
500 Py_END_ALLOW_THREADS;
502 PyErr_SetString(PyExc_RuntimeError, "error dispatching values, read the logs");
509 /*static PyObject *Values_repr(PyObject *s) {
510 PyObject *ret, *valuestring = NULL;
511 Values *self = (Values *) s;
513 if (self->values != NULL)
514 valuestring = PyObject_Repr(self->values);
515 if (valuestring == NULL)
518 ret = PyString_FromFormat("collectd.Values(type='%s%s%s%s%s%s%s%s%s',time=%lu,interval=%i,values=%s)", self->data.type,
519 *self->data.type_instance ? "',type_instance='" : "", self->data.type_instance,
520 *self->data.plugin ? "',plugin='" : "", self->data.plugin,
521 *self->data.plugin_instance ? "',plugin_instance='" : "", self->data.plugin_instance,
522 *self->data.host ? "',host='" : "", self->data.host,
523 (long unsigned) self->data.time, self->interval,
524 valuestring ? cpy_unicode_or_bytes_to_string(valuestring) : "[]");
525 Py_XDECREF(valuestring);
529 static int Values_traverse(PyObject *self, visitproc visit, void *arg) {
530 Values *v = (Values *) self;
535 static int Values_clear(PyObject *self) {
536 Values *v = (Values *) self;
541 static void Values_dealloc(PyObject *self) {
543 self->ob_type->tp_free(self);
546 static PyMemberDef Values_members[] = {
547 {"interval", T_INT, offsetof(Values, interval), 0, interval_doc},
548 {"values", T_OBJECT_EX, offsetof(Values, values), 0, values_doc},
552 static PyMethodDef Values_methods[] = {
553 {"dispatch", (PyCFunction) Values_dispatch, METH_VARARGS | METH_KEYWORDS, dispatch_doc},
554 {"write", (PyCFunction) Values_write, METH_VARARGS | METH_KEYWORDS, write_doc},
558 PyTypeObject ValuesType = {
560 "collectd.Values", /* tp_name */
561 sizeof(Values), /* tp_basicsize */
562 0, /* Will be filled in later */
563 Values_dealloc, /* tp_dealloc */
568 0/*Values_repr*/, /* tp_repr */
569 0, /* tp_as_number */
570 0, /* tp_as_sequence */
571 0, /* tp_as_mapping */
577 0, /* tp_as_buffer */
578 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
579 Values_doc, /* tp_doc */
580 Values_traverse, /* tp_traverse */
581 Values_clear, /* tp_clear */
582 0, /* tp_richcompare */
583 0, /* tp_weaklistoffset */
586 Values_methods, /* tp_methods */
587 Values_members, /* tp_members */
591 0, /* tp_descr_get */
592 0, /* tp_descr_set */
593 0, /* tp_dictoffset */
594 Values_init, /* tp_init */
596 Values_new /* tp_new */
599 static char severity_doc[] = "The severity of this notification. Assign or compare to\n"
600 "NOTIF_FAILURE, NOTIF_WARNING or NOTIF_OKAY.";
602 static char message_doc[] = "Some kind of description what's going on and why this Notification was generated.";
604 static char Notification_doc[] = "The Notification class is a wrapper around the collectd notification.\n"
605 "It can be used to notify other plugins about bad stuff happening. It works\n"
606 "similar to Values but has a severity and a message instead of interval\n"
608 "Notifications can be dispatched at any time and can be received with register_notification.";
610 static int Notification_init(PyObject *s, PyObject *args, PyObject *kwds) {
611 Notification *self = (Notification *) s;
613 int severity = 0, ret;
615 const char *message = "";
616 const char *type = "", *plugin_instance = "", *type_instance = "", *plugin = "", *host = "";
617 static char *kwlist[] = {"type", "message", "plugin_instance", "type_instance",
618 "plugin", "host", "time", "severity", NULL};
620 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ssssssdi", kwlist,
621 &type, &message, &plugin_instance, &type_instance,
622 &plugin, &host, &time, &severity))
625 tmp = Py_BuildValue("sssssd", type, plugin_instance, type_instance, plugin, host, time);
628 ret = PluginDataType.tp_init(s, tmp, NULL);
633 sstrncpy(self->message, message, sizeof(self->message));
634 self->severity = severity;
638 static PyObject *Notification_dispatch(Notification *self, PyObject *args, PyObject *kwds) {
640 const data_set_t *ds;
641 notification_t notification;
642 double t = self->data.time;
643 int severity = self->severity;
644 const char *host = self->data.host;
645 const char *plugin = self->data.plugin;
646 const char *plugin_instance = self->data.plugin_instance;
647 const char *type = self->data.type;
648 const char *type_instance = self->data.type_instance;
649 const char *message = self->message;
651 static char *kwlist[] = {"type", "message", "plugin_instance", "type_instance",
652 "plugin", "host", "time", "severity", NULL};
653 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ssssssdi", kwlist,
654 &type, &message, &plugin_instance, &type_instance,
655 &plugin, &host, &t, &severity))
659 PyErr_SetString(PyExc_RuntimeError, "type not set");
662 ds = plugin_get_ds(type);
664 PyErr_Format(PyExc_TypeError, "Dataset %s not found", type);
668 notification.time = t;
669 notification.severity = severity;
670 sstrncpy(notification.message, message, sizeof(notification.message));
671 sstrncpy(notification.host, host, sizeof(notification.host));
672 sstrncpy(notification.plugin, plugin, sizeof(notification.plugin));
673 sstrncpy(notification.plugin_instance, plugin_instance, sizeof(notification.plugin_instance));
674 sstrncpy(notification.type, type, sizeof(notification.type));
675 sstrncpy(notification.type_instance, type_instance, sizeof(notification.type_instance));
676 notification.meta = NULL;
677 if (notification.time < 1)
678 notification.time = time(0);
679 if (notification.host[0] == 0)
680 sstrncpy(notification.host, hostname_g, sizeof(notification.host));
681 if (notification.plugin[0] == 0)
682 sstrncpy(notification.plugin, "python", sizeof(notification.plugin));
683 Py_BEGIN_ALLOW_THREADS;
684 ret = plugin_dispatch_notification(¬ification);
685 Py_END_ALLOW_THREADS;
687 PyErr_SetString(PyExc_RuntimeError, "error dispatching notification, read the logs");
693 static PyObject *Notification_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
696 self = (Notification *) PluginData_new(type, args, kwds);
700 self->message[0] = 0;
702 return (PyObject *) self;
705 static int Notification_setstring(PyObject *self, PyObject *value, void *data) {
710 PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
714 new = cpy_unicode_or_bytes_to_string(&value);
719 old = ((char *) self) + (intptr_t) data;
720 sstrncpy(old, new, NOTIF_MAX_MSG_LEN);
725 /*static PyObject *Notification_repr(PyObject *s) {
727 Notification *self = (Notification *) s;
729 ret = PyString_FromFormat("collectd.Values(type='%s%s%s%s%s%s%s%s%s%s%s',time=%lu,interval=%i)", self->data.type,
730 *self->data.type_instance ? "',type_instance='" : "", self->data.type_instance,
731 *self->data.plugin ? "',plugin='" : "", self->data.plugin,
732 *self->data.plugin_instance ? "',plugin_instance='" : "", self->data.plugin_instance,
733 *self->data.host ? "',host='" : "", self->data.host,
734 *self->message ? "',message='" : "", self->message,
735 (long unsigned) self->data.time, self->severity);
739 static PyMethodDef Notification_methods[] = {
740 {"dispatch", (PyCFunction) Notification_dispatch, METH_VARARGS | METH_KEYWORDS, dispatch_doc},
744 static PyMemberDef Notification_members[] = {
745 {"severity", T_INT, offsetof(Notification, severity), 0, severity_doc},
749 static PyGetSetDef Notification_getseters[] = {
750 {"message", PluginData_getstring, Notification_setstring, message_doc, (void *) offsetof(Notification, message)},
754 PyTypeObject NotificationType = {
756 "collectd.Notification", /* tp_name */
757 sizeof(Notification), /* tp_basicsize */
758 0, /* Will be filled in later */
764 0/*Notification_repr*/, /* tp_repr */
765 0, /* tp_as_number */
766 0, /* tp_as_sequence */
767 0, /* tp_as_mapping */
773 0, /* tp_as_buffer */
774 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
775 Notification_doc, /* tp_doc */
778 0, /* tp_richcompare */
779 0, /* tp_weaklistoffset */
782 Notification_methods, /* tp_methods */
783 Notification_members, /* tp_members */
784 Notification_getseters, /* tp_getset */
787 0, /* tp_descr_get */
788 0, /* tp_descr_set */
789 0, /* tp_dictoffset */
790 Notification_init, /* tp_init */
792 Notification_new /* tp_new */