Archived Support Site

This support site is archived. You can view the old support discussions but you cannot post new discussions.

AppHarbor LogEntries Integration Not Working

CabWithMe's Avatar

CabWithMe

May 26, 2014 @ 09:44 PM

With the exact same code, build configuration and profile, our app does not log to logentries.

I'm really not sure how to troubleshoot this further (or provide additional information).

The logs appear in logentries when running locally, and do not when running deployed on AppHarbor.

Thanks in advance.

  1. Support Staff 1 Posted by rune on May 26, 2014 @ 11:40 PM

    rune's Avatar

    Hi,

    What application are you experiencing this issue with? Logging with Logentries appears to be working fine on cabwithmeorchard, and the cabwithme doesn't have Logentries installed (or logging enabled for that matter).

    Best,
    Rune

  2. 2 Posted by CabWithMe on May 27, 2014 @ 03:12 AM

    CabWithMe's Avatar

    CabWithMe.Orchard.. I see logentries, but not the ones I'm logging. I guess the exception (I see HTTP 500 coming back) isn't caught and logged by the global exception handler for WebAPI which I'm registering like this.

            config.Filters.Add(new TraceExceptionFilter());
    

    I can't reproduce the exception at all locally.

    Any ideas?

  3. Support Staff 3 Posted by rune on May 27, 2014 @ 03:35 AM

    rune's Avatar

    Ok, what does the "TraceExceptionFilter" do? Have you set this up to post directly to Logentries?

    Best,
    Rune

  4. 4 Posted by CabWithMe on May 27, 2014 @ 05:01 AM

    CabWithMe's Avatar

    public class TraceExceptionFilter : IExceptionFilter { public bool AllowMultiple { get; private set; } public Task ExecuteExceptionFilterAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken) { return Task.Factory.StartNew(() => CwmTraceSource.Instance.TraceEvent(TraceEventType.Error, actionExecutedContext.Exception.HResult, actionExecutedContext.Exception.ToString()), cancellationToken); }

    and CwmTraceSource has listeners:

    <system.diagnostics> <trace autoflush="true"> </trace> <sources> <source name="Cwm" switchName="SourceSwitch" switchType="System.Diagnostics.SourceSwitch"> <listeners> <add name="log4net" type="Cwm.Infrastructure.Logging.Log4NetTraceListener, Cwm.Core"></add> </listeners> </source> </sources> <switches> <add name="SourceSwitch" value="All" /> </switches> </system.diagnostics>

    and log4net config has

    <?xml version="1.0" encoding="utf-8"?> <log4net> <root> <!-- Value of priority may be ALL, DEBUG, INFO, WARN, ERROR, FATAL, OFF --> <priority value="ALL" /> <level value="ALL" /> <appender-ref ref="LeAppender" /> </root> <appender name="LeAppender" type="log4net.Appender.LogentriesAppender, LogentriesLog4net"> <immediateFlush value="true" /> <debug value="true" /> <useHttpPut value="false" /> <useSsl value="false" /> <layout type="log4net.Layout.PatternLayout"> <!-- The below pattern has been carefully formatted and optimized to work well with the Logentries.com entry parser. For reference see https://logentries.com/doc/search/. --> <param name="ConversionPattern" value="%d %logger %level% %m%n" /> </layout> </appender> </log4net> finally
    ` public class Log4NetTraceListener : TraceListener { public override void Fail(string message) { Fail(message, string.Empty); }

        public override void Fail(string message, string detailMessage)
        {
            StackFrame tracingStackFrame = GetTracingStackFrame(new StackTrace());
            ILog logger = LogManager.GetLogger(tracingStackFrame.GetMethod().DeclaringType);
            if (!logger.IsWarnEnabled)
                return;
            using (ThreadContext.Stacks["signature"].Push(tracingStackFrame.GetMethod().Name))
            {
                string str;
                if (!string.IsNullOrEmpty(detailMessage))
                    str = string.Format(CultureInfo.InvariantCulture, "{0}{1}{2}", (object) message, (object) Environment.NewLine, (object) detailMessage);
                else
                    str = message;
                message = str;
                logger.WarnFormat("[Fail] {0}", message);
            }
        }
    
        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", Justification = "Temporary", MessageId = "0")]
        public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data)
        {
            var objArray = new[]
            {
                data
            };
            TraceData(eventCache, source, eventType, id, objArray);
        }
    
        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", Justification = "Temporary", MessageId = "0")]
        public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, params object[] data)
        {
            if (data == null || data.Length == 0)
            {
                TraceEvent(eventCache, source, eventType, id);
            }
            else
            {
                foreach (object obj in data.Where(x => !TraceException(eventType, x)))
                {
                    var objArray = new[]
                    {
                        obj
                    };
                    TraceEvent(eventCache, source, eventType, id, "{0}", objArray);
                }
            }
        }
    
        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", Justification = "Temporary", MessageId = "0")]
        public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id)
        {
            StackFrame tracingStackFrame = GetTracingStackFrame(new StackTrace());
            ILog logger = LogManager.GetLogger(tracingStackFrame.GetMethod().DeclaringType);
            switch (eventType)
            {
                case TraceEventType.Resume:
                case TraceEventType.Transfer:
                case TraceEventType.Stop:
                case TraceEventType.Suspend:
                case TraceEventType.Verbose:
                case TraceEventType.Start:
                    if (!logger.IsDebugEnabled)
                        break;
                    using (ThreadContext.Stacks["signature"].Push(tracingStackFrame.GetMethod().Name))
                    {
                        logger.Debug(string.Empty);
                        break;
                    }
                case TraceEventType.Critical:
                    if (!logger.IsFatalEnabled)
                        break;
                    using (ThreadContext.Stacks["signature"].Push(tracingStackFrame.GetMethod().Name))
                    {
                        logger.Fatal(string.Empty);
                        break;
                    }
                case TraceEventType.Error:
                    if (!logger.IsFatalEnabled)
                        break;
                    using (ThreadContext.Stacks["signature"].Push(tracingStackFrame.GetMethod().Name))
                    {
                        logger.Error(string.Empty);
                        break;
                    }
                case TraceEventType.Warning:
                    if (!logger.IsWarnEnabled)
                        break;
                    using (ThreadContext.Stacks["signature"].Push(tracingStackFrame.GetMethod().Name))
                    {
                        logger.Warn(string.Empty);
                        break;
                    }
                case TraceEventType.Information:
                    if (!logger.IsInfoEnabled)
                        break;
                    using (ThreadContext.Stacks["signature"].Push(tracingStackFrame.GetMethod().Name))
                    {
                        logger.Info(string.Empty);
                        break;
                    }
            }
        }
    
        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", Justification = "Argument cannot be null", MessageId = "0")]
        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", Justification = "Argument cannot be null", MessageId = "5")]
        public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string format, params object[] args)
        {
            if (args.Length == 0)
                TraceEvent(eventCache, source, eventType, id);
            StackFrame tracingStackFrame = GetTracingStackFrame(new StackTrace());
            ILog logger = LogManager.GetLogger(tracingStackFrame.GetMethod().DeclaringType);
            using (ThreadContext.Stacks["signature"].Push(tracingStackFrame.GetMethod().Name))
            {
                switch (eventType)
                {
                    case TraceEventType.Resume:
                    case TraceEventType.Transfer:
                    case TraceEventType.Stop:
                    case TraceEventType.Suspend:
                    case TraceEventType.Verbose:
                    case TraceEventType.Start:
                        if (!logger.IsDebugEnabled)
                            break;
                        logger.DebugFormat(CultureInfo.CurrentCulture, format, args);
                        break;
                    case TraceEventType.Critical:
                        if (!logger.IsFatalEnabled)
                            break;
                        logger.FatalFormat(CultureInfo.CurrentCulture, format, args);
                        break;
                    case TraceEventType.Error:
                        if (!logger.IsFatalEnabled)
                            break;
                        logger.ErrorFormat(CultureInfo.CurrentCulture, format, args);
                        break;
                    case TraceEventType.Warning:
                        if (!logger.IsWarnEnabled)
                            break;
                        logger.WarnFormat(CultureInfo.CurrentCulture, format, args);
                        break;
                    case TraceEventType.Information:
                        if (!logger.IsInfoEnabled)
                            break;
                        logger.InfoFormat(CultureInfo.CurrentCulture, format, args);
                        break;
                }
            }
        }
    
        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", Justification = "Temporary", MessageId = "0")]
        public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message)
        {
            object[] strArray =
            {
                message
            };
            TraceEvent(eventCache, source, eventType, id, "{0}", strArray);
        }
    
        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", Justification = "Temporary", MessageId = "0")]
        public override void TraceTransfer(TraceEventCache eventCache, string source, int id, string message, Guid relatedActivityId)
        {
            var objArray = new object[]
            {
                message,
                relatedActivityId
            };
            TraceEvent(eventCache, source, TraceEventType.Transfer, id, "{0}", objArray);
        }
    
        public override void Write(object o)
        {
            WriteLine(o, string.Empty);
        }
    
        public override void Write(object o, string category)
        {
            WriteLine(o, category);
        }
    
        public override void Write(string message)
        {
            WriteLine(message, string.Empty);
        }
    
        public override void Write(string message, string category)
        {
            WriteLine((object) message, category);
        }
    
        public override void WriteLine(object o)
        {
            WriteLine(o, string.Empty);
        }
    
        [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", Justification = "Temporary", MessageId = "log4net.Util.ThreadContextStack.Push(System.String)")]
        public override void WriteLine(object o, string category)
        {
            StackFrame tracingStackFrame = GetTracingStackFrame(new StackTrace());
            ILog logger = LogManager.GetLogger(tracingStackFrame.GetMethod().DeclaringType);
            if (!logger.IsInfoEnabled)
                return;
            using (ThreadContext.Stacks["signature"].Push(tracingStackFrame.GetMethod().Name))
            {
                if (string.IsNullOrEmpty(category))
                    logger.Debug(o);
                else
                    logger.DebugFormat("[{0}] {1}", category, o);
            }
        }
    
        public override void WriteLine(string message, string category)
        {
            WriteLine((object) message, category);
        }
    
        public override void WriteLine(string message)
        {
            WriteLine(message, string.Empty);
        }
    
        private static StackFrame GetTracingStackFrame(StackTrace stack)
        {
            for (int index = 0; index < stack.FrameCount; ++index)
            {
                MethodBase method = stack.GetFrame(index).GetMethod();
                if (method.DeclaringType != null && (!("System.Diagnostics" == method.DeclaringType.Namespace) && (!("System.Threading" == method.DeclaringType.Namespace) && !("Log4NetTraceListener" == method.DeclaringType.Name))))
                    return stack.GetFrame(index);
            }
            return null;
        }
    
        private static bool TraceException(TraceEventType eventType, object datum)
        {
            if (TraceEventType.Critical != eventType && TraceEventType.Error != eventType)
                return false;
            var exception = datum as Exception;
            if (exception == null)
                return false;
            StackFrame tracingStackFrame = GetTracingStackFrame(new StackTrace());
            ILog logger = LogManager.GetLogger(tracingStackFrame.GetMethod().DeclaringType);
            switch (eventType)
            {
                case TraceEventType.Critical:
                    if (logger.IsFatalEnabled)
                    {
                        using (ThreadContext.Stacks["signature"].Push(tracingStackFrame.GetMethod().Name))
                        {
                            logger.Fatal(exception.Message, exception);
                        }
                    }
                    break;
                case TraceEventType.Error:
                    if (logger.IsErrorEnabled)
                    {
                        using (ThreadContext.Stacks["signature"].Push(tracingStackFrame.GetMethod().Name))
                        {
                            logger.Error(exception.Message, exception);
                        }
                    }
                    break;
            }
            return true;
        }
    }
    

    `

    Basically I don't want to take a dependency on log4net, but there is existing integration build from log4net to logentries which I'd like to leverage. This all works dandy locally

  5. Support Staff 5 Posted by rune on May 27, 2014 @ 05:06 AM

    rune's Avatar

    Ok - the functionality here seems pretty much identical to the stuff you can already use with AppHarbor. Have you tried using the approach I linked to in the other thread?

    When you see the logs/trace messages in the online log viewer under your application you'll be able to forward those to Logentries automatically.

    Best,
    Rune

Discussions are closed to public comments.
If you need help with AppHarbor please start a new discussion.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac