Is it possible to use variable substitution when specifying the implementing class for a Logback appender? e.g.,
<appender name="LOGFILE" class="${LOGFILE_APPENDER_CLASS}">
When specified as above, Logback appears to attempt to load a class with a name of "${LOGFILE_APPENDER_CLASS}". i.e., no variable substitution is performed!
21:17:11,331 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [${LOGFILE_APPENDER_CLASS}]
21:17:11,333 |-ERROR in ch.qos.logback.core.joran.action.AppenderAction - Could not create an Appender of type [${LOGFILE_APPENDER_CLASS}]. ch.qos.logback.core.util.DynamicClassLoadingException: Failed to instantiate type ${LOGFILE_APPENDER_CLASS}
at ch.qos.logback.core.util.DynamicClassLoadingException: Failed to instantiate type ${LOGFILE_APPENDER_CLASS}
I want to send output to a file in production and console for eclipse developers. I don't want to duplicate the appender configuration if possible as it contains a long list of filters that will be the same in most cases.
As per the question, all evidence indicates that LogBack will not perform variable substitution in this scenario.
Adopted solution was to switch from XML configuration file to Groovy configuration file. Then dynamically control the list of appenders based on a "bDeveloper" variable derived from the environment.
def bDeveloper = ["","true"].contains("${System.getProperty("developer")}".toLowerCase())
if (bDeveloper) {
scan("15 seconds")
lstRootAppenders.add("BEAGLE")
oLogfileAppender = ch.qos.logback.core.ConsoleAppender
}
Related
Is String manipulation possible in YAML file??
The configuration file application.yml in a Spring Boot application is reading the version from the pom file as
<properties>
<revision>10.10.11</revision>
</properties>
The YAML file
logging:
file:
name: #revision#/app.log
The issue is, how to remove the dots from the revision value i.e.
"10.10.11" → “101011“
like
name: #revision#.replace('.', '')/app.log
, so that a log file can be generated on a folder without dots
For the general case, you could use SpEL which allows to call Java methods:
name: '#{"#revision#".replace(".", "")}'
You would need the outer quotes to tell yml that # does not start a comment, and to quote #revision# so that it is interpreted as a String by SpEL.
The problem is that it does not seem to work with logging.file.name because it is read by LoggingApplicationListener & LogFile which does not seem to interpret SpEL.
It does not seem easy to customize this through Spring Boot configuration, but you could instead define your own listener (possibly based on the one above) to define your own naming scheme.
The following question might also help: register custom log appender in spring boot starter
I am writing a new micro service using gRPC. Traditionally, when logging I used to populate the trace Id in MDC of logback and the logback configuration directly takes care of printing the trace id in all the log statements. With gRPC I am making use of Context for setting the trace id, but couldn't figure out a way to directly log them using the logback config file.
I have figured that Context is the right place to do this from this link How to intercept the headers from in call to one service and insert it to another request in gRPC-java?
Find below the pattern that I use to print values from MDC of logback in java projects.
<Pattern>%date{dd-MM-yyyy;HH:mm:ss.SSS}|[%mdc{CLIENT-ID}]|[%mdc{REQ-ID}]|[%thread] %-5level %logger{36} - %msg%n
</Pattern>
Is there a way to print the values from the Context into log statements directly like above? Is this even the right way to think about logging trace id in the logs when dealing with gRPC
Yes, you are on the right track by using the context. The way to do it is to write a custom layout (subclass LayoutBase<ILoggingEvent>) that will query the context and write it in the log. The code to query the context is:
Span span = ContextUtils.getValue(Context.current());
then to convert it to a string:
span.getContext().getTraceId().toLowerBase16()
I'm aware that you can use web.config transformations as part of the build for app.config files, but in my case, I'm trying to do this for a little scheduled task that gets deployed to an on-premise server for multiple environments.
I'd rather not have to create multiple build configurations given the only change is the app.config, so I'm trying to use the Magic Chunks extension, but due to the size of the changes I want to make, I'm having to use a json file (rather than using inline json).
When I look at the release logs, the Magic Chunks step is failing with:
2018-01-10T17:33:27.6366230Z ##[section]Starting: Config transform - \\tfs-build\Tasks\DevAzureDeliveryDaemonTest\AzureDispatchers.xml
2018-01-10T17:33:27.6366230Z ==============================================================================
2018-01-10T17:33:27.6366230Z Task : Config transformation
2018-01-10T17:33:27.6366230Z Description : Transform config file with Magic Chunks
2018-01-10T17:33:27.6366230Z Version : 2.0.3
2018-01-10T17:33:27.6366230Z Author : Sergey Zwezdin
2018-01-10T17:33:27.6366230Z Help : [More Information](https://github.com/sergeyzwezdin/magic-chunks)
2018-01-10T17:33:27.6366230Z ==============================================================================
2018-01-10T17:33:27.6522335Z Preparing task execution handler.
2018-01-10T17:33:27.8710415Z Executing the powershell script: C:\agent\_work\_tasks\MagicChunks_985284e0-a7d2-4e4d-802c-0a516bffaadf\2.0.3\transform.ps1
2018-01-10T17:33:28.4335027Z ##[error]System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
2018-01-10T17:33:28.4335027Z at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
2018-01-10T17:33:28.4335027Z at System.Reflection.Assembly.GetTypes()
2018-01-10T17:33:28.4335027Z at Microsoft.PowerShell.Commands.AddTypeCommand.LoadAssemblyFromPathOrName(List`1 generatedTypes)
2018-01-10T17:33:28.4335027Z at Microsoft.PowerShell.Commands.AddTypeCommand.EndProcessing()
2018-01-10T17:33:28.4335027Z at System.Management.Automation.CommandProcessorBase.Complete()
2018-01-10T17:33:28.4960072Z Transformation found: dispatcher[#Name='oldvalue']/#Name: newvalue
(The other transformations defined in the json file are found here, but redacted for brevity)
2018-01-10T17:33:28.4960072Z
2018-01-10T17:33:28.4960072Z
2018-01-10T17:33:28.5741199Z ##[error]System.Management.Automation.MethodInvocationException: Exception calling "Transform" with "4" argument(s): "Could not load file or assembly 'System.IO.FileSystem, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified." ---> System.IO.FileNotFoundException: Could not load file or assembly 'System.IO.FileSystem, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
2018-01-10T17:33:28.5741199Z at MagicChunks.TransformTask.Transform(String type, String sourcePath, String targetPath, TransformationCollection transformation)
2018-01-10T17:33:28.5741199Z at CallSite.Target(Closure , CallSite , Type , Object , Object , Object , Object )
2018-01-10T17:33:28.5741199Z --- End of inner exception stack trace ---
2018-01-10T17:33:28.5741199Z at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception)
2018-01-10T17:33:28.5741199Z at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame)
2018-01-10T17:33:28.5741199Z at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
2018-01-10T17:33:28.5741199Z at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
2018-01-10T17:33:28.5741199Z ##[error]PowerShell script completed with 2 errors.
2018-01-10T17:33:28.5897571Z ##[section]Finishing: Config transform - \\tfs-build\Tasks\DevAzureDeliveryDaemonTest\AzureDispatchers.xml
Has anyone seen this before, and know how to resolve (or know of a better way to achieve this)?
This appears to be an issue with version 2.x of the Magic Chunks Task. Until that is resolved, changing the release to use version 1.x of the task allows to complete
When I use logback as logging framework, I add logger configuration on runtime for debugging. For example set "org.springframework" to debug level.
after I find the data I need I want to remove this configuration without restarting the application.
How can I do that?
You have two options depending upon how you want to modify the log level.
First option - using logback.xml
Logback xml provides an option to periodically scan the configuration. By setting that, you ask the logger framework to periodically update its in-memory setting to sync with the XML configuration. When you want to enable debug mode, XML configuration will look as below:
<configuration scan="true" scanPeriod="30 seconds">
<!-- Appender configurations here -->
<logger name="org.springframework" level="debug" additivity="false">
<appender-ref ref="YOUR_APPENDER_NAME"/>
</logger>
<!-- Other logger configurations (including root) go here -->
</configuration>
After you complete your task, you can either delete that logger entry or set the level to ERROR to stop logging for that package.
Second option - In-memory
If you don't want to touch your logback.xml, but somehow handle it in runtime (say, using some REST APIs of you application), you may get the specific logger instance and set the level to DEBUG. Once you complete your activity, you may set the level to 'null' so that the level is inherited from the parent. Sample code will be as below:
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import org.slf4j.LoggerFactory;
.....
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
Logger logger = context.getLogger("org.springframework");
logger.setLevel((Level.toLevel("DEBUG"));
// Do your task
logger.setLevel(null); // When we do this, level will be inherited from parent.
logback has an option that allows periodic rescanning of the configuration file to look for changes.
<configuration scan="true">
...
</configuration>
Windows Phone 8 C# project (MyApp), migrated from WP7.1. I've added a native Windows Runtime component library (AppLib) to the solution, created a reference. There's a public sealed ref class (MyClass) in it. There's a reference to it in the C# code (in OnLoaded of the main XAML page). The whole thing compiles - meaning the metadata of the component is being generated.
When I'm trying to run, the project fails with the exception or type TypeLoadException with the following message:
Typename or Namespace was not found in metadata file. (Exception from HRESULT: 0x8000000F)
Both AppLib.DLL and AppLib.winmd can be found in the XAP. The winmd contains the information about the type, and in the right namespace, too. What else should I check?
At exception time, the AppLib.dll is not listed in the modules window of the debugger. It's as if the DLL loading fails for some reason.
I've tried with brand new class in an arbitrary namespace - same problem. Looks like the problem is on the DLL level, not on class level.
The name of the WinMD file must be a prefix of the name of the namespace in which any public and activatable types are declared. For example, if your WinMD is named AppLib.winmd, your MyClass type must be defined in namespace AppLib or some other namespace nested within that namespace, for example AppLib::Something.
It must also be declared in the "best matching" WinMD, so if your type is named A.B.MyClass and you have both A.winmd and A.B.winmd in your package, the type must be defined in A.B.winmd.
The Windows Runtime uses the name of the type to determine which WinMD file defines the type. See also my answer to "XAML cannot find reference in local namespace."