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.
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 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
i am trying to store my info level log amd error level log in separate files. My error messages are being dumped correctly but info messages contain both error as well as info messages. Following is my properties file:
log4j.rootLogger = DEBUG, inf, err
log4j.appender.inf = org.apache.log4j.FileAppender
log4j.appender.inf.layout = org.apache.log4j.PatternLayout
log4j.appender.inf.layout.ConversionPattern = %d{ISO8601} %-5p %c ~ %m%n
log4j.appender.inf.File = information.log
log4j.appender.inf.Threshold = INFO
log4j.appender.inf.filter = org.apache.log4j.varia.LevelMatchFilter
log4j.appender.inf.filter.levelToMatch = INFO
log4j.appender.inf.Append = false
log4j.appender.inf.AcceptOnMatch = true
log4j.appender.inf.filter = org.apache.log4j.varia.DenyAllFilter
log4j.appender.err = org.apache.log4j.FileAppender
log4j.appender.err.layout = org.apache.log4j.PatternLayout
log4j.appender.err.layout.ConversionPattern = %d{ISO8601} %-5p %c ~ %m%n
log4j.appender.err.File = errormsg.log
log4j.appender.err.Threshold = ERROR
log4j.appender.err.filter = org.apache.log4j.varia.LevelMatchFilter
log4j.appender.err.filter.levelToMatch = ERROR
log4j.appender.err.Append = false
and my .java file is as follows:
package test;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
public class HelloLogger {
private static Logger logger = Logger.getLogger(HelloLogger.class);
public static void main(String[] args) {
PropertyConfigurator.configure("log4jconfig.properties");
logger.error("This is error");
logger.info("This is info");
logger.debug("This is debug");
}
}
Pls help.. Thanx in advance
According to this answer, the properties file is not designed to handle filters, but it may work if you change your properties file to separate the first appender's filters with IDs (ie 1 and 2):
log4j.appender.inf.filter.1 = org.apache.log4j.varia.LevelMatchFilter
log4j.appender.inf.filter.1.levelToMatch = INFO
log4j.appender.inf.Append = false
log4j.appender.inf.AcceptOnMatch = true
log4j.appender.inf.filter.2 = org.apache.log4j.varia.DenyAllFilter
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 want to post some request values alongside the multipart-formdata file contents. In the old API you could use PostFileWithRequest:
[Test]
public void Can_POST_upload_file_using_ServiceClient_with_request()
{
IServiceClient client = new JsonServiceClient(ListeningOn);
var uploadFile = new FileInfo("~/TestExistingDir/upload.html".MapProjectPath());
var request = new FileUpload{CustomerId = 123, CustomerName = "Foo"};
var response = client.PostFileWithRequest<FileUploadResponse>(ListeningOn + "/fileuploads", uploadFile, request);
var expectedContents = new StreamReader(uploadFile.OpenRead()).ReadToEnd();
Assert.That(response.FileName, Is.EqualTo(uploadFile.Name));
Assert.That(response.ContentLength, Is.EqualTo(uploadFile.Length));
Assert.That(response.Contents, Is.EqualTo(expectedContents));
Assert.That(response.CustomerName, Is.EqualTo("Foo"));
Assert.That(response.CustomerId, Is.EqualTo(123));
}
I can't find any such method in the new API, nor any overrides on client.Post() which suggest that this is still possible. Does anyone know if this is a feature that was dropped?
Update
As #Mythz points out, the feature wasn't dropped. I had made the mistake of not casting the client:
private IRestClient CreateRestClient()
{
return new JsonServiceClient(WebServiceHostUrl);
}
[Test]
public void Can_WebRequest_POST_upload_binary_file_to_save_new_file()
{
var restClient = (JsonServiceClient)CreateRestClient(); // this cast was missing
var fileToUpload = new FileInfo(#"D:/test/test.avi");
var beforeHash = this.Hash(fileToUpload);
var response = restClient.PostFileWithRequest<FilesResponse>("files/UploadedFiles/", fileToUpload, new TestRequest() { Echo = "Test"});
var uploadedFile = new FileInfo(FilesRootDir + "UploadedFiles/test.avi");
var afterHash = this.Hash(uploadedFile);
Assert.That(beforeHas, Is.EqualTo(afterHash));
}
private string Hash(FileInfo file)
{
using (var md5 = MD5.Create())
{
using (var stream = file.OpenRead())
{
var bytes = md5.ComputeHash(stream);
return BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "").ToLower();
}
}
}
None of the old API was removed from the C# Service Clients, only new API's were added.
The way you process an uploaded file inside a service also hasn't changed.