-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
output/cloudv2: Implement RequestMetadata output #3100
Merged
+4,051
−9
Merged
Changes from all commits
Commits
Show all changes
40 commits
Select commit
Hold shift + click to select a range
04b6fee
Implement RequestMetadata output
Blinkuu 6638db1
Add tracesFlusher tests
Blinkuu b330ee5
Add requestMetadatasCollector tests
Blinkuu 6040bab
Add mappers tests
Blinkuu a1f85c8
Add client tests
Blinkuu fe1140c
Format flush.go
Blinkuu 16d9fb6
Fix `TestConfigApply` test
Blinkuu 0b14184
Add TODO in client.go
Blinkuu e25c778
Fix flush_test.go
Blinkuu fddded2
Add validation logic in mappers.go
Blinkuu a9d9739
Rename `ErrAlreadyInitialized` to `ErrClientAlreadyInitialized`
Blinkuu becd581
Fix linter errors
Blinkuu dc2ed72
Remove unused `shouldStopSendingMetrics()`
Blinkuu fc0a6a2
Add //nolint: nestif directive
Blinkuu 4fa7f4f
Update proto package
Blinkuu 41cbe21
Fix mappers_test.go
Blinkuu 94be8b4
Update proto
Blinkuu 5f7b124
Set HTTP URL label to `name` tag
Blinkuu 7956a52
Update traces host
Blinkuu 1509fde
Remove `gen.sh`
Blinkuu e6129b2
Make `MetadataTraceIDKeyName` private again
Blinkuu 3ffad13
Update min TLS version to 1.3
Blinkuu eb58b6e
Reimplement `CollectRequestMetadatas()``
Blinkuu 0f6448b
Format flush_test.go
Blinkuu 4e677f6
Add //nolint:lll directive
Blinkuu 817b18c
Add copyright notice to common.proto
Blinkuu 7afb9fa
Make internal interfaces private
Blinkuu 456da47
Remove obsolete TODO
Blinkuu 2db5ace
Minimize critical section
Blinkuu 39f3da5
Add shutdown hooks
Blinkuu b3e8f86
Fix after merge
Blinkuu 127f3a8
Remove argument name from the `flusher` interface
Blinkuu 27cd2bc
Update js/modules/k6/experimental/tracing/client.go
Blinkuu 24602fb
Store insightsClient instead of shutdownHooks
Blinkuu 1910235
Update output/cloud/expv2/output.go
Blinkuu 2b82672
Update output/cloud/expv2/output.go
Blinkuu 117858c
Fix flush_test.go
Blinkuu 029632e
Bring back 5s timeout in config_test.go
Blinkuu 3fbac3e
Remove redundant validation logic
Blinkuu 6ffe102
Rollback changes in metric.pb.go
Blinkuu File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,207 @@ | ||
package insights | ||
|
||
import ( | ||
"context" | ||
"crypto/tls" | ||
"errors" | ||
"fmt" | ||
"net" | ||
"sync" | ||
|
||
"google.golang.org/grpc" | ||
"google.golang.org/grpc/credentials" | ||
"google.golang.org/grpc/credentials/insecure" | ||
"google.golang.org/grpc/status" | ||
|
||
"go.k6.io/k6/cloudapi/insights/proto/v1/ingester" | ||
) | ||
|
||
const ( | ||
testRunIDHeader = "X-K6TestRun-Id" | ||
authorizationHeader = "Authorization" | ||
) | ||
|
||
var ( | ||
// ErrClientAlreadyInitialized is returned when the client is already initialized. | ||
ErrClientAlreadyInitialized = errors.New("insights client already initialized") | ||
|
||
// ErrClientClosed is returned when the client is closed. | ||
ErrClientClosed = errors.New("insights client closed") | ||
) | ||
|
||
// ClientConfig is the configuration for the client. | ||
type ClientConfig struct { | ||
IngesterHost string | ||
ConnectConfig ClientConnectConfig | ||
AuthConfig ClientAuthConfig | ||
TLSConfig ClientTLSConfig | ||
} | ||
|
||
// ClientConnectConfig is the configuration for the client connection. | ||
type ClientConnectConfig struct { | ||
Block bool | ||
FailOnNonTempDialError bool | ||
Dialer func(context.Context, string) (net.Conn, error) | ||
} | ||
|
||
// ClientAuthConfig is the configuration for the client authentication. | ||
type ClientAuthConfig struct { | ||
Enabled bool | ||
TestRunID int64 | ||
Token string | ||
RequireTransportSecurity bool | ||
} | ||
|
||
// ClientTLSConfig is the configuration for the client TLS. | ||
type ClientTLSConfig struct { | ||
Insecure bool | ||
CertFile string | ||
} | ||
|
||
// Client is the client for the k6 Insights ingester service. | ||
type Client struct { | ||
cfg ClientConfig | ||
client ingester.IngesterServiceClient | ||
conn *grpc.ClientConn | ||
connMu *sync.RWMutex | ||
} | ||
|
||
// NewClient creates a new client. | ||
func NewClient(cfg ClientConfig) *Client { | ||
return &Client{ | ||
cfg: cfg, | ||
client: nil, | ||
conn: nil, | ||
connMu: &sync.RWMutex{}, | ||
} | ||
} | ||
|
||
// Dial creates a client connection using ClientConfig. | ||
func (c *Client) Dial(ctx context.Context) error { | ||
c.connMu.Lock() | ||
defer c.connMu.Unlock() | ||
|
||
if c.conn != nil { | ||
return ErrClientAlreadyInitialized | ||
} | ||
|
||
opts, err := dialOptionsFromClientConfig(c.cfg) | ||
if err != nil { | ||
return fmt.Errorf("failed to create dial options: %w", err) | ||
} | ||
|
||
conn, err := grpc.DialContext(ctx, c.cfg.IngesterHost, opts...) | ||
if err != nil { | ||
return fmt.Errorf("failed to dial: %w", err) | ||
} | ||
|
||
c.client = ingester.NewIngesterServiceClient(conn) | ||
c.conn = conn | ||
|
||
return nil | ||
} | ||
|
||
// IngestRequestMetadatasBatch ingests a batch of request metadatas. | ||
func (c *Client) IngestRequestMetadatasBatch(ctx context.Context, requestMetadatas RequestMetadatas) error { | ||
c.connMu.RLock() | ||
closed := c.conn == nil | ||
c.connMu.RUnlock() | ||
if closed { | ||
return ErrClientClosed | ||
} | ||
|
||
if len(requestMetadatas) < 1 { | ||
return nil | ||
} | ||
|
||
req, err := newBatchCreateRequestMetadatasRequest(requestMetadatas) | ||
if err != nil { | ||
return fmt.Errorf("failed to create request from request metadatas: %w", err) | ||
} | ||
|
||
// TODO(lukasz, retry-support): Retry request with returned metadatas. | ||
// | ||
// Note: There is currently no backend support backing up this retry mechanism. | ||
codebien marked this conversation as resolved.
Show resolved
Hide resolved
|
||
_, err = c.client.BatchCreateRequestMetadatas(ctx, req) | ||
if err != nil { | ||
st := status.Convert(err) | ||
return fmt.Errorf("failed to ingest request metadatas batch: code=%s, msg=%s", st.Code().String(), st.Message()) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// Close closes the client. | ||
func (c *Client) Close() error { | ||
c.connMu.Lock() | ||
defer c.connMu.Unlock() | ||
|
||
if c.conn == nil { | ||
return ErrClientClosed | ||
} | ||
|
||
conn := c.conn | ||
c.client = nil | ||
c.conn = nil | ||
|
||
return conn.Close() | ||
} | ||
|
||
func dialOptionsFromClientConfig(cfg ClientConfig) ([]grpc.DialOption, error) { | ||
var opts []grpc.DialOption | ||
|
||
if cfg.ConnectConfig.Block { | ||
opts = append(opts, grpc.WithBlock()) | ||
} | ||
|
||
if cfg.ConnectConfig.FailOnNonTempDialError { | ||
opts = append(opts, grpc.FailOnNonTempDialError(true)) | ||
} | ||
|
||
if cfg.ConnectConfig.Dialer != nil { | ||
opts = append(opts, grpc.WithContextDialer(cfg.ConnectConfig.Dialer)) | ||
} | ||
|
||
if cfg.TLSConfig.Insecure { //nolint: nestif | ||
opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials())) | ||
} else { | ||
if cfg.TLSConfig.CertFile != "" { | ||
creds, err := credentials.NewClientTLSFromFile(cfg.TLSConfig.CertFile, "") | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to load TLS credentials from file: %w", err) | ||
} | ||
opts = append(opts, grpc.WithTransportCredentials(creds)) | ||
codebien marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} else { | ||
opts = append(opts, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{MinVersion: tls.VersionTLS13}))) | ||
} | ||
} | ||
|
||
if cfg.AuthConfig.Enabled { | ||
opts = append(opts, grpc.WithPerRPCCredentials(newPerRPCCredentials(cfg.AuthConfig))) | ||
} | ||
|
||
return opts, nil | ||
} | ||
|
||
type perRPCCredentials struct { | ||
metadata map[string]string | ||
requireTransportSecurity bool | ||
} | ||
|
||
func newPerRPCCredentials(cfg ClientAuthConfig) perRPCCredentials { | ||
return perRPCCredentials{ | ||
metadata: map[string]string{ | ||
testRunIDHeader: fmt.Sprintf("%d", cfg.TestRunID), | ||
authorizationHeader: fmt.Sprintf("Token %s", cfg.Token), | ||
}, | ||
requireTransportSecurity: cfg.RequireTransportSecurity, | ||
} | ||
} | ||
|
||
func (c perRPCCredentials) GetRequestMetadata(_ context.Context, _ ...string) (map[string]string, error) { | ||
return c.metadata, nil | ||
} | ||
|
||
func (c perRPCCredentials) RequireTransportSecurity() bool { | ||
return c.requireTransportSecurity | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Metadata doesn't have the plural, am I missing something? I see it is used all over the code so if we change then keep it consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we are aware it doesn't have a plural form. However, together with @vortegatorres we decided to add the
s
suffix to match the conventions defined in Google API Design Guide. I'd like to keep this as "request metadatas".There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not certain which part of the Google API Design Docs apply here ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See https://google.aip.dev/233:
We use singular for a single request and plural for batch requests (see here)