logging and client, context utils
This commit is contained in:
87
pkg/eia/eia.go
Normal file
87
pkg/eia/eia.go
Normal file
@ -0,0 +1,87 @@
|
||||
package eia
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"github.com/deepmap/oapi-codegen/pkg/securityprovider"
|
||||
"github.com/rs/zerolog"
|
||||
|
||||
eiaapi "gitea.libretechconsulting.com/50W/eia-api-go/api"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultBaseURL = "https://api.eia.gov"
|
||||
defaultPingTimeout = 10 * time.Second
|
||||
defaultLogLevel = zerolog.DebugLevel
|
||||
)
|
||||
|
||||
// Simple wrapper around generated EIA API client
|
||||
// that embeds a client with a bearer auth interceptor
|
||||
// and optional logging middleware
|
||||
//
|
||||
// Performs a basic availability check against the API
|
||||
// when creating a new client, and exposes a Ping() method
|
||||
// for health / readiness probes
|
||||
type Client struct {
|
||||
ctx context.Context
|
||||
apiKey string
|
||||
healthCheckTimeout time.Duration
|
||||
*eiaapi.Client
|
||||
}
|
||||
|
||||
type ClientOpts struct {
|
||||
Context context.Context // Base context for requests
|
||||
APIKey string // API Key [EIA Opendata API v2](https://www.eia.gov/opendata/index.php)
|
||||
Logger *zerolog.Logger // Optional logger, if set is injected into logging middleware
|
||||
LogLevel *zerolog.Level // Optional log level, default is zerolog.DebugLevel
|
||||
BaseURL *url.URL // Optional, default is https://api.eia.gov
|
||||
HealthCheckTimeout *time.Duration // Timeout for Ping() function, default is 10s
|
||||
}
|
||||
|
||||
func NewClient(opts *ClientOpts) (*Client, error) {
|
||||
baseURL := defaultBaseURL
|
||||
if opts.BaseURL != nil {
|
||||
baseURL = opts.BaseURL.String()
|
||||
}
|
||||
|
||||
hcTimeout := defaultPingTimeout
|
||||
if opts.HealthCheckTimeout != nil && *opts.HealthCheckTimeout > time.Duration(0) {
|
||||
hcTimeout = *opts.HealthCheckTimeout
|
||||
}
|
||||
|
||||
middlewares := make([]eiaapi.ClientOption, 0, 2)
|
||||
|
||||
// Injects Authorization: Bearer <APIKey> header into
|
||||
// outbound API calls
|
||||
basicAuth, err := securityprovider.NewSecurityProviderBearerToken(opts.APIKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
middlewares = append(middlewares, eiaapi.WithRequestEditorFn(basicAuth.Intercept))
|
||||
|
||||
// Logging middleware, if logger is given
|
||||
if opts.Logger != nil {
|
||||
logLevel := defaultLogLevel
|
||||
if opts.LogLevel != nil {
|
||||
logLevel = *opts.LogLevel
|
||||
}
|
||||
|
||||
middlewares = append(middlewares,
|
||||
eiaapi.WithRequestEditorFn(newLoggingMiddleware(opts.Logger, logLevel)))
|
||||
}
|
||||
|
||||
client, err := eiaapi.NewClient(baseURL, slices.Clip(middlewares)...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Client{
|
||||
apiKey: opts.APIKey,
|
||||
ctx: opts.Context,
|
||||
healthCheckTimeout: hcTimeout,
|
||||
Client: client,
|
||||
}, nil
|
||||
}
|
20
pkg/eia/eia_health.go
Normal file
20
pkg/eia/eia_health.go
Normal file
@ -0,0 +1,20 @@
|
||||
package eia
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func (c *Client) Ping() error {
|
||||
ctx, cncl := context.WithTimeout(c.ctx, c.healthCheckTimeout)
|
||||
defer cncl()
|
||||
|
||||
resp, err := c.GetV2(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if resp.StatusCode != 200 {
|
||||
return fmt.Errorf("non-200 response [%s] from eia api", resp.Status)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
24
pkg/eia/eia_logging.go
Normal file
24
pkg/eia/eia_logging.go
Normal file
@ -0,0 +1,24 @@
|
||||
package eia
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
|
||||
eiaapi "gitea.libretechconsulting.com/50W/eia-api-go/api"
|
||||
)
|
||||
|
||||
func newLoggingMiddleware(logger *zerolog.Logger, level zerolog.Level) eiaapi.RequestEditorFn {
|
||||
return func(_ context.Context, req *http.Request) error {
|
||||
logger.WithLevel(level).
|
||||
Str("method", req.Method).
|
||||
Str("host", req.URL.Host).
|
||||
Str("path", req.URL.Path).
|
||||
Str("query", req.Form.Encode()).
|
||||
Time("timestamp", time.Now()).
|
||||
Send()
|
||||
return nil
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user