<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tracelytics Blog</title>
	<atom:link href="http://www.tracelytics.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.tracelytics.com/blog</link>
	<description>Let&#039;s Talk About Your Performance</description>
	<lastBuildDate>Tue, 13 Nov 2012 17:06:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Tracing Python &#8212; An API</title>
		<link>http://www.tracelytics.com/blog/tracing-python-an-api/</link>
		<comments>http://www.tracelytics.com/blog/tracing-python-an-api/#comments</comments>
		<pubDate>Fri, 14 Sep 2012 12:00:37 +0000</pubDate>
		<dc:creator>TR Jordan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.tracelytics.com/blog/?p=1723</guid>
		<description><![CDATA[New Python Instrumentation! We&#8217;re pleased to announce a new Python instrumentation version &#8212; Oboeware 1.1! We&#8217;ve added a few new libraries recently, but we&#8217;re really excited about the new customization&#160;<a href="http://www.tracelytics.com/blog/tracing-python-an-api/">...read more</a>]]></description>
			<content:encoded><![CDATA[<h1>New Python Instrumentation!</h1>
<p>We&#8217;re pleased to announce a new Python instrumentation version &#8212; Oboeware 1.1!</p>
<p>We&#8217;ve added a few new libraries recently, but we&#8217;re really excited about the new customization API we&#8217;ve introduced in this version. More than just a Python bump, this is the first package we&#8217;re releasing with an implementation of our new Oboe API. The Oboe API is a common set of idioms and metaphors for extending Tracelytics instrumentation or quickly writing your own from the ground up. We&#8217;re excited to get it out there, and we&#8217;re even more excited to see what you build with it!</p>
<p>Conceptually, the Oboe API is a multi-tiered system that allows instrumentation of everything from simple function calls to crazy distributed asynchronous event-driven applications. There are three parts: the low-level API, the high-level API, and language-specific functions.</p>
<h2>Language-specific functions</h2>
<p>The <a href="http://www.tracelytics.com/docs/oboeware/1.1/oboe.html#convenience-functions">language-specific functions</a> are just that: language-specific idioms that give you the most tracing bang for your buck. In Python, we&#8217;ve put together 4:</p>
<ul>
<li>The <code>@trace</code> decorator allows you to start a trace wherever you want. While we catch most web requests, sometimes it can be valuable to trace your backend processes as well. This can give you visibility into celery jobs, command-line scripts, or cron jobs.</li>
<li>In an existing trace, the <code>@log_method</code> decorator creates a new layer. We use this extensively in <a href="http://www.tracelytics.com/docs/oboeware/1.1/oboeware.html">oboeware</a> to actually instrument the standard python libraries like urllib2, pylibmc, or pymongo. If you&#8217;ve got an internal API client, or even just a wrapper around an existing library, use this to make sure you&#8217;re seeing exactly how performant that library is!</li>
<li>The <code>@profile_block</code> and <code>@profile_function</code> allows you to mark particular blocks of code in your app, and we&#8217;ll keep track of them in Tracelytics. If you&#8217;ve got a particularly thorny algorithm, or just a lot of log parsing to do, throw it inside a <code>@profile_block</code>&#8230;
<pre class="brush: python; title: ; notranslate">
log = open('log.txt', 'r')

with oboe.profile_block('log_parsing'):
    # Unzip, read, segment, analyze, understand, ...

log.close()
</pre>
<p>&#8230; and make sure you&#8217;re never losing sight of how long that job is taking.</li>
</ul>
<p>We understand that modifying your code with performance annotations can be trying. These functions aim to be one-line modifications that open up whole new areas of visibility in your app, with no change in functionality.</p>
<h2>High-Level API</h2>
<p>Do you want to trace your custom-built, high-performance, NumPy simulation library? Are you looking for a simple way to instrument your <a href="http://code.google.com/p/protobuf/">internal-but-open-sourced RPC protocol</a>? Or do you maybe want to trace all 7 custom tiers in your in your 7-tier web app?</p>
<p>The <a href="http://www.tracelytics.com/docs/oboeware/1.1/oboe.html#high-level-api">high-level API</a> provides a logging-like set of functions that report to the Tracelyzer agent. With these functions, you can control exactly what, where, and how you report your performance information. Additionally, this lets you control the key/value pairs reported, which can be used to mark certain layers for special treatment in Tracelytics. For instance, adding the <a href="http://support.tracelytics.com/kb/instrumenting-your-app/extending-tracelytics-customizing">KVOp key</a> identifies the layer as cache. Adding these keys to a <a href="http://redis.io">fictional hybrid Cassandra / memcache cache</a> would allow visualization in the same place.</p>
<pre class="brush: python; title: ; notranslate">
oboe.log_entry('memssandra', { 'KVOp': 'get'})
try:
    return cache.get_value(key)
except Exception:
    # log exception and re-raise
    log_exception()
    raise
finally:
    oboe.log_exit('memssandra')
</pre>
<p>Layers introduced by the high-level API aren&#8217;t an afterthought &#8212; they&#8217;re treated exactly the same as any other layer within the Tracelytics interface. Each layer gets its own visualization and a set of filters, and you can set Alerts on it just as you would full requests or application times.</p>
<h1>Low-Level API</h1>
<p>For the truly hardcore, we also have a <a href="http://www.tracelytics.com/docs/oboeware/1.1/oboe.html#low-level-api">low-level API</a>. In addition to all of the power and flexibility of the High-Level API, this level adds the concept of a Context &#8212; an object that encapsulates the request context needed to trace a request through your full stack, under whatever evented, microthread, or serializable paradigm you&#8217;re working.</p>
<h1>Build it out!</h1>
<p>We hope this release is the start of a long and varied journey to tracing everything under the sun. Are you building something with it? Let us know! Are you thinking about it? <a title="Tracelytics 14-Day Free Trail" href="http://www.tracelytics.com/signup">Sign up</a> for a Tracelytics account, and get started today!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tracelytics.com/blog/tracing-python-an-api/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Full Stack Application Monitoring Is Like A Walk In The Woods</title>
		<link>http://www.tracelytics.com/blog/full-stack-application-monitoring-is-like-a-walk-in-the-woods/</link>
		<comments>http://www.tracelytics.com/blog/full-stack-application-monitoring-is-like-a-walk-in-the-woods/#comments</comments>
		<pubDate>Thu, 06 Sep 2012 19:49:41 +0000</pubDate>
		<dc:creator>Eric Bauer</dc:creator>
				<category><![CDATA[APM]]></category>
		<category><![CDATA[Full Stack Application Tracing]]></category>

		<guid isPermaLink="false">http://www.tracelytics.com/blog/?p=1687</guid>
		<description><![CDATA[I hope everyone had a great long weekend. With Labor Day marking the unofficial end of summer, here at Tracelytics, we’re all excited about our product growth and joining the&#160;<a href="http://www.tracelytics.com/blog/full-stack-application-monitoring-is-like-a-walk-in-the-woods/">...read more</a>]]></description>
			<content:encoded><![CDATA[<p>I hope everyone had a great long weekend. With Labor Day marking the unofficial end of summer, here at <strong><a title="Tracelytics" href="http://www.tracelytics.com/">Tracelytics</a></strong>, we’re all excited about our product growth and joining the <strong><a title="AppNeta" href="http://www.appneta.com" target="_blank">AppNeta</a></strong> team.</p>
<p>Over the Labor Day Weekend, I spent my free time hiking <a title="Presidential Traverse" href="http://en.wikipedia.org/wiki/Presidential_Traverse" target="_blank">New Hampshire’s Presidential Traverse</a>. The Presi Traverse is over 20 miles long, covers 7 mountains over 4000 ft, has a total elevation gain of 7800 ft and a total elevation loss of 7400 ft. The entire hike took my group 14.5 hours.  Not to outdo ourselves, due to weather conditions and the full moon, we started the hike at 5 PM, hiked through the night and finished at 7:30 AM!</p>
<p>Along the way, I had some time to think. My thoughts wandered to how this hike compared to <a title="Tracelytics" href="http://www.tracelytics.com/signup">full-stack application monitoring</a> (I know, it’s the weekend and I’m thinking about APM solutions). Here’s how:</p>
<blockquote><p>Each mountain I climbed is similar to the different layers that make up a web application. There is a path between each mountain that I followed from start to finish which is similar to the path a web request takes within the web application. And, if any problems arose, I was carrying a headlamp that I could turn on at any moment (thanks to the full moon, this was not needed for most of the hike). This is similar to an installed <a title="Tracelytics" href="http://www.tracelytics.com/">APM</a> solution. Both are designed to consume less that 1% of overhead, are there when you need them, and are out of the way when you don’t.</p></blockquote>
<div id="attachment_1714" class="wp-caption alignnone" style="width: 604px"><a href="http://www.tracelytics.com/blog/?attachment_id=1714#main"><img class=" wp-image-1714   " title="Web App Performance Overview" src="http://www.tracelytics.com/blog/wp-content/uploads/Initial_Overview_Mountains.png" alt="Web App Performance Overview" width="594" height="253" /></a><p class="wp-caption-text">A Tracelytics View of the Presidential Range</p></div>
<p>If I examine the entire hike from start to finish, I can produce averages of elevation gain, hiking pace, and total time to complete the hike. The details are explained in the second paragraph above. These averages are similar to partial-stack application tracing. I see the data, but have no way of pointing out problem areas, getting detailed data or reporting on paths between layers.</p>
<p>When I break my trip down into the below stats, I return data that is more consistent with full-stack application monitoring. For each mountain (layer) and trail (path), I have data on time to complete each leg (web request), the name of the mountain (language or operating system), and distance/gain/loss/total time (length of request).</p>
<p>Now, if you finished reading this post, and you’re not as exhausted as I was at the end of my hike, <a title="Tracelytics 14-Day Free Trail" href="http://www.tracelytics.com/signup">sign-up</a> for a FREE 14-day trial of Tracelytics. Our SaaS solution installs in minutes and performance data is revealed in seconds!</p>
<p>So here are my “full-stack” details (all photos from <a title="Eric Bauer | LinkedIn" href="http://www.linkedin.com/in/ericnbauer" target="_blank">Eric Bauer</a>):</p>
<div id="attachment_1691" class="wp-caption alignright" style="width: 310px"><a href="http://www.tracelytics.com/blog/?attachment_id=1691#main"><img class="size-medium wp-image-1691" title="Junction Sign" src="http://www.tracelytics.com/blog/wp-content/uploads/Pic-1-sign-300x225.jpg" alt="Presi Traverse Junction" width="300" height="225" /></a><p class="wp-caption-text">2.4 miles in - 15.2 miles to go</p></div>
<ul>
<li>Appalachia to Mt. Madison
<ul>
<li>Start: 5 PM</li>
<li>Finish: 7:15 PM</li>
<li>Distance: 4.25 miles</li>
<li>Elevation start: 1303 ft</li>
<li>Elevation end: 5367 ft</li>
<li>Total gain: 4000 ft</li>
</ul>
</li>
<li>Mt. Madison to Mt. Adams
<ul>
<li>Start: 7:30 PM</li>
<li>Finish: 8:30 PM</li>
<li>Distance: 1.3 miles</li>
<li>Elevation start: 5367 ft</li>
<li>Elevation end: 5799 ft</li>
<li>Total gain: 700 ft</li>
<li>Total loss: 260 ft</li>
</ul>
</li>
</ul>
<div id="attachment_1692" class="wp-caption alignright" style="width: 310px"><a href="http://www.tracelytics.com/blog/?attachment_id=1692#main"><img class="size-medium wp-image-1692" title="Mt. Madison Sunset" src="http://www.tracelytics.com/blog/wp-content/uploads/Pic-2-Sunset-300x225.jpg" alt="Mt. Madison Sunset" width="300" height="225" /></a><p class="wp-caption-text">Sun goes down - headlamps turn on</p></div>
<ul>
<li>Mt. Adams to Mt. Jefferson
<ul>
<li>Start: 9 PM</li>
<li>Finish: 10:30 PM</li>
<li>Distance: 2.4 miles</li>
<li>Elevation start: 5799</li>
<li>Elevation end: 5716</li>
<li>Total gain: 800</li>
<li>Total loss: 860</li>
</ul>
</li>
<li>Mt. Jefferson to Mt. Washington
<ul>
<li>Start: 11 PM</li>
<li>Finish: 12:30 AM</li>
<li>Distance: 3.2 miles</li>
<li>Elevation start: 5716 ft</li>
<li>Elevation end: 6288 ft</li>
<li>Total gain: 1300 ft</li>
<li>Total loss: 750 ft</li>
</ul>
</li>
</ul>
<div id="attachment_1693" class="wp-caption alignright" style="width: 310px"><a href="http://www.tracelytics.com/blog/?attachment_id=1693#main"><img class="size-medium wp-image-1693" title="Mt. Washington Summit" src="http://www.tracelytics.com/blog/wp-content/uploads/Pic-3-Wash-Sum-300x225.jpg" alt="Mt. Washington Summit" width="300" height="225" /></a><p class="wp-caption-text">6288 ft above sea level - 12:30 AM</p></div>
<ul>
<li>Mt. Washington to Mt. Monroe
<ul>
<li>Start: 1:30 AM</li>
<li>Finish: 2:45 AM</li>
<li>Distance: 1.8 miles</li>
<li>Elevation start: 6288 ft</li>
<li>Elevation end: 5372 ft</li>
<li>Total gain: 360 ft</li>
<li>Total loss: 1270 ft</li>
</ul>
</li>
<li>Mt. Monroe to Mt. Eisenhower
<ul>
<li>Start: 3:15 AM</li>
<li>Finish: 4:15 AM</li>
<li>Distance: 2.8 miles</li>
<li>Elevation start: 5372 ft</li>
<li>Elevation loss: 4780 ft</li>
<li>Total gain: 300 ft</li>
<li>Total loss: 900 ft</li>
</ul>
</li>
</ul>
<div id="attachment_1694" class="wp-caption alignright" style="width: 235px"><a href="http://www.tracelytics.com/blog/?attachment_id=1694#main"><img class="size-medium wp-image-1694" title="Crawford Notch" src="http://www.tracelytics.com/blog/wp-content/uploads/Pic-4-Crawford-225x300.jpg" alt="Crawford Notch" width="225" height="300" /></a><p class="wp-caption-text">Finally, the end 7:30 AM</p></div>
<ul>
<li>Mt. Eisenhower to Mt. Pierce
<ul>
<li>Start: 4:30 AM</li>
<li>Finish: 5:15 AM</li>
<li>Distance: 1.7 miles</li>
<li>Elevation start: 4780 ft</li>
<li>Elevation end: 4310 ft</li>
<li>Total gain: 300 ft</li>
<li>Total loss: 780 ft</li>
</ul>
</li>
<li>Mt. Pierce to Highland Visitor Center
<ul>
<li>Start: 5:45 AM</li>
<li>Finish: 7:30 AM</li>
<li>Distance: 3.1 miles</li>
<li>Elevation start: 4310 ft</li>
<li>Elevation end: 1909 ft</li>
<li>Total loss: 2400 ft</li>
</ul>
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.tracelytics.com/blog/full-stack-application-monitoring-is-like-a-walk-in-the-woods/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>New Gig and Great News</title>
		<link>http://www.tracelytics.com/blog/new-gig-and-great-news/</link>
		<comments>http://www.tracelytics.com/blog/new-gig-and-great-news/#comments</comments>
		<pubDate>Thu, 23 Aug 2012 14:08:53 +0000</pubDate>
		<dc:creator>Eric Bauer</dc:creator>
				<category><![CDATA[APM]]></category>
		<category><![CDATA[Drupal]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.tracelytics.com/blog/?p=1673</guid>
		<description><![CDATA[I recently joined the AppNeta team and I am very excited about the prospects of our Application Performance Management software solution, Tracelytics.  AppNeta’s SaaS-based Tracelytics service provides the broadest, most&#160;<a href="http://www.tracelytics.com/blog/new-gig-and-great-news/">...read more</a>]]></description>
			<content:encoded><![CDATA[<p>I recently joined the AppNeta team and I am very excited about the prospects of our Application Performance Management software solution, Tracelytics.  AppNeta’s SaaS-based Tracelytics service provides the broadest, most in-depth performance insight into your dynamic web-based applications available today.  We support PHP, Python, Ruby and Java.  Installation only takes a few minutes and you will receive real-time application performance data shortly after the installation completes.</p>
<p>And now for the exciting news… On <a title="Drupal Webinar" href="https://www1.gotomeeting.com/register/634454865" target="_blank">September 6, 2012 at 12PM EDT</a>, AppNeta is hosting a kick-off webinar to talk about key challenges with Web application performance and hear from one of our very own customers about the success they have had with Tracelytics! The webinar will cover the following topics:</p>
<ul>
<li>Common Drupal performance pitfalls and solutions</li>
<li>Key performance indicators to keep an eye (and alert) on</li>
<li>How to use Tracelytics to get quick answers to performance problems</li>
</ul>
<p>If you’re a Drupal user, this webinar is a great opportunity for you to tune in to learn how you can use Tracelytics to manage your Drupal app’s performance. If you’re not a Drupal user, we still want to hear from you and would be happy to do a 1:1 live demo – AND <a title="Tracelytics 14-Day Free Trail" href="http://www.tracelytics.com/signup">FREE TRIAL</a> &#8211; of the service!</p>
<p>I look forward to having you join us.  Sign up <a title="Drupal Webinar" href="https://www1.gotomeeting.com/register/634454865" target="_blank">here</a> for the webinar on September 6, 2012 at 12PM EDT.</p>
<p>Interested in getting started with Tracelytics today, sign up <a title="Tracelytics 14-Day Free Trail" href="http://www.tracelytics.com/signup">here</a> for the free 14-day trial.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tracelytics.com/blog/new-gig-and-great-news/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Explaining Service-Oriented Architectures (SOA) with Apache Thrift</title>
		<link>http://www.tracelytics.com/blog/what-is-soa-apache-thrift/</link>
		<comments>http://www.tracelytics.com/blog/what-is-soa-apache-thrift/#comments</comments>
		<pubDate>Wed, 18 Jul 2012 14:05:25 +0000</pubDate>
		<dc:creator>Dave Costantino</dc:creator>
				<category><![CDATA[APM]]></category>
		<category><![CDATA[open source]]></category>

		<guid isPermaLink="false">http://www.tracelytics.com/blog/?p=1632</guid>
		<description><![CDATA[Service Oriented Architecture (SOA) Defined Service Oriented Architecture (SOA) seems like a vague, fuzzy term. At its core, SOA means separating software into isolated, reusable components (&#8220;services&#8221;) that are accessed&#160;<a href="http://www.tracelytics.com/blog/what-is-soa-apache-thrift/">...read more</a>]]></description>
			<content:encoded><![CDATA[<h2>Service Oriented Architecture (SOA) Defined</h2>
<p>Service Oriented Architecture (SOA) seems like a vague, fuzzy term. At its core, SOA means separating software into isolated, reusable components (&#8220;services&#8221;) that are accessed through well-defined interfaces. It emphasizes loose coupling, so that instead of directly calling into another component (like when using a shared library, static linking, etc.), components communicate using a network protocol.  In practical terms, this means that changes can be made to a service without affecting its clients (&#8220;consumers&#8221;), as long as the protocol remains compatible.</p>
<p>It is an &#8220;architectural style&#8221;, not an implementation. There are many ways to implement SOA, including REST and SOAP web services, language-specific implementations such as Java RMI, and older approaches using RPC frameworks such as CORBA (which dates back to the 90&#8242;s!).  Some folks also decide to build their own service / RPC layer on top of messaging frameworks such as <a href="http://code.google.com/p/protobuf/">Protocol Buffers</a> or <a href="https://github.com/msgpack/msgpack-rpc">MsgPack.</a> Others may even go as far as implementing their own custom network protocols at the wire level. There is also <a href="http://thrift.apache.org/">Thrift</a>, which we use here at Tracelytics.</p>
<h2>SOA with Modern Web Applications</h2>
<p>Many web applications start off as a monolithic code base, then move to a more distributed system using SOA. One example I&#8217;ve seen at another company: an application that generates reports from search engine marketing data. The original web application was written in PHP, with all processing, database queries, etc. occurring synchronously in the context of the HTTP request. Large reports could take several minutes (and, sometimes, hours!) to complete, and users would become impatient waiting for their browser to finally display the result.  To improve the user experience, it was decided that reports would be run asynchronously, in the background, which allowed users to check on their status, receive emails when they were finished processing, archive the report for later, etc.</p>
<p>This was done by moving the report processing logic into a separate component: a SOAP web service implemented using JBoss, a Java application server. The front end web application remained in PHP. The PHP web app would send a HTTP SOAP request to the report service, requesting that a report be initiated. If there was too much load on the system (for example, more than N reports running in parallel), the report request would be queued for later processing.  The user could continue working with the application and would receive notice when their report was complete.  The system also performed better, since the new service code was more efficient than the previous PHP implementation, and the number of actively processing reports could be controlled, based on system capacity.</p>
<p>Also, it was a more effective use of development resources since two completely separate teams could develop the code: a front-end / PHP team, and a back-end / Java services team. These teams only needed to agree on the interface (in this case, the <a href="http://en.wikipedia.org/wiki/Web_Services_Description_Language">WSDL</a>), which defined the method names, parameters, return values and any associated data structures.</p>
<h2>How We Use SOA Inside Tracelytics</h2>
<p>Tracelytics is also built on an SOA architecture. One example is our data-sharding service (internally known as &#8220;shardy&#8221;).  When the web application needs to retrieve certain types of data, for example the heat map / latency data for a particular customer app for a particular time range (last day, last 7 days, etc), it makes a request to the data-sharding service.  The service locates the data, which, depending on the time range, could be spread across dozens of tables and database servers (&#8220;shards&#8221;). It then queries it, running several SQL queries in parallel,  performing the necessary aggregation (such as filtering and sorting of the merged data set), returning a single result set to the application.</p>
<p>This service was developed using  <a href="http://thrift.apache.org/">Thrift</a>, a framework for building services.  Though originally started as a <a href="http://blog.facebook.com/blog.php?post=2261927130">Facebook</a> project, Thrift has since found a home at Apache. It is cross-language, meaning a service can be written in one language and called into by another. It supports C++, PHP, Python, Perl, Java, and many other languages. Currently, our service and client (web app) are both written in Python, but this compatibility means that there is no reason this couldn&#8217;t change in the future.</p>
<h2>Developing a Service using Apache Thrift</h2>
<p>Before developing any type of service (whether with Thrift or not!), one should design the service interface. This involves specifying the service calls, which includes the service name, method names, parameters, data types, and return values in a generic, language independent way. With Thrift, this is done by writing an IDL (interface definition language) file. There are <a href="http://mikecvet.wordpress.com/2010/04/01/facebook-thrift-tutorial/">many</a> <a href="http://diwakergupta.github.com/thrift-missing-guide/">tutorials</a> on how to do this, so we won&#8217;t repeat the same information here.</p>
<p>The IDL file is then used as input to a code generator (&#8220;thrift -gen &#8230;&#8221;), which generates both client and server stubs for you.  Thrift takes care of a lot of the tedious work: you don&#8217;t have to worry about writing error prone network communications code.  Of course, the server stub will then need to be modified to actually implement your service (the &#8220;business logic&#8221; that actually does the work of your application ).</p>
<h2>Tracing Performance Of Thrift Services</h2>
<p>If you&#8217;re using a Thrift service, you must monitor the performance of that service to see how it&#8217;s affecting the rest of your application. Tracelytics allows you to do this by <a href="http://support.tracelytics.com/kb/instrumenting-your-app/extending-tracelytics-customizing">customizing</a> your client code.   Internally, we&#8217;ve actually modified the Thrift code generator to make this automatic. Please let us know if you&#8217;re interested in this functionality!</p>
<p>(Photo Credit: <a href="http://www.flickr.com/photos/southbeachcars/">southbeachcars</a>)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tracelytics.com/blog/what-is-soa-apache-thrift/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Tracing Celery Performance For Web Applications</title>
		<link>http://www.tracelytics.com/blog/tracing-celery-performance/</link>
		<comments>http://www.tracelytics.com/blog/tracing-celery-performance/#comments</comments>
		<pubDate>Mon, 16 Jul 2012 17:10:37 +0000</pubDate>
		<dc:creator>Dan Kuebrich</dc:creator>
				<category><![CDATA[APM]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.tracelytics.com/blog/?p=1600</guid>
		<description><![CDATA[Are you using Celery to process python backend tasks asynchronously?  Have you wanted to get insight into their resource consumption and efficiency?  Here&#8217;s a few useful ways to get insight&#160;<a href="http://www.tracelytics.com/blog/tracing-celery-performance/">...read more</a>]]></description>
			<content:encoded><![CDATA[<p>Are you using <a title="Celery distributed task queue" href="http://celeryproject.org/" target="_blank">Celery</a> to process python backend tasks asynchronously?  Have you wanted to get insight into their resource consumption and efficiency?  Here&#8217;s a few useful ways to get insight into Celery&#8217;s performance when running tasks.</p>
<h2>A simple celery task</h2>
<p>For a quick review, Celery lets you turn any python method into an asynchronous task.  Here&#8217;s a simple one:</p>
<pre class="brush: python; title: ; notranslate">
from celery.task import task
@task
def add(x, y):
    return x + y
</pre>
<div>
<h2>Let&#8217;s trace Celery!</h2>
<p>We&#8217;ll start with the good stuff. In the latest release of our Python instrumentation, oboeware-1.0, we have an updated API that makes it super-easy to gather performance data from any Python code, including Celery tasks. Here&#8217;s how we&#8217;d add tracing to our example task:</p>
<pre class="brush: python; title: ; notranslate">
from celery.task import task
import oboe
from oboeware import loader

# load monkey-patched instrumentation for supported modules
loader.load_inst_modules()

# trace every unit of work done by decorated method
# (use fractional sample rate to trace a fraction of calls to decorated method)
oboe.config['tracing_mode'] = 'always'
oboe.config['sample_rate'] = 1.0

@task
@oboe.trace('celery', kvs={'Controller': 'task', 'Action': 'add'})
def add(x, y):
return x + y
</pre>
</div>
<p>The key part is the @oboe.trace decorator.  Note that we&#8217;re assigning to the keys Controller and Action.  This will be used by Tracelytics to segment the data.  You can also optionally use the keys HTTP-Host and URL to indicate domain and URL to Tracelytics.  Here&#8217;s what the data we&#8217;re gathering looks like in the dashboard (I added a few sqlalchemy queries to spice up the data):</p>
<p style="text-align: center;"><a href="http://www.tracelytics.com/blog/wp-content/uploads/Ow5Hd.png"><img class="aligncenter  wp-image-1608" title="celery in tracelytics" src="http://www.tracelytics.com/blog/wp-content/uploads/Ow5Hd-300x229.png" alt="celery in tracelytics" width="400" height="305" /></a></p>
<p>The code at the top is configuration tunables: set the sample rate to a fractional value to trace only a fraction of your Celery tasks.</p>
<h2>Event-based workers</h2>
<p>You might be using event-based workers to save a few bytes of ram.  Tracelytics also supports eventlet-based workers.  However, you&#8217;ll need to install our Tracelytics-enabled greenlet module using pip or easy install:</p>
<pre class="brush: plain; title: ; notranslate">
$ pip install --extra-index-url=http://pypi.tracelytics.com greenlet-0.3.4-tly1.0
</pre>
<h2>Slightly more interesting</h2>
<p>Of course, you&#8217;re probably interested in more complex celery tasks than that.  The good news is, all of our normal instrumentation works with your celery workers.  Here&#8217;s a screenshot of one of our internal Celery workers in action:</p>
<p><a href="http://www.tracelytics.com/blog/wp-content/uploads/urQVR.png"><br />
<img class="aligncenter" title="tracing complex celery tasks" src="http://www.tracelytics.com/blog/wp-content/uploads/urQVR-650x173.png" alt="tracing complex celery tasks" width="650" height="173" /></a></p>
<div>
<h2>Other resources</h2>
<p>Looking for different tools?  Good news&#8211;there&#8217;s a pretty healthy Celery ecosystem.  Here&#8217;s a few useful packages and I&#8217;m sure there&#8217;s tons I&#8217;m forgetting&#8211;leave comments for anything else you find helpful with Celery!</p>
<p><img class="alignright size-medium wp-image-1615" title="celerymon" src="http://www.tracelytics.com/blog/wp-content/uploads/djangoceleryadmin2-300x178.jpg" alt="celerymon" width="300" height="178" /></p>
<ul>
<li>If you want to keep track of worker status, you might be interested in <a title="celerymon on pypi" href="http://pypi.python.org/pypi/celerymon/" target="_blank">celerymon</a>, a monitor for celery tasks.  It keeps tabs of task execution and workers.</li>
<li>Trying to track down a memory leak?  Consider running <a title="dowser memory profiling for python" href="http://www.aminus.org/blogs/index.php/2008/06/11/tracking-memory-leaks-with-dowser" target="_blank">dowser</a> inside your celery worker.</li>
</ul>
<p>Photo Credit: <a href="http://www.flickr.com/photos/dottiemae/">dottiemae</a></p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.tracelytics.com/blog/tracing-celery-performance/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>10 Critical Examples Of Why Application Speed Matters</title>
		<link>http://www.tracelytics.com/blog/why-application-speed-matters/</link>
		<comments>http://www.tracelytics.com/blog/why-application-speed-matters/#comments</comments>
		<pubDate>Tue, 10 Jul 2012 14:15:13 +0000</pubDate>
		<dc:creator>Samier</dc:creator>
				<category><![CDATA[APM]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://www.tracelytics.com/blog/?p=1527</guid>
		<description><![CDATA[Behind the jargon and layers of technical bog, the application performance management industry is about one thing: speed. It’s a multi-billion dollar industry devoted to ensuring that the speed we’ve&#160;<a href="http://www.tracelytics.com/blog/why-application-speed-matters/">...read more</a>]]></description>
			<content:encoded><![CDATA[<p>Behind the jargon and layers of technical bog, the application performance management industry is about one thing: speed. It’s a multi-billion dollar industry devoted to ensuring that the speed we’ve come to expect of websites and apps is maintained. You probably think your site doesn’t have a speed problem because it loads in “just a few seconds”, but you could sell a lot more widgets, or get a lot more people using your echo-location based gourmet coffee finding app, if your site was even faster.</p>
<p>In fact, if your app isn&#8217;t fast, it is absolutely costing you business &#8211; See the Amazon example where a delay of just a few miliseconds cost them 1% of their revenues. The truth of the matter is that with website speed, it’s not that you get brownie points for being faster &#8211; you get penalized for not being lightning fast. Here are 10 great reasons why you need to be obsessed with making your website faster:</p>
<p>1. Your consumers expect sites to load in under 2 seconds. When asked by Forrester Consulting how quickly they expected a web page to load, 47% of respondents answered <a href="http://www.damcogroup.com/white-papers/ecommerce_website_perf_wp.pdf">2 seconds or less</a>. The concept of “loading” doesn’t exist anymore. People now expect browsing the internet to be like reading a book; they expect the next page to already be there. And they get annoyed if it’s not, because waiting for your page to load makes their brain hurt. <a href="http://www.webperformancetoday.com/2012/03/21/neuroscience-page-speed-web-performance/">No, really.</a></p>
<p>2. If your site takes more than 2 seconds to load, they’ll leave. Nobody is going to sit at their computer twiddling their thumbs and ruminating on how far human civilization has come since the first letter was carved into a slab of stone as the sun set on the Euphrates River. What they will do is <a href="http://www.damcogroup.com/white-papers/ecommerce_website_perf_wp.pdf">forget about you</a>; 14% will go to a competitor’s site, and 39% will start doing something else on their computer that distracts them, like looking at videos of teenagers severely injuring themselves doing skateboard tricks so they can feel better about spending their day behind a computer screen in an over-air conditioned room.</p>
<p>3. The difference between a user preferring a competitor’s site or preferring yours is<a href="http://www.nytimes.com/2012/03/01/technology/impatient-web-users-flee-slow-loading-sites.html?pagewanted=all"> 250 milliseconds</a>. If a competitor’s site is just that much faster than yours, people will subconsciously notice it and your company will lose clout and users. You know what else happens in 250ms? Nothing.</p>
<p>4. Seriously, people won’t like you anymore. Remember that time you had a little too much at the Christmas party and made an ass of yourself? <a href="http://www.damcogroup.com/white-papers/ecommerce_website_perf_wp.pdf">That’s nothing compared to this</a>. 46% of dissatisfied online shoppers are likely to develop a negative perception of the company, and 44% of them would tell their friends and family about it. Which is unfortunate, because people tend to perceive page load times as 15% slower than they actually are, and 35% <a href="http://www.strangeloopnetworks.com/resources/infographics/web-performance-and-user-expectations/internet-users-have-faulty-perceptions-of-time/">slower when they talk to other people</a>.</p>
<p>5. Your search ranking will also suffer. Google takes website speed into consideration in their ranking algorithm.</p>
<p>6. Users continue to expect higher quality graphics, which means larger webpage sizes, even as they continually want quicker load times. Just an observation, one which has broad implications for your business; your site is going to have to keep getting stronger, because the amount it’s going to have to lift is only going up.</p>
<p>7. If you do have a website that’s up to par, <a href="http://www.watchingwebsites.com/archives/proof-that-speeding-up-websites-improves-online-business/">users will spend more time on your site</a>, lowering your bounce rate, and increasing your conversion rate and revenue.</p>
<p>8. If you’re not yet convinced that we all become spoiled children as soon as you sit us in front of a web browser, consider these anecdotes from big corporations. Amazon found that a 100ms increase in load time meant a 1% drop in sales—that’s a lot of money for so seemingly imperceptible an amount of time. <a href="http://www.fastcompany.com/1825005/impatient-america-needs-faster-intertubes">That means 1 extra second of load time would cost them $1.6 billion. </a></p>
<p>9. In 2007, Shopzilla<a href="http://velocityconf.com/velocity2009/public/schedule/detail/7709"> decided their site was too slow</a> and that they would re-engineer it. They managed to decrease load time by several seconds. As a result, they get 25% more page views, revenue increased by 10%, and cut the number of servers they needed from 402 to 200.</p>
<p>10. The sin of sloth means a lot for search engines as well:</p>
<ul>
<li><a href="http://www.strangeloopnetwork.com/resources/infographics/web-performance-and-ecommerce/yahoo-400ms-faster-9-more-traffic/">Yahoo</a> found a 400ms delay in load time decreased traffic by 9%.</li>
<li>For <a href="http://radar.oreilly.com/2009/07/velocity-making-your-site-fast.html">Bing</a>, a 2 second slowdown in results led to 1.8% less searches and decreased revenue per user by 4.3%.</li>
<li><a href="http://googleresearch.blogspot.com/2009/06/speed-matters.html">Google</a> discovered that slowing down search results by just 100-400 milliseconds can induce users to perform .2%-.6% less searches. Even when the delay was removed, it took weeks before users returned to their previous search volume.  Yes, your users are that fickle.</li>
</ul>
<p>That sounds like a lot of pain and misery if your site is slow.  If only there was some way to identify the sources of latency in your site or app by tracing requests through your entire architecture from the front end to the server. Then you could eliminate them, your customers would love you, your competitors would crumble at your feet begging for mercy, you would be less stressed, lose 10lbs, and finally be able to take a vacation.<br />
If you&#8217;re looking for a secret weapon to help understand your web application&#8217;s latency and speed it up, <a href="http://www.tracelytics.com/signup">try out Tracelytics free for 14 days</a>. Don&#8217;t wind up like Don Draper.<br />
<img src="http://cdn.memegenerator.net/instances/400x/22852504.jpg" alt="Crying Draper - My website is too slow i should have used tracelytics" width="280" height="280" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.tracelytics.com/blog/why-application-speed-matters/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Looking Back On pageguide.js After One Month</title>
		<link>http://www.tracelytics.com/blog/looking-back-on-pageguide-js/</link>
		<comments>http://www.tracelytics.com/blog/looking-back-on-pageguide-js/#comments</comments>
		<pubDate>Mon, 02 Jul 2012 14:30:21 +0000</pubDate>
		<dc:creator>Brian Whalley</dc:creator>
				<category><![CDATA[APM]]></category>
		<category><![CDATA[open source]]></category>

		<guid isPermaLink="false">http://www.tracelytics.com/blog/?p=1504</guid>
		<description><![CDATA[About one month ago, we open-sourced our pageguide.js library for people to use on their own websites and projects. Let&#8217;s look at the growth and adoption of pageguide.js since we&#160;<a href="http://www.tracelytics.com/blog/looking-back-on-pageguide-js/">...read more</a>]]></description>
			<content:encoded><![CDATA[<p>About one month ago, we open-sourced our <a href="http://tracelytics.github.com/pageguide">pageguide.js</a> library for people to use on their own websites and projects. Let&#8217;s look at the growth and adoption of pageguide.js since we started to roll it out:</p>
<p>- More than 260 repository watchers</p>
<p>- 24 active forks of pageguide.js ongoing</p>
<p>- Many user submitted patches &amp; new features (and more coming in the works!)</p>
<p>- Now included in <a href="https://nuget.org/packages/jQuery.Pageguide/0.9.0">nuget</a> and other packaging libraries to make deployment even faster.</p>
<p>- Great coverage in <a href="https://plus.google.com/116812091267698107544/posts/DBi18g5RQ56">SmashingMag</a>, Dzone, and countless other web design or web utility blogs, that drove even more great attention and awareness of our library.</p>
<p>Thanks to all of you since checking out pageguide.js and spreading the word &#8211; We really appreciate it, and we look forward to seeing it on more websites around the web soon. If you&#8217;ve implemented pageguide.js on your own site somewhere, please send us a link &#8211; We&#8217;d love to see how you are using it. Drop us a line at <a href="mailto:bwhalley@tracelytics.com">bwhalley@tracelytics.com</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tracelytics.com/blog/looking-back-on-pageguide-js/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tracelytics Acquired By AppNeta: We’re One Step Closer to Tracing Everything</title>
		<link>http://www.tracelytics.com/blog/tracelytics-acquired-by-appneta/</link>
		<comments>http://www.tracelytics.com/blog/tracelytics-acquired-by-appneta/#comments</comments>
		<pubDate>Thu, 21 Jun 2012 10:59:45 +0000</pubDate>
		<dc:creator>Spiros Eliopoulos</dc:creator>
				<category><![CDATA[APM]]></category>
		<category><![CDATA[Company news]]></category>

		<guid isPermaLink="false">http://www.tracelytics.com/blog/?p=1481</guid>
		<description><![CDATA[We are excited to announce that Tracelytics has been acquired by AppNeta, an innovative network and end-user performance company.  With our powers combined, we provide complete, end-to-end performance management to&#160;<a href="http://www.tracelytics.com/blog/tracelytics-acquired-by-appneta/">...read more</a>]]></description>
			<content:encoded><![CDATA[<p>We are excited to announce that Tracelytics has been acquired by <a href="http://www.appneta.com">AppNeta</a>, an innovative network and end-user performance company.  With our powers combined, we provide complete, end-to-end performance management to our customer: from the browser, through the network, to the application, and down into application code.</p>
<p>AppNeta has built great technology and a fantastic product around network performance management and end-user monitoring. We’ve been focusing on providing insight into what’s going on in complex, distributed applications. And now, we’ll be the first company to provide truly complete, end-to-end visibility all in one place.</p>
<p>In March, we closed our Series A. With a great set of investment partners, our loyal customers, and everything that we’ve learned since we started back in June of 2010, we set off on the next stage of the Tracelytics journey. Our best efforts were not enough to predict where we would be just four months later.  It’s one of those occasions where aiming for the stars lands you in a distant galaxy.</p>
<p>We’re very excited about the future.  Today we’ve taken a big step towards our goal of tracing everything.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tracelytics.com/blog/tracelytics-acquired-by-appneta/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Advanced SQLAlchemy &amp; Performance Concerns</title>
		<link>http://www.tracelytics.com/blog/advanced-sqlalchemy-performance-concerns/</link>
		<comments>http://www.tracelytics.com/blog/advanced-sqlalchemy-performance-concerns/#comments</comments>
		<pubDate>Mon, 18 Jun 2012 13:50:08 +0000</pubDate>
		<dc:creator>TR Jordan</dc:creator>
				<category><![CDATA[APM]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.tracelytics.com/blog/?p=1465</guid>
		<description><![CDATA[Here at Tracelytics, performance is obviously one of our top priorities. However, writing performant code is nearly impossible if that code isn&#8217;t clear and well-organized. One of our favorite tools&#160;<a href="http://www.tracelytics.com/blog/advanced-sqlalchemy-performance-concerns/">...read more</a>]]></description>
			<content:encoded><![CDATA[<p>Here at Tracelytics, performance is obviously one of our top priorities. However, writing performant code is nearly impossible if that code isn&#8217;t clear and well-organized. One of our favorite tools for doing this is the <a href="http://www.sqlalchemy.org/">Python ORM SQLAlchemy</a>. It provides a nice Pythonic abstraction for writing queries, and also a powerful interface for controlling exactly what SQL is generated when performance matters. Let&#8217;s take a look at a few of the features we love.</p>
<h3>Loading Strategies</h3>
<p>One of the most common pitfalls of using an ORM is accidentally creating a <a href="http://www.tracelytics.com/blog/two-most-common-performance-mistakes/">Query in a Loop</a>. In SQLAlchemy, writing something like this:</p>
<pre class="brush: python; title: ; notranslate">
# Assuming a User class, with a group relationship to a different table...

&gt;&gt;&gt; users = Session.query(User).all()
&gt;&gt;&gt; for r in users:
...     print user.group
</pre>
<p>This runs an initial query to get the list of users, then an individual query for each user to get the group! In many ORMs, you&#8217;d have to change the structure here: batch load the users, batch load the groups, then iterate over the loaded results. SQLAlchemy provides a better way, called <a href="http://docs.sqlalchemy.org/en/rel_0_7/orm/loading.html">Loading Strategies</a>. Instead of changing the logic, you just specify which relationships to load, and SQLAlchemy will get everything you need in one query. In our example, we&#8217;d like to load all groups at the same time as the users.</p>
<pre class="brush: python; title: ; notranslate">
&gt;&gt;&gt; users = Session.query(User).options(joinedload('group')).all()
&gt;&gt;&gt; for r in users:
...     print user.group
</pre>
<p>Fewer roundtrips, much faster, and hardly any code change.</p>
<h3>Reconstructing Objects</h3>
<p>One common pattern in OO designs is to lazily compute properties, cache them, and return the cached version after that. Not only does this have performance benefits, but it also keeps the computation logic for given properties separate and coherent. A simple method might look like this:</p>
<pre class="brush: python; title: ; notranslate">
class Foo(object):

    def __init__(self):
        self._bar = None

    def bar(self):
        if self._bar is None:
            self._bar = ... # Compute bar
        return self._bar
</pre>
<p>This pattern unfortunately doesn&#8217;t work with SQLAlchemy. Specifically, objects loaded from the DB don&#8217;t re-run the <code>__init__</code> constructor, so they won&#8217;t have the <code>_bar</code> property available, and the line <code>self._bar is None</code> will fail with <code>AttributeError: 'Foo' object has no attribute '_bar'</code> . To fix this, SQLAlchemy offers a hook that runs after loading: <a href="http://docs.sqlalchemy.org/en/rel_0_7/orm/mapper_config.html#sqlalchemy.orm.reconstructor"><code>sqlalchemy.orm.reconstructor</code></a>. In our case:</p>
<pre class="brush: python; title: ; notranslate">
from sqlalchemy.orm import reconstructor

class Foo(object):

    def __init__(self):
        # Initialize persistent properties here
        self.init()

    @reconstructor
    def init(self):
        # Initialize transient properties here
        self._bar = None

    def bar(self):
        if self._bar is None:
            self._bar = ... # Compute bar
        return self._bar
</pre>
<p>In general, we do all transient initialization in a <code>reconstructor</code> method and only touch persistent properties in the constructor. Without that, new objects may behave differently than loaded objects!</p>
<h3>Polymorphic Identities</h3>
<p>ORMs typically model a single row in the database as an object, with each column represented as a field, and SQLAlchemy is no different. For most data, this makes sense. A &#8220;users&#8221; table with columns &#8220;first_name&#8221;, &#8220;joined_on&#8221;, and &#8220;active&#8221; maps cleanly to an object with the same properties. However, not all columns represent simple data. Something like &#8220;role&#8221; identifies a behavior on an object. Naively, the model methods that use that column might look like this:</p>
<pre class="brush: python; title: ; notranslate">
Base = declarative_base()
class User(Base):
    __tablename__ = 'user'

    role = Column('role', String(20), nullable=False)
    # other column definitions here...

    def get_menu_dropdown_items(self):
        if self.role == 'owner':
            # return all choices
        elif self.role == 'admin':
            # return all choices, except delete organization
        elif self.role == 'base':
            # return just personal settings
        else:
            # return blank list
</pre>
<p>Instead of returning the column data itself, the object behaves differently based on the value of the column. A common OO pattern when faced with this kind of switch is to choose a different class for each (e.g.) role. By pushing this conditional &#8220;up a level&#8221;, to class instantiation time, we only have to make that choice once, instead of repeating this if/elif/else block across all the model methods that might need it. (If you want to read more about this pattern, check out the wiki article <a href="http://c2.com/cgi/wiki?ReplaceConditionalWithPolymorphism">Replace Conditional with Polymorphism</a>).</p>
<p>By default, SQLAlchemy picks the class type when it loads the rows. To change this, we can give the base class a <em>polymorphic type</em> &#8212; a row name that SQLAlchemy will use to figure out which class to instantiate, passed to the mapper. Each subclass can then declare a <em>polymorphic identity</em> &#8212; a row value to associate with the class. If you&#8217;re using the declarative base, you can set the <code>__mapper_args__</code> to the appropriate column and value. For instance, the above example could become:</p>
<pre class="brush: python; title: ; notranslate">
Base = declarative_base()
class User(Base):
    __tablename__ = 'user'
    __mapper_args__ = { 'polymorphic_on': 'role' }

    role = Column('role', String(20), nullable=False)

    def get_menu_dropdown_items(self):
        # default implementation: return blank list

class AdminUser(User):
    __mapper_args__ = { 'polymorphic_identity': 'admin' }

    def get_menu_dropdown_items(self):
        # return all choices, except delete organization

class OwnerUser(User):
    __mapper_args__ = { 'polymorphic_identity': 'owner' }

    def get_menu_dropdown_items(self):
        # return all choices

class BaseUser(User):
    __mapper_args__ = { 'polymorphic_identity': 'base' }

    def get_menu_dropdown_items(self):
        # return just personal settings
</pre>
<p>Now, querying the <code>User</code> class will actually return a number of different implementations, matched to the data!</p>
<p>This pattern is useful when you have a number of different types that you expect to have to change with some frequency. Obviously splitting up the <code>get_menu_dropdown_items</code> logic across multiple classes makes it somewhat harder to see all types of behavior. In return, implementing a new class (e.g., <code>guest</code>), is much easier, since all the methods are in one place, and can even be statically checked (for existence) by tools such as <a href="http://www.logilab.org/857">PyLint</a>.</p>
<h3>Lazy Loading Dependencies</h3>
<p>In an ideal world, all models have no dependencies. It would even be fine to have models with one-way dependencies, with no cycles. Unfortunately, this isn&#8217;t always the case. Consider two classes, with mutual references:</p>
<pre class="brush: python; title: ; notranslate">
from sqlalchemy import *
from sqlalchemy import orm
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()
class Account(Base):
    __table_name__ = 'account'

    id       = Column('id', Integer, primary_key=True)
    prefs_id = Column('organization_id', Integer, ForeignKey('preferences.id'))

    prefs = orm.relation(AccountPrefs, uselist=False) # One-to-one relationship

class AccountPrefs(Base):
    __table_name__ = 'preferences'

    id         = Column('id', Integer, primary_key=True)
    account_id = Column('organization_id', Integer, ForeignKey('account.id'))

    account = orm.relation(Account, uselist=False) # One-to-one relationship
</pre>
<p>However, when we try to create this, it fails with <code>NameError: name 'AccountPrefs' is not defined</code>. This is because we&#8217;re referencing the <code>AccountPrefs</code> class before its definition. We can fix this by changing the relationship lines to the following:</p>
<pre class="brush: python; title: ; notranslate">
    prefs = orm.relation(&quot;AccountPrefs&quot;, uselist=False) # One-to-one relationship
    # ...
    account = orm.relation(&quot;Account&quot;, uselist=False) # One-to-one relationship
</pre>
<p>Instead of the class instead itself, we can pass a string to <code>relation</code> and defer creating the relationship until the loader is first used &#8212; typically after the import has finished.</p>
<p>If these classes are sufficiently large, or have other support code, it may make sense to break them up into two modules (e.g., <code>account.py</code> and <code>account_prefs.py</code>). This introduces a new problem: if one of these modules is loaded without the other, SQLAlchemy will again throw a <code>NameError</code>. Deferring this loading forever won&#8217;t help &#8212; the class definitions simply aren&#8217;t available!</p>
<p>Fundamentally, we have to force both modules to load if either module is loaded. We could just put the appropriate import statement in both files, but importing modules without a clear use of any of the variables seems kludgy (remember that we&#8217;re hiding the relationship declaration in strings already &#8212; tools like pylint will issue warnings on these unused imports). Ideally, we&#8217;d have an explicit declaration, with a clear purpose. Fortunately, SQLAlchemy 0.7.7 introduces a new hook: <a href="http://docs.sqlalchemy.org/en/rel_0_7/orm/extensions/declarative.html#declare-last"><code>__declare_last__</code></a>. This allows us to execute a function after the relationships are loaded, but before they are used. This gives us a chance to nest the circular import:</p>
<pre class="brush: python; title: ; notranslate">
# account.py
Base = declarative_base()
class Account(Base):
    __table_name__ = 'account'

    id       = Column('id', Integer, primary_key=True)
    prefs_id = Column('organization_id', Integer, ForeignKey('preferences.id'))

    @classmethod
    def __declare_last__(cls):
        from account_prefs import AccountPrefs
        cls.prefs = orm.relation(AccountPrefs, uselist=False)

# account_prefs.py

from account import Base
class AccountPrefs(Base):
    __table_name__ = 'preferences'

    id         = Column('id', Integer, primary_key=True)
    account_id = Column('organization_id', Integer, ForeignKey('account.id'))

    account = orm.relation(&quot;Account&quot;, uselist=False) # One-to-one relationship
</pre>
<p>We like this because it lets us manage different chunks of logic, even when that code depends on data that is naturally tightly coupled.</p>
<h3>Even more&#8230;</h3>
<p>There&#8217;s obviously a lot more to SQLAlchemy. What are some of your favorite features? Let us know in the comments!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tracelytics.com/blog/advanced-sqlalchemy-performance-concerns/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Drupal Performance Profiling With Tracelytics</title>
		<link>http://www.tracelytics.com/blog/drupal-performance-profiling/</link>
		<comments>http://www.tracelytics.com/blog/drupal-performance-profiling/#comments</comments>
		<pubDate>Thu, 07 Jun 2012 17:08:09 +0000</pubDate>
		<dc:creator>Dave Costantino</dc:creator>
				<category><![CDATA[APM]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.tracelytics.com/blog/?p=1376</guid>
		<description><![CDATA[Getting a comprehensive view of the causes of poor performance and latency in your Drupal instance can be tricky. AllPlayers.com, a Tracelytics user, has developed a module to integrate Drupal with&#160;<a href="http://www.tracelytics.com/blog/drupal-performance-profiling/">...read more</a>]]></description>
			<content:encoded><![CDATA[<p>Getting a comprehensive view of the causes of poor performance and latency in your Drupal instance can be tricky. <a href="http://AllPlayers.com/">AllPlayers.com</a>, a Tracelytics user, has developed a <a href="http://drupal.org/project/tracelytics">module</a> to integrate Drupal with Tracelytics and make this process much more straightforward. This module is an excellent example of how one can integrate custom code with the Tracelytics API to provide greater insight into application performance. Let&#8217;s explore the functionality of this module, and the source to see how that was implemented to report on full stack application tracing data.</p>
<h2>Installation</h2>
<p>Installing the Drupal module is as straightforward as <a href="http://drupal.org/project/tracelytics">downloading</a> it and extracting the .tar.gz or zip. The files should then be installed in your Drupal installation, under sites/all/modules. You can also install the module through the Drupal Admin UI.  You should have also already installed the <a href="http://support.tracelytics.com/kb/installation-instructions/installation-overview">instrumentation</a>, including instrumentation for your web server and PHP.</p>
<h2>Features</h2>
<h3>Additional Layers</h3>
<p>The module provides information on various Drupal-specific layers, each corresponding to a specific Drupal <a href="http://api.drupal.org/api/drupal/includes!module.inc/group/hooks/7">hook</a>. Hooks are PHP functions called by the Drupal framework code at various times during request processing, and are used to generate Tracelytics layer entry and exit events. These events allow Tracelytics to determine how much time each request spent processing in an individual layer. The layers supported today are:</p>
<ul>
<li><a href="http://api.drupal.org/api/drupal/modules!system!system.api.php/function/hook_boot/7">drupal_hook_boot</a> : Tasks run at the beginning of each page request.</li>
<li><a href="http://api.drupal.org/api/drupal/modules!system!system.api.php/function/hook_init/7">drupal_hook_init</a> : Setup tasks for non-cached page requests.</li>
<li><a href="http://api.drupal.org/api/drupal/modules!system!system.api.php/function/hook_form_alter/7">drupal_hook_form_alter </a>: Modifications of a form before it is rendered.</li>
<li>drupal_views (corresponds to time spent between <a href="http://api.drupal.org/api/views/views.api.php/function/hook_views_pre_view/7">drupal_hook_views_pre_view</a> and <a href="http://api.drupal.org/api/views/views.api.php/function/hook_views_post_render/7">drupal_hook_views_post_render</a>)</li>
<li><a href="http://api.drupal.org/api/drupal/modules!node!node.api.php/function/hook_node_load/7">drupal_hook_node_load </a>: Act on nodes loaded from a database.</li>
<li><a href="http://api.drupal.org/api/drupal/modules!system!system.api.php/function/hook_watchdog/7">drupal_hook_watchdog </a>: Message / event logging.</li>
<li><a href="http://api.drupal.org/api/drupal/modules!system!system.api.php/function/hook_exit/7">drupal_hook_exit </a>:  Tasks run at the end of each page request.</li>
</ul>
<h3>Controller / Action</h3>
<p>A controller and action pair is reported for each request by examining currently active Drupal &#8220;menu item&#8221;, which provides information on the code handling each request. This is particularly important with Drupal since almost all non-static requests are handled by the root index.php file, meaning the URL itself is not useful for categorizing a request.</p>
<ul>
<li>Controller: The &#8216;page_callback&#8217; function associated with the active Drupal menu item (from the <a href="http://api.drupal.org/api/drupal/includes!menu.inc/function/menu_get_item/7">menu_get_item()</a> call).</li>
<li>Action: The first argument in the &#8216;page_arguments&#8217; array associated with the active menu item.</li>
</ul>
<p><a href="http://www.tracelytics.com/blog/drupal-performance-profiling/drupal_controller_actions/" rel="attachment wp-att-1399"><img class="alignnone size-full wp-image-1399" title="Drupal_Controller_Actions" src="http://www.tracelytics.com/blog/wp-content/uploads/Drupal_Controller_Actions.png" alt="" width="522" height="344" /></a></p>
<h3>Request Partitioning</h3>
<p>Requests are associated with a specific partition, depending on the type of request. This is crucial for determining where your heaviest requests come from, and when. The support partitions today are:</p>
<ul>
<li>Admin : Drupal admin user<img class="size-medium wp-image-1400 alignright" title="Drupal_Partitions" src="http://www.tracelytics.com/blog/wp-content/uploads/Drupal_Partitions-300x217.png" alt="" width="300" height="217" /></li>
<li>Anonymous : Anonymous user (not logged-in)</li>
<li>Authenticated : Logged in user</li>
<li>Cron : Periodic / cron execution</li>
<li>Drush : Command line shell / script (see<a href="http://www.drush.org/"> www.drush.org</a>)</li>
</ul>
<h3></h3>
<h3>Complete Error Logging</h3>
<p>Drupal provides a &#8220;<a href="http://api.drupal.org/api/drupal/includes!bootstrap.inc/function/watchdog/7">watchdog</a>&#8221; function for logging error/warning/debug messages. More severe messages can be forwarded to Tracelytics and will be tracked as errors.</p>
<h2>Configuration</h2>
<p>The above features can be turned on and off through the Drupal admin interface:</p>
<p><a href="http://www.tracelytics.com/blog/drupal-performance-profiling/drupal_admin/" rel="attachment wp-att-1392"><img class="alignnone size-large wp-image-1392" title="Tracelytics Drupal Admin" src="http://www.tracelytics.com/blog/wp-content/uploads/Drupal_Admin-650x504.png" alt="" width="650" height="504" /></a></p>
<p>Note that it also integrates with <a href="http://www.drush.org/">Drush</a>, a command line / shell scripting package.</p>
<h2>How&#8217;s it work?</h2>
<p>How does this module integrate with Tracelytics?  If we examine the module code, we&#8217;ll see that it makes extensive use of the oboe_log function.  This is a function added to PHP by the Tracelytics PHP instrumentation (&#8220;oboe&#8221;) module. It allows a code to log events, and is described in more detail in our <a href="http://support.tracelytics.com/kb/instrumenting-your-app/extending-tracelytics-customizing">knowledge base</a>.  The particular snippet logs an &#8220;info&#8221; event to report the partition based on the currently logged in user:</p>
<pre class="brush: plain; title: ; notranslate">
switch ($user-&gt;uid) {
  case 1:
    oboe_log('info', array('Partition' =&gt; 'Admin'));
    break;

  case 0:
    oboe_log('info', array('Partition' =&gt; 'Anonymous'));
    break;

  default:
    oboe_log('info', array('Partition' =&gt; 'Authenticated'));
    break;
}
</pre>
<p>If we browse through the rest of the code (specially the tracelytics_early and tracelytics_late sub-modules), we&#8217;ll see that each module registers the same hook. The &#8220;early&#8221; module executes first and sends the &#8220;entry&#8221; event, while the &#8220;late&#8221; module executes last and sends the &#8220;exit&#8221; event. The order of Drupal module execution is controlled by assigning each module a <a href="http://drupal.org/project/moduleweight">weight</a>.</p>
<p>Depending on the site configuration, various other modules would also register the same hooks and perform processing. Using the timestamps on the events allows Tracelytics to determine the processing time spent in each layer.  Snippets for the &#8220;init&#8221; hooks (which are called for all non-cached page requests) are shown below:</p>
<p>tracelytics_early.module:</p>
<pre class="brush: plain; title: ; notranslate">
function tracelytics_early_init() {
  if (variable_get('tracelytics_layers', FALSE)) {
    oboe_log('drupal_hook_init', 'entry', array());
  }
}
</pre>
<p>tracelytics_late.module:</p>
<pre class="brush: plain; title: ; notranslate">
function tracelytics_late_init() {
  if (variable_get('tracelytics_layers', FALSE)) {
    oboe_log('drupal_hook_init', 'exit', array());
  }
}
</pre>
<p>The pattern used for other hooks is the same.</p>
<p>As you can see, integrating Tracelytics as part of your application is very straightforward! In future blog articles, we&#8217;ll explore integrations with other languages and platforms, including Python, Ruby, and Java.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tracelytics.com/blog/drupal-performance-profiling/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 0.466 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2013-05-17 19:37:15 -->
