Merge lp:~jpakkane/unity-scopes-api/simplelogging into lp:unity-scopes-api/devel

Proposed by Jussi Pakkanen
Status: Rejected
Rejected by: Michi Henning
Proposed branch: lp:~jpakkane/unity-scopes-api/simplelogging
Merge into: lp:unity-scopes-api/devel
Diff against target: 762 lines (+302/-41)
17 files modified
include/unity/scopes/internal/Logging.h (+70/-0)
src/scopes/internal/ActivationQueryObject.cpp (+3/-3)
src/scopes/internal/AnnotationImpl.cpp (+5/-5)
src/scopes/internal/CMakeLists.txt (+1/-0)
src/scopes/internal/Logging.cpp (+119/-0)
src/scopes/internal/PreviewQueryObject.cpp (+5/-3)
src/scopes/internal/QueryBaseImpl.cpp (+2/-2)
src/scopes/internal/QueryCtrlImpl.cpp (+2/-2)
src/scopes/internal/QueryObject.cpp (+3/-3)
src/scopes/internal/ReplyImpl.cpp (+5/-4)
src/scopes/internal/ReplyObject.cpp (+5/-5)
src/scopes/internal/RuntimeImpl.cpp (+4/-4)
src/scopes/internal/ScopeImpl.cpp (+7/-7)
src/scopes/internal/ScopeObject.cpp (+3/-3)
test/gtest/scopes/internal/CMakeLists.txt (+1/-0)
test/gtest/scopes/internal/Logging/CMakeLists.txt (+14/-0)
test/gtest/scopes/internal/Logging/Logging_test.cpp (+53/-0)
To merge this branch: bzr merge lp:~jpakkane/unity-scopes-api/simplelogging
Reviewer Review Type Date Requested Status
Michi Henning (community) Disapprove
PS Jenkins bot (community) continuous-integration Approve
Paweł Stołowski (community) Needs Fixing
Review via email: mp+209447@code.launchpad.net

Commit message

A very simple logging class.

Description of the change

A very simple logging class. Mostly a building block for further functionality.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Paweł Stołowski (stolowski) wrote :

Why not dumping to std::cerr right away in LogGatherer& LogGatherer::operator<< ? That would save us some extra string copying. Is there a good reason for buffering strings up like that?

review: Needs Information
259. By Jussi Pakkanen

Simple locking.

Revision history for this message
Jussi Pakkanen (jpakkane) wrote :

Because dumping immediately causes interleaving for multiple threads.

Updated the MR to provide simple locking.

If we want this to be fully multithreaded we either need to copy the items or create a complex locking mechanism. Since the data sizes are minuscule (less than 1k for >99% of the time) and usage infrequent, let's just copy.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
260. By Jussi Pakkanen

Merged trunk.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Paweł Stołowski (stolowski) wrote :

199 +static std::mutex print_mutex;

This could be a static private member of LogGatherer, no? I realise it's not exposed anywhere right now, but making it a static member would encapsulate it even more

Could you please provide overloaded << for all basic data types?

review: Needs Fixing
Revision history for this message
Michi Henning (michihenning) wrote :

> Could you please provide overloaded << for all basic data types?

I'd be inclined to hold off with that for the moment. There is no point in adding an operator<< for floats if we don't have any place in the code where we want to log a float. All it means is that we end up having to write more code and tests, for no gain in functionality.

Revision history for this message
Michi Henning (michihenning) wrote :

LogStream should be provided as an abstract base with only pure virtual functions. That way, we don't couple the logging mechanism to the call sites and we can replace it with something else without recompiling everything that logs something, and the choice of which logger to use can be delayed until run time.

Revision history for this message
Michi Henning (michihenning) wrote :

196 +namespace internal
197 +{
198 +
199 +static std::mutex print_mutex;
200 +
201 +LogStream errlog;

This doesn't look right. If the mutex is static, it has internal linkage, meaning that each compilation unit will end up with its own separate copy of the mutex, so locking the mutex will not achieve what it's meant to.

If we want to have all source files share the same single mutex, it needs to be a static member variable of the class.

Revision history for this message
Michi Henning (michihenning) wrote :

> This doesn't look right. If the mutex is static, it has internal linkage,

Ah, sorry, forget it. I confused source file and header file.

Revision history for this message
Paweł Stołowski (stolowski) wrote :

> > Could you please provide overloaded << for all basic data types?
>
> I'd be inclined to hold off with that for the moment. There is no point in
> adding an operator<< for floats if we don't have any place in the code where
> we want to log a float. All it means is that we end up having to write more
> code and tests, for no gain in functionality.

I think it's worth to have one for bool (and making sure it behaves as if std::boolalpha was set).

Revision history for this message
Michi Henning (michihenning) wrote :

Bool is fine with me, but let's not get carried away. If we find in two months time that we really want to log a double with formatting, we can still add something then.

Revision history for this message
Jussi Pakkanen (jpakkane) wrote :

You can totally change the logging framework without recompiling everything. You just change the .cpp file and recompile that (not-yet-done pimpling notwithstanding). There is no need to change the header for that.

As far as runtime goes, there are two things we might want to do then:

1. configure it (e.g. set log levels or the like)
2. change it (e.g. from Boost to glib or what have you)

The first one can be done just by adding some (global?) functions. A virtual base provides no improvements. The latter is something we don't ever need to do. Why on earth would we change between the two at runtime? We'll just pick one and be done with it. Even if for some strange reason we would want to, we can implement 2 in the same way as 1: a configuration option of the class.

Abstract base classes only make sense if you have multiple objects of the same type existing at the same time and need to be used interchangeably. We don't. It's just a simple "write this stuff to the log". It does _not_ need anything fancier because those features just complicate things for no good reason. As an example, let's look at this:

errlog << "Some text";

For this to work, errlog needs to be either a macro that does something magical or a concrete (that is, non-abstract) object. It can _not_ be an abstract base class because such an object is non-constructible. This is also the only way it is used. Thus:

1. we absolutely need a concrete, instantiated object with defined semantics
2. its type does not change at runtime (it behaviour might, but that's just a question of configuration)

Under these conditions, what is the benefit an abstract base class would bring?

("Because maybe we might sometime in the future do something perhaps" is NOT a valid answer, it is handwaving.)

Revision history for this message
Michi Henning (michihenning) wrote :

We have RuntimeImpl in the code as a handle to anything that the library needs. That gives us the ability to have multiple runtime instances in a process (we do this in the tests, for example), and it allows us to control the life time of each run time.

With a global logger variable, we can't do this anymore, and separate instances of the runtime in the same process will share the same logger.

I think it would be better to have RuntimeImpl own and initialise the logger. I believe that it's possible to get at the RuntimeImpl/Runtime instance from most places in the code. There may be places in value types where we would like to log something and can't get at the Runtime handle. I haven't checked this in detail yet, but I expect there won't be too many places in the code where this is the case. In most of them, we can probably make the logger available if we need it.

At any rate, I'm uncomfortable with having a global variable.

Revision history for this message
Jussi Pakkanen (jpakkane) wrote :

Not having global variables is a valid goal. To do that we either need to:

1. pass a logging provider to all classes that need logging (tedious, let's not do that)
2. have errlog class determine where the messages should go and configure LogGather to write its stuff there

Option 2 would mean roughly this in pseudocode:

if something
  l = LogGatherer(with some options)
else
  l = LogGatherer(with some other options)
endif

I would imagine this is what Qt does and why its logging classes are used like this:

qDebug() << "something";

261. By Jussi Pakkanen

Now with bool support.

Revision history for this message
Thomas Voß (thomas-voss) wrote :

As this is an implementation detail, why not use google log (see https://code.google.com/p/google-glog). It is in main, and provides all of the required functionality. At any rate, establishing an interface as in:

class Logger
{
public:
    enum class Severity
    {
        error,
        warning,
        info,
        ...
    };

    virtual std::ostream& log(Severity severity) = 0;
};

with a GLog-based implementation would be quite helpful in testing and, later on, in real reporting use-cases.

For the global variable/global function approach: Singleton is an anti-pattern from my POV, and while it might be less tedious to just have a global logger instance, it results in tight coupling and makes isolated component testing really really difficult.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Jussi Pakkanen (jpakkane) wrote :

If you look at glog, it uses singletons (or macros, which are "global functions" to use your terminology) too. You use it like this:

LOG(INFO) << "Something";

Also, could you give an example of where using a global logging function would make debugging harder? Please be specific, preferably by using sample code.

While you are at it, could you also explain how non-global logging objects should work? As an example let's say we have class A which internally uses class B, which uses class C, which in turn uses class D. Now let's suppose class D needs to write a log message. The questions to answer are:

- what object (not a function as those are forbidden, right?) should it call to send this message
- how is this object passed on to it
- who is the master owner of this object

Revision history for this message
Thomas Voß (thomas-voss) wrote :

> If you look at glog, it uses singletons (or macros, which are "global
> functions" to use your terminology) too. You use it like this:
>
> LOG(INFO) << "Something";
>

Sure, that's why I proposed a logger interface that can be implemented with the help of GLog to avoid a singleton use.

> Also, could you give an example of where using a global logging function would
> make debugging harder? Please be specific, preferably by using sample code.
>

For testing (which I originally referred to): Somewhere in your implementation (in a .cpp) you have one or multiple lines like:

  logerr << "...";

How do you test (easily) that the correct log string is generated? Of course, we could fall back to link time seams here, but I don't think that's a good idea.

> While you are at it, could you also explain how non-global logging objects
> should work? As an example let's say we have class A which internally uses
> class B, which uses class C, which in turn uses class D. Now let's suppose
> class D needs to write a log message. The questions to answer are:
>
> - what object (not a function as those are forbidden, right?) should it call
> to send this message
> - how is this object passed on to it
> - who is the master owner of this object

Hmmm, I might miss something, but D should look like:

  class D
  {
    public:
        D(const Logger::Ptr& logger) : logger(logger)
        {
        }

        void do_something()
        {
            logger->log(error) << "Something went horribly wrong";
        }
    private:
        Logger::Ptr logger;
  };

And yes, the logger dependency would have to be handed down the dependency chain. Nothing wrong with that from my perspective as the logger (and later on a reporter) in fact is a real functional requirement of class D. You will not get rid of that by satisfying it implicitly with a singleton.

The ultimate owner of the logger is the runtime.

Revision history for this message
Jussi Pakkanen (jpakkane) wrote :

> How do you test (easily) that the correct log string is generated?

By forwarding the log output to a file and inspecting its contents.

> And yes, the logger dependency would have to be handed down the dependency chain.

Please read this:

http://steve-yegge.blogspot.fi/2006/03/execution-in-kingdom-of-nouns.html

> Nothing wrong with that from my perspective

But from the perspective of the poor bastards who have to augment, basically, EVERY SINGLE CLASS in the entire source base with extra constructor arguments this is a very big problem. These people have better things to do with their time.

Revision history for this message
Thomas Voß (thomas-voss) wrote :

> > How do you test (easily) that the correct log string is generated?
>
> By forwarding the log output to a file and inspecting its contents.
>
> > And yes, the logger dependency would have to be handed down the dependency
> chain.
>
> Please read this:
>
> http://steve-yegge.blogspot.fi/2006/03/execution-in-kingdom-of-nouns.html
>

I would hold http://www.mockobjects.com/2007/04/test-smell-logging-is-also-feature.html against that and your proposal for testing.

> > Nothing wrong with that from my perspective
>
> But from the perspective of the poor bastards who have to augment, basically,
> EVERY SINGLE CLASS in the entire source base with extra constructor arguments
> this is a very big problem. These people have better things to do with their
> time.

Two things:

(1.) why would every class need to log? Littering production code with logging message sounds like bad idea. Instead, instrumenting an executable with http://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-finstrument_002dfunctions-2112 and implementing the respective hooks might be a better idea.

(2.) Under the assumption of non-universal logging (see (1.)), I would strongly assume that the scope of the changes is limited and well-defined in reality as only certain classes would need to be provided with logging capabilities.

Revision history for this message
Michi Henning (michihenning) wrote :

Cleaning up moldy oldies.

review: Disapprove

Unmerged revisions

261. By Jussi Pakkanen

Now with bool support.

260. By Jussi Pakkanen

Merged trunk.

259. By Jussi Pakkanen

Simple locking.

258. By Jussi Pakkanen

Start using the logging class instead of hitting std::cerr directly.

257. By Jussi Pakkanen

Now with numbers.

256. By Jussi Pakkanen

Some more test cases.

255. By Jussi Pakkanen

Very basic output plus some text.

254. By Jussi Pakkanen

Start work on logging classes.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'include/unity/scopes/internal/Logging.h'
2--- include/unity/scopes/internal/Logging.h 1970-01-01 00:00:00 +0000
3+++ include/unity/scopes/internal/Logging.h 2014-03-06 09:05:05 +0000
4@@ -0,0 +1,70 @@
5+/*
6+ * Copyright (C) 2014 Canonical Ltd
7+ *
8+ * This program is free software: you can redistribute it and/or modify
9+ * it under the terms of the GNU Lesser General Public License version 3 as
10+ * published by the Free Software Foundation.
11+ *
12+ * This program is distributed in the hope that it will be useful,
13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ * GNU Lesser General Public License for more details.
16+ *
17+ * You should have received a copy of the GNU Lesser General Public License
18+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
19+ *
20+ * Authored by: Jussi Pakkanen <jussi.pakkanen@canonical.com>
21+ */
22+
23+#ifndef UNITY_SCOPES_INTERNAL_LOGGING_H
24+#define UNITY_SCOPES_INTERNAL_LOGGING_H
25+
26+#include <string>
27+#include <vector>
28+#include <unity/util/NonCopyable.h>
29+
30+namespace unity
31+{
32+
33+namespace scopes
34+{
35+
36+namespace internal
37+{
38+
39+class LogGatherer;
40+
41+class LogStream final {
42+ NONCOPYABLE(LogStream);
43+public:
44+ LogStream();
45+ LogGatherer operator<<(const std::string &s);
46+ LogGatherer operator<<(const int i);
47+ LogGatherer operator<<(const char *msg);
48+ LogGatherer operator<<(const bool i);
49+};
50+
51+class LogGatherer final {
52+
53+public:
54+
55+ LogGatherer();
56+ ~LogGatherer();
57+ LogGatherer& operator<<(const std::string &s);
58+ LogGatherer& operator<<(const int i);
59+ LogGatherer& operator<<(const bool i);
60+ LogGatherer& operator<<(const char *msg);
61+
62+private:
63+ std::vector<std::string> strings;
64+};
65+
66+extern LogStream errlog;
67+
68+} // namespace internal
69+
70+} // namespace scopes
71+
72+} // namespace unity
73+
74+#endif
75
76=== modified file 'src/scopes/internal/ActivationQueryObject.cpp'
77--- src/scopes/internal/ActivationQueryObject.cpp 2014-02-27 23:29:10 +0000
78+++ src/scopes/internal/ActivationQueryObject.cpp 2014-03-06 09:05:05 +0000
79@@ -21,7 +21,7 @@
80 #include <unity/scopes/ActivationQueryBase.h>
81 #include <unity/scopes/internal/MWReply.h>
82 #include <unity/scopes/internal/MWQueryCtrl.h>
83-#include <iostream>
84+#include <unity/scopes/internal/Logging.h>
85 #include <cassert>
86
87 using namespace std;
88@@ -69,13 +69,13 @@
89 {
90 // TODO: log error
91 reply_->finished(ListenerBase::Error, e.what()); // Oneway, can't block
92- cerr << "ActivationQueryObject::run(): " << e.what() << endl;
93+ errlog << "ActivationQueryObject::run(): " << e.what();
94 }
95 catch (...)
96 {
97 // TODO: log error
98 reply_->finished(ListenerBase::Error, "unknown exception"); // Oneway, can't block
99- cerr << "ActivationQueryObject::run(): unknown exception" << endl;
100+ errlog << "ActivationQueryObject::run(): unknown exception";
101 }
102 }
103
104
105=== modified file 'src/scopes/internal/AnnotationImpl.cpp'
106--- src/scopes/internal/AnnotationImpl.cpp 2014-02-27 16:58:50 +0000
107+++ src/scopes/internal/AnnotationImpl.cpp 2014-03-06 09:05:05 +0000
108@@ -16,9 +16,9 @@
109 */
110
111 #include <unity/scopes/internal/AnnotationImpl.h>
112+#include <unity/scopes/internal/Logging.h>
113 #include <unity/UnityExceptions.h>
114 #include <sstream>
115-#include <iostream>
116 #include <cassert>
117
118 namespace unity
119@@ -85,7 +85,7 @@
120 {
121 if (annotation_type_ != Annotation::Type::GroupedLink)
122 {
123- std::cerr << "Annotation::set_label(): label is allowed in GroupedLink only" << std::endl;
124+ errlog << "Annotation::set_label(): label is allowed in GroupedLink only";
125 }
126 label_ = label;
127 }
128@@ -94,7 +94,7 @@
129 {
130 if (annotation_type_ != Annotation::Type::Link)
131 {
132- std::cerr << "Annotation::set_icon(): icon is allowed in Link annotations only" << std::endl;
133+ errlog << "Annotation::set_icon(): icon is allowed in Link annotations only";
134 }
135 icon_ = icon;
136 }
137@@ -112,7 +112,7 @@
138 {
139 if (annotation_type_ != Annotation::Type::GroupedLink)
140 {
141- std::cerr << "Annotation::label(): label is allowed in GroupedLink only" << std::endl;
142+ errlog << "Annotation::label(): label is allowed in GroupedLink only";
143 }
144 return label_;
145 }
146@@ -121,7 +121,7 @@
147 {
148 if (annotation_type_ != Annotation::Type::Link)
149 {
150- std::cerr << "Annotation::icon(): icon is allowed in Link annotations only" << std::endl;
151+ errlog << "Annotation::icon(): icon is allowed in Link annotations only";
152 }
153 return icon_;
154 }
155
156=== modified file 'src/scopes/internal/CMakeLists.txt'
157--- src/scopes/internal/CMakeLists.txt 2014-03-04 05:54:24 +0000
158+++ src/scopes/internal/CMakeLists.txt 2014-03-06 09:05:05 +0000
159@@ -25,6 +25,7 @@
160 ${CMAKE_CURRENT_SOURCE_DIR}/FilterStateImpl.cpp
161 ${CMAKE_CURRENT_SOURCE_DIR}/JsonCppNode.cpp
162 ${CMAKE_CURRENT_SOURCE_DIR}/LinkImpl.cpp
163+ ${CMAKE_CURRENT_SOURCE_DIR}/Logging.cpp
164 ${CMAKE_CURRENT_SOURCE_DIR}/MiddlewareBase.cpp
165 ${CMAKE_CURRENT_SOURCE_DIR}/MiddlewareFactory.cpp
166 ${CMAKE_CURRENT_SOURCE_DIR}/MWObject.cpp
167
168=== added file 'src/scopes/internal/Logging.cpp'
169--- src/scopes/internal/Logging.cpp 1970-01-01 00:00:00 +0000
170+++ src/scopes/internal/Logging.cpp 2014-03-06 09:05:05 +0000
171@@ -0,0 +1,119 @@
172+/*
173+ * Copyright (C) 2014 Canonical Ltd
174+ *
175+ * This program is free software: you can redistribute it and/or modify
176+ * it under the terms of the GNU Lesser General Public License version 3 as
177+ * published by the Free Software Foundation.
178+ *
179+ * This program is distributed in the hope that it will be useful,
180+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
181+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
182+ * GNU Lesser General Public License for more details.
183+ *
184+ * You should have received a copy of the GNU Lesser General Public License
185+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
186+ *
187+ * Authored by: Jussi Pakkanen <jussi.pakkanen@canonical.com>
188+ */
189+
190+#include <unity/scopes/internal/Logging.h>
191+#include <mutex>
192+#include <iostream>
193+
194+namespace unity
195+{
196+
197+namespace scopes
198+{
199+
200+namespace internal
201+{
202+
203+static std::mutex print_mutex;
204+
205+LogStream errlog;
206+
207+LogStream::LogStream() {
208+
209+}
210+
211+LogGatherer LogStream::operator<<(const std::string &s)
212+{
213+ LogGatherer l;
214+ l << s;
215+ return l;
216+}
217+
218+LogGatherer LogStream::operator<<(const int i)
219+{
220+ LogGatherer l;
221+ l << i;
222+ return l;
223+}
224+
225+LogGatherer LogStream::operator<<(const bool i)
226+{
227+ LogGatherer l;
228+ l << i;
229+ return l;
230+}
231+
232+LogGatherer LogStream::operator<<(const char *msg) {
233+ LogGatherer l;
234+ l << msg;
235+ return l;
236+}
237+
238+LogGatherer::LogGatherer()
239+{
240+
241+}
242+
243+LogGatherer::~LogGatherer()
244+{
245+ std::unique_lock<std::mutex> l(print_mutex);
246+ if(strings.empty())
247+ return;
248+ try
249+ {
250+ for(const auto &i : strings)
251+ {
252+ std::cerr << i;
253+ }
254+ const std::string &last = strings.back();
255+ if(last.empty() or last.back() != '\n')
256+ {
257+ std::cerr << std::endl;
258+ }
259+ } catch(...) {
260+ // There's not much we can do in this case.
261+ }
262+}
263+
264+LogGatherer& LogGatherer::operator<<(const std::string &s)
265+{
266+ strings.push_back(s);
267+ return *this;
268+}
269+
270+LogGatherer& LogGatherer::operator<<(const int i)
271+{
272+ return *this << std::to_string(i);
273+}
274+
275+LogGatherer& LogGatherer::operator<<(const bool i)
276+{
277+ std::string val(i ? "true" : "false");
278+ return *this << val;
279+}
280+
281+LogGatherer& LogGatherer::operator<<(const char *msg) {
282+ strings.emplace_back(msg);
283+ return *this;
284+}
285+
286+} // namespace internal
287+
288+} // namespace scopes
289+
290+} // namespace unity
291
292=== modified file 'src/scopes/internal/PreviewQueryObject.cpp'
293--- src/scopes/internal/PreviewQueryObject.cpp 2014-03-04 03:15:11 +0000
294+++ src/scopes/internal/PreviewQueryObject.cpp 2014-03-06 09:05:05 +0000
295@@ -16,6 +16,7 @@
296 * Authored by: Michal Hruby <michal.hruby@canonical.com>
297 */
298
299+#include <unity/scopes/internal/Logging.h>
300 #include <unity/scopes/internal/MWQueryCtrl.h>
301 #include <unity/scopes/internal/MWReply.h>
302 #include <unity/scopes/internal/PreviewQueryObject.h>
303@@ -25,8 +26,9 @@
304 #include <unity/scopes/ListenerBase.h>
305 #include <unity/scopes/QueryBase.h>
306 #include <unity/scopes/ReplyProxyFwd.h>
307+#include <unity/scopes/SearchReply.h>
308+#include <unity/scopes/PreviewReply.h>
309
310-#include <iostream>
311 #include <cassert>
312
313 using namespace std;
314@@ -79,13 +81,13 @@
315 pushable_ = false;
316 // TODO: log error
317 reply_->finished(ListenerBase::Error, e.what()); // Oneway, can't block
318- cerr << "PreviewQueryObject::run(): " << e.what() << endl;
319+ errlog << "PreviewQueryObject::run(): " << e.what();
320 }
321 catch (...)
322 {
323 // TODO: log error
324 reply_->finished(ListenerBase::Error, "unknown exception"); // Oneway, can't block
325- cerr << "PreviewQueryObject::run(): unknown exception" << endl;
326+ errlog << "PreviewQueryObject::run(): unknown exception";
327 }
328 }
329
330
331=== modified file 'src/scopes/internal/QueryBaseImpl.cpp'
332--- src/scopes/internal/QueryBaseImpl.cpp 2014-02-27 23:00:59 +0000
333+++ src/scopes/internal/QueryBaseImpl.cpp 2014-03-06 09:05:05 +0000
334@@ -17,12 +17,12 @@
335 */
336
337 #include <unity/scopes/internal/QueryBaseImpl.h>
338+#include <unity/scopes/internal/Logging.h>
339
340 #include <unity/scopes/QueryCtrl.h>
341 #include <unity/scopes/Scope.h>
342 #include <unity/scopes/SearchMetadata.h>
343
344-#include <iostream>
345 #include <cassert>
346
347 using namespace std;
348@@ -105,7 +105,7 @@
349 catch (std::bad_cast const& e) // this shouldn't really happen, if it does, that's a bug
350 {
351 // TODO: log this
352- std::cerr << "QueryBaseImpl()::set_metadata(): " << e.what() << std::endl;
353+ errlog << "QueryBaseImpl()::set_metadata(): " << e.what();
354 throw;
355 }
356 }
357
358=== modified file 'src/scopes/internal/QueryCtrlImpl.cpp'
359--- src/scopes/internal/QueryCtrlImpl.cpp 2014-01-23 11:28:34 +0000
360+++ src/scopes/internal/QueryCtrlImpl.cpp 2014-03-06 09:05:05 +0000
361@@ -18,6 +18,7 @@
362
363 #include <unity/scopes/internal/QueryCtrlImpl.h>
364
365+#include <unity/scopes/internal/Logging.h>
366 #include <unity/scopes/internal/MiddlewareBase.h>
367 #include <unity/scopes/internal/MWQueryCtrl.h>
368 #include <unity/scopes/internal/MWReply.h>
369@@ -26,7 +27,6 @@
370 #include <unity/scopes/ScopeExceptions.h>
371
372 #include <cassert>
373-#include <iostream> // TODO: remove this once logging is added
374
375 using namespace std;
376
377@@ -67,7 +67,7 @@
378 }
379 catch (std::exception const& e)
380 {
381- cerr << e.what() << endl;
382+ errlog << e.what();
383 // TODO: log error
384 }
385 }
386
387=== modified file 'src/scopes/internal/QueryObject.cpp'
388--- src/scopes/internal/QueryObject.cpp 2014-03-04 03:15:11 +0000
389+++ src/scopes/internal/QueryObject.cpp 2014-03-06 09:05:05 +0000
390@@ -18,6 +18,7 @@
391
392 #include <unity/scopes/internal/QueryObject.h>
393
394+#include <unity/scopes/internal/Logging.h>
395 #include <unity/Exception.h>
396 #include <unity/scopes/ActivationQueryBase.h>
397 #include <unity/scopes/internal/MWQueryCtrl.h>
398@@ -29,7 +30,6 @@
399 #include <unity/scopes/QueryBase.h>
400 #include <unity/scopes/SearchQueryBase.h>
401
402-#include <iostream>
403 #include <cassert>
404
405 using namespace std;
406@@ -116,14 +116,14 @@
407 pushable_ = false;
408 // TODO: log error
409 reply_->finished(ListenerBase::Error, e.what()); // Oneway, can't block
410- cerr << "ScopeBase::run(): " << e.what() << endl;
411+ errlog << "ScopeBase::run(): " << e.what();
412 }
413 catch (...)
414 {
415 pushable_ = false;
416 // TODO: log error
417 reply_->finished(ListenerBase::Error, "unknown exception"); // Oneway, can't block
418- cerr << "ScopeBase::run(): unknown exception" << endl;
419+ errlog << "ScopeBase::run(): unknown exception";
420 }
421 }
422
423
424=== modified file 'src/scopes/internal/ReplyImpl.cpp'
425--- src/scopes/internal/ReplyImpl.cpp 2014-03-04 06:26:21 +0000
426+++ src/scopes/internal/ReplyImpl.cpp 2014-03-06 09:05:05 +0000
427@@ -16,6 +16,7 @@
428 * Authored by: Michi Henning <michi.henning@canonical.com>
429 */
430
431+#include <unity/scopes/internal/Logging.h>
432 #include <unity/scopes/internal/ReplyImpl.h>
433
434 #include <unity/scopes/Annotation.h>
435@@ -37,7 +38,7 @@
436
437 #include <cassert>
438 #include <sstream>
439-#include <iostream> // TODO: remove this once logging is added
440+#include <cassert>
441
442 using namespace std;
443
444@@ -262,7 +263,7 @@
445 catch (std::exception const& e)
446 {
447 // TODO: log error
448- cerr << e.what() << endl;
449+ errlog << e.what();
450 }
451 }
452 }
453@@ -290,7 +291,7 @@
454 error_message = "unknown exception";
455 }
456 // TODO: log error
457- cerr << error_message << endl;
458+ errlog << error_message;
459
460 try
461 {
462@@ -299,7 +300,7 @@
463 catch (std::exception const& e)
464 {
465 // TODO: log error
466- cerr << e.what() << endl;
467+ errlog << e.what();
468 }
469 }
470
471
472=== modified file 'src/scopes/internal/ReplyObject.cpp'
473--- src/scopes/internal/ReplyObject.cpp 2014-02-24 05:04:11 +0000
474+++ src/scopes/internal/ReplyObject.cpp 2014-03-06 09:05:05 +0000
475@@ -16,6 +16,7 @@
476 * Authored by: Michi Henning <michi.henning@canonical.com>
477 */
478
479+#include <unity/scopes/internal/Logging.h>
480 #include <unity/scopes/internal/ReplyObject.h>
481 #include <unity/scopes/internal/ResultReplyObject.h>
482 #include <unity/scopes/internal/PreviewReplyObject.h>
483@@ -27,7 +28,6 @@
484 #include <unity/scopes/internal/CategorisedResultImpl.h>
485
486 #include <cassert>
487-#include <iostream> // TODO: remove this once logging is added
488
489 using namespace std;
490 using namespace unity::scopes::internal;
491@@ -50,8 +50,8 @@
492 assert(receiver_base);
493 assert(runtime);
494 reap_item_ = runtime->reply_reaper()->add([this] {
495- cerr << "No activity on ReplyObject for scope " << this->origin_proxy_
496- << ": ReplyObject destroyed" << endl;
497+ errlog << "No activity on ReplyObject for scope " << this->origin_proxy_
498+ << ": ReplyObject destroyed";
499 this->disconnect();
500 });
501 }
502@@ -162,12 +162,12 @@
503 }
504 catch (std::exception const& e)
505 {
506- cerr << "ReplyObject::finished(): " << e.what() << endl;
507+ errlog << "ReplyObject::finished(): " << e.what();
508 // TODO: log error
509 }
510 catch (...)
511 {
512- cerr << "ReplyObject::finished(): unknown exception" << endl;
513+ errlog << "ReplyObject::finished(): unknown exception";
514 // TODO: log error
515 }
516 }
517
518=== modified file 'src/scopes/internal/RuntimeImpl.cpp'
519--- src/scopes/internal/RuntimeImpl.cpp 2014-02-21 05:12:05 +0000
520+++ src/scopes/internal/RuntimeImpl.cpp 2014-03-06 09:05:05 +0000
521@@ -19,6 +19,7 @@
522 #include <unity/scopes/internal/RuntimeImpl.h>
523
524 #include <unity/scopes/internal/DfltConfig.h>
525+#include <unity/scopes/internal/Logging.h>
526 #include <unity/scopes/internal/RegistryConfig.h>
527 #include <unity/scopes/internal/RegistryImpl.h>
528 #include <unity/scopes/internal/RuntimeConfig.h>
529@@ -30,7 +31,6 @@
530
531 #include <cassert>
532 #include <future>
533-#include <iostream> // TODO: remove this once logging is added
534
535
536 using namespace std;
537@@ -72,7 +72,7 @@
538
539 if (registry_configfile_.empty() || registry_identity_.empty())
540 {
541- cerr << "Warning: no registry configured" << endl;
542+ errlog << "Warning: no registry configured";
543 registry_identity_ = "";
544 }
545 else
546@@ -100,12 +100,12 @@
547 }
548 catch (std::exception const& e) // LCOV_EXCL_LINE
549 {
550- cerr << "~RuntimeImpl(): " << e.what() << endl;
551+ errlog << "~RuntimeImpl(): " << e.what();
552 // TODO: log error
553 }
554 catch (...) // LCOV_EXCL_LINE
555 {
556- cerr << "~RuntimeImpl(): unknown exception" << endl;
557+ errlog << "~RuntimeImpl(): unknown exception";
558 // TODO: log error
559 }
560 }
561
562=== modified file 'src/scopes/internal/ScopeImpl.cpp'
563--- src/scopes/internal/ScopeImpl.cpp 2014-02-27 23:00:59 +0000
564+++ src/scopes/internal/ScopeImpl.cpp 2014-03-06 09:05:05 +0000
565@@ -18,6 +18,7 @@
566
567 #include <unity/scopes/internal/ScopeImpl.h>
568
569+#include <unity/scopes/internal/Logging.h>
570 #include <unity/scopes/internal/ResultImpl.h>
571 #include <unity/scopes/internal/MiddlewareBase.h>
572 #include <unity/scopes/internal/MWScope.h>
573@@ -33,7 +34,6 @@
574 #include <unity/scopes/internal/PreviewReplyObject.h>
575
576 #include <cassert>
577-#include <iostream> // TODO: remove this once logging is added
578
579 using namespace std;
580
581@@ -134,7 +134,7 @@
582 catch (std::exception const& e)
583 {
584 // TODO: log error
585- cerr << "activate(): " << e.what() << endl;
586+ errlog << "activate(): " << e.what();
587 try
588 {
589 ro->finished(ListenerBase::Error, e.what());
590@@ -142,7 +142,7 @@
591 }
592 catch (...)
593 {
594- cerr << "activate(): unknown exception" << endl;
595+ errlog << "activate(): unknown exception";
596 }
597 throw;
598 }
599@@ -172,7 +172,7 @@
600 catch (std::exception const& e)
601 {
602 // TODO: log error
603- cerr << "perform_action(): " << e.what() << endl;
604+ errlog << "perform_action(): " << e.what();
605 try
606 {
607 // TODO: if things go wrong, we need to make sure that the reply object
608@@ -182,7 +182,7 @@
609 }
610 catch (...)
611 {
612- cerr << "perform_action(): unknown exception" << endl;
613+ errlog << "perform_action(): unknown exception";
614 }
615 throw;
616 }
617@@ -216,7 +216,7 @@
618 catch (std::exception const& e)
619 {
620 // TODO: log error
621- cerr << "preview(): " << e.what() << endl;
622+ errlog << "preview(): " << e.what();
623 try
624 {
625 ro->finished(ListenerBase::Error, e.what());
626@@ -224,7 +224,7 @@
627 }
628 catch (...)
629 {
630- cerr << "preview(): unknown exception" << endl;
631+ errlog << "preview(): unknown exception";
632 }
633 throw;
634 }
635
636=== modified file 'src/scopes/internal/ScopeObject.cpp'
637--- src/scopes/internal/ScopeObject.cpp 2014-02-27 23:29:10 +0000
638+++ src/scopes/internal/ScopeObject.cpp 2014-03-06 09:05:05 +0000
639@@ -19,6 +19,7 @@
640 #include <unity/scopes/internal/ScopeObject.h>
641
642 #include <unity/scopes/internal/ActivationQueryObject.h>
643+#include <unity/scopes/internal/Logging.h>
644 #include <unity/scopes/internal/MWQuery.h>
645 #include <unity/scopes/internal/MWReply.h>
646 #include <unity/scopes/internal/PreviewQueryObject.h>
647@@ -29,7 +30,6 @@
648 #include <unity/UnityExceptions.h>
649
650 #include <cassert>
651-#include <iostream> // TODO: remove this once logging is added
652 #include <sstream>
653
654 using namespace std;
655@@ -122,7 +122,7 @@
656 catch (...)
657 {
658 }
659- cerr << "query(): " << e.what() << endl;
660+ errlog << "query(): " << e.what();
661 // TODO: log error
662 throw;
663 }
664@@ -135,7 +135,7 @@
665 catch (...)
666 {
667 }
668- cerr << "query(): unknown exception" << endl;
669+ errlog << "query(): unknown exception";
670 // TODO: log error
671 throw;
672 }
673
674=== modified file 'test/gtest/scopes/internal/CMakeLists.txt'
675--- test/gtest/scopes/internal/CMakeLists.txt 2014-02-24 14:56:26 +0000
676+++ test/gtest/scopes/internal/CMakeLists.txt 2014-03-06 09:05:05 +0000
677@@ -3,6 +3,7 @@
678 add_subdirectory(DynamicLoader)
679 add_subdirectory(JsonNode)
680 add_subdirectory(lttng)
681+add_subdirectory(Logging)
682 add_subdirectory(MiddlewareFactory)
683 add_subdirectory(Reaper)
684 add_subdirectory(RegistryConfig)
685
686=== added directory 'test/gtest/scopes/internal/Logging'
687=== added file 'test/gtest/scopes/internal/Logging/CMakeLists.txt'
688--- test/gtest/scopes/internal/Logging/CMakeLists.txt 1970-01-01 00:00:00 +0000
689+++ test/gtest/scopes/internal/Logging/CMakeLists.txt 2014-03-06 09:05:05 +0000
690@@ -0,0 +1,14 @@
691+add_executable(
692+ Logging_test
693+ Logging_test.cpp
694+)
695+
696+target_link_libraries(
697+ Logging_test
698+ ${TESTLIBS}
699+)
700+
701+add_test(
702+ Logging
703+ Logging_test
704+)
705
706=== added file 'test/gtest/scopes/internal/Logging/Logging_test.cpp'
707--- test/gtest/scopes/internal/Logging/Logging_test.cpp 1970-01-01 00:00:00 +0000
708+++ test/gtest/scopes/internal/Logging/Logging_test.cpp 2014-03-06 09:05:05 +0000
709@@ -0,0 +1,53 @@
710+/*
711+ * Copyright © 2014 Canonical Ltd.
712+ *
713+ * This program is free software: you can redistribute it and/or modify it
714+ * under the terms of the GNU Lesser General Public License version 3,
715+ * as published by the Free Software Foundation.
716+ *
717+ * This program is distributed in the hope that it will be useful,
718+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
719+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
720+ * GNU Lesser General Public License for more details.
721+ *
722+ * You should have received a copy of the GNU Lesser General Public License
723+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
724+ *
725+ * Authored by: Jussi Pakkanen <jussi.pakkanen@canonical.com>
726+ */
727+
728+#include <unity/scopes/internal/Logging.h>
729+#include <unity/UnityExceptions.h>
730+#include <unity/scopes/Variant.h>
731+
732+#include <gtest/gtest.h>
733+#include <memory>
734+#include <algorithm>
735+
736+using namespace testing;
737+using unity::scopes::internal::errlog;
738+
739+namespace
740+{
741+
742+class LoggingTest : public Test
743+{
744+public:
745+ LoggingTest()
746+ {
747+ }
748+
749+};
750+
751+TEST_F(LoggingTest, basic)
752+{
753+ std::string msg("Second message to stderr.");
754+ errlog << "First message to stderr.";
755+ errlog << msg;
756+ errlog << "Piecewise " << "message " << "to stderr.\n";
757+ errlog << 1 << " is the loneliest number. Not " << 2 << ".\n";
758+ errlog << "True is " << true << " and False is " << false << ".";
759+}
760+
761+
762+} // namespace

Subscribers

People subscribed via source and target branches

to all changes: