summaryrefslogtreecommitdiffstats
path: root/doc/howto-write-reporter
blob: abc77d5d3f9bd4c1c3564cfff720572d654d5903 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
How to write your reporter plugin
---------------------------------
This plugin receives the entire finished crash report and posts/reports
it somewhere (e.g. logs it, mails it, posts it on some web tool...)

You have to override these methods:

std::string Report(const map_crash_data_t& pCrashData,
                    const map_plugin_settings_t& pSettings,
                    const char *pArgs)

void SetSettings(const map_plugin_settings_t& pSettings);
- It is not a mandatory method.

Example of header plugin
------------------------
$ cat abrt-reporter-hello-world.h

#ifndef ABRT_REPORTER_HELLO_WORLD_H
#define ABRT_REPORTER_HELLO_WORLD_H

/*
 * If you want to build reporter you have to include `reporter'.
 * Others are analyzer.h, database.h and action.h
 */
#include <abrt/reporter.h>

class CHelloWorld : public CReporter
{
    private:
        /*
         * In our tutorial we will have two options called OptionBool
         * and PrintString. Daemon will load HelloWorld.conf and pass
         * it to our SetSettings method in parsed form, allowing us to
         * change options
         */
        bool m_OptionBool;
        std::string m_PrintString;

    public:
        /**
        * A method, which reports a crash dump to particular receiver.
        * The plugin can take arguments, but the plugin has to parse them
        * by itself.
        * @param pCrashData A crash report.
        * @oaran pSettings A settings passed from gui or cli
        * @param pArgs Plugin's arguments.
        * @retun A message which can be displayed after a report is created.
        */
        virtual std::string Report(const map_crash_data_t& pCrashData,
                                   const map_plugin_settings_t& pSettings,
                                   const char *pArgs);

        /**
        * A method, which takes settings and apply them. It is not a mandatory
	* method.
        * @param pSettings Plugin's settings
        */
        virtual void SetSettings(const map_plugin_settings_t& pSettings);
};

#endif

Example of source code of plugin
--------------------------------
$ cat abrt-reporter-hello-world.cpp

#include <abrt/abrtlib.h>
#include <abrt/abrt_exception.h>
#include "abrt-reporter-hello-world.h"

std::string CHelloWorld::Report(const map_crash_data_t& pCrashData,
                const map_plugin_settings_t& pSettings,
                const char *pArgs)
{
    if (!m_OptionBool)
    {
        /*
         * Exceptions is used to notify gui/cli that something is wrong
         * and stop reporting; gui/cli will show it as an error message.
         */
        throw CABRTException(EXCEP_PLUGIN, "OptionBool is set to `no', wrong");
    }

    /*
     * Same as example above, but here we show now how you can use try..catch block
     */
    try
    {
    }
    catch (CABRTException& e)
    {
        //throw CABRTException(EXCEP_PLUGIN, "Oops something wrong");
    }

    /*
     * If you want to log some information use function log.
     * abrtd can be started as standalone application running in
     * foreground (abrtd -d) and then you will see log information.
     * Logging has tree levels and they are controlled by VERBx where `x'
     * can be 1,2 and 3. If you want to see level1(VERB1 message) run abrtd -dv,
     * for level2 (VERB2 message) -dvv and for level3 (VERB3 message) -dvvv.
     */

     VERB1 log("what you sometimes want to see, even on a production box");
     VERB2 log("debug message, not going into insanely small details");
     VERB3 log("lots and lots of details");

    return m_PrintString;
}

void CHelloWorld::SetSettings(const map_plugin_settings_t& pSettings)
{
    m_pSettings = pSettings;

    map_plugin_settings_t::const_iterator end = pSettings.end();
    map_plugin_settings_t::const_iterator it;

    it = pSettings.find("OptionBool");
    if (it != end)
        m_OptionBool = string_to_bool(it->second.c_str());

    it = pSettings.find("PrintString");
    if (it != end)
        m_PrintString = it->second;

}

/*
 * Use the macro PLUGIN_INFO in the *.cpp file of your plugin so that your
 * subclass will be properly registered and treated as a plugin.
 * This sets up all the lower-level and administrative details to fit your
 * class into the plugin infrastructure. The syntax is:
 *
 * PLUGIN_INFO(type, plugin_class, name, version, description, email, www, gtk_builder)
 *  - "type" is one of ANALYZER, ACTION, REPORTER, or DATABASE
 *  - "plugin_class" is the identifier of the class
 *  - "name" is a string with the name of the plugin
 *  - "version" is a string with the version of the plugin
 *  - "description" is a string with the summary of what the plugin does
 *  - "email" and "www" are strings with the contact info for the author
 *  - "gtk_builder" is path to plugins gui
 */

PLUGIN_INFO(REPORTER,
            CHelloWorld,
            "HelloWorld",
            "0.0.1",
            "Show `Hello world!!!' in gui",
            "author",
            "www adress to project/plugin",
            "/path/to/gui.plugin")

Example of configuration file
-----------------------------
When option 'Enabled' is missing or is set to 'no', plugin won't be loaded
at abrtd start-up (but may be loaded later if plugin is used in one of the
directives). If it is set to 'yes', plugin is loaded right away.
At the plugin load time, options are parsed by daemon and passed to plugin's
SetSettings method.


$ cat HelloWorld.conf
Enabled = yes

# just for demonstration
# if OptionBool is set to yes, it will print the text specified in PrintString option
# if OptionBool is set to no, the error with the message "OptionBool is set to `no', wrong"
will be generated.

OptionBool = yes

PrintString = "Hello World!!!"

Example of Makefile
-------------------
Makefile is written to build plugin on 64bit machines. If you want to build for
32bit get rid of -m64 in build section and rename /usr/lib64/abrt to /usr/lib/abrt

$ cat Makefile
PROGRAM	=	libHelloWorld
CXX	=	g++
SRCS	+=	abrt-reporter-hello-world.cpp
OBJS	+=	$(addsuffix .o, $(basename $(SRCS)))


.PHONY: clean install uninstall

%.o: %.cpp
	$(CXX) `pkg-config --cflags --libs abrt` -m64 -c -Wall -std=c++98 -pedantic $<

$(PROGRAM).so: $(OBJS)
	$(CXX) -shared $< -o $@

clean:
	rm -f *.o *.so

install:
	install -m 755 -D $(PROGRAM).so /usr/lib64/abrt/
	install -m 644 -D HelloWorld.conf /etc/abrt/plugins/

uninstall:
	rm -f /usr/lib64/abrt/$(PROGRAM).so
	rm -f /etc/abrt/plugins/HelloWorld.conf