Archive for the ‘FogBugz’ Category

Search Axis Auto-Complete: Helping you find what you’re looking for (even faster)

July 23rd, 2014 by Aaron Maenpaa

In April, I talked about how we’re trying to make our axis search more discoverable, and ultimately, more widely used. Our first step was to introduce the search guide, which brought our axis documentation directly into FogBugz where it’s more relevant and contextual. The next step (which I hinted at), was to more actively help you create axis queries via auto-complete:

Auto-complete in action

… wait, what? What are axis queries?

In addition to supporting run-of-the-mill “full-text” search (e.g., “bob widget bug”), FogBugz also supports axis queries which let you filter cases based on criteria that apply to specific case fields. You probably know that you can specify exact values for fields in a filter, but it can be slow to click around for a one-time need to find a case. Instead of choosing between specific but slow and fast but vague, try an axis query. Compared to full-text search, axes can greatly reduce the number of matching results you need to scan over (or worse yet click and view). If you know a case was about a crash and there was an email in the case mentioning “I tried reinstalling”, you could simply search for those words, but if you know that “crash” was in the case title, using the title axis could make finding the case much faster:

On my FogBugz installation, that’s 239 cases down to 4! If you also know the case is in your “Support” project and had a tag “regression”, add project:Support tag:regression to your query. Avoiding scanning over a long result list just saved enough time to watch at least 29 cat gifs, and that’s just scratching the surface! So far, axis auto-complete has been really well received in our internal testing. On the second day of our Summer 2014 internship, I observed one of our interns doing an axis search using the new auto-complete feature… which is something I would have never expected even a few months ago. Axis search has gone from a largely hidden power-user feature to a productivity booster that’s discoverable enough for brand new users to find it.

… so what does this auto-complete…uh…complete?

When you start typing any axis name, you will see a list of potential matches. Typing a value for an axis will auto-complete possibilities (for example, your list of project names after the project: axis). Auto-complete also knows how you can sort your cases, suggesting sortable column options when you start to type them after “orderBy:” Finally, it lists past queries from your search history in case you’re just trying to make the same search you made the other day.

assigned

Axes: Including assignedTo, editedBy, opened and many more.

me

Objects: Including the names of people, projects, milestones in FogBugz, as well as special names like me, today, tomorrow.

auto-complete historical searches

Historical searches: Helping you run your favorite searches again.

Our favorite searches:

With all this talk about axis searches, it seems like we should share some of the searches we run frequently to help get you started:

 Michael: “What was that case again?”

 Justin: “Cases I’ve assigned out.”

 Adam: “I put this on everything.”

 Aaron: “Who’s doing what?”

Documentation is available on our help portal for auto-complete, the search guide and our complete list of axes. Like the look of it, but don’t have FogBugz? You can try FogBugz for free today!

Eight Jackalopes Walk Into An Office

July 9th, 2014 by Elizabeth Hall

Intern Group Final

As always, our interns are working on real features for our real products and have already made tremendous contributions to the Trello and FogBugz teams. We think they’re pretty special – not only did they stand out amongst the 776 applications we received but during these first few weeks they’ve had the chance to teach us a thing or two. Whether it’s coming up with new strategies for dealing with the Tanner during Werewolf or showing off cool video games they’ve made at hackathons, the class of 2014 is constantly impressing us.

Before we blink and it’s all over we want to take a moment to show off this year’s amazing talent. Here they are our eight wonderful interns (lovingly dubbed jackalopes*) in their own words.

Alex Lew
20140627-DSC_0021

Hi! My name’s Alex, and I’m an intern on the Platform team this summer. Obligatory fun fact: I grew up in North Carolina, and my high school’s library had the largest collection of books and music in and about Esperanto of any library in the United States (excepting the Library of Congress).

Laura Watiker
20140627-DSC_0035

My name’s Laura and I’m working on the Trello team this summer. During the school year, I go to Oberlin College in Ohio, studying CS and Econ. I grew up in the New York City suburbs, but I’m happily living in the Brooklyn housing this summer. Aside from pushing lots of computer keys, I do work with Oberlin’s co-ops, play a bunch of instruments, and theorize 2048 strategy.

Graham Carling
20140627-DSC_0039

My name is Graham, I just finished my Sophomore year at Brown. I am originally from Manhattan and a graduate of Stuyvesant high school, a short walk from the Fog Creek offices. I am majoring in Computer Science (I know, shocking) and for the last couple semesters I have been working as a TA for some of Brown’s CS classes. Outside of work I like going to concerts, mainly of the electronic variety, along with seeing my friends from high school and working on a side project of mine. So far my summer has been packed full of fun events, and when I’m not going fishing or shooting arrows I’ve been working on the new notification center feature for FogBugz.

Jonathan Pevarnek
20140627-DSC_0040
Hello, I’m Jonathan, a masters student in Computer Science at the University of Michigan. I’m from a small island called Grosse Ile in south-east Michigan. When I’m not working, I like to read books, go on bike rides, and work with a campus community service organization (Circle K). This summer, I’ve mainly been working with Doug to extend Trello email integration.

Matthew Hayes
20140627-DSC_0055

I am Matthew Hayes, from Syosset, Long Island, NY. I just finished my junior year as a CS major at Cornell University upstate in Ithaca, and will be working on a FogBugz activity feed this summer. Fun fact: I caught the biggest fish on this year’s fishing trip (evidence below).

Peter Johnson
20140627-DSC_0025

My name’s Peter, and I’m working on adding saved searches and list sorting to Trello this summer. I just finished my junior year at William & Mary in Virginia, and in my free time I enjoy running long distances and playing Dots!

Steven Lyubomirsky
20140627-DSC_0052

If you’re inclined to take me at my word, my name is Steven Lyubomirsky, I’m a rising junior at Princeton, I study computer science, and am incredibly handsome. If you’re not, at least three of those can be independently verified. I live under the watchful guard of my blue parakeet in Fort Lee, NJ, a safe distance from the incredibly radioactive center of the universe (NYC, of course), where I like to demarcate my domain with my nightly walks. This summer I’m working on the Platform team.

David Patrzeba
20140627-DSC_0065

My name is David Patrzeba and I am an intern on the FogBugz team (Project Jackalope). I started on June 6, 2014 because the newest addition to my family decided to arrive on my original start date of June 2, 2014. I am a NJ native and will be traveling home every weekend to be with them, but during the week I will be staying at the Clark St. residence in Brooklyn. I am a rising senior at Rutgers University (The State University of New Jersey) where I am studying Electrical & Computer Engineering, Computer Science, and Economics. Fun Fact: I served in a Special Operations unit in the Army for 7 years, and I may be Fog Creek’s oldest intern ever.

0611142012-MOTION
Matt wasn’t lying. He really did catch the biggest fish.

*Each year the intern class is named after the next letter in the alphabet. This year is “J”. Do you have a fantastic “K” animal name recommendation for next year? Talk to me!

The Search Guide: Helping you find what you’re looking for

April 11th, 2014 by Aaron Maenpaa

As you may already know, FogBugz offers an impressive array of search axes to help you slice and dice your data. These axes allow you to build searches to find particular cases or any cases matching pretty much arbitrary criteria. While all of these axes are documented on our help site, we kept finding that while axis search is really valuable to us when we use FogBugz, we kept talking to customers who just didn’t know about it.

We’re trying to change that.

The first thing we’re doing is adding a prompt to the search box:

search guide button

When you click it, it expands to show an axis guide:

search axis guide

We’re hoping that the prompt stays out of the way during normal use, but helps make the axes more discoverable, presents the axis documentation in a more useful format, and ultimately helps you find the cases you’re looking for, when you’re looking for them.

… but wait, there’s more

Like I said, this is the first thing we’re doing. We’re working on some other stuff we think you’ll like. Here’s a sneak peak (provided you haven’t already reached your daily recommended intake of Comic Sans ;-):

search auto-complete

Like the look of it, but don’t have FogBugz? You can sign up for a free FogBugz trial today!

Fog Creek and Heartbleed

April 10th, 2014 by Mendy Berkowitz

Along with the rest of the internet, Fog Creek has been reacting to the Heartbleed vulnerability which was discovered this Monday.

TL;DR: FogBugz and Kiln On Demand, Copilot and the Fog Creek website were not vulnerable. Trello was vulnerable and has been remediated.

Fog Creek handles SSL connections at the load balancers in front of the application servers. The load balancers for FogBugz and Kiln On Demand, Copilot and the fogcreek.com website are using the 0.9.8 branch of OpenSSL. This version does not have the newer heartbeat extension and is therefore not vulnerable to Heartbleed. None of your data on fogbugz.com, kilnhg.com, copilot.com or fogcreek.com has been exposed to the Heartbleed vulnerability.

The load balancers for Trello were using the 1.0.1 branch of OpenSSL and were vulnerable. We have upgraded OpenSSL and replaced the Trello certificates. More details and important recommended steps for all users are available in a post on the Trello blog.

We have also reviewed our vendors (for things like this blog) to ensure that our other SSL certificates were not potentially compromised. Fortunately we have not had to replace any other certificates.

If you have configured web hooks in your Kiln On Demand account, we recommend that you verify that the target servers have not been affected. If you use one of the pre-configured types, or your custom web hook uses HTTPS, the data sent to that external service may be at risk. We do not however, send any of your Kiln login credentials, so they are safe.

We take the security of your data seriously. We are committed to protecting it and to maintaining clear and open communication with you. If you have any questions, comments or concerns please contact us.

Production Debugging: A story about “Exception code: 0xe053534f”

March 20th, 2014 by Aaron Maenpaa

Imagine for a moment that you’ve been running an ASP.NET app for years, and on one otherwise sunny Saturday morning, you get a call saying that the app has started crashing randomly. What do you do?

Step 0: Check the event log

It took me way too long to get used to checking the Event Log (Start → Event Viewer). I don’t know if I expected it to be loggier, or what, but there’s good stuff in there. You should check it out.

You might even find an error like this one (Windows Logs → Application) :

Faulting application name: w3wp.exe, version: 7.5.7601.17514, time stamp: 0x4ce7afa2
Faulting module name: KERNELBASE.dll, version: 6.1.7601.17651, time stamp: 0x4e21213c
Exception code: 0xe053534f
Fault offset: 0x000000000000cacd
Faulting process id: 0x%9
Faulting application start time: 0x%10
Faulting application path: %11
Faulting module path: %12
Report Id: %13

This report is a little terse but it can be the gateway to figuring out what’s wrong. “Faulting” sounds bad: It means “crashing”. Translating to English, It’s saying “the IIS worker process (w3wp.exe) crashed”. Since this is exactly what you’re looking into, it’s a start. Exception code 0xe053534f is a stack overflow (I wish I had advice for how to map exception codes to what the problem is, but as far as I can tell, Google and hope are your best bet).

Ok, so what now?

Step 1: Googling

Looking around, amongst the “I’m getting 0xe053534f, how do I fix it?” posts on forums you’ll realize that what you want is a crash dump, and you’ll find some advice on how to obtain one, like this, or this.

You probably don’t want to use AdPlus

While AdPlus is indeed super cool, and indeed has a mode that will allow you monitor all of the IIS worker processes (a command which I will not include here because I don’t want to encourage you to use it), in my experience the overhead was way too high: The throughput on the monitored servers dropped to the point where 1. They basically weren’t doing any work, 2. They stopped crashing (Don’t worry… subset of servers during a time of reduced throughput requirements, negligible customer impact).

You probably don’t want to try and set up an Unhandled Exception Module

At least not while you’re under the gun. I never actually got it to work, and it wouldn’t actually help us here since it probably wouldn’t get called for a stack overflow anyway.

Step 2: Check the event log

Did you know that Windows Error Reporting has your back? If you look at the Event Log, the event right after the crash should be from Windows Error Reporting and hopefully it has some more information like:

Fault bucket , type 0
Event Name: APPCRASH
Response: Not available
Cab Id: 0
 
Problem signature:
P1: w3wp.exe
P2: 7.5.7601.17514
P3: 4ce7afa2
P4: KERNELBASE.dll
P5: 6.1.7601.17651
P6: 4e21213c
P7: e053534f
P8: 000000000000cacd
P9:
P10:
 
Attached files:
 
These files may be available here:
C:\ProgramData\Microsoft\Windows\WER\ReportQueue\AppCrash_w3wp.exe_16c01b4e25db8aa7e52fdd921dbac8b8dba70ff_e37855c7
 
Analysis symbol:
Rechecking for solution: 0
Report Id: 3bfe0e87-a15d-11e3-a83d-14feb5d64ad7
Report Status: 4

… okay, so that’s not super informative, but there’s a line in there that should get you excited, C:\ProgramData\Microsoft\Windows\WER\ReportQueue is a folder that might already contain crash dumps… no collection required! You probably want to look there and see if there are dumps that look relevant to resolving your problem.

What if there aren’t any crash dumps?

Check all affected servers, you only need one. I never got around to trying it, but SysInternals ProcDump looks like it might do the job, hopefully without taking the toll that AdPlus did.

DebugDiag also came up repeatedly while I was looking around, maybe that would do the trick. Looks more complicated to get going than ProcDump though.

Step 3: Windbg

Okay, you’ve got a crash dump, open it up in windbg, and look around (there are tons of windbg cheat sheets around like this one, this one, or this one). We’re going to:

  1. Load the CLR extensions (.loadby sos mscorwks).

  2. Load the symbols (.symfix).

  3. Inspect the stack (!clrstack).

  4. Inspect the exception (!printexception).

This dump file has an exception of interest stored in it.
The stored exception information can be accessed via .ecxr.
(1cbc.3d34): Unknown exception - code e053534f (first/second chance not available)
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for ntdll.dll -
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for KERNELBASE.dll -
ntdll!NtWaitForSingleObject+0xa:
00000000`76ed135a c3              ret
0:078> .loadby sos mscorwks
------------------------------------------------------------
sos.dll needs a full memory dump for complete functionality.
You can create one with .dump /ma <filename>
------------------------------------------------------------
0:078> !clrstack
*********************************************************************
* Symbols can not be loaded because symbol path is not initialized. *
*                                                                   *
* The Symbol Path can be set by:                                    *
*   using the _NT_SYMBOL_PATH environment variable.                 *
*   using the -y <symbol_path> argument when starting the debugger. *
*   using .sympath and .sympath+                                    *
*********************************************************************
PDB symbol for mscorwks.dll not loaded
------------------------------------------------------------
sos.dll needs a full memory dump for complete functionality.
You can create one with .dump /ma <filename>
------------------------------------------------------------
c0000005 Exception in C:\Windows\Microsoft.NET\Framework64\v2.0.50727\sos.clrstack debugger extension.
PC: 00000642`ffcbf8e4  VA: 00000000`00000000  R/W: 0  Parameter: 00000000`00000000
0:078> .symfix
0:078> !clrstack
OS Thread Id: 0x3d34 (78)
(!clrstack processes a max of 1000 stack frames)
Child-SP         RetAddr          Call Site
000000000e0e6c70 000007ff01a617e9 HtmlAgilityPack.HtmlNode.CloseNode(HtmlAgilityPack.HtmlNode)
000000000e0e6cf0 000007ff01a617e9 HtmlAgilityPack.HtmlNode.CloseNode(HtmlAgilityPack.HtmlNode)
000000000e0e6d70 000007ff01a617e9
<many, many, many more lines of that>
0:078> !printexception
Exception object: 0000000270090138
Exception type: System.StackOverflowException
Message: <none>
InnerException: <none>
StackTrace (generated):
<none>
StackTraceString: <none>
HResult: 800703e9

Here’s what we’ve learned so far:

  1. We’ve confirmed a stack overflow as the cause of our problem.

  2. We’re seeing the error in HtmlAgilityPack, but we can’t actually see the base of the stack because !clrstack gives up too soon.

Delve Deeper

!clrstack won’t go deep enough to show us the base of the stack, but we can get the base of the native stack via k 1000

0:078> k 1000
Child-SP          RetAddr           Call Site
<the native error handling frames>
00000000`0e0e6c70 000007ff`01a617e9 0x000007ff`01a617bc
00000000`0e0e6cf0 000007ff`01a617e9 0x000007ff`01a617e9
<lots of stack frames>
00000000`0e13ad70 000007ff`01a5d442 0x000007ff`01a617e9
00000000`0e13adf0 000007ff`01a5cf28 0x000007ff`01a5d442
00000000`0e13ae80 000007ff`01a5c39a 0x000007ff`01a5cf28
00000000`0e13aed0 000007ff`01a5bd9c 0x000007ff`01a5c39a
00000000`0e13af20 000007ff`01a5bbaa 0x000007ff`01a5bd9c
00000000`0e13afe0 000007ff`01a5b224 0x000007ff`01a5bbaa
00000000`0e13b020 000007ff`01a5aff3 0x000007ff`01a5b224
00000000`0e13b060 000007ff`01a5af05 0x000007ff`01a5aff3
00000000`0e13b0b0 000007ff`01a6f836 0x000007ff`01a5af05
00000000`0e13b0f0 000007ff`01a582e1 0x000007ff`01a6f836
00000000`0e13b4e0 000007ff`01a50fd0 0x000007ff`01a582e1
00000000`0e13b7f0 000007ff`0221f79c 0x000007ff`01a50fd0
00000000`0e13bdf0 000007ff`019513ef 0x000007ff`0221f79c
00000000`0e13be70 000007ff`0194c972 0x000007ff`019513ef
00000000`0e13bf90 000007ff`01949ff0 0x000007ff`0194c972
00000000`0e13c2f0 000007ff`01341aa2 0x000007ff`01949ff0
00000000`0e13c6a0 000007ff`013409c6 0x000007ff`01341aa2
00000000`0e13c900 000007ff`00ffc48e 0x000007ff`013409c6
00000000`0e13c9d0 000007ff`00f1708c 0x000007ff`00ffc48e
00000000`0e13ccd0 000007ff`008f5ec4 0x000007ff`00f1708c
00000000`0e13cdc0 000007ff`00d23e05 0x000007ff`008f5ec4
00000000`0e13d600 000007ff`00c7e416 0x000007ff`00d23e05
00000000`0e13d6d0 000007ff`00c7ad5e 0x000007ff`00c7e416
00000000`0e13d7d0 000007ff`00c78d85 0x000007ff`00c7ad5e
00000000`0e13d960 000007ff`00c6ccb9 0x000007ff`00c78d85
00000000`0e13d9b0 000007ff`00c69be1 0x000007ff`00c6ccb9
00000000`0e13dad0 000007ff`00c691ab 0x000007ff`00c69be1
00000000`0e13dc50 000007ff`00c684c4 0x000007ff`00c691ab
00000000`0e13dcb0 000007fe`f14ee0ba 0x000007ff`00c684c4
00000000`0e13dcf0 000007fe`f47451c7 mscorwks!UMThunkStubAMD64+0x7a
<more native frames>

We’ve got the base of our stack, we just can’t read it :). Fortunately, the !IP2MD command will turn the last pointer into a description of the method:


0:078> !IP2MD 0x000007ff01a617e9
MethodDesc: 000007ff0237bed8
Method Name: HtmlAgilityPack.HtmlNode.CloseNode(HtmlAgilityPack.HtmlNode)
Class: 000007ff01d1da00
MethodTable: 000007ff0237c3d8
mdToken: 0600000b
Module: 000007ff0237abc0
IsJitted: yes
CodeAddr: 000007ff01a61700

Putting together some copy/paste, some Vim, some !IP2MD and some grep you can turn that list of pointers into the base of your stack:

HtmlAgilityPack.HtmlNode.CloseNode(HtmlAgilityPack.HtmlNode)
HtmlAgilityPack.HtmlNode.CloseNode(HtmlAgilityPack.HtmlNode)
HtmlAgilityPack.HtmlDocument.CloseCurrentNode()
HtmlAgilityPack.HtmlDocument.PushNodeEnd(Int32, Boolean)
HtmlAgilityPack.HtmlDocument.Parse()
HtmlAgilityPack.HtmlDocument.Load(System.IO.TextReader)
HtmlAgilityPack.HtmlDocument.LoadHtml(System.String)
FogCreek.HtmlParser.HtmlParser.Initialize(System.String)
FogCreek.HtmlParser.HtmlParser.ExtractSafeHtml(System.String, FogCreek.HtmlParser.IHtmlTransform[])
FogCreek.HtmlParser.HtmlParser.ExtractText(System.String)
FogCreek.FogBugz.__Global.GetMessageTextByMsg(Wasabi.Runtime.Mail.MailMessage, Boolean, Boolean, System.Nullable`1<Boolean>)
FogCreek.FogBugz.CFullTextIndexer.IndexBugEvent(FogCreek.Search.Interfaces.IDocument, System.DateTime ByRef, Int32 ByRef, FogCreek.FogBugz.CBugEvent, System.Nullable`1<Boolean>)
FogCreek.FogBugz.CFullTextIndexer.IndexBug(Int32, Int32, Int32 ByRef)
FogCreek.FogBugz.CFullTextIndexer.MemorySafeIndexBug(Int32, Int32, Int32)
FogCreek.FogBugz.CFullTextIndexer.IndexItem(System.String, Int32, Int32, Int32 ByRef)
FogCreek.FogBugz.CFullTextIndexer.UpdateByType(System.String, Int32)
FogCreek.FogBugz.CFullTextIndexer.HeartbeatUpdateIndex(FogCreek.FogBugz.CNotification, System.String, Int32)
FogCreek.FogBugz.__Global.SingleHeartbeatFogBugz(Int32, Int32, Int32, System.DateTime)
FogCreek.FogBugz.__Global.SingleHeartbeatPlatform(Int32, Int32, Int32, System.DateTime)
FogCreek.FogBugz.__Global.DoWork(Int32, FogCreek.FogBugz.CTrialManager)
FogCreek.FogBugz.__Global.StartMultiHeartbeat()
FogCreek.FogBugz.HttpHandler.ProcessRequest(System.Web.HttpContext)
System.Web.HttpApplication+CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
System.Web.HttpApplication.ExecuteStep(IExecutionStep, Boolean ByRef)
System.Web.HttpApplication+PipelineStepManager.ResumeSteps(System.Exception)
System.Web.HttpApplication.BeginProcessRequestNotification(System.Web.HttpContext, System.AsyncCallback)
System.Web.HttpRuntime.ProcessRequestNotificationPrivate(System.Web.Hosting.IIS7WorkerRequest, System.Web.HttpContext)
System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr, IntPtr, IntPtr, Int32)
System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr, IntPtr, IntPtr, Int32)
DomainNeutralILStubClass.IL_STUB(Int64, Int64, Int64, Int32)

Step 4: Fix the Bug

What we’ve learned:

  1. We’ve got a crash caused by recursion in HtmlAgilityPack.

  2. Our code is calling into HtmlAgilityPack while processing email for the search index.

You can fish around in the dump a little more to try and find stuff like parameters that will help you track down the requests causing problems, but that was enough to point me in the right direction.

Not coincidentally, we’ve shared our fork of HtmlAgilityPack on GitHub (and a patch on Codeplex).

Bonus: Even More Debugging

While investigating a separate crash I found use for a different command: !analyze -v, which helpfully extracted the relevant exception and call stack all on it’s own:

0:054> !analyze -v
<lots of stuff>
EXCEPTION_OBJECT: !pe ff5ce5e0
Exception object: 00000000ff5ce5e0
Exception type: System.InvalidOperationException
Message: The ConnectionString property has not been initialized.
InnerException: <none>
StackTrace (generated):
<none>
StackTraceString: <none>
HResult: 80131509
 
MANAGED_OBJECT: !dumpobj ff5d0210
Name: System.String
MethodTable: 000007ff001d0d90
EEClass: 000007ff001ccdf0
Size: 2226(0x8b2) bytes
(C:\Windows\assembly\GAC_64\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
String:    at System.Data.SqlClient.SqlConnection.PermissionDemand()
at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
at System.Data.SqlClient.SqlConnection.Open()
at FogCreek.Database.Connection.Open() in d:\code\hosted\build\FB\8.9.106H\fogbugz\FogBugzUtils\FogCreek.Search\FogUtil.Database\FogUtil.Database\Connection.cs:line 79
at FogCreek.Database.Command.ExecuteNonQuery() in d:\code\hosted\build\FB\8.9.106H\fogbugz\FogBugzUtils\FogCreek.Search\FogUtil.Database\FogUtil.Database\Command.cs:line 164
at FogCreek.Database.IndexFile.Unlock() in d:\code\hosted\build\FB\8.9.106H\fogbugz\FogBugzUtils\FogCreek.Search\FogUtil.Database\FogUtil.Database\IndexFile.cs:line 149
at FogCreek.Search.Store.Lock.Release() in d:\code\hosted\build\FB\8.9.106H\fogbugz\FogBugzUtils\FogCreek.Search\FogUtil.Search\Store\Lock.cs:line 26
at Lucene.Net.Index.IndexWriter.Finalize() in d:\code\hosted\build\FB\8.9.106H\fogbugz\FogBugzUtils\FogCreek.Search\FogUtil.Search\Lucene.Net\Index\IndexWriter.cs:line 562
<even more stuff>

Oh look, a finalizer causing a problem. I’ve never seen that before</sarcasm> (Seriously though, if anyone has ever told you that you probably shouldn’t use finalizers, this is why: they’re hard to test, they can interfere with the operation of the garbage collector, and they can straight up crash your app if they generate exceptions).

Conclusion

I put this together because while the internet is rife with WindDbg cheat sheets, it doesn’t seem to have quite as many walk-throughs of how the various and sundry commands might apply to debugging ASP.NET crashes, which commands are useful and what kind of output you might expect. Hopefully this helps you. I know it will help remind me of what to do the next time I need to resort to WinDbg.

PS: If debugging production apps makes you feel a tingling sense of accomplishment, you might like to know that we’re hiring.

FogBugz Visits the Head(er) Shrinker

February 7th, 2014 by Adam Wishneusky

The look and feel of FogBugz On Demand hasn’t changed much in two years. We thought we’d update it, starting with the part that shows up on every page: the header. We re-designed the FogBugz On Demand header to make it more modern, compact and organized.

R.I.P. old header…

old header

Long live new header!

new header

Not everyone has the luxury of a 4K display. When you’re working on a small laptop screen, space is limited. Menu bars, docks and taskbars gobble up vertical space. To make more room for your actual work, we made the new header 15% shorter. We did this by consolidating the two rows into one. The FogBugz and Kiln links from above moved into a hover menu:

new - product dropdown

To fit the menus from the top-right into the new design, we made smarter use of the width of the bar. Our customers told us that they work mostly with cases, so we grouped all of the case-related controls at the left. We used symbols for the right-hand menus and removed the List Cases button. You now get to your filters by hovering over Cases.

The first thing we learned when we rolled the new design out to 10% of accounts was that you click List Cases a LOT. To give you faster access than hovering then clicking inside the new menu, we made Cases clickable. Hover over it to get to a specific filter, or just click on it to show your current case list.

new - cases dropdown

Hover over the four right-hand menus and you’ll see that Admin is now “gear,” Extras is now “toolbox,” Help is now “?” and My Settings is now the avatar menu. Log Out has moved into the avatar menu. If you have a larger screen, you have no doubt noticed that the old search box didn’t do you any favors. Whatever length text you entered, it stayed tiny. The new box knows that sometimes you use a lot of search axes in order to narrow down and speed up your search. While it starts out compact,

new - search box 1

When you click into it and type, it grows so you can see what you’re doing:

new - search box 2

We’d love to know what you think of it so drop us a line. Not using FogBugz On Demand? Sign up for a free trial today!

Bee: A Desktop FogBugz Client for Mac

November 20th, 2013 by Adam Wishneusky

Bee
Bee is a Mac client for FogBugz. It makes tracking your cases simpler and faster with its beautiful design with fluid animations. It is deeply integrated with Mac OS X so you can receive notifications from your teammates and use QuickLook to view case attachments. You can time cases from your menubar and Bee also intelligently tells you what you should be working on next. In addition to FogBugz, Bee also works with plain text files for your project notes and supports syncing tasks with GitHub and JIRA.

Bee requires Mac OS X 10.8+ and is available from the Mac App Store. A free trial and further information is available from the Neat.io site.

Case Event Merging – One Case to Rule Them All

November 8th, 2013 by Stephen Asbury

If you’ve been using FogBugz for issue tracking or customer support for a while, you’ve probably encountered a situation like this. One of your customers sends you an email asking for a new feature, and FogBugz creates a case for you to track the request.

email_one_capture

Five minutes later, the same customer sends another email with brilliant new insights as to how the feature should work. Here comes another case.

email_two_capture

So now you have two cases about the same request. What do you do? You don’t want to reply to the same customer request in two places. You don’t want to copy and paste information from one into the other. You or someone else at your company might miss the duplicates list and the other email chain. It would be much better if you could see both emails in a single case.

Now you can!

Introducing Case Event Merging

Well, maybe I should say re-introducing. We introduced case merging back in August of 2012. At that time we received an excellent solution from one of our customers, for which we are very grateful. We liked the idea so much that we have built it into the FogBugz On Demand Performance Upgrade, hopefully with a few improvements.

Now, when a case is marked as a duplicate, FogBugz does two things. First, it places a message at the top of the duplicate case telling you that its events are now also merged into another case.

leader_duplicate_capture

Second, FogBugz provides you with controls on the main case, located in the “Duplicates” area of the side bar, to show or hide the merged events.

case_hidden_capture

Three controls indicate the types of events you can merge from duplicate cases. From left to right these are:

Email events are shown by default so that you can see the full conversation with your customer. Comments and BugzScouts are initially hidden. Click on each control to toggle the visibility of the merged events. The events are inserted into the normal event list and highlighted in purple, as shown below. They will also let you know which case the event comes from.

case_merged_capture

We have found that most times we want to see events from a duplicate case, it’s the email events we care about. Sometimes you do need the comments, so you can click the control to show them. When looking at crash report cases created by BugzScout, there are often so many events that showing them all can be overwhelming, so they’re hidden by default. Click the control to show them if you need to see every report of the error.

No more clicking around to get all of the information you need! Case event merge consolidates information from multiple cases, allowing you to see everything you need – in one case.  If you’d like to use native Case Event Merge, sign up for the Performance Upgrade to FogBugz On Demand (if you haven’t already). Get started by sending us your site URL.

Update: We have improved case merging! See the docs for details.

Responsive HTML Emails: a Different Strategy

November 1st, 2013 by Tina Ye

Email has become quite the funny thing. It follows us everywhere. To the grocery line. To the dinner table. To the… shower? (Well… why not.) So when we set out to rethink the FogBugz email notifications from the ground up, we knew we had to ensure a great in-shower email experience—and that meant optimizing for mobile.

There are a wealth of resources on this topic. Campaign Monitor has an  exhaustive, start-to-finish guide. Smashing Magazine posted about various mobile email design tricks. MailChimp has written definitively on the topic. And if you don’t want to read so many words, Litmus recently provided a juicy summary of their own.

However, there is one small problem with all of the above: they all advocate the use of media queries.

A Media Query Quandary

Media query support can pretty much be  taken for granted in desktop browsers, but it remains unknown to many email clients today. One of the most popular mobile email clients is the Gmail app for Android and iPhone, and it remains a staunch non-attendee of the media query party. Without media queries to detect device size and reconfigure the layout accordingly, users could be stuck squinting at something like this:

TinyEmail

Pinch me!

A mobile design strategy that doesn’t address one of the most popular mobile email clients isn’t a very good strategy. So we thought… what if we took a different approach?

One Layout to Rule Them All

Most mobile email design articles still want you to think “multiple layouts for multiple screen sizes.” For instance, design a two-column layout for desktop, and then adapt it into a single-column layout for mobile. This strategy relies heavily on media queries to detect the device width and then activate the appropriate layout by reflowing content, shrinking headers, or hiding entire sections. You can see why this would be a problem when media query support is still so spotty…

So rather than depend on media queries to modify the layout, we thought, “Why not just design one layout that looks good on all screen sizes?”

Impossible? Nay, it’s possible!

Mobile First

I was inspired by Luke Wroblewski’s  mobile first approach. Here, one considers the use case with the most limitations first (mobile), and then designs upwards from there. After all, it is easier to fit a small kitten into a big jar than a big kitten into a small jar (They were having a sale at the metaphor factory, okay?). Aaaanyway, it’s a great design philosophy, and it made all the difference in how we arrived at our final design.

We began by asking, what layouts work well on mobile? The answer for us was to think “single column.”

Screen Shot 2013-10-14 at 4.03.36 PM-1

By single column, I mean that the primary flow of the content is downward rather than both downward and side-by-side. Side-by-side content usually requires reflowing to fit on a smaller screen. In contrast, a linear downward flow means content simply scales horizontally to fit the available space. Voila, one layout for any screen size!

Screen Shot 2013-10-15 at 1.43.06 PM

That said, there are times when side-by-side content will not need to be reflowed to fit on smaller screens. Sometimes, the contents of a column can work just as nicely when narrowed down on a smaller screen. Of course, I would not advocate compressing paragraphs of text down to 160px-wide corridors, but it is okay to maintain the side-by-side position of things like labels, asides, notes, and icons. You’ll see lots of examples of this in the final FogBugz notification email design.

Finally, lest you think a single-column approach is too aesthetically restrictive, here are a couple of very nice-looking designs using a predominantly single-column approach. Check out this lushly illustrated piece from Code School. Or this beautifully typeset promo email from Tinkering Monkey.*

PrettyEmails

These are the “desktop versions” of the emails, but because they are single-column, you can easily imagine how they’d scale down to mobile. Screenshots courtesy of Email Wizardry.

As for the design of the Fogbugz notification emails, our goal is to communicate the status of a case quickly and effortlessly. We don’t need a whole lot of stylized typography or eye-catching illustration to do this—that would be distracting and counter-productive. On the other hand, we do need to convey a lot of information, so we relied on strong typographical hierarchy, a flexible grid, and subtle color to organize the design. Here’s a peek at the final design:

NotificationFinal

Because of the diversity of information present, it’s quite a bit more complex than a strictly single-column layout. But it acts like one: it scales nicely horizontally, and does not need to be re-stacked or rearranged to fit on a smaller screen. One layout, multiple screens.

Now that I’ve hopefully convinced you to free yourself from the shackles of designing multiple layouts, let’s see what this looks like at the implementation level…

Writing the Codez

On mobile, you have limited real estate, so it makes sense to use as much of the screen as possible. A fluid width: 100% layout does the trick. We simply apply that inline to the largest container element, and get something like this:

iphone

But on desktop, this same code would create a readability nightmare:

BigWideEmail

This is easy to fix. Let’s put in some breathing room on the sides, with a simple little max-width added (also inline) to the main container element:

NormalEmail

Ah… much better. Now we’re not violating any typographic rules about sane line lengths.

And that’s basically it! You now have your completely responsive, mobile-and-desktop-friendly, superhero-quality email layout, all without using a single media query.

And you thought this section was going to be long.

Wait, What About Outlook?

Darn, we can’t go party just yet! As it turns out, even an old CSS2 property like max-width isn’t recognized in all email clients. Without it, our emails will just go back to being super-wide and hard-to-read. What can we do to solve this?

If you can say with confidence that none of your users will ever view an important email in Lotus Notes, Outlook, or even Apple Mail, then you can skip all this nonsense and head down to the club. For the rest of us, we’ll catch up with you later. It won’t take long.

Lotus Notes 8 & Outlook 2000-2003

Since Lotus Notes 8 and Outlook are exclusively desktop clients, we can get away with forcing them to always show a fixed-width desktop-optimized view. We do that by targeting them with a conditional: Lotus Notes and older versions of Outlook use Internet Explorer as their rendering engine, so we check for IE, then insert a fixed-width constraining element around the entirety of the email’s content.

<!--[if IE]>
  <table width="540" align="center" cellpadding="0" cellspacing="0" border="0">
    <tr>
      <td>
<![endif]-->
[EMAIL BODY HERE]
<!--[if IE]>
      </td>
    </tr>
  </table>
<![endif]-->

Note that the constraining element is a table. This is because, as we discovered, divs cannot be reliably centered in all email clients.

Outlook 2007+

Moving on, we can use the exact same strategy in Outlook 2007 and newer. The only difference is, Outlook 2007+ uses Microsoft Office as its rendering engine. Don’t ask why; just add gte mso 9 to the conditional. That bit of magic incantation there stands for “greater than or equal to Microsoft Office version 9,” which covers Office 2000 or newer:

<!--[if (gte mso 9)|(IE)]>
  <table width="540" align="center" cellpadding="0" cellspacing="0" border="0">
    <tr>
      <td>
<![endif]-->
[EMAIL BODY HERE]
<!--[if (gte mso 9)|(IE)]>
      </td>
    </tr>
  </table>
<![endif]-->

Apple Mail

Unexpectedly, our testing revealed that Apple Mail also fails to respect max-width! Fortunately, it does understand media queries, so we can add a fallback. Put this in a linked stylesheet or between <style> tags in the head:

@media only screen and (min-device-width: 541px) {
  .content {
    width: 540px !important;
  }
}

This just says, “If my device isn’t an itty-bitty phone, then make the whole thing fixed width.”

Done! Here is everything all together in one file.

Finally, remember to test test test. We test on  Litmus, our coworkers, and a small percentage of our real live users. Test until you can test no more, and then release it into the world!

Now we can go party!

png;base64966f535a9ef49316

* I should note that these two examples do use media queries for small refinements like tweaking the spacing and size of the graphics. However, if you view them on a mobile device that doesn’t understand media queries, the experience would still be pretty good. These layouts may use media queries, but they do not depend on them.

FogBugz On Demand Performance Upgrade

October 22nd, 2013 by Dane Bertram

Some months ago we launched a beta for an upcoming infrastructure upgrade of FogBugz On Demand. The response we received was great! Hundreds of you—our awesome customers—signed up to kick the tires on a shiny, new, kiwi-riding-an-ocelot fast FogBugz On Demand service.

When we first launched the beta there were a number of core features that hadn’t been finished just yet: custom fields, the working on menu, quick case add on the list page, etc. We can happily report that all of those features (and more!) have now been implemented! As a result, the beta is now closed and we’ve started rolling out the FogBugz On Demand Performance Upgrade (née “Project Ocelot”) to large swaths of our customers over the past few weeks. Thousands of you in fact.

How can I tell if I have the new hotness?

If you created your FogBugz On Demand account after August 5th, 2013 you’ve been using it the whole time! If not, have you seen this cheery little “Welcome to fast” dialog after logging into your FogBugz On Demand account?

"Welcome to Fast!" dialog from the FogBugz On Demand Performance Upgrade

If you haven’t, your account hasn’t been enrolled in the performance upgrade yet. We’re currently selectively enrolling customers that are an ideal fit given the features that have currently been completed in the new interface. Want to sneak a peek? Let us know your FogBugz On Demand account info and we can enable “the switcher” for you—a toggle for enabling and disabling the Performance Upgrade that lives on your user options page within FogBugz.

If the beta is closed, why haven’t you enrolled everyone?

Just because we’ve completed the beta, doesn’t mean the FogBugz team is off on a sandy beach somewhere sipping Kiwi Koolattas. We’re busy adding more features, porting top-used plugins, and fixing the bugs you’ve been reporting to us about the new, faster FogBugz On Demand and releasing juicy updates every week. Keep the feedback coming!

There are still plenty of things left for us to implement in the new interface. Currently only the list, case, and search pages have been super-charged and there are a number of existing features that haven’t been updated to work with the new interface just yet. In the coming months as we knock more items off our super-fast FogBugz-powered to-do list, we’ll be enrolling more and more accounts.

What makes the Performance Upgrade so fancy? Why’d it take so long? What’s the secret sauce?

Easy there, Captain Questions! We—the FogBugz team—are also planning to write up a bunch of juicy blog posts telling not only the history of “Project Ocelot,” but also describing various parts of the underlying tech that power it. Hybrid modes, generated code, escape hatches, client-side MVC, elasticsearch, JSON APIs, and more!

A huge “Thank you!” again, to all of our faithful beta testers and a warm “Welcome to Fast!” for those of you whose accounts have already been enrolled in the FogBugz On Demand Performance Upgrade. We hope you like it!


Looking for more?

Visit the Archives or subscribe via RSS.