Skip to content

Commit

Permalink
story(issue-258): example update custom framework to use new package …
Browse files Browse the repository at this point in the history
…api (#266)

* refactor(issue-258): update custom framework example

* feat(issue-258): actually configure trace provider for custom framework

* chore(docs): updated coverage badge.

---------

Co-authored-by: GitHub Action <[email protected]>
  • Loading branch information
Zaba505 and actions-user authored Sep 14, 2024
1 parent 52b40ce commit 1f9f90d
Show file tree
Hide file tree
Showing 16 changed files with 531 additions and 97 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go)
[![Go Reference](https://pkg.go.dev/badge/github.com/z5labs/bedrock.svg)](https://pkg.go.dev/github.com/z5labs/bedrock)
[![Go Report Card](https://goreportcard.com/badge/github.com/z5labs/bedrock)](https://goreportcard.com/report/github.com/z5labs/bedrock)
![Coverage](https://img.shields.io/badge/Coverage-96.5%25-brightgreen)
![Coverage](https://img.shields.io/badge/Coverage-96.9%25-brightgreen)
[![build](https://github.com/z5labs/bedrock/actions/workflows/build.yaml/badge.svg)](https://github.com/z5labs/bedrock/actions/workflows/build.yaml)

**bedrock provides a minimal, modular and composable foundation for
Expand Down
31 changes: 31 additions & 0 deletions example/custom_framework/echo/app/app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) 2024 Z5Labs and Contributors
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT

package app

import (
"context"

"github.com/z5labs/bedrock/example/custom_framework/echo/endpoint"

"github.com/z5labs/bedrock/example/custom_framework/framework"
"github.com/z5labs/bedrock/example/custom_framework/framework/rest"
)

type Config struct {
rest.Config `config:",squash"`
}

func Init(ctx context.Context, cfg Config) (framework.App, error) {
log := framework.Logger(cfg.Logging)

app := rest.NewApp(
rest.OpenApi(cfg.OpenApi),
rest.OTel(cfg.OTel),
rest.HttpServer(cfg.Http),
rest.WithEndpoint(endpoint.Echo(log)),
)
return app, nil
}
1 change: 0 additions & 1 deletion example/custom_framework/echo/config.yaml
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
custom: "hello"
61 changes: 61 additions & 0 deletions example/custom_framework/echo/endpoint/echo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (c) 2024 Z5Labs and Contributors
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT

package endpoint

import (
"context"
"encoding/json"
"log/slog"
"net/http"

"github.com/z5labs/bedrock/example/custom_framework/framework/rest"
)

type echoHandler struct {
log *slog.Logger
}

func Echo(log *slog.Logger) rest.Endpoint {
h := &echoHandler{
log: log,
}

return rest.Endpoint{
Method: http.MethodPost,
Path: "/echo",
Operation: rest.NewOperation(h),
}
}

type EchoRequest struct {
Msg string `json:"msg"`
}

func (EchoRequest) ContentType() string {
return "application/json"
}

func (req *EchoRequest) UnmarshalBinary(b []byte) error {
return json.Unmarshal(b, req)
}

type EchoResponse struct {
Msg string `json:"msg"`
}

func (EchoResponse) ContentType() string {
return "application/json"
}

func (resp *EchoResponse) MarshalBinary() ([]byte, error) {
return json.Marshal(resp)
}

func (h *echoHandler) Handle(ctx context.Context, req *EchoRequest) (*EchoResponse, error) {
h.log.InfoContext(ctx, "echoing back received message to client", slog.String("echo_msg", req.Msg))
resp := &EchoResponse{Msg: req.Msg}
return resp, nil
}
57 changes: 57 additions & 0 deletions example/custom_framework/echo/endpoint/echo_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright (c) 2024 Z5Labs and Contributors
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT

package endpoint

import (
"encoding/json"
"io"
"log/slog"
"net/http"
"net/http/httptest"
"strings"
"testing"

"github.com/stretchr/testify/assert"
)

func TestEcho(t *testing.T) {
t.Run("will echo message back", func(t *testing.T) {
t.Run("always", func(t *testing.T) {
e := Echo(slog.Default())

req := `{"msg": "hello world"}`

w := httptest.NewRecorder()
r := httptest.NewRequest(
http.MethodPost,
"/echo",
strings.NewReader(req),
)
r.Header.Set("Content-Type", "application/json")

e.ServeHTTP(w, r)

resp := w.Result()
if !assert.Equal(t, http.StatusOK, resp.StatusCode) {
return
}

b, err := io.ReadAll(resp.Body)
if !assert.Nil(t, err) {
return
}

var echoResp EchoResponse
err = json.Unmarshal(b, &echoResp)
if !assert.Nil(t, err) {
return
}
if !assert.Equal(t, "hello world", echoResp.Msg) {
return
}
})
})
}
4 changes: 2 additions & 2 deletions example/custom_framework/echo/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import (
"bytes"
_ "embed"

"github.com/z5labs/bedrock/example/custom_framework/echo/service"
"github.com/z5labs/bedrock/example/custom_framework/echo/app"
"github.com/z5labs/bedrock/example/custom_framework/framework"
)

//go:embed config.yaml
var cfgSrc []byte

func main() {
framework.Rest(bytes.NewReader(cfgSrc), service.Init)
framework.Run(bytes.NewReader(cfgSrc), app.Init)
}
71 changes: 0 additions & 71 deletions example/custom_framework/echo/service/service.go

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
otel:
serviceName: {{env "SERVICE_NAME"}}
service_name: {{env "SERVICE_NAME"}}
service_version: {{env "SERVICE_VERSION"}}
otlp:
target: {{env "OTLP_ADDR"}}

logging:
level: {{env "LOG_LEVEL" | default "INFO"}}

http:
port: {{env "HTTP_PORT" | default 8080}}
81 changes: 62 additions & 19 deletions example/custom_framework/framework/framework.go
Original file line number Diff line number Diff line change
@@ -1,33 +1,76 @@
package framework

import (
"bytes"
"context"
_ "embed"
"io"
"log/slog"
"net/http"
"os"
"sync"

"github.com/z5labs/bedrock/example/custom_framework/framework/internal"
"github.com/z5labs/bedrock/example/custom_framework/framework/internal/global"

"github.com/z5labs/bedrock"
)

//go:embed base_config.yaml
var baseCfgSrc []byte
//go:embed default_config.yaml
var configBytes []byte

func init() {
global.RegisterConfigSource(internal.ConfigSource(bytes.NewReader(configBytes)))
}

type OTelConfig struct {
ServiceName string `config:"service_name"`
ServiceVersion string `config:"service_version"`
OTLP struct {
Target string `config:"target"`
} `config:"otlp"`
}

type LoggingConfig struct {
Level slog.Level `config:"level"`
}

type Config struct {
OTel struct {
ServiceName string `config:"serviceName"`
OTLP struct {
Target string `config:"target"`
} `config:"otlp"`
} `config:"otel"`

Logging struct {
Level slog.Level `config:"level"`
} `config:"logging"`

Http struct {
Port uint `config:"port"`
} `config:"http"`
OTel OTelConfig `config:"otel"`
Logging LoggingConfig `config:"logging"`
}

var logger *slog.Logger
var initLoggerOnce sync.Once

func Logger(cfg LoggingConfig) *slog.Logger {
initLoggerOnce.Do(func() {
logger = slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
AddSource: true,
Level: cfg.Level,
}))
})
return logger
}

func Rest[T any](cfg io.Reader, f func(context.Context, T, *http.ServeMux) error) error {
return nil
type App bedrock.App

func Run[T any](r io.Reader, build func(context.Context, T) (App, error)) {
err := bedrock.Run(
context.Background(),
bedrock.AppBuilderFunc[T](func(ctx context.Context, cfg T) (bedrock.App, error) {
return build(ctx, cfg)
}),
global.ConfigSources...,
)
if err == nil {
return
}

// there's a chance Run failed on config parsing/unmarshalling
// thus the logging config is most likely unusable and we should
// instead create our own logger here for logging this error
log := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
AddSource: true,
}))
log.Error("failed while running application", slog.String("error", err.Error()))
}
28 changes: 28 additions & 0 deletions example/custom_framework/framework/internal/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) 2024 Z5Labs and Contributors
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT

package internal

import (
"io"
"os"

"github.com/z5labs/bedrock/pkg/config"
)

func ConfigSource(r io.Reader) config.Source {
return config.FromYaml(
config.RenderTextTemplate(
r,
config.TemplateFunc("env", os.Getenv),
config.TemplateFunc("default", func(s string, v any) any {
if len(s) == 0 {
return v
}
return s
}),
),
)
}
Loading

0 comments on commit 1f9f90d

Please sign in to comment.