public ActionResult RequestIdTest(string id) { ViewBag.RequestId = JavascriptLogging.RequestId(); ViewBag.PassedInRequestId = id; return(View()); }
public void IsLoggingUrl_NoUrlsConfigured_CodeConfig() { JavascriptLogging.SetJsnlogConfiguration(null, null); Assert.True(LoggingUrlHelpers.IsLoggingUrl("/jsnlog.logger")); Assert.True(LoggingUrlHelpers.IsLoggingUrl("http://abc.com/jsnlog.logger")); Assert.False(LoggingUrlHelpers.IsLoggingUrl("http://abc.com/jsnlog.css")); }
public static void SetConfigCache(string configXml, ILoggingAdapter logger = null) { // Set config cache in JavascriptLogging to contents of xe XmlElement xe = ConfigToXe(configXml); JavascriptLogging.SetJsnlogConfiguration(null, logger); JavascriptLogging.GetJsnlogConfiguration(() => xe); }
protected void Application_BeginRequest() { // Configure CORS. JavascriptLogging.SetJsnlogConfiguration(new JsnlogConfiguration { defaultAjaxUrl = "http://apicorslocalhost.local/jsnlog.logger", corsAllowedOriginsRegex = @"^https?:\/\/([a-z0-9]+[.])*corslocalhost[.]local$", productionLibraryPath = "~/Scripts/jsnlog.min.js" }); }
/// <summary> /// Processes the incoming request. This method is not depended on the environment and so can be unit tested. /// Note that the incoming request may not be the POST request with log data. /// /// Effect of this method: /// * setting StatusCode on the response parameter /// * adding headers to the response parameter /// * logging contents of log request /// </summary> /// <param name="json"> /// JSON payload in the incoming request /// </param> /// <param name="logRequestBase"> /// * Type of browser that sent the request /// * IP address that sent the address /// * Url that the request was sent to /// * Request Id sent as part of the request /// * Request data to be given to onLogging event handler /// </param> /// <param name="serverSideTimeUtc">Current time in UTC</param> /// <param name="httpMethod">HTTP method of the request</param> /// <param name="origin">Value of the Origin request header</param> /// <param name="response"> /// Empty response object. This method can add headers, etc. /// </param> internal static void ProcessLogRequest(string json, LogRequestBase logRequestBase, DateTime serverSideTimeUtc, string httpMethod, string origin, LogResponse response) { JsnlogConfiguration jsnlogConfiguration = JavascriptLogging.GetJsnlogConfiguration(); ILoggingAdapter logger = JavascriptLogging.GetLogger(); if ((httpMethod != "POST") && (httpMethod != "OPTIONS")) { response.StatusCode = (int)HttpStatusCode.MethodNotAllowed; return; } string corsAllowedOriginsRegex = jsnlogConfiguration.corsAllowedOriginsRegex; bool originIsAllowed = ((!string.IsNullOrEmpty(corsAllowedOriginsRegex)) && (!string.IsNullOrEmpty(origin)) && Regex.IsMatch(origin, corsAllowedOriginsRegex)); if (originIsAllowed) { response.AppendHeader("Access-Control-Allow-Origin", origin); } response.StatusCode = (int)HttpStatusCode.OK; if (httpMethod == "OPTIONS") { // Standard HTTP response (not related to CORS) response.AppendHeader("Allow", "POST"); // Only if the origin is allowed send CORS headers if (originIsAllowed) { response.AppendHeader("Access-Control-Max-Age", Constants.CorsAccessControlMaxAgeInSeconds.ToString()); response.AppendHeader("Access-Control-Allow-Methods", "POST"); response.AppendHeader("Access-Control-Allow-Headers", "jsnlog-requestid, content-type"); } return; } // httpMethod must be POST List <FinalLogData> logDatas = ProcessLogRequestExec(json, logRequestBase, serverSideTimeUtc, jsnlogConfiguration); // --------------------------------- // Pass log data to Common Logging foreach (FinalLogData logData in logDatas) { logger.Log(logData); } }
public void SetConfigWithJsnlogInWebConfig() { // Arrange string configXml = @" <jsnlog maxMessages=""5""> </jsnlog> "; XmlElement xe = CommonTestHelpers.ConfigToXe(configXml); JsnlogConfiguration jsnlogConfiguration = new JsnlogConfiguration(); // Act Exception ex = Assert.Throws <ConflictingConfigException>(() => JavascriptLogging.SetJsnlogConfiguration(() => xe, jsnlogConfiguration)); }
protected void Application_BeginRequest() { // Use configuration in code instead of configuration in web.config/. JavascriptLogging.SetJsnlogConfiguration(new JsnlogConfiguration { serverSideMessageFormat = "%userHostAddress, %logger, %level, %message", productionLibraryPath = "~/Scripts/jsnlog.min.js", loggers = new List <Logger> { new Logger { name = "jsLogger", level = "FATAL" } } }); }
public void SetConfigWithoutJsnlogInWebConfig() { // Arrange JsnlogConfiguration jsnlogConfiguration = new JsnlogConfiguration { maxMessages = 5 }; JavascriptLogging.SetJsnlogConfiguration(() => null, jsnlogConfiguration); // Act JsnlogConfiguration retrievedJsnlogConfiguration = JavascriptLogging.GetJsnlogConfiguration(); // Assert // Retrieved object is expected to be the exact same object that was put in Assert.Equal(jsnlogConfiguration, retrievedJsnlogConfiguration); Assert.Equal(jsnlogConfiguration.maxMessages, retrievedJsnlogConfiguration.maxMessages); }
public void GetConfigFromWebConfig() { // Arrange string configXml = @" <jsnlog maxMessages=""5""> </jsnlog> "; XmlElement xe = CommonTestHelpers.ConfigToXe(configXml); JavascriptLogging.SetJsnlogConfiguration(null); JavascriptLogging.GetJsnlogConfiguration(() => xe); // Act JsnlogConfiguration retrievedJsnlogConfiguration = JavascriptLogging.GetJsnlogConfiguration(); // Assert // Retrieved object is expected to be the exact same object that was put in Assert.Equal((uint)5, retrievedJsnlogConfiguration.maxMessages); }
/// <summary> /// Returns true if a request with the given url is a logging request that should be handled /// by JSNLog. /// /// Note that the user may have set the defaultUrl or an appender url because they want to use /// the standard url /jsnlog.logger for something else. So you don't want to always allow /// /jsnlog.logger. /// /// On the other hand, it is impossible to figure out exactly what urls the user has used, because you /// don't know which loggers are being used in the user's code. /// So you can't only match against the urls specified with the appenders. /// /// So this method assumes that in addition to the appenders that have been configured, /// the default appender is also used. That is, it also passes the defaultUrl set by the user /// (and if that is not set, the defaultDefaultUrl). /// </summary> /// <param name="url"></param> /// <returns></returns> public static bool IsLoggingUrl(string url) { if (string.IsNullOrEmpty(url)) { throw new ArgumentNullException(url); } JsnlogConfiguration jsnlogConfiguration = JavascriptLogging.GetJsnlogConfiguration(); if (jsnlogConfiguration == null) { return(UrlMatchesAppenderUrl(Constants.DefaultDefaultAjaxUrl, url)); } string resolvedDefaultUrl = ResolvedAppenderUrl(Constants.DefaultDefaultAjaxUrl, jsnlogConfiguration.defaultAjaxUrl, null); if (UrlMatchesAppenderUrl(resolvedDefaultUrl, url)) { return(true); } if (jsnlogConfiguration.ajaxAppenders != null) { foreach (AjaxAppender ajaxAppender in jsnlogConfiguration.ajaxAppenders) { string resolvedAppenderUrl = ResolvedAppenderUrl( Constants.DefaultDefaultAjaxUrl, jsnlogConfiguration.defaultAjaxUrl, ajaxAppender.url); if (UrlMatchesAppenderUrl(resolvedAppenderUrl, url)) { return(true); } } } return(false); }
private void LoggingHandler(LoggingEventArgs e) { var currReqId = JavascriptLogging.RequestId(); e.FinalMessage = String.Format("[{0,-36}] {1}", currReqId, e.FinalMessage); }
// This version is not reliant on sitting in a web site, so can be unit tested. // generateClosure - if false, no function closure is generated around the generated JS code. Only set to false when unit testing. // Doing this assumes that jsnlog.js has loaded before the code generated by the method is executed. // // You want to set this to false during unit testing, because then you need direct access outside the closure of variables // that are private to the closure, specifically dummyappenders that store the log messages you receive, so you can unit test them. public void ProcessRootExec(StringBuilder sb, Func <string, string> virtualToAbsoluteFunc, string userIp, string requestId, bool generateClosure) { Dictionary <string, string> appenderNames = new Dictionary <string, string>(); JsnlogConfiguration jsnlogConfiguration = JavascriptLogging.GetJsnlogConfiguration(); string loggerProductionLibraryVirtualPath = jsnlogConfiguration.productionLibraryPath; bool loggerEnabled = jsnlogConfiguration.enabled; string loggerProductionLibraryPath = null; if (!string.IsNullOrEmpty(loggerProductionLibraryVirtualPath)) { // Every hard coded path must be resolved. See the declaration of DefaultDefaultAjaxUrl loggerProductionLibraryPath = Utils.AbsoluteUrl(loggerProductionLibraryVirtualPath, virtualToAbsoluteFunc); } JavaScriptHelpers.WriteJavaScriptBeginTag(sb); if (generateClosure) { JavaScriptHelpers.WriteLine(string.Format("var {0} = function ({1}) {{", Constants.GlobalMethodCalledAfterJsnlogJsLoaded, Constants.JsLogObjectName), sb); } // Generate setOptions for JSNLog object itself var jsonFields = new List <string>(); JavaScriptHelpers.AddJsonField(jsonFields, Constants.JsLogObjectClientIpOption, userIp, new StringValue()); JavaScriptHelpers.AddJsonField(jsonFields, Constants.JsLogObjectRequestIdOption, requestId, new StringValue()); JavaScriptHelpers.GenerateSetOptions(Constants.JsLogObjectName, jsnlogConfiguration, appenderNames, virtualToAbsoluteFunc, sb, jsonFields); if (loggerEnabled) { // Process all loggers and appenders. First process the appenders, because the loggers can be // dependent on the appenders, and will use appenderNames to translate configuration appender names // to JavaScript names. int sequence = 0; GenerateCreateJavaScript(jsnlogConfiguration.ajaxAppenders, sb, virtualToAbsoluteFunc, appenderNames, ref sequence); GenerateCreateJavaScript(jsnlogConfiguration.consoleAppenders, sb, virtualToAbsoluteFunc, appenderNames, ref sequence); GenerateCreateJavaScript(jsnlogConfiguration.loggers, sb, virtualToAbsoluteFunc, appenderNames, ref sequence); } // ------------- if (generateClosure) { // Generate code to execute the function, in case jsnlog.js has already been loaded. // Wrap in try catch, so if jsnlog.js hasn't been loaded, the resulting exception will be swallowed. JavaScriptHelpers.WriteLine(string.Format("}}; try {{ {0}({1}); }} catch(e) {{}};", Constants.GlobalMethodCalledAfterJsnlogJsLoaded, Constants.JsLogObjectName), sb); } JavaScriptHelpers.WriteJavaScriptEndTag(sb); // Write the script tag that loads jsnlog.js after the code generated from the web.config. // When using jsnlog.js as an AMD module or in a bundle, jsnlog.js will be loaded after that code as well, // and creating a similar situation in the default out of the box loading option makes it more likely // you pick up bugs during testing. if (!string.IsNullOrWhiteSpace(loggerProductionLibraryPath)) { JavaScriptHelpers.WriteScriptTag(loggerProductionLibraryPath, sb); } }
private static FinalLogData ProcessLogItem(LogRequestSingleMsg logItem, LogRequestBase logRequestBase, DateTime serverSideTimeUtc, JsnlogConfiguration jsnlogConfiguration) { string serversideLoggerNameOverride = jsnlogConfiguration.serverSideLogger; string messageFormat = jsnlogConfiguration.serverSideMessageFormat; string levelOverride = jsnlogConfiguration.serverSideLevel; string dateFormat = jsnlogConfiguration.dateFormat; try { LevelUtils.ValidateLevel(levelOverride); } catch (Exception e) { throw new PropertyException("levelOverride", e); } // ---------------- string message = logItem.m; string logger = logItem.n; string level = logItem.l; // note that level as sent by the javascript is a number string entryId = logItem.u; DateTime utcDate = DateTime.UtcNow; string timestampMs = logItem.t; try { double ms = double.Parse(timestampMs); utcDate = DateTime.SpecifyKind((new DateTime(1970, 1, 1)).AddMilliseconds(ms), DateTimeKind.Utc); } catch { } // ---------------- string jsonmessage = ""; if (messageFormat.Contains("%jsonmessage")) { jsonmessage = LogMessageHelpers.EnsureValidJson(message); } // ---------------- var logRequest = new LogRequest(message, logger, level, utcDate, entryId, jsonmessage, logRequestBase); var loggingEventArgs = new LoggingEventArgs(logRequest) { Cancel = false, ServerSideMessageFormat = messageFormat }; // ---------------- if (string.IsNullOrWhiteSpace(logger)) { logger = Constants.RootLoggerNameServerSide; } loggingEventArgs.FinalLogger = serversideLoggerNameOverride ?? logger; string consolidatedLevel = levelOverride ?? level; loggingEventArgs.FinalLevel = LevelUtils.ParseLevel(consolidatedLevel).Value; // ---------------- loggingEventArgs.FinalMessage = messageFormat .Replace("%message", message) .Replace("%entryId", entryId) .Replace("%jsonmessage", jsonmessage) .Replace("%utcDateServer", serverSideTimeUtc.ToString(dateFormat)) .Replace("%utcDate", utcDate.ToString(dateFormat)) .Replace("%dateServer", Utils.UtcToLocalDateTime(serverSideTimeUtc).ToString(dateFormat)) .Replace("%date", Utils.UtcToLocalDateTime(utcDate).ToString(dateFormat)) .Replace("%level", level) .Replace("%newline", System.Environment.NewLine) .Replace("%userAgent", logRequestBase.UserAgent) .Replace("%userHostAddress", logRequestBase.UserHostAddress) .Replace("%requestId", logRequestBase.RequestId ?? "") .Replace("%url", logRequestBase.Url) .Replace("%logger", logger); // ---------------- JavascriptLogging.RaiseLoggingEvent(loggingEventArgs); // If user wrote event handler that decided not to log the message, return null if (loggingEventArgs.Cancel) { return(null); } return(loggingEventArgs); }
private void RunTest(JsnlogConfiguration jsnlogConfiguration) { JavascriptLogging.SetJsnlogConfiguration(() => null, jsnlogConfiguration); JsnlogConfiguration retrievedJsnlogConfiguration = JavascriptLogging.GetJsnlogConfiguration(); }