Skip to content

Commit

Permalink
updating setup steps
Browse files Browse the repository at this point in the history
  • Loading branch information
ankurs committed Apr 24, 2023
1 parent 4fbaa49 commit 378e03c
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 90 deletions.
74 changes: 73 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,85 @@ The core module is the base module for cold brew and provides the base implement

## Index

- [func ConfigureInterceptors(DoNotLogGRPCReflection bool, traceHeaderName string)](<#func-configureinterceptors>)
- [func SetupEnvironment(env string)](<#func-setupenvironment>)
- [func SetupHystrixPrometheus()](<#func-setuphystrixprometheus>)
- [func SetupLogger(logLevel string, jsonlogs bool) error](<#func-setuplogger>)
- [func SetupNROpenTelemetry(serviceName, license, version string, ratio float64) error](<#func-setupnropentelemetry>)
- [func SetupNewRelic(serviceName, apiKey string, tracing bool) error](<#func-setupnewrelic>)
- [func SetupReleaseName(rel string)](<#func-setupreleasename>)
- [func SetupSentry(dsn string)](<#func-setupsentry>)
- [type CB](<#type-cb>)
- [func New(c config.Config) CB](<#func-new>)
- [type CBGracefulStopper](<#type-cbgracefulstopper>)
- [type CBService](<#type-cbservice>)
- [type CBStopper](<#type-cbstopper>)


## func [ConfigureInterceptors](<https://github.com/go-coldbrew/core/blob/main/initializers.go#L200>)

```go
func ConfigureInterceptors(DoNotLogGRPCReflection bool, traceHeaderName string)
```

ConfigureInterceptors configures the interceptors package with the provided DoNotLogGRPCReflection is a boolean that indicates whether to log the grpc.reflection.v1alpha.ServerReflection service calls in logs traceHeaderName is the name of the header to use for tracing \(e.g. X\-Trace\-Id\) \- if empty, defaults to X\-Trace\-Id

## func [SetupEnvironment](<https://github.com/go-coldbrew/core/blob/main/initializers.go#L89>)

```go
func SetupEnvironment(env string)
```

SetupEnvironment sets the environment This is used to identify the environment in Sentry and New Relic env is the environment to set for the service \(e.g. prod, staging, dev\)

## func [SetupHystrixPrometheus](<https://github.com/go-coldbrew/core/blob/main/initializers.go#L192>)

```go
func SetupHystrixPrometheus()
```

SetupHystrixPrometheus sets up the hystrix metrics This is a workaround for hystrix\-go not supporting the prometheus registry

## func [SetupLogger](<https://github.com/go-coldbrew/core/blob/main/initializers.go#L65>)

```go
func SetupLogger(logLevel string, jsonlogs bool) error
```

SetupLogger sets up the logger It uses the coldbrew logger to log messages to stdout logLevel is the log level to set for the logger jsonlogs is a boolean to enable or disable json logs

## func [SetupNROpenTelemetry](<https://github.com/go-coldbrew/core/blob/main/initializers.go#L135>)

```go
func SetupNROpenTelemetry(serviceName, license, version string, ratio float64) error
```

setupOpenTelemetry sets up the OpenTelemetry tracing It uses the New Relic OTLP exporter to send traces to New Relic One APM and Insights serviceName is the name of the service license is the New Relic license key version is the version of the service ratio is the sampling ratio to use for traces

## func [SetupNewRelic](<https://github.com/go-coldbrew/core/blob/main/initializers.go#L40>)

```go
func SetupNewRelic(serviceName, apiKey string, tracing bool) error
```

SetupNewRelic sets up the New Relic tracing and monitoring agent for the service It uses the New Relic Go Agent to send traces to New Relic One APM and Insights serviceName is the name of the service apiKey is the New Relic license key tracing is a boolean to enable or disable tracing

## func [SetupReleaseName](<https://github.com/go-coldbrew/core/blob/main/initializers.go#L98>)

```go
func SetupReleaseName(rel string)
```

SetupReleaseName sets the release name This is used to identify the release in Sentry rel is the release name to set for the service \(e.g. v1.0.0\)

## func [SetupSentry](<https://github.com/go-coldbrew/core/blob/main/initializers.go#L80>)

```go
func SetupSentry(dsn string)
```

SetupSentry sets up the Sentry notifier It uses the Sentry HTTP Transport to send errors to Sentry server dsn is the Sentry DSN to use for sending errors

## type [CB](<https://github.com/go-coldbrew/core/blob/main/types.go#L42-L54>)

CB is the interface that wraps coldbrew methods.
Expand All @@ -67,7 +139,7 @@ type CB interface {
}
```

### func [New](<https://github.com/go-coldbrew/core/blob/main/core.go#L356>)
### func [New](<https://github.com/go-coldbrew/core/blob/main/core.go#L363>)

```go
func New(c config.Config) CB
Expand Down
36 changes: 4 additions & 32 deletions config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,39 +13,9 @@ import "github.com/go-coldbrew/core/config"
- [type Config](<#type-config>)


## type [Config](<https://github.com/go-coldbrew/core/blob/main/config/config.go#L32-L102>)
## type [Config](<https://github.com/go-coldbrew/core/blob/main/config/config.go#L6-L78>)

### Config is the configuration for the Coldbrew server
It is populated from environment variables and has sensible defaults for all fields so that you can just use it as is without any configuration
The following environment variables are supported and can be used to override the defaults for the fields

```
LISTEN_HOST - Host to listen on, defaults to
GRPC_PORT - GRPC Port, defaults to 9090
HTTP_PORT - HTTP Port, defaults to 9091
APP_NAME - Name of the Application
ENVIRONMENT - Environment e.g. Production / Integration / Development
LOG_LEVEL - LogLevel to print, default to info
JSON_LOGS - Should logs be emitted in json format, defaults to true
DISABLE_SWAGGER - Should we disable swagger at /swagger/, defaults to false
DISABLE_DEBUG - Should we disable go debug at /debug/, defaults to false
DISABLE_PROMETHEUS - Should we disable prometheus at /metrics, defaults to false
ENABLE_PROMETHEUS_GRPC_HISTOGRAM - Enables grpc request histograms in prometheus reporting
NEW_RELIC_LICENSE_KEY - The License key for NewRelic metrics reporting
NEW_RELIC_DISTRIBUTED_TRACING - Enable NewRelic Distributed Tracing
NEW_RELIC_OPENTELEMETRY - Enable new relic opentelemetry
NEW_RELIC_OPENTELEMETRY_SAMPLE - Sampling ratio for NR opentelemetry
SENTRY_DSN - DSN for reporting errors to sentry
RELEASE_NAME - Name of this release
DISABLE_GRPC_REFLECTION - When set disable the GRPC reflecttion server which can be useful for tools like grpccurl, default false
TRACE_HEADER_NAME - Trace header, when this HTTP header is present CB will add the value to log/trace contexts
HTTP_HEADER_PREFIX - When we match this HTTP header prefix, we forward append the values to grpc metadata
DO_NOT_LOG_GRPC_REFLECTION - Should we log calls to GRPC reflection API, defaults to true
DISABLE_SIGNAL_HANDLER - Should we disable signal handler, defaults to false and CB handles all SIG_INT/SIG_TERM
SHUTDOWN_DURATION_IN_SECONDS - Duration for which CB will wait for calls to complete before shutting down the server
GRPC_GRACEFUL_DURATION_IN_SECONDS - Duration for which CB will wait for healthcheck fail to be propagated before initiating server shutdown once shutdown is initiated all new calls will fail
USE_JSON_BUILTIN_MARSHALLER - UseJSONBuiltinMarshaller switches marshaler for application/json to encoding/json
```
Config is the configuration for the Coldbrew server It is populated from environment variables and has sensible defaults for all fields so that you can just use it as is without any configuration The following environment variables are supported and can be used to override the defaults for the fields

```go
type Config struct {
Expand Down Expand Up @@ -79,6 +49,8 @@ type Config struct {
NewRelicOpentelemetry bool `envconfig:"NEW_RELIC_OPENTELEMETRY" default:"true"`
// Sampling ratio for NR opentelemetry
NewRelicOpentelemetrySample float64 `envconfig:"NEW_RELIC_OPENTELEMETRY_SAMPLE" default:"0.2"`
// The name of the application in NewRelic
NewRelicAppname string `envconfig:"NEW_RELIC_APPNAME" default:""`
// DSN for reporting errors to sentry
SentryDSN string `envconfig:"SENTRY_DSN" default:""`
// Name of this release
Expand Down
28 changes: 2 additions & 26 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,6 @@ package config
// Config is the configuration for the Coldbrew server
// It is populated from environment variables and has sensible defaults for all fields so that you can just use it as is without any configuration
// The following environment variables are supported and can be used to override the defaults for the fields
//
// LISTEN_HOST - Host to listen on, defaults to
// GRPC_PORT - GRPC Port, defaults to 9090
// HTTP_PORT - HTTP Port, defaults to 9091
// APP_NAME - Name of the Application
// ENVIRONMENT - Environment e.g. Production / Integration / Development
// LOG_LEVEL - LogLevel to print, default to info
// JSON_LOGS - Should logs be emitted in json format, defaults to true
// DISABLE_SWAGGER - Should we disable swagger at /swagger/, defaults to false
// DISABLE_DEBUG - Should we disable go debug at /debug/, defaults to false
// DISABLE_PROMETHEUS - Should we disable prometheus at /metrics, defaults to false
// ENABLE_PROMETHEUS_GRPC_HISTOGRAM - Enables grpc request histograms in prometheus reporting
// NEW_RELIC_LICENSE_KEY - The License key for NewRelic metrics reporting
// NEW_RELIC_DISTRIBUTED_TRACING - Enable NewRelic Distributed Tracing
// NEW_RELIC_OPENTELEMETRY - Enable new relic opentelemetry
// NEW_RELIC_OPENTELEMETRY_SAMPLE - Sampling ratio for NR opentelemetry
// SENTRY_DSN - DSN for reporting errors to sentry
// RELEASE_NAME - Name of this release
// DISABLE_GRPC_REFLECTION - When set disable the GRPC reflecttion server which can be useful for tools like grpccurl, default false
// TRACE_HEADER_NAME - Trace header, when this HTTP header is present CB will add the value to log/trace contexts
// HTTP_HEADER_PREFIX - When we match this HTTP header prefix, we forward append the values to grpc metadata
// DO_NOT_LOG_GRPC_REFLECTION - Should we log calls to GRPC reflection API, defaults to true
// DISABLE_SIGNAL_HANDLER - Should we disable signal handler, defaults to false and CB handles all SIG_INT/SIG_TERM
// SHUTDOWN_DURATION_IN_SECONDS - Duration for which CB will wait for calls to complete before shutting down the server
// GRPC_GRACEFUL_DURATION_IN_SECONDS - Duration for which CB will wait for healthcheck fail to be propagated before initiating server shutdown once shutdown is initiated all new calls will fail
// USE_JSON_BUILTIN_MARSHALLER - UseJSONBuiltinMarshaller switches marshaler for application/json to encoding/json
type Config struct {
// Host to listen on
ListenHost string `envconfig:"LISTEN_HOST" default:"0.0.0.0"`
Expand Down Expand Up @@ -60,6 +34,8 @@ type Config struct {
NewRelicOpentelemetry bool `envconfig:"NEW_RELIC_OPENTELEMETRY" default:"true"`
// Sampling ratio for NR opentelemetry
NewRelicOpentelemetrySample float64 `envconfig:"NEW_RELIC_OPENTELEMETRY_SAMPLE" default:"0.2"`
// The name of the application in NewRelic
NewRelicAppname string `envconfig:"NEW_RELIC_APPNAME" default:""`
// DSN for reporting errors to sentry
SentryDSN string `envconfig:"SENTRY_DSN" default:""`
// Name of this release
Expand Down
23 changes: 15 additions & 8 deletions core.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,23 @@ func (c *cb) SetOpenAPIHandler(handler http.Handler) {
c.openAPIHandler = handler
}

// processConfig processes the config and sets up the logger, newrelic, sentry, environment, release name, jaeger, hystrix prometheus and signal handler
func (c *cb) processConfig() {
setupLogger(c.config.LogLevel, c.config.JSONLogs)
setupNewRelic(c.config.AppName, c.config.NewRelicLicenseKey, c.config.NewRelicDistributedTracing)
setupSentry(c.config.SentryDSN)
setupEnvironment(c.config.Environment)
setupReleaseName(c.config.ReleaseName)
SetupLogger(c.config.LogLevel, c.config.JSONLogs)
nrName := c.config.AppName
if nrName == "" {
nrName = c.config.AppName
}
SetupNewRelic(nrName, c.config.NewRelicLicenseKey, c.config.NewRelicDistributedTracing)
SetupSentry(c.config.SentryDSN)
SetupEnvironment(c.config.Environment)
SetupReleaseName(c.config.ReleaseName)
cls := setupJaeger(c.config.AppName)
if cls != nil {
c.closers = append(c.closers, cls)
}
setupHystrix()
configureInterceptors(c.config.DoNotLogGRPCReflection, c.config.TraceHeaderName)
SetupHystrixPrometheus()
ConfigureInterceptors(c.config.DoNotLogGRPCReflection, c.config.TraceHeaderName)
if !c.config.DisableSignalHandler {
dur := time.Second * 10
if c.config.ShutdownDurationInSeconds > 0 {
Expand All @@ -78,13 +83,15 @@ func (c *cb) processConfig() {
grpc_prometheus.EnableHandlingTimeHistogram()
}
if c.config.NewRelicOpentelemetry {
setupNROpenTelemetry(c.config.AppName, c.config.NewRelicLicenseKey, c.config.ReleaseName, c.config.NewRelicOpentelemetrySample)
SetupNROpenTelemetry(nrName, c.config.NewRelicLicenseKey, c.config.ReleaseName, c.config.NewRelicOpentelemetrySample)
}
}

// https://grpc-ecosystem.github.io/grpc-gateway/docs/operations/tracing/#opentracing-support
var grpcGatewayTag = opentracing.Tag{Key: string(ext.Component), Value: "grpc-gateway"}

// tracingWrapper is a middleware that creates a new span for each incoming request.
// It also adds the span to the context so it can be used by other middlewares or handlers to add additional tags.
func tracingWrapper(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
parentSpanContext, err := opentracing.GlobalTracer().Extract(
Expand Down
64 changes: 41 additions & 23 deletions initializers.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,15 @@ import (
semconv "go.opentelemetry.io/otel/semconv/v1.12.0"
)

// setupNewRelic sets up the New Relic tracing and monitoring agent for the service
// SetupNewRelic sets up the New Relic tracing and monitoring agent for the service
// It uses the New Relic Go Agent to send traces to New Relic One APM and Insights
func setupNewRelic(serviceName, apiKey string, tracing bool) {
// serviceName is the name of the service
// apiKey is the New Relic license key
// tracing is a boolean to enable or disable tracing
func SetupNewRelic(serviceName, apiKey string, tracing bool) error {
if strings.TrimSpace(apiKey) == "" {
log.Info(context.Background(), "Not initializing NewRelic because token is empty")
return
return nil
}

app, err := newrelic.NewApplication(
Expand All @@ -48,43 +51,51 @@ func setupNewRelic(serviceName, apiKey string, tracing bool) {
)
if err != nil {
log.Error(context.Background(), "msg", "NewRelic could not be initialized", "err", err)
return
return err
}
nrutil.SetNewRelicApp(app)
log.Info(context.Background(), "NewRelic initialized for "+serviceName)
return nil
}

// setupLogger sets up the logger
// SetupLogger sets up the logger
// It uses the coldbrew logger to log messages to stdout
func setupLogger(logLevel string, jsonlogs bool) {
// logLevel is the log level to set for the logger
// jsonlogs is a boolean to enable or disable json logs
func SetupLogger(logLevel string, jsonlogs bool) error {
log.SetLogger(log.NewLogger(gokit.NewLogger(loggers.WithJSONLogs(jsonlogs))))

ll, err := loggers.ParseLevel(logLevel)
if err != nil {
log.Error(context.Background(), "err", "could not set log level", "level", logLevel)
} else {
log.SetLevel(ll)
return err
}
log.SetLevel(ll)
return nil
}

// setupSentry sets up the Sentry notifier
// SetupSentry sets up the Sentry notifier
// It uses the Sentry HTTP Transport to send errors to Sentry server
func setupSentry(dsn string) {
// dsn is the Sentry DSN to use for sending errors
func SetupSentry(dsn string) {
if dsn != "" {
notifier.InitSentry(dsn)
}
}

// setupEnvironment sets the environment
func setupEnvironment(env string) {
// SetupEnvironment sets the environment
// This is used to identify the environment in Sentry and New Relic
// env is the environment to set for the service (e.g. prod, staging, dev)
func SetupEnvironment(env string) {
if env != "" {
notifier.SetEnvironment(env)
}
}

// setupReleaseName sets the release name
// SetupReleaseName sets the release name
// This is used to identify the release in Sentry
func setupReleaseName(rel string) {
// rel is the release name to set for the service (e.g. v1.0.0)
func SetupReleaseName(rel string) {
if rel != "" {
notifier.SetRelease(rel)
}
Expand Down Expand Up @@ -117,10 +128,14 @@ func setupJaeger(serviceName string) io.Closer {

// setupOpenTelemetry sets up the OpenTelemetry tracing
// It uses the New Relic OTLP exporter to send traces to New Relic One APM and Insights
func setupNROpenTelemetry(serviceName, license, version string, ratio float64) {
// serviceName is the name of the service
// license is the New Relic license key
// version is the version of the service
// ratio is the sampling ratio to use for traces
func SetupNROpenTelemetry(serviceName, license, version string, ratio float64) error {
if serviceName == "" || license == "" {
log.Info(context.Background(), "msg", "not initializing NR opentelemetry tracing")
return
return nil
}
var headers = map[string]string{
"api-key": license,
Expand All @@ -135,7 +150,7 @@ func setupNROpenTelemetry(serviceName, license, version string, ratio float64) {
otlpExporter, err := otlptrace.New(context.Background(), otlptracegrpc.NewClient(clientOpts...))
if err != nil {
log.Error(context.Background(), "msg", "creating OTLP trace exporter", "err", err)
return
return err
}

d := resource.Default()
Expand All @@ -148,13 +163,13 @@ func setupNROpenTelemetry(serviceName, license, version string, ratio float64) {
)
if err != nil {
log.Error(context.Background(), "msg", "creating OTLP resource", "err", err)
return
return err
}
r, err := resource.Merge(d, res)

if err != nil {
log.Error(context.Background(), "msg", "merging OTLP resource", "err", err)
return
return err
}

tracerProvider := sdktrace.NewTracerProvider(
Expand All @@ -169,17 +184,20 @@ func setupNROpenTelemetry(serviceName, license, version string, ratio float64) {
otel.SetTracerProvider(wrapperTracerProvider)
opentracing.SetGlobalTracer(bridgeTracer)
log.Info(context.Background(), "msg", "Initialized NR opentelemetry tracing")
return nil
}

// setupHystrix sets up the hystrix metrics
// SetupHystrixPrometheus sets up the hystrix metrics
// This is a workaround for hystrix-go not supporting the prometheus registry
func setupHystrix() {
func SetupHystrixPrometheus() {
promC := hystrixprometheus.NewPrometheusCollector("hystrix", nil, prometheus.DefBuckets)
metricCollector.Registry.Register(promC.Collector)
}

// configureInterceptors configures the interceptors package with the provided
func configureInterceptors(DoNotLogGRPCReflection bool, traceHeaderName string) {
// ConfigureInterceptors configures the interceptors package with the provided
// DoNotLogGRPCReflection is a boolean that indicates whether to log the grpc.reflection.v1alpha.ServerReflection service calls in logs
// traceHeaderName is the name of the header to use for tracing (e.g. X-Trace-Id) - if empty, defaults to X-Trace-Id
func ConfigureInterceptors(DoNotLogGRPCReflection bool, traceHeaderName string) {
if DoNotLogGRPCReflection {
interceptors.FilterMethods = append(interceptors.FilterMethods, "grpc.reflection.v1alpha.ServerReflection")
}
Expand Down

0 comments on commit 378e03c

Please sign in to comment.