Skip to content

Commit

Permalink
Merge pull request #2 from cdleo/feature/adding_comments
Browse files Browse the repository at this point in the history
Feature/adding comments
  • Loading branch information
cdleo committed Feb 9, 2022
2 parents a33c2ef + eda10c0 commit 7e27927
Show file tree
Hide file tree
Showing 8 changed files with 303 additions and 48 deletions.
62 changes: 62 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
This document is a loose guideline showing ways for you to contribute.

## Table of Contents
- [Git](#git)
- [Tutorial](#tutorial)
- [Pro Git](#pro-git)
- [Pull requests](#pull-requests)
- [Commit messages](#commit-messages)
- [Suggesting enhancements](#suggesting-enhancements)
- [Reporting bugs](#reporting-bugs)
- [Submitting pull requests](#submitting-pull-requests)

## Git

If you are unfamiliar with git, the internet is filled with with a wealth of excellent resources. Use whatever you need to become comfortable, these are only some suggestions to get you started. As an absolute first step, any contribution requires you to [join GitHub by creating your own account](https://github.com/join).

### Tutorial
Github provides an excellent interactive tutorial to get you ramped up on the basics: [Github interactive tutorial](https://try.github.io/levels/1/challenges/1)

### Pro Git
If you want to dive deep and learn the intricacies of git, the [Pro Git](https://git-scm.com/book/en/v2) book is a fantastic read. It includes chapters on how to [get started](https://git-scm.com/book/en/v2/Getting-Started-About-Version-Control) and covers [the basics](https://git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository), continues with [branching](https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell) and even includes a [chapter specifically on GitHub](https://git-scm.com/book/en/v2/GitHub-Account-Setup-and-Configuration).

### Pull requests
Pull requests are the canonical way of contributing to projects on github. If you have never created a pull request, or want to make sure that you are going about contributing the right way, check out this [step-by-step guide](https://codeburst.io/a-step-by-step-guide-to-making-your-first-github-contribution-5302260a2940).

### Commit messages
Commit messages are a central element of contributing to git projects. They provide a history of your work, and well written commit messages are a central resource of well curated git projects. [This blog post](https://chris.beams.io/posts/git-commit/) summarizes what is generally considered good practice for formulating great commit messages.

## Suggesting enhancements
Opening issues to discuss enhancements is a great way to encourage improvements. Next I've put som suggestions on what you can include in your issue.

- **Use a descriptive title** summarizing the core improvement you suggest
- **Describe the workflow** that you wish to add
- **Add a use case diagram** if you feel that is a good way to present your idea
- **Mention other tools** that provide features similar to what you would like to see in the project (if applies)

Do whatever you think is necessary to best present your enhancement.

## Reporting bugs
Choose the repository that you think the bug belongs to most, and create an issue there. It is easiest to create a separate issue for every bug that you encounter.

The following is not a mandatory list of information, but a recommendation of what can make sense to include in your issue. Include what you think is crucial to best demonstrate your problem, and help your fellow community members in finding a solution.

- **Use a descriptive title** that describes the essence of your problem
- **Include clear steps to reproduce the problem.** Include as much information as possible.
- **Provide information about your system**, the version you are experiencing problems with, the environment you are using, your operating system etc.
- **Explain where and how your experienced behavior differs from what you expected**
- **Include output** to provide more information and context
- **Add as much context as possible** in any way you see fit and necessary.

## Submitting pull requests
If you are unsure about *how* to create a pull request, [this guide](https://codeburst.io/a-step-by-step-guide-to-making-your-first-github-contribution-5302260a2940) should get you on track.

We welcome any contributions that improve the quality of our projects. Be it pull requests for spelling and grammar mistakes or entire enhancements. When creating a pull request, check the project's `README.md` and `CONTRIBUTIONS.md` files for possible additional information on what is required to commit code or other changes, such as including unit tests or conforming to the style of the project. The following are suggestions of what can be included in a good pull request.

- **Use a descriptive title** to present your work
- **Make sure all your changes are included** and that you did not leave out any changes that you wish to contribute.
- **Describe your changes in detail** to show your peers exactly what you have contributed
- **Include issues in your description** if your changes refer to bugs, enhancements or other types of issues
- **Conform to the style of the project**, such as keeping the same indentation level and brace style

Information on how to develop on a project and how to create builds are usually included in the projects README. If the supplied information is insufficient for you to get started, do not hesitate to create an issue and ask for help. We want to keep the barrier to entry as low as possible.
117 changes: 115 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,126 @@
# go-e2h
# GO-E2H

GO Enhanced Error Handling is a lightweight Golang package to add a better stack trace and context information on error events.
GO Enhanced Error Handling (a.k.a. go-e2h) is a lightweight Golang module to add a better stack trace and context information on error events.

## Usage

We use an object of the provided interface EnhancedError to store the context and stack information:

```go
type EnhancedError interface {
// This function returns the Error string plus the origin custom message (if exists)
Error() string
// This function returns the source error
Cause() error
}
```

**Note:** You will never need to use the `EnhancedError` specific type, due to all provided functions uses golang standard interface, which it's compatible.

To save the error callstack and add helpful information, we provide the following stateless functions:

```go
// This function just store or adds stack information
func Trace(e error) error

// Same as Trace, but adding a descriptive context message
func Tracem(e error, message string) error

// Same as Trace, but supporting a variadic function with format string as context information
func Tracef(e error, format string, args ...interface{}) error
```

Additionally, this module provide functions to pretty print the error information, over different outputs:

```go
// This function returns an string containing the description of the very first error in the stack
func Source(err error) string

// This function returns the error stack information in a JSON format
func FormatJSON(err error, rootFolder2Show string, indented bool) []byte

// This function returns the error stack information in a pretty format
func FormatPretty(err error, rootFolder2Show string) string
```

## Usage

The use of this module is very simple, as you may see:
1 - You get/return a `standard GO error`.
2 - You call the `Trace` function (in all of yours versions) and get another error compatible object.
3 - At the highest point of the callstack, or the desired level to log/print the event, you call a formatter.

**Note:** You could call any of the `Trace` functions **even if no error have occurred**, in which case returns a `nil` value

The following example program shows the use of `Source`, `Trace` and `Formatting` options:
```go
package e2h_test

import (
"fmt"

"github.com/cdleo/go-e2h"
)

func foo() error {
return fmt.Errorf("foo")
}

func bar() error {
return e2h.Tracem(foo(), "This call wraps the GO standard error and adds this message and other helpful information")
}

func ExampleEnhancedError() {

err := e2h.Tracef(bar(), "This call adds this %s message and stack information", "formatted")

fmt.Printf("Just cause => %s\n", e2h.Source(err))

fmt.Printf("Just as Error => %v\n", err)

fmt.Printf("Full info (pretty) =>\n%s", e2h.FormatPretty(err, "github.com"))

fmt.Printf("Full info JSON (indented) =>\n\t%s\n", e2h.FormatJSON(err, "github.com", true))

fmt.Printf("Full info JSON (std) =>\n\t%s\n", e2h.FormatJSON(err, "github.com", false))

// Output:
// Just cause => foo
// Just as Error => foo: This call wraps the GO standard error and adds this message and other helpful information
// Full info (pretty) =>
// - This call adds this formatted message and stack information:
// github.com/cdleo/go-e2h_test.ExampleEnhancedError
// github.com/cdleo/go-e2h/e2h_example_test.go:22
// - This call wraps the GO standard error and adds this message and other helpful information:
// github.com/cdleo/go-e2h_test.bar
// github.com/cdleo/go-e2h/e2h_example_test.go:17
// - foo
// Full info JSON (indented) =>
// {
// "error": "foo: This call wraps the GO standard error and adds this message and other helpful information",
// "stack_trace": [
// {
// "func": "github.com/cdleo/go-e2h_test.ExampleEnhancedError",
// "caller": "github.com/cdleo/go-e2h/e2h_example_test.go:22",
// "context": "This call adds this formatted message and stack information"
// },
// {
// "func": "github.com/cdleo/go-e2h_test.bar",
// "caller": "github.com/cdleo/go-e2h/e2h_example_test.go:17",
// "context": "This call wraps the GO standard error and adds this message and other helpful information"
// }
// ]
// }
// Full info JSON (std) =>
// {"error":"foo: This call wraps the GO standard error and adds this message and other helpful information","stack_trace":[{"func":"github.com/cdleo/go-e2h_test.ExampleEnhancedError","caller":"github.com/cdleo/go-e2h/e2h_example_test.go:22","context":"This call adds this formatted message and stack information"},{"func":"github.com/cdleo/go-e2h_test.bar","caller":"github.com/cdleo/go-e2h/e2h_example_test.go:17","context":"This call wraps the GO standard error and adds this message and other helpful information"}]}

}
```

## Sample

You can find a sample of the use of go-e2h project [HERE](https://github.com/cdleo/go-e2h/blob/master/e2h_example_test.go)

## Contributing

Comments, suggestions and/or recommendations are always welcomed. Please check the [Contributing Guide](CONTRIBUTING.md) to learn how to get started contributing.
10 changes: 9 additions & 1 deletion e2h.go
Original file line number Diff line number Diff line change
@@ -1,35 +1,43 @@
/*
Package e2h its the package of the Enhanced Error Handling module
*/
package e2h

import (
"fmt"
)

// ExtendedError interface
type EnhancedError interface {
Error() string
Cause() error
}

// Entity details with detailed info
type details struct {
file string
line int
funcName string
message string
}

// Entity enhancedError with error and details
type enhancedError struct {
err error
stack []details
}

// This function returns the Error string plus the origin custom message (if exists)
func (e *enhancedError) Error() string {

if e.stack[0].message != "" {
if len(e.stack[0].message) > 0 {
return fmt.Sprintf("%s: %s", e.err.Error(), e.stack[0].message)
}

return e.err.Error()
}

// This function returns the source error
func (e *enhancedError) Cause() error {
return e.err
}
37 changes: 25 additions & 12 deletions e2hFormatters.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/*
Package e2h its the package of the Enhanced Error Handling module
*/
package e2h

import (
Expand All @@ -12,10 +15,10 @@ type jsonStack struct {
Context string `json:"context,omitempty"`
}

func newJSONStack(item *details, prefixToRemove string) jsonStack {
func newJSONStack(item *details, rootFolder2Show string) jsonStack {
return jsonStack{
FuncName: item.funcName,
Caller: fmt.Sprintf("%s:%d", removeUnTilPrefix(item.file, prefixToRemove), item.line),
Caller: fmt.Sprintf("%s:%d", removePathBeforeFolder(item.file, rootFolder2Show), item.line),
Context: item.message,
}
}
Expand All @@ -25,7 +28,8 @@ type jsonDetails struct {
Stack []jsonStack `json:"stack_trace"`
}

func Cause(err error) string {
// This function returns an string containing the description of the very first error in the stack
func Source(err error) string {
switch err.(type) {
case EnhancedError:
return err.(*enhancedError).Cause().Error()
Expand All @@ -34,7 +38,8 @@ func Cause(err error) string {
}
}

func FormatJSON(err error, fromFolderPath string) []byte {
// This function returns the error stack information in a JSON format
func FormatJSON(err error, rootFolder2Show string, indented bool) []byte {

details := jsonDetails{
Err: err.Error(),
Expand All @@ -45,20 +50,27 @@ func FormatJSON(err error, fromFolderPath string) []byte {
case EnhancedError:
stkError := err.(*enhancedError)
for i := len(stkError.stack) - 1; i >= 0; i-- {
details.Stack = append(details.Stack, newJSONStack(&stkError.stack[i], fromFolderPath))
details.Stack = append(details.Stack, newJSONStack(&stkError.stack[i], rootFolder2Show))
}
default:
//Do Nothing
}

result, marshalError := json.Marshal(details)
var result []byte
var marshalError error
if indented {
result, marshalError = json.MarshalIndent(details, "", "\t")
} else {
result, marshalError = json.Marshal(details)
}
if marshalError != nil {
return []byte{0}
}
return result
}

func FormatPretty(err error, fromFolderPath string) string {
// This function returns the error stack information in a pretty format
func FormatPretty(err error, rootFolder2Show string) string {

var result string
switch err.(type) {
Expand All @@ -70,7 +82,7 @@ func FormatPretty(err error, fromFolderPath string) string {
result += fmt.Sprintf("- %s:\n", stackItem.message)
}
result += fmt.Sprintf(" %s\n", stackItem.funcName)
result += fmt.Sprintf(" \t%s:%d\n", removeUnTilPrefix(stackItem.file, fromFolderPath), stackItem.line)
result += fmt.Sprintf(" \t%s:%d\n", removePathBeforeFolder(stackItem.file, rootFolder2Show), stackItem.line)
}
result += fmt.Sprintf("- %s\n", stkError.Cause())
default:
Expand All @@ -79,15 +91,16 @@ func FormatPretty(err error, fromFolderPath string) string {
return result
}

func removeUnTilPrefix(file string, fromFolderPath string) string {
// Utility funtion that removes the first part of the file path til the folder indicated in `newRootFolder` argument
func removePathBeforeFolder(file string, newRootFolder string) string {

if len(fromFolderPath) <= 0 {
if len(newRootFolder) <= 0 {
return file
}

fileParts := strings.Split(file, fromFolderPath)
fileParts := strings.Split(file, newRootFolder)
if len(fileParts) < 2 {
return file
}
return fromFolderPath + fileParts[1]
return newRootFolder + fileParts[1]
}
14 changes: 12 additions & 2 deletions e2hTracer.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,30 @@
/*
Package e2h its the package of the Enhanced Error Handling module
*/
package e2h

import (
"fmt"
"runtime"
)

func TraceA(e error) error {
// This function calls the addTrace in order to create or add stack info
func Trace(e error) error {
return addTrace(e, "")
}
func Trace(e error, message string) error {

// Same as Trace, but adding a descriptive message
func Tracem(e error, message string) error {
return addTrace(e, message)
}

// Same as Tracem, but the descriptive message can have formatted values
func Tracef(e error, format string, args ...interface{}) error {
return addTrace(e, format, args...)
}

// This is the private function that creates the first EnhancedError
// with info or add the new info to the existing one
func addTrace(err error, format string, args ...interface{}) error {

if err == nil {
Expand Down
Loading

0 comments on commit 7e27927

Please sign in to comment.