Skip to content
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

Experimental tracing module (2/3): define and expose a tracing.Client #2854

Conversation

oleiade
Copy link
Member

@oleiade oleiade commented Jan 13, 2023

About

To keep Pull Requests as small as possible and reduce the review burden, this PR is the second in a chain of three implementing the decided API design for the experimental tracing module.

⚠️ ✋🏻 This PR is part of a PR chain, and is based on #2853

This second PR builds upon #2853 and adds a Client type to k6/experimental/tracing. This type mimics the relevant part of the HTTP module to allow users to perform HTTP requests embedding a trace context while also attaching the produced trace id as output metadata on the HTTP-related samples. In the larger context of the module's goal, the Client should hold the underlying logic for the instrumentHTTP function that's to come in the third PR. Still, it also allows users to selectively trace requests and reconfigure their tracing configuration on the fly if they wish.

To achieve that, it is built upon the HTTP module's request function, which wraps with hooking logic to ensure the expected headers are produced and present and emit the output metadata.

The Client is configured using an options object that lets the user select the propagation format they use. Other options, such as sampling rate, and baggage, have been added for forward compatibility and convenience but will lead to "not implemented" errors if used.

Example of it in action

import http from "k6/http";
import { check } from "k6";
import tracing from "k6/experimental/tracing";

// Explicitly instantiating a tracing client allows to distringuish
// instrumented from non-instrumented HTTP calls, by keeping APIs separate.
// It also allows for finer-grained configuration control, by letting
// users changing the tracing configuration on the fly during their
// script's execution.
let instrumentedHTTP = new tracing.Client({
	propagator: "w3c",
});

const testData = { name: "Bert" };

export default () => {
	// Using the tracing client instance, HTTP calls will have
	// their trace context headers set.
	let res = instrumentedHTTP.request("GET", "http://httpbin.org/get", null, {
		headers: {
			"X-Example-Header": "instrumented/request",
		},
	});
	check(res, {
		"status is 200": (r) => r.status === 200,
	});

	// The tracing client offers more flexibility over
	// the `instrumentHTTP` function, as it leaves the
	// imported standard http module untouched. Thus,
	// one can still perform non-instrumented HTTP calls
	// using it.
	res = http.post("http://httpbin.org/post", JSON.stringify(testData), {
		headers: { "X-Example-Header": "noninstrumented/post" },
	});
	check(res, {
		"status is 200": (r) => r.status === 200,
	});

	res = instrumentedHTTP.del("http://httpbin.org/delete", null, {
		headers: { "X-Example-Header": "instrumented/delete" },
	});
	check(res, {
		"status is 200": (r) => r.status === 200,
	});
};

In order to observe this example in action, I recommend to run it with the --http-debug too. That way you'll be able to observe the Traceparent header being added (note that when using the b3 or jaeger propagators, the header is named differently.

go run go.k6.io/k6 run --http-debug samples/experimental/tracing-client.js

Review

⚠️ Although this PR has >1000 lines addition, a considerable chunk of it is testing. I believe the amount of actual logic is somewhat limited ⚠️

The commits have been organized to be progressive, and make sense as a sequence; thus, you should review them in order.

References

Previous PR: #2853

@codecov-commenter
Copy link

codecov-commenter commented Jan 13, 2023

Codecov Report

❗ No coverage uploaded for pull request base (experimental/tracing-module-propagators@3889364). Click here to learn what that means.
The diff coverage is n/a.

@@                            Coverage Diff                             @@
##             experimental/tracing-module-propagators    #2854   +/-   ##
==========================================================================
  Coverage                                           ?   76.68%           
==========================================================================
  Files                                              ?      222           
  Lines                                              ?    16796           
  Branches                                           ?        0           
==========================================================================
  Hits                                               ?    12880           
  Misses                                             ?     3086           
  Partials                                           ?      830           
Flag Coverage Δ
ubuntu 76.68% <0.00%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@oleiade oleiade requested review from mstoykov and codebien and removed request for olegbespalov January 13, 2023 16:56
@oleiade
Copy link
Member Author

oleiade commented Jan 13, 2023

Heads-up @olegbespalov, I removed you from reviewers to ensure consistency in the PR-chain. This PR is indeed part of a chain, and the bot has automatically selected @imiric and @codebien for the first and last one. I aligned the reviewers for this one as I believe it will make the review easier for reviewers if they review the three of them.

If you wish to review this module, and have time for it, feel free to add yourself back or ping me to do; I'll gladly do so 🙇🏻 👍🏻

@codebien
Copy link
Contributor

@oleiade can you change the base branch to experimental/tracing-module-propagators, please? Otherwise, we see the changes from 1/3 here also.

@oleiade oleiade changed the base branch from master to experimental/tracing-module-propagators January 16, 2023 10:04
@oleiade
Copy link
Member Author

oleiade commented Jan 16, 2023

@codebien done ✅ thanks for pointing it out 🙇🏻

@oleiade oleiade force-pushed the experimental/tracing-module-propagators branch 2 times, most recently from 1b4a7a9 to e3463aa Compare January 16, 2023 14:59
@oleiade oleiade force-pushed the experimental/tracing-module-client branch 2 times, most recently from 9dbd43f to f6f06f5 Compare January 16, 2023 15:03
@oleiade oleiade force-pushed the experimental/tracing-module-propagators branch 2 times, most recently from 9df375a to beeacb4 Compare January 16, 2023 15:44
@oleiade oleiade force-pushed the experimental/tracing-module-client branch from f6f06f5 to e6452eb Compare January 16, 2023 15:46
Copy link
Contributor

@mstoykov mstoykov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good in general but I have a bunch of comments

js/modules/k6/experimental/tracing/client.go Outdated Show resolved Hide resolved
js/modules/k6/experimental/tracing/client.go Outdated Show resolved Hide resolved
js/modules/k6/experimental/tracing/client.go Outdated Show resolved Hide resolved
js/modules/k6/experimental/tracing/client.go Outdated Show resolved Hide resolved
js/modules/k6/experimental/tracing/client.go Outdated Show resolved Hide resolved
Comment on lines 22 to 27
var (
isW3C = i.Propagator == W3CPropagatorName
isB3 = i.Propagator == B3PropagatorName
isJaeger = i.Propagator == JaegerPropagatorName
)
if !isW3C && !isB3 && !isJaeger {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason we just don't do the equal comparision directly in the if sttatement?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a style recommendation I discovered in the Google style guide, which, I find, helps with readability, as the if statement ends up much shorter and reads almost like a sentence. I'm not hung onto this though, if you have a strong opinion against that, I'm happy to drop it 🙇🏻

js/modules/k6/experimental/tracing/client_test.go Outdated Show resolved Hide resolved
js/modules/k6/experimental/tracing/client_test.go Outdated Show resolved Hide resolved
cmd/integration_test.go Outdated Show resolved Hide resolved
Copy link
Contributor

@codebien codebien left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@oleiade Added a few comments.

It should already be possible to introduce an integration test here, so I would add it. WDYT?

js/modules/k6/experimental/tracing/client.go Show resolved Hide resolved
js/modules/k6/experimental/tracing/client.go Outdated Show resolved Hide resolved
js/modules/k6/experimental/tracing/goja.go Show resolved Hide resolved
js/modules/k6/experimental/tracing/options.go Show resolved Hide resolved
@oleiade oleiade force-pushed the experimental/tracing-module-client branch from e6452eb to ae5537e Compare January 19, 2023 10:34
@oleiade oleiade force-pushed the experimental/tracing-module-propagators branch from beeacb4 to 8b5b35c Compare January 19, 2023 14:05
@oleiade oleiade force-pushed the experimental/tracing-module-client branch 2 times, most recently from 936303a to ba46f51 Compare January 19, 2023 14:08
@oleiade
Copy link
Member Author

oleiade commented Jan 23, 2023

@codebien I've rebased the PR chain on the latest state of master, and updated the integration tests accordingly 👍🏻

@oleiade oleiade force-pushed the experimental/tracing-module-client branch from 5f006aa to 0821167 Compare January 23, 2023 16:10
This commit exposes the Client constructor publicly as part of the
k6/experimental/tracing module. From this point forward users will be
able to instantiate the Client, and perform instrumented HTTP requests
using it.

This commit also adds a bunch of integration tests covering the expected
behavior of the module's API.
@oleiade oleiade force-pushed the experimental/tracing-module-client branch from 0821167 to 4b0fa98 Compare January 24, 2023 09:13
Copy link
Contributor

@codebien codebien left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👏

@oleiade oleiade requested a review from mstoykov January 24, 2023 09:23
Copy link
Contributor

@mstoykov mstoykov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a nitpick about style with common.Throw, but LGTM even with it

js/modules/k6/experimental/tracing/client.go Outdated Show resolved Hide resolved
Comment on lines +67 to +72
assert.NotNil(t, gotParams)
gotHeaders := gotParams.Get("headers").ToObject(rt)
assert.NotNil(t, gotHeaders)
gotTraceParent := gotHeaders.Get(traceparentHeaderName)
assert.NotNil(t, gotTraceParent)
assert.Equal(t, testTraceID, gotTraceParent.String())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: In general I prefer to user require as it will stop the execution directly which helps in two ways:

  1. I won't get a wall of text when i break somethign listing 20 things that went wrong, when the first thing that went wrong is likely to tell me what I neeed to know to fix it.
  2. In this particular case assert.NotNil failing means that hte test will panic with nil exception. Arguably you can mix assert and require, but I have rarely been in a case taht this makes sense 🤷

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, I try to use require when it's a requirement for the test, as in: "this is required even to perform the test in the first place", and use assert for stuff that's tested. I guess I approach it in a rather semantic way, "this is required to perform the test", and "this asserts the behavior of the tested code is correct".

It's also how I understood it to be used in the tests I've been exposed.

Do you have a strong opinion on this, or would it be fine if I keep it like this? I'm okay with either way.

Co-authored-by: Ivan <2103732+codebien@users.noreply.github.com>
Copy link
Contributor

@codebien codebien left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking so we remember to rebase the fixups before merging

@mstoykov
Copy link
Contributor

Blocking so we remember to rebase the fixups before merging

Won't this just be "squashing" it in the previours PR ?

@oleiade
Copy link
Member Author

oleiade commented Jan 25, 2023

Indeed, I would expect to squash this in the 1/3 PR, which would obfuscate the fixups. If you have a strong opinion on this I'm happy to rebase them anyways though 👍🏻

Co-authored-by: Ivan <2103732+codebien@users.noreply.github.com>
Copy link
Contributor

@codebien codebien left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, I would expect to squash this in the 1/3 PR

I thought we would keep the history, if we are going to squash then okay for me.

@oleiade oleiade merged commit 79c350d into experimental/tracing-module-propagators Jan 26, 2023
@oleiade oleiade deleted the experimental/tracing-module-client branch January 26, 2023 13:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants