-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit b0c7e67
Showing
24 changed files
with
2,338 additions
and
0 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
* @razorpay/go_maintainers | ||
/opentelemetry/ @razorpay/spine-edge |
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,32 @@ | ||
name: Run Tests | ||
concurrency: | ||
group: ${{ github.workflow }}-${{ github.ref }} | ||
cancel-in-progress: ${{ github.event_name == 'pull_request' }} | ||
on: | ||
push: | ||
branches: | ||
- 'master' | ||
pull_request: | ||
|
||
jobs: | ||
test: | ||
runs-on: [ self-hosted, non-api ] | ||
strategy: | ||
max-parallel: 4 | ||
matrix: | ||
go-version: ["1.23"] | ||
|
||
name: Run Tests | ||
steps: | ||
- name: checkout | ||
uses: actions/checkout@v2 | ||
|
||
- name: setup golang | ||
uses: actions/setup-go@v5 | ||
with: | ||
go-version: '${{ matrix.go-version }}' | ||
|
||
- run: sh ./run_tests.sh | ||
env: | ||
GIT_TOKEN: ${{ secrets.GIT_TOKEN }} | ||
GOPRIVATE: github.com/razorpay/* |
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,16 @@ | ||
# vendor folder | ||
vendor/* | ||
|
||
# idea folder created by JetBrains | ||
.idea/ | ||
|
||
# vscode folder | ||
.vscode/* | ||
|
||
# tmp folder | ||
tmp/* | ||
|
||
# Desktop Services Store | ||
.DS_Store | ||
|
||
**/vendor |
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 @@ | ||
# golib |
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,86 @@ | ||
# Reference file : https://github.com/golangci/golangci-lint/blob/master/.golangci.reference.yml | ||
run: | ||
timeout: 10m | ||
paths: | ||
exclude: | ||
- tests/** | ||
linters-settings: | ||
tagalign: | ||
sort: false | ||
|
||
linters: | ||
enable-all: true | ||
disable: | ||
- deadcode # deprecated | ||
- exhaustivestruct # deprecated | ||
- golint # deprecated | ||
- ifshort # deprecated | ||
- interfacer # deprecated | ||
- maligned # deprecated | ||
- nosnakecase # deprecated | ||
- scopelint # deprecated | ||
- scopelint # deprecated | ||
- structcheck # deprecated | ||
- varcheck # deprecated | ||
- sqlclosecheck # not relevant yet (SQL) | ||
- rowserrcheck # not relevant yet (SQL) | ||
- execinquery # not relevant yet (SQL) | ||
- cyclop # duplicate of gocyclo | ||
- lll # Not relevant | ||
- gocyclo # FIXME must be fixed | ||
- gocognit # Too strict | ||
- nestif # Too many false-positive. | ||
- prealloc # Too many false-positive. | ||
- makezero # Not relevant | ||
- dupl # Too strict | ||
- gosec # Too strict | ||
- gochecknoinits | ||
- gochecknoglobals | ||
- wsl # Too strict | ||
- nlreturn # Not relevant | ||
- gomnd # Too strict | ||
- stylecheck # skip because report issues related to some generated files. | ||
- testpackage # Too strict | ||
- tparallel # Not relevant | ||
- paralleltest # Not relevant | ||
- exhaustive # Not relevant | ||
- exhaustruct # Not relevant | ||
- goerr113 # Too strict | ||
- wrapcheck # Too strict | ||
- noctx # Too strict | ||
- bodyclose # too many false-positive | ||
- forcetypeassert # Too strict | ||
- tagliatelle # Too strict | ||
- varnamelen # Not relevant | ||
- nilnil # Not relevant | ||
- ireturn # Not relevant | ||
- contextcheck # too many false-positive | ||
- containedctx # too many false-positive | ||
- maintidx # kind of duplicate of gocyclo | ||
- nonamedreturns # Too strict | ||
- gosmopolitan # not relevant | ||
- depguard # Not relevant for now as we don't have a list of blacklisted dependencies | ||
- gci # not relevant as go imports is already used | ||
- godot # not relevant as it only checks if the comment is ended in period or not. | ||
- gofumpt # not relevant as we use goimports | ||
- thelper # test case helper linter, not relevant | ||
- inamedparam # Named interface params | ||
|
||
issues: | ||
# Excluding configuration per-path, per-linter, per-text and per-source | ||
exclude-rules: | ||
# Exclude some linters from running on tests files. | ||
- path: '(.+)_test.go' | ||
linters: | ||
- errcheck | ||
- funlen | ||
- usestdlibvars | ||
- thelper | ||
- errchkjson | ||
- goconst | ||
- testifylint | ||
- path: 'tests' | ||
linters: | ||
- thelper | ||
- testifylint | ||
|
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,31 @@ | ||
.PHONY: build integration-test unit-test lint imports obs-stack-up obs-stack-down run-example run-test | ||
|
||
build: | ||
go build -v ./... | ||
|
||
integration-test: | ||
go test -race -v ./tests --tags=integration | ||
|
||
unit-test: | ||
go test -race -v ./... -coverprofile=unit-test.cov -covermode=atomic | ||
|
||
lint: | ||
@golangci-lint run --config=.golangci.yml | ||
|
||
imports: | ||
goimports -w . | ||
|
||
obs-stack-up: | ||
docker-compose -f ./tests/testdata/docker-compose.yaml up -d | ||
|
||
obs-stack-down: | ||
docker-compose -f ./tests/testdata/docker-compose.yaml down | ||
|
||
run-example: | ||
make obs-stack-up | ||
cd ./example && go build -v ./... && ./example | ||
|
||
run-test: | ||
make unit-test | ||
make integration-test | ||
|
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,120 @@ | ||
# Opentelemetry | ||
Package opentelemetry provides telemetry instrumentation support for applications | ||
using Opentelemetry specification. This package owns the responsibility of | ||
creating and destroying telemetry providers which sends data to the external | ||
components via exporters provided in the configuration. | ||
|
||
## Features | ||
1. Instrumentation support for Tracing | ||
2. Instrumentation support for Metrics | ||
|
||
## Usage Examples | ||
|
||
### Fetch the package as a dependency | ||
```go | ||
go get -u github.com/razorpay/goutils/opentelemetry | ||
``` | ||
### Parse and generate the [opentelemetry configuration] (opentelemetry/config/config.go) | ||
The client is responsible for generating opentelemetry configuration. Client can have an example opentelemetry configuration | ||
block like below in its configuration file: | ||
``` | ||
{ | ||
"service_name": "local_service", | ||
"exporters": [ | ||
{ | ||
"name": "local_prometheus", | ||
"kind": "prometheus", | ||
"config": { | ||
"port": 9092, | ||
"process_metrics": true, | ||
"go_metrics": true | ||
} | ||
}, | ||
{ | ||
"name": "local_tempo", | ||
"kind": "opentelemetry", | ||
"config": { | ||
"host": "localhost", | ||
"port": 4317, | ||
} | ||
}, | ||
{ | ||
"name": "local_jaeger", | ||
"kind": "opentelemetry", | ||
"config": { | ||
"host": "localhost" | ||
"port": 14268, | ||
} | ||
} | ||
], | ||
"metrics": { | ||
"exporters": ["local_prometheus"] | ||
}, | ||
"traces": { | ||
"exporters": ["local_tempo", "local_jaeger"], | ||
"sample_rate": 1 | ||
} | ||
} | ||
``` | ||
|
||
### Initialise the instrumentation providers | ||
After generating the above configuration for opentelemetry, initialise the instrumentation providers like below: | ||
```go | ||
err := opentelemetry.Register(context, opentelemetry) | ||
``` | ||
|
||
### Instrument application for Tracing | ||
```go | ||
tracer := otel.Tracer("test") | ||
commonAttrs := []attribute.KeyValue{ | ||
attribute.String("attrA", "A"), | ||
attribute.String("attrB", "B"), | ||
attribute.String("attrC", "C"), | ||
} | ||
ctx, span := tracer.Start( | ||
ctx, | ||
"test-example", | ||
trace.WithAttributes(commonAttrs...)) | ||
|
||
// some operation | ||
|
||
span.End() | ||
``` | ||
### Instrument application for Metrics | ||
```go | ||
meter := otel.Meter("test-example") | ||
opt := api.WithAttributes( | ||
attribute.Key("attrA").String("A"), | ||
attribute.Key("attrB").String("B"), | ||
) | ||
counter, err := meter.Float64Counter("foo") | ||
counter.Add(context, 5, opt) | ||
histogram, err := meter.Float64Histogram( | ||
"baz", | ||
api.WithDescription("a histogram with custom buckets and rename"), | ||
api.WithExplicitBucketBoundaries(64, 128, 256, 512, 1024, 2048, 4096), | ||
) | ||
histogram.Record(context, 136, opt) | ||
``` | ||
|
||
For more details, refer [opentelemetry/example/main.go] (example instrumentation file) | ||
|
||
### Viewing example telemetry data | ||
Run ``` make run-example ``` to run a sample instrumentation 'test-service' application and to set up Prometheus, Otel-collector and Jaeger which will collect metrics and tracing data | ||
of the application. | ||
1. To view traces, use jaeger endpoint ``` localhost:16686 ```. | ||
2. To view metrics, use prometheus endpoint ``` localhost:9090 ```. | ||
3. Run ``` make obs-stack-down ``` to bring down the observability stack. | ||
|
||
### Viewing telemetry data for any application | ||
Run ``` make obs-stack ``` to setup Prometheus, Otel-collector and Jaeger which will collect metrics and tracing data | ||
of the application which are exporting data to them. | ||
1. To view traces, use jaeger endpoint ``` localhost:16686 ```. | ||
2. To view metrics, use prometheus endpoint ``` localhost:9090 ```. | ||
3. Run ``` make obs-stack-down ``` to bring down the observability stack. | ||
|
||
## TODOs | ||
- Support for push based configuration for exporting metrics | ||
- Allow different formats for the propagation of the trace (the `TextMapPropagator`) | ||
- Support for exporting Metrics and Logging using Opentelemetry Exporter | ||
|
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,50 @@ | ||
package config | ||
|
||
import ( | ||
"errors" | ||
) | ||
|
||
var ErrNoExporter = errors.New("no exporters declared") | ||
var ErrTelemetryConfigMissing = errors.New("config for telemetry instance is not provided") | ||
|
||
// Config is the root configuration for the OTEL observability stack | ||
type Config struct { | ||
ServiceName string `mapstructure:"service_name" json:"service_name"` | ||
Exporters []Exporter | ||
Metrics *MetricsConfig | ||
Trace *TraceConfig | ||
} | ||
|
||
type ExporterKind string | ||
|
||
// Exporter has the information to configure an exporter | ||
// instance. | ||
// | ||
// The Kind is the name of the kind of exporter we want: | ||
// OTEL, Prometheus, ... | ||
// | ||
// The Config is the configuration for this provider | ||
type Exporter struct { | ||
Name string | ||
Kind ExporterKind | ||
Config map[string]interface{} | ||
} | ||
|
||
type MetricsConfig struct { | ||
Exporters []string | ||
} | ||
|
||
type TraceConfig struct { | ||
Exporters []string | ||
SampleRate float64 `mapstructure:"sample_rate" json:"sample_rate"` | ||
} | ||
|
||
func Validate(cfg *Config) error { | ||
if cfg.Exporters == nil || len(cfg.Exporters) == 0 { | ||
return ErrNoExporter | ||
} | ||
if cfg.Metrics == nil && cfg.Trace == nil { | ||
return ErrTelemetryConfigMissing | ||
} | ||
return nil | ||
} |
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,20 @@ | ||
package config | ||
|
||
import ( | ||
"encoding/json" | ||
) | ||
|
||
func Parse(configInString map[string]interface{}, cfgStructPointer interface{}) error { | ||
if configInString == nil { | ||
return nil | ||
} | ||
b, err := json.Marshal(configInString) | ||
if err != nil { | ||
return err | ||
} | ||
err = json.Unmarshal(b, cfgStructPointer) | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
} |
Oops, something went wrong.