commit
927ca879b2
@ -6,6 +6,8 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -238,3 +240,64 @@ func FromError(err error) *Error {
|
|||||||
|
|
||||||
return Parse(err.Error())
|
return Parse(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalJSON returns error data
|
||||||
|
func (e *Error) MarshalJSON() ([]byte, error) {
|
||||||
|
return e.Marshal()
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON set error data
|
||||||
|
func (e *Error) UnmarshalJSON(data []byte) error {
|
||||||
|
return e.Unmarshal(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProtoMessage noop func
|
||||||
|
func (e *Error) ProtoMessage() {}
|
||||||
|
|
||||||
|
// Reset resets error
|
||||||
|
func (e *Error) Reset() {
|
||||||
|
*e = Error{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns error as string
|
||||||
|
func (e *Error) String() string {
|
||||||
|
return fmt.Sprintf(`{"id":"%s","detail":"%s","status":"%s","code":%d}`, e.ID, e.Detail, e.Status, e.Code)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal returns error data
|
||||||
|
func (e *Error) Marshal() ([]byte, error) {
|
||||||
|
return []byte(e.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal set error data
|
||||||
|
func (e *Error) Unmarshal(data []byte) error {
|
||||||
|
str := string(data)
|
||||||
|
if len(data) < 41 {
|
||||||
|
return fmt.Errorf("invalid data")
|
||||||
|
}
|
||||||
|
parts := strings.FieldsFunc(str[1:len(str)-1], func(r rune) bool {
|
||||||
|
return r == ','
|
||||||
|
})
|
||||||
|
for _, part := range parts {
|
||||||
|
nparts := strings.FieldsFunc(part, func(r rune) bool {
|
||||||
|
return r == ':'
|
||||||
|
})
|
||||||
|
for idx := 0; idx < len(nparts); idx++ {
|
||||||
|
switch {
|
||||||
|
case nparts[idx] == `"id"`:
|
||||||
|
e.ID = nparts[idx+1][1 : len(nparts[idx+1])-1]
|
||||||
|
case nparts[idx] == `"detail"`:
|
||||||
|
e.Detail = nparts[idx+1][1 : len(nparts[idx+1])-1]
|
||||||
|
case nparts[idx] == `"status"`:
|
||||||
|
e.Status = nparts[idx+1][1 : len(nparts[idx+1])-1]
|
||||||
|
case nparts[idx] == `"code"`:
|
||||||
|
c, err := strconv.ParseInt(nparts[idx+1], 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
e.Code = int32(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
31
errors/errors.proto
Normal file
31
errors/errors.proto
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Copyright 2021 Unistack LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package micro.errors;
|
||||||
|
|
||||||
|
option cc_enable_arenas = true;
|
||||||
|
option go_package = "go.unistack.org/micro/v3/errors;errors";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
option java_outer_classname = "MicroErrors";
|
||||||
|
option java_package = "micro.errors";
|
||||||
|
option objc_class_prefix = "MERRORS";
|
||||||
|
|
||||||
|
message Error {
|
||||||
|
string id = 1;
|
||||||
|
string detail = 2;
|
||||||
|
string status = 3;
|
||||||
|
uint32 code = 4;
|
||||||
|
}
|
@ -7,6 +7,37 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestContext(t *testing.T) {
|
||||||
|
ctx := context.TODO()
|
||||||
|
buf := bytes.NewBuffer(nil)
|
||||||
|
l := NewLogger(WithLevel(TraceLevel), WithOutput(buf))
|
||||||
|
if err := l.Init(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
nl, ok := FromContext(NewContext(ctx, l.Fields("key", "val")))
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("context without logger")
|
||||||
|
}
|
||||||
|
nl.Info(ctx, "message")
|
||||||
|
if !bytes.Contains(buf.Bytes(), []byte(`"key":"val"`)) {
|
||||||
|
t.Fatalf("logger fields not works, buf contains: %s", buf.Bytes())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFields(t *testing.T) {
|
||||||
|
ctx := context.TODO()
|
||||||
|
buf := bytes.NewBuffer(nil)
|
||||||
|
l := NewLogger(WithLevel(TraceLevel), WithOutput(buf))
|
||||||
|
if err := l.Init(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
l.Fields("key", "val").Info(ctx, "message")
|
||||||
|
if !bytes.Contains(buf.Bytes(), []byte(`"key":"val"`)) {
|
||||||
|
t.Fatalf("logger fields not works, buf contains: %s", buf.Bytes())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestClone(t *testing.T) {
|
func TestClone(t *testing.T) {
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
buf := bytes.NewBuffer(nil)
|
buf := bytes.NewBuffer(nil)
|
||||||
|
Loading…
Reference in New Issue
Block a user