I am trying to log events of a Java application to separate log files based on a key set to the ThreadContext. But my key is not reaching the child thread (created on MouseEvent) even after setting "log4j2.isThreadContextMapInheritable" to "true" in system properties. Someone please help me to get this resolved.
My main method:
public class Application {
static {
System.setProperty("log4j2.isThreadContextMapInheritable","true");
}
private final static Logger LOGGER = LogManager.getLogger(Application.class);
public static void main(String[] args) throws Exception
{
ThreadContext.put("cfg","RLS");
LOGGER.info("New window opening!!!"+ThreadContext.get("cfg"));
newWindow();
}
private static void newWindow() throws Exception {
ButtonFrame buttonFrame = new ButtonFrame("Button Demo");
buttonFrame.setSize( 350, 275 );
buttonFrame.setVisible( true );
}
}
ButtonFrame class:
public class ButtonFrame extends JFrame{
private final static Logger LOGGER = LogManager.getLogger(NewWindow.class);
JButton bChange;
JFrame frame = new JFrame("Our JButton listener example");
public ButtonFrame(String title)
{
super( title );
setLayout( new FlowLayout() );
bChange = new JButton("Click Me!");
bChange.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
try {
LOGGER.info("Mouse clicked!!!"+ThreadContext.get("cfg"));
JDialog d = new JDialog(frame, "HI", true);
d.setLocationRelativeTo(frame);
d.setVisible(true);
} catch (Exception e1) {
e1.printStackTrace();
}
}
#Override
public void mousePressed(MouseEvent e) {}
#Override
public void mouseReleased(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
});
add( bChange );
setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
}
log4j2.properties file:
appenders = rls,otr,routing
appender.rls.type = RollingFile
appender.rls.name = RollingFile_Rls
appender.rls.fileName = D:\\RLS\\rls_%d{MMdd}.log
appender.rls.filePattern = D:\\RLS\\rls_%d{MMdd}.log
appender.rls.layout.type = PatternLayout
appender.rls.layout.pattern = %d{ABSOLUTE} %level{length=1}
%markerSimpleName [%C{1}:%L] %m%n
appender.rls.policies.type = Policies
appender.rls.policies.time.type = TimeBasedTriggeringPolicy
appender.rls.policies.time.interval = 1
appender.rls.policies.time.modulate = true
appender.rls.policies.size.type = SizeBasedTriggeringPolicy
appender.rls.policies.size.size = 100MB
appender.rls.strategy.type = DefaultRolloverStrategy
appender.rls.strategy.max = 5
appender.otr.type = RollingFile
appender.otr.name = RollingFile_Otr
appender.otr.fileName = D:\\RLS\\otr_%d{MMdd}.log
appender.otr.filePattern = D:\\RLS\\otr_%d{MMdd}.log
appender.otr.layout.type = PatternLayout
appender.otr.layout.pattern = %d{ABSOLUTE} %level{length=1}
%markerSimpleName [%C{1}:%L] %m%n
appender.otr.policies.type = Policies
appender.otr.policies.time.type = TimeBasedTriggeringPolicy
appender.otr.policies.time.interval = 1
appender.otr.policies.time.modulate = true
appender.otr.policies.size.type = SizeBasedTriggeringPolicy
appender.otr.policies.size.size = 100MB
appender.otr.strategy.type = DefaultRolloverStrategy
appender.otr.strategy.max = 5
appender.routing.type = Routing
appender.routing.name = Route_Finder
appender.routing.routes.type = Routes
appender.routing.routes.pattern = $${ctx:cfg}
appender.routing.routes.route1.type = Route
appender.routing.routes.route1.ref = RollingFile_Rls
appender.routing.routes.route1.key = RLS
appender.routing.routes.route2.type = Route
appender.routing.routes.route2.ref = RollingFile_Otr
appender.routing.routes.route2.key = $${ctx:cfg}
loggers = rls,otr
logger.rls.name = logging
logger.rls.level = info
logger.rls.additivity = false
logger.rls.appenderRefs=rls
logger.rls.appenderRef.rls.ref = Route_Finder
logger.rls.name = logging
logger.rls.level = info
logger.rls.additivity = false
logger.rls.appenderRefs=rls
logger.rls.appenderRef.rls.ref = Route_Finder
logger.otr.name = other
logger.otr.level = info
logger.otr.additivity = false
logger.otr.appenderRefs=otr
logger.otr.appenderRef.otr.ref = Route_Finder
rootLogger.level = trace
rootLogger.appenderRefs = stdout
rootLogger.appenderRef.stdout.ref = stdout
You can put log4j2.component.properties file in the classpath to control various aspects of Log4j 2 behavior.
For example content of log4j2.component.properties:
# https://logging.apache.org/log4j/2.x/manual/configuration.html#SystemProperties
# If true use an InheritableThreadLocal to implement the ThreadContext map.
# Otherwise, use a plain ThreadLocal.
# (Maybe ignored if a custom ThreadContext map is specified.)
# Default is false
# Modern 2.10+
log4j2.isThreadContextMapInheritable=true
# Legacy for pre-2.10
isThreadContextMapInheritable=true
This has priority over system properties, but it can be overridden by environment variable LOG4J_IS_THREAD_CONTEXT_MAP_INHERITABLE as described in the
documentation.
Adding OP's comment as answer
The ThreadContext map can be configured to use an InheritableThreadLocal by setting system property isThreadContextMapInheritable to true.
Set the system property as -DisThreadContextMapInheritable=true when we start our application, or in application code using the following piece of code: System.setProperty("isThreadContextMapInheritable", "true");
https://logging.apache.org/log4j/2.x/manual/thread-context.html
https://logging.apache.org/log4j/2.x/manual/configuration.html#SystemProperties
Related
code below is the example given by the apache log4j2 ,but how can i configure KafkaAppender in this way?
#Plugin(name = "CustomConfigurationFactory", category = ConfigurationFactory.CATEGORY)
#Order(50)
public class CustomConfigurationFactory extends ConfigurationFactory {
static Configuration createConfiguration(final String name, ConfigurationBuilder<BuiltConfiguration> builder) {
builder.setConfigurationName(name);
builder.setStatusLevel(Level.INFO);
// builder.add(builder.newFilter("ThresholdFilter", Filter.Result.ACCEPT, Filter.Result.NEUTRAL).
// addAttribute("level", Level.DEBUG));
AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE").
addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
appenderBuilder.add(builder.newLayout("PatternLayout").
addAttribute("pattern", "%d [%t] %-5level: %msg%n%throwable"));
// appenderBuilder.add(builder.newFilter("MarkerFilter", Filter.Result.DENY,
// Filter.Result.NEUTRAL).addAttribute("marker", "FLOW"));
AppenderComponentBuilder kafkaAppender = builder.newAppender("Stdout", "CONSOLE").
addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
builder.add(appenderBuilder);
builder.add(builder.newLogger("org.apache.logging.log4j", Level.DEBUG).
add(builder.newAppenderRef("Stdout")).
addAttribute("additivity", false));
builder.add(builder.newRootLogger(Level.INFO).add(builder.newAppenderRef("Stdout")));
return builder.build();
}
}
i solved it ,
final AppenderComponentBuilder ddlKafkaAppender = builder.newAppender("ddl-kafka", "Kafka").addAttribute("topic", config.getDdlTopic());
ddlKafkaAppender.addComponent(builder.newProperty("bootstrap.servers", config.getHost()));
ddlKafkaAppender.add(builder.newLayout("PatternLayout").
addAttribute("pattern", "%message"));
builder.add(ddlKafkaAppender);
final AppenderComponentBuilder sqlKafkaAppender = builder.newAppender("sql-kafka", "Kafka").addAttribute("topic", config.getSqlTopic());
sqlKafkaAppender.addComponent(builder.newProperty("bootstrap.servers", config.getHost()));
sqlKafkaAppender.add(builder.newLayout("PatternLayout").
addAttribute("pattern", "%message"));
builder.add(sqlKafkaAppender);
builder.add(builder.newLogger("org.apache.logging.log4j", Level.DEBUG).
add(builder.newAppenderRef("Stdout")).
addAttribute("additivity", false));
builder.add(builder.newLogger("sql", Level.INFO).
add(builder.newAppenderRef("sql-kafka")));
builder.add(builder.newLogger("ddl", Level.INFO).
add(builder.newAppenderRef("ddl-kafka")));
I have been trying to override the Process Delegate for the page "Update Contract Price".
public ContractPriceUpdate()
{
Items.SetSelected<ContractDetail.selected>();
Items.SetProcessDelegate<ContractMaint>(UpdatePrices);
Items.SetProcessCaption(Messages.Update);
Items.SetProcessAllCaption(Messages.UpdateAll);
PXUIFieldAttribute.SetDisplayName<Contract.contractCD>(Caches[typeof(Contract)], Common.Messages.Identifier);
}
protected static void UpdatePrices(ContractMaint graph, ContractDetail item)
{
Contract contract = PXSelect<Contract, Where<Contract.contractID, Equal<Required<Contract.contractID>>>>.Select(graph, item.ContractID);
using (PXTransactionScope ts = new PXTransactionScope())
{
if (contract.IsTemplate != true)
{
ContractMaintExt contractMaintExt = CreateInstance<ContractMaintExt>();
contractMaintExt.Contracts.Current = contract;
if (contract.IsActive == true &&
contract.IsPendingUpdate != true &&
contract.Status != Contract.status.PendingActivation)
{
CTBillEngine engine = CreateInstance<CTBillEngine>();
engine.Upgrade(contract.ContractID);
engine.Clear();
contractMaintExt.Contracts.Current = PXSelect<Contract, Where<Contract.contractID, Equal<Required<Contract.contractID>>>>.Select(engine, item.ContractID);
item = PXSelect<ContractDetail,
Where<ContractDetail.contractID, Equal<Required<ContractDetail.contractID>>,
And<ContractDetail.lineNbr, Equal<Required<ContractDetail.lineNbr>>>>>.Select(engine, item.ContractID, item.LineNbr);
}
contractMaintExt.ContractDetails.Cache.SetDefaultExt<ContractDetail.basePriceOption>(item);
contractMaintExt.ContractDetails.Cache.SetDefaultExt<ContractDetail.basePrice>(item);
contractMaintExt.ContractDetails.Cache.SetDefaultExt<ContractDetail.renewalPriceOption>(item);
contractMaintExt.ContractDetails.Cache.SetDefaultExt<ContractDetail.renewalPrice>(item);
contractMaintExt.ContractDetails.Cache.SetDefaultExt<ContractDetail.fixedRecurringPriceOption>(item);
contractMaintExt.ContractDetails.Cache.SetDefaultExt<ContractDetail.fixedRecurringPrice>(item);
contractMaintExt.ContractDetails.Cache.SetDefaultExt<ContractDetail.usagePriceOption>(item);
contractMaintExt.ContractDetails.Cache.SetDefaultExt<ContractDetail.usagePrice>(item);
contractMaintExt.ContractDetails.Update(item);
contractMaintExt.Actions.PressSave();
}
else
{
TemplateMaint templateMaint = CreateInstance<TemplateMaint>();
templateMaint.Templates.Current = PXSelect<ContractTemplate, Where<ContractTemplate.contractID, Equal<Required<ContractTemplate.contractID>>>>.Select(graph, item.ContractID);
templateMaint.ContractDetails.Cache.SetDefaultExt<ContractDetail.basePriceOption>(item);
templateMaint.ContractDetails.Cache.SetDefaultExt<ContractDetail.basePrice>(item);
templateMaint.ContractDetails.Cache.SetDefaultExt<ContractDetail.renewalPriceOption>(item);
templateMaint.ContractDetails.Cache.SetDefaultExt<ContractDetail.renewalPrice>(item);
templateMaint.ContractDetails.Cache.SetDefaultExt<ContractDetail.fixedRecurringPriceOption>(item);
templateMaint.ContractDetails.Cache.SetDefaultExt<ContractDetail.fixedRecurringPrice>(item);
templateMaint.ContractDetails.Cache.SetDefaultExt<ContractDetail.usagePriceOption>(item);
templateMaint.ContractDetails.Cache.SetDefaultExt<ContractDetail.usagePrice>(item);
templateMaint.ContractDetails.Update(item);
templateMaint.Actions.PressSave();
}
ts.Complete();
}
}
Here I need to customize this condition:
if (contract.IsActive == true &&
contract.IsPendingUpdate != true &&
contract.Status != Contract.status.PendingActivation)
I tried to override the constructor to with my own custom static method where I would rewrite all the code but change the condition like this, but it is not working:
public override void Initialize()
{
var processDelegate = (PXProcessingBase<ContractDetail>.ProcessListDelegate)Base.Items.GetProcessDelegate();
Base.Items.SetProcessDelegate<ContractMaint>(UpdatePricesProc);
}
#region Event Handlers
public static void UpdatePricesProc(ContractMaint graph, ContractDetail item)
{
Contract contract = PXSelect<Contract, Where<Contract.contractID, Equal<Required<Contract.contractID>>>>.Select(graph, item.ContractID);
}
Need help to figure this out. Thanks.
I tried the following code based on other responses on how to add custom appender programmatically. I do see log messages appear on the console, but I do not see them in a locally running Seq server. I verified the Seq URL was set http://localhost:5341/. I also tried a hosted version of Seq with API Key to see if I could catch anything being set via Fiddler, but nothing is sent. What am I missing?
public static void SetLevel(string loggerName, string levelName)
{
ILog log = LogManager.GetLogger(loggerName);
Logger l = (Logger)log.Logger;
l.Level = l.Hierarchy.LevelMap[levelName];
}
// Add an appender to a logger
public static void AddAppender(string loggerName, IAppender appender)
{
ILog log = LogManager.GetLogger(loggerName);
Logger l = (Logger)log.Logger;
l.AddAppender(appender);
l.Repository.Configured = true;
}
// Create a new file appender
public static IAppender CreateSeqAppender(string name)
{
var seqAppender = new SeqAppender();
seqAppender.ServerUrl = ConfigurationManager.AppSettings["Seq:Url"];
var seqApiKey = ConfigurationManager.AppSettings["Seq:ApiKey"];
if (seqApiKey != null)
{
seqAppender.ApiKey = seqApiKey;
}
PatternLayout patternLayout = new PatternLayout();
var LOG_PATTERN = "%d [%t] %-5p %m%n";
patternLayout.ConversionPattern = LOG_PATTERN;
patternLayout.ActivateOptions();
seqAppender.Name = name;
seqAppender.BufferSize = 1;
seqAppender.Layout = patternLayout;
seqAppender.ActivateOptions();
return seqAppender;
}
static void Main()
{
BasicConfigurator.Configure();
// In order to set the level for a logger and add an appender reference you
// can then use the following calls:
SetLevel("Log4net.MainForm", "ALL");
AddAppender("Log4net.MainForm", CreateSeqAppender("SeqAppender"));
//BasicConfigurator.Configure();
var logger = LogManager.GetLogger("MyLogger");
logger.Info("This is a test log message");
}
After a bit more investigation I figured out how to get this to work. Instead the code in AddAppender above I just did the following:
var root = ((Hierarchy)LogManager.GetRepository()).Root;
root.AddAppender(CreateSeqAppender());
Hopefully, this helps someone else out.
I am developing VoIP application (Dialler) in windows phone 8, In that application contain dial pad , contacts, call log , I already create a dial pad and contact list, I need to develop a call log function in that application. I struggle in to create a call log for windows phone 8 any help please
This is a class that creates an XML file which holds the logs of all calls. You didn't specify the question enough or what you want to do, or what have you already tried. So here is an idea of what you should implement:
public class Logger
{
private static string logPath;
public Logger()
{
logPath = "/Logs/log.xml";
}
public void LogData(string contactName, string duration)
{
Object thisLock = new Object();
logPath += DateTime.Now.ToShortDateString().Replace('.', '_') + ".log";
XmlDocument doc = new XmlDocument();
lock (thisLock)
{
try
{
XmlNode root = null;
if (File.Exists(logPath))
{
doc.Load(logPath);
root = doc.SelectSingleNode("/Call");
}
else
{
doc.AppendChild(doc.CreateXmlDeclaration("1.0", "UTF-8", null));
root = doc.AppendChild(doc.CreateElement("Call"));
}
XmlElement call = doc.CreateElement("call");
root.AppendChild(call);
XmlElement xcontactName = doc.CreateElement("contactName");
xcontactName.InnerText = contactName;
call.AppendChild(xcontactName);
XmlElement xdate = doc.CreateElement("date");
xdate.InnerText = DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss");
call.AppendChild(xdate);
XmlElement xduration = doc.CreateElement("duration");
xduration.InnerText = duration;
call.AppendChild(xduration);
doc.Save(logPath);
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
}
}
}
I would like to create a method that orders an IEnumerable List by a given property where the property is passed into the method by a string i.e. (Mind you the first code example does not work, but the second does and is what I am trying to emulate dynamically).
string sortName = "SerialNumber";
IEnumerable<PartSummary> partList = FunctionToCreateList();
partOrderedList = partList.OrderBy(what do I stick in here);
that would be equivalent to
IEnumerable<PartSummary> partList = FunctionToCreateList();
partOrderedList = partList.OrderBy(p => p.SerialNumber);
How can I accomplish this?
Are you saying you want to pass the order by in to your method? If so, you can use this:
Expression<Func<PartSummary, bool>> orderByClause
Then you can do this:
partOrderedList = partList.OrderBy(orderByClause);
Then you can handle your order by in your business layer or wherever you wish.
Okay, update: If you want to pass in the column name as a string you can do something like as follows:
Create a static class for an extension method (reference: http://social.msdn.microsoft.com/Forums/en-US/linqprojectgeneral/thread/39028ad2-452e-409f-bc9e-d1b263e921f6/):
static class LinqExtensions
{
public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string sortingColumn, bool isAscending)
{
if (String.IsNullOrEmpty(sortingColumn))
{
return source;
}
ParameterExpression parameter = Expression.Parameter(source.ElementType, String.Empty);
MemberExpression property = Expression.Property(parameter, sortingColumn);
LambdaExpression lambda = Expression.Lambda(property, parameter);
string methodName = isAscending ? "OrderBy" : "OrderByDescending";
Expression methodCallExpression = Expression.Call(typeof(Queryable), methodName,
new Type[] { source.ElementType, property.Type },
source.Expression, Expression.Quote(lambda));
return source.Provider.CreateQuery<T>(methodCallExpression);
}
}
Then you can create your method:
static IQueryable<PartSummary> FunctionToCreateList()
{
IList<PartSummary> list = new List<PartSummary>();
list.Add(new PartSummary
{
Id = 1,
SerialNumber = "A",
});
list.Add(new PartSummary
{
Id = 2,
SerialNumber = "B",
});
return list.AsQueryable();
}
And then call your method:
static void Main(string[] args)
{
IQueryable<PartSummary> partOrderedList = FunctionToCreateList();
PartSummary partSummary = new PartSummary();
string sortBy = "Id";
partOrderedList = partOrderedList.OrderBy(sortBy, false);
foreach (PartSummary summary in partOrderedList)
{
Console.WriteLine(summary.Id + ", " + summary.SerialNumber);
}
Console.ReadLine();
}
Now you can pass in the column name as a string and sort.
Hope this helps!
You can also avoid extending and just use a compiled expression tree to accomplish this:
public Func<T, object> ResolveToProperty<T>(String propertyName)
{
Type t = typeof(T);
var paramExpression = Expression.Parameter(t, "element");
var propertyExpression = Expression.Property(paramExpression, propertyName);
return Expression.Lambda<Func<T, object>>(propertyExpression, paramExpression).Compile();
}
string sortName = "SerialNumber";
IEnumerable<PartSummary> partList = FunctionToCreateList();
var partOrderedList = partList.OrderBy(ResolveToProperty<PartSummary>(sortName));