Problem with export open telemetry data to newRelic - go

I have an issue with exporting and sending the open telemetry data to the newRelic's GRPC endpoint.
This is my snippet code that tries to connect to the newRelic endpoint:
var headers = map[string]string{
"api-key": "my newRelc API key",
}
var clientOpts = []otlptracegrpc.Option{
otlptracegrpc.WithEndpoint("https://otlp.nr-data.net:4317"),
otlptracegrpc.WithInsecure(),
otlptracegrpc.WithReconnectionPeriod(2 * time.Second),
otlptracegrpc.WithDialOption(grpc.WithBlock()),
otlptracegrpc.WithTimeout(30 * time.Second),
otlptracegrpc.WithHeaders(headers),
otlptracegrpc.WithCompressor("gzip"),
}
otlpExporter, err := otlptrace.New(ctx, otlptracegrpc.NewClient(clientOpts...))
if err != nil {
return nil, fmt.Errorf("creating OTLP trace exporter: %w", err)
}
resource, _ := g.Config.resource(ctx)
tracerProvider := trace.NewTracerProvider(
trace.WithSampler(trace.AlwaysSample()),
trace.WithBatcher(otlpExporter),
trace.WithResource(resource),
)
otel.SetTracerProvider(tracerProvider)
it stuck in step otlptrace.New.
I'm new in OpenTelemetry, I read the open telemetry documentation and I can print Otel data in the console but when I want to export it to newrelic it does not work.
I read newRelic Otel documentation too and they had an exporter SDK but it discontinued and they provide this new GRPC endpoint but it does not have well documentation and example.
Do you have any idea?

I found the problem, The issue was about TLS.
I replaced this line:
otlptracegrpc.WithInsecure(),
with this line:
otlptracegrpc.WithTLSCredentials(credentials.NewClientTLSFromCert(nil, "")),

Related

Is there a way to add collaborators to a Google Sheet using the Golang Client Library or REST API?

I am able to create a new spreadsheet with the gsheets client library, and my next step is to add editors to that newly created sheet so that the sheet can be accessed by the users of the application
Here is the code for creating the sheet:
ctx := context.Background()
srv, err := gsheets.NewService(ctx)
if err != nil {
log.Printf("Unable to retrieve Sheets client: %v", err)
}
sp := &gsheets.Spreadsheet{
Properties: &gsheets.SpreadsheetProperties{
Title: groupName,
},
}
spreadsheet, err := srv.Spreadsheets.Create(sp).Do()
if err != nil {
return nil, err
}
I have searched through the golang client library docs and the REST API docs, and I am unable to find anything related to adding collaborators
I was expecting there to be some request object that allows me to add a collaborator using their email and role:
req := gsheets.Request{
AddCollaborator: &gsheets.AddCollaboratorRequest{
Email: "person#gmail.com",
Role: "editor",
},
}
busr := &gsheets.BatchUpdateSpreadsheetRequest{
Requests: []*gsheets.Request{&req},
}
res, err := srv.Spreadsheets.BatchUpdate(spreadsheetId, busr).Do()
or at the very least I was expecting there to be an API endpoint where I can achieve the same result
I am also curious if there is a way to create this new spreadsheet as read only to the public? This would at least allow me to continue developing
It is possible to add editors with the google.golang.org/api/sheets/v4 library.
You can simply create a spreadsheet with:
func (r *SpreadsheetsService) Create(spreadsheet *Spreadsheet) *SpreadsheetsCreateCall
and add editors with Editor type:
type Editors struct {
...
// Users: The email addresses of users with edit access to the protected
// range.
Users []string `json:"users,omitempty"`
...
}
Check library docs for more details.

400 Bad request when generating the Google API access token using Go iamcredentials client API

I am trying to implement iamcredentials Go API client to generate an Access Token to access some Google APIs via REST API, I am using this code
package main
import (
"context"
"log"
"google.golang.org/api/iamcredentials/v1"
)
func main() {
iamcredentialsService, err := iamcredentials.NewService(context.Background())
if err != nil {
log.Println("error initialize iamcredential Service ", err)
return
}
accessTokenCall := iamcredentialsService.Projects.ServiceAccounts.GenerateAccessToken(
"projects/-/serviceAccounts/some-sa#some-project-id.iam.gserviceaccount.com:generateAccessToken",
&iamcredentials.GenerateAccessTokenRequest{
Scope: []string{
iamcredentials.CloudPlatformScope,
},
},
)
iamResp, err := accessTokenCall.Do()
if err != nil {
log.Println("error generate access token", err)
return
}
log.Println(iamResp)
}
But when I tried to run the above snippet, I got this message
go run main.go
error generate access token googleapi: Error 400: Request contains an invalid argument., badRequest
Is there any way to check which one is causing the above response? I am not sure since there isn't any good example of implementation. Any help would be appreciated, Thanks.
Notes :
I have checked following documentation on this topic https://cloud.google.com/iam/docs/creating-short-lived-service-account-credentials and this https://pkg.go.dev/google.golang.org/api/iamcredentials/v1#pkg-overview
I have already setup the Service account using Service Account Token Creator role on IAM and also enabled the IAM API from the console
Also I have added GOOGLE_APPLICATION_CREDENTIALS to the environment variables as suggested
#DanielFarrell is right, you need to remove the :generateAccessToken at the end. Here the documentation in the code. Don't hesitate to explore it, it's open source ;)
// GenerateAccessToken: Generates an OAuth 2.0 access token for a
// service account.
//
// - name: The resource name of the service account for which the
// credentials are requested, in the following format:
// `projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`. The `-`
// wildcard character is required; replacing it with a project ID is
// invalid.
func (r *ProjectsServiceAccountsService) GenerateAccessToken(name string, generateaccesstokenrequest *GenerateAccessTokenRequest) *ProjectsServiceAccountsGenerateAccessTokenCall {
c := &ProjectsServiceAccountsGenerateAccessTokenCall{s: r.s, urlParams_: make(gensupport.URLParams)}
c.name = name
c.generateaccesstokenrequest = generateaccesstokenrequest
return c
}

Google Translation API WithAPIKey option error

I am building a multilingual SAAS website builder in Golang which is run per client. Each client can have their own website and can translate their website in the desired language.
Since the feature is per client, so I collected an API key from client, which I used to translate their site content.
Here is the code,
V2
package main
import (
"context"
"fmt"
"cloud.google.com/go/translate"
"google.golang.org/api/option"
)
func main() {
translationStrings := []string{"hello"}
ctx := context.Background()
opts := option.WithAPIKey(APIKEY)
c, err := translate.NewClient(ctx, opts)
if err != nil {
fmt.Println(err)
}
defer c.Close()
resp, err := c.Translate(ctx, translationStrings, language.French,
&translate.Options{
Source: language.English,
Format: translate.Text,
})
if err != nil {
fmt.Println(err)
}
fmt.Println(resp)
}
V3
translate "cloud.google.com/go/translate/apiv3"
translatepb "google.golang.org/genproto/googleapis/cloud/translate/v3"
c, err := translate.NewTranslationClient(ctx, opts)
if err != nil {
fmt.Println(err)
}
defer c.Close()
req := &translatepb.TranslateTextRequest{
Contents: translationStrings,
TargetLanguageCode: "sr-Latn",
}
resp, err := c.TranslateText(ctx, req)
The code with V2 works well but the same code with V3 does not work. It gives error:
API keys are not supported for gRPC APIs. Remove the WithAPIKey option from your client-creating call.
As stated in the error, it is asking me to remove WithAPIKey options. But if I remove this then how will I use the api key for each client.
I have chosen to work with V3 apis because the will be translated as a whole so it will be a large request. I have read in the docs that V3 api can work in batches.
So my questions are:
how can I use per client api key structure with api V3?
Is it okay to go with the api V2 for the purpose as stated above?
Cloud Translation API v3 does not currently support API keys. It is recommended that you create a service account for Cloud Translation API v3 requests. For information on creating a service account, see Creating and managing service accounts. Your service account must be added to one of the IAM roles added for Cloud Translation API v3.

Golang HTTP uploading file to S3 using tusd only uploading metadata

I am using the tusd library to upload a file directly to S3 in Go. It seems to be functioning however tusd uploads two files a .info metadata file and a .bin actual content file. For some reason my code is only uploading the info file.
The documentation is quite tricky to navigate so perhaps I have missed a setting somewhere
Code as gist to show both the server and the client code.
There are mutiple issues here.
Your tus libary import paths are wrong they should be:
"github.com/tus/tusd/pkg/handler"
"github.com/tus/tusd/pkg/s3store"
You dont use the S3 store propely, you setup a configuration to have storage directly on your server
fStore := filestore.FileStore{
Path: "./uploads",
}
Instead it should be something like this:
// S3 acces configuration
s3Config := &aws.Config{
Region: aws.String(os.Getenv("AWS_REGION")),
Credentials: credentials.NewStaticCredentials(os.Getenv("AWS_ACCESS_KEY_ID"), os.Getenv("AWS_SECRET_ACCESS_KEY"), ""),
DisableSSL: aws.Bool(true),
S3ForcePathStyle: aws.Bool(true),
}
// Setting up the s3 storage
s3Store := s3store.New(os.Getenv("AWS_BUCKET_NAME"), s3.New(session.Must(session.NewSession()), s3Config))
// Creates a new and empty store composer
composer := handler.NewStoreComposer()
// UseIn sets this store as the core data store in the passed composer and adds all possible extension to it.
s3Store.UseIn(composer)
// Setting up handler
handler, err := handler.NewHandler(handler.Config{
BasePath: "/files/",
StoreComposer: composer,
})
if err != nil {
panic(fmt.Errorf("Unable to create handler: %s", err))
}
// Listen and serve
http.Handle("/files/", http.StripPrefix("/files/", handler))
err = http.ListenAndServe(":8080", nil)
if err != nil {
panic(fmt.Errorf("Unable to listen: %s", err))
}
It is possible that your client isnt working proprely also (I didnt test it).
I would recommend you use https://github.com/eventials/go-tus instead of trying to implement the protocol by yourself.

How to Assume Cross-Account Role?

AWS' Golang SDK says that I should use stscreds.AssumeRoleProvider to assume a cross-account role (in this case, for querying another account's DynamoDb table from a web server). This code works:
var sess *session.Session
func init() {
sess = session.Must(session.NewSession(&aws.Config{
Region: aws.String("us-west-2"),
}))
}
func getDynamoDbClient() *dynamodb.DynamoDB {
crossAccountRoleArn := "arn:...:my-cross-account-role-ARN"
creds := stscreds.NewCredentials(sess, crossAccountRoleArn, func(arp *stscreds.AssumeRoleProvider) {
arp.RoleSessionName = "my-role-session-name"
arp.Duration = 60 * time.Minute
arp.ExpiryWindow = 30 * time.Second
})
dynamoDbClient := dynamodb.New(sess, aws.NewConfig().WithCredentials(creds))
return dynamoDbClient
}
According to the documentation, the returned client is thread-safe:
DynamoDB methods are safe to use concurrently.
The question is, since the credential are auto-renewed via stscreds.AssumeRoleProvider, do I
Need to new up a new client on each request (to ensure that I've got unexpired credentials), or
Can I new up a DynamoDb client when the web server starts up, and reuse it for the life of the web server?
Edited To Note:
I dug into the source code for the Golang AWS SDK, and it looks like the credentials returned by stscreds.NewCredentials() are nothing more than a wrapper around a reference to the stscreds.AssumeRoleProvider. So it seems likely to me that the client will magically get auto-renewed credentials.
AWS' documentation leaves something to be desired.
roleArn := "arn:aws:iam::1234567890:role/my-role"
awsSession, _ := session.NewSession(&aws.Config{
Region: aws.String("us-west-2"),
})
stsClient := sts.New(awsSession)
stsRequest := sts.AssumeRoleInput{
RoleArn: aws.String(roleArn),
RoleSessionName: aws.String("my-role-test"),
DurationSeconds: aws.Int64(900), //min allowed
}
stsResponse, err := stsClient.AssumeRole(&stsRequest)
if err != nil {
log.Fatal("an exception occurred when attempting to assume the my role. error=" + err.Error())
}
os.Setenv("AWS_ACCESS_KEY_ID", *stsResponse.Credentials.AccessKeyId)
os.Setenv("AWS_SECRET_ACCESS_KEY", *stsResponse.Credentials.SecretAccessKey)
os.Setenv("AWS_SESSION_TOKEN", *stsResponse.Credentials.SessionToken)
os.Setenv("AWS_SECURITY_TOKEN", *stsResponse.Credentials.SessionToken)
os.Setenv("ASSUMED_ROLE", roleArn)

Resources