<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Sentry Blog</title>
  <link href="https://blog.sentry.io/feed.xml" rel="self" type="application/atom+xml" />
  <link href="https://blog.sentry.io" rel="alternate" type="text/html" />
  <updated>2017-06-02T11:48:02-07:00</updated>
  <id>https://blog.sentry.io/</id>

  
  




  <entry>
    <title>New Sentry Pricing: Outcomes and Observability for Everyone</title>
    <link href="https://blog.sentry.io/2017/05/25/new-sentry-pricing" rel="alternate" type="text/html" title="New Sentry Pricing: Outcomes and Observability for Everyone" />
    <updated>2017-05-25T00:00:00-07:00</updated>
    <published>2017-05-25T00:00:00-07:00</published>
    <id>https://blog.sentry.io/2017/05/25/new-sentry-pricing</id>
    <content type="html">&lt;p&gt;Like your team, Sentry moves fast. We eat our own dog food, drink our own champagne, take our vitamins, and monitor for errors. We’re obsessive about building the most important features and enabling the best possible experience to serve every developer everywhere.&lt;/p&gt;

&lt;p&gt;One of the great benefits of having tens of thousands of Sentry users sending billions of data points every month is that we’re able to see a massive variety of events and patterns, including those that are a reflection of usage and workflows, not just code errors and crash reports.&lt;/p&gt;

&lt;p&gt;So, in the spirit of making Sentry as easy to adopt and scale as possible for all types of users, we’re rolling out new &lt;strong&gt;outcomes-oriented pricing plans&lt;/strong&gt;. Wait, what the heck?&lt;/p&gt;

&lt;h2 id=&quot;counting-events-is-the-biggest-barrier-to-success&quot;&gt;Counting Events is the Biggest Barrier to Success&lt;/h2&gt;

&lt;p&gt;Yeah, that’s right: outcomes. The more attention we’ve paid to customer use cases, the more we’ve come to understand that counting events is the biggest barrier to success. Ultimately, the only number of events that aligns to every objective for error monitoring is MORE. Flexibility is among the most important features Sentry offers, and packaging to enable greater flexibility at lower total cost is the only way to ensure every Sentry user can drive the outcomes they care about, from faster issue resolution to proactive triage to root cause targeting to reducing technical debt.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/post-images/new-sentry-pricing/plans.png&quot; alt=&quot;Image of the new Sentry pricing plans&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/post-images/new-sentry-pricing/on-demand.png&quot; alt=&quot;On-demand events cost $0.00019 per event when paying anually or $0.00024 when paying monthly&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In order to help drive the goal of outcomes, the new plans are designed to give you greater observability and let you track more errors without worrying as much about the cost of each event. The decisions you make about monitoring, as well as how you align product development priorities, relies on seeing things that you didn’t previously know were important. So, if better resolution workflows are a priority, there’s a plan with the features you need to support them. If easier event allocation and management is important, the new pricing plans make it easy to prioritize that, too.&lt;/p&gt;

&lt;p&gt;What that actually means: Sentry users have told us (and we’ve seen) that they run out of events before diving into key use cases or adopting the workflows that help prevent, not just detect, errors. You love that it’s open-source and that it’s simple to get started, but guessing how many events you’ll need for the next month or year can actually compound the problem you set out to solve in the first place. Setting the bar for events too low sucks, especially when you really start to achieve developer efficiencies and want to scale.&lt;/p&gt;

&lt;h2 id=&quot;discovering-more-reasons-to-monitor--setting-more-interesting-goals&quot;&gt;Discovering More Reasons to Monitor &amp;amp; Setting More Interesting Goals&lt;/h2&gt;

&lt;p&gt;Better error monitoring makes your entire team more effective and able to focus on improving your product so that more users use it more. That means not only needing more events as you scale, but also discovering more reasons to monitor and setting more interesting goals. If you’re worried about hitting your events cap, and if each additional event carries a marginal cost, that uncertainty forces you to take your eye off the ball.&lt;/p&gt;

&lt;p&gt;With outcomes-oriented pricing, you’re allotted more events than your first, second, third, fourth, and fifth use cases will likely require without any of the extra expense. As your monitoring starts to depend on more breadth and structure, Sentry levels-up on event bandwidth along with the features you need, like our export API, data forwarding, and per-project rate limiting. Plus, with annual discounts under contracts (versus having to pay in advance), it’s way easier to adopt a plan that suits your development roadmap, not blocked by typical up-front billing hurdles.&lt;/p&gt;

&lt;p&gt;So, please welcome bigger, better error monitoring into your dev stack with Sentry. Still open source and easy to use, but now with plans assured to give you more events and features so your team can focus on building awesome products and gaining more insight, not counting bugs.&lt;/p&gt;
</content>
    <author><name>Ryan Goldman</name></author>
    <category term="welcome" />
    <summary type="html">With outcomes-oriented pricing, improve observability and error monitoring without worrying about event caps. Focus on building awesome apps, not counting bugs.</summary>
  </entry>
  
  




  <entry>
    <title>Welcome Elizabeth Campbell</title>
    <link href="https://blog.sentry.io/2017/05/19/welcome-elizabeth" rel="alternate" type="text/html" title="Welcome Elizabeth Campbell" />
    <updated>2017-05-19T00:00:00-07:00</updated>
    <published>2017-05-19T00:00:00-07:00</published>
    <id>https://blog.sentry.io/2017/05/19/welcome-elizabeth</id>
    <content type="html">&lt;p&gt;We’re excited to welcome &lt;a href=&quot;https://www.linkedin.com/in/elizabethlisacampbell/&quot;&gt;Elizabeth Campbell&lt;/a&gt; (a.k.a. EC$$) to team Sentry as head of BD.&lt;/p&gt;

&lt;p&gt;EC will work with partners to grow and extend Sentry’s reach. Before Sentry, EC was at Dropbox and Facebook, where she worked on strategic partnerships, operations, and everything in between.&lt;/p&gt;

&lt;p&gt;Outside of work, you can find EC reading way too much Politico and sprinting through an airport near you. Right now, she’s listening to Ludacris’s freestyle of “Llama Llama Red Pajama” and dares you to tell her this is not art.&lt;/p&gt;
</content>
    <author><name>Sentry</name></author>
    <category term="welcome" />
    <summary type="html">Elizabeth Campbell joins the Sentry team</summary>
  </entry>
  
  




  <entry>
    <title>PyCon After-Party: Eat! Drink! Mingle and Be Merry!</title>
    <link href="https://blog.sentry.io/2017/05/16/pyconafterparty" rel="alternate" type="text/html" title="PyCon After-Party: Eat! Drink! Mingle and Be Merry!" />
    <updated>2017-05-16T00:00:00-07:00</updated>
    <published>2017-05-16T00:00:00-07:00</published>
    <id>https://blog.sentry.io/2017/05/16/pyconafterparty</id>
    <content type="html">&lt;p&gt;We are hosting an after party at Pycon together with &lt;a href=&quot;https://www.linode.com/&quot;&gt;Linode&lt;/a&gt;. Come hang out and join us for some food, drinks, games and fun with the community. This event will be one for the books, we look forward to seeing you all there!&lt;/p&gt;

&lt;h3 id=&quot;when&quot;&gt;When&lt;/h3&gt;

&lt;p&gt;Friday, May 19th at 6:40 PM—8:40 PM&lt;/p&gt;

&lt;h3 id=&quot;where&quot;&gt;Where&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://www.spiritof77bar.com/&quot;&gt;Spirit of 77&lt;/a&gt;, 500 NE Martin Luther King Jr Blvd, Portland, OR 97232&lt;/p&gt;

&lt;iframe src=&quot;https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2795.172366565841!2d-122.66355428525696!3d45.52673683729087!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x5495a0ae8f8c51dd%3A0x91b17a8f9b962cb2!2sSpirit+of+77!5e0!3m2!1sen!2sus!4v1494968152144&quot; width=&quot;100%&quot; height=&quot;450&quot; frameborder=&quot;0&quot; style=&quot;border:0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;Please bring your badge and expect to comply with the PyCon &lt;a href=&quot;https://us.pycon.org/2017/about/code-of-conduct/&quot;&gt;Code of Conduct&lt;/a&gt;.&lt;/p&gt;
</content>
    <author><name>Christina Nguyen</name></author>
    <category term="events" />
    <summary type="html">Come hang out and join us for some food, drinks, games and fun with the community.</summary>
  </entry>
  
  




  <entry>
    <title>Automatically Get Commits With Heroku Releases</title>
    <link href="https://blog.sentry.io/2017/05/15/heroku-commits" rel="alternate" type="text/html" title="Automatically Get Commits With Heroku Releases" />
    <updated>2017-05-15T00:00:00-07:00</updated>
    <published>2017-05-15T00:00:00-07:00</published>
    <id>https://blog.sentry.io/2017/05/15/heroku-commits</id>
    <content type="html">&lt;p&gt;Tracking Heroku releases with Sentry just got a whole lot better.&lt;/p&gt;

&lt;p&gt;With the deploy hook configured, you can track releases of your Heroku app in Sentry and see new errors as they arise. Now, with our &lt;a href=&quot;https://blog.sentry.io/2017/05/01/release-commits.html&quot;&gt;expanded Releases feature&lt;/a&gt;, Sentry can automatically retrieve the relevant commit data associated with your release each time you deploy a new version. When you enable this feature, you also gain access to &lt;a href=&quot;https://blog.sentry.io/2017/05/09/release-deploys.html&quot;&gt;deploy emails&lt;/a&gt; so that relevant team members can be alerted immediately when their code has gone out.&lt;/p&gt;

&lt;p&gt;Having access to this commit data for a release can be extremely helpful in debugging new errors, as it adds the  ability to see which files have changed most recently, and which members of an organization have been involved in pushing code since the last release.&lt;/p&gt;

&lt;p&gt;If you’re using Heroku to deploy your app and want to take advantage of release tracking with Sentry, just follow these steps:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Connect your repository to your Sentry organization so that we can automatically retrieve your commit data.&lt;/p&gt;

    &lt;div class=&quot;frame&quot;&gt;
   &lt;img src=&quot;/img/post-images/release-commits/add-repo.png&quot; alt=&quot;Add a repo&quot; /&gt;
 &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Enable the Heroku integration in your Sentry Project Settings.&lt;/p&gt;

    &lt;div class=&quot;frame&quot;&gt;
   &lt;img src=&quot;/img/post-images/release-commits/enable-heroku.png&quot; alt=&quot;Add a repo&quot; /&gt;
 &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;In the Heroku Plugin Configuration, specify which repository and deploy environment to be associated with your Sentry project.&lt;/p&gt;

    &lt;div class=&quot;frame&quot;&gt;
   &lt;img src=&quot;/img/post-images/release-commits/heroku-project-config.png&quot; alt=&quot;Add a repo&quot; /&gt;
 &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Navigate to your Project’s Release Tracking settings and copy the deploy hook command to your Heroku config.&lt;/p&gt;

    &lt;div class=&quot;frame&quot;&gt;
   &lt;img src=&quot;/img/post-images/release-commits/heroku-config.png&quot; alt=&quot;Add a repo&quot; /&gt;
 &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And voilà! You’ll immediately start getting rich commit information and deploy emails with each new release.&lt;/p&gt;
</content>
    <author><name>Katie Lundsgaard</name></author>
    <category term="product" />
    <summary type="html">Introducing commit data with Heroku Releases</summary>
  </entry>
  
  




  <entry>
    <title>Sentry Turns 9!</title>
    <link href="https://blog.sentry.io/2017/05/12/happy-birthday-sentry" rel="alternate" type="text/html" title="Sentry Turns 9!" />
    <updated>2017-05-12T06:00:00-07:00</updated>
    <published>2017-05-12T06:00:00-07:00</published>
    <id>https://blog.sentry.io/2017/05/12/happy-birthday-sentry</id>
    <content type="html">&lt;p&gt;Today marks nine years since the very &lt;a href=&quot;https://github.com/getsentry/sentry/commit/3c2e87573d3bd16f61cf08fece0638cc47a4fc22&quot;&gt;first commit to Sentry&lt;/a&gt; — or as it used to be called, &lt;em&gt;django-db-log&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Sentry was born to solve a very simple problem: within a &lt;a href=&quot;https://djangoproject.com/&quot;&gt;Django&lt;/a&gt; project, which normally sends you an email for every error, how do we log those to the database and expose aggregate views? This was essential for any high traffic application due to various failure scenarios overwhelming your inbox. While you could achieve the similar results with logs, this also helped us prioritize which issues were the most important, often by how frequently they were occurring. Additionally it gave us immediate access to that data via a web UI.&lt;/p&gt;

&lt;p&gt;Over time we expanded the scope of Sentry. It started as simple aggregation in Django, then expanded into collecting things like stack locals and richer context. Due to community demand we eventually brought it into the larger Python ecosystem, removing the Django requirement. As the months and years went by, many of the core contributors grew into other roles at new companies, and often those companies weren’t using Python at all. This was the trigger that really lead us to our initial cross platform functionality, and started with support for languages like Ruby (via Chef) and JavaScript (via Mozilla).&lt;/p&gt;

&lt;div class=&quot;frame&quot;&gt;
  &lt;img src=&quot;/img/post-images/birthday/timeline.png&quot; alt=&quot;Timeline&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;The biggest change of course was when we spun out the cloud service – &lt;a href=&quot;https://sentry.io/&quot;&gt;sentry.io&lt;/a&gt; – and began to put real investment into the project. For the first few years of it’s life we used the revenue from the service to fund community events (ever been to karaoke with us at PyCon?), but it was still very much a straight forward mixed open source plus cloud service. If you didn’t want to host it yourself, we did it for you for small fee.&lt;/p&gt;

&lt;p&gt;Today we have massive technology companies like Stripe and Uber running Sentry behind their firewall, but equally large organizations like Dropbox and Hubspot trusting our cloud. This part of the story has been interesting, as we’ve hit a point where very capable engineering organizations use both our cloud as well as open source offerings, simply because they wanted to outsource part of the burden. All in all, Sentry has continued to grow and saturate the market, to the point where you’d be hard pressed to find a technology company that doesn’t rely on it, let alone a reason to choose a different product.&lt;/p&gt;

&lt;div class=&quot;frame&quot;&gt;
  &lt;img src=&quot;/img/post-images/birthday/growth.png&quot; alt=&quot;Growth&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;Looking at where things have ended up, it’s crazy to think about the shape of things just a couple of years ago. Sentry the company is now 30 full-time employees spread across San Francisco, Austin, and Vienna. While we’re still heads down building the core of Sentry, our ambitions continue to grow. A lot of investment lately has been into many things that are under the hood, such as &lt;a href=&quot;https://blog.sentry.io/2017/03/14/react-native.html&quot;&gt;cross-language call stacks&lt;/a&gt; and &lt;a href=&quot;https://blog.sentry.io/2017/05/09/release-deploys.html&quot;&gt;first class deploy tracking&lt;/a&gt;. While Sentry may look and feel similar to what it was almost a decade ago, under the hood we’ve become so much more.&lt;/p&gt;

&lt;p&gt;Our story is far from over, and if you’re interested in taking part in that journey, &lt;a href=&quot;https://sentry.io/jobs/&quot;&gt;we’d love to talk to you&lt;/a&gt;!&lt;/p&gt;
</content>
    <author><name>David Cramer</name></author>
    <category term="" />
    <summary type="html">Sentry is nine years old!</summary>
  </entry>
  
  




  <entry>
    <title>@ Your Teammates With Mentions</title>
    <link href="https://blog.sentry.io/2017/05/12/mentions" rel="alternate" type="text/html" title="@ Your Teammates With Mentions" />
    <updated>2017-05-12T05:00:00-07:00</updated>
    <published>2017-05-12T05:00:00-07:00</published>
    <id>https://blog.sentry.io/2017/05/12/mentions</id>
    <content type="html">&lt;p&gt;Collaboration is a major 🗝️ for success. You can now mention other members in issues, making teamwork even easier. Use @ to tag team members - they’ll receive an email and be subscribed to that issue.&lt;/p&gt;

&lt;div class=&quot;frame&quot;&gt;
  &lt;img src=&quot;/img/post-images/mentions/mentions-post.gif&quot; alt=&quot;Mentions Details&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;Any mentioned user will be able to see &lt;em&gt;why&lt;/em&gt; they are getting notifications in the body of the emails they receive:&lt;/p&gt;

&lt;div class=&quot;frame&quot;&gt;
  &lt;img src=&quot;/img/post-images/mentions/mentioned-email.png&quot; alt=&quot;Mentions Details&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;In your issue dashboard you can do a quick search for &lt;code class=&quot;highlighter-rouge&quot;&gt;subscribed:me&lt;/code&gt; to see which issues are you subscribed to, any with a little green comment icon &lt;img height=&quot;25&quot; width=&quot;25&quot; src=&quot;/img/post-images/mentions/green-comment.png&quot; alt=&quot;green icon&quot; /&gt; will be issues you are mentioned in.&lt;/p&gt;

&lt;p&gt;You can manually unsubscribe from any issue by selecting &lt;strong&gt;Unsubscribe Me&lt;/strong&gt;. (a.k.a Don’t @ me)&lt;/p&gt;
</content>
    <author><name>Meredith Heller</name></author>
    <category term="product" />
    <summary type="html">Bring more people in the loop with mentions</summary>
  </entry>
  
  




  <entry>
    <title>Welcome Ryan Goldman</title>
    <link href="https://blog.sentry.io/2017/05/12/welcome-ryan" rel="alternate" type="text/html" title="Welcome Ryan Goldman" />
    <updated>2017-05-12T00:00:00-07:00</updated>
    <published>2017-05-12T00:00:00-07:00</published>
    <id>https://blog.sentry.io/2017/05/12/welcome-ryan</id>
    <content type="html">&lt;p&gt;We’re excited to welcome &lt;a href=&quot;https://www.linkedin.com/in/ryangoldman&quot;&gt;Ryan Goldman&lt;/a&gt; to the Sentry team as VP Marketing.&lt;/p&gt;

&lt;p&gt;Ryan most recently led marketing at SignalFx and has built or contributed to teams at Mixpanel, Cloudera, and Cisco. He’ll be helping us find new ways to reach and serve the developer community in order to put a new Sentry in every home.&lt;/p&gt;

&lt;p&gt;Prior to marketing for tech, Ryan managed international development projects for NGOs, moonlighted as a music journalist, and created a social network for trading mixtapes. He also likes to read, run, and volunteer with animals.&lt;/p&gt;
</content>
    <author><name>Sentry</name></author>
    <category term="welcome" />
    <summary type="html">Ryan Goldman joins the Sentry team</summary>
  </entry>
  
  




  <entry>
    <title>Keep an Eye on New Code With Deploys</title>
    <link href="https://blog.sentry.io/2017/05/09/release-deploys" rel="alternate" type="text/html" title="Keep an Eye on New Code With Deploys" />
    <updated>2017-05-09T05:00:00-07:00</updated>
    <published>2017-05-09T05:00:00-07:00</published>
    <id>https://blog.sentry.io/2017/05/09/release-deploys</id>
    <content type="html">&lt;p&gt;No matter what review process you have, going live is the ultimate test for new code. With Sentry’s &lt;a href=&quot;https://blog.sentry.io/2017/05/01/release-commits&quot;&gt;new Release features&lt;/a&gt;, you’ll have the tools you need to confidently guide deploys across the finish line.&lt;/p&gt;

&lt;p&gt;When Sentry is aware of the timing and scope of your deploys, it will send a rich deploy emails to the involved parties detailing how many files have changed and what commits are being released.&lt;/p&gt;

&lt;div class=&quot;frame&quot;&gt;
  &lt;img style=&quot;height:700px;&quot; src=&quot;/img/post-images/release-deploys/deploy-email.png&quot; alt=&quot;Releases Overview&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;Deploy tracking isn’t just for production - the extra context will allow you to track what commits go to what environment at what time, giving you the complete picture of a changeset’s lifecycle.&lt;/p&gt;

&lt;p&gt;The email also links you to the release summary for each project affected, which will give you a breakdown of new issues and resolved issues for your release – everything you need to be confident your code is running smoothly, or to be ready to triage unforeseen problems.&lt;/p&gt;

&lt;div class=&quot;frame&quot;&gt;
  &lt;img src=&quot;/img/post-images/release-commits/releases-overview.png&quot; alt=&quot;Releases Overview&quot; /&gt;
&lt;/div&gt;

&lt;h3 id=&quot;sending-deploy-information&quot;&gt;Sending Deploy Information&lt;/h3&gt;

&lt;p&gt;Deploys in Sentry work together with the Release features you unlock by integrating commit data. If you already tag events with a release id in your SDK and send commit data &lt;a href=&quot;https://docs.sentry.io/learn/releases/&quot;&gt;(Release Documentation)&lt;/a&gt;, then there’s only one step left to unlock deploy tracking and emails. Post to the &lt;a href=&quot;https://docs.sentry.io/api/releases/post-release-deploys/&quot;&gt;Deploy API&lt;/a&gt; as part of your deployment process, and we’ll do the rest!&lt;/p&gt;

&lt;h4 id=&quot;shell-script-example&quot;&gt;Shell script example:&lt;/h4&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Create a new deploy&lt;/span&gt;
curl https://sentry.io/api/0/organizations/&lt;span class=&quot;nv&quot;&gt;$ORGANIZATION_SLUG&lt;/span&gt;/releases/&lt;span class=&quot;nv&quot;&gt;$RELEASE_VERSION&lt;/span&gt;/deploys/ &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  -X POST &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  -H &lt;span class=&quot;s1&quot;&gt;'Authorization: Bearer {TOKEN}'&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  -H &lt;span class=&quot;s1&quot;&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  -d &lt;span class=&quot;s1&quot;&gt;'
  {
    &quot;environment&quot;: &quot;production&quot;,
    &quot;name&quot;: &quot;my-deploy&quot;
}
'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;stay-tuned&quot;&gt;Stay tuned!&lt;/h3&gt;

&lt;p&gt;This is part two of a series of posts about the new features we’ve added to our Releases workflow. In the meantime, you can check out &lt;a href=&quot;https://docs.sentry.io/learn/releases/&quot;&gt;our docs&lt;/a&gt; for more details on how to get started. As always, let us know what you think on &lt;a href=&quot;https://twitter.com/getsentry&quot;&gt;Twitter&lt;/a&gt; and the &lt;a href=&quot;https://forum.sentry.io/&quot;&gt;Sentry forum&lt;/a&gt;.&lt;/p&gt;
</content>
    <author><name>Max Bittker</name></author>
    <category term="product" />
    <summary type="html">Have the tools you need to confidently guide deploys across the finish line.</summary>
  </entry>
  
  




  <entry>
    <title>Welcome Dena Metili Mwangi</title>
    <link href="https://blog.sentry.io/2017/05/09/welcome-dena" rel="alternate" type="text/html" title="Welcome Dena Metili Mwangi" />
    <updated>2017-05-09T00:00:00-07:00</updated>
    <published>2017-05-09T00:00:00-07:00</published>
    <id>https://blog.sentry.io/2017/05/09/welcome-dena</id>
    <content type="html">&lt;p&gt;Please help us welcome &lt;a href=&quot;https://github.com/denamwangi&quot;&gt;Dena Metili Mwangi&lt;/a&gt; to the team at Sentry.&lt;/p&gt;

&lt;p&gt;Dena joins us fresh from Hackbright Academy and has a background in Economics. Most recently, she spent her time playing with data and surveys while working on impact evaluations at the World Bank. When not coding, you’ll find her at a coffee shop or playing with other people’s cats. At Sentry, she’ll be focused on growth engineering.&lt;/p&gt;
</content>
    <author><name>Sentry</name></author>
    <category term="welcome" />
    <summary type="html">Dena Metili Mwangi joins the Sentry team</summary>
  </entry>
  
  




  <entry>
    <title>Releases Are Better With Commits</title>
    <link href="https://blog.sentry.io/2017/05/01/release-commits" rel="alternate" type="text/html" title="Releases Are Better With Commits" />
    <updated>2017-05-01T00:00:00-07:00</updated>
    <published>2017-05-01T00:00:00-07:00</published>
    <id>https://blog.sentry.io/2017/05/01/release-commits</id>
    <content type="html">&lt;p&gt;Knowing what code changed recently is extremely helpful in determining the cause of an error, which is why we’ve expanded our Releases feature to support commit data. By integrating commit data, you’ll unlock a number of helpful features:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Enhanced releases overview page that allows you to see new and resolved issues, files changed and authors all in the same place (see photo below)&lt;/li&gt;
  &lt;li&gt;Resolving Sentry issues via commit messages&lt;/li&gt;
  &lt;li&gt;Suggested assignees for issues&lt;/li&gt;
  &lt;li&gt;Detailed deploy emails (look out for a more in-depth look at deploys in Sentry soon)&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;frame&quot;&gt;
  &lt;img src=&quot;/img/post-images/release-commits/releases-overview.png&quot; alt=&quot;Releases Overview&quot; /&gt;
&lt;/div&gt;

&lt;h3 id=&quot;connecting-a-repository&quot;&gt;Connecting a repository&lt;/h3&gt;

&lt;p&gt;To get started, go to your organization’s dashboard, click “Repositories” and then click “Add Repository.” This will create a webhook and we’ll start collecting commit data, which you can then reference in releases.&lt;/p&gt;

&lt;div class=&quot;frame&quot;&gt;
  &lt;img src=&quot;/img/post-images/release-commits/add-repo.png&quot; alt=&quot;Add a repo&quot; /&gt;
&lt;/div&gt;

&lt;h3 id=&quot;adding-commits-to-releases&quot;&gt;Adding commits to releases&lt;/h3&gt;

&lt;p&gt;To indicate which commits are part of a release, you simply send along a &lt;code class=&quot;highlighter-rouge&quot;&gt;refs&lt;/code&gt; attribute when creating a release. In the below example, we’re telling Sentry that this release contains the my-repo repository, in which the current version (HEAD) is &lt;code class=&quot;highlighter-rouge&quot;&gt;2da95dfb052f477380608d59d32b4ab9&lt;/code&gt;. When you send this information, we’ll figure out which commits are part of the release based on your git history and previous releases.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Create a new release&lt;/span&gt;
curl https://sentry.io/api/0/organizations/:organization_slug/releases/ &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  -X POST &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  -H &lt;span class=&quot;s1&quot;&gt;'Authorization: Bearer {TOKEN}'&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  -H &lt;span class=&quot;s1&quot;&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  -d &lt;span class=&quot;s1&quot;&gt;'
  {
    &quot;version&quot;: &quot;2da95dfb052f477380608d59d32b4ab9&quot;,
    &quot;refs&quot;: [{
        &quot;repository&quot;:&quot;my-repo&quot;,
        &quot;commit&quot;:&quot;2da95dfb052f477380608d59d32b4ab9&quot;
    }],
    &quot;projects&quot;:[&quot;my-project&quot;,&quot;my-other-project&quot;]
}
'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;resolving-issues-via-commits&quot;&gt;Resolving issues via commits&lt;/h3&gt;

&lt;p&gt;Once you are sending commit data, you can start resolving issues by including &lt;code class=&quot;highlighter-rouge&quot;&gt;fixes &amp;lt;SHORT-ID&amp;gt;&lt;/code&gt; in your commit messages. For example, a commit message might look like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Prevent empty queries on users

Fixes MYAPP-317
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;When Sentry sees this, we’ll automatically annotate the matching issue with a reference to the commit, and, later, when that commit is part of a release, we’ll mark the issue as resolved.&lt;/p&gt;

&lt;h3 id=&quot;stay-tuned&quot;&gt;Stay tuned&lt;/h3&gt;

&lt;p&gt;We’ll have a series of posts about the new features we’ve added to our releases workflow. In the meantime, you can check out &lt;a href=&quot;https://docs.sentry.io/learn/releases/&quot;&gt;our docs&lt;/a&gt; for more details on how to get started. As always, let us know what you think on the &lt;a href=&quot;https://forum.sentry.io/&quot;&gt;Sentry forum&lt;/a&gt;.&lt;/p&gt;
</content>
    <author><name>Jess MacQueen</name></author>
    <category term="product" />
    <summary type="html">Connect a repository to add commit data to Sentry</summary>
  </entry>
  
  




  <entry>
    <title>Welcome Erik Lee</title>
    <link href="https://blog.sentry.io/2017/04/25/welcome-erik" rel="alternate" type="text/html" title="Welcome Erik Lee" />
    <updated>2017-04-25T00:00:00-07:00</updated>
    <published>2017-04-25T00:00:00-07:00</published>
    <id>https://blog.sentry.io/2017/04/25/welcome-erik</id>
    <content type="html">&lt;p&gt;Help us welcome &lt;a href=&quot;https://twitter.com/eriktlee&quot;&gt;Erik Lee&lt;/a&gt; to the Sentry team!&lt;/p&gt;

&lt;p&gt;Erik joins the Sentry team from Mixpanel and RainforestQA, where he helped customers make sense out of data and build better products, respectively. At Sentry, he’ll be working with the business team to enable customers to succeed using Sentry.&lt;/p&gt;

&lt;p&gt;While not sipping his LaCroix, you can find him chasing his dog with his girlfriend and coming up with excuses to justify his sneaker collection.&lt;/p&gt;
</content>
    <author><name>Sentry</name></author>
    <category term="welcome" />
    <summary type="html">Erik Lee joins Sentry's business team</summary>
  </entry>
  
  




  <entry>
    <title>Welcome Jan Crisostomo</title>
    <link href="https://blog.sentry.io/2017/04/13/welcome-jan" rel="alternate" type="text/html" title="Welcome Jan Crisostomo" />
    <updated>2017-04-13T00:00:00-07:00</updated>
    <published>2017-04-13T00:00:00-07:00</published>
    <id>https://blog.sentry.io/2017/04/13/welcome-jan</id>
    <content type="html">&lt;p&gt;Join us in welcoming &lt;a href=&quot;https://twitter.com/janfcrisostomo&quot;&gt;Jan Crisostomo&lt;/a&gt; to the Sentry team!&lt;/p&gt;

&lt;p&gt;If you’re an engineer, you may recognize Jan’s work from such emails as, “&lt;strong&gt;Engineering opportunities with [Company]!&lt;/strong&gt;”, “&lt;strong&gt;Just following up on my previous email&lt;/strong&gt;”, and “&lt;strong&gt;PLZ DON’T BLOCK ME&lt;/strong&gt;”. Jan has recruited and managed talent programs for tech companies like Google and Dropbox, most recently at Bessemer Venture Partners where she advised and recruited for a variety of early-stage startups.&lt;/p&gt;

&lt;p&gt;Jan will help build the Sentry team as Head of Talent, which she finds ironic since she has no talents. When she’s not self-consciously crafting third-person biographies, Jan can be found sipping tea, traveling, and writing chapters for her inevitable cult classic The 4-Hour Nap.&lt;/p&gt;
</content>
    <author><name>Sentry</name></author>
    <category term="welcome" />
    <summary type="html">Jan Crisostomo joins Sentry's operations team</summary>
  </entry>
  
  




  <entry>
    <title>The Troubles With iOS Symbolication</title>
    <link href="https://blog.sentry.io/2017/04/11/ios-symbolication-troubles" rel="alternate" type="text/html" title="The Troubles With iOS Symbolication" />
    <updated>2017-04-11T00:00:00-07:00</updated>
    <published>2017-04-11T00:00:00-07:00</published>
    <id>https://blog.sentry.io/2017/04/11/ios-symbolication-troubles</id>
    <content type="html">&lt;p&gt;Who does not love iOS? It’s a great operating system. However I can tell you
about a type of person that has a love/hate relationship with iOS: engineers
who have to debug crashes on iOS devices. iOS makes debugging crashes trickier
than most environments which in turn makes the job of tools like Sentry and
Crashlytics that much harder. In this blog post we want to give you a bit of
insight into how Sentry deals with iOS crashes and what is necessary for you
to have an enjoyable crash reporting experience.&lt;/p&gt;

&lt;h1 id=&quot;crashing-in-the-first-place&quot;&gt;Crashing in the First Place&lt;/h1&gt;

&lt;p&gt;The first part that goes into a crash is to generate a report we can actually
send to Sentry. For this to work you need something that can generate you a
basic backtrace at the moment a crash happens. There are two popular libraries
for iOS that can do that. One is KSCrash, the other is PLCrashReporter. Those
two libraries hook into different parts of the OS to respond to errors and to
extract a backtrace. This in itself is already a very complex undertaking and
we’re glad that others have done this task for us.&lt;/p&gt;

&lt;p&gt;There are many different situations that can cause crashes and each of them has
different characteristics. I don’t want to get too much into detail here but
it’s important to understand that not all crashes will result in the same
quality of reporting. An extreme case for iOS are C++ exceptions which will not
create proper backtraces on iOS because of how the exception system works.&lt;/p&gt;

&lt;p&gt;When we manage to report a stacktrace and some important data on crashing we
persist that temporarily on the device. Next time you start the application
we send that information to the server. The stacktrace is the most interesting
part and this also is the first complexity that spills over to the server
side.&lt;/p&gt;

&lt;p&gt;To give you a bit of an idea what this looks like, here is an example
stacktrace after you extract it:&lt;/p&gt;

&lt;pre&gt;
CrashLibiOS                     0x100077c4c
CrashProbeiOS                   0x200050220
UIKit                           0x31d104d30
UIKit                           0x31d104cb0
UIKit                           0x31d0ef128
UIKit                           0x31d10459c
UIKit                           0x31d68f628
UIKit                           0x31d68b6c0
UIKit                           0x31d68b1e0
UIKit                           0x31d68a49c
UIKit                           0x31d0ff30c
UIKit                           0x31d0cfda0
UIKit                           0x31d8b975c
UIKit                           0x31d8b3130
CoreFoundation                  0x3111ffb5c
CoreFoundation                  0x3111ff4a4
CoreFoundation                  0x3111fd0a4
CoreFoundation                  0x31112b2b8
GraphicsServices                0x314690198
UIKit                           0x31d13a7fc
UIKit                           0x31d135534
CrashProbeiOS                   0x20004f2a4
libdyld.dylib                   0x30f0f65b8
&lt;/pre&gt;

&lt;p&gt;So the first step would be to find some names for those addresses.  This process
is often called “symbolizing” or “symbolicating”.  We can already see where the
addresses are located because the device sends us a list of loaded images
(object files) and where they are loaded into memory.  To find the names we
need to look at symbol tables.&lt;/p&gt;

&lt;h1 id=&quot;stacktraces-on-ios&quot;&gt;Stacktraces on iOS&lt;/h1&gt;

&lt;p&gt;So as you can see stacktraces are fairly incomplete. While we can easily
find out what frameworks the addresses are contained in, it’s unlikely that you
will be able to find the function names for them on the device. There are two
cases you have to keep apart here. One case is where the symbols are in fact
missing, the other one is where symbols are marked as redacted.&lt;/p&gt;

&lt;p&gt;Missing symbols are typically what you have in release builds for your own
applications. In release builds most of the symbols you encounter are not
actually on the device so if we were to try to locate the function names on
the device we will not succeed. Instead they are stored in what is commonly
referred to as a “dsym file”.  Technically a dsym file is a macho file just
like an executable but it only contains the symbol table and debug information.
So while they could be in the same file, they usually are not. When I said that
“most” symbols are not on the device, this refers to the fact that some symbols
need to be in the file.  This is because most applications on iOS are written
in Objective-C. This is relevant because Objective-C implements methods through
a mechanism that is based on the idea of sending messages from object to
object. These messages are referred to as “selectors” and they are essentially
the name of the method.&lt;/p&gt;

&lt;p&gt;PLCrashReporter and some other tools are often attempting to find such symbols
even if the normal symbols are not on the device, however for the bulk of the
symbols you need to do this on the server.&lt;/p&gt;

&lt;p&gt;The second case of missing function names we need to concern ourselves with
is a weirder one: redacted symbols.&lt;/p&gt;

&lt;h1 id=&quot;redacted-symbols&quot;&gt;Redacted Symbols&lt;/h1&gt;

&lt;p&gt;Redacted symbols are symbols that are indeed available on the device but tools
like KSCrash or PLCrashReporter cannot access. When iOS loads system libraries
it removes symbols so that when one attempts to read the symbol by parsing the
framework one will only come across a symbol with the name &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;redacted&amp;gt;&lt;/code&gt; .This
is most likely done to save some memory or for security reasons. Because all
system frames will have the same constant string as a symbol there is a lot
that does not have to be loaded into memory.&lt;/p&gt;

&lt;p&gt;The downside is that we are not able to tell you which function in UIKit caused
your crash. When you hook your phone up to Xcode you can see such symbols
though. So how does that work? The answer is a bit bizarre and requires some
understanding of what happens when iOS loads the system libraries.&lt;/p&gt;

&lt;p&gt;When iOS redacts symbols it stores a copy of the original symbol on the file
system in a cache file that is not accessible for non rooted devices. The file
is named &lt;code class=&quot;highlighter-rouge&quot;&gt;dyld_shared_cache_arm64&lt;/code&gt; for arm64 etc. From the file name you
can see that this is considered a cache file. This means the file is updated as
redacted symbols are added to it. Apple built this system to primarily support
the flow where you debug your own device. If you run your own app and you hook
it up to the debugger all the frames that you are interested in will have their
redacted symbols added to the cache file. When you connect the phone to Xcode,
Xcode will go in and “prepare the device for development” and that will
essentially download the cache file and run it through a process where dummy
debug symbols are built for it. It will in fact create a folder structure below
&lt;code class=&quot;highlighter-rouge&quot;&gt;~/Library/Developer/Xcode/iOS DeviceSupport&lt;/code&gt; for your version of iOS and put
new macho files in there with symbols recovered from the cache file.&lt;/p&gt;

&lt;p&gt;Now you can guess what the problem with this is: if you have never seen a
symbol it won’t be in the cache file. This is particularly noticeable if you
are working with “legacy” architectures. For instance if you hook up an arm64
device with Xcode it will be able to extract some armv7 symbols but it will
most likely not find all. Your chances are most likely higher if you are
running a lot of 32bit apps to populate the cache, but you might as well just
hook it up with an older device instead. Whenever you add a device to Xcode it
will merge together the symbols it extracts.&lt;/p&gt;

&lt;p&gt;This shows one of the core issues that come up with symbolizing on iOS: you
need to collect as many of these debug symbols as possible.&lt;/p&gt;

&lt;h1 id=&quot;symbolicating-app-and-system&quot;&gt;Symbolicating App and System&lt;/h1&gt;

&lt;p&gt;Sentry is using two separate systems for resolving functions. For customer
debug symbols we are using our own LLVM based symbolication library for Python.
We fetch debug symbols from our S3 backed asset storage and then symbolicate
based on the symbols we have on our device. This scales quite well to the
workload caused by apps. These are typically large symbol files but there are
not that many per app.&lt;/p&gt;

&lt;p&gt;On the other hand dealing with symbols from the system libraries is a different
story.  There are thousands of symbol files and because the cache might be
incomplete we actually want to be quite fuzzy over them. As example for this
fuzziness is that we might be dealing with incomplete debug symbols for
system libraries from one SDK. In that case we want to try a few older versions
as well in case we find matches there.&lt;/p&gt;

&lt;p&gt;To achieve this goal we wrote a separate system we call the sentry symbol
server and it is a simple HTTP service written in Rust that takes a batch
request of addresses to symbolicate and then responds with the function names
if it finds them. It uses a custom file format that can be memory mapped in. We
then use a separate build process to create these mmap’ed files and put them to
S3. In regular intervals the server checks back with S3 and fetches new memory
maps if necessary.&lt;/p&gt;

&lt;h1 id=&quot;the-final-result&quot;&gt;The Final Result&lt;/h1&gt;

&lt;p&gt;After symbolication our boring crash report from before looks more like this:&lt;/p&gt;

&lt;pre&gt;
CrashLibiOS        -[CRLCrashNULL crash] (CRLCrashNULL.m:37)
CrashProbeiOS      -[CRLDetailViewController doCrash] (CRLDetailViewController.m:53)
UIKit              -[UIApplication sendAction:to:from:forEvent:]
UIKit              -[UIControl sendAction:to:forEvent:]
UIKit              -[UIControl _sendActionsForEvents:withEvent:]
UIKit              -[UIControl touchesEnded:withEvent:]
UIKit              __UIGestureEnvironmentSortAndSendDelayedTouches
UIKit              __UIGestureEnvironmentUpdate
UIKit              -[UIGestureEnvironment _deliverEvent:toGestureRecognizers:usingBlock:]
UIKit              -[UIGestureEnvironment _updateGesturesForEvent:window:]
UIKit              -[UIWindow sendEvent:]
UIKit              -[UIApplication sendEvent:]
UIKit              ___dispatchPreprocessedEventFromEventQueue
UIKit              ___handleEventQueue
CoreFoundation     ___CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
CoreFoundation     ___CFRunLoopDoSources0
CoreFoundation     ___CFRunLoopRun
CoreFoundation     _CFRunLoopRunSpecific
GraphicsServices   _GSEventRunModal
UIKit              -[UIApplication _run]
UIKit              _UIApplicationMain
CrashProbeiOS      main (main.m:16)
libdyld.dylib      _start
&lt;/pre&gt;

&lt;p&gt;And this allows us then to render the crash report in a more presentable way.
Because we know which symbols are from your app and which ones are from the system
we can by default hide frames you likely don’t care about:&lt;/p&gt;

&lt;div class=&quot;frame&quot;&gt;
  &lt;img src=&quot;/img/post-images/ios-symbolication-troubles/ios-stack.png&quot; alt=&quot;iOS Stacktrace Example&quot; /&gt;
&lt;/div&gt;

&lt;h1 id=&quot;in-an-ideal-world&quot;&gt;In an Ideal World&lt;/h1&gt;

&lt;p&gt;In an ideal world Apple would provide a web service that does what our symbol
server does. You give it the UUID of the image you want to symbolicate and the
address in it, and you get back a response of the symbol that is at that
address. At present the process of collecting all the symbols from different SDK
versions is slow, requires a lot of manual labour and is not even guaranteed to
always succeed.&lt;/p&gt;

&lt;h1 id=&quot;future-plans&quot;&gt;Future Plans&lt;/h1&gt;

&lt;p&gt;Sadly we are limited to providing system symbol resolving on our cloud
hosted version.  There are some concerns about the redistribution of system
symbol files which is why we currently cannot offer this service for on-prem
customers.&lt;/p&gt;

&lt;p&gt;If you are interested for support for system symbol symbolication for on-prem
installations leave your feedback &lt;a href=&quot;https://forum.sentry.io&quot;&gt;in the forums&lt;/a&gt;.  We
are playing with the idea of making our symbol server a public API in case
there is demand for it.&lt;/p&gt;

&lt;p&gt;If this article was of interest of you let us know. We might do a followup
where we explain our heuristics and the technical challenges on doing server
side symbolication.&lt;/p&gt;
</content>
    <author><name>Armin Ronacher</name></author>
    <category term="" />
    <summary type="html">Some in depth information about how symbolication of crash reports on iOS works.</summary>
  </entry>
  
  




  <entry>
    <title>Open Source Sprint at Sentry</title>
    <link href="https://blog.sentry.io/2017/04/03/open-source-sprint" rel="alternate" type="text/html" title="Open Source Sprint at Sentry" />
    <updated>2017-04-03T00:00:00-07:00</updated>
    <published>2017-04-03T00:00:00-07:00</published>
    <id>https://blog.sentry.io/2017/04/03/open-source-sprint</id>
    <content type="html">&lt;p&gt;In March, we hosted a sprint for the SF Python community to help newcomers interested contributing to open source. For two days, over 50 people came together in the Sentry offices to work on widely used projects like Mypy, Zulip, Certbot, and of course, Sentry. In particular, five attendees merged their first commits to a major open source project.&lt;/p&gt;

&lt;p&gt;If you’d like to see what was built, check out the PRs below! And if you’d like to start contributing to Sentry, check out &lt;a href=&quot;https://docs.sentry.io/internal/&quot;&gt;our docs for setting up your development environment&lt;/a&gt; and come chat with us on &lt;a href=&quot;https://forum.sentry.io/&quot;&gt;our community forum&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;contributors-to-sentry&quot;&gt;Contributors to Sentry&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/travisoneill&quot;&gt;travisoneill&lt;/a&gt; helped us &lt;a href=&quot;https://github.com/getsentry/sentry/pull/5100&quot;&gt;improve our project search parser&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/scotchka&quot;&gt;scotchka&lt;/a&gt; improved &lt;a href=&quot;https://github.com/getsentry/sentry/pull/5103&quot;&gt;our public issue pages&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/jamesmura&quot;&gt;jamesmura&lt;/a&gt; worked on &lt;a href=&quot;https://github.com/getsentry/sentry/pull/5098&quot;&gt;filtering MySQL passwords&lt;/a&gt;, project search &lt;a href=&quot;https://github.com/getsentry/sentry/pull/5101&quot;&gt;jumping to the right event&lt;/a&gt; when you search for a given event id, and &lt;a href=&quot;https://github.com/getsentry/sentry/pull/5094&quot;&gt;adding &lt;code class=&quot;highlighter-rouge&quot;&gt;event_id&lt;/code&gt; to our webhook payload&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ganeshkbalaji&quot;&gt;ganeshkbalaji&lt;/a&gt; simplified &lt;a href=&quot;github.com/getsentry/sentry/pull/5096&quot;&gt;our member invite flow&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/jgriffith23&quot;&gt;jgriffith23&lt;/a&gt; added &lt;a href=&quot;https://github.com/getsentry/sentry/pull/5097&quot;&gt;read-only member&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author><name>Eric Feng</name></author>
    <category term="events" />
    <summary type="html">In March, Sentry hosted an open source sprint for the SF Python community.</summary>
  </entry>
  
  




  <entry>
    <title>Welcome Evan Ralston</title>
    <link href="https://blog.sentry.io/2017/03/31/welcome-evan" rel="alternate" type="text/html" title="Welcome Evan Ralston" />
    <updated>2017-03-31T00:00:00-07:00</updated>
    <published>2017-03-31T00:00:00-07:00</published>
    <id>https://blog.sentry.io/2017/03/31/welcome-evan</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;https://github.com/evralston&quot;&gt;Evan Ralston&lt;/a&gt; joins Sentry this week as an operations engineer.&lt;/p&gt;

&lt;p&gt;Evan previously worked at a number of Bay area startups where he helped improve uptime of their web services. He will be helping Sentry’s operations team get ahead of projects, instead of dealing with systems problems reactively.&lt;/p&gt;

&lt;p&gt;When not automating himself out of a job, Evan likes convincing people to watch Steven Universe.&lt;/p&gt;
</content>
    <author><name>Sentry</name></author>
    <category term="welcome" />
    <summary type="html">Evan Ralston joins Sentry's operations team</summary>
  </entry>
  
  




  <entry>
    <title>Tips for Reducing JavaScript Error Noise</title>
    <link href="https://blog.sentry.io/2017/03/27/tips-for-reducing-javascript-error-noise" rel="alternate" type="text/html" title="Tips for Reducing JavaScript Error Noise" />
    <updated>2017-03-27T00:00:00-07:00</updated>
    <published>2017-03-27T00:00:00-07:00</published>
    <id>https://blog.sentry.io/2017/03/27/tips-for-reducing-javascript-error-noise</id>
    <content type="html">&lt;p&gt;If you’re using Sentry to monitor and debug browser JavaScript issues, you might be suffering from a common affliction: noisy, low-value errors that make it harder for you and your team to identify high-priority issues.&lt;/p&gt;

&lt;p&gt;This happens because browser JavaScript is perhaps the single most complex environment from which to capture errors – because it’s not just one environment! There are multiple major browsers, JavaScript engines, operating systems, and browser extension ecosystems, all of which come together to make capturing good errors difficult.&lt;/p&gt;

&lt;p&gt;Sentry does a decent job out of the box cutting through all this noise, but for the best results, it needs your help. Below are a few additional steps you can take to configure Sentry to greatly reduce the amount of noisy errors you receive.&lt;/p&gt;

&lt;h2 id=&quot;whitelist-your-urls&quot;&gt;Whitelist your URLs&lt;/h2&gt;

&lt;p&gt;Sentry’s &lt;a href=&quot;https://docs.sentry.io/clients/javascript/&quot;&gt;browser JavaScript SDK&lt;/a&gt;(Raven.js), by default, will pick up &lt;strong&gt;any&lt;/strong&gt; uncaught error triggered from your web app. That includes code running on your page that isn’t necessarily authored or controlled by you. For example, errors triggered from browser extensions, malware, or 3rd-party applications like chat widgets, analytics, and ad code.&lt;/p&gt;

&lt;p&gt;To ignore such problematic errors, you can configure Raven.js to whitelist errors originating solely from your own code:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;Raven&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'your-dsn'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;whitelistUrls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;'www.example.com/static/js'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// your code&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;'ajax.googleapis.com'&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;// code served from Google CDN&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This example configuration ensures that only errors that originate from scripts served from &lt;code class=&quot;highlighter-rouge&quot;&gt;www.example.com/static/js&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;ajax.googleapis.com&lt;/code&gt; are reported to the Sentry server. This small configuration change is the easiest, most impactful change you can make to reduce errors.&lt;/p&gt;

&lt;h2 id=&quot;use-inbound-data-filters&quot;&gt;Use inbound data filters&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://blog.sentry.io/2016/09/14/reduce-noise-inbound-data-filters.html&quot;&gt;Inbound data filters&lt;/a&gt; are a Sentry feature designed to discard known low-value errors from your projects. They are easily toggled
inside your Sentry project settings, and any errors they discard as a result do not count towards your account quota.&lt;/p&gt;

&lt;p&gt;There are 3 filters that are particularly valuable for JavaScript developers:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Legacy browsers&lt;/strong&gt; – old browsers like IE9 produce low-fidelity error reports that aren’t always actionable&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;3rd-party extensions&lt;/strong&gt; – automatically drop errors from known browser extensions, malware, and ad scripts&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Web crawlers&lt;/strong&gt; – drop errors triggered from known web crawlers like Google Bot&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inbound filters are not as powerful as configuring Raven.js to whitelist error URLs, but they’re nice because they can be enabled with a single click from inside your project settings.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note that inbound data filters are &lt;a href=&quot;https://github.com/getsentry/sentry/tree/master/src/sentry/filters&quot;&gt;open source&lt;/a&gt; and contributed to by the community. If you are encountering an error that you feel should be discarded globally by these filters, consider &lt;a href=&quot;https://github.com/getsentry/sentry/issues/new&quot;&gt;opening an issue/pull request&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;use-the-latest-version-of-ravenjs&quot;&gt;Use the latest version of Raven.js&lt;/h2&gt;

&lt;p&gt;Sentry’s browser JavaScript SDK is under active development, and changes are frequently made to both improve the &lt;em&gt;quality&lt;/em&gt; of error reports &lt;strong&gt;and&lt;/strong&gt; reduce the &lt;em&gt;quantity&lt;/em&gt; of low-value errors.&lt;/p&gt;

&lt;p&gt;For example, &lt;a href=&quot;https://github.com/getsentry/raven-js/releases/tag/3.12.0&quot;&gt;Raven.js 3.12.0&lt;/a&gt; now suppresses back-to-back duplicate errors by default. This is a life-saver if you are suffering from errors that trigger from asynchronous loops (e.g. from &lt;code class=&quot;highlighter-rouge&quot;&gt;setTimeout&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;XMLHttpRequest&lt;/code&gt; callbacks). In long lived applications, errors like these can result in thousands of events for a single user!&lt;/p&gt;

&lt;p&gt;To get the best experience, keep your copy of Raven.js up to date. Sentry will tell you when there’s a new version available, but it’s also worth checking &lt;a href=&quot;https://github.com/getsentry/raven-js/releases&quot;&gt;the changelog&lt;/a&gt; periodically to see what’s new.&lt;/p&gt;

&lt;h2 id=&quot;use-source-maps&quot;&gt;Use source maps&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://blog.sentry.io/2015/10/29/debuggable-javascript-with-source-maps.html&quot;&gt;Source maps&lt;/a&gt; don’t just make debugging your production stack traces easier, they make it easier for Sentry to group errors into individual issues. This means that events bucket into a smaller, more manageable set of issues, which means less noise in your issue stream and less 2AM emails about broken code.&lt;/p&gt;

&lt;p&gt;Making source maps a part of your build and deploy process isn’t as easy as toggling a button, but our in-depth &lt;a href=&quot;https://docs.sentry.io/clients/javascript/sourcemaps/&quot;&gt;source map documentation&lt;/a&gt; has everything you need to get started. Besides helping to reduce noise, source maps may be the single most profound improvement you can make to your monitoring and debugging workflow.&lt;/p&gt;

&lt;h2 id=&quot;ignore-troublesome-errors&quot;&gt;Ignore troublesome errors&lt;/h2&gt;

&lt;p&gt;Some errors you’re just never going to fix. When that happens, it might be time to declare bankruptcy and ignore them entirely.&lt;/p&gt;

&lt;p&gt;You can either ignore the error via the Sentry UI, or configure Raven.js to prevent them client-side using the &lt;code class=&quot;highlighter-rouge&quot;&gt;ignoreErrors&lt;/code&gt; option. Doing so from Raven.js is ideal because errors discarded at the client-level do not reach Sentry’s servers and do not count against your event quota.&lt;/p&gt;

&lt;p&gt;Here’s what it looks like:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;Raven&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'your-dsn'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ignoreErrors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;s1&quot;&gt;'Can\'t execute code from freed script'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;sr&quot;&gt;/SecurityError&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\:&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt; DOM Exception 18$/&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Be careful though: once you make this change, you’ll never see these errors again. And error strings that were previously just nuisances could become bigger problems down the line that you’ll never be informed of. Choose your &lt;code class=&quot;highlighter-rouge&quot;&gt;ignoreErrors&lt;/code&gt; array wisely!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note that browsers can produce different error messages for the same fundamental error. For a single &lt;code class=&quot;highlighter-rouge&quot;&gt;ReferenceError&lt;/code&gt;, you may need to input multiple strings/regexes to cover all possible browsers.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;upload-your-source-files-and-source-maps&quot;&gt;Upload your source files (and source maps)&lt;/h2&gt;

&lt;p&gt;When Sentry encounters an error triggered from a JavaScript file, it attempts to download that source file from your app servers in order to correlate line and column information with actual source content. This source content is the basis of Sentry’s error grouping algorithm.&lt;/p&gt;

&lt;p&gt;If your source files are only accessible over the web, there’s a lot of bad things that can happen. For example, you might have a build process that removes old JavaScript files from servers as you deploy new ones. If your users trigger errors from older cached scripts, when Sentry goes to download them, they will no longer be available. Not having access to that content can mess up the grouping algorithm, which means separate issues will be created for errors that would normally be bucketed under an existing issue.&lt;/p&gt;

&lt;p&gt;To avoid these and other interruption scenarios (e.g. network availability), we strongly recommend you &lt;strong&gt;upload your production JavaScript files and source maps&lt;/strong&gt; as release artifacts. This means that Sentry will always have direct access to these files, ensuring maximum grouping effectiveness.&lt;/p&gt;

&lt;p&gt;Uploading source files is done using the Sentry API, and is pretty simple:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;curl https://sentry.io/api/0/projects/:organization_slug/:project_slug/releases/:release/files/ &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  -X POST &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  -H &lt;span class=&quot;s1&quot;&gt;'Authorization: Bearer YOUR_TOKEN_HERE'&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  -F &lt;span class=&quot;nv&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;@app.js.map &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  -F &lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;http://example.com/app.js.map&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;To learn more about artifacts and releases, please see &lt;a href=&quot;https://docs.sentry.io/clients/javascript/sourcemaps/#uploading-source-maps-to-sentry&quot;&gt;our documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;were-here-to-help&quot;&gt;We’re here to help&lt;/h2&gt;

&lt;p&gt;We just discussed 6 ways you can reduce noise from browser JavaScript projects – some easy, some more involved. As always, if you want additional assistance with reducing JavaScript noise, please reach out on the &lt;a href=&quot;https://forum.sentry.io&quot;&gt;Sentry forum&lt;/a&gt; or contact our helpful &lt;a href=&quot;https://sentry.io/support/&quot;&gt;support team&lt;/a&gt;.&lt;/p&gt;
</content>
    <author><name>Ben Vinegar</name></author>
    <category term="welcome" />
    <summary type="html">Spare your inbox from noisy unwanted errors with these helpful tips.</summary>
  </entry>
  
  




  <entry>
    <title>Welcome Kelly Carino</title>
    <link href="https://blog.sentry.io/2017/03/20/welcome-kelly" rel="alternate" type="text/html" title="Welcome Kelly Carino" />
    <updated>2017-03-20T00:00:00-07:00</updated>
    <published>2017-03-20T00:00:00-07:00</published>
    <id>https://blog.sentry.io/2017/03/20/welcome-kelly</id>
    <content type="html">&lt;p&gt;We’re excited to announce that &lt;a href=&quot;https://github.com/mikellykels&quot;&gt;Kelly Carino&lt;/a&gt; is joining the Sentry team.&lt;/p&gt;

&lt;p&gt;Kelly joins us from Massdrop where she worked on improving the customer experience as well as scaling the support team. During her last few months at Massdrop, she completed an online course at Coding Dojo. At Sentry, she will be focusing on technical support and building out projects with the team.&lt;/p&gt;
</content>
    <author><name>Sentry</name></author>
    <category term="welcome" />
    <summary type="html">Kelly Carino joins the Sentry team</summary>
  </entry>
  
  




  <entry>
    <title>React Native</title>
    <link href="https://blog.sentry.io/2017/03/14/react-native" rel="alternate" type="text/html" title="React Native" />
    <updated>2017-03-14T00:00:00-07:00</updated>
    <published>2017-03-14T00:00:00-07:00</published>
    <id>https://blog.sentry.io/2017/03/14/react-native</id>
    <content type="html">&lt;p&gt;We have released a dedicated React Native SDK with some awesome features. If you are using &lt;a href=&quot;https://github.com/getsentry/raven-js&quot;&gt;raven-js&lt;/a&gt; with React Native, we recommend that you switch over to our brand new &lt;a href=&quot;https://github.com/getsentry/react-native-sentry&quot;&gt;react-native-sentry&lt;/a&gt; SDK.&lt;/p&gt;

&lt;p&gt;With this new SDK, Sentry is now able to provide mixed stacktraces. This means that if a JavaScript call causes a crash in native code, you will see the last call from JavaScript before the crash. This also means that with the new SDK, native crashes are properly handled on iOS.&lt;/p&gt;

&lt;div class=&quot;frame&quot;&gt;
  &lt;img src=&quot;/img/post-images/react-native/mixed-stacktraces.png&quot; alt=&quot;Mixed Stacktraces&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;Of course, if an error occurs in JavaScript, we also provide you with a useful stacktrace.&lt;/p&gt;

&lt;div class=&quot;frame&quot;&gt;
  &lt;img src=&quot;/img/post-images/react-native/react-native-error.png&quot; alt=&quot;React Native Stacktrace&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;Since we use our powerful, &lt;a href=&quot;https://github.com/getsentry/sentry-swift&quot;&gt;native Swift SDK&lt;/a&gt; in the background, you will also get much more information about the device and operating system.&lt;/p&gt;

&lt;div class=&quot;frame&quot;&gt;
  &lt;img src=&quot;/img/post-images/react-native/device-info.png&quot; alt=&quot;Device Info&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;When you also have an Android app, it will gracefully fall back to use &lt;a href=&quot;https://github.com/getsentry/raven-js&quot;&gt;raven-js&lt;/a&gt; since we currently only fully support iOS.&lt;/p&gt;

&lt;p&gt;To start using the new SDK, see the &lt;a href=&quot;https://docs.sentry.io/clients/react-native/&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;react-native-sentry&lt;/code&gt; documentation&lt;/a&gt;.&lt;/p&gt;
</content>
    <author><name>Daniel Griesser</name></author>
    <category term="product" />
    <summary type="html">Offical React Native Support</summary>
  </entry>
  
  




  <entry>
    <title>Introducing Reprocessing</title>
    <link href="https://blog.sentry.io/2017/03/02/introducing-reprocessing" rel="alternate" type="text/html" title="Introducing Reprocessing" />
    <updated>2017-03-02T00:00:00-08:00</updated>
    <published>2017-03-02T00:00:00-08:00</published>
    <id>https://blog.sentry.io/2017/03/02/introducing-reprocessing</id>
    <content type="html">&lt;h1 id=&quot;introducing-reprocessing-for-ios&quot;&gt;Introducing Reprocessing for iOS&lt;/h1&gt;
&lt;p&gt;In order to provide useful and human-readable stacktraces for iOS crashes, developers have to share their app debug symbols with Sentry. If a crash comes in, Sentry uses these debug symbols to map memory address to the according function name and line number.&lt;/p&gt;

&lt;p&gt;For example: the unreadable &lt;code class=&quot;highlighter-rouge&quot;&gt;0x205d2d000&lt;/code&gt; becomes
&lt;code class=&quot;highlighter-rouge&quot;&gt;ViewController.onClickFatalError(AnyObject) -&amp;gt; () (ViewController.swift:113)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now the user knows exactly where the app crashed and can fix the bug. But for this to work inside Sentry, there was a catch: you had to provide these symbols &lt;em&gt;before&lt;/em&gt; the crash occurs. And not all iOS developers have access to symbols before they go up on the App store.&lt;/p&gt;

&lt;p&gt;Today we are proud to announce our new reprocessing feature. With this update, iOS events that cannot be processed due to missing debug symbols will be held from the event stream and reprocessed once the symbols have been uploaded.&lt;/p&gt;

&lt;h2 id=&quot;why-reprocessing-matters&quot;&gt;Why reprocessing matters&lt;/h2&gt;

&lt;p&gt;This has two major advantages for iOS developers. The first is that this keeps noise down due to bad grouping caused by lack of information. In the past, if events were submitted before debug symbols were uploaded, you could easily end up with lots of incorrectly grouped errors that were just duplicates from older issues.&lt;/p&gt;

&lt;p&gt;The second benefit is that since we put those issues on hold temporarily, we will not send out any email notifications from those until the debug symbols are up.&lt;/p&gt;

&lt;p&gt;While in a perfect world you would never see an event before the debug symbols are ingested, we know that this is hard to do in practice. In particular, if you have bitcode-enabled builds, it can take a long time for processing to finish on the iTunes Connect side. This means that there is a good chance that someone may start (ab)using your app before you’ve had time to upload symbols.&lt;/p&gt;

&lt;h2 id=&quot;enabling-reprocessing&quot;&gt;Enabling reprocessing&lt;/h2&gt;

&lt;p&gt;Reprocessing is disabled by default and can be turned on in the project settings. Additionally, if you have an issue that lacks debug symbols, we’ll point you to the reprocessing settings page.&lt;/p&gt;

&lt;div class=&quot;frame&quot;&gt;
  &lt;img src=&quot;/img/post-images/reprocessing/reprocessing-hint.png&quot; alt=&quot;Reprocessing Hint&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;In the project settings you can turn it on with a flip of a switch:&lt;/p&gt;

&lt;div class=&quot;frame&quot;&gt;
  &lt;img src=&quot;/img/post-images/reprocessing/reprocessing-settings.png&quot; alt=&quot;Reprocessing Settings&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;There you can also see a log of all the reasons events were not processed (for instance, because of missing debug symbols, because broken debug symbols were uploaded etc.).&lt;/p&gt;

&lt;p&gt;When debug symbols are missing you can see this on the event stream.  A red warning bar will appear and inform you to upload missing symbols.&lt;/p&gt;

&lt;div class=&quot;frame&quot;&gt;
  &lt;img src=&quot;/img/post-images/reprocessing/bar.png&quot; alt=&quot;Reprocessing Bar&quot; /&gt;
&lt;/div&gt;

&lt;p&gt;Our command line tools have been updated to trigger reprocessing automatically. If you are using an older version of &lt;code class=&quot;highlighter-rouge&quot;&gt;sentry-cli&lt;/code&gt; that does not have this automatically enabled, you can also manually trigger reprocessing from the project settings.&lt;/p&gt;

&lt;h2 id=&quot;how-it-works&quot;&gt;How it works&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What happens if it’s turned on?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When the feature is enabled, all events that are missing mandatory debug symbols go into a queue and will not show up until their debug symbols are uploaded.  Currently we only require a small set of debug symbols and when all those are up the event is free to be reprocessed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is considered a mandatory debug symbol?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is currently implementation defined and we might tweak it in the future. For now, you can see the list of debug symbols we deem required in your project settings once we encounter such debug symbols. We recommend uploading all debug symbols you have.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What triggers reprocessing?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There is an API you can hit which starts the reprocessing. By default this is done automatically by the sentry-cli tool but this can be disabled. You can also trigger reprocessing again from the project settings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What about optional debug symbols?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We recommend uploading optional debug symbols first or to not trigger reprocessing until you have them all up. Once an event is no longer on hold we no longer permit reprocessing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I see events on hold?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There is currently no way for you to see such events but we will investigate this option in the future.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens if I disable reprocessing?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you disable reprocessing, events that are already on hold will be processed and shown to you in the stream view. Future events that come in will also show up as they arrive. This, however, might cause bad grouping because information relevant for grouping could be unavailable. We recommend against turning off reprocessing.&lt;/p&gt;

&lt;h2 id=&quot;see-also-our-updated-swift-client&quot;&gt;See also our updated Swift client&lt;/h2&gt;

&lt;p&gt;Reprocessing isn’t the only thing that’s changed for iOS. We recently pushed out a big change to our &lt;a href=&quot;https://sentry.io/for/cocoa/&quot;&gt;Swift client&lt;/a&gt; which – together with some server side changes – greatly improves the accuracy of our symbolication process. If you are not using the latest and greatest version yet, please make sure to upgrade.&lt;/p&gt;
</content>
    <author><name>Armin Ronacher</name></author>
    <category term="" />
    <summary type="html">We improved our development experience for iOS.</summary>
  </entry>
  
  




  <entry>
    <title>Dodging S3 Downtime With Nginx and HAProxy</title>
    <link href="https://blog.sentry.io/2017/03/01/dodging-s3-downtime-with-nginx-and-haproxy" rel="alternate" type="text/html" title="Dodging S3 Downtime With Nginx and HAProxy" />
    <updated>2017-03-01T00:00:00-08:00</updated>
    <published>2017-03-01T00:00:00-08:00</published>
    <id>https://blog.sentry.io/2017/03/01/dodging-s3-downtime-with-nginx-and-haproxy</id>
    <content type="html">&lt;p&gt;Like many websites and service providers, we use and depend on Amazon S3. Among other things, we primarily use S3 as a data store for uploaded artifacts like JavaScript source maps and iOS debug symbols; which are a critical part in our event processing pipeline. Yesterday, S3 experienced an outage that lasted 3 hours, but the impact on our processing pipeline was very minimal.&lt;/p&gt;

&lt;p&gt;Last week, we set off on solving one potential problem that we were experiencing: fetching data out of S3 was neither as performant nor reliable as we would hope. Our servers are in Dallas, while our S3 buckets are in Virginia (us-east-1). This means that we see an average of 32ms ping times, and 100ms for a full Layer 6 TLS handshake. Additionally, S3 throttles bandwidth to servers outside of their network, which limits the ability for us to fetch our largest assets in a timely manner. While increasing performance was our primary goal, this project turned out to be extremely beneficial during the S3 outage and kept our processing pipeline chugging along for the duration of it.&lt;/p&gt;

&lt;p&gt;We started off by putting together a quick S3 proxy cache that lived in our datacenter that would cache full assets from S3, allowing us to serve them on our local network without going to Virginia and back every single time. The requirements of this experiment were:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;minimize risk to production-facing traffic&lt;/li&gt;
  &lt;li&gt;avoid introducing single points of failure&lt;/li&gt;
  &lt;li&gt;prove the concept without increasing hardware bill&lt;/li&gt;
  &lt;li&gt;avoid committing changes to application code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We completed our task with two popular services, no application code required. We used &lt;a href=&quot;https://nginx.org/&quot;&gt;nginx&lt;/a&gt; as an S3 cache, while using &lt;a href=&quot;http://www.haproxy.org/&quot;&gt;HAProxy&lt;/a&gt; to route requests back to S3 if nginx were to fail.&lt;/p&gt;

&lt;p&gt;The goal of the nginx server was to leverage the &lt;a href=&quot;https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_cache&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;proxy_cache&lt;/code&gt;&lt;/a&gt; and store all of our S3 assets on disk when requested. We wanted to leverage a large 750GB disk cache and keep a very large set of actively cached data.&lt;/p&gt;

&lt;p&gt;Our new proposed infrastructure would look like this:&lt;/p&gt;

&lt;div class=&quot;row&quot;&gt;
  &lt;div class=&quot;col-md-10 col-md-offset-1&quot;&gt;
    &lt;img src=&quot;/img/post-images/nginx/graph.png&quot; class=&quot;white-background outline-none&quot; /&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;The setup should look relatively familiar for anyone who has worked with service discovery. Each application server that’s running our Sentry code has an HAProxy process running on &lt;code class=&quot;highlighter-rouge&quot;&gt;localhost&lt;/code&gt;. HAProxy is tasked with directing traffic to our cache server, which will proxy upstream to Amazon. This configuration also allows for a failover to occur, allowing HAProxy to talk directly to Amazon and bypass our cache without any interruption.&lt;/p&gt;

&lt;p&gt;Configuring HAProxy is quick, only taking eight lines:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Define a DNS resolver for S3
resolvers dns
  # Which nameserver do we want to use?
  nameserver google 8.8.8.8
  # Cache name resolutions for 300s
  hold valid 300s

listen s3
  bind 127.0.0.1:10000
  mode http
  # Define our s3cache upstream server
  server s3cache 10.0.0.1:80 check inter 500ms rise 2 fall 3
  # With actual Amazon S3 as a backup host using our DNS resolver
  server amazon s3.amazonaws.com:443 resolvers dns ssl verify required check inter 1000ms backup
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;On each application server tasked with communicating to S3, the HAProxy Admin ends up displaying this:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/img/post-images/nginx/admin.png&quot;&gt;&lt;img src=&quot;/img/post-images/nginx/admin.png&quot; class=&quot;outline-none&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This gives us a live view of the cache’s health from the perspective of a single application server. Ironically, this also came in handy when S3 went down, clearly depicting that there was exactly two hours and 57 minutes of downtime during which we could not communicate with Amazon.&lt;/p&gt;

&lt;p&gt;Configuring nginx was a little bit more involving since it’s doing the heavy lifting:&lt;/p&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;http&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kn&quot;&gt;gzip&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# need to setup external DNS resolver
&lt;/span&gt;  &lt;span class=&quot;kn&quot;&gt;resolver&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.8.8.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kn&quot;&gt;resolver_timeout&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;5s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# configure cache directory with 750G and holding old objects for max 30 days
&lt;/span&gt;  &lt;span class=&quot;kn&quot;&gt;proxy_cache_path&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/var/cache/nginx&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;levels=1:2&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;keys_zone=default:500m&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;max_size=750g&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;inactive=30d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;kn&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;10.0.0.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;default_server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kn&quot;&gt;keepalive_timeout&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3600&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kn&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;kn&quot;&gt;proxy_http_version&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;c1&quot;&gt;# Make sure we're proxying along the correct headers
&lt;/span&gt;      &lt;span class=&quot;kn&quot;&gt;proxy_set_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Host&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;s3.amazonaws.com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# Pass along Authorization credentials to upstream S3
&lt;/span&gt;      &lt;span class=&quot;kn&quot;&gt;proxy_set_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Authorization&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$http_authorization&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# Make sure we're using Keep-Alives with S3
&lt;/span&gt;      &lt;span class=&quot;kn&quot;&gt;proxy_set_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Connection&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;c1&quot;&gt;# Configure out caches
&lt;/span&gt;      &lt;span class=&quot;kn&quot;&gt;proxy_cache&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# Cache all 200 OK's for 30 days
&lt;/span&gt;      &lt;span class=&quot;kn&quot;&gt;proxy_cache_valid&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;30d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# Use stale cache file in all errors from upstream if we can
&lt;/span&gt;      &lt;span class=&quot;kn&quot;&gt;proxy_cache_use_stale&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;timeout&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;invalid_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;updating&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;http_500&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;http_502&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;http_503&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;http_504&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# Lock the cache so that only one request can populate it at a time
&lt;/span&gt;      &lt;span class=&quot;kn&quot;&gt;proxy_cache_lock&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;c1&quot;&gt;# Verify and reuse our SSL session for our upstream connection
&lt;/span&gt;      &lt;span class=&quot;kn&quot;&gt;proxy_ssl_verify&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;kn&quot;&gt;proxy_ssl_session_reuse&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;c1&quot;&gt;# Set back a nice HTTP Header to indicate what the cache status was
&lt;/span&gt;      &lt;span class=&quot;kn&quot;&gt;add_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;X-Cache-Status&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$upstream_cache_status&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;always&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

      &lt;span class=&quot;c1&quot;&gt;# Set this to a variable instead of using an `upstream`
&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;# to coerce nginx into resolving as DNS instead of caching
&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;# it once on process boot and never updating.
&lt;/span&gt;      &lt;span class=&quot;kn&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$s3_host&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'s3.amazonaws.com'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;kn&quot;&gt;proxy_pass&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$s3_host&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This configuration is allowing us to use a 750GB disk cache for our S3 objects as configured by &lt;a href=&quot;https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_cache_path&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;proxy_cache_path&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This proxy service had been running for a week while we watched our bandwidth and S3 bill drop, but we had an unexpected exchange yesterday morning:&lt;/p&gt;

&lt;div class=&quot;row&quot;&gt;
  &lt;div class=&quot;col-xs-10 col-xs-offset-1 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3&quot;&gt;
    &lt;div class=&quot;frame&quot;&gt;
      &lt;img src=&quot;/img/post-images/nginx/slack.png&quot; /&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;HAProxy had immediately notified us when S3 started showing signs of trouble. In a random turn of events, the proxy that we had implemented to serve as a cache was now serving all of Sentry’s S3 assets while the Amazon service was offline. During the full three hours, we exhibited some problems when users attempted to upload artifacts, but the event processing pipeline happily kept flowing.&lt;/p&gt;

&lt;p&gt;From start to finish, our proxy cache took less than a day to implement. In this past week, we have reduced our S3 bandwidth cost by 70%, gained even more performance and reliability when processing events, and took back the majority of the eggs we had the S3 basket.&lt;/p&gt;
</content>
    <author><name>Matt Robenolt</name></author>
    <category term="inside-sentry" />
    <summary type="html">How we took eggs out of the S3 basket.</summary>
  </entry>
  
</feed>
