增加exceptionless,支持error原生
This commit is contained in:
parent
8c955c89ea
commit
bff14dcc82
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
@ -1,99 +1,67 @@
|
||||||
package exceptionless
|
package exceptionless
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"math/rand"
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
var config map[string]interface{} = nil
|
||||||
URL string
|
|
||||||
Token string
|
// 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 {
|
func main() {
|
||||||
if config == nil {
|
handlePolling()
|
||||||
return errors.New("nil of Config")
|
|
||||||
}
|
|
||||||
conf = config
|
|
||||||
conf.Token = "Bearer " + conf.Token
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func post(uri string, body interface{}) (*[]byte, error) {
|
func handlePolling() {
|
||||||
url := fmt.Sprintf(`%s/%s`, conf.URL, uri)
|
if client.ApiKey != "" && client.UpdateSettingsWhenIdleInterval > 0 {
|
||||||
reqbody, _ := json.Marshal(body)
|
fmt.Println("polling!")
|
||||||
req, err := http.NewRequest("POST", url, strings.NewReader(string(reqbody)))
|
poll()
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func WriteMessages(msg string) {
|
// Configure is the function that creates an Exceptionless client
|
||||||
message := &struct {
|
func Configure(config Exceptionless) Exceptionless {
|
||||||
Message string
|
client = config
|
||||||
}{
|
handlePolling()
|
||||||
Message: msg,
|
return client
|
||||||
}
|
|
||||||
post("api/v2/events", message)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func WriteLogs(msg string) {
|
// GetClient returns the Exceptionless client
|
||||||
message := &struct {
|
func GetClient() Exceptionless {
|
||||||
Message string
|
return client
|
||||||
Type string
|
|
||||||
Date string
|
|
||||||
}{
|
|
||||||
Type: "log",
|
|
||||||
Message: msg,
|
|
||||||
Date: time.Now().Format("2006-01-02 15:04:05"),
|
|
||||||
}
|
|
||||||
post("api/v2/events", message)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func WriteErrors(msg string) {
|
// GetConfig returns the project configuration
|
||||||
message := &struct {
|
func GetConfig() map[string]interface{} {
|
||||||
SimpleError interface{}
|
return config
|
||||||
Type string
|
}
|
||||||
Date string
|
|
||||||
}{
|
// SubmitEvent sends log events to Exceptionless
|
||||||
Type: "error",
|
func SubmitEvent(eventBody string) string {
|
||||||
SimpleError: &struct {
|
if client.ApiKey == "" {
|
||||||
Message string
|
fmt.Println("is zero value")
|
||||||
}{
|
}
|
||||||
Message: msg,
|
resp := Post("events", eventBody, client.ApiKey)
|
||||||
},
|
return resp
|
||||||
Date: time.Now().Format("2006-01-02 15:04:05"),
|
}
|
||||||
}
|
|
||||||
post("api/v2/events", message)
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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")
|
|
||||||
}
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
package exceptionless
|
||||||
|
|
||||||
|
type UserDescription struct {
|
||||||
|
email string
|
||||||
|
description string
|
||||||
|
data string
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
package exceptionless
|
||||||
|
|
||||||
|
type UserIdentity struct {
|
||||||
|
identity string
|
||||||
|
name string
|
||||||
|
data string
|
||||||
|
}
|
||||||
3
go.mod
3
go.mod
|
|
@ -5,11 +5,10 @@ go 1.17
|
||||||
require (
|
require (
|
||||||
github.com/eclipse/paho.mqtt.golang v1.2.0
|
github.com/eclipse/paho.mqtt.golang v1.2.0
|
||||||
github.com/gin-gonic/gin v1.7.4
|
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/gomodule/redigo v1.8.5
|
||||||
|
github.com/google/uuid v1.1.2
|
||||||
github.com/hashicorp/consul/api v1.10.1
|
github.com/hashicorp/consul/api v1.10.1
|
||||||
github.com/influxdata/influxdb v1.9.5
|
github.com/influxdata/influxdb v1.9.5
|
||||||
github.com/sirupsen/logrus v1.7.0
|
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
github.com/syndtr/goleveldb v1.0.0
|
github.com/syndtr/goleveldb v1.0.0
|
||||||
go.mongodb.org/mongo-driver v1.7.4
|
go.mongodb.org/mongo-driver v1.7.4
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue