website

#astro#js#html#css

git clone https://git.pyrossh.dev/website

木 Personal website of pyrossh. Built with astrojs, shiki, vite.


src/posts/eyecandy-golang-error-reporting.md
2f32cac 1
---
2f32cac 2
title: Eyecandy golang error reporting
2f32cac 3
description: Better error message logging in golang
2f32cac 4
pubDate: 2016-09-17
2f32cac 5
tags:
2f32cac 6
  - golang
2f32cac 7
  - error
2f32cac 8
  - formatting
2f32cac 9
published: true
2f32cac 10
---
2f32cac 11
2f32cac 12
We at playlyfe wanted to get an email report as soon as an error occurred on our production servers. Since golang does not have
2f32cac 13
stack traces with its inbuilt error mechanism we had to find a quick and simple solution which wouldn’t require too much refactoring
2f32cac 14
of our existing codebase. So this is how we went about accomplishing this task. First we decided to wrap our errors so that we can get the runtime stack whenever an error occurs.
2f32cac 15
2f32cac 16
We first started using this library https://github.com/go-errors/errors
2f32cac 17
but soon found out that it wasn’t exactly suited for our use case. So we created this minimalistic and easy approach to wrap all our
2f32cac 18
existing errors. First we decided to wrap our errors so that we can get the runtime stack whenever an error occurs.
2f32cac 19
2f32cac 20
```go
2f32cac 21
package utils
2f32cac 22
2f32cac 23
import (
2f32cac 24
    "bytes"
2f32cac 25
    "database/sql"
2f32cac 26
    "runtime"
2f32cac 27
)
2f32cac 28
2f32cac 29
type WrappedError struct {
2f32cac 30
    Err error
2f32cac 31
    StackTrace string
2f32cac 32
}
2f32cac 33
2f32cac 34
func(e * WrappedError) Error() string {
2f32cac 35
    return e.Err.Error()
2f32cac 36
}
2f32cac 37
2f32cac 38
func E(e error) error {
2f32cac 39
    switch e.(type) {
2f32cac 40
    case *WrappedError:
2f32cac 41
        return e
2f32cac 42
    case nil:
2f32cac 43
        return nil
2f32cac 44
    default:
2f32cac 45
        stackTrace := make([]byte , 1 << 16)
2f32cac 46
        runtime.Stack(stackTrace, false)
2f32cac 47
        buffer := &bytes.Buffer{}
2f32cac 48
        for _ , a := range stackTrace {
2f32cac 49
            if a != 0 {
2f32cac 50
                buffer.WriteByte(a)
2f32cac 51
            }
2f32cac 52
        }
2f32cac 53
        return &WrappedError {
2f32cac 54
            Err: e,
2f32cac 55
            StackTrace: buffer.String(),
2f32cac 56
        }
2f32cac 57
    }
2f32cac 58
}
2f32cac 59
```
2f32cac 60
2f32cac 61
But then just sending the error stack in plain format to our emails wasn’t going to be nice to read at all. We needed more
2f32cac 62
information like context and session information and things like that. On top of that I also wanted to make our stack traces
2f32cac 63
prettier so that it would easier to figure out where the error started from.
2f32cac 64
2f32cac 65
So to parse the error stack trace I found this cool library which does that for and on top of that it also themes it very well
2f32cac 66
https://github.com/maruel/panicparse
2f32cac 67
2f32cac 68
But then it didn’t properly expose an API to do it properly and after a few dabblings here,
2f32cac 69
https://github.com/maruel/panicparse/issues/8
2f32cac 70
with the developer and +1’s we got a proper api which I could use.
2f32cac 71
And now I haz got a prettier stack traces like this,
2f32cac 72
2f32cac 73
![Terminal 1](@/assets/images/terminal1.png)
2f32cac 74
2f32cac 75
So great I got ANSI coloring setup and the errors look great in our console but what about our
2f32cac 76
mails. Of course this wasn’t going to work since emails primarily render text and HTML only, and
2f32cac 77
ANSI color codes was going to make our messages a mess.
2f32cac 78
2f32cac 79
So then I went about digging github for an ANSI terminal codes to HTML converter so that it would
2f32cac 80
look exactly like this in my mail. And then I found this cool go library which does that,
2f32cac 81
https://github.com/buildkite/terminal
2f32cac 82
2f32cac 83
Now all emails require inline CSS or else they wouldn’t work so then I had to find out a way to do that too.
2f32cac 84
And this was it,
2f32cac 85
https://github.com/aymerick/douceur
2f32cac 86
2f32cac 87
Finally after messing around with so many libraries I got around to getting it to work and this is how it looks in my email,
2f32cac 88
2f32cac 89
![Email 1](@/assets/images/email1.png)