Skip to content

Commit 14d245a

Browse files
authored
feat: improve log (#181)
1 parent 79885fa commit 14d245a

File tree

19 files changed

+274
-208
lines changed

19 files changed

+274
-208
lines changed

benchmark/bench_test.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ package benchmark
1818

1919
import (
2020
"context"
21-
"github.com/functionstream/function-stream/fs"
21+
"github.com/functionstream/function-stream/fs/api"
2222
"github.com/functionstream/function-stream/fs/runtime/wazero"
2323
"math/rand"
2424
"os"
@@ -114,8 +114,14 @@ func BenchmarkStressForBasicFunc(b *testing.B) {
114114
func BenchmarkStressForBasicFuncWithMemoryQueue(b *testing.B) {
115115
memoryQueueFactory := contube.NewMemoryQueueFactory(context.Background())
116116

117-
s, err := server.NewServer(server.WithFunctionManager(fs.WithTubeFactory(common.MemoryTubeType, memoryQueueFactory),
118-
fs.WithRuntimeFactory(common.WASMRuntime, wazero.NewWazeroFunctionRuntimeFactory())))
117+
s, err := server.NewServer(
118+
server.WithRuntimeFactoryBuilder(common.WASMRuntime, func(configMap common.ConfigMap) (api.FunctionRuntimeFactory, error) {
119+
return wazero.NewWazeroFunctionRuntimeFactory(), nil
120+
}),
121+
server.WithTubeFactoryBuilder(common.MemoryTubeType, func(configMap common.ConfigMap) (contube.TubeFactory, error) {
122+
return memoryQueueFactory, nil
123+
}),
124+
)
119125
if err != nil {
120126
b.Fatal(err)
121127
}

common/errors.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@
1616

1717
package common
1818

19-
import "errors"
19+
import "fmt"
2020

2121
var (
22-
ErrorFunctionNotFound = errors.New("function not found")
23-
ErrorFunctionExists = errors.New("function already exists")
24-
ErrorTubeFactoryNotFound = errors.New("tube factory not found")
25-
ErrorRuntimeFactoryNotFound = errors.New("runtime factory not found")
22+
ErrorFunctionNotFound = fmt.Errorf("function not found")
23+
ErrorFunctionExists = fmt.Errorf("function already exists")
24+
ErrorRuntimeFactoryNotFound = fmt.Errorf("runtime factory not found")
25+
ErrorTubeFactoryNotFound = fmt.Errorf("tube factory not found")
2626
)

common/log.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright 2024 Function Stream Org.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package common
18+
19+
import (
20+
"github.com/go-logr/logr"
21+
"github.com/go-logr/zapr"
22+
"go.uber.org/zap"
23+
)
24+
25+
const (
26+
DebugLevel int = 4
27+
)
28+
29+
type Logger struct {
30+
*logr.Logger
31+
}
32+
33+
func NewDefaultLogger() *Logger {
34+
zapLogger, err := zap.NewDevelopment()
35+
if err != nil {
36+
panic("failed to create zap logger:" + err.Error())
37+
}
38+
zaprLog := zapr.NewLogger(zapLogger)
39+
return NewLogger(&zaprLog)
40+
}
41+
42+
func NewLogger(logger *logr.Logger) *Logger {
43+
return &Logger{logger}
44+
}
45+
46+
func (l *Logger) DebugEnabled() bool {
47+
return l.GetV() >= DebugLevel
48+
}
49+
50+
func (l *Logger) Debug(msg string, keysAndValues ...interface{}) {
51+
if l.DebugEnabled() {
52+
l.V(DebugLevel).Info(msg, keysAndValues...)
53+
}
54+
}
55+
56+
func (l *Logger) SubLogger(keysAndValues ...any) *Logger {
57+
internalLogger := l.WithValues(keysAndValues...)
58+
return &Logger{&internalLogger}
59+
}

common/model/function.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import (
2424
)
2525

2626
type TubeConfig struct {
27-
Type string `json:"type"` // Default to `default`
27+
Type string `json:"type"`
2828
Config contube.ConfigMap `json:"config,omitempty"`
2929
}
3030

fs/api/instance.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@
1717
package api
1818

1919
import (
20-
"log/slog"
21-
20+
"github.com/functionstream/function-stream/common"
2221
"github.com/functionstream/function-stream/common/model"
2322
"github.com/functionstream/function-stream/fs/contube"
2423
"golang.org/x/net/context"
@@ -30,11 +29,10 @@ type FunctionInstance interface {
3029
Definition() *model.Function
3130
Index() int32
3231
Stop()
33-
Run(factory FunctionRuntimeFactory, sources []<-chan contube.Record, sink chan<- contube.Record)
34-
WaitForReady() <-chan error
35-
Logger() *slog.Logger
32+
Run(runtime FunctionRuntime, sources []<-chan contube.Record, sink chan<- contube.Record)
33+
Logger() *common.Logger
3634
}
3735

3836
type FunctionInstanceFactory interface {
39-
NewFunctionInstance(f *model.Function, funcCtx FunctionContext, i int32, logger *slog.Logger) FunctionInstance
37+
NewFunctionInstance(f *model.Function, funcCtx FunctionContext, i int32, logger *common.Logger) FunctionInstance
4038
}

fs/api/runtime.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121
)
2222

2323
type FunctionRuntime interface {
24-
WaitForReady() <-chan error
2524
Call(e contube.Record) (contube.Record, error)
2625
Stop()
2726
}

fs/contube/http.go

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
package contube
1818

1919
import (
20+
"github.com/functionstream/function-stream/common"
2021
"io"
21-
"log/slog"
2222
"net/http"
2323
"sync"
2424
"sync/atomic"
@@ -30,9 +30,10 @@ import (
3030
type state int
3131

3232
const (
33-
EndpointKey = "endpoint"
33+
EndpointKey = "endpoint"
34+
IncludeMetadata = "includeMetadata"
3435

35-
stateReady state = iota
36+
stateReady state = iota // TODO: Why do we need this? Maybe we can remove it.
3637
stateClosed state = iota
3738
)
3839

@@ -43,6 +44,11 @@ var (
4344
)
4445

4546
type EndpointHandler func(ctx context.Context, endpoint string, payload []byte) error
47+
type HttpHandler func(w http.ResponseWriter, r *http.Request, payload []byte) Record
48+
49+
func DefaultHttpHandler(_ http.ResponseWriter, _ *http.Request, payload []byte) Record {
50+
return NewRecordImpl(payload, func() {})
51+
}
4652

4753
type endpointHandler struct {
4854
ctx context.Context
@@ -55,32 +61,42 @@ type HttpTubeFactory struct {
5561
ctx context.Context
5662
mu sync.RWMutex
5763
endpoints map[string]*endpointHandler
64+
handler HttpHandler
5865
}
5966

6067
func NewHttpTubeFactory(ctx context.Context) *HttpTubeFactory {
68+
return NewHttpTubeFactoryWithIntercept(ctx, DefaultHttpHandler)
69+
}
70+
71+
func NewHttpTubeFactoryWithIntercept(ctx context.Context, handler HttpHandler) *HttpTubeFactory {
6172
return &HttpTubeFactory{
6273
ctx: ctx,
6374
endpoints: make(map[string]*endpointHandler),
75+
handler: handler,
6476
}
6577
}
6678

6779
type httpSourceTubeConfig struct {
6880
Endpoint string `json:"endpoint" validate:"required"`
6981
}
7082

71-
func (f *HttpTubeFactory) Handle(ctx context.Context, endpoint string, payload []byte) error {
83+
func (f *HttpTubeFactory) getEndpoint(endpoint string) (*endpointHandler, bool) {
7284
f.mu.RLock()
85+
defer f.mu.RUnlock()
7386
e, ok := f.endpoints[endpoint]
87+
return e, ok
88+
}
89+
90+
func (f *HttpTubeFactory) Handle(ctx context.Context, endpoint string, record Record) error {
91+
e, ok := f.getEndpoint(endpoint)
7492
if !ok {
75-
f.mu.RUnlock()
7693
return ErrEndpointNotFound
7794
}
78-
f.mu.RUnlock()
7995
if e.s.Load() == stateClosed {
8096
return ErrEndpointClosed
8197
}
8298
select {
83-
case e.c <- NewRecordImpl(payload, func() {}):
99+
case e.c <- record:
84100
return nil
85101
case <-ctx.Done():
86102
return ctx.Err()
@@ -125,28 +141,33 @@ func (f *HttpTubeFactory) NewSinkTube(_ context.Context, _ ConfigMap) (chan<- Re
125141
}
126142

127143
func (f *HttpTubeFactory) GetHandleFunc(getEndpoint func(r *http.Request) (string, error),
128-
logger *slog.Logger) func(http.ResponseWriter, *http.Request) {
144+
logger *common.Logger) func(http.ResponseWriter, *http.Request) {
129145
return func(w http.ResponseWriter, r *http.Request) {
130146
endpoint, err := getEndpoint(r)
131147
if err != nil {
132-
logger.Error("Failed to get endpoint", "error", err)
148+
logger.Error(err, "Failed to get endpoint")
133149
http.Error(w, errors.Wrap(err, "Failed to get endpoint").Error(), http.StatusBadRequest)
134150
return
135151
}
136-
log := logger.With(slog.String("endpoint", endpoint), slog.String("component", "http-tube"))
137-
log.Info("Handle records from http request")
152+
log := logger.SubLogger("endpoint", endpoint, "component", "http-tube")
153+
if log.DebugEnabled() {
154+
log.Debug("Handle records from http request")
155+
}
138156
content, err := io.ReadAll(r.Body)
139157
if err != nil {
140-
log.Error("Failed to read body", "error", err)
158+
log.Error(err, "Failed to read body")
141159
http.Error(w, errors.Wrap(err, "Failed to read body").Error(), http.StatusBadRequest)
142160
return
143161
}
144-
err = f.Handle(r.Context(), endpoint, content)
162+
record := f.handler(w, r, content)
163+
err = f.Handle(r.Context(), endpoint, record)
145164
if err != nil {
146-
log.Error("Failed to handle record", "error", err)
165+
log.Error(err, "Failed to handle record")
147166
http.Error(w, err.Error(), http.StatusInternalServerError)
148167
return
149168
}
150-
log.Info("Handled records from http request")
169+
if log.DebugEnabled() {
170+
log.Debug("Handled records from http request")
171+
}
151172
}
152173
}

fs/contube/http_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func TestHttpTubeHandleRecord(t *testing.T) {
2929
f := NewHttpTubeFactory(ctx)
3030

3131
endpoint := "test"
32-
err := f.Handle(ctx, "test", []byte("test"))
32+
err := f.Handle(ctx, "test", NewRecordImpl([]byte("test"), nil))
3333
assert.ErrorIs(t, err, ErrEndpointNotFound)
3434

3535
config := make(ConfigMap)
@@ -39,7 +39,7 @@ func TestHttpTubeHandleRecord(t *testing.T) {
3939
_, err = f.NewSourceTube(ctx, config)
4040
assert.ErrorIs(t, err, ErrorEndpointAlreadyExists)
4141

42-
err = f.Handle(ctx, endpoint, []byte("test"))
42+
err = f.Handle(ctx, endpoint, NewRecordImpl([]byte("test"), nil))
4343
assert.Nil(t, err)
4444

4545
record := <-source
@@ -48,7 +48,7 @@ func TestHttpTubeHandleRecord(t *testing.T) {
4848
cancel()
4949

5050
assert.Nil(t, <-source)
51-
err = f.Handle(ctx, endpoint, []byte("test"))
51+
err = f.Handle(ctx, endpoint, NewRecordImpl([]byte("test"), nil))
5252
assert.Error(t, err, ErrEndpointNotFound)
5353
}
5454

0 commit comments

Comments
 (0)