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
=== added file 'include/unity/scopes/internal/Logging.h'
--- include/unity/scopes/internal/Logging.h 1970-01-01 00:00:00 +0000
+++ include/unity/scopes/internal/Logging.h 2014-03-06 09:05:05 +0000
@@ -0,0 +1,70 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Jussi Pakkanen <jussi.pakkanen@canonical.com>
17 */
18
19#ifndef UNITY_SCOPES_INTERNAL_LOGGING_H
20#define UNITY_SCOPES_INTERNAL_LOGGING_H
21
22#include <string>
23#include <vector>
24#include <unity/util/NonCopyable.h>
25
26namespace unity
27{
28
29namespace scopes
30{
31
32namespace internal
33{
34
35class LogGatherer;
36
37class LogStream final {
38 NONCOPYABLE(LogStream);
39public:
40 LogStream();
41 LogGatherer operator<<(const std::string &s);
42 LogGatherer operator<<(const int i);
43 LogGatherer operator<<(const char *msg);
44 LogGatherer operator<<(const bool i);
45};
46
47class LogGatherer final {
48
49public:
50
51 LogGatherer();
52 ~LogGatherer();
53 LogGatherer& operator<<(const std::string &s);
54 LogGatherer& operator<<(const int i);
55 LogGatherer& operator<<(const bool i);
56 LogGatherer& operator<<(const char *msg);
57
58private:
59 std::vector<std::string> strings;
60};
61
62extern LogStream errlog;
63
64} // namespace internal
65
66} // namespace scopes
67
68} // namespace unity
69
70#endif
071
=== modified file 'src/scopes/internal/ActivationQueryObject.cpp'
--- src/scopes/internal/ActivationQueryObject.cpp 2014-02-27 23:29:10 +0000
+++ src/scopes/internal/ActivationQueryObject.cpp 2014-03-06 09:05:05 +0000
@@ -21,7 +21,7 @@
21#include <unity/scopes/ActivationQueryBase.h>21#include <unity/scopes/ActivationQueryBase.h>
22#include <unity/scopes/internal/MWReply.h>22#include <unity/scopes/internal/MWReply.h>
23#include <unity/scopes/internal/MWQueryCtrl.h>23#include <unity/scopes/internal/MWQueryCtrl.h>
24#include <iostream>24#include <unity/scopes/internal/Logging.h>
25#include <cassert>25#include <cassert>
2626
27using namespace std;27using namespace std;
@@ -69,13 +69,13 @@
69 {69 {
70 // TODO: log error70 // TODO: log error
71 reply_->finished(ListenerBase::Error, e.what()); // Oneway, can't block71 reply_->finished(ListenerBase::Error, e.what()); // Oneway, can't block
72 cerr << "ActivationQueryObject::run(): " << e.what() << endl;72 errlog << "ActivationQueryObject::run(): " << e.what();
73 }73 }
74 catch (...)74 catch (...)
75 {75 {
76 // TODO: log error76 // TODO: log error
77 reply_->finished(ListenerBase::Error, "unknown exception"); // Oneway, can't block77 reply_->finished(ListenerBase::Error, "unknown exception"); // Oneway, can't block
78 cerr << "ActivationQueryObject::run(): unknown exception" << endl;78 errlog << "ActivationQueryObject::run(): unknown exception";
79 }79 }
80}80}
8181
8282
=== modified file 'src/scopes/internal/AnnotationImpl.cpp'
--- src/scopes/internal/AnnotationImpl.cpp 2014-02-27 16:58:50 +0000
+++ src/scopes/internal/AnnotationImpl.cpp 2014-03-06 09:05:05 +0000
@@ -16,9 +16,9 @@
16 */16 */
1717
18#include <unity/scopes/internal/AnnotationImpl.h>18#include <unity/scopes/internal/AnnotationImpl.h>
19#include <unity/scopes/internal/Logging.h>
19#include <unity/UnityExceptions.h>20#include <unity/UnityExceptions.h>
20#include <sstream>21#include <sstream>
21#include <iostream>
22#include <cassert>22#include <cassert>
2323
24namespace unity24namespace unity
@@ -85,7 +85,7 @@
85{85{
86 if (annotation_type_ != Annotation::Type::GroupedLink)86 if (annotation_type_ != Annotation::Type::GroupedLink)
87 {87 {
88 std::cerr << "Annotation::set_label(): label is allowed in GroupedLink only" << std::endl;88 errlog << "Annotation::set_label(): label is allowed in GroupedLink only";
89 }89 }
90 label_ = label;90 label_ = label;
91}91}
@@ -94,7 +94,7 @@
94{94{
95 if (annotation_type_ != Annotation::Type::Link)95 if (annotation_type_ != Annotation::Type::Link)
96 {96 {
97 std::cerr << "Annotation::set_icon(): icon is allowed in Link annotations only" << std::endl;97 errlog << "Annotation::set_icon(): icon is allowed in Link annotations only";
98 }98 }
99 icon_ = icon;99 icon_ = icon;
100}100}
@@ -112,7 +112,7 @@
112{112{
113 if (annotation_type_ != Annotation::Type::GroupedLink)113 if (annotation_type_ != Annotation::Type::GroupedLink)
114 {114 {
115 std::cerr << "Annotation::label(): label is allowed in GroupedLink only" << std::endl;115 errlog << "Annotation::label(): label is allowed in GroupedLink only";
116 }116 }
117 return label_;117 return label_;
118}118}
@@ -121,7 +121,7 @@
121{121{
122 if (annotation_type_ != Annotation::Type::Link)122 if (annotation_type_ != Annotation::Type::Link)
123 {123 {
124 std::cerr << "Annotation::icon(): icon is allowed in Link annotations only" << std::endl;124 errlog << "Annotation::icon(): icon is allowed in Link annotations only";
125 }125 }
126 return icon_;126 return icon_;
127}127}
128128
=== modified file 'src/scopes/internal/CMakeLists.txt'
--- src/scopes/internal/CMakeLists.txt 2014-03-04 05:54:24 +0000
+++ src/scopes/internal/CMakeLists.txt 2014-03-06 09:05:05 +0000
@@ -25,6 +25,7 @@
25 ${CMAKE_CURRENT_SOURCE_DIR}/FilterStateImpl.cpp25 ${CMAKE_CURRENT_SOURCE_DIR}/FilterStateImpl.cpp
26 ${CMAKE_CURRENT_SOURCE_DIR}/JsonCppNode.cpp26 ${CMAKE_CURRENT_SOURCE_DIR}/JsonCppNode.cpp
27 ${CMAKE_CURRENT_SOURCE_DIR}/LinkImpl.cpp27 ${CMAKE_CURRENT_SOURCE_DIR}/LinkImpl.cpp
28 ${CMAKE_CURRENT_SOURCE_DIR}/Logging.cpp
28 ${CMAKE_CURRENT_SOURCE_DIR}/MiddlewareBase.cpp29 ${CMAKE_CURRENT_SOURCE_DIR}/MiddlewareBase.cpp
29 ${CMAKE_CURRENT_SOURCE_DIR}/MiddlewareFactory.cpp30 ${CMAKE_CURRENT_SOURCE_DIR}/MiddlewareFactory.cpp
30 ${CMAKE_CURRENT_SOURCE_DIR}/MWObject.cpp31 ${CMAKE_CURRENT_SOURCE_DIR}/MWObject.cpp
3132
=== added file 'src/scopes/internal/Logging.cpp'
--- src/scopes/internal/Logging.cpp 1970-01-01 00:00:00 +0000
+++ src/scopes/internal/Logging.cpp 2014-03-06 09:05:05 +0000
@@ -0,0 +1,119 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Jussi Pakkanen <jussi.pakkanen@canonical.com>
17 */
18
19#include <unity/scopes/internal/Logging.h>
20#include <mutex>
21#include <iostream>
22
23namespace unity
24{
25
26namespace scopes
27{
28
29namespace internal
30{
31
32static std::mutex print_mutex;
33
34LogStream errlog;
35
36LogStream::LogStream() {
37
38}
39
40LogGatherer LogStream::operator<<(const std::string &s)
41{
42 LogGatherer l;
43 l << s;
44 return l;
45}
46
47LogGatherer LogStream::operator<<(const int i)
48{
49 LogGatherer l;
50 l << i;
51 return l;
52}
53
54LogGatherer LogStream::operator<<(const bool i)
55{
56 LogGatherer l;
57 l << i;
58 return l;
59}
60
61LogGatherer LogStream::operator<<(const char *msg) {
62 LogGatherer l;
63 l << msg;
64 return l;
65}
66
67LogGatherer::LogGatherer()
68{
69
70}
71
72LogGatherer::~LogGatherer()
73{
74 std::unique_lock<std::mutex> l(print_mutex);
75 if(strings.empty())
76 return;
77 try
78 {
79 for(const auto &i : strings)
80 {
81 std::cerr << i;
82 }
83 const std::string &last = strings.back();
84 if(last.empty() or last.back() != '\n')
85 {
86 std::cerr << std::endl;
87 }
88 } catch(...) {
89 // There's not much we can do in this case.
90 }
91}
92
93LogGatherer& LogGatherer::operator<<(const std::string &s)
94{
95 strings.push_back(s);
96 return *this;
97}
98
99LogGatherer& LogGatherer::operator<<(const int i)
100{
101 return *this << std::to_string(i);
102}
103
104LogGatherer& LogGatherer::operator<<(const bool i)
105{
106 std::string val(i ? "true" : "false");
107 return *this << val;
108}
109
110LogGatherer& LogGatherer::operator<<(const char *msg) {
111 strings.emplace_back(msg);
112 return *this;
113}
114
115} // namespace internal
116
117} // namespace scopes
118
119} // namespace unity
0120
=== modified file 'src/scopes/internal/PreviewQueryObject.cpp'
--- src/scopes/internal/PreviewQueryObject.cpp 2014-03-04 03:15:11 +0000
+++ src/scopes/internal/PreviewQueryObject.cpp 2014-03-06 09:05:05 +0000
@@ -16,6 +16,7 @@
16 * Authored by: Michal Hruby <michal.hruby@canonical.com>16 * Authored by: Michal Hruby <michal.hruby@canonical.com>
17*/17*/
1818
19#include <unity/scopes/internal/Logging.h>
19#include <unity/scopes/internal/MWQueryCtrl.h>20#include <unity/scopes/internal/MWQueryCtrl.h>
20#include <unity/scopes/internal/MWReply.h>21#include <unity/scopes/internal/MWReply.h>
21#include <unity/scopes/internal/PreviewQueryObject.h>22#include <unity/scopes/internal/PreviewQueryObject.h>
@@ -25,8 +26,9 @@
25#include <unity/scopes/ListenerBase.h>26#include <unity/scopes/ListenerBase.h>
26#include <unity/scopes/QueryBase.h>27#include <unity/scopes/QueryBase.h>
27#include <unity/scopes/ReplyProxyFwd.h>28#include <unity/scopes/ReplyProxyFwd.h>
29#include <unity/scopes/SearchReply.h>
30#include <unity/scopes/PreviewReply.h>
2831
29#include <iostream>
30#include <cassert>32#include <cassert>
3133
32using namespace std;34using namespace std;
@@ -79,13 +81,13 @@
79 pushable_ = false;81 pushable_ = false;
80 // TODO: log error82 // TODO: log error
81 reply_->finished(ListenerBase::Error, e.what()); // Oneway, can't block83 reply_->finished(ListenerBase::Error, e.what()); // Oneway, can't block
82 cerr << "PreviewQueryObject::run(): " << e.what() << endl;84 errlog << "PreviewQueryObject::run(): " << e.what();
83 }85 }
84 catch (...)86 catch (...)
85 {87 {
86 // TODO: log error88 // TODO: log error
87 reply_->finished(ListenerBase::Error, "unknown exception"); // Oneway, can't block89 reply_->finished(ListenerBase::Error, "unknown exception"); // Oneway, can't block
88 cerr << "PreviewQueryObject::run(): unknown exception" << endl;90 errlog << "PreviewQueryObject::run(): unknown exception";
89 }91 }
90}92}
9193
9294
=== modified file 'src/scopes/internal/QueryBaseImpl.cpp'
--- src/scopes/internal/QueryBaseImpl.cpp 2014-02-27 23:00:59 +0000
+++ src/scopes/internal/QueryBaseImpl.cpp 2014-03-06 09:05:05 +0000
@@ -17,12 +17,12 @@
17 */17 */
1818
19#include <unity/scopes/internal/QueryBaseImpl.h>19#include <unity/scopes/internal/QueryBaseImpl.h>
20#include <unity/scopes/internal/Logging.h>
2021
21#include <unity/scopes/QueryCtrl.h>22#include <unity/scopes/QueryCtrl.h>
22#include <unity/scopes/Scope.h>23#include <unity/scopes/Scope.h>
23#include <unity/scopes/SearchMetadata.h>24#include <unity/scopes/SearchMetadata.h>
2425
25#include <iostream>
26#include <cassert>26#include <cassert>
2727
28using namespace std;28using namespace std;
@@ -105,7 +105,7 @@
105 catch (std::bad_cast const& e) // this shouldn't really happen, if it does, that's a bug105 catch (std::bad_cast const& e) // this shouldn't really happen, if it does, that's a bug
106 {106 {
107 // TODO: log this107 // TODO: log this
108 std::cerr << "QueryBaseImpl()::set_metadata(): " << e.what() << std::endl;108 errlog << "QueryBaseImpl()::set_metadata(): " << e.what();
109 throw;109 throw;
110 }110 }
111}111}
112112
=== modified file 'src/scopes/internal/QueryCtrlImpl.cpp'
--- src/scopes/internal/QueryCtrlImpl.cpp 2014-01-23 11:28:34 +0000
+++ src/scopes/internal/QueryCtrlImpl.cpp 2014-03-06 09:05:05 +0000
@@ -18,6 +18,7 @@
1818
19#include <unity/scopes/internal/QueryCtrlImpl.h>19#include <unity/scopes/internal/QueryCtrlImpl.h>
2020
21#include <unity/scopes/internal/Logging.h>
21#include <unity/scopes/internal/MiddlewareBase.h>22#include <unity/scopes/internal/MiddlewareBase.h>
22#include <unity/scopes/internal/MWQueryCtrl.h>23#include <unity/scopes/internal/MWQueryCtrl.h>
23#include <unity/scopes/internal/MWReply.h>24#include <unity/scopes/internal/MWReply.h>
@@ -26,7 +27,6 @@
26#include <unity/scopes/ScopeExceptions.h>27#include <unity/scopes/ScopeExceptions.h>
2728
28#include <cassert>29#include <cassert>
29#include <iostream> // TODO: remove this once logging is added
3030
31using namespace std;31using namespace std;
3232
@@ -67,7 +67,7 @@
67 }67 }
68 catch (std::exception const& e)68 catch (std::exception const& e)
69 {69 {
70 cerr << e.what() << endl;70 errlog << e.what();
71 // TODO: log error71 // TODO: log error
72 }72 }
73}73}
7474
=== modified file 'src/scopes/internal/QueryObject.cpp'
--- src/scopes/internal/QueryObject.cpp 2014-03-04 03:15:11 +0000
+++ src/scopes/internal/QueryObject.cpp 2014-03-06 09:05:05 +0000
@@ -18,6 +18,7 @@
1818
19#include <unity/scopes/internal/QueryObject.h>19#include <unity/scopes/internal/QueryObject.h>
2020
21#include <unity/scopes/internal/Logging.h>
21#include <unity/Exception.h>22#include <unity/Exception.h>
22#include <unity/scopes/ActivationQueryBase.h>23#include <unity/scopes/ActivationQueryBase.h>
23#include <unity/scopes/internal/MWQueryCtrl.h>24#include <unity/scopes/internal/MWQueryCtrl.h>
@@ -29,7 +30,6 @@
29#include <unity/scopes/QueryBase.h>30#include <unity/scopes/QueryBase.h>
30#include <unity/scopes/SearchQueryBase.h>31#include <unity/scopes/SearchQueryBase.h>
3132
32#include <iostream>
33#include <cassert>33#include <cassert>
3434
35using namespace std;35using namespace std;
@@ -116,14 +116,14 @@
116 pushable_ = false;116 pushable_ = false;
117 // TODO: log error117 // TODO: log error
118 reply_->finished(ListenerBase::Error, e.what()); // Oneway, can't block118 reply_->finished(ListenerBase::Error, e.what()); // Oneway, can't block
119 cerr << "ScopeBase::run(): " << e.what() << endl;119 errlog << "ScopeBase::run(): " << e.what();
120 }120 }
121 catch (...)121 catch (...)
122 {122 {
123 pushable_ = false;123 pushable_ = false;
124 // TODO: log error124 // TODO: log error
125 reply_->finished(ListenerBase::Error, "unknown exception"); // Oneway, can't block125 reply_->finished(ListenerBase::Error, "unknown exception"); // Oneway, can't block
126 cerr << "ScopeBase::run(): unknown exception" << endl;126 errlog << "ScopeBase::run(): unknown exception";
127 }127 }
128}128}
129129
130130
=== modified file 'src/scopes/internal/ReplyImpl.cpp'
--- src/scopes/internal/ReplyImpl.cpp 2014-03-04 06:26:21 +0000
+++ src/scopes/internal/ReplyImpl.cpp 2014-03-06 09:05:05 +0000
@@ -16,6 +16,7 @@
16 * Authored by: Michi Henning <michi.henning@canonical.com>16 * Authored by: Michi Henning <michi.henning@canonical.com>
17 */17 */
1818
19#include <unity/scopes/internal/Logging.h>
19#include <unity/scopes/internal/ReplyImpl.h>20#include <unity/scopes/internal/ReplyImpl.h>
2021
21#include <unity/scopes/Annotation.h>22#include <unity/scopes/Annotation.h>
@@ -37,7 +38,7 @@
3738
38#include <cassert>39#include <cassert>
39#include <sstream>40#include <sstream>
40#include <iostream> // TODO: remove this once logging is added41#include <cassert>
4142
42using namespace std;43using namespace std;
4344
@@ -262,7 +263,7 @@
262 catch (std::exception const& e)263 catch (std::exception const& e)
263 {264 {
264 // TODO: log error265 // TODO: log error
265 cerr << e.what() << endl;266 errlog << e.what();
266 }267 }
267 }268 }
268}269}
@@ -290,7 +291,7 @@
290 error_message = "unknown exception";291 error_message = "unknown exception";
291 }292 }
292 // TODO: log error293 // TODO: log error
293 cerr << error_message << endl;294 errlog << error_message;
294295
295 try296 try
296 {297 {
@@ -299,7 +300,7 @@
299 catch (std::exception const& e)300 catch (std::exception const& e)
300 {301 {
301 // TODO: log error302 // TODO: log error
302 cerr << e.what() << endl;303 errlog << e.what();
303 }304 }
304}305}
305306
306307
=== modified file 'src/scopes/internal/ReplyObject.cpp'
--- src/scopes/internal/ReplyObject.cpp 2014-02-24 05:04:11 +0000
+++ src/scopes/internal/ReplyObject.cpp 2014-03-06 09:05:05 +0000
@@ -16,6 +16,7 @@
16 * Authored by: Michi Henning <michi.henning@canonical.com>16 * Authored by: Michi Henning <michi.henning@canonical.com>
17 */17 */
1818
19#include <unity/scopes/internal/Logging.h>
19#include <unity/scopes/internal/ReplyObject.h>20#include <unity/scopes/internal/ReplyObject.h>
20#include <unity/scopes/internal/ResultReplyObject.h>21#include <unity/scopes/internal/ResultReplyObject.h>
21#include <unity/scopes/internal/PreviewReplyObject.h>22#include <unity/scopes/internal/PreviewReplyObject.h>
@@ -27,7 +28,6 @@
27#include <unity/scopes/internal/CategorisedResultImpl.h>28#include <unity/scopes/internal/CategorisedResultImpl.h>
2829
29#include <cassert>30#include <cassert>
30#include <iostream> // TODO: remove this once logging is added
3131
32using namespace std;32using namespace std;
33using namespace unity::scopes::internal;33using namespace unity::scopes::internal;
@@ -50,8 +50,8 @@
50 assert(receiver_base);50 assert(receiver_base);
51 assert(runtime);51 assert(runtime);
52 reap_item_ = runtime->reply_reaper()->add([this] {52 reap_item_ = runtime->reply_reaper()->add([this] {
53 cerr << "No activity on ReplyObject for scope " << this->origin_proxy_53 errlog << "No activity on ReplyObject for scope " << this->origin_proxy_
54 << ": ReplyObject destroyed" << endl;54 << ": ReplyObject destroyed";
55 this->disconnect();55 this->disconnect();
56 });56 });
57}57}
@@ -162,12 +162,12 @@
162 }162 }
163 catch (std::exception const& e)163 catch (std::exception const& e)
164 {164 {
165 cerr << "ReplyObject::finished(): " << e.what() << endl;165 errlog << "ReplyObject::finished(): " << e.what();
166 // TODO: log error166 // TODO: log error
167 }167 }
168 catch (...)168 catch (...)
169 {169 {
170 cerr << "ReplyObject::finished(): unknown exception" << endl;170 errlog << "ReplyObject::finished(): unknown exception";
171 // TODO: log error171 // TODO: log error
172 }172 }
173}173}
174174
=== modified file 'src/scopes/internal/RuntimeImpl.cpp'
--- src/scopes/internal/RuntimeImpl.cpp 2014-02-21 05:12:05 +0000
+++ src/scopes/internal/RuntimeImpl.cpp 2014-03-06 09:05:05 +0000
@@ -19,6 +19,7 @@
19#include <unity/scopes/internal/RuntimeImpl.h>19#include <unity/scopes/internal/RuntimeImpl.h>
2020
21#include <unity/scopes/internal/DfltConfig.h>21#include <unity/scopes/internal/DfltConfig.h>
22#include <unity/scopes/internal/Logging.h>
22#include <unity/scopes/internal/RegistryConfig.h>23#include <unity/scopes/internal/RegistryConfig.h>
23#include <unity/scopes/internal/RegistryImpl.h>24#include <unity/scopes/internal/RegistryImpl.h>
24#include <unity/scopes/internal/RuntimeConfig.h>25#include <unity/scopes/internal/RuntimeConfig.h>
@@ -30,7 +31,6 @@
3031
31#include <cassert>32#include <cassert>
32#include <future>33#include <future>
33#include <iostream> // TODO: remove this once logging is added
3434
3535
36using namespace std;36using namespace std;
@@ -72,7 +72,7 @@
7272
73 if (registry_configfile_.empty() || registry_identity_.empty())73 if (registry_configfile_.empty() || registry_identity_.empty())
74 {74 {
75 cerr << "Warning: no registry configured" << endl;75 errlog << "Warning: no registry configured";
76 registry_identity_ = "";76 registry_identity_ = "";
77 }77 }
78 else78 else
@@ -100,12 +100,12 @@
100 }100 }
101 catch (std::exception const& e) // LCOV_EXCL_LINE101 catch (std::exception const& e) // LCOV_EXCL_LINE
102 {102 {
103 cerr << "~RuntimeImpl(): " << e.what() << endl;103 errlog << "~RuntimeImpl(): " << e.what();
104 // TODO: log error104 // TODO: log error
105 }105 }
106 catch (...) // LCOV_EXCL_LINE106 catch (...) // LCOV_EXCL_LINE
107 {107 {
108 cerr << "~RuntimeImpl(): unknown exception" << endl;108 errlog << "~RuntimeImpl(): unknown exception";
109 // TODO: log error109 // TODO: log error
110 }110 }
111}111}
112112
=== modified file 'src/scopes/internal/ScopeImpl.cpp'
--- src/scopes/internal/ScopeImpl.cpp 2014-02-27 23:00:59 +0000
+++ src/scopes/internal/ScopeImpl.cpp 2014-03-06 09:05:05 +0000
@@ -18,6 +18,7 @@
1818
19#include <unity/scopes/internal/ScopeImpl.h>19#include <unity/scopes/internal/ScopeImpl.h>
2020
21#include <unity/scopes/internal/Logging.h>
21#include <unity/scopes/internal/ResultImpl.h>22#include <unity/scopes/internal/ResultImpl.h>
22#include <unity/scopes/internal/MiddlewareBase.h>23#include <unity/scopes/internal/MiddlewareBase.h>
23#include <unity/scopes/internal/MWScope.h>24#include <unity/scopes/internal/MWScope.h>
@@ -33,7 +34,6 @@
33#include <unity/scopes/internal/PreviewReplyObject.h>34#include <unity/scopes/internal/PreviewReplyObject.h>
3435
35#include <cassert>36#include <cassert>
36#include <iostream> // TODO: remove this once logging is added
3737
38using namespace std;38using namespace std;
3939
@@ -134,7 +134,7 @@
134 catch (std::exception const& e)134 catch (std::exception const& e)
135 {135 {
136 // TODO: log error136 // TODO: log error
137 cerr << "activate(): " << e.what() << endl;137 errlog << "activate(): " << e.what();
138 try138 try
139 {139 {
140 ro->finished(ListenerBase::Error, e.what());140 ro->finished(ListenerBase::Error, e.what());
@@ -142,7 +142,7 @@
142 }142 }
143 catch (...)143 catch (...)
144 {144 {
145 cerr << "activate(): unknown exception" << endl;145 errlog << "activate(): unknown exception";
146 }146 }
147 throw;147 throw;
148 }148 }
@@ -172,7 +172,7 @@
172 catch (std::exception const& e)172 catch (std::exception const& e)
173 {173 {
174 // TODO: log error174 // TODO: log error
175 cerr << "perform_action(): " << e.what() << endl;175 errlog << "perform_action(): " << e.what();
176 try176 try
177 {177 {
178 // TODO: if things go wrong, we need to make sure that the reply object178 // TODO: if things go wrong, we need to make sure that the reply object
@@ -182,7 +182,7 @@
182 }182 }
183 catch (...)183 catch (...)
184 {184 {
185 cerr << "perform_action(): unknown exception" << endl;185 errlog << "perform_action(): unknown exception";
186 }186 }
187 throw;187 throw;
188 }188 }
@@ -216,7 +216,7 @@
216 catch (std::exception const& e)216 catch (std::exception const& e)
217 {217 {
218 // TODO: log error218 // TODO: log error
219 cerr << "preview(): " << e.what() << endl;219 errlog << "preview(): " << e.what();
220 try220 try
221 {221 {
222 ro->finished(ListenerBase::Error, e.what());222 ro->finished(ListenerBase::Error, e.what());
@@ -224,7 +224,7 @@
224 }224 }
225 catch (...)225 catch (...)
226 {226 {
227 cerr << "preview(): unknown exception" << endl;227 errlog << "preview(): unknown exception";
228 }228 }
229 throw;229 throw;
230 }230 }
231231
=== modified file 'src/scopes/internal/ScopeObject.cpp'
--- src/scopes/internal/ScopeObject.cpp 2014-02-27 23:29:10 +0000
+++ src/scopes/internal/ScopeObject.cpp 2014-03-06 09:05:05 +0000
@@ -19,6 +19,7 @@
19#include <unity/scopes/internal/ScopeObject.h>19#include <unity/scopes/internal/ScopeObject.h>
2020
21#include <unity/scopes/internal/ActivationQueryObject.h>21#include <unity/scopes/internal/ActivationQueryObject.h>
22#include <unity/scopes/internal/Logging.h>
22#include <unity/scopes/internal/MWQuery.h>23#include <unity/scopes/internal/MWQuery.h>
23#include <unity/scopes/internal/MWReply.h>24#include <unity/scopes/internal/MWReply.h>
24#include <unity/scopes/internal/PreviewQueryObject.h>25#include <unity/scopes/internal/PreviewQueryObject.h>
@@ -29,7 +30,6 @@
29#include <unity/UnityExceptions.h>30#include <unity/UnityExceptions.h>
3031
31#include <cassert>32#include <cassert>
32#include <iostream> // TODO: remove this once logging is added
33#include <sstream>33#include <sstream>
3434
35using namespace std;35using namespace std;
@@ -122,7 +122,7 @@
122 catch (...)122 catch (...)
123 {123 {
124 }124 }
125 cerr << "query(): " << e.what() << endl;125 errlog << "query(): " << e.what();
126 // TODO: log error126 // TODO: log error
127 throw;127 throw;
128 }128 }
@@ -135,7 +135,7 @@
135 catch (...)135 catch (...)
136 {136 {
137 }137 }
138 cerr << "query(): unknown exception" << endl;138 errlog << "query(): unknown exception";
139 // TODO: log error139 // TODO: log error
140 throw;140 throw;
141 }141 }
142142
=== modified file 'test/gtest/scopes/internal/CMakeLists.txt'
--- test/gtest/scopes/internal/CMakeLists.txt 2014-02-24 14:56:26 +0000
+++ test/gtest/scopes/internal/CMakeLists.txt 2014-03-06 09:05:05 +0000
@@ -3,6 +3,7 @@
3add_subdirectory(DynamicLoader)3add_subdirectory(DynamicLoader)
4add_subdirectory(JsonNode)4add_subdirectory(JsonNode)
5add_subdirectory(lttng)5add_subdirectory(lttng)
6add_subdirectory(Logging)
6add_subdirectory(MiddlewareFactory)7add_subdirectory(MiddlewareFactory)
7add_subdirectory(Reaper)8add_subdirectory(Reaper)
8add_subdirectory(RegistryConfig)9add_subdirectory(RegistryConfig)
910
=== added directory 'test/gtest/scopes/internal/Logging'
=== added file 'test/gtest/scopes/internal/Logging/CMakeLists.txt'
--- test/gtest/scopes/internal/Logging/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ test/gtest/scopes/internal/Logging/CMakeLists.txt 2014-03-06 09:05:05 +0000
@@ -0,0 +1,14 @@
1add_executable(
2 Logging_test
3 Logging_test.cpp
4)
5
6target_link_libraries(
7 Logging_test
8 ${TESTLIBS}
9)
10
11add_test(
12 Logging
13 Logging_test
14)
015
=== added file 'test/gtest/scopes/internal/Logging/Logging_test.cpp'
--- test/gtest/scopes/internal/Logging/Logging_test.cpp 1970-01-01 00:00:00 +0000
+++ test/gtest/scopes/internal/Logging/Logging_test.cpp 2014-03-06 09:05:05 +0000
@@ -0,0 +1,53 @@
1/*
2 * Copyright © 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Jussi Pakkanen <jussi.pakkanen@canonical.com>
17 */
18
19#include <unity/scopes/internal/Logging.h>
20#include <unity/UnityExceptions.h>
21#include <unity/scopes/Variant.h>
22
23#include <gtest/gtest.h>
24#include <memory>
25#include <algorithm>
26
27using namespace testing;
28using unity::scopes::internal::errlog;
29
30namespace
31{
32
33class LoggingTest : public Test
34{
35public:
36 LoggingTest()
37 {
38 }
39
40};
41
42TEST_F(LoggingTest, basic)
43{
44 std::string msg("Second message to stderr.");
45 errlog << "First message to stderr.";
46 errlog << msg;
47 errlog << "Piecewise " << "message " << "to stderr.\n";
48 errlog << 1 << " is the loneliest number. Not " << 2 << ".\n";
49 errlog << "True is " << true << " and False is " << false << ".";
50}
51
52
53} // namespace

Subscribers

People subscribed via source and target branches

to all changes: