By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,730 Members | 1,480 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,730 IT Pros & Developers. It's quick & easy.

creating unique message identifiers

P: n/a
I'm trying to implement logging in my application, so that each log
message has its unique identifier, e.g.
log(identifier, text)
What I want to achieve is that the compiler screams if the log() with
'identifier' is also used in some other place in the code which would
make the 'identifier' not unique.
Is that something that can be achieved in C++?
Thanks
Nov 4 '08 #1
Share this Question
Share on Google+
13 Replies


P: n/a
On Nov 4, 11:54 am, mliptak <Meht...@gmail.comwrote:
I'm trying to implement logging in my application, so that
each log message has its unique identifier, e.g.
log(identifier, text)
What I want to achieve is that the compiler screams if the
log() with 'identifier' is also used in some other place in
the code which would make the 'identifier' not unique.
Is that something that can be achieved in C++?
It depends on the type of identifier, but in general, yes,
provided log is a macro. In the general case, you need a local
static variable to achieve it, and the actual identifier won't
be known until compile time. If identifier is text, however,
you can generate it with a macro using __FILE__ and __LINE__.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Nov 4 '08 #2

P: n/a
On Nov 4, 2:21*pm, James Kanze <james.ka...@gmail.comwrote:
On Nov 4, 11:54 am, mliptak <Meht...@gmail.comwrote:
I'm trying to implement logging in my application, so that
each log message has its unique identifier, e.g.
log(identifier, text)
What I want to achieve is that the compiler screams if the
log() with 'identifier' is also used in some other place in
the code which would make the 'identifier' not unique.
Is that something that can be achieved in C++?

It depends on the type of identifier, but in general, yes,
provided log is a macro. *In the general case, you need a local
static variable to achieve it, and the actual identifier won't
be known until compile time. *If identifier is text, however,
you can generate it with a macro using __FILE__ and __LINE__.
What if I want to set the identifier myself, not have it generated at
compile time (using local static variable)?

I was also thinking of using the __FILE__ and __LINE__ but the problem
is this could change when the code changes, and I need to have the
identifier fixed for each message.
Nov 4 '08 #3

P: n/a
On Nov 4, 10:54*am, mliptak <Meht...@gmail.comwrote:
I'm trying to implement logging in my application, so that each log
message has its unique identifier, e.g.
log(identifier, text)
What do you need that identifier for?
What I want to achieve is that the compiler screams if the log() with
'identifier' is also used in some other place in the code which would
make the 'identifier' not unique.
It is not possible in the general case when a binary is built by
linking several object files compiled separately. In this case you
could make the linker produce an error, however, it still would not be
possible in the presence of dynamic libraries.

--
Max
Nov 4 '08 #4

P: n/a
On Nov 4, 2:54*pm, Maxim Yegorushkin <maxim.yegorush...@gmail.com>
wrote:
On Nov 4, 10:54*am, mliptak <Meht...@gmail.comwrote:
I'm trying to implement logging in my application, so that each log
message has its unique identifier, e.g.
log(identifier, text)

What do you need that identifier for?
The requirement is to have the log messages searchable easily, by
tools like grep. It is a bit more convenient than search by message
text.
>
What I want to achieve is that the compiler screams if the log() with
'identifier' is also used in some other place in the code which would
make the 'identifier' not unique.

It is not possible in the general case when a binary is built by
linking several object files compiled separately. In this case you
could make the linker produce an error, however, it still would not be
possible in the presence of dynamic libraries.
Yes, I thought about the dynamic libraries before. In my case it is
ok if it does not work for dynamic libraries as I don't use them right
now.
>
--
Max
Nov 4 '08 #5

P: n/a
mliptak wrote:
On Nov 4, 2:21 pm, James Kanze <james.ka...@gmail.comwrote:
>On Nov 4, 11:54 am, mliptak <Meht...@gmail.comwrote:
>>I'm trying to implement logging in my application, so that
each log message has its unique identifier, e.g.
log(identifier, text)
What I want to achieve is that the compiler screams if the
log() with 'identifier' is also used in some other place in
the code which would make the 'identifier' not unique.
Is that something that can be achieved in C++?
It depends on the type of identifier, but in general, yes,
provided log is a macro. In the general case, you need a local
static variable to achieve it, and the actual identifier won't
be known until compile time. If identifier is text, however,
you can generate it with a macro using __FILE__ and __LINE__.

What if I want to set the identifier myself, not have it generated at
compile time (using local static variable)?

I was also thinking of using the __FILE__ and __LINE__ but the problem
is this could change when the code changes, and I need to have the
identifier fixed for each message.
Why don't you want to use '__FILE__' and '__LINE__'? If these
change too often, add '__DATE__' and '__TIME__' which, together
with your version management should be enough.
OTOH, I have written a logging library which allows grouping of
code and which emits the group's tag name. You can have a look
at that at http://sourceforge.net/projects/templog/. (The main
goal of this was to use expression templates to gain performance
when logging is turned off and I haven't found the time yet to
document anything, so I apologize if it seems a bit cryptic.)

HTH,

Schobi
Nov 4 '08 #6

P: n/a
On Nov 4, 3:48*pm, Hendrik Schober <spamt...@gmx.dewrote:
mliptak wrote:
On Nov 4, 2:21 pm, James Kanze <james.ka...@gmail.comwrote:
On Nov 4, 11:54 am, mliptak <Meht...@gmail.comwrote:
>I'm trying to implement logging in my application, so that
each log message has its unique identifier, e.g.
log(identifier, text)
What I want to achieve is that the compiler screams if the
log() with 'identifier' is also used in some other place in
the code which would make the 'identifier' not unique.
Is that something that can be achieved in C++?
It depends on the type of identifier, but in general, yes,
provided log is a macro. *In the general case, you need a local
static variable to achieve it, and the actual identifier won't
be known until compile time. *If identifier is text, however,
you can generate it with a macro using __FILE__ and __LINE__.
What if I want to set the identifier myself, not have it generated at
compile time (using local static variable)?
I was also thinking of using the __FILE__ and __LINE__ but the problem
is this could change when the code changes, and I need to have the
identifier fixed for each message.

* Why don't you want to use '__FILE__' and '__LINE__'? If these
* change too often, add '__DATE__' and '__TIME__' which, together
* with your version management should be enough.
I think it is too complicated for what I really need to achieve.
What I had in mind originally was something like:

log(ERROR01, "Text of error 1");
log(ERROR02, "Text of error 2");
* OTOH, I have written a logging library which allows grouping of
* code and which emits the group's tag name. You can have a look
* at that athttp://sourceforge.net/projects/templog/. (The main
* goal of this was to use expression templates to gain performance
* when logging is turned off and I haven't found the time yet to
* document anything, so I apologize if it seems a bit cryptic.)

* HTH,

* Schobi
Nov 4 '08 #7

P: n/a
On Nov 4, 3:05 pm, mliptak <Meht...@gmail.comwrote:
>
What I meant by this is to have the "code" associated with particular
"text" and this association never changes (which is not true if I'd be
using __FILE__ and __LINE__).

You asked why have identifier at all.. Well another requirement is to
have the "code" unique throughout the program.

Example:

// a.cc
// ok
log(code1, "text1");
log(code2, "text2");
...
// invalid - code1 already used before
log(code1, "text3");
If that line had read
log(code1, "text1"),
would that have been OK?
>
// b.cc
// invalid - code1 already used elsewhere
log(code1, "text4");
// ok
log(code4, "text5");
If you want to have a consistent mapping between a numeric/symbolic ID
and a string, the worst thing you can do is require the programmer to
provide both the ID and the string.

The solution I would propose is to use only the ID in the log
statements, and use a separate mechanism (for example a table) to map
the ID to a string.
For example, something like this:

enum logID {
code1,
code2,
code4
};

char const * const logString[] = {
"text1",
"text2",
"text5"
};

void log(enum logID id)
{
char const * const text = logString[id];
// write text to log destination
}
//usage: log(code1);

To keep the mapping between the ID's and the texts consistent, you can
generate the enumeration and the table from a single source. This
could even be done with the preprocessor.

Bart v Ingen Schenau
Nov 4 '08 #8

P: n/a
On 4 Nov., 15:59, mliptak <Meht...@gmail.comwrote:
On Nov 4, 3:48*pm, Hendrik Schober <spamt...@gmx.dewrote:


mliptak wrote:
On Nov 4, 2:21 pm, James Kanze <james.ka...@gmail.comwrote:
>On Nov 4, 11:54 am, mliptak <Meht...@gmail.comwrote:
>>I'm trying to implement logging in my application, so that
>>each log message has its unique identifier, e.g.
>>log(identifier, text)
>>What I want to achieve is that the compiler screams if the
>>log() with 'identifier' is also used in some other place in
>>the code which would make the 'identifier' not unique.
>>Is that something that can be achieved in C++?
>It depends on the type of identifier, but in general, yes,
>provided log is a macro. *In the general case, you need a local
>static variable to achieve it, and the actual identifier won't
>be known until compile time. *If identifier is text, however,
>you can generate it with a macro using __FILE__ and __LINE__.
What if I want to set the identifier myself, not have it generated at
compile time (using local static variable)?
I was also thinking of using the __FILE__ and __LINE__ but the problem
is this could change when the code changes, and I need to have the
identifier fixed for each message.
* Why don't you want to use '__FILE__' and '__LINE__'? If these
* change too often, add '__DATE__' and '__TIME__' which, together
* with your version management should be enough.

I think it is too complicated for what I really need to achieve.
What I had in mind originally was something like:

log(ERROR01, "Text of error 1");
log(ERROR02, "Text of error 2");
Certainly, if you search for simplicity using __FILE__ and __LINE__ is
the way to go. I once used your approach (manually and written in C
loads of years ago), but the reason not to use __LINE__ and __FILE__
was because of a restricted environment where low space overhead was
at a premium. (It was not for logging but for assertions, and in case
of an assert, the integer id was simply dumped).

/Peter
Nov 4 '08 #9

P: n/a
On Nov 4, 5:15*pm, Bart van Ingen Schenau
<Bart.van.Ingen.Sche...@ict.nlwrote:
On Nov 4, 3:05 pm, mliptak <Meht...@gmail.comwrote:


What I meant by this is to have the "code" associated with particular
"text" and this association never changes (which is not true if I'd be
using __FILE__ and __LINE__).
You asked why have identifier at all.. Well another requirement is to
have the "code" unique throughout the program.
Example:
// a.cc
// ok
log(code1, "text1");
log(code2, "text2");
...
// invalid - code1 already used before
log(code1, "text3");

If that line had read
* log(code1, "text1"),
would that have been OK?
// b.cc
// invalid - code1 already used elsewhere
log(code1, "text4");
// ok
log(code4, "text5");

If you want to have a consistent mapping between a numeric/symbolic ID
and a string, the worst thing you can do is require the programmer to
provide both the ID and the string.

The solution I would propose is to use only the ID in the log
statements, and use a separate mechanism (for example a table) to map
the ID to a string.
For example, something like this:

enum logID {
* code1,
* code2,
* code4

};

char const * const logString[] = {
* "text1",
* "text2",
* "text5"

};

void log(enum logID id)
{
* char const * const text = logString[id];
* // write text to log destination}

//usage: log(code1);

To keep the mapping between the ID's and the texts consistent, you can
generate the enumeration and the table from a single source. This
could even be done with the preprocessor.

Bart v Ingen Schenau
Yes, I was thinking about this, but the problem is the "text" is not
only a text, but string with parameters, either:
"text param %d, %s", a, b
or:
"text param " << a << ", " << b

I think I will end up with:
void log(enum logID id, ...)
{
}
and do the vsnprintf() magic in there.
Nov 5 '08 #10

P: n/a
On Nov 4, 2:31 pm, mliptak <Meht...@gmail.comwrote:
On Nov 4, 2:21 pm, James Kanze <james.ka...@gmail.comwrote:
On Nov 4, 11:54 am, mliptak <Meht...@gmail.comwrote:
I'm trying to implement logging in my application, so that
each log message has its unique identifier, e.g.
log(identifier, text) What I want to achieve is that the
compiler screams if the log() with 'identifier' is also
used in some other place in the code which would make the
'identifier' not unique. Is that something that can be
achieved in C++?
It depends on the type of identifier, but in general, yes,
provided log is a macro. In the general case, you need a
local static variable to achieve it, and the actual
identifier won't be known until compile time. If identifier
is text, however, you can generate it with a macro using
__FILE__ and __LINE__.
What if I want to set the identifier myself, not have it
generated at compile time (using local static variable)?
You mean that you want the user to provide an indentifier, that
the compiler checks for uniqueness? The compiler can't do that
per se (at least not within a single statement), but you could
easily use it as the initializer of a local static variable,
which would check for uniqueness at runtime.
I was also thinking of using the __FILE__ and __LINE__ but the
problem is this could change when the code changes, and I need
to have the identifier fixed for each message.
The real question is what the identifier is to be used for.
Most of the time, if you need each point of invocation to have a
separate identifier, it is for some sort of tracing or
debugging, in which case, __FILE__ and __LINE__ are far more
useful than anything else you could come up with.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Nov 5 '08 #11

P: n/a
On Nov 4, 3:05 pm, mliptak <Meht...@gmail.comwrote:
On Nov 4, 2:53 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
mliptak wrote:
On Nov 4, 2:21 pm, James Kanze <james.ka...@gmail.comwrote:
>On Nov 4, 11:54 am, mliptak <Meht...@gmail.comwrote:
>>I'm trying to implement logging in my application, so
>>that each log message has its unique identifier, e.g.
>>log(identifier, text)
>>What I want to achieve is that the compiler screams if
>>the log() with 'identifier' is also used in some other
>>place in the code which would make the 'identifier' not
>>unique. Is that something that can be achieved in C++?
>It depends on the type of identifier, but in general,
>yes, provided log is a macro. In the general case, you
>need a local static variable to achieve it, and the
>actual identifier won't be known until compile time. If
>identifier is text, however, you can generate it with a
>macro using __FILE__ and __LINE__.
What if I want to set the identifier myself, not have it
generated at compile time (using local static variable)?
I was also thinking of using the __FILE__ and __LINE__ but
the problem is this could change when the code changes,
and I need to have the identifier fixed for each message.
I think you're still to figure out exactly what you need
(i.e. the "requirements" part of your design). What does it
mean "to have the identifier fixed for each message"? Do
you intend to have the same message sprinkled throughout
your code and have the same identifier accompany it? If the
messages are unique, why nave an identifier at all? If the
messages aren't unique and can be the same, using the exact
location in your code to generate the identifier is a nice
way to ensure uniqueness of them.
What I meant by this is to have the "code" associated with
particular "text" and this association never changes (which is
not true if I'd be using __FILE__ and __LINE__).
Aha. Something like errno. Or the error codes returned by
Internet message protocols (smtp, nntp, http...).

That really requires an external registry. The simplest
solution is to maintain a list of code/message pairs, use it to
generate a mapping function, and just pass the code to log
(which uses the mapping function to obtain the message).

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Nov 5 '08 #12

P: n/a
On Nov 5, 6:49 am, mliptak <Meht...@gmail.comwrote:
On Nov 4, 5:15 pm, Bart van Ingen Schenau
<Bart.van.Ingen.Sche...@ict.nlwrote:
On Nov 4, 3:05 pm, mliptak <Meht...@gmail.comwrote:
If you want to have a consistent mapping between a
numeric/symbolic ID and a string, the worst thing you can do
is require the programmer to provide both the ID and the
string.
The solution I would propose is to use only the ID in the
log statements, and use a separate mechanism (for example a
table) to map the ID to a string.
For example, something like this:
enum logID {
code1,
code2,
code4
};
char const * const logString[] = {
"text1",
"text2",
"text5"
};
void log(enum logID id)
{
char const * const text = logString[id];
// write text to log destination}
//usage: log(code1);
To keep the mapping between the ID's and the texts
consistent, you can generate the enumeration and the table
from a single source. This could even be done with the
preprocessor.
Yes, I was thinking about this, but the problem is the "text"
is not only a text, but string with parameters, either:
"text param %d, %s", a, b
or:
"text param " << a << ", " << b
I think I will end up with:
void log(enum logID id, ...)
{}
and do the vsnprintf() magic in there.
That's a good recepe for program crashes down the line. In such
cases, the usual solution is for log to return an output stream
wrapper (or even an ostream&, if you don't have to worry about
threading), log inserts the header text (the code, plus anything
you've already mapped), and the client appends the rest.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Nov 5 '08 #13

P: n/a
mliptak <Me*****@gmail.comkirjutas:
On Nov 4, 2:21*pm, James Kanze <james.ka...@gmail.comwrote:
>On Nov 4, 11:54 am, mliptak <Meht...@gmail.comwrote:
I'm trying to implement logging in my application, so that
each log message has its unique identifier, e.g.
log(identifier, text)
What I want to achieve is that the compiler screams if the
log() with 'identifier' is also used in some other place in
the code which would make the 'identifier' not unique.
Is that something that can be achieved in C++?

It depends on the type of identifier, but in general, yes,
provided log is a macro. *In the general case, you need a local
static variable to achieve it, and the actual identifier won't
be known until compile time. *If identifier is text, however,
you can generate it with a macro using __FILE__ and __LINE__.

What if I want to set the identifier myself, not have it generated at
compile time (using local static variable)?

I was also thinking of using the __FILE__ and __LINE__ but the problem
is this could change when the code changes, and I need to have the
identifier fixed for each message.
I have had a similar need sometimes - need to attach unique identifiers
to error messages which could be searched for in the source code later,
if necessary. As I have been too lazy to implement any kind of registry
or something, I have just entered the identifier by hand. If the error is
originally generated e.g. at line 345 of image_processing.cpp, I would
have used an identifier like "IMPR345". Over time the code moves to
another line, and there might be another source file with similar name,
etc., but I have actually not encountered any collisions so far. To
reduce the collision probability one could also encode current year/month
in the identifier.

Paavo


Nov 6 '08 #14

This discussion thread is closed

Replies have been disabled for this discussion.