I need to configure NLog settings from another application, essentially I have a main Application and a Configuration Application and need to set some log settings from the Configuration Application.
I have tried below but minlevel is an enum and is not valid.. :(
<logger name="*" minlevel="${appsetting:MinimumLogLevel}" writeTo="File" />
It would be perfect for this to work, any suggestions?
Thanks
** Updated Answer **
NLog ver. 4.6 added support for using NLog-Config-Variables in minLevel. See https://github.com/NLog/NLog/pull/2709
NLog ver. 4.6.7 added support for adjusting minLevel at runtime, by modifying NLog-Config-Variables and calling ReconfigExistingLoggers(). See https://github.com/NLog/NLog/pull/3184
** Original Answer **
the minlevel attribute is indeed not a Layout, so you can't use layout renderers like `${appsetting}.
You could do it programmatically:
var configuration = LogManager.Configuration;
//TODO find correct rule
var rule = configuration.LoggingRules[0];
//disable all
rule.DisableLoggingForLevel(LogLevel.Trace);
rule.DisableLoggingForLevel(LogLevel.Debug);
rule.DisableLoggingForLevel(LogLevel.Trace);
rule.DisableLoggingForLevel(LogLevel.Info);
rule.DisableLoggingForLevel(LogLevel.Warn);
rule.DisableLoggingForLevel(LogLevel.Error);
rule.DisableLoggingForLevel(LogLevel.Fatal);
var minLevelRaw = System.Configuration.ConfigurationManager.AppSettings["minLevel"];
var minLevel = LogLevel.FromString(minLevelRaw);
//enable correct one
rule.EnableLoggingForLevels(minLevel, LogLevel.Fatal); //enable from minLevel to fatal
LogManager.Configuration = configuration;
or if it should work for all rules, you could use GlobalThreshold:
var minLevelRaw = System.Configuration.ConfigurationManager.AppSettings["minLevel"];
var minLevel = LogLevel.FromString(minLevelRaw);
LogManager.GlobalThreshold = minLevel;
Related
Azure App Functions 3.0
I am attempting to log activities and errors from an internal class used by functions but the logs are not correct written, since I cannot instantiate/find the service binded to the correct "ILogger" (the one naturally injected in constructors and functions).
I do not want to pass down the Logger instance through classes from the entry point, but inject it correctly.
Tried new LoggerFactory() with no success.
var loggerFactory = new LoggerFactory();
var logger = loggerFactory.CreateLogger("InfoLogger");
logger.LogInformation("Please, log this information!");
Tried ActivatorUtilities.CreateInstance() with Ninject registering the service provider associated with the logger at startup with no success.
// Startup.cs
NinjectKernel._kernel
.Bind<IServiceProvider>()
.ToMethod(context => builder.Services.BuildServiceProvider())
.InSingletonScope();
// MyInternalClass.cs
var serviceProvider = NinjectKernel.Get<IServiceProvider>();
var logger = ActivatorUtilities.CreateInstance<ILogger>(serviceProvider);
logger.LogInformation($"Information Ticket: {ticket} | Data: ...");
Any help are welcome!
I'm working against Azure websites where the portal can be used to over-ride values in the web.config's AppSetting and ConnectionString sections. But other sections still require a transform or hard-coding of the web.config. I need to apply the same control over values found at /configuration/system.net/mailSettings/smtp
Ideally, I'd like to store a string in an AppSetting value and then, when the site boots, it parses this string and over-writes the initial contents of my SMTP section with parsed values found in AppSettings.
Big picture objective: eliminate reliance on hard-coded smtp values of the web.config and instead, apply those values from the portal's listing of AppSettings. Possible?
thx
I'm not too familiar with System.Net.Mail, but you can always read and initialize your own config. You can set the following AppSettings in the portal
smtp.host = <hostName>
smtp.port = <port>
smtp.userName = <userName>
smtp.password = <password>
smtp.defaultCredentials = <true | false>
and then have something like that in your code.
public SmtpClient GetSmtpClient()
{
Func<string, string> config = s => ConfigurationManager.AppSettings[s] ?? System.Environment.GetEnvironmentVariable(s);
return new SmtpClient
{
Host = config("smtp.host"),
Port = int.Parse(config("smtp.port")), // handle parsing errors
Credentials = new NetworkCredential(config("smtp.userName"), config("smtp.userName")),
UseDefaultCredentials = bool.Parse(config("smtp.defaultCredentials")), //handle parsing errors
};
}
then when debugging locally you can rely on Environment Variables and when deploying to Azure you use the AppSettings.
i need help to using this below configuration in xml file to change my url web service,
`<configuration>
<appSettings>
<add key="UserName" value="ova"/>
<add key="UserPassword" value="ova"/>
<add key="ServiceName" value="xe"/>
<add key="ServerName" value="localhost"/>
<add key="WebService" value="/FDC_Service/FDC_Service.asmx"/>
</appSettings>
</configuration>`
and its code i need to chnange with calling server name and web service in source Code appliation, like this below
FDC_Service.FDC_ServiceClass asd = new FDC_Service.FDC_ServiceClass();
retval = asd.FDC_Command(database.UserName, database.UserPassword, database.ServiceName, str);
FDC_Service is my web service, i need help
thanks....
I hope this answers your question
in you .cs code add
using System.Configuration;
Then in your method add
var username = ConfigurationManager.AppSettings["UserName"];
var password = ConfigurationManager.AppSettings["UserPassword"];
var serviceName = ConfigurationManager.AppSettings["ServerName"];
FDC_Service.FDC_ServiceClass asd = new FDC_Service.FDC_ServiceClass();
retval = asd.FDC_Command(username, password, serviceName, str);
This is working for me. Set the appropriate uri when instantiating:
ws = new wsPedidosWeb.OperacionesTiendaPortTypeClient(
new wsPedidosWeb.OperacionesTiendaPortTypeClient.EndpointConfiguration(),
new uri("http://whatever")
);
In case someone is looking for the full code; like I did:
private static string GetServiceAddressUrlByContractName(string contractFullName)
{
var clientSection = WebConfigurationManager
.GetSection("system.serviceModel/client") as ClientSection;
var endpointList = clientSection?.Endpoints.Cast<ChannelEndpointElement>().ToList();
return endpointList?.FirstOrDefault(e => e.Contract== contractFullName)?.Address.ToString();
}
I'm not using any XML configuration and am doing everything at run time.
My application runs and Jersey my API works, but I'm not seeing any logs being written. I expect to see something like INFO: [MyApp] Initializing log4j from [classpath:environment-${MY_ENVIRONMENT}.properties]
when this application boots up to confirm it's seeing the log4j configuration.
I've avoided using log4j.properties since I want different logging configuration per my application's environment.
How can I get this application writing logs via my log configuration?
My main class is:
import com.sun.jersey.api.container.grizzly2.GrizzlyServerFactory;
import com.sun.jersey.api.core.PackagesResourceConfig;
import com.sun.jersey.api.core.ResourceConfig;
import com.sun.jersey.api.json.JSONConfiguration;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.grizzly.servlet.WebappContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.web.context.ContextLoaderListener;
...
protected static HttpServer startServer() throws IOException {
ResourceConfig rc = new PackagesResourceConfig("com.company.product.api.resources");
Map<String,Boolean> features = rc.getFeatures();
features.put(JSONConfiguration.FEATURE_POJO_MAPPING, true);
return GrizzlyServerFactory.createHttpServer(BASE_URI, rc);
}
public static void main(String[] args) throws IOException {
//Without this, ApplicationContextProvider has no context
AnnotationConfigApplicationContext annotationCtx = new AnnotationConfigApplicationContext(Config.class);
//The only reason this is here is because I think I need it for log4j config
WebappContext ctx = new WebappContext("API", "/");
//enable log4j configuration
ctx.addListener("org.springframework.web.util.Log4jConfigListener");
ctx.addContextInitParameter("log4jConfigLocation", "classpath:environment-${MY_ENVIRONMENT}.properties");
//enable annotation configuration so we can avoid XML
ctx.addContextInitParameter("contextClass", "org.springframework.web.context.support.AnnotationConfigWebApplicationContext");
ctx.addContextInitParameter("contextConfigLocation", "com.company.product.api");
//allow spring to do all of it's stuff
ctx.addListener(ContextLoaderListener.class);
HttpServer httpServer = startServer();
System.in.read();
httpServer.stop();
}
In environment-production.properties, all configuration is properly being used, except for log4j:
# Define the root logger with appender file
log4j.rootLogger = DEBUG, FILE
# Define the file appender
log4j.appender.FILE=org.apache.log4j.DailyRollingFileAppender
# Set the name of the file
log4j.appender.FILE.File=/var/log/productionApi/productionApi.log
# Set the immediate flush to true (default)
log4j.appender.FILE.ImmediateFlush=true
# Set the threshold to debug mode
log4j.appender.FILE.Threshold=debug
# Set the append to false, should not overwrite
log4j.appender.FILE.Append=true
# Set the DatePattern
log4j.appender.FILE.DatePattern='.' yyyy-MM-dd-a
# Define the layout for file appender
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.conversionPattern=%m%n
Based on the example, you didn't call ctx.deploy(HttpServer). If you don't do that, then the ServletContext listener you've defined won't be invoked (note: it doesn't matter if you call deploy before or after the server has started).
You may pass log4j.configuration system property to do the trick.
For example:
java -Dlog4j.configuration=environment-production.properties
I am currently struggling to get something up and running on an nServiceBus hosted application. I have an azure ServiceBus queue that a 3rd party is posting messages to and I want my application (which is hosted locally at the moment) to receive these messages.
I have googled for answers on how to configure the endpoint but I have had no luck in a valid config. Has anyone ever done this as I can find examples of how to connect to Azure storage queues but NOT servicebus queue. (I need azure servicebus queues for other reasons)
The config I have is as below
public void Init()
{
Configure.With()
.DefaultBuilder()
.XmlSerializer()
.UnicastBus()
.AzureServiceBusMessageQueue()
.IsTransactional(true)
.MessageForwardingInCaseOfFault()
.UseInMemoryTimeoutPersister()
.InMemorySubscriptionStorage();
}
.
Message=Exception when starting endpoint, error has been logged. Reason: Input queue [mytimeoutmanager#sb://[*].servicebus.windows.net/] must be on the same machine as this Source=NServiceBus.Host
.
<configuration>
<configSections>
<section name="MessageForwardingInCaseOfFaultConfig" type="NServiceBus.Config.MessageForwardingInCaseOfFaultConfig, NServiceBus.Core" />
<section name="UnicastBusConfig" type="NServiceBus.Config.UnicastBusConfig, NServiceBus.Core" />
<section name="AzureServiceBusQueueConfig" type="NServiceBus.Config.AzureServiceBusQueueConfig, NServiceBus.Azure" />
<section name="AzureTimeoutPersisterConfig" type="NServiceBus.Timeout.Hosting.Azure.AzureTimeoutPersisterConfig, NServiceBus.Timeout.Hosting.Azure" />
</configSections>
<AzureServiceBusQueueConfig IssuerName="owner" QueueName="testqueue" IssuerKey="[KEY]" ServiceNamespace="[NS]" />
<MessageForwardingInCaseOfFaultConfig ErrorQueue="error" />
<!-- Use the following line to explicitly set the Timeout manager address -->
<UnicastBusConfig TimeoutManagerAddress="MyTimeoutManager" />
<!-- Use the following line to explicity set the Timeout persisters connectionstring -->
<AzureTimeoutPersisterConfig ConnectionString="UseDevelopmentStorage=true" />
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedruntime version="v4.0" />
<requiredruntime version="v4.0.20506" />
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
</startup>
</configuration>
Try moving UnicastBus() to the end of your call, like this:
Configure.With()
.DefaultBuilder()
.XmlSerializer()
.AzureServiceBusMessageQueue()
.IsTransactional(true)
.MessageForwardingInCaseOfFault()
.UseInMemoryTimeoutPersister()
.InMemorySubscriptionStorage()
.UnicastBus(); // <- Here
And about those third parties posting messages to the queue. Keep in mind that they need to respect how NServiceBus handles serialization/deserialization. Here is how this is done in NServiceBus (the most important part is that the BrokeredMessage is initialized with a raw message, the result of a serialziation using the BinaryFormatter):
private void Send(Byte[] rawMessage, QueueClient sender)
{
var numRetries = 0;
var sent = false;
while(!sent)
{
try
{
var brokeredMessage = new BrokeredMessage(rawMessage);
sender.Send(brokeredMessage);
sent = true;
}
// back off when we're being throttled
catch (ServerBusyException)
{
numRetries++;
if (numRetries >= MaxDeliveryCount) throw;
Thread.Sleep(TimeSpan.FromSeconds(numRetries * DefaultBackoffTimeInSeconds));
}
}
}
private static byte[] SerializeMessage(TransportMessage message)
{
if (message.Headers == null)
message.Headers = new Dictionary<string, string>();
if (!message.Headers.ContainsKey(Idforcorrelation))
message.Headers.Add(Idforcorrelation, null);
if (String.IsNullOrEmpty(message.Headers[Idforcorrelation]))
message.Headers[Idforcorrelation] = message.IdForCorrelation;
using (var stream = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(stream, message);
return stream.ToArray();
}
}
If you want NServiceBus to correctly deserialize the message, make sure your thierd parties serialize it correctly.
I now had exactly the same problem and spent several hours to figure out how to solve it. Basically Azure timeout persister is only supported for Azure hosted endpoints that use NServiceBus.Hosting.Azure. If you use NServiceBus.Host process to host your endpoints, it uses NServiceBus.Timeout.Hosting.Windows namespace classes. It initialized a TransactionalTransport with MSMQ and there you get this message.
I used two methods to avoid it:
If you must use As_Server endpoint configuration, you can use .DisableTimeoutManager() in your initialization, it will skip the TimeoutDispatcher initialization completely
Use As_Client endpoint configuration, it doesn't use transactional mode for the transport and timeout dispatcher is not inialized
There could be a way to inject Azure timeout manager somehow but I have not found it yet and I actually need As_Client thingy, so it works fine for me.