Linux swap directories quickly

If you’re hopping back and forth between say /etc/apache2 and /var/log/apache2. From /etc/apache2 type:

pushd /var/log/apache2

 

This pushes /etc/apache2 on the directory stack and then cd’s to /var/log/apache2. Now to go back, just type:

pushd

 

This swaps the current directory and the directory on the top of the stack. pushd again and you’re back to /var/log/apache2.

Triggering xdebug from PHPStorm’s REST client

If you want to trigger and xdebug session from PHPStorm’s REST client (or anywhere else for that matter), you can set the debug cookie manually. Add a new Request header:

  • Name: Cookie
  • Value: XDEBUG_SESSION=PHPSTORM

phpstorm-xdebug-cookie

The value to use for XDEBUG_SESSION can be set in php.ini under xdebug.idekey

 

PHPStorm Tip – Conditional Breakpoints

Simple Condition:

After creating a breakpoint -> right click -> Edit. The conditions box lets you enter the conditions under which the breakpoint will suspend execution.

breakpoint-conditional

Break only if another breakpoint has been hit:

I’ve found this really handy for functions that get called a lot, but I only want it to suspend when it’s been called from a specific place. This is great, for example, if I want to only break on a line after it’s been called by a specific test. Here’s how:
1. Set a breakpoint in the unit test. Right click -> Edit -> Uncheck ‘Suspend’ (because I don’t actually want it to stop here)
breakpoint-trigger
2. Set a breakpoint on the line I actually want to suspend on. Right click -> Edit -> Uncheck ‘Suspend’, Select the breakpoint from step #1 in the “Disabled until selected breakpoint is hit”. If you have so many breakpoints that its hard to find the one you want, see the last tip below.
breakpoint-target

Bulk edit / delete breakpoints:

You can get to the bulk edit screen using any of these methods:
  • Ctrl + Shift + F8
  • Right Click on a Breakpoint and click “View Breakpoints”
  • Menu: Run ->View Breakpoints
Within the dialog, hitting Ctrl + A then Delete will remove all breakpoints.

Compacting a dynamic VHD

Start Diskpart from the command prompt.

select vdisk file="<path>"
compact vdisk

 

Designing in the name of “flexibility”

Oh man, the post, Winning is the worst thing that can happen in Vegas, names and calls out a tendency of which I’ve gradually been gaining self-awareness.

Future coding is a lot like playing the roulette. If you can guess where the requirements of tomorrow will land today, you’ve just scored the ultimate programmer’s prize: looking like a wizard. You saw the future and you were right! High five, brain!

That’s the almost irresistible draw of “flexibility”—often just a euphemism for building half or whole features before you know how they’re supposed to work or whether you need them. Just like in Vegas, the worst thing that can happen is to be right about this once in a while.

 

Relating to technical debt:

Running up the debt on your code is not just about the quick hacks and dirty commits you know you really should clean up (but just don’t). No, the far more insidious kind of debt is that acquired in the name of “flexibility”.

 

Equating this to technical debt never crossed my mind before but really resonates with me. Before hearing this talk, I had been thinking a lot about the role of code comments. Over this past year my conviction that comments bring more of a liability than benefit 99% of the time has been deepening. They take time to write (which could be spent on writing clearer code to begin with), and when they aren’t maintained (which seems to happen a lot), the code is much harder to understand than if there were no comments at all. It’s not much of a leap for me to agree that coding for unknown future requirements is a bad thing. It becomes a liability that must be understood and maintained and rarely outweighs the benefits of getting it right once in a while.

Grasping Complexity with Both Hands

I really enjoyed this talk, Grasping Complexity with Both Hands (outline), by Glenn Vanderburg. Here are a couple of his ideas that I found really thought-provoking:

New idea doesn’t have to be perfect to be good. Don’t dismiss them as soon as you find a single flaw.

How to make decisions in the face of truly complex problems:

  • Don’t think in terms of right and wrong solutions. Think in terms of costs, benefits, and risks.
  • Don’t expect a perfect and complete answer. Try to find 80/20 solutions.
  • Don’t expect to find a perfect, simple solution that covers all edge cases and all possible things that can go wrong. Ways to tackle this:
    • Solve the common case optimally, and accept sub-optimal solutions for the edge cases.
    • Don’t try to predict everything that will go wrong and prevent it. Instead create good feedback loops so that you can respond when something actually does go wrong.

WordPress + IIS + Wincache = plugin update trouble

A while ago, we started having trouble updating our wordpress plugins (and wordpress itself). Updating a plugin would fail with a “Could not remove the old plugin”. The plugin directory is there, but empty, and strangely cannot be deleted. We’ve found that restarting the app pool seems to resolve everything, even allowing the auto-update to work correctly.

We finally found the root cause. It’s a known issue with wordpress and the version (1.1.630.0) of wincache we’re using. Updating to the latest development build (1.2.1209) seems to have resolved the issue.

TeamCity & Beanstalk: bad_record_mac

I started getting bad_record_mac errors when TeamCity would try to connect to our SVN repository hosted on beanstalkapp.com. Here is the fix:

  • From command prompt, run
  • c:teamcitybintomcat7w.exe //ES//TeamCity
  • Click the “Java” tab
  • Add the following to Java Options:
  • -Dsvnkit.http.sslProtocols=SSLv3
  • Restart the teamcity service

From: http://devnet.jetbrains.net/thread/434355;jsessionid=D5DF978AB09E2CD1E16F9C8B65482E94?tstart=-2

WordPress Admin Alert

If you want to show a message in the Admin area of wordpress, add the following to your functions.php of your theme:

add_action( 'admin_notices', 'warning_method' );

function warning_method()
{
   echo '<div>Message here.</div>';
}

 

Omniture API: Pulling Campaign Tracking Code Click-Throughs programatically

This is the process I used to pull campaign tracking code click throughs programatically through the Omniture Reporting API. While you can start with code, I found it to be much more productive to use Omniture’s API Explorer to figure out exactly what I wanted first. The API Explorer is nice because it shows you the available methods  with their parameters and gives you immediate feedback as to whether it worked or not. The first section below goes through the API Explorer. The second half contains the code I wrote and is specific to C# and Visual Studio 2010.

 

Access to the API

First, you need web service access to Omniture. This creates a Share Secret key which is used instead of your password when making API calls. The username passed to the API is a combination of your company and your Omniture username: <username>:<company>.  Your username and shared key should look something like this:

  • Username: jdoe:Company
  • Shared Secret: 728275238473afe875ae398fea323ad3

 

API Explorer

You’ll want to verify that your username and shared secret actually work. The best way to do that is with the API Explorer. Enter your username and shared secret in the first section.

2012-04-10_142911

In the next section, choose “Company” for the API and “GetTokenCount” for the Method. This is a great Method to start with because it doesn’t require any parameters. Click “Get Response”.

2012-04-10_143825

The response shows up in a box below. If there are any problems, the error will appear here. If all is well, you’ll see the data you requested. In this case, we asked for the Token Count and got back 9978. Omniture gives you an allotment of API tokens. Each call you make (regardless of the response size) consumes 1 token.

2012-04-10_143320

Now that we know that we can successfully access the API, the next step is figuring out the API calls you want to use and the parameters that they take. In my case, I wanted to get a Ranked Report containing the number of Click-throughs for each Campaign Tracking Code. The Report API documentation explains most of the parameter fields and options. I selected “Report” for the API, and “GetRankedReport” for the Method. This populates the parameter section with a template for all possible options (it can be a bit overwhelming, but fortunately, you don’t need most of it most of the time).

2012-04-10_144729

After quite a bit of trial and error, I ended up with this:

2012-04-10_145725

Which results in this response:
2012-04-10_150038

Once you figure out how to pull the data you need through the API explorer, it’s time to move on to the code.

 

The Code (Visual Studio 2010 specific)

Omniture has created guides for a number of different platforms. You can search for them on the Omniture Developer Connection. In my case, I’m building the project in Visual Studio 2010, which has a guide and some libraries that Omniture created. I followed steps 1-4 of the guide to get started as they are. Their API client class follows the request structure you used in the API Explorer pretty closely. You need to create a reportDescription object within which you will put the parameters you need.

I decided to create an Extension method to populate the reportDescription object for me. Here it is:

public static class reportDescriptionExtensions
{
    public static reportDescription PopulateWith(this reportDescription reportDescription, string reportSuite, string startDate, string endDate, string filter, int top, int startingWith)
    {
        reportDescription.reportSuiteID = reportSuite;
        reportDescription.dateFrom = startDate;
        reportDescription.dateTo = endDate;
        reportDescription.metrics = new reportDefinitionMetric[]
            {
                new reportDefinitionMetric() { id = "instances" }
            };
        reportDescription.elements = new reportDefinitionElement[]
            {
                new reportDefinitionElement()
                {
                    id = "trackingCode",
                    search = new reportDefinitionSearch()
                    {
                        type = reportDefinitionSearchType.and,
                        keywords = new string[] { filter }
                    },
                    top = top,
                    startingWith = startingWith,
                }
            };

        return reportDescription;
    }
}

 

Note that the reportDescription object is created outside of this method and is passed in. I’ve both hardcoded some of the values and passed in others as arguments. I ended up adding in a few extra parameters that I didn’t have in the API Explorer example above: I added a search and split the results into pages (top & startWith). Note how the values and structure here are pretty close to what we had in the API Explorer.

Here is the client I created to pull down the report and convert it to my own reporting format. I’ll break each section down below.

public class SiteCatalystClient
{
    private string url;
    private string username;
    private string password;
    private int top;

    public SiteCatalystClient(string url, string username, string password)
    {
        this.url = url;
        this.username = username;
        this.password = password;
        top = 10000;
    }

    public ClickthroughReport GetClickThroughsReport(string reportSuite, string filter, string startDate, string endDate)
    {
        using (var client = OmnitureWebServicePortTypeClient.getClient(username, password, url))
        {
            ((CustomBinding)client.Endpoint.Binding).Elements.Find<TransportBindingElement>().MaxReceivedMessageSize = int.MaxValue;
            var startingWith = 0;
            var report = new ClickthroughReport();
            var executionCount = 0;

            do
            {
                var trackingCodeReportDescription = new reportDescription().PopulateWith(reportSuite, startDate, endDate, filter, top, startingWith);
                var reportResponse = client.ReportGetRankedReport(trackingCodeReportDescription);

                foreach (var dataPoint in reportResponse.report.data)
                {
                    report.AddRecord(new ClickthroughReportRecord()
                    {
                        Name = dataPoint.name,
                        ClickThroughs = (int)dataPoint.counts[0]
                    });
                }

                startingWith += top;

                if (reportResponse.report.data.Count() < top) break;
            } while (++executionCount < 10);

            return report;
        }
    }
}

 
Let’s break this down. The constructor takes the API url (https://api.omniture.com/admin/1.3/), username (the combined username from above), and password (shared secret). I also set top to the number of records I want to fetch each time.

public SiteCatalystClient(string url, string username, string password)
{
    this.url = url;
    this.username = username;
    this.password = password;
    top = 10000;
}

 

The only method that this class has at this time is to pull the Compaign Tracking code click-throughs. It takes the reportSuite, filter (filters on the actual tracking code to narrow the results down), and startDate and endDate. It returns a ClickthroughReport object which is my own object I use elsewhere in my project.

public ClickthroughReport GetClickThroughsReport(string reportSuite, string filter, string startDate, string endDate)

 

Next I instantiate the client that Omniture provided in the library we downloaded earlier, then I overrode the MaxReceivedMessageSize to the largest possible value. This sets how large the messages can be coming back from Omniture. The messages for my reports were quite large, so I just set this limit as high as it could go.

using (var client = OmnitureWebServicePortTypeClient.getClient(username, password, url))
{
    ((CustomBinding)client.Endpoint.Binding).Elements.Find<TransportBindingElement>().MaxReceivedMessageSize = int.MaxValue;

 

Then I set starting values for startingWith and executionCount and create my ClickthroughReport object which I will return from this method.
var startingWith = 0;
var report = new ClickthroughReport();
var executionCount = 0;

 

 

We go into a do while loop. Our result set is paged, so each time through the loop pulls the next range of data. I have it limited to 10 loops though because I don’t want this report to run for too long.

do
{
    ///.....
} while (++executionCount < 10);

 

I create the reportDescription object (this was provided in the Omniture library) and populate it with my extension method, PopulateWith, that I showed above.

var trackingCodeReportDescription = new reportDescription().PopulateWith(reportSuite, startDate, endDate, filter, top, startingWith);
Now we finally get to the actual API call. We give it the reportDescription object we just created.
var reportResponse = client.ReportGetRankedReport(trackingCodeReportDescription);

The reportResponse object contains a property called report which contains a property called data. Data is an array with the values we want. I loop through each item and place it in to my own report record object:

foreach (var dataPoint in reportResponse.report.data)
{
    report.AddRecord(new ClickthroughReportRecord()
    {
        Name = dataPoint.name,
        ClickThroughs = (int)dataPoint.counts[0]
    });
}
The last little bit is to increment the record we’ll start with next time and break out of the loop if we’re at the end of the result set.
startingWith += top;

if (reportResponse.report.data.Count() < top) break;
I return my report object which is essentially just a list of campaign codes with their corresponding click-through values.
Next Posts