Skip to content

Latest commit

 

History

History
137 lines (91 loc) · 5.87 KB

DEV-CONVENTIONS.md

File metadata and controls

137 lines (91 loc) · 5.87 KB

Project Conventions

We follow a number of conventions in our source base to help us create something cohesive and coherent, which makes the source base easier to create, maintain, and use.

Others docs you should look at:

Coding conventions

  • Follow the general guidance from Effective Go

  • Go Code Review Comments provides a good collection of common code review comments so you can get your code up to snuff before asking others to look at it.

  • Comment your code.

    • Follow the general guidance from Go's commenting conventions
    • If reviewers ask questions about why the code is the way it is, that's a sign that comments might be helpful.
  • Command-line flags should use dashes, not underscores

  • Naming

    • Please consider package name when selecting an interface name, and avoid redundancy. For example, use adapter.AspectConfig instead of adapter.AdapterConfig.

    • Must use lowercase for Go package names.

    • Must use camel case for Go types.

    • Use singular nouns for types unless they represent a collection. Use plural nouns for collections.

    • Please consider parent directory name when choosing a package name:

      • adapters/factMapper/tracker.go should say package factMapper not package factmapperadapter.

      • Unless there's a good reason, package names should match the name of the directory in which the .go file exists.

      • Importers can use a different name if they need to disambiguate.

Logging conventions

Istio code is expected to use the standard Istio logging package. When importing external package to Istio, if these packages send logs to the standard Go "log" package or to the global zap logger, the log data will automatically be captured by the Istio log package and merged into the primary log stream(s) produced for the component. If other logging packages are used, their output will uncoordinated and unrelated to the primary log output, which isn't great for users of the component.

The Istio logging package supports four logging levels:

  • Error - Always an error.
  • Warn - Something unexpected, but probably not an error.
  • Info - Useful info about something happening.
  • Debug - Extra stuff useful during development.

By default, errors, warnings, and informational data is emitted, while debug is only enabled when a component is started with particular options.

The Istio logging package is built on top of the Zap logger and thus inherits its efficiency and flexibility. In any high performance paths, prefer to use the Error, Warn, Info, and Debug methods, as these are the most efficient. All other variations of these four calls end up triggering some memory allocations and have a considerably higher execution time.

If you need to do a fair bit of computation in order to produce data for logging, you should protect that code using the ErrorEnabled, WarnEnabled, InfoEnabled, and DebugEnabled methods.

Be careful not to introduce expensive computations as part of the evaluation of a log statement. For example:

log.Debug(fmt.Sprintf("%s %s %d", s1, s2, i1))

Even when debug-level logs are disabled, the fmt.Sprintf call will still execute. Instead, you should write:

if log.DebugEnabled() {
    log.Debug(fmt.Sprintf("%s %s %d", s1, s2, i1))
}

Note that Mixer adapters don't use the standard Istio logging package. Instead, they are expected to use the adapter logger interface.

Testing conventions

  • For Go code, unit tests are written using the standard Go testing package.

  • All new packages and most new significant functionality must come with unit tests with code coverage >98%

  • Table-driven tests are preferred for testing multiple scenarios/inputs

  • Significant features should come with integration and/or end-to-end tests

  • Tests must be robust. In particular, don't assume that async operations will complete promptly just because it's a test. Put proper synchronization in place or if not possible put in place some retry logic.

Directory and file conventions

  • Avoid package sprawl. Find an appropriate subdirectory for new packages.

  • Avoid general utility packages. Packages called "util" are suspect. Instead, derive a name that describes your desired function.

  • Use lowercase for file and directory names.

  • Use underscores for Go file names, e.g. type DeviceAllocator must reside in device_allocator.go.

  • All directory names should be singular unless required by existing frameworks. This is to avoid mixed singular and plural names in the full paths. NOTE: Traditional Unix directory names are often singular, such as "/usr/bin".

  • Third-party code

    • Go code for normal third-party dependencies is managed by the Go Dep.

    • Third-party code must carry licenses. This includes modified third-party code and excerpts.