Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I want to catch all errors in the production environment and send them to the Sentry. But I can't understand how to add it as a middleware. Do I need to write a custom logger than implement logger.Logger interface or I can do it somehow differently?
Seems like you want a sentry logging middleware. Every big logging library should have their own middleware implementation. For example logrus
import (
"github.com/sirupsen/logrus"
"github.com/evalphobia/logrus_sentry"
)
func main() {
log := logrus.New()
hook, err := logrus_sentry.NewSentryHook(YOUR_DSN, []logrus.Level{
logrus.PanicLevel,
logrus.FatalLevel,
logrus.ErrorLevel,
})
if err == nil {
log.Hooks.Add(hook)
}
}
If you want to create your own (assuming you're using logrus), you'll have to implement the interface for the hook and then post those entries yourself to sentry.
Thanks, #martinni39 based on your code and code in the Buffalo manual I created this function:
func SentryLogger(lvl logger.Level) logger.FieldLogger {
l := logrus.New()
l.Level = lvl
levels := []logrus.Level{
logrus.PanicLevel,
logrus.FatalLevel,
logrus.ErrorLevel,
}
hook, err := logrus_sentry.NewSentryHook("your sentry dsn", levels)
hook.StacktraceConfiguration.Enable = true
hook.StacktraceConfiguration.IncludeErrorBreadcrumb = true
if err == nil {
l.Hooks.Add(hook)
}
return logger.Logrus{FieldLogger: l}
}
Then added to the buffalo options in the app.go
Logger: SentryLogger(logger.DebugLevel),
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have a GC function in Go, It is triggered by pubsub push subscription to a topic. I am trying to receive the publishTime and it does not appear populated.
The specs say string (Timestamp format), however, that field in my model is empty. Every other piece of information is populated except publishTime.
type PubSubMessageModel struct {
Data []byte `json:"data"`
Attributes map[string]string `json:"attributes"`
PublishTime string `json:"publishTime"`
}
Simply trying to log the property;
log.Info().Msgf("Publish Time is - %s\n", m.PublishTime)
results in an empty string:
Publish Time is -
Any suggestions?
It's not very well documented, but it is.
The event structure is different when you have a push to the function directly compare to a push Subscription with a HTTP triggered function.
Instead, you can access publishTime and messageId via the event ID and timestamp properties of the event metadata. This metadata is accessible via the context object that is passed to your function when it is invoked.
In the background context description, in Go, there is an explanation of the package to use (functions/metadata) to get the context values
Here how to achieve this
Perform a go get cloud.google.com/go
Use this dependency in your code and get the message metadata from the context
import (
"cloud.google.com/go/functions/metadata"
"context"
"log"
)
type PubSubMessage struct {
Data []byte `json:"data"`
}
// HelloPubSub consumes a Pub/Sub message.
func HelloPubSub(ctx context.Context, m PubSubMessage) error {
meta,err := metadata.FromContext(ctx)
if err != nil {
log.Println(err)
return err
}
log.Printf("publishTime, %s", meta.Timestamp)
log.Printf("messageId, %s", meta.EventID)
log.Printf("Type, %s", meta.EventType)
log.Printf("Resource, %s", meta.Resource)
return nil
}
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I have 3 packages total: repository, restrict, and main.
In my repository package, I have a structure called "RestrictionRuleRepository" defined as:
type RestrictionRuleRepository struct {
storage map[string]float64
}
In another package restrict, I have a "NewService" function defined:
func NewService(repository rule.Repository) Service {
return &service{
repository: repository,
}
}
Finally, in my package main, I have these two lines of code:
ruleRepo := repository.RestrictionRuleRepository{}
restrictionService := restrict.NewService(&ruleRepo)
My code is compiling without any errors. Why is this allowed in Golang? Doesn't my NewService function expect a Repository type, but I am passing in the address of a RestrictionRuleRepository struct to it?
Most likely rule.Repository is an interface and the *RestrictionRuleRepository type just happens to implement that interface.
Here is an example:
package main
import (
"fmt"
)
type Repository interface {
SayHi()
}
type RestrictionRuleRepository struct {
storage map[string]float64
}
func (r *RestrictionRuleRepository) SayHi() {
fmt.Println("Hi!")
}
type service struct {
repository Repository
}
type Service interface {
MakeRepoSayHi()
}
func NewService(repository Repository) Service {
return &service{
repository: repository,
}
}
func (s *service) MakeRepoSayHi() {
s.repository.SayHi()
}
func main() {
ruleRepo := RestrictionRuleRepository{}
restrictionService := NewService(&ruleRepo)
restrictionService.MakeRepoSayHi()
}
This compiles fine as you can see in https://play.golang.org/p/bjKYZLiVKCh.
I also recommend https://tour.golang.org/methods/9 as a good place to get started with interfaces.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
There is a recommended way where put receivers in Go when we have multiple structs in one file?
Option A: Methods after each struct
Buyer struct {
// omitted code
}
func (s *Buyer) Buy() {
// omitted code
}
Seller struct {
// omitted code
}
func (s *Seller) Sell() {
// omitted code
}
Option B: Methods after all structs
Buyer struct {
// omitted code
}
Seller struct {
// omitted code
}
func (s *Buyer) Buy() {
// omitted code
}
func (s *Seller) Sell() {
// omitted code
}
The language spec allows you to put them anywhere in the same package (you can put them in different files too but must be in the same package). Spec: Method declarations:
A receiver base type cannot be a pointer or interface type and it must be defined in the same package as the method.
Other than that it's just common sense. Put them close (next) to the receiver type (which is Option A in your question). Easier to find, easier to maintain.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
i am confusing that, is below snippet perfect?
import "sync"
import "sync/atomic"
var initialized uint32
var instance *singleton
var instance *singleton
var once sync.Once
func GetInstance() *singleton {
once.Do(func() {
instance = &singleton{}
})
return instance
}
atomic.StoreUint32(&initialized, 1) will flush instance to all CPUs?
i think i need add an atomic store and load for instance, like below snippet
var instance *singleton
var once sync.Once
func GetInstance() *singleton {
once.Do(func() {
atomic.StorePointer(&instance, &singleton{})
})
return atomic.LoadPointer(&instance)
}
i think Once.Do is only guarantee execute function f one time.
and atomic.StoreUint32(&o.done, 1) is only memory barrier for o.done.
it doesn't ensure instance is global visible
func (o *Once) Do(f func()) {
if atomic.LoadUint32(&o.done) == 1 {
return
}
// Slow-path.
o.m.Lock()
defer o.m.Unlock()
if o.done == 0 {
defer atomic.StoreUint32(&o.done, 1)
f()
}
}
Lets break down your question to two pieces:
Singletons
Atomics and the Go memory model
Singletons
Go has package level variables. These are instantiated before anything has the chance to get moving, therefore if you good with these things being created as soon as the package is used, you get a singleton for free.
package somepack
var(
connection = createConn()
)
func Connection() SomeConnection {
return connection
}
connection will be created once and therefore Connection() will return the same instance of it safely.
Sometimes developers reach for a singleton when they want "lazy" instantiation. This is a good idea if the resource is expensive to create and not always needed. This is where sync.Once is useful.
var (
connection SomeConnection // Not instantiated
connectionOnce sync.Once
)
func Connection() SomeConnection {
connectionOnce.Do(func(){
connection = createConn()
})
return connection
}
Notice I'm not doing anything special with the assignment (e.g., atomic.Store()). This is because sync.Once takes care of all the locking required for this to be safe.
Atomics and the Go memory model
A good resource to start with is the published docs for this: The Go Memory Model
Your concern of "flushing" to the different CPUs is valid (despite some of the comments) because each CPU has its own cache with its own state. C++ (among other languages like Rust) developers tend to care about this because they get to. Go developers don't get to care AS much because Go only has "happens before". Rust in fact has some nice docs on it.
That being said, you normally don't need to worry about it. A mutex (and sync.Once) will force the state of the memory on each CPU to be what you would expect.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I would probably prefer to use pressly/chi, but I guess it makes no difference. I imagine given an input URL like this example.com/Jd8saD.jpg?resize=420x320&fit=crop&rotate=90, then it would go to the following GET function because of r.Get("/:image", ImageGET):
function ImageGET(w http.ResponseWriter, r *http.Request) {
if r.URL.Query().Get("resize") != "" {
// do something
}
if r.URL.Query().Get("crop") != "" {
// do something
}
if r.URL.Query().Get("watermark") != "" {
// do something
}
etc
}
Now, my question is, how should I design whatever function does the image processing so that it will process everything properly and efficiently? I don't expect you to write code that will handle the resizing, but how would these functions look like? Perhaps:
function Resize(size string) (imgfile?, error) {
// the resize stuff
}
What would that returned imgfile even be? A struct containing some relevant img info?
Likely,
imgfile
will satisfy the image.Image interface and not the data saved on disk (ie. the actual jpg file)
Image is a finite rectangular grid of color.Color values taken from a color model.
Lots of 3rd party golang image libraries use image.Image to manipulate images.
I would use a standard image.Image interface retrieved (read to memory) by a filename in the imageGET function and modified according to the queries. You can see also the jpeg golang library from the standard lib.
function ImageGET(w http.ResponseWriter, r *http.Request) {
// GetJPEGImageFromFileSystem must decode os.File content and
// return a golang image.Image interface
img, _ := GetJPEGImageFromFileSystem(r.URL.Query().Get("filename"))
if r.URL.Query().Get("resize") != "" {
// If resizing, write over the image.Image in Memory,
// but not the image File on disk
img, _ = Resize(img, r.URL.Query().GET("resize"))
}
// etc...
}
function Resize(img image.Image, size string) (image.Image, error) {
// the resize stuff -- or, alternatively just call a dependency in the original handler to resize
return resizedImage, nil
}
Now, my question is, how should I design whatever function does the
image processing so that it will process everything properly and
efficiently?
Depends on the package you are using for your stuff and what you want to do with it. If you look for example to the imaging package you see that they return always: *image.NRGBA
That type implements the image.Image interface.
At the next step you can use the Encode function.
func Encode(w io.Writer, img image.Image, format Format) error
As you see that function uses a io.Writer.
function ImageGET(w http.ResponseWriter, r *http.Request) {
// ...
imaging.Encode(w,img,imaging.PNG)
// ...
So you just need to use the writer from the your handler there and ready.
So to keep your function correct just return the image.Image interface.