Flamingo in Production¶
The benefit of Go is that you build/compile a standalone binary without any external dependencies.
We recommend that you do so in a proper continuous integration pipeline that runs all your tests before with go test -race -vet=all ./...
Deployment Artifact¶
Make sure to bundle the templates and config files. For example in a tarball/zipball or a Docker image
Docker¶
Check the file example/dist/Dockerfile
for an example Dockerfile that you can use in your application:
# Example Dockerfile for Flamingo/Go based Projects
# Builder
FROM golang:alpine AS builder
RUN apk update && apk add --no-cache ca-certificates tzdata git && update-ca-certificates
COPY . /app
RUN cd /app && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app .
# Final image
FROM scratch
# add timezone data and ssl root certificates
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
# add artifacts
#ADD config /config
# add binary
COPY --from=builder /app/app /app
ENTRYPOINT ["/app"]
CMD ["serve"]
Running Flamingo¶
- Run it behind a Load Balancer like Nginx or a Kubernetes Ingress
Observability¶
Logging¶
Logging is an essential part of any application, as it helps in tracking events, debugging issues, and monitoring the application’s behavior. The Flamingo Web Framework provides a simple and efficient way to implement logging in your web applications.
Basic usage¶
To start using the logger in Flamingo, you need to inject the flamingo.Logger
interface.
package example
import (
"flamingo.me/flamingo/v3/framework/flamingo"
)
type (
MyStruct struct{
logger flamingo.Logger
}
)
func (s *MyStruct) Inject(logger flamingo.Logger) *MyStruct {
s.logger = logger
return s
}
func (s *MyStruct) SomeFunc() {
s.logger.Debug("This is a debug message")
s.logger.Info("This is an info message")
s.logger.Warn("This is a warning message")
s.logger.Error("This is an error message")
s.logger.Fatal("This is a fatal message")
}
Trace logging¶
Flamingo also supports a Trace log level, which is below Debug and intended to provide very detailed logging information. This can be useful for deep debugging and tracing the flow of your application. However, the Trace log level is not enabled by default and requires a build tag to be activated.
This will add the Trace functions to the flamingo.Logger
interface.
To enable the Trace log level, you need to compile your application with the tracelog
build tag:
go build -tags tracelog
Logging with Context and additional fields¶
Flamingo's logger also supports logging with context and additional fields, which is useful for adding extra metadata to your log entries:
func (s *MyStruct) someFunction(ctx context.Context) {
s.logger.WithField(flamingo.LogKeyCategory, "SomeCategory").Info("This is an info message with context")
s.logger.WithContext(ctx).Info("This is an info message with context")
}
You can chain multiple With
functions together. There are a lot of prepared constants for common log keys.
Default and custom logger implementations¶
The standard implementation for the Logger interface is the zap Logger. It is automatically bound to the interface by Flamingo.
Read more about the ZAP Logger in Flamingo
To use another implementation, you can specify the ApplicationOption WithCustomLogger
and pass a Flamingo module:
package main
import (
"flamingo.me/flamingo/v3"
)
func main() {
flamingo.App([]dingo.Module{
// your modules
}, flamingo.WithCustomLogger(new(MyLogModule)))
}
This Flamingo module must at least bind an implementation to the flamingo.Logger
interface.
An alternative implementation available in the core is silentzap
. Silentzap wraps the zap logger and only logs when
an error happens, but then all levels are in the same context/trace.
OpenTelemetry¶
For metrics support and to push tracing information to Jaeger/Zipkin Flamingo uses OpenTelemetry. Read more about OpenTelemetry