I recently heard a quote by Tom Ziglar on a Ziglar Show podcast that went like this: “The fastest way to success is by replacing bad habits with good habits.”

This got me thinking. What kind of bad habits do I have, and what do I want to replace them with?

I started writing down a list of bad habits that I have, and discovered that a lot of them went like this:

  • I’m not very organized.
  • I’m not in the physical shape I want to be in.
  • I’m not holding people accountable for the results they produce like I wish I was.
  • I’m not following through on the tasks I delegate as well as I’d like.
  • I’m not setting clear enough standards and expectations for myself and my team.
  • I’m not …

I realized that most of these could easily be reversed into statements like:

  • I’m always getting better at being organized.
  • I’m working on my physical health and improving my fitness.
  • I’m holding people accountable for the results they produce.
  • I’m following through on the tasks I delegate.
  • I’m setting clear standards and expectations for myself and my team.
  • I’m …

Taken a step further, I’m looking for little improvements for each of these areas each and every week. If I’m targeting being more organized this week, maybe it means that I’m working on writing down every task or commitment I make. Maybe I’m focused on labeling my emails more accurately.

Soon, those small steps add up to big change as the new habits I’m replacing the old habits with are becoming more and more ‘normal’ to me, and I am gradually improving in the areas that I’ve identified as places I want to improve.

There’s no quick road to success, just hard work and perseverance.

So you’ve just gotten that management role for which you’ve been gunning for months or years now. Congratulations! You’re a few weeks in, and you’re realizing that you are in over your head, and that maybe this isn’t all it’s cracked up to be. You’re looking for advice, and I’ve got some for you!

Have a story you want to tell

Some people call this a vision. I like the concept of ‘telling a story’. Think about what you want your story to be six months, a year, and 3 years down the road. Use some of your thinking time to put yourself into the future and look back on the time period you’re going for. Think about what the journey looked like, and write it down.

Here are some questions to ask when coming up with your story:

  • What does your team look like?
  • What have you accomplished together? What ‘next-level’ things did you achieve?
  • How have you grown?
  • What direct impact have you had?
  • How are things better than when you found them?

You don’t have to know everything

In David Marquet’s book Turn the Ship Around he mentions how he had studied for over a year to take command of a certain type of submarine. He studied how everything worked, and was an absolute expert on every facet of that type of submarine. At the very last minute he was reassigned to one of the most underperforming submarines in the US Navy. To add insult to injury, it was a class of submarine that he was not familiar with. He learned some valuable lessons about how you don’t have to be an expert, and you don’t have to know everything to be an effective leader. In fact, the opposite was true. He was more effective because he empowered his crew to make decisions based on the information they had (which is often much more than the leader has.) This allowed him to be freed up to focus on more strategic issues affecting him and his crew. Ultimately, his crew and submarine went on to become one of the highest rated crews in US Navy history.

Here’s a great talk where he shares some of these ideas:

Like many companies, I’m sure, we’re investigating using Sensu for monitoring and Graphite for metrics collecting. The docs for making these two commuicate together over AMQP are pretty good except for one thing.

Using the docs that I’ve read, when you start up Sensu first with its default options for AMQP, and then start up Graphite to read from that queue, Graphite will crash every time it tries to create the exchange. The reason for this, after lots of hair-pulling and debugging, is because Graphite is hard-coded to set up a durable exchange for its metrics, while Sensu’s default is to set up a non-durable exchange. RabbitMQ will not allow you to create an exchange with the same name and different options, so whichever piece of software created the exchange will work, but the other will blow up all over your face.

The solution to this is pretty simple, but I haven’t seen it documented anywhere. Simply add "durable": true to your exchange configuration in your Sensu config.json like so:

    "handlers": {
        "graphite": {
          "exchange": {
            "name": "graphite",
            "type": "topic",
            "key": "metrics",
            "durable": true
          "type": "amqp",
          "send_only_check_output": true

Hope that helps!

WordPress is awesome, why’d you switch?

So, I’ve been really hating WordPress as a blog engine lately. Tons of spam, lots of emails from spam accounts signing up and trying to post comments, etc. We had some discussion at the office recently about what blog engine to use for our corporate blog, (we ended up using WordPress) but through the process I decided to evaluate Octopress as an approach to static content serving for my personal blog.

On top of the security issues that I’ve been dealing with (constantly updating the software, plugins and deleting spam), I host at Dreamhost. They are not known as the fastest hosting company around, and I was finding that my pages were loading so slowly that it was beginning to get frustrating.

Plus, I could never find a good WordPress theme that I wanted to look at and I never have time to spend customizing a complex WordPress theme.

Enter Octopress

I evaluated Octopress for about 10 minutes and knew I was hooked. I loved the simplicity and the beauty of its default theme (and since it’s themeable using SASS I can easily customize it) and the ease of deployment to any number of hosting platforms (rsync, github pages, heroku, etc) leaves no excuse not to use it! Also, since all the content is generated dynamically on your machine and then uploaded as static content, it is very fast to serve on the server, and is less prone to spam and security holes.

How I did it

I simply exported all of my posts and pages using the Export functionality in the WordPress administration tool and then ran it through exitwp. The result was phenomenal! I ended up with an export of all my pages and posts. Since I was already using Disqus all the comments came over automatically.

I did have to do some very basic formatting for some of my code snippets in order to get the syntax highlighting to work properly, but that was a simple matter of just setting the language in the generated markdown files.


I use the Rsync deploy method to my Dreamhost shared server, but I am also considering migrating to github pages at some point. Deploying is as simple as:

$ rake generate
$ rake deploy

And that’s it! You can even streamline it more by only running one command:

$ rake gen_deploy

Overall, the migration was even more simple than I had expected, and I’m very happy with the results! Now the hard part is coming up with interesting content to put here!

I have been working on migrating my company’s Pivotal Tracker to JIRA. We love most of the features of JIRA, but we were really missing the nice updates to our Campfire room to tell us what is going on with our issues.

Sure, we could use an RSS feed plugin for Campy, but that is not real-time enough.

I didn’t want to write a huge plugin just to send messages to Campfire (it seems like such a simple thing to do!). I was poking around for solutions, and came across this plugin. It’s a plugin that runs scripts written in the Groovy dynamic language for Java. One nice thing about this plugin is that it lets you execute Python (Jython) or Ruby (Jruby). The only problem is that you can’t write a listener using Python, so I ended up having to learn Groovy.

Here’s what I came up with. It requires you to install the HTTPBuilder libraries for Groovy, and this script will require some customization to fit your environment. Right now it only supports sending messages when new issues are created and when a new comment is added to an existing issue, but other issue events would be easy enough to add - this is meant as an example.

import com.atlassian.jira.event.issue.AbstractIssueEventListener
    import com.atlassian.jira.event.issue.IssueEvent
    import com.atlassian.jira.ComponentManager
    import org.apache.log4j.Category
    import groovyx.net.http.RESTClient
    import static groovyx.net.http.ContentType.JSON
    import static com.atlassian.jira.event.type.EventType.*

    class CampfireListener extends AbstractIssueEventListener {

        void workflowEvent(IssueEvent event) {
            def Category log = Category.getInstance("com.onresolve.jira.groovy.PostFunction")
            def campfire = new RESTClient('https://CAMPFIREID.campfirenow.com/room/ROOMID/')
            def issueBaseUrl = "http://yourjirahost:8080/path-to-jira/browse/"
            campfire.auth.basic 'CAMPFIRE AUTH TOKEN', 'X'
            switch (event.getEventTypeId()) {
                case ISSUE_COMMENTED_ID:
                    def resp = campfire.post( path: 'speak.json',
                                          body: [ message: [ type: "TextMessage", body:
                                              String.format("%s added a comment to %s (%s%s):",
                                                  event.issue.getKey())] ],
                                          requestContentType: JSON)
                    resp = campfire.post( path: 'speak.json',
                                          body: [ message: [ type: "PasteMessage", body:
                                              String.format("%s", event.getComment().getBody()) ] ],
                                          requestContentType: JSON)
                case ISSUE_CREATED_ID:
                    def resp = campfire.post( path: 'speak.json',
                            body: [ message: [ type: "TextMessage", body:
                                String.format('%s created a new issue: "%s" (%s%s):',
                                    event.issue.getKey()) ] ],
                            requestContentType: JSON)
                    resp = campfire.post( path: 'speak.json',
                          body: [ message: [ type: "PasteMessage", body:
                              String.format("%s", event.getIssue().getDescription()) ] ],
                          requestContentType: JSON)