Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: add Config page #234

Merged
merged 5 commits into from
Oct 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions docs/07-config.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
id: config
title: Config
sidebar_label: Config
sidebar_position: 7
---

ogen could be configurated via `.ogen.yml` file:

```yaml [title=".ogen.yml"]
# sets generator options.
generator:
# sets generator features.
features:
enable:
# Enables paths client generation
- "paths/client"
# Enables paths server generation
- "paths/server"
# Enables validation of client requests
- "client/request/validation"
# Enables validation of server responses
- "server/response/validation"
# Enables OpenTelemetry integration
- "ogen/otel"
disable_all: true
```

See full config example [here](https://github.com/ogen-go/ogen/blob/main/examples/_config/example_all.yml).

### Features

ogen provides a opt-in/opt-out mechanism for some features like OpenTelemetry integration.

You can find a [complete feature list](https://github.com/ogen-go/ogen/blob/main/gen/features.go) in ogen repository.
121 changes: 74 additions & 47 deletions docs/07-faq.mdx → docs/08-faq.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
id: faq
title: Frequently Asked Questions (FAQ)
sidebar_label: FAQ
sidebar_position: 7
sidebar_position: 8
---

### How to set `404 Not Found` handler?
Expand Down Expand Up @@ -116,75 +116,102 @@ func newServer() *http.Server {

See [Static router](concepts/static_router.mdx#using-nethttp-middlewares) section for more details.

### How to use prometheus?
### How to use Prometheus?

To instrument server or client with OpenTelemetry and prometheus exporter, pass `oas.Option`:
See [OpenTelemetry Go SDK examples](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/c3c853808383d1bce596cbb910546c305c9187e8/examples/prometheus/main.go#L33-L38).

Also, see [our `autometer` helper](https://pkg.go.dev/github.com/go-faster/sdk/autometer).

Example setup:

```go
package main

import (
"github.com/go-faster/errors"
promClient "github.com/prometheus/client_golang/prometheus"
"go.opentelemetry.io/otel/exporters/prometheus"
"go.opentelemetry.io/otel/sdk/export/metric/aggregation"
"go.opentelemetry.io/otel/sdk/metric/aggregator/histogram"
controller "go.opentelemetry.io/otel/sdk/metric/controller/basic"
processor "go.opentelemetry.io/otel/sdk/metric/processor/basic"
selector "go.opentelemetry.io/otel/sdk/metric/selector/simple"
"go.opentelemetry.io/otel/sdk/resource"
semconv "go.opentelemetry.io/otel/semconv/v1.7.0"
"context"

"example/internal/oas"

"application/oas"
"github.com/prometheus/client_golang/prometheus"
otelprometheus "go.opentelemetry.io/otel/exporters/prometheus"
"go.opentelemetry.io/otel/metric"
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/resource"
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
)

// Resource returns new resource for application.
func Resource(name string) *resource.Resource {
r, _ := resource.Merge(
const appName = "my-ogen-service"

// setupMeterProvider setups Prometheus instrumentation.
func setupMeterProvider(reg prometheus.Registerer) (metric.MeterProvider, ShutdownFunc, error) {
// Create an OpenTelemetry Resource description.
//
// See https://opentelemetry.io/docs/languages/go/resources/
appResource, err := resource.Merge(
resource.Default(),
resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceNameKey.String(name),
semconv.ServiceNameKey.String(appName),
),
)
return r
}
if err != nil {
return nil, nil, err
}

func newPrometheus(config prometheus.Config, options ...controller.Option) (*prometheus.Exporter, error) {
c := controller.New(
processor.NewFactory(
selector.NewWithHistogramDistribution(
histogram.WithExplicitBoundaries(config.DefaultHistogramBoundaries),
),
aggregation.CumulativeTemporalitySelector(),
processor.WithMemory(true),
),
options...,
// Create Prometheus exporter and given registerer.
exp, err := otelprometheus.New(
otelprometheus.WithRegisterer(reg),
)
return prometheus.New(config, c)
}
if err != nil {
return nil, nil, err
}

// newMeterProviderOption returns oas.Option for prometheus instrumentation.
func newMeterProviderOption() (oas.Option, error) {
registry := promClient.NewPedanticRegistry()
res := Resource("app")
promExporter, err := newPrometheus(prometheus.Config{
DefaultHistogramBoundaries: promClient.DefBuckets,

Registry: registry,
Gatherer: registry,
Registerer: registry,
},
controller.WithCollectPeriod(0),
controller.WithResource(res),
mp := sdkmetric.NewMeterProvider(
sdkmetric.WithResource(appResource),
sdkmetric.WithReader(exp),
)
return mp, func(ctx context.Context) error {
// Flush collected metrics.
_ = mp.ForceFlush(ctx)
return mp.Shutdown(ctx)
}, nil
}

type ShutdownFunc = func(ctx context.Context) error

func createAPIServer(h oas.Handler) (_ *oas.Server, _ ShutdownFunc, rerr error) {
meterProvider, shutdown, err := setupMeterProvider(prometheus.DefaultRegisterer)
if err != nil {
return nil, nil, err
}
defer func() {
// Shutdown MeterProvider and release resources in case of error.
if rerr != nil {
shutdown(context.TODO())
}
}()

server, err := oas.NewServer(h, oas.WithMeterProvider(meterProvider))
if err != nil {
return nil, errors.Wrap(err, "prometheus")
return nil, nil, err
}
return oas.WithMeterProvider(promExporter.MeterProvider()), nil

// Returned `shutdown` function would stop metric collection.
return server, shutdown, nil
}
```

### How to add some tags to generated structures?

[Use `x-oapi-codegen-extra-tags` extension.](spec/extensions.md#extra-struct-field-tags)

### How to disable OpenTelemetry integration?

Disable `ogen/otel` feature via [config](config):

```yaml [title=".ogen.yml"]
generator:
features:
disable:
- "ogen/otel"
```
14 changes: 9 additions & 5 deletions docs/concepts/convenient_errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ If spec meets all following requirements:
then `ogen` generates special handler for errors returned by `Handler` implementation and does not generate default response variant.

For example:

```yaml
openapi: 3.0.3
info:
Expand Down Expand Up @@ -87,9 +88,12 @@ type Handler interface {

### Force or Disable `Convenient errors`

Use `--convenient-errors` option

- `auto` (default) generates `NewError` if possible
- `on` tells generator to fail if spec does not meet requirements
- `off` disables `Convenient errors` at all
Use `generator.convenient_errors` option

```yaml
generator:
# `auto` (default) generates `NewError` if possible
# `on` tells generator to fail if spec does not meet requirements
# `off` disables `Convenient errors` at all
convenient_errors: "auto"
```
78 changes: 78 additions & 0 deletions docs/spec/extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,37 @@ Optionally, type name can be specified by `x-ogen-name`, for example:
}
```

### Custom field name

Optionally, type name can be specified by `x-ogen-properties`, for example:

```yaml
components:
schemas:
Node:
type: object
properties:
parent:
$ref: "#/components/schemas/Node"
child:
$ref: "#/components/schemas/Node"
x-ogen-properties:
parent:
name: "Prev"
child:
name: "Next"
```

The generated source code looks like:

```go
// Ref: #/components/schemas/Node
type Node struct {
Prev *Node `json:"parent"`
Next *Node `json:"child"`
}
```

### Extra struct field tags

Optionally, additional Go struct field tags can be specified by `x-oapi-codegen-extra-tags`, for example:
Expand Down Expand Up @@ -151,3 +182,50 @@ requestBody:
items:
type: number
```

### Operation groups

Optionally, operations can be grouped so a handler interface will be generated for each group of operations.
This is useful for organizing operations for large APIs.

The group for operations on a path or individual operations can be specified by `x-ogen-operation-group`, for example:

```yaml
paths:
/images:
x-ogen-operation-group: Images
get:
operationId: listImages
...
/images/{imageID}:
x-ogen-operation-group: Images
get:
operationId: getImageByID
...
/users:
x-ogen-operation-group: Users
get:
operationId: listUsers
...
```

The generated handler interfaces look like this:

```go
// x-ogen-operation-group: Images
type ImagesHandler interface {
ListImages(ctx context.Context, req *ListImagesRequest) (*ListImagesResponse, error)
GetImageByID(ctx context.Context, req *GetImagesByIDRequest) (*GetImagesByIDResponse, error)
}

// x-ogen-operation-group: Users
type UsersHandler interface {
ListUsers(ctx context.Context, req *ListUsersRequest) (*ListUsersResponse, error)
}

type Handler interface {
ImagesHandler
UsersHandler
// All un-grouped operations will be on this interface
}
```
Loading