CHUCK:
[Gibberish]
[Chuckles]
CHUCK:
That was really weird.
[This episode is sponsored by Frontend Masters. They have a terrific lineup of live courses you can attend either online or in person. They also have a terrific backlog of courses you can watch including JavaScript the Good Parts, Build Web Applications with Node.js, AngularJS In-Depth, and Advanced JavaScript. You can go check them out at FrontEndMasters.com.]
[This episode is sponsored by Hired.com. Every week on Hired, they run an auction where over a thousand tech companies in San Francisco, New York, and L.A. bid on JavaScript developers, providing them with salary and equity upfront. The average JavaScript developer gets an average of 5 to 15 introductory offers and an average salary offer of $130,000 a year. Users can either accept an offer and go right into interviewing with the company or deny them without any continuing obligations. It’s totally free for users. And when you’re hired, they also give you a $2,000 bonus as a thank you for using them. But if you use the JavaScript Jabber link, you’ll get a $4,000 bonus instead. Finally, if you’re not looking for a job and know someone who is, you can refer them to Hired and get a $1,337 bonus if they accept a job. Go sign up at Hired.com/JavaScriptJabber.]
[This episode is sponsored by Rackspace. Are you looking for a place to host your latest creation? Want terrific support, high performance all backed by the largest open source cloud? What if you could try it for free? Try out Rackspace at JavaScriptJabber.com/Rackspace and get a $300 credit over six months. That’s $50 per month at JavaScriptJabber.com/Rackspace.]
[This episode is sponsored by Wijmo 5, a brand new generation of JavaScript controls. A pretty amazing line of HTML5 and JavaScript products for enterprise application development in that Wijmo 5 leverages ECMAScript 5 and each control ships with AngularJS directives. Check out the faster, lighter, and more mobile Wijmo 5.]
CHUCK:
Hey everybody and welcome to episode 138 of the [chuckles] I almost said the TrackJS show.
TODD:
Yeah! [Laughter]
JOE:
Introducing…
DAVE:
The TrackJS show.
CHUCK:
Hey everybody and welcome to episode 138 of the JavaScript Jabber Show. This week on our panel, we have Jamison Dance.
JAMISON:
Hello friends.
CHUCK:
Dave Smith.
DAVE:
Hello.
CHUCK:
AJ O’Neal.
AJ:
Yo, yo, yo, coming at you live from the Deep South, Provo.
CHUCK:
Joe Eames.
JOE:
Hey, everybody.
CHUCK:
I’m Charles Max Wood from DevChat.TV. We also have a special guest, Todd Gardner.
TODD:
Greetings from the north, Minneapolis.
CHUCK:
Do you want to introduce yourself real quick, Todd?
TODD:
Sure. So, my name is Todd Gardner. I’m one of the cofounders of a company called TrackJS, a JavaScript error tracking service. I’m also a consultant and speaker at various conferences, somewhat straddling the JavaScript and .NET communities.
DAVE:
Cool. So, you like errors?
TODD:
I hate errors. They’re terrible. [Laughter]
TODD:
They generally mean that we didn’t understand something about either our code or our users or our environment. And yeah, so trying to get rid of them as fast as we can is a big important thing for me.
JOE:
I’d like to hear the whole history of what and why about TrackJS.
TODD:
So, that’s a great question. For a number of years, I was a freelance consultant. In fact, I still am kind of, on the side. And I would help big companies and startups build web applications. And with the whole JavaScript renaissance that’s happened over the last four, five years or so, more and more of those clients shifted to building single-page applications with Knockout or Backbone or Angular or now React (it’s up and coming). But with just about every client I would go to, we would need some way to understand how the customers were using the app, because it’s hard to build an app that doesn’t break in some subset of users.
The environment that we deal with is really, really hostile, because each browser has implemented JavaScript in slightly different ways. And then the devices themselves can change. Users install all kinds of plugins that can manipulate the DOM themselves and change things. Or they could be operating on a poor network where a particular resource like maybe a JavaScript file just doesn’t load for some reason, or loads incredibly slow. And so, there are all these things about our environment that we build for that just blow up in ways we could never expect, and ways that we could never possibly test for.
And so, I would build these tools to understand what percentage of my users are encountering errors on different pages. And so, I built these a few different times for a few different clients. And so did my future partners. So, I actually pitched them at a conference in Minneapolis called MinneBar which is an awesome unconference. But I pitched them like, “Hey. We keep building these JavaScript error tracking tools and we’re getting good at it. We have some cool ideas that I don’t see anybody else doing. Maybe we could build this once really, really well so that we don’t have to reinvent it and bill our clients every time. And they were so excited. My partner Eric in fact, he called me on the drive home from the conference just to reiterate how excited he was about the idea, like, “This is brilliant. We got to go do this.” So, we built a prototype of this thing.
And the thing that was really unique about us, about our idea, was that JavaScript unlike other languages like server-side language, if you have the error or the exception object in C# or Python or whatever you basically have everything you need to know to recreate the issue and fix it. But in JavaScript first you have to be lucky enough to even get the error. [Chuckles]
TODD:
Second, you know, and not just some random little piece of information like something screwed up. But even if you get there, even if you have a stack trace it might have occurred so many callbacks deep in your app that you don’t have any idea how this particular situation could have happened. And so, the thing that’s unique about what we do is that we track all of these other events that are going on the page. So, I know we’re trying to understand how your application state is changing by tracking what you put into your console. So then, you could actually add print line debugging messages into your app.
So, we really think using console.log is a really cool thing as long as you can put the tooling around it to not make everything really noisy and gross. And we track the network so that you can understand when something fails because the user’s on a poor connection or maybe there’s some interference going on, on the internet. And then we track the kind of things that the user and the environment are doing, like what are they clicking on? What are they putting into your app? What are the other JavaScript frameworks that are on the page? Maybe, what plugins have been installed? That sort of thing.
So, we had this idea and we went and we built a prototype of it and took it to the JavaScriptMN user group, the local user group. And I begged and pleaded the organizers. “Hey, if I bring this idea, can you give me 15 minutes to show some people?” And they let us do it. So, we brought our prototype in and afterwards I had three different people from significant companies in the area come up to me, basically credit card in hand saying, “I love this. I want it. Sign me up right now,” which was amazing. Of course, I couldn’t sell to them because it wasn’t anything but [chuckles] a duct tape and chicken wire demo at that point. But that was validation to go off and build this thing.
And so, we’ve been iterating on it and growing it ever since.
JOE:
Can you talk more about who ‘we’ is?
TODD:
Oh, yeah. So, Eric Brandes who I mentioned before, he’s another independent software developer in the Minneapolis–Saint Paul area. Nick Pelton is our lead UI creative. He runs another business called Westwerk Design which is like a WordPress and branding consultancy shop also in Minneapolis. And then we actually just hired our first person, which is kind of crazy. His name is Jordan Griffin and he’s a friend of mine for a long time. He’s another C#, JavaScript consultant in Minneapolis–Saint Paul.
DAVE:
So, when was it that you got started?
TODD:
We’ve been running… so, the idea when I pitched to everybody was in March of 2013. And we did our demo in July of 2013. We started the company in August. We launched a private beta for six customers in October of 2013. And we ran for six customers until January where those six customers proceeded to Denial of Service us over and over again. [Laughter]
TODD:
You know, as we [inaudible] “Oh alright. They put us on another app or they got hit with a lot of traffic today.” And our systems would melt under the pressure. But that’s why you do a beta and you learn from it. In January of this year we launched a public beta, which was free and we would bring customers on 50 at a time or so, just to test our systems. And then we started charging in March. So, we were I guess a thing that people could give us money, which was interesting. So, we’ve been going since March as a company that could actually take revenue.
DAVE:
Cool, super cool.
CHUCK:
And now you’re rich. [Chuckles]
TODD:
Someday, I will be. So, TrackJS is bootstrapped, which is a different thing to the whole startup culture. And for a long time we actually felt like we might have doing something wrong because all of the stories we’d hear of famous startups would be, “Oh yeah, we just closed a 40 million dollar venture seed round and we’re hiring like crazy.” And we’d ask, “Well, how much money do you make?” “Oh, we haven’t figured out our business model yet.” And so, we felt like because we had revenue and we didn’t have investors, are we doing something backwards? [Laughter]
CHUCK:
Have you ever watched Shark Tank?
TODD:
I have, yeah, yeah.
CHUCK:
Because it seems like most of the businesses that they are most willing to invest in are the ones that are in the stage that you’re at where you’ve got revenue and you can basically show them, “If you put $10 in we can get $100 back out.” And so, that revenue model I think is critical. So, yeah, don’t think you’re doing anything backward.
DAVE:
Yeah, you’re going to be rich and a TV star.
CHUCK:
Yeah.
TODD:
[Chuckles] Are you saying I need to go on Shark Tank? [Chuckles]
CHUCK:
Not necessarily.
JOE:
I don’t think TrackJS would do well on Shark Tank.
DAVE:
Yeah, something tells me… [Laughs]
JOE:
I don’t think they’d grasp it.
DAVE:
Something tells me they might not be into it.
TODD:
Somehow I need to explain what we do to the average American television watcher.
JOE:
Yeah.
CHUCK:
Yeah.
TODD:
I’m not sure. I have a hard time explaining it to anybody in the technical industry who’s not a JavaScript developer exactly what our problem is.
CHUCK:
Yeah.
JOE:
Yeah, explain it to a reality TV show judge. [Laughter]
DAVE:
What could possibly go wrong?
TODD:
So, the internet is a series of tubes. And sometimes… [Laughter]
CHUCK:
Tubes and wires.
JAMISON:
So, I have a couple of questions about the technical side of error tracking in JavaScript. You talked a little bit about how it’s messed up. Can you talk a little bit more about specifically why you need something like TrackJS? Node has uncaught exception handlers. And browsers will sometimes tell you they have window.onerror. And why isn’t that good enough?
TODD:
Well, it’s getting better but it’s still pretty terrible. So, window.onerror is a thing that’s been around since the very beginning of JavaScript. And you can always just attach this function handler in the browser to window.onerror and get some information about any uncaught exception that happens. But what you actually get on window.onerror is not consistent between browsers at all. Up until about nine months ago, you would only get three pieces of information. You would get the error name, the file it came from, and a line number. So, you get something like ‘e is undefined on scripts.js line 1’, something that you have no idea what that means at all.
In the last nine months or so, it’s been really amazing. All of the edge browsers have implemented at least two more properties. They give you also a column number, which is interesting, but they give you the actual error object. So, they give you an object that contains the stack trace or whatever that particular browser had implemented on error. But this is really only available in the last version or two of Chrome, the last version of Firefox, Internet Explorer with a certain patch on it, and Safari something. I don’t particularly know.
The problem is that most applications that we run, at least if you’re targeting an enterprise or a SAAS project, chances are we have to support browsers that don’t have this yet. And so, to actually get error information, to get an error itself, you need to find more creative ways to catch the error. Even if you have error, what I found with some research that we’ve been doing is that the error itself is implemented differently even if you look at IE 11, latest Firefox, latest Chrome, you can’t just go…
JAMISON:
It’d be too easy.
TODD:
[Chuckles] Yeah. If you just go into the console and type new Error(‘blah’), you will get three different shapes of objects in those three browsers. Now, there are patterns. But they’re not identical. You couldn’t shove them through the same ingestion system and process them the same way without knowing what browser they came from.
CHUCK:
So, you can’t just say, “Shove it through here. Oh, it’s not that one. Try the next one.”
TODD:
You can. But we’re talking about those three browsers as very common.
CHUCK:
Yeah.
TODD:
But now you also have to deal with all the old versions of them that could be running in public. You have to deal with their mobile variants, their modded variants, their development variants. You get into Android browser and Chrome and the number of browsers that have differences in this becomes very, very large. And so, it ends up being easier for us anyway, on our backend is we understand what browser it came from so that we know how to process it.
CHUCK:
Did I just hear you…
DAVE:
So, how do you solve the problem?
CHUCK:
I think I just heard you basically call the internet a legacy system. [Laughter]
TODD:
Well, I’ve heard lots of definitions of legacy systems. My personal favorite is that a legacy system is any system that I didn’t write. [Laughter]
TODD:
And so, I definitely did not write the internet. So, that’s probably true.
JOE:
That is a good definition. [Chuckles]
CHUCK:
But Dave’s question is a good one.
DAVE:
Yeah, so given all the variants in how browsers do this, what is your solution?
TODD:
A lot of complicated checking at low levels.
JOE:
So, you’re basically the jQuery for error handling, is what you wrote.
TODD:
So, we do have to do a lot of similar things to jQuery. And I have, we’ve looked to the jQuery source a lot for, how did they solve particular problems? So, a lot of what TrackJS does is because we can’t count on these common, like an easy way to capture an error from any given browser. We patch or we override a lot of the base-level browser API and insert listeners in its place.
So, when we’re on the page and you want, and you make an Ajax request, technically we’ve patched XML HTTP Request to be our own thing. And we intercept your call, we record some information about it like when it was started and what kind of call it is, and then we record when it comes back. And so, we can tell the difference and record that, “Hey, an Ajax event happened. Here is the result of it.” Now, that’s all totally transparent to you or to the people using us because we mirror the browser API exactly. We would accept the same values or return the same values. And being that those values change depending on what browser we’re on, there is a lot of experimentation and a lot of cross-browser testing to make sure we don’t break things.
Probably the most interesting thing that we discovered with that was actually for Chrome on iOS 7 and above. So, Chrome on iOS actually doesn’t include their own version of WebKit. They just are a UI that sits on top of the existing Safari WebKit, right? But so, the browser code needs to communicate with the backend native code. And rather than having their own, like a native piece of code to do that, they actually send Ajax calls that we could intercept at the application layer. So, I would have just a webpage that I’m showing on Chrome on iOS and TrackJS’s listeners could pick up the communication that Chrome was sending back to Safari’s WebKit.
DAVE:
Whoa. Seriously?
TODD:
Seriously.
CHUCK:
That is awesome.
TODD:
We were listening to them. We were detecting them. We had to filter them out because we actually thought they weren’t relevant, that we didn’t want that happening. But for a while because they would actually have their own undocumented API of some things that they were doing, we would generate these really nasty security warnings saying that, “Oh, we think there’s some sort of forgery happening here.” And it was because we weren’t fully accounting for all of the parameters that they were sending through. And so, this is one particular example. But there’s all kinds of these niggly little things with different browsers on how they’ve chosen to do things.
JOE:
Wow.
DAVE:
So, earlier you mentioned how when you’re deep in callback, nested callbacks in your app, and somehow TrackJS is able to reassemble these errors so that you can tell that this Ajax request that threw an exception, or this response rather that threw an exception, originated from X over here. Is that how you do this, is by tracking all these Ajax requests so that when an error happens, you could tell from where it originated?
TODD:
So, we can’t pinpoint exactly where it originated from. We can give you hints as to what else was going on at the time. So, there are a couple of different things going on here. One is we have this event engine, which is what we’re listening to. We’re listening to console. We’re listening to Ajax. We’re listening to user clicks and inputs. And as that’s happening, we’re just recording this thing into a log that’s sitting in browser memory. So that’d say, “Hey, these are the interesting things that are happening. This is what’s going on.”
When an exceptional event happens, like we caught an error or there’s a couple of different things we regard as exceptional. If somebody wrote console.error or a global error happened or we caught something bubbling out of the DOM or an Ajax came back with a failing code, if any of those things happen we say, “Great. Here is an error. Here’s something that the developers probably want to know about.” And I have that error information itself but I also have this log of all of the things that were happening that led up to it, which is interesting. We call that telemetry. It’s like, “These are all the things that were going on to get to this particular state, to get to this situation.” And so, we feed that information back to the developers. It says, “We have 20% of your users using IE11 on this page. And the users land on this form. They enter this. They click on this button. This Ajax goes off. And then you get this error,” which is a lot more information than just, “Blah, something wasn’t defined.”
JAMISON:
Yeah.
CHUCK:
I really like the approach, especially since what I heard was, “We can’t read the stack trace either.” [Chuckles]
CHUCK:
“So, we’re going to give you all the other information because we’re watching everything.”
TODD:
Right. Well, so the upper part of this whole thing is the actual stack trace itself, because you really need both pieces of information to deduce. You need to understand how your code is running but you also need to understand, how did you get to that code? And so, TrackJS is more likely to capture a stack trace then if you weren’t doing anything at all, because we actually wrap up all of the different places that you could be passing a callback into the DOM.
So, when you attach and addEventListener or a setTimeout, you’re passing a function into the DOM that could blow up. So, we’ve actually transparently wrapped that up in a try/catch handler. And so, we’ll actually catch errors emanating off of it with more information. And we actually rolled out this other thing that you have to turn on because it’s got some performance issues with Angular specifically. But we have this thing called an asynchronous callback. So, are you familiar with the Chrome Async Stacks in their latest version of Dev Tools?
JAMISON:
I know it’s…
DAVE:
Yeah, I was just going to ask you about that.
JAMISON:
It’s a magic button that you click.
DAVE:
Yeah.
TODD:
So, imagine. So, what Chrome Dev Tools is, is you can click on this magic button and now you can see the stack trace of, “Here is the stack trace of the current executing frame.” But you can also see back and see the stack trace of the executing frame that might have attached that callback. So, if I have a click handler that blows up, the stack trace it’ll give me is only back to where that event called back. It’ll start with your onclick function. But it’s interesting to know, how did this onclick function get bound up? How did this actually get attached? And so, the Chrome Dev Tools tell you that, will trace it backwards, these stacks all the way back to the origination of the page.
So, we implemented actually something similar. I know we call it Async Stacks. And so, you can opt into this and we’ll actually capture a stack trace at the time you bind an event. Now, we can't go back forever. We only capture the previous two stacks due to some memory limitations, because we need to run in all browsers. We can’t run just in latest Chrome. But it’s interesting to look at a stack trace where you can say, “Great. I can see this onclick handler. I can go back to where that was started. It was bound up, say in initialize function that was part of my application wiring it up.” And so, you can see a lot more information about how did an error actually become a callback, [inaudible].
JAMISON:
What do you use to capture…
CHUCK:
Can [inaudible]…
JAMISON:
Oh, go ahead.
CHUCK:
I just want to ask, because the issue that I have with backtrace is usually the size of the async stuff, which you explained fairly well, is that my backtraces always look like, “Okay. Here’s what happened in your code. And then it went through all these, line 1 of minified jQuery or line 1 of minified Angular or line 1 of minified something else.” And so, at that point the stack trace is pretty much useless. [Laughter]
TODD:
Yeah.
CHUCK:
Does TrackJS help with that at all?
TODD:
Not directly. So, there are two different things you can do to get better about that. The first is you can name functions. So, oftentimes the thing that produces non-valuable stack traces is when you pass anonymous functions into the libraries. And so, the thing that blows up is probably your anonymous function. Chances are it’s not actually jQuery or Angular blowing up. But if you don’t give a name to this function that you threw into there, it’ll blow up and it’ll just say, “Hey, something blew up inside of Angular.” So, you can get around that by actually naming your anonymous functions, which is well supported.
When you’re typing in some function you’re going to pass in, say function myName and then the parameters just to give it a descriptive message. Now, there is, a footnote to that is if you need to support Internet Explorer 9 or before, there’s some features that it chose to implement with the names of functions will leak into their containing scope. I can shoot you guys a link to actually a very, very thorough research of this particular issue you could include in the show notes. It’s a quirky, hard thing to debug. But if you don’t have to support IE9 it’s a non-issue.
The other thing you can do to get a better one is to generate source maps. So, when you are minifying your JavaScript file, it’s going to filter out all of these things like the names of the functions that you use and reduce it to K or X or whatever. And that’s not very helpful. But if you produce a source map which you can do from either Closure Compiler or Uglify, it’ll produce a .map file which will translate back to the original function names and stuff like that. And we support that in TrackJS where if we give you a stack trace that says, that looks like garbage to you, it’s full of non-helpful information, you can actually just drag and drop your source maps on top of it and we’ll translate it back to the original things, along with code snippets of, “These are the actual real source code lines that generated this stack trace.”
CHUCK:
Cool.
DAVE:
So, one of the things I really liked about some of the other backend error tracking systems I’ve used is that when they capture an exception, not only do they get the stack trace but they get the environment at each frame of the stack trace. So, you can see what local variable values were at each time. Is that even possible in JavaScript?
TODD:
You know, I’ve looked into it. If it is, I do not know a way. So, if any of your listeners happen to be brilliant like that and just know how to do that, send me an email and we should talk, because I have no idea how to get access to that without being super intrusive and replacing parts of the DOM that I’m not comfortable doing.
JAMISON:
It seems like it’s a language feature level thing.
DAVE:
Yeah, that’s what I was thinking.
CHUCK:
So, I have another question and that is, how intrusive is it? And I’m asking specifically about on mobile devices, a lot of times I’m limited by bandwidth constraints or memory constraints or both. And so, how large is it to pull in or do I just put it into my build process and process it with everything else? And then how much overhead does it add to the things that you’re tracking with the events?
TODD:
Yeah, that’s a good question. So, the actual JavaScript library itself, I haven’t measured in a while.
The last time I did, it was 6K after gzipping. And so, it’s pretty lightweight. You probably wouldn’t notice it compared to most other libraries. You can reference it directly from our CDN, which we host on CloudFront. Or you can pull it in locally and bundle it with all your other scripts. So, hopefully 6K isn’t too heavy. We’ve tried to strip that down as small as we can. So, you’ll have to pull that in.
And we ask that we’re before any of your custom scripts on the page, because of the nature of how we do things with patching a lot of the base-level browser API. If any errors happen before we’re on the page or if they grab references to things before we’re on the page, we’ll either not know that the error happened or we won’t know as much information as we could. And so, the sooner we can get onto the page, the better. Now, that does have some concerns around blocking calls. I know a lot of people like loading JavaScript in async. And although we do work and we support it, there is the downside of anything that happens before we’re on the page is blind to us. And so, there’s a risk that you take on. You’re gaining some performance doing async but you’re sacrificing some visibility to errors.
In terms of the actual performance of your app, the default configuration of TrackJS, so we have a pretty rich API in JavaScript that you can configure what we do differently. But the default configuration, nobody has ever noticed a performance overhead. Somebody did actually publish a jsPerf spec on us. And there was a, oh I think like a 6 millisecond overhead to throwing an error that they noticed on their particular machine. Because the performance issue is specific to the machine that you’re running on, I can’t say that, “Oh, we add exactly this.” Essentially as we’re listening there is one extra level function call that happens whenever you bind an event or fire an Ajax call. And there is a little bit of extra processing that happens to gather information when an error is thrown. But hopefully when an error is thrown, it’s not very often to the point that you need to worry about that being a major performance. Usually you want to know the information is more important than maybe a momentary performance loss there.
Memory footprint is very, very low. So, the in-browser event log is limited to 30 things which we serialize down to strings. So, we’re not keeping references to any objects. And we only know the last 30 things that have happened, which is just what we chose as a relevant time horizon there.
The only part of our system that we have found to have some performance issues is that asynchronous call stacks. And that’s specifically because in order to capture that stack trace we have to essentially throw an error every time you bind an event. We throw an error and we capture the stack trace off of it. And so, the nature of that is we have a memory footprint for every event that is bound. And there is a processing overhead to generate a stack trace for every call to addEventListener.
And so, Internet Explorer 10 and before specifically have a pretty significant performance impact with throwing an error. And Angular under the cover specifically attaches a lot of events to the DOM. And so, you combine those two things and old versions of Internet Explorer running Angular with this feature on have a noticeable performance impact, which is why we left it off by default. And we just ask our customers to, “Hey, test this out. Make sure that this is an acceptable performance for your app and for your scenario.”
DAVE:
Don’t old versions of Internet Explorer running Angular already have a massive performance problem?
[Laughter]
TODD:
Absolutely, absolutely.
CHUCK:
Well, what was that that you called it in IE9? A feature?
TODD:
[Chuckles] Well so, it’s not a bug because it’s in their spec. That is what they chose to implement. And at the spec they were implementing at the time as far as I know, there was nothing explicitly saying that they shouldn’t do this or they couldn’t do this. But so, when you define, when you type something like var foo equals function foo and then you define your function, the subtle difference in behavior is that the name of that function, that function foo leaked out into the global scope. And so, you have this double variable thing happening where both the var foo and the function foo overwrote each other. And so, the values that you are working with might not be what you understand. I can’t really even do justice explaining this without a computer in front of me. So, I’ll send you guys a link that anybody who’s interested can dig in further on this.
CHUCK:
So, I’m wondering too. Does the performance or anything else change when you’re on a mobile device? Or are there other gotchas on the mobile device?
TODD:
Mobile devices are pretty good generally. We don’t add a significant amount of performance overhead in terms of what we’re just [inaudible], what we’re listening to. There’s one extra little JavaScript function call that happens as we are listening to events. But raw JavaScript execution time is rarely the thing that slows down an app. It’s usually things like DOM manipulation and CSS reflow and that sort of thing. It’s actually the things that are causing perceived performance problems in their app. If you are doing a lot of really, really heavy JavaScript manipulation and a lot of calls into the DOM or a lot of calls into the browser API very rapidly, we could become something there. But chances are you shouldn’t do that in a mobile device to begin with.
CHUCK:
And if I go out of range of the cell tower does it save up the stuff or does it just try and fire an Ajax call and then handle it however the browser handles that when it fails?
TODD:
So, we’re actually looking at offline caching right now. That’s one of the things that are on deck for us. But right now what we’ll do is when we attempt to send an error and if you’ve fallen off the network, our client will see that, “Hey, we couldn’t talk to our server,” and it’ll shut itself down and not try and send them anymore. That’s both a, we don’t want to cause a lot of churn on the browser if that connectivity is not working. It’s also a throttling capability for our own server, because if our server’s not able to ingest stuff fast enough we want our clients to slow themselves down.
JAMISON:
Can I ask a little bit about the server technology?
TODD:
Absolutely.
JAMISON:
Is it interesting at all?
TODD:
Well, I think it’s very interesting.
JAMISON:
Alright.
TODD:
But this is a JavaScript show. And a lot of the server-side technology is .NET based.
JOE:
Hey, that’s a favorite on here. [Laughter]
TODD:
So, the server-side tech, we’re hosted on Microsoft Azure cloud. And we utilize that pretty heavily. When you send us an error, we grab it and we store it in a queue and we process them later. And that’s how we handle a lot of our ingestion problems over the day. So, all of the things come into a queue where we have a series of larger machines behind that that are processing data in off of the queue. Our data, we store it all in Elasticsearch which is amazing. If you haven’t played with Elasticsearch before, that’s actually built on the JVM part of Lucene, or it’s built on top of Lucene. And it’s a fantastic searchable document storage system. Many…
JOE:
Lucene‘s awesome.
CHUCK:
Yeah.
TODD:
Yeah, yeah. So, we actually started it as, “Hey, we’re going to use this thing for search,” because that’s what it was named for. And we stored all of our data elsewhere. But over time as we grew, we found that we really didn’t ever access our data anywhere other than from Elasticsearch. And so, today we actually just store everything in Elasticsearch. We back up out of Elasticsearch. We do every, Elasticsearch is our persistence. And it works fantastic for us. So then, after data’s in Elasticsearch we have an ASP MVC app that renders our UI. It’s probably 90% server-side rendered. And then we use Pjax and Backbone on the frontend to augment a few things and make some more seamless transactions as you’re clicking through our UI.
DAVE:
I have a question about your UI.
TODD:
Yeah.
DAVE:
Does it use TrackJS? [Chuckles]
TODD:
Absolutely, it uses TrackJS. So, we absolutely dog-food this. We’ve actually caught quite a few of our own bugs with TrackJS which is incredibly validating [chuckles] when we can use our own tool. So, in side projects all of us are using TrackJS in all of our other projects. It is amazing feedback, first of all because you’re never more honest than with yourself when you say, “Hey, this tool sucks because X.” You can fix it really fast, because it’ll help yourself in more than one way.
JOE:
Yeah.
TODD:
And in fact, we’re playing with the idea of how do we open up maybe even our own demo. I think it’d be really cool if you hit the TrackJS page, if I could just let you see TrackJS on TrackJS. I’ll just let you in and you could play around and see the kind of errors that we get and the information that we collect. I think that’d be a really cool way to show people what we do and how we’ve instrumented our own app to get more information. But we’re still working on that.
DAVE:
You might blow up a lot of people’s heads with the mental recursion there, though. Be careful. [Laughter]
TODD:
TrackJS on TrackJS. Well, I actually got the idea from another company called Baremetrics which is really cool. They show you all kinds of metrics about how a Software as a Service company is performing. And they plug in to Stripe. And the thing that sold me, the thing that gave me the idea, is you can go and get the metrics of Baremetrics. I can go in and I can see what they’re doing for monthly revenue, because they just publish it. Like, “Here’s our business metrics.” [Chuckles]
TODD:
I thought that was incredibly, I mean it’s brave. To show off how you’re performing internally for the world to see is very, very brave. But it was also very reassuring. They trust their tool enough to just show it off to the whole world. And I thought that was just really, really cool. And I want to do the same thing.
DAVE:
Cool. Well, I wanted to ask a little bit more about console.log.
TODD:
Yeah.
DAVE:
You talked about something, but I didn’t quite understand what you were saying.
TODD:
I love console.log. Console.log was one of the first things I started using to understand how my JavaScript app worked. But what was always so infuriating is that it wasn’t consistently implemented. And so, I’d start writing console.log to either debug or capture some information. But you run it in an old version of Internet Explorer and it just wouldn’t work. And what was even crazier or more infuriating is you’d open up the debug console and then it would start working.
JOE:
Yeah. [Chuckles]
TODD:
And it would stop working and you’re like, “Oh, why won’t this work?” But I think console.log is an incredibly valuable tool. Just about any other language has some sort of logging facility built into it that is valuable to just, occasionally you’re in a function doing something interesting. You’re changing state in some way. And you write a log message just so that if something goes wrong later, you can understand more about that. Well, console.log is that for JavaScript. And so, what we do is we polyfill console.log so it’s safe to use in all the browsers. But we also listen to it. And so, the things that you send into console.log go directly…
JAMISON:
Wait, wait, wait, wait, wait. Safe to use in all the browsers?
TODD:
Yeah. So, we…
JAMISON:
Why is console.log unsafe?
TODD:
Well, my earlier example of if you put console.log and you shipped to a browser that, or you shipped to IE9.
JOE:
Right.
TODD:
And you had a console.log in your app, as soon as your function execution hit console.log, IE9 would throw an error saying, “log is not a function.” Your execution would stop and you would just be left there. So, if you put a console.log at the top of an onclick function, the user would click something, an error would be generated, and nothing in that onclick function would happen. That’s what I mean, not safe.
JAMISON:
I think I wasn’t listening when you said that part, because that sounds bonkers. [Laughter]
TODD:
That hasn’t [bit] you before, Jamison?
JAMISON:
No. I have not had to do very much with IE.
TODD:
Oh, you’re a very lucky man.
JAMISON:
[Chuckles]
TODD:
You are very, very fortunate.
JAMISON:
I’m sheltered.
JOE:
Yeah, you are.
TODD:
A lot of the apps that I still work on target enterprise or government or internet spaces. And they make ridiculous amounts of money. But they have to support old browsers. So, we still have to deal with these things.
DAVE:
I got to tell a console.log story. So, I don’t know if anyone heard, but when Todd was talking he said this. If the Dev Tools are open in IE9 console.log works. And if you close them, I think it actually keeps working for the life of that browser session, right? And so, as a developer you don’t even realize you’ve written this bug and then you send your thing out to production or whatever, or to your QA team, and they’re like, “None of this stuff works.” And it was so bad for us on our team that we actually wrote a unit test that greps our code for console.log. [Laughter]
DAVE:
And fails the test if you use it natively.
JOE:
Awesome.
TODD:
Well, so probably a better solution to that would have been to do something like TrackJS where we polyfill console.log. So, we go over and we examine window.console and we make sure it’s there. And then we go over console.log, console.info, warn, debug, error, the major parts of console. And we make sure that they’re all functions. They might not actually print to a console, because if the browser didn’t implement that there’s nothing we can do. But we can make sure that they’re all valid functions, that they won’t die if, or that your execution won’t stop if you call it.
And then we actually gather the information that you sent into it and we record it as part of our telemetry. And so, you can go ahead and put console logging statements in your code at interesting parts. And then when an error happens, we’ll feed that information back to you. So, you can see how your application changed over time, which we actually think is really cool. It’s totally changed how I’ve written single-page applications just to be able to log stuff that I want, that I think is interesting.
CHUCK:
Now, we’ve talked a lot about TrackJS and I think it’s a really cool tool. But I’m interested in what you think best practices are for handling, tracking, and even creating errors and error objects in your code.
TODD:
Yeah. So, I think errors are, I think a lot of JavaScript developers are either afraid of them or don’t understand them. When something bad happens, it’s a lot easier to trace down what happened if you have some sort of descriptive message. And so, when you’re writing a function that does something, usually there’s some sort of expectation that the arguments you got in have a certain shape or the values on the object you’re dealing with are in a certain range of values. And if they’re not, if you don’t do anything, it’ll just blow up in an anonymous way. It’ll say either ‘undefined is not a function’ or a ‘property doesn’t exist’, or something like that when you try and reference something.
type:
throw new Error(‘param blah was expected but not found’) or something to that effect. So that when this actually blows up in a real situation, you have a message that actually tells you what happened. And I rarely see that in code.
And there are a couple of reasons for that. One is, because of how dynamic JavaScript is, you can’t possibly or you shouldn’t necessarily test for every possible, or write errors for every possible input and output of the function because of how much code ends up needing to get shipped down. You can’t put a paragraph of error text in an error because that would all have to be downloaded by the browser and create a slower time to deliver that file and heavier memory weight on the browser and all those sort of things. But rather than, you can’t do everything but what we do now is almost nothing. And I’ve rarely seen any code that throws an error.
And I think, at least in my own applications, I’ve found a lot of benefit to checking for common things that could go wrong, checking that the parameter that I got is not undefined. And if it is, throw an error right then and there so that I know, so that I can debug that issue later.
CHUCK:
That makes sense. But if you throw an error, it still halts execution in everything else, just like the regular ones that you get out of the browser right? So, you have to be aware of where you’re putting them and what the effect is going to be if it blows up.
TODD:
Absolutely.
CHUCK:
Even if you explicitly tell it to.
TODD:
Yeah, you’re absolutely right. I’m not saying to avoid the error. I’m saying that if you’ve gotten into a situation where you have a function that got called improperly in a way that it shouldn’t have, I think it’s better to throw a descriptive error at that point rather than just let the browser throw a ‘blah was undefined’ message because it will help you debug it sooner. Now, you shouldn’t just bury that error, because chances are you were needed to do something with that data. So, the error existed.
All I was saying by throwing an error is to actually give better information about it. People should throw their own errors with their own messages in them rather than just relying on the varied implementation of browsers to tell you different messages that may or may not help you. And so, if the function that you’re executing or the function that you’re calling maybe is not necessarily, and so an error is unneeded, you can always just use try/catch and then log off that the thing happened. But don’t actually halt execution. But that very much depends on the situation that you’re in. I generally prefer to throw the error and stop execution. And then hopefully you’ve built some sort of logging tool that you can feed that information back so the developers know that it happened.
CHUCK:
So, the other thing that I have a question about on that is, and I haven’t really looked at the error implementation in JavaScript, and it sounds like you said it varies from browser to browser. So, is there a way to standardize that some or are you still limited by what the browser gives you?
TODD:
No, there are some ways to standardize that a little bit. So for example, even to this day the implementation of Error, if you go into Firefox, Chrome and Internet Explorer 11 and you just go into the console and type new Error, the fields on all three of those objects are slightly different.
In fact, if you look at Internet Explorer 11 it doesn’t have a stack trace in that particular case, because in IE11 you actually have to throw an error to get its stack trace. Throw is a keyword that will actually perform that action whereas in Firefox and Chrome you have the stack trace just for instantiating the error. But even then, all of the fields are slightly aligned in different ways. And the format of the stack trace itself, the string is in a slightly different format. So, Chrome has implemented a stack trace API where you can actually get a stack trace as an array of strings with more information, which is really cool, except that most people can’t just write for only Chrome.
And so, there are a couple of actually really cool libraries that could help with this if you want to build some stuff yourself. The first is stacktrace.js which is a really cool library that attempts to normalize the stack trace across different browser implementations. And in a browser that perhaps can’t even generate a stack trace like IE9 it will attempt to guess the stack trace. It will actually inspect the JavaScript files themselves and try and guess the names of functions and recreate one. It’s not 100% accurate and it does have some performance issues obviously because it’s pulling in and doing a lot of string manipulation, but it’s pretty cool.
The other library that does some similar capabilities is called TraceKit. And TraceKit will do the same thing where it will help normalize an error object.
CHUCK:
Very cool.
TODD:
But of course, if you use TrackJS you don’t have to worry about any of that.
CHUCK:
Of course. [Laughter]
TODD:
That goes without saying.
JAMISON:
I was going to ask a question that will cause a conflict of interest.
CHUCK:
Go.
JAMISON:
What are your competitors? Are there others? Is TrackJS the only thing that does this hosted JavaScript error tracking stuff?
TODD:
No. There are a few other people in the space. And in fact, something new seems to be jumping into the space every month or so, which is interesting. There are a number of larger companies that do this sort of thing that I won’t name on the air. So, there are a number of competitors that exist in the server-side aspect of error tracking. And there’s a ton of really great tools and I’m sure you all know, have heard of one, or probably used them. And there’s some really cool functionality there to gather error information from your server infrastructure and aggregate it together and give you a bunch of insight.
But the niche that we feel is not being, there’s not a good solution, is in the client-side. And all of these server-side tools, they have an entry into the client-side error tracking. But typically it’s about capturing whatever happens on window.onerror and sending it back to the server, which we found is just not enough. Just because you happen to catch an error object in browser-side JavaScript doesn’t mean you have enough information to actually fix it. And so, that’s what we’re trying to do, what’s unique about us, is how we really capture and in-depth almost like marketing analytics style information about what’s happening in the browsers to feedback as additional context to figure out, how did the user, how did the app, and how did the environment arrive at this error to begin with? And so, that’s the niche I think we’re filling. And when it comes to actually finding an error and understanding enough information to actually fix it, I haven’t seen another tool that can come close to what we’re doing right now.
JOE:
That’s awesome. So, I want to ask about pricing.
TODD:
Yeah. So, we have a little bit different model of pricing than I think a lot of people expect. We do not price our system based on number or errors you send us, which is kind of odd. Our internal cost would be much more closely aligned to errors. But instead, we price you based on how busy your site is. So, we price based on what we call hits. So, how many unique times our tracker initializes every month.
And so, the idea behind that is I want to help you get to zero errors. Well, it’ll never get to zero errors but I want to help you get to as close to zero errors as realistic. And when I help you get to zero errors, I feel like I’ve added a whole lot of value. And I don’t want to basically price myself out. And so, we bill or we price our system based on how busy your site gets. The better an application you write, the more popular it will become and the more you grow. And so, larger more established applications will need to come into a higher tier for us. If you just have your own personal blog or your own little web app and you just want to play with it, it might even qualify for our free tier. So that’s, you would just come in pretty easy.
JOE:
So, you do have a free tier? I just glanced at it and I didn’t see the free tier.
TODD:
[Chuckles] Yeah, we kind of copied the…
JOE:
Oh yeah.
TODD:
The 37signals kind of path.
JOE:
Right.
TODD:
And so, there is a free tier. We just don’t make it super obvious. It’s pretty restricted. We only show you what happened in the last 24 hours and you have to have less than 10,000 unique hits a month. But that’s usually enough for a personal developer to play with it and see what’s going on and get accustomed to it. And that’s what the free tier was designed for, just for people to play, see what they want to do.
DAVE:
Super cool. I was going to ask about that, too. I’m glad to see that.
CHUCK:
Alright. Well, is there anything that we should have asked about before we get to the picks?
TODD:
No. I think I covered everything I wanted to talk about.
CHUCK:
Cool. If people what to get more information about TrackJS or about what you guys are working on, what’s the best place to do that?
TODD:
Well, you can get it at a couple of places. The basic information’s on the website. That’s TrackJS.com. You can reach out to me or my team at hello@trackjs.com or hit us up on Twitter. We have the @trackjs handle. If you want to just reach out to me personally, I’m out on Twitter as well, @toddhgardner or todd@trackjs.com.
JOE:
Awesome.
CHUCK:
Awesome. Alright, let’s get some picks. Dave Smith, got some picks for us?
DAVE:
Oh, you know I do. Oh, I’m torn. I actually have a long list but I think I’m going to limit it down to just two. The first one is a tool that has been around a lot longer than I realized but that many people would benefit from using (and we are going to start using it at my work and I’ve already started using it for personal projects) and it’s called Webpack. So, I never really got into Grunt or Gulp for that matter. But Webpack seems to do exactly what I want with bundling my JavaScript and my CSS and my assets. It looks to be really cool. And I started using it on a personal project yesterday and I have liked it a lot.
And that leads me to my second pick, which is because I was using Webpack to do a React project, I was writing a lot of JSX. And I found this really cool vim plugin called, uncreatively, vimjsx. And if you just clone that into your bundle repo you can get really nice JSX syntax highlighting and auto-indenting and everything, which is actually a bit tricky for editors because HTML and JavaScript is weird. But it is a really nice plugin for vim. So, those are my picks.
JOE:
Awesome.
JAMISON:
Webpack is rad.
CHUCK:
Vim. When are you going to use a real editor? [Laughter]
CHUCK:
I have to get those in every once in a while. [Laughter]
CHUCK:
Alright. Jamison, what are your picks?
JAMISON:
I have many picks. Actually, I’ll just do three. So, the first pick is a little browser game called skeal, like seal mixed with ski.
JOE:
You’re going to have to spell that out.
JAMISON:
S-K-E-A-L. And the game in fact is Seal the singer mixed with skiing. So, it works well. It was made for [Ludum Dare] I think. It just made me giggle uncontrollably.
The next pick is this interactive game visualization thing around diversity and segregation called Polygons. It’s made by Vi Hart who does these really cool YouTube math videos and this person that I can’t remember his name. I think Nick, maybe. I don’t know. But anyways, they basically took some papers that people did on population dynamics and how these game theory rules apply to groups of people. And they made actual games based on them where you try and move people around to make them happier. And you see that if people prefer and are unwilling to be with people that aren’t like them, then that results in a lot of segregation. But if you change people’s preferences so that they prefer being with people that are less like them, then that creates a more diverse community. It’s just a really cool illustration of the power of interactive visualizations in communicating ideas.
And the last pick is this new Paul Graham article. I know some people roll their eyes at everything Paul Graham writes. But I thought this was one pretty wise, ‘The Fatal Pinch’. It talks about something that happens towards the end of a startup lifecycle. It matched my own experiences really well and I wish that I had read it a year ago. It’s pretty short and it’s well-written and it’s nothing controversial or crazy or whatever. So, those are my picks.
CHUCK:
Awesome. Joe, what are your picks?
JOE:
Alright. I got three picks today. The first one is the Hour of Code which is a national or international educational push to get kids to try out coding. And the whole point of it is to get kids to spend an hour coding. This week, the week of December 8th through December 11th is National Computer Science Week. And so, by the time everybody hears this it’ll be a little bit late. But you can get involved next year by volunteering to teach an Hour of Code at a local elementary or hosting your own event. I’ve actually gone and taught a couple of events already this week. I’m going to teach a couple more. But Code.org is the place that is the source for all of this and they have these materials for kids.
So, if you have any interest in your kids, say under age 15, you want to get them into programming, Code.org has some really cool games that they can play and learn to code at the same time. One of them uses basically visual coding, drag and drop type stuff with the characters from Frozen. So, if you have younger kids or girls that are way into Frozen, it’s a really great way to introduce them to some of the logic and concepts of coding like loops and things like that. And then there’s another game called Code Combat which is really cool because it’s actually like a fighting game. You have a little character but you control them by writing code. And you could a bunch of different languages on that one, JavaScript, Python, et cetera. And I’ve done it already with a couple of classes of 30 kids and they’re just so absorbed. So, if you have any interest in getting your kids into coding, these are great places. And I’ll put the links in the show notes. But they’re all linked off of Code.org.
And while I’m at it, I want to pick my daughter who came and helped me out. She’s been doing web development for a year now and she was great. She actually ended up teaching the Governor of Utah how to code, which was pretty cool to watch that happen.
TODD:
[Chuckles] Cool.
CHUCK:
That’s awesome.
JOE:
Yeah. Afterward, she got interviewed by a news station and they asked her how it was to teach the governor how to code and she says, “It was like teaching my grandpa how to use Facebook.” [Laughter]
JOE:
Yeah, it was pretty cool. And I’m going to make that my, that was a multi-part pick so I’m going that my only pick for today.
CHUCK:
Alright. AJ, what are your picks?
AJ:
Just piggybacking off of Joe’s coding games there. I’ve picked this once before. It’s called Untrusted. And it is a game where you write the game in order to complete the game. So, you start out basically in a room and I don’t remember what the first level is. But it’s like your character can’t move or something like that, or the exit doesn’t exist so you have to uncomment the line that allows your character to move or creates the exit object or something like that. And then you just go through the levels and it gets progressively harder. And you have to modify the code of the game in order to be able to complete the level. And I had a lot of fun doing that.
And I’m also going to pick Firefly because no matter how many years… [Laughter]
AJ:
It’s been since they didn’t ever finish the series, I always want them to. And I always love rewatching episodes.
DAVE:
Keep the dream alive.
AJ:
Exactly.
CHUCK:
[Laughs]
AJ:
And there’s one episode called Objects In Space and it’s just hilarious. And maybe it’s not that hilarious if you haven’t watched other episodes. But there’s this bounty hunter who’s very poetic and just has a lot of really funny lines. I was watching that today. It was awesome.
Also I will pick Studio C which apparently is gaining a lot of popularity right now because they had a video called ‘Scott Sterling’ that came out. It’s a comedy sketch about soccer. But my favorite one of theirs recently is ‘Peeta’s Song’ that’s making fun of The Hunger Games. I love The Hunger Games but I do admit that Peeta really does need to be made fun of. [Laughter]
AJ:
And then just as a follow-up I finished ‘Ready Player One’, loved it. It was absolutely great. And I also finished ‘A Link Between Worlds’ and I think that it’s probably my favorite Zelda game. So, that’s what I got.
CHUCK:
Alright. You know what, I don’t know if I have any picks today. It’s just been a crazy week. I am looking for contracts and I’m putting stuff together. So, if you are hiring JavaScript or Ruby people or if you’re okay paying a little lower rate to get some iOS work done, I am happy to pick up any or all of that. And yeah, Todd, what are your picks?
TODD:
I have three picks. The first one is an awesome conference that talks about some really important problems and that’s NotepadConf out at NotepadConf.com. And this is the textiest conference that you’ll ever attend. [Laughter]
TODD:
All about the latest technological advancements in plaintext editing. And it’s for developers, content authors, plaintext enthusiasts, or people who just need to strip formatting out of copying/pasting text. There will be a Spring NotepadConf coming up called Notepad Live, date to be determined. But it will be sometime in Minneapolis.
The second pick is NDCvideos.com. NDC is the Norwegian Developers Conference. And they record every session that they do in really high quality video and post them all online for free, which is really, really cool. They just finished NDC London and so those talks will be up soon. But there are several years’ worth of talks online at NDCvideos.com.
And the third is Elasticsearch, which I mentioned earlier but it is just amazing. It’s an amazing open source project that does all kinds of really, really cool things with storing and reporting and aggregating your data, and totally worth checking out.
CHUCK:
Awesome.
DAVE:
[Chuckles] I’m sorry. Can you tell me more about NotepadConf? [Laughter]
TODD:
Yeah. I can tell you lots about NotepadConf.
DAVE:
Question one.
JAMISON:
I’d say Todd is a NotepadConf evangelist, actually. A certified NotepadConf MVP perhaps? [Laughter]
TODD:
I’m not certified yet. I’m still waiting to hear back from Microsoft on this. [Laughter]
TODD:
But I am in contention for the Microsoft MVP award for Notepad. [Laughter]
CHUCK:
Oh, man.
DAVE:
Am I just uninformed or am I being trolled? I would love to go to this conference [laughs].
TODD:
So, the first one already occurred last November.
DAVE:
I see.
TODD:
There will be another one and it’s going to be modeled very much after Visual Studio Live. But this one will be Notepad Live. [Laughter]
DAVE:
Oh my gosh.
TODD:
And we’re going talk [chuckles] we’re going to talk about what’s coming up in Notepad for Windows 10.
[Laughter]
DAVE:
I just clicked the register button. [Laughter]
DAVE:
I’m not going to spoil it.
TODD:
So, NotepadConf.com is a treasure trove of dry developer humor. Totally go check that out. [Chuckles]
CHUCK:
This is great.
DAVE:
I don’t see an address. Where’s the address. Oh, there it is. Okay, I’ll [inaudible]
TODD:
Oh, I like… I think…
CHUCK:
I need to submit to the Call for Proposals.
[Laughter]
JAMISON:
It looks pretty exclusive. I don’t know.
CHUCK:
Yeah, maybe.
TODD:
No, they’ve got some good stuff here, ‘.TXT: NoSQL before it was cool’. [Laughter]
TODD:
Well, yeah. Clearly, most developers, the first time you wrote some sort of data persistence it was to a text file, right? We’ve been doing NoSQL forever.
CHUCK:
Yeah. [Laughter]
JOE:
‘To Monospace or Not To Monospace: A Guide to What Typeface You Should Be Using’. Is that one of the new features in Notepad? You can choose typeface now?
TODD:
Well you could always choose a typeface. You didn’t have to pick a monospace typeface.
JOE:
Oh, wow.
JAMISON:
See, it’s comments like that that make me…
CHUCK:
Ooh, fancy.
JAMISON:
I’m going to vote for you to be the Notepad MVP.
DAVE:
Yeah, no kidding.
JAMISON:
Because it’s by voting, right? Isn’t that how they pick MVPs?
TODD:
I think so. I think you… somebody sends a nomination in for MVP.
JAMISON:
And then you campaign.
TODD:
And then I think, I’m not sure who’s allowed to vote. I think it might just be other insiders. [Chuckles]
JAMISON:
Oh, so it’s like the illuminati but for Notepad.
TODD:
Yeah, yeah. The Microsoft illuminati. [Laughter]
CHUCK:
Oh my gosh. Yeah, we’ll email both Microsoft people we know. [Laughter]
CHUCK:
Alright, well I think we’re done. So, we’ll wrap up the show. We’ll catch you all next week.
[Have you noticed that a lot of developers always land the job they interview for? Are you worried that someone else just landed your dream job? John Sonmez can show you how to do this with the course ‘How to Market Yourself as a Software Developer’. Go to DevCareerBoost.com and sign up using the code JJABBER to get
$100 off.]
[This episode is sponsored by MadGlory. You’ve been building software for a long time and sometimes it’s get a little overwhelming. Work piles up, hiring sucks, and it’s hard to get projects out the door. Check out MadGlory.
They’re a small shop with experience shipping big products. They’re smart, dedicated, will augment your team and work as hard as you do. Find them online at MadGlory.com or on Twitter at MadGlory.]
[Hosting and bandwidth provided by the Blue Box Group. Check them out at Bluebox.net.]
[Bandwidth for this segment is provided by CacheFly, the world’s fastest CDN. Deliver your content fast with CacheFly. Visit CacheFly.com to learn more.]
[Do you wish you could be part of the discussion on JavaScript Jabber? Do you have a burning question for one of our guests? Now you can join the action at our membership forum. You can sign up at
JavaScriptJabber.com/jabber and there you can join discussions with the regular panelists and our guests.]