Log4j 2
  1. Log4j 2
  2. LOG4J2-441

logger level configuration does not work correct

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: Core
    • Labels:
      None

      Description

      Configuring the loglevel in the logger does not work in combination with configuring the loglevel at the appender-refs. I analyzed this with the beta9. See the table which lists various loglevel configurations for the 3 loggers. The column format for the table is:
      Column 1-6 are the logger with their level config (level@logger1, level@appender-ref)(level@logger2, level@appender-ref)(level@logger3, level@appender-ref)
      Column 7 is the actual output
      Column 8 is the expected Output

      For instance the first row of the table shows a logging result which I not expected in that way. You can take log4j2.xml.row1 to reproduce the first row. The first logger is named "com". The second logger is named "com.log4jtest" and the third logger is named "com.log4jtest.test". This looks like a bug in log4j 2.0:
      Logger1 considers the levels

      {info, debug, warning}

      but not the level trace. What is the default level, if there is no level defined at the logger header and also not at the appender-ref? Here it seems that the Logger1 has the level debug as default which is not clear for me. For me it would make sense if the default level is either OFF or ALL when there is no explicit level set. But either way there should be a clear rule for this. The other rows are showing similar inconsistent logging behaviour.

      1 2 3 4 5 6 7 8
      level 1 logger level 1 appender-ref level 2 logger level 2 appender-ref level 3 logger level 3 appender-ref actual output expected output
      - - - info debug debug Logger3: info logger
      Logger2: info logger
      Logger1: info logger
      Logger3: debug logger
      Logger1: debug logger
      Logger3: warning logger
      Logger2: warning logger
      Logger1: warning logger
      Logger3: info logger
      Logger2: info logger
      Logger3: debug logger
      Logger3: warning logger
      Logger2: warning logger
      - - - info - debug no output Logger3: info logger
      Logger2: info logger
      Logger3: debug logger
      Logger3: warning logger
      Logger2: warning logger
      - - info info - debug no output Logger3: info logger
      Logger2: info logger
      Logger3: debug logger
      Logger3: warning logger
      Logger2: warning logger
      fatal fatal info info - debug no output Logger3: info logger
      Logger2: info logger
      Logger3: debug logger
      Logger3: warning logger
      Logger2: warning logger
      info info info info - debug no output Logger3: info logger
      Logger2: info logger
      Logger1: info logger
      Logger3: debug logger
      Logger3: warning logger
      Logger2: warning logger
      Logger1: warning logger
      debug debug info info   debug no output Logger3: info logger
      Logger2: info logger
      Logger1: info logger
      Logger3: debug logger
      Logger3: warning logger
      Logger2: warning logger
      Logger1: warning logger
      info debug info info - debug no output Logger3: info logger
      Logger2: info logger
      Logger1: info logger
      Logger3: debug logger
      Logger3: warning logger
      Logger2: warning logger
      Logger1: warning logger
      debug info info info - debug no output Logger3: info logger
      Logger2: info logger
      Logger1: info logger
      Logger3: debug logger
      Logger3: warning logger
      Logger2: warning logger
      Logger1: warning logger
      debug trace info info - debug no output Logger3: info logger
      Logger2: info logger
      Logger1: info logger
      Logger3: debug logger
      Logger3: warning logger
      Logger2: warning logger
      Logger1: warning logger
      - - info info fatal debug no output Logger2: info logger
      Logger2: warning logger
      - - info info trace debug Logger3: info logger
      Logger2: info logger
      Logger1: info logger
      Logger3: debug logger
      Logger1: debug logger
      Logger3: warning logger
      Logger2: warning logger
      Logger1: warning logger
      Logger1: trace logger
      Logger3: info logger
      Logger2: info logger
      Logger3: debug logger
      Logger2: warning logger
      - - - info trace debug Logger3: info logger
      Logger2: info logger
      Logger1: info logger
      Logger3: debug logger
      Logger1: debug logger
      Logger3: warning logger
      Logger2: warning logger
      Logger1: warning logger
      Logger1: trace logger
      Logger3: info logger
      Logger2: info logger
      Logger3: debug logger
      Logger2: warning logger
      - - info - trace debug Logger3: info logger
      Logger2: info logger
      Logger1: info logger
      Logger3: debug logger
      Logger1: debug logger
      Logger3: warning logger
      Logger2: warning logger
      Logger1: warning logger
      Logger1: trace logger
      Logger3: info logger
      Logger2: info logger
      Logger3: debug logger
      Logger2: warning logger

      Here is the log4j2.xml:

      <?xml version="1.0" encoding="UTF-8" ?>
      <configuration>
      	<appenders>
      		<console name="TestConsole0">
      			<PatternLayout pattern="RootLogger: %msg%n"/>
      		</console>
      		<console name="TestConsole1">
      			<PatternLayout pattern="Logger1: %msg%n"/>
      		</console>
      		<console name="TestConsole2">
      			<PatternLayout pattern="Logger2: %msg%n"/>
      		</console>
      		<console name="TestConsole3">
      			<PatternLayout pattern="Logger3: %msg%n"/>
      		</console>
      	</appenders>
      	
      	<loggers>
      		<logger name="com" >
      			<appender-ref ref="TestConsole1" />
      		</logger>
      		
      		<logger name ="com.log4jtest" level="info">
      			<appender-ref ref="TestConsole2" level="info"/>
      		</logger>
      		
      		<logger name ="com.log4jtest.test" level="fatal">
      			<appender-ref ref="TestConsole3" level="debug"/>
      		</logger>
      		
      		<root level="error">
      			<appender-ref ref="TestConsole0" level="error"/>
      		</root>
      	</loggers>
      </configuration>
      

      And here are the logging calls:

      Log4j2LogLevelTest.java
      package com.log4jtest.test;
      
      import static org.junit.Assert.*;
      
      import org.apache.logging.log4j.LogManager;
      import org.apache.logging.log4j.Logger;
      import org.junit.Test;
      
      public class Log4j2LogLevelTest {
      
      	private static final Logger logger = LogManager.getLogger(Log4j2LogLevelTest.class);
      	
      	@Test
      	public void testLogLevel() {
      		logger.info("info logger");
      		logger.debug("debug logger");
      		logger.warn("warning logger");
      		logger.trace("trace logger");
      	}
      
      }
      
      1. log4j2.xml.row1
        0.9 kB
        Andreas Rytina
      2. log4j2.xml.row10
        0.9 kB
        Andreas Rytina
      3. log4j2.xml.row11
        0.9 kB
        Andreas Rytina
      4. log4j2.xml.row12
        0.9 kB
        Andreas Rytina
      5. log4j2.xml.row13
        0.9 kB
        Andreas Rytina
      6. log4j2.xml.row2
        0.9 kB
        Andreas Rytina
      7. log4j2.xml.row3
        0.9 kB
        Andreas Rytina
      8. log4j2.xml.row4
        0.9 kB
        Andreas Rytina
      9. log4j2.xml.row5
        0.9 kB
        Andreas Rytina
      10. log4j2.xml.row6
        0.9 kB
        Andreas Rytina
      11. log4j2.xml.row7
        0.9 kB
        Andreas Rytina
      12. log4j2.xml.row8
        0.9 kB
        Andreas Rytina
      13. log4j2.xml.row9
        0.9 kB
        Andreas Rytina

        Activity

        Hide
        Ralph Goers added a comment -

        Fix committed in revision 1609639. Please verify and close.

        Show
        Ralph Goers added a comment - Fix committed in revision 1609639. Please verify and close.
        Hide
        Ralph Goers added a comment -

        This change, when I commit it, won't be in rc2. That release is already in progress.

        Show
        Ralph Goers added a comment - This change, when I commit it, won't be in rc2. That release is already in progress.
        Hide
        Andreas Rytina added a comment -

        Great! I will try out the logger level inheritance with RC2.

        Show
        Andreas Rytina added a comment - Great! I will try out the logger level inheritance with RC2.
        Hide
        Ralph Goers added a comment -

        I was able to make a fairly simple change to allow the LoggerConfig to inherit its Level from its parent. Interestingly, not a single unit test was affected, which means all our unit tests specify a level on a Logger element. I will add some tests for this and if those go as expected I will also update the docs and commit the change.

        Show
        Ralph Goers added a comment - I was able to make a fairly simple change to allow the LoggerConfig to inherit its Level from its parent. Interestingly, not a single unit test was affected, which means all our unit tests specify a level on a Logger element. I will add some tests for this and if those go as expected I will also update the docs and commit the change.
        Hide
        Scott Harrington added a comment -

        Yes, that was surprising to me when I first rewrote my log4j 1.2 XML configurations for use in log4j 2.0.

        There are two main reasons a user will define a logger element: (a) to adjust the level, or (b) to map to a different chain of appenders, i.e. with additivity="false".

        In log4j 1.2 it was common to omit a "level" (or "priority") element for case (b).

        In log4j 2.0 you now have to explicitly set the level on every Logger (rarely is the "error" default the right guess - but that's a separate discussion).

        I think this will become an FAQ/complaint, so if you add a section to configuration.html that addresses the difference, then at least you can point folks to that section when they ask.

        If the root level truly needs to be parameterized, the docs could suggest a Lookup such as this: <Logger name="com.foo.Bar" level="${sys:myframework.root.logging.level}">

        Show
        Scott Harrington added a comment - Yes, that was surprising to me when I first rewrote my log4j 1.2 XML configurations for use in log4j 2.0. There are two main reasons a user will define a logger element: (a) to adjust the level, or (b) to map to a different chain of appenders, i.e. with additivity="false". In log4j 1.2 it was common to omit a "level" (or "priority") element for case (b). In log4j 2.0 you now have to explicitly set the level on every Logger (rarely is the "error" default the right guess - but that's a separate discussion). I think this will become an FAQ/complaint, so if you add a section to configuration.html that addresses the difference, then at least you can point folks to that section when they ask. If the root level truly needs to be parameterized, the docs could suggest a Lookup such as this: <Logger name="com.foo.Bar" level="${sys:myframework.root.logging.level}">
        Hide
        Ralph Goers added a comment -

        I do see one thing.

        In the sample configuration log4j2.xml.row1 I see Loggers configured that have no Level specified. In Log4j 1 this would result in a Logger being added with no log level (the level would be obtained from the first parent that had a level). In Log4j 2 the LoggerConfig defaults to a Level of error. The hierarchy for Loggers is intact in that they point to the first LoggerConfig. However, what you are really asking for is inheritance of Levels in LoggerConfigs. Implementing that would match Log4j 1 but would introduce a bit of complexity.

        Show
        Ralph Goers added a comment - I do see one thing. In the sample configuration log4j2.xml.row1 I see Loggers configured that have no Level specified. In Log4j 1 this would result in a Logger being added with no log level (the level would be obtained from the first parent that had a level). In Log4j 2 the LoggerConfig defaults to a Level of error. The hierarchy for Loggers is intact in that they point to the first LoggerConfig. However, what you are really asking for is inheritance of Levels in LoggerConfigs. Implementing that would match Log4j 1 but would introduce a bit of complexity.
        Hide
        Ralph Goers added a comment -

        I'm still not clear on what is not working. As I stated previously and from what Andreas has described, handling of log levels is working correctly and is the same as in Log4j 1, with the exception that Log4j 2 allows filters to be specified in more places.

        Jan, Remko's answer to your question, while accurate, doesn't fully describe what will happen. The Level on the Logger element is used to completely filter events. That is the value used to determine whether the result from the isEnabled calls will be true or false. If it passes that filter then the filter on the AppenderRef will be used to determine if the event should be passed to the Appender. The Appender itself can then have a filter to determine whether the event should be processed by the Appender. If the Logger were to have 2 AppenderRefs they both can specify a Level, but those Levels will only be used for filtering if the event passes the filtering on the Logger element.

        Show
        Ralph Goers added a comment - I'm still not clear on what is not working. As I stated previously and from what Andreas has described, handling of log levels is working correctly and is the same as in Log4j 1, with the exception that Log4j 2 allows filters to be specified in more places. Jan, Remko's answer to your question, while accurate, doesn't fully describe what will happen. The Level on the Logger element is used to completely filter events. That is the value used to determine whether the result from the isEnabled calls will be true or false. If it passes that filter then the filter on the AppenderRef will be used to determine if the event should be passed to the Appender. The Appender itself can then have a filter to determine whether the event should be processed by the Appender. If the Logger were to have 2 AppenderRefs they both can specify a Level, but those Levels will only be used for filtering if the event passes the filtering on the Logger element.
        Hide
        Remko Popma added a comment -

        RC2 is now being reviewed. Barring showstoppers it should be available in a
        day or two.

        On Mon, Jun 23, 2014 at 8:16 PM, Andreas Rytina (JIRA) <jira@apache.org>

        Show
        Remko Popma added a comment - RC2 is now being reviewed. Barring showstoppers it should be available in a day or two. On Mon, Jun 23, 2014 at 8:16 PM, Andreas Rytina (JIRA) <jira@apache.org>
        Hide
        Andreas Rytina added a comment -

        Jan Winter this issue is also affected to beta9 as mentioned in the issue's description. Nevertheless we should test it with RC2 again. RC2 will be released soon, right?

        Show
        Andreas Rytina added a comment - Jan Winter this issue is also affected to beta9 as mentioned in the issue's description. Nevertheless we should test it with RC2 again. RC2 will be released soon, right?
        Hide
        Remko Popma added a comment -

        It would be whatever level is most strict. So, fatal.
        (And we're at rc1, I strongly recommend you upgrade.)

        Show
        Remko Popma added a comment - It would be whatever level is most strict. So, fatal. (And we're at rc1, I strongly recommend you upgrade.)
        Hide
        Jan Winter added a comment -

        As I know is this issue affected to beta4 version.

        From my point of view was the major misunderstanding here

        		<logger name ="com.log4jtest.test" level="fatal">
        			<appender-ref ref="TestConsole3" level="debug"/>
        		</logger>
        

        Which "com.log4jtest.test"-LoggerConfig.level will be setted for TestConsole3?

        • DEBUG or FATAL?
        Show
        Jan Winter added a comment - As I know is this issue affected to beta4 version. From my point of view was the major misunderstanding here <logger name ="com.log4jtest.test" level="fatal"> <appender-ref ref="TestConsole3" level="debug"/> </logger> Which "com.log4jtest.test"-LoggerConfig.level will be setted for TestConsole3? DEBUG or FATAL?
        Hide
        Ralph Goers added a comment -

        The corresponding content in Log4j 2 can be found at http://logging.apache.org/log4j/2.x/manual/architecture.html#Log_Levels.

        Have we cleared this up or is there still an issue to be resolved?

        Show
        Ralph Goers added a comment - The corresponding content in Log4j 2 can be found at http://logging.apache.org/log4j/2.x/manual/architecture.html#Log_Levels . Have we cleared this up or is there still an issue to be resolved?
        Hide
        Ralph Goers added a comment -

        If you have a Logger of org.x.y.z configured by a LoggerConfig of org.x.y.z at DEBUG then all debug messages using that Logger should appear in LOG4J 2, regardless of how the root logger is configured. If you are not seeing that behavior then there is a bug. However, we have many unit tests for that so I'd be very surprised if that was the case. If you have a Logger of org.x.y it would use the root Logger's level since it has no configuration of its own. If you are seeing some other behavior than this then please provide the configuration file and some code to demonstrate the problem.

        The only real difference between Log4j 1 and Log4j 2 is that the logger configuration is in a separate hierarchy from the loggers. In Log4j 2 a Logger will point to the LoggerConfig that best matches its name and then that LoggerConfig will point directly to its parent rather than having a single chain of Loggers, some of which are configured and some of which are not.

        FWIW, the Log4j 1.2 manual was what was used as the basis for the initial version of the Log4j 2 manual. Many of the same examples should appear there, in this case probably on the Configuration page.

        Show
        Ralph Goers added a comment - If you have a Logger of org.x.y.z configured by a LoggerConfig of org.x.y.z at DEBUG then all debug messages using that Logger should appear in LOG4J 2, regardless of how the root logger is configured. If you are not seeing that behavior then there is a bug. However, we have many unit tests for that so I'd be very surprised if that was the case. If you have a Logger of org.x.y it would use the root Logger's level since it has no configuration of its own. If you are seeing some other behavior than this then please provide the configuration file and some code to demonstrate the problem. The only real difference between Log4j 1 and Log4j 2 is that the logger configuration is in a separate hierarchy from the loggers. In Log4j 2 a Logger will point to the LoggerConfig that best matches its name and then that LoggerConfig will point directly to its parent rather than having a single chain of Loggers, some of which are configured and some of which are not. FWIW, the Log4j 1.2 manual was what was used as the basis for the initial version of the Log4j 2 manual. Many of the same examples should appear there, in this case probably on the Configuration page.
        Hide
        Anthony Baldocchi added a comment -

        Apologies. I think I was unclear. I was not speaking from an implementation perspective but from a configuration perspective. From an implementation perspective, I would expect loggers at each level of the hierarchy to have a configured level; the issue is how that level is assigned when the configuration does not specify a level for a given logger. The point I was making is that Log4j2 does not appear to implement level inheritance as specified at https://logging.apache.org/log4j/1.2/manual.html (a number of good Examples are listed there). I experienced this particular issue in my current production configuration: if the root level is set to INFO and you define a logger org.x.y.z with level DEBUG, only INFO->FATAL messages are produced. The log4j2 configuration I use is derived from a log4j 1.2 configuration where this behavior was as I mentioned in my earlier comment (that is, when the root logger was configured with level INFO and logger org.x.y.z was configured with level DEBUG, log events from org.x.y.z at levels DEBUG->FATAL are logged). I believe this particular behavior quirk accounts for most of the differences between expected and actual outputs specified in the table.

        Show
        Anthony Baldocchi added a comment - Apologies. I think I was unclear. I was not speaking from an implementation perspective but from a configuration perspective. From an implementation perspective, I would expect loggers at each level of the hierarchy to have a configured level; the issue is how that level is assigned when the configuration does not specify a level for a given logger. The point I was making is that Log4j2 does not appear to implement level inheritance as specified at https://logging.apache.org/log4j/1.2/manual.html (a number of good Examples are listed there). I experienced this particular issue in my current production configuration: if the root level is set to INFO and you define a logger org.x.y.z with level DEBUG, only INFO->FATAL messages are produced. The log4j2 configuration I use is derived from a log4j 1.2 configuration where this behavior was as I mentioned in my earlier comment (that is, when the root logger was configured with level INFO and logger org.x.y.z was configured with level DEBUG, log events from org.x.y.z at levels DEBUG->FATAL are logged). I believe this particular behavior quirk accounts for most of the differences between expected and actual outputs specified in the table.
        Hide
        Ralph Goers added a comment -

        Your understanding does not match my reading of the Log4j 1.2 code. If you call logger.info it calls Category.getEffectiveLevel(), which looks for the first logger that has a level and returns that level. That level is checked against info. If it does not pass that level the event is ignored. Parent levels are not checked.

        Additivity only comes into play inside callAppenders. It first processes the appenders in the current logger and then traverses to the parent loggers until one is marked non-additive. It does no level checking at all for that. As far as I can tell the Log4j 2 behavior matches this.

        Yes, filters on Appenders and AppenderRefs just determine whether that particular component will process the log event.

        Show
        Ralph Goers added a comment - Your understanding does not match my reading of the Log4j 1.2 code. If you call logger.info it calls Category.getEffectiveLevel(), which looks for the first logger that has a level and returns that level. That level is checked against info. If it does not pass that level the event is ignored. Parent levels are not checked. Additivity only comes into play inside callAppenders. It first processes the appenders in the current logger and then traverses to the parent loggers until one is marked non-additive. It does no level checking at all for that. As far as I can tell the Log4j 2 behavior matches this. Yes, filters on Appenders and AppenderRefs just determine whether that particular component will process the log event.
        Hide
        Anthony Baldocchi added a comment -

        This is definitely a significant deviation from Log4j 1.2 behavior as I understand it with regard to log level behavior. In Log4j 1.2, the logger levels didn't act as filters from parent logger to child logger but instead determination of logger level was determined by checking the leaf logger for level and iterating up parents until a level value or the root logger was reached. So, for example, if level 1 logger configuration specified INFO level, level 2 specified DEBUG level, and level 3 specified TRACE level, then with additivity disabled, logging to level 3 would allow messages from TRACE->FATAL, to level 2 would allow DEBUG->FATAL, and level 1 would allow INFO->FATAL. The way it works currently, if level 1 logger configuration specifies INFO level, then level 2 and level 3 loggers will both only allow INFO->FATAL level log messages even though their configurations specify DEBUG and TRACE respectively. Was this behavior different by design? I don't recall seeing any documentation that called this behavior out.

        With regard to the level on AppenderRef new functionality, my understanding of how this is supposed to work is that once a decision is made to log to a particular logger, the level on the AppenderRef could further filter log events to allow different appenders to handle different subsets of log messages; whether a parent's AppenderRef level will apply to a child logger only matters if the child either has additivity enabled (in which case the level should only apply when the log event is processed by the parent logger) or does not specify an AppenderRef (in which case the parent's AppenderRefs apply). I think from the chart given above that the AppenderRef behavior matches expectations, although it would take further testing with much more targeted scenarios to validate.

        Show
        Anthony Baldocchi added a comment - This is definitely a significant deviation from Log4j 1.2 behavior as I understand it with regard to log level behavior. In Log4j 1.2, the logger levels didn't act as filters from parent logger to child logger but instead determination of logger level was determined by checking the leaf logger for level and iterating up parents until a level value or the root logger was reached. So, for example, if level 1 logger configuration specified INFO level, level 2 specified DEBUG level, and level 3 specified TRACE level, then with additivity disabled, logging to level 3 would allow messages from TRACE->FATAL, to level 2 would allow DEBUG->FATAL, and level 1 would allow INFO->FATAL. The way it works currently, if level 1 logger configuration specifies INFO level, then level 2 and level 3 loggers will both only allow INFO->FATAL level log messages even though their configurations specify DEBUG and TRACE respectively. Was this behavior different by design? I don't recall seeing any documentation that called this behavior out. With regard to the level on AppenderRef new functionality, my understanding of how this is supposed to work is that once a decision is made to log to a particular logger, the level on the AppenderRef could further filter log events to allow different appenders to handle different subsets of log messages; whether a parent's AppenderRef level will apply to a child logger only matters if the child either has additivity enabled (in which case the level should only apply when the log event is processed by the parent logger) or does not specify an AppenderRef (in which case the parent's AppenderRefs apply). I think from the chart given above that the AppenderRef behavior matches expectations, although it would take further testing with much more targeted scenarios to validate.
        Hide
        Ralph Goers added a comment -

        I still can't make heads or tails out of this, but I think the issue is that when a logger delegates to its parent it does not evaluate the filters on the parent. Both Log4j 1.x and Logback do the same thing but I do wonder if that is really the correct behavior.

        Show
        Ralph Goers added a comment - I still can't make heads or tails out of this, but I think the issue is that when a logger delegates to its parent it does not evaluate the filters on the parent. Both Log4j 1.x and Logback do the same thing but I do wonder if that is really the correct behavior.
        Hide
        Andreas Rytina added a comment -

        Now I attached for each row one configuration file. This should make it easier for testing

        Show
        Andreas Rytina added a comment - Now I attached for each row one configuration file. This should make it easier for testing
        Hide
        Andreas Rytina added a comment -

        Hi Remko,
        thank you for your feedback. I have given the first logger a name but the problem seems to be still there. Each row of this table is a separate log level configuration. I will now create a concrete test case for each row to make it more clear

        Show
        Andreas Rytina added a comment - Hi Remko, thank you for your feedback. I have given the first logger a name but the problem seems to be still there. Each row of this table is a separate log level configuration. I will now create a concrete test case for each row to make it more clear
        Hide
        Remko Popma added a comment -

        In the configuration above, there is one logger without a name. The only logger is "allowed" not to have a name is the root logger. All others MUST have a name. Does the problem still occur if this logger has a name?

        To be honest, I don't understand the table with your results yet, but the way I understand levels to work is that the logger and appender-ref act as a filter pipeline: first the logger filters the events, and all events that get through are then filtered again by the level on the appender-ref. (Team, please correct me if I'm wrong.) Does that match the results you are seeing?

        Show
        Remko Popma added a comment - In the configuration above, there is one logger without a name. The only logger is "allowed" not to have a name is the root logger. All others MUST have a name. Does the problem still occur if this logger has a name? To be honest, I don't understand the table with your results yet, but the way I understand levels to work is that the logger and appender-ref act as a filter pipeline: first the logger filters the events, and all events that get through are then filtered again by the level on the appender-ref. (Team, please correct me if I'm wrong.) Does that match the results you are seeing?
        Hide
        Remko Popma added a comment -

        Edited table: allow headers to wrap (could not see 2 right-most columns).

        Show
        Remko Popma added a comment - Edited table: allow headers to wrap (could not see 2 right-most columns).

          People

          • Assignee:
            Ralph Goers
            Reporter:
            Andreas Rytina
          • Votes:
            1 Vote for this issue
            Watchers:
            6 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development