gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

CONTRIBUTING.md (17832B)


      1 # Contributing to opentelemetry-go
      2 
      3 The Go special interest group (SIG) meets regularly. See the
      4 OpenTelemetry
      5 [community](https://github.com/open-telemetry/community#golang-sdk)
      6 repo for information on this and other language SIGs.
      7 
      8 See the [public meeting
      9 notes](https://docs.google.com/document/d/1E5e7Ld0NuU1iVvf-42tOBpu2VBBLYnh73GJuITGJTTU/edit)
     10 for a summary description of past meetings. To request edit access,
     11 join the meeting or get in touch on
     12 [Slack](https://cloud-native.slack.com/archives/C01NPAXACKT).
     13 
     14 ## Development
     15 
     16 You can view and edit the source code by cloning this repository:
     17 
     18 ```sh
     19 git clone https://github.com/open-telemetry/opentelemetry-go.git
     20 ```
     21 
     22 Run `make test` to run the tests instead of `go test`.
     23 
     24 There are some generated files checked into the repo. To make sure
     25 that the generated files are up-to-date, run `make` (or `make
     26 precommit` - the `precommit` target is the default).
     27 
     28 The `precommit` target also fixes the formatting of the code and
     29 checks the status of the go module files.
     30 
     31 Additionally, there is a `codespell` target that checks for common
     32 typos in the code. It is not run by default, but you can run it
     33 manually with `make codespell`. It will set up a virtual environment
     34 in `venv` and install `codespell` there.
     35 
     36 If after running `make precommit` the output of `git status` contains
     37 `nothing to commit, working tree clean` then it means that everything
     38 is up-to-date and properly formatted.
     39 
     40 ## Pull Requests
     41 
     42 ### How to Send Pull Requests
     43 
     44 Everyone is welcome to contribute code to `opentelemetry-go` via
     45 GitHub pull requests (PRs).
     46 
     47 To create a new PR, fork the project in GitHub and clone the upstream
     48 repo:
     49 
     50 ```sh
     51 go get -d go.opentelemetry.io/otel
     52 ```
     53 
     54 (This may print some warning about "build constraints exclude all Go
     55 files", just ignore it.)
     56 
     57 This will put the project in `${GOPATH}/src/go.opentelemetry.io/otel`. You
     58 can alternatively use `git` directly with:
     59 
     60 ```sh
     61 git clone https://github.com/open-telemetry/opentelemetry-go
     62 ```
     63 
     64 (Note that `git clone` is *not* using the `go.opentelemetry.io/otel` name -
     65 that name is a kind of a redirector to GitHub that `go get` can
     66 understand, but `git` does not.)
     67 
     68 This would put the project in the `opentelemetry-go` directory in
     69 current working directory.
     70 
     71 Enter the newly created directory and add your fork as a new remote:
     72 
     73 ```sh
     74 git remote add <YOUR_FORK> git@github.com:<YOUR_GITHUB_USERNAME>/opentelemetry-go
     75 ```
     76 
     77 Check out a new branch, make modifications, run linters and tests, update
     78 `CHANGELOG.md`, and push the branch to your fork:
     79 
     80 ```sh
     81 git checkout -b <YOUR_BRANCH_NAME>
     82 # edit files
     83 # update changelog
     84 make precommit
     85 git add -p
     86 git commit
     87 git push <YOUR_FORK> <YOUR_BRANCH_NAME>
     88 ```
     89 
     90 Open a pull request against the main `opentelemetry-go` repo. Be sure to add the pull
     91 request ID to the entry you added to `CHANGELOG.md`.
     92 
     93 ### How to Receive Comments
     94 
     95 * If the PR is not ready for review, please put `[WIP]` in the title,
     96   tag it as `work-in-progress`, or mark it as
     97   [`draft`](https://github.blog/2019-02-14-introducing-draft-pull-requests/).
     98 * Make sure CLA is signed and CI is clear.
     99 
    100 ### How to Get PRs Merged
    101 
    102 A PR is considered **ready to merge** when:
    103 
    104 * It has received two qualified approvals[^1].
    105 
    106   This is not enforced through automation, but needs to be validated by the
    107   maintainer merging.
    108   * The qualified approvals need to be from [Approver]s/[Maintainer]s
    109     affiliated with different companies. Two qualified approvals from
    110     [Approver]s or [Maintainer]s affiliated with the same company counts as a
    111     single qualified approval.
    112   * PRs introducing changes that have already been discussed and consensus
    113     reached only need one qualified approval. The discussion and resolution
    114     needs to be linked to the PR.
    115   * Trivial changes[^2] only need one qualified approval.
    116 
    117 * All feedback has been addressed.
    118   * All PR comments and suggestions are resolved.
    119   * All GitHub Pull Request reviews with a status of "Request changes" have
    120     been addressed. Another review by the objecting reviewer with a different
    121     status can be submitted to clear the original review, or the review can be
    122     dismissed by a [Maintainer] when the issues from the original review have
    123     been addressed.
    124   * Any comments or reviews that cannot be resolved between the PR author and
    125     reviewers can be submitted to the community [Approver]s and [Maintainer]s
    126     during the weekly SIG meeting. If consensus is reached among the
    127     [Approver]s and [Maintainer]s during the SIG meeting the objections to the
    128     PR may be dismissed or resolved or the PR closed by a [Maintainer].
    129   * Any substantive changes to the PR require existing Approval reviews be
    130     cleared unless the approver explicitly states that their approval persists
    131     across changes. This includes changes resulting from other feedback.
    132     [Approver]s and [Maintainer]s can help in clearing reviews and they should
    133     be consulted if there are any questions.
    134 
    135 * The PR branch is up to date with the base branch it is merging into.
    136   * To ensure this does not block the PR, it should be configured to allow
    137     maintainers to update it.
    138 
    139 * It has been open for review for at least one working day. This gives people
    140   reasonable time to review.
    141   * Trivial changes[^2] do not have to wait for one day and may be merged with
    142     a single [Maintainer]'s approval.
    143 
    144 * All required GitHub workflows have succeeded.
    145 * Urgent fix can take exception as long as it has been actively communicated
    146   among [Maintainer]s.
    147 
    148 Any [Maintainer] can merge the PR once the above criteria have been met.
    149 
    150 [^1]: A qualified approval is a GitHub Pull Request review with "Approve"
    151   status from an OpenTelemetry Go [Approver] or [Maintainer].
    152 [^2]: Trivial changes include: typo corrections, cosmetic non-substantive
    153   changes, documentation corrections or updates, dependency updates, etc.
    154 
    155 ## Design Choices
    156 
    157 As with other OpenTelemetry clients, opentelemetry-go follows the
    158 [OpenTelemetry Specification](https://opentelemetry.io/docs/specs/otel).
    159 
    160 It's especially valuable to read through the [library
    161 guidelines](https://opentelemetry.io/docs/specs/otel/library-guidelines).
    162 
    163 ### Focus on Capabilities, Not Structure Compliance
    164 
    165 OpenTelemetry is an evolving specification, one where the desires and
    166 use cases are clear, but the method to satisfy those uses cases are
    167 not.
    168 
    169 As such, Contributions should provide functionality and behavior that
    170 conforms to the specification, but the interface and structure is
    171 flexible.
    172 
    173 It is preferable to have contributions follow the idioms of the
    174 language rather than conform to specific API names or argument
    175 patterns in the spec.
    176 
    177 For a deeper discussion, see
    178 [this](https://github.com/open-telemetry/opentelemetry-specification/issues/165).
    179 
    180 ## Documentation
    181 
    182 Each non-example Go Module should have its own `README.md` containing:
    183 
    184 - A pkg.go.dev badge which can be generated [here](https://pkg.go.dev/badge/).
    185 - Brief description.
    186 - Installation instructions (and requirements if applicable).
    187 - Hyperlink to an example. Depending on the component the example can be:
    188   - An `example_test.go` like [here](exporters/stdout/stdouttrace/example_test.go).
    189   - A sample Go application with its own `README.md`, like [here](example/zipkin).
    190 - Additional documentation sections such us:
    191   - Configuration,
    192   - Contributing,
    193   - References.
    194 
    195 [Here](exporters/jaeger/README.md) is an example of a concise `README.md`.
    196 
    197 Moreover, it should be possible to navigate to any `README.md` from the
    198 root `README.md`.
    199 
    200 ## Style Guide
    201 
    202 One of the primary goals of this project is that it is actually used by
    203 developers. With this goal in mind the project strives to build
    204 user-friendly and idiomatic Go code adhering to the Go community's best
    205 practices.
    206 
    207 For a non-comprehensive but foundational overview of these best practices
    208 the [Effective Go](https://golang.org/doc/effective_go.html) documentation
    209 is an excellent starting place.
    210 
    211 As a convenience for developers building this project the `make precommit`
    212 will format, lint, validate, and in some cases fix the changes you plan to
    213 submit. This check will need to pass for your changes to be able to be
    214 merged.
    215 
    216 In addition to idiomatic Go, the project has adopted certain standards for
    217 implementations of common patterns. These standards should be followed as a
    218 default, and if they are not followed documentation needs to be included as
    219 to the reasons why.
    220 
    221 ### Configuration
    222 
    223 When creating an instantiation function for a complex `type T struct`, it is
    224 useful to allow variable number of options to be applied. However, the strong
    225 type system of Go restricts the function design options. There are a few ways
    226 to solve this problem, but we have landed on the following design.
    227 
    228 #### `config`
    229 
    230 Configuration should be held in a `struct` named `config`, or prefixed with
    231 specific type name this Configuration applies to if there are multiple
    232 `config` in the package. This type must contain configuration options.
    233 
    234 ```go
    235 // config contains configuration options for a thing.
    236 type config struct {
    237 	// options ...
    238 }
    239 ```
    240 
    241 In general the `config` type will not need to be used externally to the
    242 package and should be unexported. If, however, it is expected that the user
    243 will likely want to build custom options for the configuration, the `config`
    244 should be exported. Please, include in the documentation for the `config`
    245 how the user can extend the configuration.
    246 
    247 It is important that internal `config` are not shared across package boundaries.
    248 Meaning a `config` from one package should not be directly used by another. The
    249 one exception is the API packages.  The configs from the base API, eg.
    250 `go.opentelemetry.io/otel/trace.TracerConfig` and
    251 `go.opentelemetry.io/otel/metric.InstrumentConfig`, are intended to be consumed
    252 by the SDK therefore it is expected that these are exported.
    253 
    254 When a config is exported we want to maintain forward and backward
    255 compatibility, to achieve this no fields should be exported but should
    256 instead be accessed by methods.
    257 
    258 Optionally, it is common to include a `newConfig` function (with the same
    259 naming scheme). This function wraps any defaults setting and looping over
    260 all options to create a configured `config`.
    261 
    262 ```go
    263 // newConfig returns an appropriately configured config.
    264 func newConfig(options ...Option) config {
    265 	// Set default values for config.
    266 	config := config{/* […] */}
    267 	for _, option := range options {
    268 		config = option.apply(config)
    269 	}
    270 	// Perform any validation here.
    271 	return config
    272 }
    273 ```
    274 
    275 If validation of the `config` options is also performed this can return an
    276 error as well that is expected to be handled by the instantiation function
    277 or propagated to the user.
    278 
    279 Given the design goal of not having the user need to work with the `config`,
    280 the `newConfig` function should also be unexported.
    281 
    282 #### `Option`
    283 
    284 To set the value of the options a `config` contains, a corresponding
    285 `Option` interface type should be used.
    286 
    287 ```go
    288 type Option interface {
    289 	apply(config) config
    290 }
    291 ```
    292 
    293 Having `apply` unexported makes sure that it will not be used externally.
    294 Moreover, the interface becomes sealed so the user cannot easily implement
    295 the interface on its own.
    296 
    297 The `apply` method should return a modified version of the passed config.
    298 This approach, instead of passing a pointer, is used to prevent the config from being allocated to the heap.
    299 
    300 The name of the interface should be prefixed in the same way the
    301 corresponding `config` is (if at all).
    302 
    303 #### Options
    304 
    305 All user configurable options for a `config` must have a related unexported
    306 implementation of the `Option` interface and an exported configuration
    307 function that wraps this implementation.
    308 
    309 The wrapping function name should be prefixed with `With*` (or in the
    310 special case of a boolean options `Without*`) and should have the following
    311 function signature.
    312 
    313 ```go
    314 func With*(…) Option { … }
    315 ```
    316 
    317 ##### `bool` Options
    318 
    319 ```go
    320 type defaultFalseOption bool
    321 
    322 func (o defaultFalseOption) apply(c config) config {
    323 	c.Bool = bool(o)
    324     return c
    325 }
    326 
    327 // WithOption sets a T to have an option included.
    328 func WithOption() Option {
    329 	return defaultFalseOption(true)
    330 }
    331 ```
    332 
    333 ```go
    334 type defaultTrueOption bool
    335 
    336 func (o defaultTrueOption) apply(c config) config {
    337 	c.Bool = bool(o)
    338     return c
    339 }
    340 
    341 // WithoutOption sets a T to have Bool option excluded.
    342 func WithoutOption() Option {
    343 	return defaultTrueOption(false)
    344 }
    345 ```
    346 
    347 ##### Declared Type Options
    348 
    349 ```go
    350 type myTypeOption struct {
    351 	MyType MyType
    352 }
    353 
    354 func (o myTypeOption) apply(c config) config {
    355 	c.MyType = o.MyType
    356     return c
    357 }
    358 
    359 // WithMyType sets T to have include MyType.
    360 func WithMyType(t MyType) Option {
    361 	return myTypeOption{t}
    362 }
    363 ```
    364 
    365 ##### Functional Options
    366 
    367 ```go
    368 type optionFunc func(config) config
    369 
    370 func (fn optionFunc) apply(c config) config {
    371 	return fn(c)
    372 }
    373 
    374 // WithMyType sets t as MyType.
    375 func WithMyType(t MyType) Option {
    376 	return optionFunc(func(c config) config {
    377 		c.MyType = t
    378         return c
    379 	})
    380 }
    381 ```
    382 
    383 #### Instantiation
    384 
    385 Using this configuration pattern to configure instantiation with a `NewT`
    386 function.
    387 
    388 ```go
    389 func NewT(options ...Option) T {…}
    390 ```
    391 
    392 Any required parameters can be declared before the variadic `options`.
    393 
    394 #### Dealing with Overlap
    395 
    396 Sometimes there are multiple complex `struct` that share common
    397 configuration and also have distinct configuration. To avoid repeated
    398 portions of `config`s, a common `config` can be used with the union of
    399 options being handled with the `Option` interface.
    400 
    401 For example.
    402 
    403 ```go
    404 // config holds options for all animals.
    405 type config struct {
    406 	Weight      float64
    407 	Color       string
    408 	MaxAltitude float64
    409 }
    410 
    411 // DogOption apply Dog specific options.
    412 type DogOption interface {
    413 	applyDog(config) config
    414 }
    415 
    416 // BirdOption apply Bird specific options.
    417 type BirdOption interface {
    418 	applyBird(config) config
    419 }
    420 
    421 // Option apply options for all animals.
    422 type Option interface {
    423 	BirdOption
    424 	DogOption
    425 }
    426 
    427 type weightOption float64
    428 
    429 func (o weightOption) applyDog(c config) config {
    430 	c.Weight = float64(o)
    431 	return c
    432 }
    433 
    434 func (o weightOption) applyBird(c config) config {
    435 	c.Weight = float64(o)
    436 	return c
    437 }
    438 
    439 func WithWeight(w float64) Option { return weightOption(w) }
    440 
    441 type furColorOption string
    442 
    443 func (o furColorOption) applyDog(c config) config {
    444 	c.Color = string(o)
    445 	return c
    446 }
    447 
    448 func WithFurColor(c string) DogOption { return furColorOption(c) }
    449 
    450 type maxAltitudeOption float64
    451 
    452 func (o maxAltitudeOption) applyBird(c config) config {
    453 	c.MaxAltitude = float64(o)
    454 	return c
    455 }
    456 
    457 func WithMaxAltitude(a float64) BirdOption { return maxAltitudeOption(a) }
    458 
    459 func NewDog(name string, o ...DogOption) Dog    {…}
    460 func NewBird(name string, o ...BirdOption) Bird {…}
    461 ```
    462 
    463 ### Interfaces
    464 
    465 To allow other developers to better comprehend the code, it is important
    466 to ensure it is sufficiently documented. One simple measure that contributes
    467 to this aim is self-documenting by naming method parameters. Therefore,
    468 where appropriate, methods of every exported interface type should have
    469 their parameters appropriately named.
    470 
    471 #### Interface Stability
    472 
    473 All exported stable interfaces that include the following warning in their
    474 documentation are allowed to be extended with additional methods.
    475 
    476 > Warning: methods may be added to this interface in minor releases.
    477 
    478 Otherwise, stable interfaces MUST NOT be modified.
    479 
    480 If new functionality is needed for an interface that cannot be changed it MUST
    481 be added by including an additional interface. That added interface can be a
    482 simple interface for the specific functionality that you want to add or it can
    483 be a super-set of the original interface. For example, if you wanted to a
    484 `Close` method to the `Exporter` interface:
    485 
    486 ```go
    487 type Exporter interface {
    488 	Export()
    489 }
    490 ```
    491 
    492 A new interface, `Closer`, can be added:
    493 
    494 ```go
    495 type Closer interface {
    496 	Close()
    497 }
    498 ```
    499 
    500 Code that is passed the `Exporter` interface can now check to see if the passed
    501 value also satisfies the new interface. E.g.
    502 
    503 ```go
    504 func caller(e Exporter) {
    505 	/* ... */
    506 	if c, ok := e.(Closer); ok {
    507 		c.Close()
    508 	}
    509 	/* ... */
    510 }
    511 ```
    512 
    513 Alternatively, a new type that is the super-set of an `Exporter` can be created.
    514 
    515 ```go
    516 type ClosingExporter struct {
    517 	Exporter
    518 	Close()
    519 }
    520 ```
    521 
    522 This new type can be used similar to the simple interface above in that a
    523 passed `Exporter` type can be asserted to satisfy the `ClosingExporter` type
    524 and the `Close` method called.
    525 
    526 This super-set approach can be useful if there is explicit behavior that needs
    527 to be coupled with the original type and passed as a unified type to a new
    528 function, but, because of this coupling, it also limits the applicability of
    529 the added functionality. If there exist other interfaces where this
    530 functionality should be added, each one will need their own super-set
    531 interfaces and will duplicate the pattern. For this reason, the simple targeted
    532 interface that defines the specific functionality should be preferred.
    533 
    534 ## Approvers and Maintainers
    535 
    536 ### Approvers
    537 
    538 - [Evan Torrie](https://github.com/evantorrie), Verizon Media
    539 - [Sam Xie](https://github.com/XSAM), Cisco/AppDynamics
    540 - [David Ashpole](https://github.com/dashpole), Google
    541 - [Robert Pająk](https://github.com/pellared), Splunk
    542 - [Chester Cheung](https://github.com/hanyuancheung), Tencent
    543 - [Damien Mathieu](https://github.com/dmathieu), Elastic
    544 
    545 ### Maintainers
    546 
    547 - [Aaron Clawson](https://github.com/MadVikingGod), LightStep
    548 - [Anthony Mirabella](https://github.com/Aneurysm9), AWS
    549 - [Tyler Yahn](https://github.com/MrAlias), Splunk
    550 
    551 ### Emeritus
    552 
    553 - [Gustavo Silva Paiva](https://github.com/paivagustavo), LightStep
    554 - [Josh MacDonald](https://github.com/jmacd), LightStep
    555 
    556 ### Become an Approver or a Maintainer
    557 
    558 See the [community membership document in OpenTelemetry community
    559 repo](https://github.com/open-telemetry/community/blob/main/community-membership.md).
    560 
    561 [Approver]: #approvers
    562 [Maintainer]: #maintainers