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
}
Related
The demand is to add an user of ObjectType PosixAccount into a group of ObjectType groupOfNames by adding it as value of attribute member.
I'm using go-ldap module to accomplish that.
Here below is a sample of the code I've written to complete this demand:
package main
import (
"log"
"github.com/go-ldap/ldap"
)
func main() {
// connection code here
PutOnGroup := ldap.NewModifyRequest("cn=0000-00000-00000f-abc123-app-
session,ou=servicesAccounts,dc=example,dc=com", []ldap.Control{})
PutOnGroup.Replace("member", []string{"cn=1000000-fa00-de00-ac00-f00c00e00d00b00-
ingestion-svc"})
err = conn.Modify(PutOnGroup)
if err != nil {
log.Fatalf("error putting user on group %v: %v", PutOnGroup, err)
}
}
The thing is by doing that I just replace the user which is already member's attribute of group.
I'd like to input this member into the group alongside with members which is already there.
How could I do that?
I'm not used to ask questions in StackOverflow so if my question is lacking of details I'm looking foward to provide more information.
This problem was solved by changing the ldap.NewModifyRequest's function Replace to Add.
PutOnGroup := ldap.NewModifyRequest("cn=0000-00000-00000f-abc123-app-
session,ou=servicesAccounts,dc=example,dc=com", []ldap.Control{})
PutOnGroup.Add("member", []string{"cn=1000000-fa00-de00-ac00-f00c00e00d00b00-
ingestion-svc"})
I'm trying to access messageId of the Pub/Sub message triggering my Golang function. To do so, I'm trying to modify the PubSubMessage struct from the Cloud Functions documentation:
// PubSubMessage is the payload of a Pub/Sub event.
// See the documentation for more details:
// https://cloud.google.com/pubsub/docs/reference/rest/v1/PubsubMessage
type PubSubMessage struct {
Data []byte `json:"data"`
MessageId string `json:"messageId"`
}
The function compiles OK but the MessageID value comes empty. Changing the type doesn't help.
I wonder if there's a way to get the triggering message Id from within a function. Or maybe that's not passed to functions at all?
In the document you refer,
Event structure
Cloud Functions triggered from a Pub/Sub topic will be
sent events conforming to the PubsubMessage type, with the caveat that
publishTime and messageId are not directly available in the
PubsubMessage. 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.
You can get messageId like this.
import "cloud.google.com/go/functions/metadata"
func YourFunc(ctx context.Context, m PubSubMessage) error {
metadata, err := metadata.FromContext(ctx)
if err != nil {
// Handle Error
}
messageId := metadata.EventID
// Rest of your code below here.
}
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),
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 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.