增加exceptionless,支持error原生

This commit is contained in:
suguo.yao 2022-08-13 22:04:48 +08:00
parent 8c955c89ea
commit bff14dcc82
8 changed files with 296 additions and 94 deletions

85
exceptionless/api.go Normal file
View File

@ -0,0 +1,85 @@
package exceptionless
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
)
// Post posts to the Exceptionless Server
func Post(endpoint string, postBody string, authorization string) string {
exceptionless := GetClient()
// err := godotenv.Load(".env")
// if err != nil {
// log.Fatalf("Error loading .env file")
// }
var baseURL string = os.Getenv("BASE_API_URL")
if exceptionless.ServerURL != "" {
baseURL = exceptionless.ServerURL
}
url := baseURL + endpoint
var jsonStr = []byte(postBody)
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
req.Header.Set("Authorization", "Bearer "+authorization)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
// body, _ := ioutil.ReadAll(resp.Body)
return string(resp.Status)
}
// GET makes api GET requests
func Get(endpoint string, authorization string) map[string]interface{} {
exceptionless := GetClient()
// err := godotenv.Load(".env")
// if err != nil {
// log.Fatalf("Error loading .env file")
// }
var baseURL string = os.Getenv("BASE_API_URL")
if exceptionless.ServerURL != "" {
baseURL = exceptionless.ServerURL
}
url := baseURL + endpoint
httpClient := &http.Client{}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
fmt.Println(err)
// return "Error"
}
req.Header.Add("accept", "application/json")
req.Header.Add("Authorization", "Bearer "+authorization)
res, err := httpClient.Do(req)
if err != nil {
fmt.Println(err)
// return "Error"
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Println(err)
// return "Error"
}
// resp := string(body)
var result map[string]interface{}
json.Unmarshal([]byte(body), &result)
return result
}

143
exceptionless/builder.go Normal file
View File

@ -0,0 +1,143 @@
package exceptionless
import (
"encoding/json"
"fmt"
"time"
"github.com/google/uuid"
)
// Event is the main model for events
type Event struct {
EventType string `json:"type"`
Source string `json:"source,omitempty"`
Date string `json:"date,omitempty"`
Tags []string `json:"tags,omitempty"`
Message string `json:"message,omitempty"`
Geo string `json:"geo,omitempty"`
Value uint `json:"value,omitempty"`
Data map[string]interface{} `json:"data,omitempty"`
ReferenceID uuid.UUID `json:"reference_id,omitempty"`
Count uint `json:"count,omitempty"`
}
// GetBaseEvent returns an empty Event struct that can be built into any type of event.
func GetBaseEvent(eventType string, message string, date string) Event {
return Event{
EventType: eventType,
Message: message,
Date: date,
}
}
// AddSource adds a string value source to an event
func AddSource(event Event, source string) Event {
event.Source = source
return event
}
// AddTags adds a string array of tags for the event
func AddTags(event Event, tags []string) Event {
event.Tags = tags
return event
}
// AddGeo adds the lat and long location of the user the event impacted
func AddGeo(event Event, geo string) Event {
event.Geo = geo
return event
}
// AddValue adds an arbitrary number value to the event
func AddValue(event Event, value uint) Event {
event.Value = value
return event
}
// AddReferenceID adds an indentifier to later refer to this event
func AddReferenceID(event Event, referenceID uuid.UUID) Event {
event.ReferenceID = referenceID
return event
}
// AddCount adds a number to help track the number of times the event has occurred
func AddCount(event Event, count uint) Event {
event.Count = count
return event
}
func AddLogLevel(event Event, level string) Event {
var updatedEvent Event
if event.Data != nil {
event.Data["@level"] = level
updatedEvent = event
} else {
data := map[string]interface{}{}
data["@level"] = level
updatedEvent = AddData(event, data)
}
return updatedEvent
}
// AddData adds a string mapping to create a data object of additional values
func AddData(event Event, data map[string]interface{}) Event {
event.Data = data
return event
}
// SubmitError is a convenience wrapper to quickly build and submit an error
func SubmitError(err error) string {
exceptionlessClient := GetClient()
if exceptionlessClient.UpdateSettingsWhenIdleInterval > 0 {
config := GetConfig()
fmt.Println(config)
// We are stripping out info accoring to the config settings
}
referenceID := uuid.Must(uuid.NewUUID())
errorMap := map[string]interface{}{}
errorMap["type"] = "error"
errorMap["message"] = err.Error()
errorMap["date"] = time.Now().Format(time.RFC3339)
data := map[string]interface{}{}
data["@simple_error"] = errorMap
var mainEvent = Event{
EventType: "error",
Message: err.Error(),
Data: data,
ReferenceID: referenceID,
}
json, err := json.Marshal(mainEvent)
if err != nil {
fmt.Println(err)
return err.Error()
}
resp := SubmitEvent(string(json))
return resp
}
func SubmitLog(message string, level string) string {
exceptionlessClient := GetClient()
referenceID := uuid.Must(uuid.NewUUID())
if exceptionlessClient.UpdateSettingsWhenIdleInterval > 0 {
config := GetConfig()
fmt.Println(config)
// We are stripping out info accoring to the config settings
// We would also prevent logs of levels below the log level set by the settings
}
var event Event
date := time.Now().Format(time.RFC3339)
event = GetBaseEvent("log", message, date)
event = AddReferenceID(event, referenceID)
data := map[string]interface{}{}
data["@level"] = level
event = AddData(event, data)
json, err := json.Marshal(event)
if err != nil {
fmt.Println(err)
return err.Error()
}
resp := SubmitEvent(string(json))
return resp
}

View File

@ -1,99 +1,67 @@
package exceptionless
import (
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"strings"
"math/rand"
"time"
)
type Config struct {
URL string
Token string
var config map[string]interface{} = nil
// Exceptionless type defines the client configuration structure
type Exceptionless struct {
ApiKey string
ServerURL string
UpdateSettingsWhenIdleInterval int32
IncludePrivateInformation bool
}
var conf *Config
var client = Exceptionless{}
func Init(config *Config) error {
if config == nil {
return errors.New("nil of Config")
}
conf = config
conf.Token = "Bearer " + conf.Token
return nil
func main() {
handlePolling()
}
func post(uri string, body interface{}) (*[]byte, error) {
url := fmt.Sprintf(`%s/%s`, conf.URL, uri)
reqbody, _ := json.Marshal(body)
req, err := http.NewRequest("POST", url, strings.NewReader(string(reqbody)))
if err != nil {
return nil, err
func handlePolling() {
if client.ApiKey != "" && client.UpdateSettingsWhenIdleInterval > 0 {
fmt.Println("polling!")
poll()
}
}
req.Header.Add("Authorization", conf.Token)
req.Header.Add("Content-Type", "application/json")
tr := &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
client := &http.Client{Transport: tr}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode == 202 {
return nil, nil
}
respBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return &respBody, nil
// Configure is the function that creates an Exceptionless client
func Configure(config Exceptionless) Exceptionless {
client = config
handlePolling()
return client
}
func WriteMessages(msg string) {
message := &struct {
Message string
}{
Message: msg,
}
post("api/v2/events", message)
// GetClient returns the Exceptionless client
func GetClient() Exceptionless {
return client
}
func WriteLogs(msg string) {
message := &struct {
Message string
Type string
Date string
}{
Type: "log",
Message: msg,
Date: time.Now().Format("2006-01-02 15:04:05"),
}
post("api/v2/events", message)
// GetConfig returns the project configuration
func GetConfig() map[string]interface{} {
return config
}
func WriteErrors(msg string) {
message := &struct {
SimpleError interface{}
Type string
Date string
}{
Type: "error",
SimpleError: &struct {
Message string
}{
Message: msg,
},
Date: time.Now().Format("2006-01-02 15:04:05"),
// SubmitEvent sends log events to Exceptionless
func SubmitEvent(eventBody string) string {
if client.ApiKey == "" {
fmt.Println("is zero value")
}
resp := Post("events", eventBody, client.ApiKey)
return resp
}
func poll() {
r := rand.New(rand.NewSource(99))
c := time.Tick(10 * time.Second)
for _ = range c {
resp := Get("projects/config", client.ApiKey)
config = resp
jitter := time.Duration(r.Int31n(client.UpdateSettingsWhenIdleInterval)) * time.Millisecond
time.Sleep(jitter)
}
post("api/v2/events", message)
}

View File

@ -1,13 +0,0 @@
package exceptionless
import "testing"
func TestWriteMessage(t *testing.T) {
Init(&Config{
URL: "https://api.exceptionless.com",
Token: "MyNc2Rmfymq1XJ52rJdPW021zbQiAbzdxV92znbm",
})
// WriteMessages("adfasdfadsfsdf")
// WriteLogs("aaasfas222rwerwer")
WriteErrors("bbbbbb")
}

6
exceptionless/log.go Normal file
View File

@ -0,0 +1,6 @@
package exceptionless
func createLog(source string, message string, level string, geo string, referenceID string, date string, value uint) {
// event := BuildEvent("log", message, source, nil, nil, nil, nil, nil, nil)
// fmt.Println(event)
}

View File

@ -0,0 +1,7 @@
package exceptionless
type UserDescription struct {
email string
description string
data string
}

View File

@ -0,0 +1,7 @@
package exceptionless
type UserIdentity struct {
identity string
name string
data string
}

3
go.mod
View File

@ -5,11 +5,10 @@ go 1.17
require (
github.com/eclipse/paho.mqtt.golang v1.2.0
github.com/gin-gonic/gin v1.7.4
github.com/gofrs/uuid v3.3.0+incompatible
github.com/gomodule/redigo v1.8.5
github.com/google/uuid v1.1.2
github.com/hashicorp/consul/api v1.10.1
github.com/influxdata/influxdb v1.9.5
github.com/sirupsen/logrus v1.7.0
github.com/stretchr/testify v1.7.0
github.com/syndtr/goleveldb v1.0.0
go.mongodb.org/mongo-driver v1.7.4