Ozcode https://oz-code.com Debug like a Wizard Sun, 04 Apr 2021 08:26:44 +0000 en-US hourly 1 https://oz-code.com/wp-content/uploads/2020/03/ozcode_logo.svg Ozcode https://oz-code.com 32 32 Supercharging Web Apps by Testing and Debugging in Production https://oz-code.com/blog/production-debugging/supercharging-web-apps-testing-debugging-in-production Wed, 31 Mar 2021 14:08:05 +0000 https://oz-code.com/?p=17999 Two ways your web application can break are UI bugs and deep-down logical bugs in the server. You can detect and resolve both types with Selenium Test Automation and debugging in Production.

The post Supercharging Web Apps by Testing and Debugging in Production appeared first on Ozcode.

]]>

This post is co-authored by Himanshu Sheth, Senior Manager, Technical Content Marketing at LambdaTest.

“Move fast and break things,” goes the famous saying by Mark Zukerberg. But developers know that there’s a delicate balance between your release velocity and how robust your application is going to be. When bugs slip through Staging and get to Production, they start affecting your customers. When that happens (and it certainly does), it’s going to get everybody’s attention and become your top priority. Two ways your web application can break are UI bugs and deep-down logical bugs in the server.

In this post, I’ll show how you can detect and resolve both these types of Production bugs, hopefully before your customers notice them. First, I’ll show how to use Selenium test automation using LambdaTest Cloud Grid to run a web app simultaneously on multiple browsers to catch UI glitches.

With a cloud-based Selenium Grid, you can catch UI issues way ahead of time by testing the features across a range of browser and platform combinations. The fierce battle of quality vs. time can be won by testing on a cloud-based Selenium Grid!

Then I’ll show how Ozcode Live Debugger’s time-travel debugging digs deep into your live server code to help you debug exceptions and logical errors in Production. My reference application is this mock eCommerce site where you can purchase all sorts of goodies related to .NET.

Selenium test automation is a necessity, not a luxury

One of the biggest challenges faced by web developers is uniformity of the UI across different browsers, devices, and platform combinations. Cross-browser compatibility issues can create a huge bottleneck on the user experience, especially if you have not tested the UI on browsers & platforms that are widely used by your target audience. You do not want to irk your customers with misplaced buttons, overlapping texts, and other such usability issues that would drive them away from your website (or web application). However, it is impossible to cover the entire gamut of browsers and operating systems since the list can be an endless one. Did you know that despite the dominance of Chrome and Firefox, Internet Explorer is still relevant, even today? Free up your IT team from the unnecessary burden of constantly maintaining an in-house Selenium Grid that is high on maintenance and yields lower returns. Instead, prioritize the browser & OS combinations on which you intend to perform testing and kick-start with testing on a reliable & scalable cloud-based Selenium Grid by LambdaTest.

How to get started with Automated Browser Testing using a Selenium Grid On-Cloud

If you’re not already familiar with Selenium and how it works, I would recommend reading the “What is Selenium” guide by LambdaTest.

If you’ve worked with Selenium before and prefer it for automating browser interactions, you should give LambdaTest a spin. It helps to overcome existing infrastructure issues with your automation testing script.

To run your existing Selenium test script over LambdaTest Grid, you will need to change the Hub URL from your local machine to LambdaTest cloud. You can do that by declaring your username and access key in the remote Hub URL to successfully authenticate your access to the LambdaTest cloud servers. Your LambdaTest username & access key can be obtained from the Profile Page.

Here are the brief set of steps to perform Automation testing on LambdaTest:

You can monitor the status of the tests run on LambdaTest Grid by navigating to the Automation Dashboard.

Now that you have set up the account on LambdaTest, it’s time to port the working existing test implementation to LambdaTest. Suppose you have used the NUnit framework in Selenium C# for writing the automation tests. The change will be majorly involved in the method implemented under the [SetUp] annotation. This is where you have to instantiate the browser on which the test needs to be performed.

Here is the code snippet which showcases the instantiation of the Chrome browser on a local Selenium Grid:

				
					using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using System.Reflection;
using System.Threading;
using System.Collections.Generic;
using System.Web;

namespace NUnitTest
{
    public class NUnitTest
    {
        String test_url = "test_url";
        public IWebDriver driver;

        [SetUp]
        public void start_Browser()
        {
            /* Local Selenium WebDriver */
            driver = new ChromeDriver();
            driver.Url = test_url;
            driver.Manage().Window.Maximize();
        }
        /* Tests follow here */
    }
}

				
			

As seen above, the start_browser() method instantiates the Chrome browser, after which the URL under test is set. The test(s) would be implemented in method(s) that are under the [Test] annotation.

Before running the tests, generate the desired browser capabilities using the LambdaTest Capabilities Generator. As shown below, select the appropriate browser, browser version, and platform on which you intend to perform the test:

So, how do we port this implementation such that the existing tests run on cloud-based Selenium Grid from LambdaTest? Well, the changes are only involved in the method implemented under the [SetUp] annotation. Instead of a local Selenium WebDriver, we use the Remote WebDriver that passes the test request to the LambdaTest Hub [@hub.lambdatest.com/wd/hub].

				
					using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Remote;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Collections.Generic;
using System.Web;

namespace NUnitTest
{
    public class NUnitTest
    {
        String test_url = "test_url";
        public IWebDriver driver;

        /* LambdaTest Credentials and Grid URL */
        String username = "user-name";
        String accesskey = "access-key";
        String gridURL = "@hub.lambdatest.com/wd/hub";

        [SetUp]
        public void start_Browser()
        {
            DesiredCapabilities capabilities = new DesiredCapabilities();

            capabilities.SetCapability("user", username);
            capabilities.SetCapability("accessKey", accesskey);
            capabilities.SetCapability("build", "[C#] Demo of LambdaTest Grid");
            capabilities.SetCapability("name", "[C#] Demo of LambdaTest Grid");
            capabilities.SetCapability("platform", "Windows 10");
            capabilities.SetCapability("browserName", "Chrome");
            capabilities.SetCapability("version", "latest");

            driver = new RemoteWebDriver(new Uri("https://" + username + ":" + accesskey + gridURL), capabilities, TimeSpan.FromSeconds(600));
            driver.Url = test_url;
            driver.Manage().Window.Maximize();
        }
        /* Tests follow here */
    }
}

				
			

With this, you are all set to run your tests on the LambdaTest Selenium Grid. On execution, you can visit the Automation Dashboard to keep a watch on the status of the tests.

Have a look at how your website (or web app) can render differently on different browsers (and browser versions):

Shown below is a cross-browser test performed on IE 8 (running on Windows 7).  Not only is the rendering messed up, but the “Next” button (which is in the SVG format) is also displayed incorrectly.

Compare this with a working test that is run on Chrome 89 + Windows 10 combination. There are no issues whatsoever in the rendering of the web page.

The key takeaway is that cross-browser testing at scale should feature in your automation testing checklist. With this, your customers would be greeted with an ever-lasting product experience that works like a charm on browsers and devices that they love to use!

Online Selenium Grid such as LambdaTest has made it super-easy for us to ensure a cross-browser compatible experience without having to worry much about the infrastructure limitations that curtail browser and test coverage. LambdaTest offers much-needed scalability and reliability so that cross-browser tests can be performed at scale!

Debugging logic in Production with Time-Travel Fidelity

Let’s now look at that other type of bug which I earlier mentioned – a logical bug. Our mock eCommerce site offers a Buy 2 Get 1 FREE deal with some bugs built-in. When I chose 2 of those nifty sweatshirts, the site automatically gave me a third one. Well, they’re cool, but not that cool, so I decided to bag it. But when updating the quantity to 0, the site throws an exception.

Watch this.

Ozcode automatically catches the exception and displays it in the dashboard. We can see it’s an ArgumentOutOfRangeException.

To debug the exception, I click the Debug button.

Ozcode shows where the exception was thrown in the code, and you immediately understand why. There’s an OutOfRange Guard clause, and the value of Input is -1.

Now let’s climb up the call stack a bit and look at method AdjustQuantity where we implemented the Buy2 Get 1 Free deal.

First off, from the red/green color coding, we see exactly which parts of this method were executed in this error flow. The first “if” statement handles the Buy 2 Get 1 Free.

				
					if (newQuantity == 2)
{
	newQuantity = 3
}

				
			

But that handles the case when a customer modifies the number of items from 1 to 2.

In this case, I’ve changed my mind and updated the quantity back to 0, so the second “if” statement is executed (as we can easily see because it’s green).

				
					if (currentQuantity > 2 && newQuantity < 2)
{
	newQuantity--
}

				
			

But someone has not considered an input value of 0 to newQuantity, so we get our exception.

Now, there are any number of APMs or error monitoring tools that will show you that ArgumentOutOfRangeException with the invalid input of -1. None of those will show you the code across the whole call stack and the values of all locals, variables, and method parameters and return values that show you exactly HOW you got to that invalid input. It’s only once you have that data that the fix for this bug becomes trivial.

Now, you may be thinking, “this was a simple example; real life is more complicated.” You may be right, but even for an example like this, you may have found yourself guessing at the solution, adding log entries to validate it, and rebuilding to test. This kind of observability into the code along the whole execution flow of the error is what makes it easy (or at least much easier) to fix any bug, whether it’s in a monolithic application, a redundant microservice, or a serverless function that runs for a microsecond and is then gone – let’s see you reproduce that. With Ozcode, there’s no need to reproduce it. It’s all recorded for you.

Testing and debugging in production, better together

Testing and debugging are two inseparable facets of delivering robust, working software. For Dev/QA collaboration to be frictionless, developers need as much information about errors as possible, and it’s up to QA to provide it. A while ago, I maintained that a perfect bug report could be provided as a single shareable link, and that’s true for server-side logic bugs. If we now consider UX, we need a bit more data, and that’s what LambdaTest provides to complete the picture. LambdaTest can simultaneously test your UI across a large matrix of OSs and browser versions. If one of those combinations generates an exception, data about the exact scenario, configurations, and versions can be provided to Ozcode Production Debugger, where you can take the analysis down to code level. Being able to debug errors connected to specific OS/browser combinations at a code level will drastically cut down the time it takes to understand where the problem is and fix your code. This is truly end-to-end error resolution.

The post Supercharging Web Apps by Testing and Debugging in Production appeared first on Ozcode.

]]>
Finding the Bug in the Haystack: Hunting down Exceptions in Production https://oz-code.com/blog/production-debugging/finding-the-bug-in-the-haystack-hunting-down-exceptions-in-production Wed, 24 Mar 2021 06:00:08 +0000 https://oz-code.com/?p=17756 As companies move fast and break things, they then have to fix all those things they have broken. With machine learning you can find the bugs that matter, and with time-travel debugging you can then fix them.

The post Finding the Bug in the Haystack: Hunting down Exceptions in Production appeared first on Ozcode.

]]>

This post is co-published by Logz.io and is co-authored by Omer Raviv, Co-founder & CTO @ Ozcode, and Dotan Horovits, Product Evangelist @ Logz.io.

Software companies are in constant pursuit to optimize their delivery flow and increase release velocity. But as they get better at CI/CD in the spirit of “move fast and break things,” they are also being forced to have a very sobering conversation about “how do we fix all those things we’ve been breaking so fast?”

As a result, today’s cloud-native world is fraught with production errors and in dire need of observability.

Climbing the ELK Stack Everest

The depth and breadth of production errors in today’s cloud-native world are apparent from the vast number of exceptions that these applications generate. And how do companies address the issue?

Logs, logs, and more logs.

Modern applications generate mountains of logs, and those logs are generously peppered with exceptions. The sheer magnitude of exceptions makes it extremely difficult to weed out just the right ones. Which exceptions are new? Which are just noise? Which contain important information, such as an error in a newly deployed feature or a customer that’s having a terrible experience and is about to churn?

Let machine learning find the needle in a haystack of errors in Kibana with Logz.io

Let’s take a look at a real-world scenario. If you’ve ever worked at an eCommerce company, this will sound familiar.

The end of November rolls around.

Your friends and family are giddy about all the neat things they’re going to buy.

You are somewhere between stressed and having a full-blown panic attack. It’s your company’s biggest day of the year for sales. Your infrastructure and code had better be up for the task.

Black Friday hits, your website traffic is peaking, and the nightmare begins.

Despite all of your best efforts and meticulous testing, your “buy 2 get 1 free” coupon code simply DOES NOT WORK.

What now?

Let’s look at some logs.

I already mentioned that your logs are likely to contain loads of exceptions. How are you going to pick out the ones related to your coupon code? The open-source ELK Stack is popular for ingesting those mountains of logs and slicing and dicing them in Kibana Discover to understand the scenario at hand. Each log entry can contain structured data, so you can filter on a specific field or piece of contextual data. Logs can also be enriched with additional contextual data you can filter on, such as a user’s email, the browser type, etc.

In our Black Friday nightmare scenario, you might filter on the particular services that are flaking out, the relevant time frame, and on your coupon code field:

A typical investigation in Kibana Discover involves an iterative process of filtering and querying to narrow down the search context, which can be tedious and time-consuming when having so many outstanding exceptions in the environment.

Logz.io offers a Log Management service based on the ELK Stack that saves you the hassle of managing the open source yourself at scale. But it does much more than that. Logz.io’s Exceptions tab within Kibana Discover does a fantastic job doing what no human can – looking through the hundreds of thousands of log lines that contains exceptions and using machine learning smarts (Logz.io’s Insights Engine) to group them together to a concise aggregated view, which can be filtered in all the same useful ways we apply filters in Kibana Discover.

In our Black Friday incident, even after filtering out, we’re faced with more than half a million log hits. However, the Logz.io’s Exceptions tab in Kibana flags only 17 clustered exceptions in this search context. Let’s take a closer look at these errors:

In the Exceptions tab, we immediately spot a new exception – ArgumentOutOfRangeException – that started firing intensively during the incident time window. In a real-world, cloud-native system, this would filter out the noise and let you home in on the right exceptions.

You now know where to start your final assault, where to start looking. But where do you go from here?
 

Ozcode – see the code behind the logs

The logs are the telemetry of our software’s black box. It records what the system tells us it is doing. Now that we used Logz.io’s Insights Engine to find out which exception we should focus on, we’d like to open up the black box and get code-level understanding of that exception. This is where Ozcode’s exception capture comes in. Ozcode Production Debugger’s exception capture includes all the data we need: you can time travel to see line-by-line code execution, up to the point where your application threw an exception,  viewing locals variables, method parameters and return values, network requests, database queries, and more.

The ArgumentOutOfRangeException exception and call stack we saw in Logz.io’s Kibana don’t provide enough data for us to understand what happened. However, by simply jumping over to the Ozcode dashboard and filtering for the specific exception type and time range, we can delve deeper…

The Ozcode recording shows us a visual look at the code execution that led to the bug – every expression that was false is highlighted in red, every expression that was true is highlighted in green, and every variable and method call show their exact value. We can see we had a simple calculation error in our “Buy 2 Get 1 free” sale, which made us think the customer wanted to buy a negative number of items.

Now that we understand what happened, That’s an easy fix! No need to try to reproduce the issue on the local dev machine to solve the mystery.

Zoom in fast and fix things

The ELK stack, and Kibana in particular, gives us tremendously powerful tools to investigate logs. Using Logz.io’s machine learning-based insights, we can surface the relevant exceptions and related logs inside Kibana out of the endless noise and millions of logs that modern cloud-based systems generate. The Ozcode Production Debugger enhances this experience even further by giving us code-level observability and time travel recording to quickly understand the root cause behind each exception. You can combine that with additional telemetry such as metrics and traces to increase your system’s observability and enhance your troubleshooting capabilities.

Ozcode Production Debugger

 

Ozcode Production Debugger

The post Finding the Bug in the Haystack: Hunting down Exceptions in Production appeared first on Ozcode.

]]>
An Observability Platform for Developers https://oz-code.com/blog/devops/an-observability-platform-for-developers Thu, 18 Mar 2021 14:12:23 +0000 https://oz-code.com/?p=17805 Observability platforms plays a vital role in an enterprise’s tool stack, but they fall short of providing developers with the actionable data they need to resolve Production errors.

The post An Observability Platform for Developers appeared first on Ozcode.

]]>

Observability platforms play a vital role in an enterprise’s tool stack, providing DevOps/SREs and Production Support staff with a system-level view of their applications’ and infrastructure’s health and performance levels. By alerting the right DevOps and engineering staff to performance bottlenecks and live-site incidents, observability platforms help keep the company’s systems running smoothly to maintain the ever-important business continuity. However, the observability that these platforms provide is primarily at a system level. When a software error surfaces in Production, the people tasked with fixing it are developers. To resolve Production errors, developers need actionable data that enables them to reproduce and debug those errors, and that’s where the current state-of-the-art observability platforms fall short. They barely scrape the surface of the code-level observability that developers need. The performance metrics and stack traces that DevOps/SREs work with are ineffective and frustrating for developers who have to fix an urgent Production issue and only serve to create friction where collaboration is needed.

Ozcode Production Debugger introduces both a paradigm shift and a cultural shift in the realm of resolving Production incidents. By providing developers with the code-level observability they need, Ozcode turns Production Debugging into a monitoring discipline in which developers are empowered to actively participate as part of their day-to-day responsibilities. The rest of this post describes how Ozcode provides developers with the code-level observability they need to do an effective root-cause analysis of Production errors leading to a rapid resolution. It’s important to note that Ozcode Production Debugger and traditional observability platforms are not mutually exclusive but rather complement each other and are equally vital components of an enterprise tool stack.

Taking observability beyond the system and down to code-level

APMs such as New Relic, Dynatrace, AppDynamics, DataDog, and others have developed in recent years into full-fledged observability platforms. They include an enriched set of features to include capabilities like log analysis, real user monitoring, synthetic testing, error monitoring, and more. However, none of these platforms enable code-level observability, which is the crucial missing piece that allows developers and DevOps/SREs to collaborate and quickly resolve issues and prevent faulty deployments from reaching Production.

Ozcode Production Debugger presents a new paradigm for troubleshooting Production errors by turning Production Debugging into a monitoring discipline through the following key capabilities.

Autonomous exception capture replaces reproducing an error

Ozcode Production Debugger uses an agent that runs next to and monitors your application. When your application throws an exception, the Ozcode agent adds byte-code instrumentation to the code along the entire execution path from the initial interaction that triggered the exception to the line of code that threw it. Now, observability platforms also operate by adding instrumentation to your applications and infrastructure, but here’s the difference. Ozcode captures and records code-level Production data that is specific to the complete error execution flow that caused the exception. No observability platform provides that level of data. The Ozcode agent then transmits this debug data to the Ozcode server, where the relevant developer can analyze it independently of the live Production system.

Reproducing a Production error can be extremely challenging for several reasons:

  • Matching the scale and structure of Production in a parallel environment is usually not feasible (of possible at all)
  • Reproducing the exact user scenario that caused the error may be impossible
  • Matching the right source code to the current Production binary may be impossible
  • The ephemeral nature of microservices and serverless make it even more difficult for Production systems built on those technologies

By capturing the code execution flow of an error, Ozcode removes the need to reproduce an error. You debug the actual Production code where the error manifested in a completely non-intrusive way.

Ozcode Production Debugger - LEARN MORE

Time-travel debugging: the “Development experience” on Production code

During development, developers are used to debugging errors by stepping through their code with full visibility into their application’s runtime data. Doing the same in Production ranges from difficult to impossible, and observability platforms don’t even try to address this issue.

One way you might consider is to attach a remote debugger. There are tools on the market that let you connect to a live application for debugging. However, setting them up can be very complex, and company policies often forbid such connections for reasons of security.

And then, even if you were able to set up a remote connection to your Production systems, stepping through the code would require stopping the application flow with breakpoints. Again, company policies usually forbid this activity as it stops the application flow not only for the debugging developer but also for customers.

Ozcode Production Debugger delivers the “Development experience“on Production with Time-Travel debugging.

The detailed debug data stored in Ozcode exception captures provide the same code-level observability that developers are used to getting in their development environments. They can step back and forth through the complete error execution flow across the whole call stack with full visibility into:

  • Local variables
  • Method parameters and return values
  • Network requests
  • Database queries
  • Relevant log entries
  • Event trace across microservices

Moreover, Ozcode makes it easier for developers to understand what happened in the error execution flow through various visual aids. For example, red/green coloring for conditional statements, greyed-out text for code that is not executed, annotations providing the values of variables and method parameters within the body of the code, and more.

Ozcode Production Debugger - LEARN MORE

Using dynamic logging with tracepoints to make log-based debugging effective

Observability platforms may offer advanced log analysis as part of their enriched feature set. While the traditional way of troubleshooting with logs is better than nothing, it is NOT an effective way to debug Production issues for the following reasons:

  • Insufficiency – it’s impossible to predict exactly where an error will occur, so it’s equally impossible to ensure that you have diagnostic log entries in the right places of your code.
  • Distribution – logs from the multiple components of today’s complex software systems may be distributed between various sources, including files and databases. Piecing together the right logs to understand an error is extremely difficult.
  • Process – since there are never enough log entries present to debug an error, debugging-by-logs is a tedious, iterative process that goes something like this: analyze existing logs → formulate a theory for root-cause of the error → add logs to test the theory → rebuild → redeploy → reproduce the error. Usually, several iterations of this process are required before the root-cause is determined so a fix can be put in place.

Ozcode makes debugging-by-logs highly effective by addressing each of these issues:

  • Dynamic logging with tracepoints solves “insufficiency” – with Ozcode, there’s no need to predict where an error will occur. You can add tracepoints anywhere in the code and set up structured dynamic logs to output any data item for analysis or examine the application state every time the code passes through a tracepoint.
  • Log aggregation solves “distribution” – Ozcode assembles the log entries relevant to the error execution flow into one place, so there’s no need to dig through multiple sources to extract the relevant log entries.
  • Autonomous exception capture with time-travel debugging solves “process” – the process using Ozcode is completely different. Autonomous exception capture gives you the complete error execution flow, so there is no need to reproduce an error. Time-travel debugging lets you step through the error execution flow with code-level observability. Using tracepoints and dynamic logs, you can add and remove log output and examine application state anywhere in your code at will without having to rebuild and redeploy.

Observability platforms and Ozcode, better together

Ultimately, observability platforms may alert you to an error in your application and even point you to where in the code you might start looking; however, from there, it’s a guessing game. These tools do not provide the code-level observability into the error execution flow needed to do an effective root cause analysis. Metrics and dashboards cannot replace time-travel debug information required to fix Production errors.

Nevertheless, it’s important to emphasize again that Ozcode Production Debugger and observability platforms are complementary tools, and both are vital components of an enterprise tool stack. Observability platforms monitor your systems for performance metrics and resource usage to ensure a good level of business continuity during normal operation. However, Production errors are inevitable, and when they occur, they disrupt business continuity. That’s when Ozcode Production Debugger jumps in to restore it.

In other words…

Observability platforms maintain business continuity during normal operations. Ozcode Production Debugger restores business continuity when errors occur.

Ozcode Production Debugger

Autonomous Exception Capture
Never have to reproduce a bug again

Time-travel Debugging
Code-level data at your fingertips

Tracepoints
Add dynamic logs and view data anywhere in your code without having to redeploy

Ozcode Production Debugger - LEARN MORE

The post An Observability Platform for Developers appeared first on Ozcode.

]]>
Ozcode Live Collaborative Debugger for FREE so Everyone Can Use It: Dev, QA, DevOps, SRE https://oz-code.com/blog/general/ozcode-live-collaborative-debugger-for-free-so-everyone-can-use-it-dev-qa-devops-sre Sun, 07 Mar 2021 15:38:25 +0000 https://oz-code.com/?p=17717 To effectively resolve incidents in Production and pre-Production environments, Developers, QA, DevOps and SREs need to collaborate with code-level visibility into the data on those environments. That's why we launched Ozcode's collaborative Production Debugger.

The post Ozcode Live Collaborative Debugger for FREE so Everyone Can Use It: Dev, QA, DevOps, SRE appeared first on Ozcode.

]]>

Ozcode has been solving developer debugging pains for years. The tremendous adoption of our Visual Studio Extension showed just how badly developers need data to resolve bugs. But when we saw that debugging pains don’t go away when a build is deployed, we understood that solving debugging pains must be extended beyond the developer’s IDE. We launched Ozcode’s live collaborative Production Debugger a year ago with exactly that in mind. Here’s what happened.

A thousand people from small and large enterprises across industries and geographies have joined our early access program and started using the Production Debugger. Together, we are growing as a community of software professionals from various disciplines who are discovering that there’s more to debugging than initially meets the eye. We knew developers would come on board since they are the clearest winners of digging into Production environments and seeing why things are going wrong. Finally, extracting data from Production was easy – no more endless cycles with code changes only for deploying log files.

Debugging with log files - Ozcode

But we were also betting on others, and indeed they came. We found QA testers using the Production Debugger to provide (what we think of as) perfect bug reports. With Ozcode, gone are the days of, “It works on my machine.” And then, DevOps engineers started to get very interested. We believe this will be a DevOps trend in 2021 because nowadays when we meet with customers, DevOps engineers are taking a front seat in the discussions. DevOps engineers have seen how collaborating with developers on resolving Production incidents using the Production Debugger does wonders for DevOps KPIs like MTTR. Now, it’s not surprising that companies adopting the Production Debugger first try it out on test environments before installing it on Production. But we also found that many companies continue to use the Production Debugger on pre-Production environments in QA and Staging. This kind of “shift-left Production Debugging” also improves DevOps KPIs with fewer bugs making it through that final deployment to Production (think Defect Escape Rate).

Ozcode Production Debugger - LEARN MORE

With a thousand development, QA, and DevOps engineers running the Production Debugger on Production and pre-Production environments, the flow of feedback has been tremendous. Everything from UI to low-level algorithms has changed based on feedback we have received. We strongly believe that it’s this power of the community that helps us refine our platform to build a great product. As a token of thanks to our growing community, we are announcing the Always FREE Edition of Ozcode Production Debugger for teams of up to 5 users. We are convinced that debugging live QA, Staging, and Production systems should be available to everyone in the field and believe that this free offering will make debugging collaborative and much simpler for thousands more software professionals in the coming year. Our “Always Free” edition allows teams of 5 users to run 100 agents and debug a million events every month. This is an offering that can bring real value to an organization even before widespread adoption on its Production and pre-Production environments. Here are all the details of Ozcode Always Free.

If you’re ready to get on board, sign up here.

The post Ozcode Live Collaborative Debugger for FREE so Everyone Can Use It: Dev, QA, DevOps, SRE appeared first on Ozcode.

]]>
3 Reasons to Enable Debugging in Production https://oz-code.com/blog/production-debugging/3-reasons-to-enable-debugging-in-production Sun, 28 Feb 2021 20:25:40 +0000 https://oz-code.com/?p=17644 Software systems are incredibly complex and are full of defects. Sure, they’ll work most of the time, but every system has its day. Here are 3 reasons why debugging in Production should be as accessible and easy as possible.

The post 3 Reasons to Enable Debugging in Production appeared first on Ozcode.

]]>

Marc Andreesen’s famous, “Software is eating the world” was an “Aha moment” for many people. In his famous 2011 article, he showed how software has become the key component to delivering value in every industry. Software continues to grow exponentially in every aspect – development, testing, and deployment practices, tools, languages, architectures, networking, databases, are all moving forward at full speed. But with all this growth, one thing is certain. Nothing’s perfect. All these advances come with a cost. Software systems are incredibly complex and are full of defects. Sure, they’ll work most of the time, but every system has its day. Some of the more famous examples include spaceships crashing on Mars and stocks taking a tumble. But you don’t have to go that far. Services that build the basic fabric of our lives go down all the time, and this downtime can cost companies up to $5,600 per minute. So, here are 3 reasons why debugging in Production should be as accessible and easy as possible.

Reduce developer burnout

What developers want to do most is develop awesome code. They understand that part of that is debugging their code, but that’s OK. While they’re developing, debugging code is just another part of their day as they add lines of code, and then step through it when something goes wrong. Debugging in Production is different. By the time a bug is detected in Production, you don’t know which developer is responsible for the bug. Much of the time, you’re not even sure where the bug really is. Just because code throws an exception somewhere, doesn’t mean that’s where the bug is. So the developer tasked with fixing the bug has to stop developing awesome code and start the painful journey of trying to reproduce the bug, guessing the solution, adding code and logs, rebuilding, redeploying…and it doesn’t usually work first time. Modern software architectures like microservices and serverless only make things more difficult. The problematic piece of code may not even be running once the developer digs in and tries to solve the issue. This irritating process can be very arduous and time-consuming and therefore contributes to developer burnout.

Now imagine that these developers had access to tools that cut their Production debugging time by 80%. Even if you have DevOps engineers and IT managers gate-keeping Production systems, debugging Production errors on pre-Production environments like Staging or even QA can dramatically shorten the debug cycle and remove developer frustrations trying to fix Production errors.

Ozcode Production Debugger

Deliver more value

Over $10K of a developer’s yearly salary goes on debugging in Production. Part of the problem is that companies don’t have the right tools available, so developers waste a lot of time that costs companies a lot of money. Some studies show that developers can spend up to 25% of their time debugging in Production. If companies could get great Production Debugging tools for free, their developers would spend a lot less time on debugging and a lot more time developing the next great feature. So, while the company reduces the time developers waste on debugging (and developer burn-out in the process), it can also deliver more value.

We all win

We saw that enabling debugging in Production helps reduce developer burnout and enables companies to deliver more value. That means all those services we depend on won’t go down so much, and they’ll provide us with more and better features, all at a lower cost. Developers win, the businesses win, and in fact, we all win.

Ozcode Production Debugger

Fix bugs 5x faster

Debug microservices and serverless code

On-premises or in the cloud

The post 3 Reasons to Enable Debugging in Production appeared first on Ozcode.

]]>
Ozcode C# Riddle #1: What’s Your Type? https://oz-code.com/blog/net-c-tips/ozcode-c-riddle-1-whats-your-type Thu, 28 Jan 2021 16:13:42 +0000 https://oz-code.com/?p=17185 This is the first in our series of Ozcode C# riddles. In these riddles, we explore some of the deep, dark corners of the language to help you hone your problem-solving skills. Along the way, you’ll meet some C# debugging tools, and also develop some best practices for handling errors in C#. C# is a …

Ozcode C# Riddle #1: What’s Your Type? Read More »

The post Ozcode C# Riddle #1: What’s Your Type? appeared first on Ozcode.

]]>

This is the first in our series of Ozcode C# riddles. In these riddles, we explore some of the deep, dark corners of the language to help you hone your problem-solving skills. Along the way, you’ll meet some C# debugging tools, and also develop some best practices for handling errors in C#.

C# is a strongly typed language … for the most part. It uses static typing to enforce type safety at compile time, but since the introduction of the dynamic keyword in C#4, C# supports dynamic typing, and type safety is only enforced at runtime. When it comes to collections, things can get a bit tricky. Working with collections can involve anything from iterating through a simple list of items, to searching through a large and complex object graph. One way to traverse collections is to use an enumerator, and that’s in the core of today’s riddle.

Consider a collection of integers 1, 2, and 3. You can declare it as an array:

var arr = new[] { 1, 2, 3 };

You can also declare it using a generic List type (List<T>):

var list = new List { 1, 2, 3 };

Which declaration you use can have a huge impact on how your code runs.

The Riddle

What is the output of the code snippet below? (Answer below)

To solve this riddle, you need to know about:

  • collections, especially the process of iterating through them
  • the difference between value types and reference types

using System;
using System.Collections;
using System.Collections.Generic;

public class Program 
{
  public static void Main() 
  {
    var arr = new [] {1, 2, 3};
    var list = new List < int > {1 ,2, 3};

    var arrEnumerator = arr.GetEnumerator();
    var listEnumerator = list.GetEnumerator();

    MoveNext(arrEnumerator);
    MoveNext(arrEnumerator);
    MoveNext(arrEnumerator);

    Console.WriteLine();

    MoveNext(listEnumerator);
    MoveNext(listEnumerator);
    MoveNext(listEnumerator);
  }

  private static void MoveNext(IEnumerator enumerator) 
  {
    if (enumerator.MoveNext()) 
    {
      Console.WriteLine(enumerator.Current);
    }
  }

  private static void MoveNext(IEnumerator < int > enumerator) 
  {
    if (enumerator.MoveNext()) 
    {
      Console.WriteLine(enumerator.Current);
    }
  }
}
Enhance Visual Studio Debugging - Ozcode

The Solution

So, your knee-jerk response would be that the output is:

1
2
3

1
2
3

But that’s not the case.

If you don’t believe me, copy the snippet into your favorite IDE and run it.

So, what’s going on? On the face of it, in both cases, you’re just iterating through a set of integers. That may be true but iterating through an array is not the same as iterating through a generic List. All collections in C# have a GetEnumerator() method which returns an enumerator object that lets you iterate through the items of the collection. However, not all enumerators have the same type.

The behavior of the array is very intuitive. Invoking  MoveNext(arrEnumerator) three times iterates the array enumerator so it’s pointing to the last element, and getCurrent returns 2 as expected. So why doesn’t it work like that for the listEnumerator?

Well, the enumerator for a generic list is a struct:

public struct List.Enumerator : System.Collections.Generic.IEnumerator

And a struct is a value type.

Now, here’s the catch. In case you didn’t notice, we’re not iterating our two enumerators directly by calling their MoveNext methods, we’re doing it indirectly through our own MoveNext methods. When you pass a Value type to a method, the method doesn’t operate on the parameter directly, but on a copy of the parameter. So, when we apply MoveNext on the List enumerator (within our own MoveNext method), we’re iterating a copy of the enumerator rather than the original enumerator. This is known as boxing in C#. Consequently, the original enumerator remains at its starting point– before the first element of the list.

So, the output of this program is: (drumroll)


1
2
3

1
1
1

(Ba dah boom)

Don’t believe me? Check here.

Why doesn’t this happen for the array?

Since the array enumerator is a Reference type, when we pass it to our MoveNext method, the method does not create a copy, but rather operates directly on the object. Consequently, the array enumerator iterates through the integers to the last value which is returned with Current.

Why worry about enumerator types?

It’s rare to need to a collection’s enumerator directly. In my 10 years of experience programming in C#, I haven’t had to do that more than once or twice.  A more common (and easier) way to iterate through the elements of a collection (and a c# coding best practice) is to use a foreach loop which manages reference types and value types internally, so you don’t have to worry about it.


using System;
using System.Collections.Generic;

public class Program 
{
  public static void Main() 
  {
    var arr = new [] {1, 2, 3};
    var list = new List < int > {1, 2, 3};

    foreach(var i in arr) 
    {
      Console.WriteLine(i);
    }

    Console.WriteLine();

    foreach(var i in list) 
    {
      Console.WriteLine(i);
    }
  }
}
And now the result is as expected:

1
2
3

1
2
3
You really wanna check?

Main Takeaways

Your main takeaways from this riddle are:

  • Don’t use enumerators unless you really have to. Use a foreach loop instead.
  • When you pass a parameter to a method, make sure you know if it’s a Value type or a Reference type.

Ozcode - Join Us

 

The post Ozcode C# Riddle #1: What’s Your Type? appeared first on Ozcode.

]]>
Our Top C#, .NET, Production Debugging, Visual Studio Extension, Azure, and DevOps Blog Posts of 2020 https://oz-code.com/blog/general/our-top-c-net-production-debugging-visual-studio-extension-azure-and-devops-blog-posts-of-2020 Thu, 31 Dec 2020 18:37:35 +0000 https://oz-code.com/?p=16488 We have published dozens of blog posts throughout this crazy and challenging year to help us become better developers and better debuggers. As we all start debugging our lives from COVID into 2021, here’s a pick of our top 10 posts from 2020.

The post Our Top C#, .NET, Production Debugging, Visual Studio Extension, Azure, and DevOps Blog Posts of 2020 appeared first on Ozcode.

]]>

Start the countdown. 2020 is almost done, and we finally see the light at the end of this year-long tunnel. What a ride this has been! As we all scrambled for alcogel, face masks, and toilet paper, one definitive truth stands out in the world of software development.

There will always be bugs.

I can’t help but make this association. Look at what the mother of all “bugs,” COVID-19, has done to the mother of all Production systems, humanity. How different would the lives of so many people be right now if we had the right debugging tools (i.e., a vaccine) way back at the beginning of this year? It’s no different for software and all the Production systems that are at the very core of our lives. From essential utilities like electrical power and the internet to online gaming and entertainment systems, bugs will happen, bugs are destructive, and once bugs hit us where it hurts, it’s paramount to resolve them as quickly as possible.

Humanity is finally starting to debug itself from COVID-19, but here at Ozcode, debugging has always been at the core of our activity. Throughout this year, we have published dozens of blog posts that can help us all become better developers and better at debugging our software. Here is a pick of our top 10 posts published during 2020.

ASP.NET Framework has been around since 2002, living through Web Forms, MVC, and Web API. It has matured to the point that it offers proven methodologies that work well. In this blog post, we go through some of the most popular NuGet packages used in ASP.NET Core applications that will give you a running start on your projects.

What are those packages? >

Serverless architectures continue to take hold of the software industry. However, with the benefits of scalability, robustness, and decoupled functionality come debugging challenges similar to those we see with microservices. And these stem from the ephemeral nature of these short-lived units of execution. How do you debug code that throws an exception and then disappears? This is the challenge of debugging Azure Functions, but it can be just like debugging an error in your local IDE if you have the right tools. This post is based on a webinar we hosted earlier this year showing how to use Ozcode Production Debugger to debug serverless code in Azure Functions.

Show me how to debug Azure Functions >

Ozcode Production Debugger - LEARN MORE

Life (and programming) is so much easier when you have the right tool for the job. Here is a list of the top 10 .NET tools downloaded from NuGet Gallery.

Did you say 10 open source tools? >

Two of the biggest yearly software development surveys show C# and .NET in the top 10 picks of the software community. Whether you’re a C# master and .NET maven or a newbie to this branch of software development, there’s always a lot to learn. This blog will point you to some of the top resources you can use, whether you’re just getting started or are looking to delve deeply into the finer points of C# and .NET.

I want to learn >

Tools, tools, and more tools. We have many tools for debugging in Development, but Production systems pose many challenges for debugging. We usually turn to logs, but log files don’t cut it. You never have the right logs available, so you have to add more logs, rebuild, redeploy, and try again – usually several times until you solve an issue. This post highlights some of the top tools you can use for .NET debugging in Production.

I need those tools >

Debugging Production systems is critical for business. Estimates for the cost of Production downtime go as high as $5600 per minute, so clearly, when things go sideways on an eCommerce site, a stock trading system, or a lunar lander, fixing that bug is top of mind for everyone. Many of the tools and methods in use today are not effective in debugging Production systems. This post describes why these tools are insufficient and then goes on to describe the four pillars of Production debugging that an effective debugger stands on.

What are the 4 pillars? >

NuGet Gallery is the most popular repository on the web for open-source NuGet packages, delivering about a billion downloads every week. But, like many public open-source resources on the web, NuGet periodically suffers from outages. That’s when your builds begin to break. JFrog Artifactory is a DevOps solution for end-to-end management of binary artifacts, including NuGet packages. It can protect you from outages in NuGet Gallery and offers a host of other benefits for your .NET development with NuGet.

Tell me about JFrog Artifactory >

Production debugging with logs offers several advantages. Logs show you a sequence of events, they’re easy to filter to weed out errors, and they’re very reliable. But debugging with logs also presents challenges. You have to dig through mountains of distributed log files to find the log entries you want, and in practice, you never have enough logs. Consequently, debugging with logs is very tedious and ineffective. Dynamic logging with tracepoints offers a new paradigm for log-based debugging in which you can get the right logs, in the right place, at the right time – without having to rebuild and redeploy your application.

Show me how to add logs without rebuilding and redeploying >

Ozcode Production Debugger - LEARN MORE

Observability has become a hot topic when it comes to monitoring Production and troubleshooting Production errors. But the truth is that today’s typical observability tools can only go so far in resolving Production errors. They might point you in the right direction, but they don’t provide enough information to really get to the root cause of an error. For that, you need code-level observability.

How does code-level observability help me resolve Production errors? >

Infrastructure as Code has brought great advances to DevOps, making application deployment much more robust. Infrastructure can now be defined in structured file formats so deployments can be version controlled and run repeatably as a one-click process. This blog shows how you can deploy Ozcode Production Debugger as part of an IaC specification using C#. This post is based on a webinar we hosted earlier this year, which you can view at the end of the post.

Show me how to deploy Ozcode using IaC >

2021, here we come!

Ozcode – FIND. FIX. DEPLOY

Production Debugger
Bridging the gap between observability and debugging on QA, Staging and Production.

Visual Studio Extension
Powerful and intuitive local debugging that visualizes your code to the deepest level.

Ozcode - Disruptive Debugging Solutions

 

 

 

The post Our Top C#, .NET, Production Debugging, Visual Studio Extension, Azure, and DevOps Blog Posts of 2020 appeared first on Ozcode.

]]>
5 Habits for Highly Effective .NET Debugging https://oz-code.com/blog/net-c-tips/5-habits-highly-effective-net-debugging Thu, 24 Dec 2020 14:03:09 +0000 https://oz-code.com/?p=16182 Effective .NET debugging is not an art. It’s a science that can be mastered by acquiring these five habits when you approach a bug.

The post 5 Habits for Highly Effective .NET Debugging appeared first on Ozcode.

]]>

As developers, when we’re debugging software, we first have to understand what that piece of code does. Only then can we try to figure out want went wrong (i.e., what’s the bug) and come up with a fix. Over the years, I’ve met many developers, and some are better at debugging than others. When interviewing developers, I routinely give them technical exercises to assess their .NET debugging skills. I’ve found that developers who are effective at debugging typically write better code. The features they develop are more robust and complete. So, it shouldn’t surprise anyone that improving your debugging skills will make you a better developer and even help you further your career. But can anyone improve their debugging skills?

Can you improve your .NET Debugging skills?

Some people may think that being good at debugging is a gift; you either have it, or you don’t. In a great book I recently read (see below), the author spelled it out nicely:

“Debugging is more science than art. It can and should be methodical, and as such, can be taught.”

I love that. Debugging can be taught, and it should be a part of every software development course. We can all improve our debugging skills. The question is, “How?”

The 5 habits of software developers for highly effective .NET debugging

To improve your .NET  debugging skills, you need to think like a craftsman. You need to master the basics to perfection until they come naturally, almost effortlessly. However, forming good habits is hard. It requires time, practice, and diligence. As the saying goes, “There’s only one way to do a good job, and that is, to do a good job.” So, here are 5 habits you can develop that will make you a master of debugging:

  1. Reproduce consistently
  2. Understand what needs to be fixed
  3. Create tests that fail to verify the potential fix
  4. Continue debugging until all the tests pass
  5. Verify that the bug has been fixed in Production

If you follow this workflow, you will be able to capture and understand a bug and resolve it quickly, effectively, and completely. You may sometimes be tempted to skip a step. Don’t do it. Each step is designed to keep you focused and optimize your work so that the following steps will be effective. Skipping a step can lead you in the wrong direction, eventually forcing you to start over and repeat all the steps from the beginning.

Let’s dive in.

Reproduce consistently

The first thing about a bug that should concern you is how to reproduce it. There are four steps to this habit. At the end of this step, you should have two sets of instructions: a sure-fire way to reproduce the bug and the shortest way to reproduce it.

Find any initial steps to reproduce

You want to find the steps needed to make the bug occur. This is critical. If you can’t reproduce the bug, how can you fix it? Even if the error seems obvious and simple, you’d be surprised how these things can come back and haunt you from Production. Adding or changing code that doesn’t fix the bug may even introduce new bugs. I know, I’ve been there.

Ensure your method is robust

Once you’ve found the steps to reproduce the bug, you want to ensure it’s consistent. You should approach this like a QA engineer and execute your steps under different scenarios. If the bug does not reproduce every time, you’ll have to re-examine your diagnosis of the problem and tweak the steps so that the bug reproduces every time you go through them. This is crucial to understanding what is broken so you can really resolve the issue.

Find the shortest method

Once you can reproduce the bug consistently, you want to find the shortest way to do so. See if you can reduce the number of steps. For example, if a bug occurs when 9 items are added to an order on an eCommerce site, are all 9 items really required to reproduce the bug? Perhaps changing the order in which the items are added can reproduce the bug after the 3rd item. Having a quick way to reproduce the bug will help both you as the developer and QA to reproduce the bug and validate your fix.

Write down your steps as a repeatable script

I can’t stress this enough. You’ve got to write things down. It’s your way of communicating this critical step of reproducing the bug with the rest of your team. It can be in a work item, or a bug report, whatever works in your team. But if it’s not written down, it doesn’t exist. You may even forget the steps if you haven’t written them down.

So, to complete this step, you should have two scripts written down. The first provides a robust, sure-fire way to reproduce the bug. You (or QA) will use this script later to ensure the bug has really been fixed. The second is the shortest way to reproduce the bug. You’ll use this as you investigate the bug and develop your fix. You’ll probably have to go through these steps several times before you come up with your solution, so having a short-cut to reproduce can be really useful (as long as you have the robust, sure-fire script as your final validation of the fix).

Ozcode Production Debugger - LEARN MORE

Understand what really needs to be fixed

Before you dive into fixing a bug, you need to pause and really think about what needs to be fixed and how your fix may impact the entire system. I’ll give you an example.

Say you’re debugging a backend transaction that occasionally fails because it can’t write a log entry to a disk after completing an operation. You could fix this by adding a try/catch block around the code that writes to the disk. The operation would be complete. Failing to write the log entry to the disk may throw an exception, which you would catch, and your program would continue executing successfully. Great. Mark that one as DONE! On to the next issue.

Not so fast!

What if logging transactions to a disk is a contractual obligation your company has undertaken. Your customer needs those logs for whatever reason, and you are legally bound to provide them. So, you can’t just decide to “move on” if a transaction fails to write to disk.

Sometimes, you may not even be sure how the system should behave. A menu item in a WPF application doesn’t work for a specific customer. Should you continue to display the manu item in a disabled state or remove it altogether.

Every change to your code can affect other parts of the system. This is the “blast radius” of your fix. If your fix touches several modules, what are the side-effects to those modules and your system as a whole? Your attention to these details can be key here. You might consider bringing other team members into the picture, such as QA engineers, product managers, business analysts, UX designers, or anyone else who might be affected by your changes. This kind of consideration and collaboration will only serve to gain you the respect of your team members and others across the organization.

Once you have a good understanding of the problem domain and the expected behavior of the system, you can move on to the next step – writing a test.

Create tests that fail without your fix

You may ask why this bug you’re working on wasn’t detected sooner. While there may be different reasons, one thing is for sure. Nobody ever tested the specific scenario that caused the bug to surface. So, before you change any code, use that short script you created to reproduce the bug as a starting point and write a test that fails because of the error you’re debugging. This may be anything from a (suite of) unit test(s) to a more encompassing end-to-end test if necessary. Whatever the case, you should strive to narrow your focus to a very specific code execution flow so you don’t have to reboot your entire system to run the test.

Continue debugging until all tests pass

Now that you have a test suite, you can start modifying the code until all the tests pass. You get a lot more out of these tests than you think.

  1. Your tests are a coded spec of your system
    By going through your tests, one can understand how your system should work, and the tests are a way to verify if the spec was implemented correctly
  2. You know when you’re done
    Once all your tests pass, you have fixed the bug. There is no guessing or estimation of completeness of the task. Note, however, that creating enough unit tests to cover all edge cases of the code your debugging is a bit of an art. You may find yourself adding more tests until you are confident that a feature is complete and thoroughly tested.
  3. You know that your fix doesn’t break anything else
    If all bug fixes are verified with a suite of tests, then if your fix breaks something else, those tests will fail. This is where these habits start to compound as you accumulate more and more value from your tests over time. The tests you write today will protect your fix from a new bug that turns up tomorrow.

The 6th habit for effective .NET Debugging

Following those five habits of high-performance debugging form the basis of good software development. Once you have mastered them, you can take the next step to multiply your effectiveness. To achieve the next level of mastery, you need to find the tools that will enable you to work faster:

A unit test runner: most IDEs have this capability either built-in or through extensions. Personally, I love solutions that automatically run unit tests every time you save a file. If you just broke something, you’ll get instant feedback.

CI/CD: Automated build and deploy processes are pillars of a successful DevOps adoption. If you’re not doing it yet, this is a good time to start. And if you are, make sure your CI server runs your tests for every build. If any of your tests fail, you don’t want to push that build to Production.

APM/Error monitors: Reproducing Production errors can be very difficult. An APM or Error Monitor can point you in the right direction with a stack trace or contextual data that guides you when writing that robust script you need to reproduce an error. It certainly gives you more to go on than just a user’s description of what went wrong.

Logs and analytics: Log files contain tons of information. The right log analysis tools will let you slice and dice your logs to get actionable insights out of them. Once you can piece together what happened around your bug, you can start working on your robust script to reproduce it.

Ozcode Production Debugger - LEARN MORE

Highly effective .NET debugging in Production

To most developers, debugging is strongly identified with putting breakpoints in your code and then using F10 and F11 to through lines of code using an IDE such as Visual Studio while inspecting the call stack, local variables, threads, logs, events, etc. We all do that. However, you can’t do that in Production. You can’t put a breakpoint in live code and freeze an application that’s serving your customers. So, reproducing a bug in Production always involves guesswork.

Let’s remove the guesswork.

About 2000 words ago, I mentioned the first habit of highly effective debugging that you should master – consistently reproducing the bug. If you think about this methodically, there are a few things that can help you discover where your program logic breaks.

  1. Complete code execution flow of the bug
  2. Database queries and network request that were sent
  3. The state of the software, from static variables to local variables of the functions
  4. If the system threw exceptions, which exceptions, where and how we got there
  5. Relevant log entries

That’s exactly what Ozcode Production Debugger provides. Ozcode’s autonomous exception capture records all the relevant information leading up to an exception. You can then step through your code with full time-travel debug information,…

…and even add tracepoints to create dynamic logs providing code-level visibility to locals and variables anywhere in your application – without having to rebuild a new version and redeploy your application…

…basically taking all the guesswork out of .NET debugging on Production systems.

This post was inspired by Michael Shpilt’s book, “Practical Debugging for .NET Developers,” which gives an amazing breakdown of tools and techniques that will make you highly effective when debugging .NET applications.
Practical Debugging for .NET Developers

Ozcode Production Debugger

Autonomous Exception Capture
Never have to reproduce a bug again

Time-travel Debugging
Code-level data at your fingertips

Tracepoints
Add dynamic logs and view data anywhere in your code without having to redeploy

Ozcode Production Debugger - LEARN MORE

The post 5 Habits for Highly Effective .NET Debugging appeared first on Ozcode.

]]>
Bridging the DevOps/Development Observability Chasm to Boost DevOps KPIs https://oz-code.com/blog/devops/bridging-the-devops-development-observability-chasm-to-boost-devops-kpis https://oz-code.com/blog/devops/bridging-the-devops-development-observability-chasm-to-boost-devops-kpis#comments Thu, 10 Dec 2020 12:23:09 +0000 https://oz-code.com/?p=15921 In many companies, DevOps adoption is hindered by a chasm between DevOps and Development. Bridging that chasm with a Production Debugger improves DevOps KPIs.

The post Bridging the DevOps/Development Observability Chasm to Boost DevOps KPIs appeared first on Ozcode.

]]>

DevOps has become mainstream. No doubt about it. Everyone’s doing DevOps these days. Or so they say. And yet, in many companies, DevOps has meant nothing more than creating a position called something like “DevOps Engineer” or “Head of Delivery,” and assigning it to someone in the Ops team. If you ask developers in these companies what DevOps is, they will probably start talking about IT, infrastructure as code, configuring build and release automation tools, maintaining and monitoring production deployments, etc. The different teams continue to work in silos, and all that has happened is that the Ops/Development chasm that existed earlier has evolved into a DevOps/Development chasm.

That’s not DevOps.

DevOps is not just a role, position, or specific function. It’s an organizational culture, a set of best practices and tools, a complete mindset that companies need to adopt in order to deliver better software faster. One of the tenets of a successful DevOps adoption is having close collaboration between Operations and Development. This post will show how building and maintaining a DevOps/Development bridge to cross that chasm can help teams perform better and improve several classic DevOps KPIs.

DevOps is broken - the DevOps/Development chasm

Different studies repeatedly show that companies that successfully adopt DevOps consistently deliver better software faster. What that means is that they’re performing better on a set of DevOps KPIs. For example, the diagram below taken from the Accelerate State of DevOps 2019 Report shows that companies evaluated as “Elite” adopters of DevOps can deploy changes on demand within an hour with a failure rate of less than 15%. And if service is disrupted, they can restore it within an hour. On the other end of the spectrum, “low” level adopters take months before deploying a change. They deploy new versions once a week at best, about half of the deployments fail, and it can take up to a month to restore service.

State of DevOps

Source: Accelerate State of DevOps 2019 Report, DORA (Google Cloud)

One of the reasons that companies on the lower end of the spectrum don’t perform as well is the lack of DevOps/Development communication. The different teams still work in silos. Developers push changes to source control. Automated systems then run tests, build versions, and promote those versions up the pipeline through QA and Staging until they finally reach DevOps for deployment to Production. But by that time, the developers who pushed the changes for that build are already several versions ahead or working on a different project altogether.

Similarly, when something goes wrong in Production, DevOps uses observability tools to gather data snapshots of logs, metrics, and traces (the pillars of observability) and throws them over the proverbial wall back at developers. But developers don’t operate at the level of logs, metrics, and traces. They may not know how to leverage that kind of data, they may not have access to the DevOps engineers who produced it, and they certainly don’t have access to Production systems. They can only work with what has been dumped on them. Developers operate at a code-level. To do an effective root cause analysis of Production errors, they need code-level observability into those Production systems, which they do not get. In this sense, DevOps is broken in companies with low adoption because the  continuous cycle of feedback and communication between DevOps and development is broken.

Bridging the chasm with the four pillars of production debugging

Let’s examine how the four pillars of production debugging can bridge the DevOps/development chasm and fix the broken DevOps cycle.

Autonomous exception capture means errors are detected as soon as they occur and are captured together with all the relevant data. Developers don’t have to spend any time or energy trying to reproduce an error that happened in Production on their development machines to understand what went wrong. They don’t need anything from the DevOps engineers.

Code-level observability provides developers with the Production data that they need. Regardless ofthe scale of the Production system or the complexity of the scenario that caused the error, the developer has the exact error execution flow along with all relevant line-by-line data to examine. There’s no need for DevOps to collect anything and share it with developers.

Time-travel debugging. With code-level data and the complete error execution flow, developers can step through the Production code line-by-line to evaluate the root cause of the error, just like they’re used to doing on their development builds. Again, the feedback from Production is inherent in the error capture. Developers know exactly where the exception was thrown and have all the data they need built into the system across the complete call stack.

Collaboration is an integral component of the DevOps/Development feedback loop. Enabling focused communication between developers and DevOps, pointing at specific lines of code and the relevant data around them promotes effective collaboration between the teams towards fixing Production errors.

Collaborative .NET Debugging - Ozcode

Boosting DevOps KPIs

In a successful DevOps adoption, teams work together in a harmonious rhythm towards that ultimate goal of delivering better software faster. Progress towards that goal is measured through a variety of KPIs that are typical in the industry. Let’s see how bridging the DevOps/development gap improves some typical DevOps KPIs.

Change Failure Rate

This metric is the number of deployments that fail divided by the total number of deployments. As you increase your deployment frequency (the “faster” part of “better software faster”), you may find your change failure rate increasing. If that happens, you should consider scaling down your deployment frequency and look more carefully at the issues in your code, especially if they recur from one deployment to the next. The term “Production” Debugger is a little bit misleading because you can install one in your pre-Production systems too. Running a Production Debugger in your Staging and even in your QA environment can shift left detection of flaws in your deployments. The closer your staging environment is to your production environment, the more effective it will be in surfacing errors before they reach Production. As a result, more deployments will succeed, and your change failure rate should decrease.

Mean Time to Detection (MTTD)

This KPI measures how long it takes you to detect an issue once it has occurred. It’s easy to see how a Production Debugger that uses autonomous exception capture can reduce MTTD for Production software failures. As soon as an exception is thrown, it appears on your dashboard and is immediately detected.

Mean Time Between Failures (MTBF)

This metric is an indicator of the quality of your Production software. The fewer bugs in Production, the longer the time between failures. Just like detecting bugs in your pre-Production systems can improve your change failure rate, it can also improve your MTBF. By shifting left your handling of software issues, fewer bugs will reach Production, and MTBF should increase.

Mean Time to Recovery (MTTR)

MTTR reflects the average time it takes you to recover from a software failure and resolve the issue. Now, it’s well known that the further up the CI/CD pipeline a bug is detected, the more difficult it is to fix. In other words, it’s much easier to fix a bug in your development environment than one in Production. But what if you could now approach Production issues in the same way you approach bugs in your development IDE. That’s exactly the edge that a Production Debugger gives you. Time-travel debugging with code-level observability gives a development-like experience and can cut debugging time by up to 80%. This can certainly cut this very critical KPI down. When Production downtime can cost thousands of dollars a minute, every improvement in MTTR directly impacts the company’s bottom line.

Defect Escape Rate

This is another metric that can be managed by shifting left your production debugging. Defect escape rate is the ratio of bugs found in Production to bugs found in Production and pre-Production systems. If your defect escape rate is too high, you might just be deploying too frequently and not putting enough emphasis on code quality in QA and Staging. It’s clear that testing more in QA and using a Production Debugger on your Staging environment can reduce your defect escape rate.

Customer Tickets

At the end of the day, it’s all about keeping your customers happy. Happy customers translate into more revenue from sales and fewer expenses on addressing issues. If you use a production debugger to prevent issues from getting to Production and fix them as quickly as possible if they do, then you should be seeing fewer customer tickets. While you may want to qualify which types of customer tickets to include for this metric, it can be a good overall assessment of how successfully you have adopted DevOps.

The role of a Production Debugger in bridging the chasm

There are two factors to the DevOps/Development chasm that is breaking DevOps. One is the lack of code-level observability that developers need in order to explain the logs, metrics, and traces that DevOps collects when things go wrong in Production. The other is the DevOps/Development disconnect when these two groups work in silos. It basically amounts to a poor level of feedback from DevOps back to development, both at a code level and at a human communication level. The role of a Production Debugger is to bridge the chasm on both factors by shifting left to detect and handle issues in pre-Production environments and providing the observability and means for effective communication on issues that do crop up in Production (and we know that they will). At the end of the day, bridging that chasm enables you to release faster while baking quality into your code, and you’ll see the effects as those classic DevOps KPIs improve over time.

Ozcode Production Debugger

Autonomous exception capture
Instantly detect exceptions in Production and reduce MTTD

Code-level observability
Tie incidents directly to code and reduce MTTR

Time-travel fidelity
See the value of all variables and method calls across the whole call stack for every line of code

Ozcode Production Debugger

 

The post Bridging the DevOps/Development Observability Chasm to Boost DevOps KPIs appeared first on Ozcode.

]]>
https://oz-code.com/blog/devops/bridging-the-devops-development-observability-chasm-to-boost-devops-kpis/feed 7
8 Must-Know NuGet Packages for an ASP.NET Core Application https://oz-code.com/blog/net-c-tips/8-must-know-nuget-packages-asp-net-core-application Thu, 03 Dec 2020 12:20:48 +0000 https://oz-code.com/?p=15785 Here are some of the most popular NuGet packages used in ASP.NET Core applications. Use these packages to get a running start on your project.

The post 8 Must-Know NuGet Packages for an ASP.NET Core Application appeared first on Ozcode.

]]>

When a new framework or technology first appears, it’s like the wild west. Everyone’s doing their own thing, trying to figure out the best way to build a product. That’s not the case with the ASP.NET framework. We’ve been going at it since 2002, living through Web Forms, MVC, and Web API. We made every mistake possible and learned from it. I’m not saying we figured everything out and achieved perfection, but we do have experience and proven methodologies that work well. In this article, I’ll go over some of the most popular NuGet packages used in ASP.NET Core applications. Those packages became popular for good reasons, and using them will give you a running start on your projects.

1. Swahshbuckle.AspNetCore

Swashbuckle is the toolset that adds Swagger support to your application (now called OpenAPI). If you’re building a REST Web API server, Swagger provides you with some very valuable services. It will automatically generate a JSON object that describes your entire API. This includes the endpoints, the models, and the possible results. From that JSON, Swashbuckle produces a beautiful UI and documentation that you can view when entering the default address mysite.com/swagger. Here’s what it looks like for the Ozcode Production Debugger server:
Ozcode Server Swagger - Ozcode

Besides the automatic documentation that is always up to date, you can also generate clients automatically. You’ll be able to create a DLL which you can reference in your C# client application. Once generated and referenced, instead of using HttpClient, just call methods in the generated client project.

Find Swashuckle.AspNetCore  on NuGet Gallery

2. AutoMapper

When dealing with APIs, you’re constantly going back and forth from database models, to DTO models. DTO stands for Data Transfer Object and it’s when you want the client to use a different schema from the one in your database. There are many reasons  to do that. For example, you may want to provide less information to the client, organize it differently, and perhaps, most importantly, to decouple the database from the REST service. After all, if you change something in your server, you don’t necessarily want to change all your clients along with it.

Automapper provides an easy way to transform one type of object to another. In our case, it will usually be a persistent model to a DTO model.

At startup:

var configuration = new MapperConfiguration(cfg =>  
{
    cfg.CreateMap<Bar, BarDto>()
        .ForMember(dto => dto.Address, expression => expression.MapFrom(bar => bar.UserAddress));
});

In business logic, executing the transformation is as easy as:

var barDto = mapper.Map<BarDto>(bar);

 

Find AutoMapper on NuGet Gallery

3. Entity Framework

I can’t possibly write a post like this without mentioning EntityFramework (EF) and EntityFrameworkCore. It’s the most widely used ORM in .NET by far, with over 100 million downloads for each package. The basic usage is to be able to map C# objects to database entities (tables). Then, you can use LINQ to query these database entities like regular collections. EF produces SQL under the hood, and the whole experience is seamless and quite magical. In addition to Microsoft’s SQL Server, Entity Framework also works with PostgreSQL, SQLite, CosmosDB, MySQL, Oracle, and others. But working with EF isn’t the only option to work with databases. You can go old-school and work with raw SQL with ADO.NET and stored procedures. It’s going to take much longer to develop, but you can achieve crazy performance. Of course, stored procedures have their own issues when you have too many of them (complexity, debuggability, extensibility, etc.).
Find EntityFramework and EntityFrameworkCore on NuGet Gallery

Enhance Visual Studio Debugging - Ozcode

4. Dapper

Dapper is another alternative to Entity Framework. It provides a way to write raw SQL and easily map it to C# objects. Kind of like ADO.NET, except for the mapping to objects part. “Why use it?” you might ask. Performance is the main reason, but Dapper is also very flexible. Dapper is much faster than EF in certain scenarios and even a little faster than ADO.NET raw SQL, according to this benchmark. So Dapper is somewhere between Entity Framework and ADO.NET. You still have to write SQL queries, but it’s much easier to use than ADO.NET. You can choose to use Dapper and Entity Framework together. The performance-sensitive parts can be developed with Dapper and the rest with EF. Here’s a small taste:
string sql = "SELECT TOP 10 * FROM OrderDetails"; 
using (var connection = new SqlConnection(FiddleHelper.GetConnectionStringSqlServerW3Schools())) 
{ 
      var orderDetails = connection.Query(sql).ToList();      
      FiddleHelper.WriteTable(orderDetails); 
}
Find Dapper on NuGet Gallery

5. MediatR

MediatR is the most popular mediator pattern implementation in .NET.

Mediator Pattern - Ozcode “What’s the mediator pattern?” you might ask. It’s a way to send messages between classes with no dependencies on one another. Those messages might be classified as notifications, commands, or requests/responses. They might be synchronous or asynchronous. Here’s an example of a simple notification. First, install the packages MediatR and MediatR.Extensions.Microsoft.DependencyInjection. Add MetiatR in Startup services:
public void ConfigureServices(IServiceCollection services) 
{ 
    // ... 
    services.AddMediatR(typeof(Startup)); 
}
Create a notification message:
public class Ping : INotification { }
Create a handler for the notification (you can have multiple)
public class PingHandler : INotificationHandler{ 
    public Task Handle(Ping notification, CancellationToken cancellationToken) 
    { 
        Debug.WriteLine("handled"); 
        return Task.CompletedTask; 
    } 
}
Now you can publish the notification anywhere:
public class MyController : ControllerBase 
{ 
    private readonly IMediator _mediator;
public SignInUpController(IMediator mediator) { _mediator = mediator; } [HttpGet] public async Task Foo() { await _mediator.Publish(new Ping()); return Ok(); } }

Find MediatR on NuGet Gallery

Enhance Visual Studio Debugging - Ozcode

6. RestSharp

RestSharp is an HTTP client. It allows you to make HTTP requests, much like the built-in HttpClient. Except that it’s actually simple and convenient. Here is an example. I’m sending a simple POST request to a server. Here’s how it looks with RestSharp:

var client = new RestClient("https://localhost:5003/"); 

var request = new RestRequest("Login/SignUp", DataFormat.Json);
request.AddJsonBody(new SignUpViewModel() { Email = "aaa@gmail.com" });
SignUpResponse response = await client.PostAsync<SignUpResponse>(request);
Console.WriteLine($"response = {response.Token}");

Nice, clean, and intuitive, right?

On the other hand, here’s how it looks with HttpClient:

var data = new SignUpViewModel() { Email = "aaa@gmail.com" }; 
var client = new HttpClient();
var dataAsString = JsonConvert.SerializeObject(data);
var content = new StringContent(dataAsString, Encoding.UTF8, "application/json");
var respone = await client.PostAsync("https://localhost:5003/Login/SignUp", content);
var resultStr = await respone.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<SignUpResponse>(resultStr);
Console.WriteLine($"response = {result.Token}");

With HttpClient, you have to use a JSON serializer like Newtonsoft.Json, not to mention that the code looks way worse in comparison.

By the way, RestSharp doesn’t have a dependency on other libraries. This means you don’t have to worry about version conflicts with Newtonsoft.Json and alike.

Find RestSharp on NuGet Gallery

7. Polly

Polly is a wonderful fault-handling factory. It allows you to create policies on how to handle your faults. Do you want to retry three times? No problem. Do you want to add to a particular queue after something fails exactly 17 times? You can do that as well. If you want different behaviors for different errors, that’s possible. Here’s a simple example:

// Retry multiple times, calling an action on each retry  
// with the current exception and retry count 
Policy 
    .Handle() 
    .Retry(3, onRetry: (exception, retryCount) => 
    { 
        // Add logic to be executed before each retry, such as logging 
    });
Find Polly on NuGet Gallery

8. protobuf-net

When we talk about serialization, we are usually thinking about JSON or XML. But neither of those are going to be the best performing serialization by a longshot. The most performant serialization is going to be binary. Something completely incomprehensible by humans. protobuf-net is exactly that—an extremely fast binary serializer. If you’re familiar with gRPC, then you probably know that it uses protobuf under the hood. That’s not the only use case, though. There are many scenarios when you might want a fast serialization protocol. Note that without gRPC and their .proto files, protobuf will be pretty hard for versioning. You won’t be able to easily add or remove properties from your serialized objects and have the same API support different versions. Other alternatives for fast binary serializations are FlatBuffers and MessagePack. MessagePack, for example, does support schema changes and allows versioning support. Flatbuffers has other advantages, like direct access to a part of the serialization without unpacking everything.

Find protobuf-net on NuGet Gallery

NuGet packages worth a special mention

There are many more popular NuGet packages. I couldn’t mention everything, but here are some that you should probably be familiar with:
  • Json – The most popular community NuGet package of all times. It was even included automatically in some older versions of ASP.NET. But because of various reasons (performance, version conflicts), Microsoft made the switch to System.Text.Json, which is the default JSON serializer in the latest versions of ASP.NET Core.
  • Logging packages – Some of the most popular NuGet packages are logging frameworks. These include Serilog, NLog, log4net, and Extensions.Logging.
  • Queues – Queuing frameworks are extremely powerful, and most applications make use of some queue technology or other. Some of them are Kafka, Azure Queue, and RabbitMQ.
  • Unit test frameworks – Also very useful to know both testing frameworks and mocking frameworks. The first include xunit, NUnit. The latter includes Moq and FakeItEasy.
  • Caching is an integral part of modern applications. In this regard, Redis is worth knowing.

Ozcode Visual Studio Extension

Elevate LINQ debugging with visibility, clarity and insights into your queries.

Time travel to see how your code will execute before you step through it.

Heads-up display gives you powerful visualizations so you can instantly understand what’s happening in your code.

Data tips provide deep insights into your data letting you drill down to any level in a data object.

Enhance Visual Studio Debugging - Ozcode

The post 8 Must-Know NuGet Packages for an ASP.NET Core Application appeared first on Ozcode.

]]>