Skip to content

Commit

Permalink
merging commit as one
Browse files Browse the repository at this point in the history
  • Loading branch information
Harnoor-se7en committed Oct 15, 2024
0 parents commit b0c7e67
Show file tree
Hide file tree
Showing 24 changed files with 2,338 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* @razorpay/go_maintainers
/opentelemetry/ @razorpay/spine-edge
32 changes: 32 additions & 0 deletions .github/workflows/tests.yml
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/*
16 changes: 16 additions & 0 deletions .gitignore
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# golib
86 changes: 86 additions & 0 deletions opentelemetry/.golangci.yml
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

31 changes: 31 additions & 0 deletions opentelemetry/Makefile
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

120 changes: 120 additions & 0 deletions opentelemetry/README.md
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

50 changes: 50 additions & 0 deletions opentelemetry/config/config.go
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
}
20 changes: 20 additions & 0 deletions opentelemetry/config/util.go
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
}
Loading

0 comments on commit b0c7e67

Please sign in to comment.