Wednesday 4 December 2013

Ray Gun Post Panic Recover

Ok so I have created my first Go open source package I can add back to the community.

go_raygun
Usage guide can be found at the bottom of this post.

That being said, it is a working progress and any improvement suggestions are welcome, I will be expanding it to cover more areas.

In this blog I will be explaining what I have learnt from the Go 'defer, panic and recover', Go's runtime package, and Ray Gun.

First RayGun is a real time error reporting cloud service that can be set up in under 5 minutes, as they say anyway. The benefits of this application are greater than what I am using it for.

There are the many supported languages '.Net, Java, Python....' but they also provide a REST JSON endpoint here. This is what I use to post the messages to RayGun.

Secondly defer, panic and recover. There is a good blog on how it works here. I will explain more later in the blog on how I am using it.

Third and final the runtime package in Go. The two functions I use are runtime.Caller and runtime.Stack.  The Stack does what it says, it returns a byte array stack for what ever byte length you set.

stack := make([]byte, 1<<16)
stack = stack[:runtime.Stack(stack, false)]
Deconstructing this it does a couple of things. first it makes an object called stack of a byte array with length 1<<16, the 1<<16 syntax is short hand for binary integer to the power 16. I am using the runtime.Stack function. This populates the stack object created with current stack tract.

note: There is also the ability to run a stack tract from debug.Stack. The way I have explained above is the preferred Go way.

The Caller function allows you to get the line and filePath from the stack. You also have the ability to skip a set amount of callers from top of the stack. I am setting the caller to skip 4 levels.
_, filePath, line, _ := runtime.Caller(4)
 The reason I am skipping 4 is so that I return the Caller from where the panic happened. The comes back to explaining how I am using defer, panic and recover.

defer: If you are from a c# background like me it is similar to a finally block. defer will always happen at the end of the function no matter what happens in child functions. The most common use of this is opening connections. As soon as you open a connection you create a defer that closes the connections.

panic: A panic is raised when a runtime exception happens. When a panic happens it stop on that line of code and ends the function. (any defer's that are on that method will still be called, it is important to not set any defer's in this method if you are using this goRayGun package as it will return an incorrect value from runtime.Caller)

recover: The recover function can be called in defer via a inline if statement.
if r := recover(); r != nil { }
Recover will check to see if a panic has been raised. r is of type interface and needs to be type cast to be used. In Go you can call a panic passing in an object. However if you get a runtime panic it will always return an error object with the error message.
errorMsg := r.(error).Error() 

go_raygun set up


As you will be able to see in the from the github link at the top there is an example of how to use the package. In short though, you need to set up the RayGunConfig.json with your application and RayGun settings and save this into the same directory as code you are using it for. The first thing you have to do is create an instance of the package. I have added an interface for the package if people want to use it, (this will enable mocking as explain in my last blog and will be helpful when testing your application). I have not used the interface in my example as wanted to keep it as simple and small as I could.

Before you can use the RaygunRecovery function you must first call LoadRaygunSettings. This only has to be done once from your main function as long as you declare a package global instance of the goraygun package.

Once it is set up you can use the RaygunRecovery in a defer before you call any function that could panic.

An extension I am looking to do is pass back an error object from the defer. This could be done by passing an error pointer object to the defer. I will keep you updated, but if anyone would like to create a fork of the repo could work paired on it.

Note: I have made some amendments.

1) It is now possible to have one defer in your code and any functions below will be caught by the RaygunRecovery.

2) I am now parsing the stack trace into an array of stack events, passing them to Raygun. This helps in determining where the panic came from and the root it had taken. 

Monday 28 October 2013

Go Package set up with testing in mind

Hi all,

I am going to attempt to explain how to set up a package in Go with the option to Mock the methods in the package for testing. I say attempt because I am still learning Go and the best practice way of doing things, so apologies in advance.

This link to stretchr/testify is required for the following examples. A massive thanks to these guys for making my life a lot easier.

I am going to use very simple examples and more comment the structure than anything, will post an update of code once completed.

So first thing, want to create a package that I am for simplistic reasons going to call 'mypackage.go'.

In this file we are going to create an interface that will expose our public methods outside of this package.

type IPackage interface{
     Method1(string obj) error
     Method2(string obj) string
}

Now we need to create a struct to implement this interface

type Package struct {
}

Next we create the functions we are going to use, and make sure you use a pointer to the struct you have just crated.

func(p *Package)Method1(string obj) error {
        //add all the code needed here
}

func(p *Package)Method2(string obj) string {
        //add all the code needed here
}

Ok we have now created all we need to on our package, we can move onto implementing this in our code that is going to need testing, by mocking of this package.

In a new go file first thing we need to do is create a reference to the package. Create a var to the interface package

var package IPackage

Now instantiate the interface with the concrete struct.

package = new(Package)

Using this object you can access the functions we created.

err := package.Method1("hello")
string := package.Method2("world")

So far we have created a package with an interface for public methods, then used this package and the exposed methods in our code.

The next thing we require to do is test our code in our app, not in the package. To do this we require the ability to Mock the Methods in our package, giving set responses.

In the standard Go testing file import the stretchr/testify API.

Now we need to set up our mocking on the package and methods so when they are called in our app code we can control the response.

So lets create a mock object struct.

type MockPackage struct {
       mock.Mock
}

Next create a local var of our struct

var mockPackage *MockPackage

Next we set up the methods we want to mock. This only need to be done once for each method and just sets how it takes the arguments in and what it is set to return.

func(p *MockPackage)Method1(string obj) error {
       args := p.Mock.Called(obj)
       return args.Error(0)
}

func(p *MockPackage)Method2(string obj) string {
       args := p.Mock.Called(obj)
       return args.Get(0).(string)

Finally we get onto the fun bit. Using these mocked methods in our tests, setting the expected results, enabling us to test the areas that we really want to test in our code and not the package code.

lets create a test

func TestMethod(t *testing.T){

       mockPackage := new(MockPackage)
       package = mockPackage

       mockPackage.Mock.On("Method1", mock.Anything).Return(fmt.Errorf("mock error"))

       //now do your code here, if's, loops.....logic that need testing in your app.
       err := someMethodtoTest()

      //can use testify to assert variables.
      assert.NotNil(t, err, "should have found error")

       assert.Equal(t, true, mockPackage.Mock.AssertNumberofCalls(t, "Method1", 1), "Method1 not called the correct amount")

}

The first thing you need to do is 'override' the real object calls with the new Mock object. This is done by creating an instance of the Mock object and then setting the real object to it. This will make it so that every time the real object is called it will use your Mock methods instead.
The Mock methods are then each set up meaning that when in the code "Method1" is called and containing anything as its variable it will return an error. Then we call the code in our app that we want to test. Lets say our code we want to test is that when our Package Mehtod1 is called and returns an error, we want to bubble that error up to this method. Using the assert.NotNil method checks the error returned.

The second assert is very useful so I have given an example. It uses two asserts in one. First it does an Equals assert, then it uses a second assert to gain the count of the method called.

There are many more examples on their Git hub site and API documentation, this as explained more of a simple set up of your package and how to use in code and tests.

Hope this has helped. comments are always welcome. I will be uploading code snipping as soon as I can.