이 콘텐츠는 선택한 언어로 제공되지 않습니다.
Chapter 18. Maven Indexer Plugin
The Maven Indexer Plugin is required for the Maven plugin to enable it to quickly search Maven Central for artifacts.
To Deploy the Maven Indexer plugin use the following commands:
Prerequisites
Before deploying the Maven Indexer Plugin, make sure that you have followed the instructions in the Installing on Apache Karaf Preparing to Use Maven section.
Deploy the Maven Indexer Plugin
Go to the Karaf console and enter the following command to install the Maven Indexer plugin:
features:install hawtio-maven-indexer
Enter the following commands to configure the Maven Indexer plugin:
config:edit io.hawt.maven.indexer config:proplist config:propset repositories 'https://maven.oracle.com' config:proplist config:update
Wait for the Maven Indexer plugin to be deployed. This may take a few minutes. Look out for messages like those shown below to appear on the log tab.
When the Maven Indexer plugin has been deployed, use the following commands to add further external Maven repositories to the Maven Indexer plugin configuration:
config:edit io.hawt.maven.indexer
config:proplist
config:propset repositories external repository
config:proplist
config:update
18.1. Log
Apache Karaf provides a dynamic and powerful logging system.
It supports:
- the OSGi Log Service
- the Apache Log4j v1 and v2 framework
- the Apache Commons Logging framework
- the Logback framework
- the SLF4J framework
- the native Java Util Logging framework
It means that the applications can use any logging framework, Apache Karaf will use the central log system to manage the loggers, appenders, etc.
18.1.1. Configuration files
The initial log configuration is loaded from etc/org.ops4j.pax.logging.cfg
.
This file is a standard Log4j2 configuration file.
You find the different Log4j2 elements:
- loggers
- appenders
- layouts
You can add your own initial configuration directly in the file.
The default configuration is the following:
# # Copyright 2005-2018 Red Hat, Inc. # # Red Hat licenses this file to you under the Apache License, version # 2.0 (the "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. See the License for the specific language governing # permissions and limitations under the License. # # # Internal Log4j2 configuration # log4j2.status = WARN log4j2.verbose = false log4j2.dest = out # # Common pattern layouts for appenders defined as reusable properties # See https://logging.apache.org/log4j/2.x/manual/layouts.html#PatternLayout # references will be replaced by felix.fileinstall # log4j2.pattern = %d{DEFAULT} | %-5.5p | %-20.20t | %-32.32c{1.} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n #log4j2.pattern = %d{DEFAULT} %-5.5p {%t} [%C.%M()] (%F:%L) : %m%n # # Appenders configuration # # Console appender not used by default (see log4j2.rootLogger.appenderRefs) log4j2.appender.console.type = Console log4j2.appender.console.name = Console log4j2.appender.console.layout.type = PatternLayout log4j2.appender.console.layout.pattern = ${log4j2.pattern} # Rolling file appender log4j2.appender.rolling.type = RollingRandomAccessFile log4j2.appender.rolling.name = RollingFile log4j2.appender.rolling.fileName = ${karaf.data}/log/fuse.log log4j2.appender.rolling.filePattern = ${karaf.data}/log/fuse-%i.log.gz # uncomment to not force a disk flush #log4j2.appender.rolling.immediateFlush = false log4j2.appender.rolling.append = true log4j2.appender.rolling.layout.type = PatternLayout log4j2.appender.rolling.layout.pattern = ${log4j2.pattern} log4j2.appender.rolling.policies.type = Policies log4j2.appender.rolling.policies.size.type = SizeBasedTriggeringPolicy log4j2.appender.rolling.policies.size.size = 16MB log4j2.appender.rolling.strategy.type = DefaultRolloverStrategy log4j2.appender.rolling.strategy.max = 20 # Audit file appender log4j2.appender.audit.type = RollingRandomAccessFile log4j2.appender.audit.name = AuditRollingFile log4j2.appender.audit.fileName = ${karaf.data}/security/audit.log log4j2.appender.audit.filePattern = ${karaf.data}/security/audit.log.%i log4j2.appender.audit.append = true log4j2.appender.audit.layout.type = PatternLayout log4j2.appender.audit.layout.pattern = ${log4j2.pattern} log4j2.appender.audit.policies.type = Policies log4j2.appender.audit.policies.size.type = SizeBasedTriggeringPolicy log4j2.appender.audit.policies.size.size = 8MB # OSGi appender log4j2.appender.osgi.type = PaxOsgi log4j2.appender.osgi.name = PaxOsgi log4j2.appender.osgi.filter = * # # Loggers configuration # # Root logger log4j2.rootLogger.level = INFO log4j2.rootLogger.appenderRef.RollingFile.ref = RollingFile log4j2.rootLogger.appenderRef.PaxOsgi.ref = PaxOsgi log4j2.rootLogger.appenderRef.Console.ref = Console log4j2.rootLogger.appenderRef.Console.filter.threshold.type = ThresholdFilter log4j2.rootLogger.appenderRef.Console.filter.threshold.level = ${karaf.log.console:-OFF} #log4j2.rootLogger.appenderRef.Sift.ref = Routing # Spifly logger log4j2.logger.spifly.name = org.apache.aries.spifly log4j2.logger.spifly.level = WARN # Security audit logger log4j2.logger.audit.name = org.apache.karaf.jaas.modules.audit log4j2.logger.audit.level = INFO log4j2.logger.audit.additivity = false log4j2.logger.audit.appenderRef.AuditRollingFile.ref = AuditRollingFile # help with identification of maven-related problems with pax-url-aether #log4j2.logger.aether.name = shaded.org.eclipse.aether #log4j2.logger.aether.level = TRACE #log4j2.logger.http-headers.name = shaded.org.apache.http.headers #log4j2.logger.http-headers.level = DEBUG #log4j2.logger.maven.name = org.ops4j.pax.url.mvn #log4j2.logger.maven.level = TRACE
The default configuration defines the ROOT
logger, with INFO
log level, using the out
file appender. You can change the log level to any Log4j2 valid value. From most verbose to least verbose, you can specify TRACE, DEBUG, INFO, ERROR, or FATAL.
The osgi:*
appender is a special appender to send the log message to the OSGi Log Service.
A stdout
console appender is pre-configured, but not enabled by default. This appender allows you to display log messages directly to standard output. It’s interesting if you plan to run Apache Karaf in server mode (without console).
To enable it, you have to add the stdout
appender to the rootLogger
:
log4j2.rootLogger=INFO, out, stdout, osgi:*
The out
appender is the default one. It is a rolling file appender that maintains and rotates 10 1MB log files. The log files are located in data/log/fuse.log
by default.
The sift
appender is not enabled by default. This appender allows you to have one log file per deployed bundle. By default, the log file name format uses the bundle symbolic name (in the data/log
folder).
You can edit this file at runtime. Apache Karaf reloads the file and the changes are in effect. You do not need to restart Apache Karaf.
Another configuration file is used by Apache Karaf: etc/org.apache.karaf.log.cfg
. This files configures the Log Service used by the log commands (see later).
18.1.2. Commands
Instead of changing the etc/org.ops4j.pax.logging.cfg
file, Apache Karaf provides a set of commands allowing to dynamically change the log configuration and see the log content:
18.1.2.1. log:clear
The log:clear
command clears the log entries.
18.1.2.2. log:display
The log:display
command displays the log entries.
By default, it displays the log entries of the rootLogger
:
karaf@root()> log:display 2015-07-01 19:12:46,208 | INFO | FelixStartLevel | SecurityUtils | 16 - org.apache.sshd.core - 0.12.0 | BouncyCastle not registered, using the default JCE provider 2015-07-01 19:12:47,368 | INFO | FelixStartLevel | core | 68 - org.apache.aries.jmx.core - 1.1.1 | Starting JMX OSGi agent
You can also display the log entries from a specific logger, using the logger
argument:
karaf@root()> log:display ssh 2015-07-01 19:12:46,208 | INFO | FelixStartLevel | SecurityUtils | 16 - org.apache.sshd.core - 0.12.0 | BouncyCastle not registered, using the default JCE provider
By default, all log entries will be displayed. It could be very long if your Apache Karaf container is running since a long time. You can limit the number of entries to display using the -n
option:
karaf@root()> log:display -n 5 2015-07-01 06:53:24,143 | INFO | JMX OSGi Agent | core | 68 - org.apache.aries.jmx.core - 1.1.1 | Registering org.osgi.jmx.framework.BundleStateMBean to MBeanServer com.sun.jmx.mbeanserver.JmxMBeanServer@27cc75cb with name osgi.core:type=bundleState,version=1.7,framework=org.apache.felix.framework,uuid=5335370f-9dee-449f-9b1c-cabe74432ed1 2015-07-01 06:53:24,150 | INFO | JMX OSGi Agent | core | 68 - org.apache.aries.jmx.core - 1.1.1 | Registering org.osgi.jmx.framework.PackageStateMBean to MBeanServer com.sun.jmx.mbeanserver.JmxMBeanServer@27cc75cb with name osgi.core:type=packageState,version=1.5,framework=org.apache.felix.framework,uuid=5335370f-9dee-449f-9b1c-cabe74432ed1 2015-07-01 06:53:24,150 | INFO | JMX OSGi Agent | core | 68 - org.apache.aries.jmx.core - 1.1.1 | Registering org.osgi.jmx.framework.ServiceStateMBean to MBeanServer com.sun.jmx.mbeanserver.JmxMBeanServer@27cc75cb with name osgi.core:type=serviceState,version=1.7,framework=org.apache.felix.framework,uuid=5335370f-9dee-449f-9b1c-cabe74432ed1 2015-07-01 06:53:24,152 | INFO | JMX OSGi Agent | core | 68 - org.apache.aries.jmx.core - 1.1.1 | Registering org.osgi.jmx.framework.wiring.BundleWiringStateMBean to MBeanServer com.sun.jmx.mbeanserver.JmxMBeanServer@27cc75cb with name osgi.core:type=wiringState,version=1.1,framework=org.apache.felix.framework,uuid=5335370f-9dee-449f-9b1c-cabe74432ed1 2015-07-01 06:53:24,501 | INFO | FelixStartLevel | RegionsPersistenceImpl | 78 - org.apache.karaf.region.persist - 4.0.0 | Loading region digraph persistence
You can also limit the number of entries stored and retained using the size
property in etc/org.apache.karaf.log.cfg
file:
# # The number of log statements to be displayed using log:display. It also defines the number # of lines searched for exceptions using log:display exception. You can override this value # at runtime using -n in log:display. # size = 500
By default, each log level is displayed with a different color: ERROR/FATAL are in red, DEBUG in purple, INFO in cyan, etc. You can disable the coloring using the --no-color
option.
The log entries format pattern doesn’t use the conversion pattern define in etc/org.ops4j.pax.logging.cfg
file. By default, it uses the pattern
property defined in etc/org.apache.karaf.log.cfg
.
# # The pattern used to format the log statement when using log:display. This pattern is according # to the log4j2 layout. You can override this parameter at runtime using log:display with -p. # pattern = %d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n
You can also change the pattern dynamically (for one execution) using the -p
option:
karaf@root()> log:display -p "\%d - \%c - \%m\%n" 2015-07-01 07:01:58,007 - org.apache.sshd.common.util.SecurityUtils - BouncyCastle not registered, using the default JCE provider 2015-07-01 07:01:58,725 - org.apache.aries.jmx.core - Starting JMX OSGi agent 2015-07-01 07:01:58,744 - org.apache.aries.jmx.core - Registering MBean with ObjectName [osgi.compendium:service=cm,version=1.3,framework=org.apache.felix.framework,uuid=6361fc65-8df4-4886-b0a6-479df2d61c83] for service with service.id [13] 2015-07-01 07:01:58,747 - org.apache.aries.jmx.core - Registering org.osgi.jmx.service.cm.ConfigurationAdminMBean to MBeanServer com.sun.jmx.mbeanserver.JmxMBeanServer@27cc75cb with name osgi.compendium:service=cm,version=1.3,framework=org.apache.felix.framework,uuid=6361fc65-8df4-4886-b0a6-479df2d61c83
The pattern is a regular Log4j2 pattern where you can use keywords such as %d for the date, %c for the class, %m for the log message, etc.
18.1.2.3. log:exception-display
The log:exception-display
command displays the last occurred exception.
As for log:display
command, the log:exception-display
command uses the rootLogger
by default, but you can specify a logger with the logger
argument.
18.1.2.4. log:get
The log:get
command show the current log level of a logger.
By default, the log level shown is the one from the root logger:
karaf@root()> log:get Logger │ Level ────────────────────────────────────┼────── ROOT │ INFO org.apache.aries.spifly │ WARN org.apache.karaf.jaas.modules.audit │ INFO org.apache.sshd │ INFO
You can specify a particular logger using the logger
argument:
karaf@root()> log:get ssh INFO
The logger
argument accepts the ALL
keyword to display the log level of all logger (as a list).
For example, if you have defined your own logger in etc/org.ops4j.pax.logging.cfg
file like this:
log4j2.logger.my.name = MyLogger log4j2.logger.my.level = DEBUG
you can see the list of loggers with the corresponding log level:
karaf@root()> log:get ALL Logger │ Level ────────────────────────────────────┼────── MyLogger │ DEBUG ROOT │ INFO org.apache.aries.spifly │ WARN org.apache.karaf.jaas.modules.audit │ INFO org.apache.sshd │ INFO
The log:list
command is an alias to log:get ALL
.
18.1.2.5. log:log
The log:log
command allows you to manually add a message in the log. It’s interesting when you create Apache Karaf scripts:
karaf@root()> log:log "Hello World" karaf@root()> log:display 12:55:21.706 INFO [pipe-log:log "Hello World"] Hello World
By default, the log level is INFO, but you can specify a different log level using the -l
option:
karaf@root()> log:clear karaf@root()> log:log -l ERROR "Hello World" karaf@root()> log:display 12:55:41.460 ERROR [pipe-log:log "Hello World"] Hello World
18.1.2.6. log:set
The log:set
command sets the log level of a logger.
By default, it changes the log level of the rootLogger
:
karaf@root()> log:set DEBUG karaf@root()> log:get Logger │ Level ────────────────────────────────────┼────── ROOT │ DEBUG ...
You can specify a particular logger using the logger
argument, after the level
one:
karaf@root()> log:set INFO my.logger karaf@root()> log:get my.logger Logger | Level ----------------- my.logger | INFO
The level
argument accepts any Log4j2 log level: TRACE, DEBUG, INFO, WARN, ERROR, FATAL.
By it also accepts the DEFAULT special keyword.
The purpose of the DEFAULT keyword is to delete the current level of the logger (and only the level, the other properties like appender are not deleted) in order to use the level of the logger parent (logger are hierarchical).
For example, you have defined the following loggers (in etc/org.ops4j.pax.logging.cfg
file):
rootLogger=INFO,out,osgi:* my.logger=INFO,appender1 my.logger.custom=DEBUG,appender2
You can change the level of my.logger.custom
logger:
karaf@root()> log:set INFO my.logger.custom
Now we have:
rootLogger=INFO,out,osgi:* my.logger=INFO,appender1 my.logger.custom=INFO,appender2
You can use the DEFAULT keyword on my.logger.custom
logger to remove the level:
karaf@root()> log:set DEFAULT my.logger.custom
Now we have:
rootLogger=INFO,out,osgi:* my.logger=INFO,appender1 my.logger.custom=appender2
It means that, at runtime, the my.logger.custom
logger uses the level of its parent my.logger
, so INFO
.
Now, if we use DEFAULT keyword with the my.logger
logger:
karaf@root()> log:set DEFAULT my.logger
We have:
rootLogger=INFO,out,osgi:* my.logger=appender1 my.logger.custom=appender2
So, both my.logger.custom
and my.logger
use the log level of the parent rootLogger
.
It’s not possible to use DEFAULT keyword with the rootLogger
and it doesn’t have parent.
18.1.2.7. log:tail
The log:tail
is exactly the same as log:display
but it continuously displays the log entries.
You can use the same options and arguments as for the log:display
command.
By default, it displays the entries from the rootLogger
:
karaf@root()> log:tail 2015-07-01 07:40:28,152 | INFO | FelixStartLevel | SecurityUtils | 16 - org.apache.sshd.core - 0.9.0 | BouncyCastle not registered, using the default JCE provider 2015-07-01 07:40:28,909 | INFO | FelixStartLevel | core | 68 - org.apache.aries.jmx.core - 1.1.1 | Starting JMX OSGi agent 2015-07-01 07:40:28,928 | INFO | FelixStartLevel | core | 68 - org.apache.aries.jmx.core - 1.1.1 | Registering MBean with ObjectName [osgi.compendium:service=cm,version=1.3,framework=org.apache.felix.framework,uuid=b44a44b7-41cd-498f-936d-3b12d7aafa7b] for service with service.id [13] 2015-07-01 07:40:28,936 | INFO | JMX OSGi Agent | core | 68 - org.apache.aries.jmx.core - 1.1.1 | Registering org.osgi.jmx.service.cm.ConfigurationAdminMBean to MBeanServer com.sun.jmx.mbeanserver.JmxMBeanServer@27cc75cb with name osgi.compendium:service=cm,version=1.3,framework=org.apache.felix.framework,uuid=b44a44b7-41cd-498f-936d-3b12d7aafa7b
To exit from the log:tail
command, just type CTRL-C.
18.1.3. JMX LogMBean
All actions that you can perform with the log:*
command can be performed using the LogMBean.
The LogMBean object name is org.apache.karaf:type=log,name=*
.
18.1.3.1. Attributes
-
Level
attribute is the level of the ROOT logger.
18.1.3.2. Operations
-
getLevel(logger)
to get the log level of a specific logger. As this operation supports the ALL keyword, it returns a Map with the level of each logger. -
setLevel(level, logger)
to set the log level of a specific logger. This operation supports the DEFAULT keyword as for thelog:set
command.
18.1.4. Advanced configuration
18.1.4.1. Filters
You can apply a filter to an appender. A filter evaluates each log event and determines whether to send it to the log.
Log4j2 provides ready to use filters.
See Filters on the Log4J site for a comprehensive view into these.
18.1.4.2. Nested appenders
A nested appender is a special kind of appender that you use "inside" another appender. It allows you to create some kind of "routing" between a chain of appenders.
The most used "nested compliant" appenders are:
-
The AsyncAppender (
org.apache.log4j2.AsyncAppender
) logs events asynchronously. This appender collects the events and dispatch them to all the appenders that are attached to it. -
The RewriteAppender (
org.apache.log4j2.rewrite.RewriteAppender
) forwards log events to another appender after possibly rewriting the log event.
This kind of appender accepts an appenders
property in the appender definition:
log4j2.appender.[appender-name].appenders=[comma-separated-list-of-appender-names]
For example, you can create an AsyncAppender named async
and asynchronously dispatch the log events to a JMS appender:
log4j2.appender.async=org.apache.log4j2.AsyncAppender log4j2.appender.async.appenders=jms log4j2.appender.jms=org.apache.log4j2.net.JMSAppender ...
18.1.4.3. Error handlers
Sometimes, appenders can fail. For example, a RollingFileAppender
tries to write to the filesystem, but the filesystem is full, or a JMS appender tries to send a message, but the JMS broker is unavailable.
Logging can be critical so it is important to know if the log appender fails.
Each log appender can delegate error handling to an error handler, which provides a chance to react to an appender error.
-
The FailoverAppender (
org.apache.log4j2.varia.FailoverAppender
) allows a secondary appender to take over if the primary appender fails. The error message is printed onSystem.err
, and logged in the secondary appender.
For more on the FailoverAppender, go to Log4j2’s Apppender Page.
You can define the error handler that you want to use for each appender using the errorhandler
property on the appender definition itself:
log4j2.appender.[appender-name].errorhandler=[error-handler-class] log4j2.appender.[appender-name].errorhandler.root-ref=[true|false] log4j2.appender.[appender-name].errorhandler.logger-ref=[logger-ref] log4j2.appender.[appender-name].errorhandler.appender-ref=[appender-ref]
18.1.4.4. OSGi specific MDC attributes
The sift
appender is a OSGi oriented appender allowing you to split the log events based on MDC (Mapped Diagnostic Context) attributes.
MDC allows you to distinguish the different source of log events.
The sift
appender provides OSGi-oriented MDC attributes by default:
-
bundle.id
is the bundle ID -
bundle.name
is the bundle symbolic name -
bundle.version
is the bundle version
You can use these MDC properties to create a log file per bundle:
#log4j2.rootLogger.appenderRef.Sift.ref = Routing # Sift - MDC routing #log4j2.appender.routing.type = Routing #log4j2.appender.routing.name = Routing #log4j2.appender.routing.routes.type = Routes #log4j2.appender.routing.routes.pattern = \$\$\\\{ctx:bundle.name\} #log4j2.appender.routing.routes.bundle.type = Route #log4j2.appender.routing.routes.bundle.appender.type = RollingRandomAccessFile #log4j2.appender.routing.routes.bundle.appender.name = Bundle-\$\\\{ctx:bundle.name\} #log4j2.appender.routing.routes.bundle.appender.fileName = ${karaf.log}/bundle-\$\\\{ctx:bundle.name\}.log #log4j2.appender.routing.routes.bundle.appender.filePattern = ${karaf.log}/bundle-\$\\\{ctx:bundle.name\}.log.%i #log4j2.appender.routing.routes.bundle.appender.append = true #log4j2.appender.routing.routes.bundle.appender.layout.type = PatternLayout #log4j2.appender.routing.routes.bundle.appender.layout.pattern = ${log4j2.pattern} #log4j2.appender.routing.routes.bundle.appender.policies.type = Policies #log4j2.appender.routing.routes.bundle.appender.policies.size.type = SizeBasedTriggeringPolicy #log4j2.appender.routing.routes.bundle.appender.policies.size.size = 8MB
18.1.4.5. Enhanced OSGi stack trace renderer
By default, Apache Karaf provides a special stack trace renderer, adding some OSGi specific specific information.
In the stack trace, in addition of the class throwing the exception, you can find a pattern [id:name:version]
at the end of each stack trace line, where:
-
id
is the bundle ID -
name
is the bundle name -
version
is the bundle version
It’s very helpful to diagnosing the source of an issue.
For example, in the following IllegalArgumentException stack trace, we can see the OSGi details about the source of the exception:
java.lang.IllegalArgumentException: Command not found: *:foo at org.apache.felix.gogo.runtime.shell.Closure.execute(Closure.java:225)[21:org.apache.karaf.shell.console:4.0.0] at org.apache.felix.gogo.runtime.shell.Closure.executeStatement(Closure.java:162)[21:org.apache.karaf.shell.console:4.0.0] at org.apache.felix.gogo.runtime.shell.Pipe.run(Pipe.java:101)[21:org.apache.karaf.shell.console:4.0.0] at org.apache.felix.gogo.runtime.shell.Closure.execute(Closure.java:79)[21:org.apache.karaf.shell.console:4.0.0] at org.apache.felix.gogo.runtime.shell.CommandSessionImpl.execute(CommandSessionImpl.java:71)[21:org.apache.karaf.shell.console:4.0.0] at org.apache.karaf.shell.console.jline.Console.run(Console.java:169)[21:org.apache.karaf.shell.console:4.0.0] at java.lang.Thread.run(Thread.java:637)[:1.7.0_21]
18.1.4.6. Custom appenders
You can use your own appenders in Apache Karaf.
The easiest way to do that is to package your appender as an OSGi bundle and attach it as a fragment of the org.ops4j.pax.logging.pax-logging-service
bundle.
For example, you create MyAppender
:
public class MyAppender extends AppenderSkeleton { ... }
You compile and package as an OSGi bundle containing a MANIFEST looking like:
Manifest: Bundle-SymbolicName: org.mydomain.myappender Fragment-Host: org.ops4j.pax.logging.pax-logging-service ...
Copy your bundle in the Apache Karaf system
folder. The system
folder uses a standard Maven directory layout: groupId/artifactId/version.
In the etc/startup.properties
configuration file, you define your bundle in the list before the pax-logging-service bundle.
You have to restart Apache Karaf with a clean run (purging the data
folder) in order to reload the system bundles. You can now use your appender directly in etc/org.ops4j.pax.logging.cfg
configuration file.