creating unique message identifiers

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • mliptak

    creating unique message identifiers

    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
  • James Kanze

    #2
    Re: creating unique message identifiers

    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:james.kan ze@gmail.com
    Conseils en informatique orientée objet/
    Beratung in objektorientier ter Datenverarbeitu ng
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

    Comment

    • mliptak

      #3
      Re: creating unique message identifiers

      On Nov 4, 2:21 pm, James Kanze <james.ka...@gm ail.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.

      Comment

      • Maxim Yegorushkin

        #4
        Re: creating unique message identifiers

        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

        Comment

        • mliptak

          #5
          Re: creating unique message identifiers

          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

          Comment

          • Hendrik Schober

            #6
            Re: creating unique message identifiers

            mliptak wrote:
            On Nov 4, 2:21 pm, James Kanze <james.ka...@gm ail.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(identifie r, 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

            Comment

            • mliptak

              #7
              Re: creating unique message identifiers

              On Nov 4, 3:48 pm, Hendrik Schober <spamt...@gmx.d ewrote:
              mliptak wrote:
              On Nov 4, 2:21 pm, James Kanze <james.ka...@gm ail.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

              Comment

              • Bart van Ingen Schenau

                #8
                Re: creating unique message identifiers

                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

                Comment

                • peter koch

                  #9
                  Re: creating unique message identifiers

                  On 4 Nov., 15:59, mliptak <Meht...@gmail. comwrote:
                  On Nov 4, 3:48 pm, Hendrik Schober <spamt...@gmx.d ewrote:
                  >
                  >
                  >
                  >
                  >
                  mliptak wrote:
                  On Nov 4, 2:21 pm, James Kanze <james.ka...@gm ail.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(identifie r, 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

                  Comment

                  • mliptak

                    #10
                    Re: creating unique message identifiers

                    On Nov 4, 5:15 pm, Bart van Ingen Schenau
                    <Bart.van.Ingen .Sche...@ict.nl wrote:
                    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.

                    Comment

                    • James Kanze

                      #11
                      Re: creating unique message identifiers

                      On Nov 4, 2:31 pm, mliptak <Meht...@gmail. comwrote:
                      On Nov 4, 2:21 pm, James Kanze <james.ka...@gm ail.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:james.kan ze@gmail.com
                      Conseils en informatique orientée objet/
                      Beratung in objektorientier ter Datenverarbeitu ng
                      9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                      Comment

                      • James Kanze

                        #12
                        Re: creating unique message identifiers

                        On Nov 4, 3:05 pm, mliptak <Meht...@gmail. comwrote:
                        On Nov 4, 2:53 pm, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:
                        mliptak wrote:
                        On Nov 4, 2:21 pm, James Kanze <james.ka...@gm ail.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(identifie r, 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 "requiremen ts" 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:james.kan ze@gmail.com
                        Conseils en informatique orientée objet/
                        Beratung in objektorientier ter Datenverarbeitu ng
                        9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                        Comment

                        • James Kanze

                          #13
                          Re: creating unique message identifiers

                          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.nl wrote:
                          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:james.kan ze@gmail.com
                          Conseils en informatique orientée objet/
                          Beratung in objektorientier ter Datenverarbeitu ng
                          9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                          Comment

                          • Paavo Helde

                            #14
                            Re: creating unique message identifiers

                            mliptak <Mehturt@gmail. comkirjutas:
                            On Nov 4, 2:21 pm, James Kanze <james.ka...@gm ail.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_processin g.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




                            Comment

                            Working...