Skip to content

Commit

Permalink
Add/Replace fields with SetFields (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
vearutop authored Apr 18, 2021
1 parent d4e057a commit abb0344
Show file tree
Hide file tree
Showing 12 changed files with 342 additions and 39 deletions.
75 changes: 61 additions & 14 deletions .github/workflows/bench.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
name: bench
on:
push:
tags:
- v*
branches:
- master
- main
pull_request:
workflow_dispatch:
inputs:
old:
description: 'Old Ref'
required: false
default: 'master'
new:
description: 'New Ref'
required: true

env:
GO111MODULE: "on"
CACHE_BENCHMARK: "off" # Enables benchmark result reuse between runs, may skew latency results.
RUN_BASE_BENCHMARK: "on" # Runs benchmark for PR base in case benchmark result is missing.
jobs:
bench:
strategy:
matrix:
go-version: [ 1.15.x ]
go-version: [ 1.16.x ]
runs-on: ubuntu-latest
steps:
- name: Install Go
Expand All @@ -22,27 +28,68 @@ jobs:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@v2
- name: Restore vendor
with:
ref: ${{ (github.event.inputs.new != '') && github.event.inputs.new || github.event.ref }}
- name: Go cache
uses: actions/cache@v2
with:
# In order:
# * Module download cache
# * Build cache (Linux)
path: |
vendor
key: ${{ runner.os }}-go-vendor-${{ hashFiles('**/go.mod') }}
- name: Populate dependencies
run: |
(test -d vendor && echo vendor found) || (go mod vendor)
~/go/pkg/mod
~/.cache/go-build
key: ${{ runner.os }}-go-cache-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-cache
- name: Restore benchstat
uses: actions/cache@v2
with:
path: ~/go/bin/benchstat
key: ${{ runner.os }}-benchstat
- name: Restore base benchmark result
if: env.CACHE_BENCHMARK == 'on'
id: benchmark-base
uses: actions/cache@v2
with:
path: |
bench-master.txt
bench-main.txt
# Use base sha for PR or new commit hash for master/main push in benchmark result key.
key: ${{ runner.os }}-bench-${{ (github.event.pull_request.base.sha != github.event.after) && github.event.pull_request.base.sha || github.event.after }}
- name: Checkout base code
if: env.RUN_BASE_BENCHMARK == 'on' && steps.benchmark-base.outputs.cache-hit != 'true' && (github.event.pull_request.base.sha != '' || github.event.inputs.old != '')
uses: actions/checkout@v2
with:
ref: ${{ (github.event.pull_request.base.sha != '' ) && github.event.pull_request.base.sha || github.event.inputs.old }}
path: __base
- name: Run base benchmark
if: env.RUN_BASE_BENCHMARK == 'on' && steps.benchmark-base.outputs.cache-hit != 'true' && (github.event.pull_request.base.sha != '' || github.event.inputs.old != '')
run: |
export REF_NAME=master
cd __base
BENCH_COUNT=5 make bench-run bench-stat
cp bench-master.txt ../bench-master.txt
- name: Benchmark
run: REF_NAME=${GITHUB_REF##*/} make bench
id: bench
run: |
export REF_NAME=new
BENCH_COUNT=5 make bench-run bench-stat
OUTPUT=$(make bench-stat)
OUTPUT="${OUTPUT//'%'/'%25'}"
OUTPUT="${OUTPUT//$'\n'/'%0A'}"
OUTPUT="${OUTPUT//$'\r'/'%0D'}"
echo "::set-output name=result::$OUTPUT"
- name: Comment Benchmark Result
uses: marocchino/sticky-pull-request-comment@v2
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
header: bench
message: |
### Benchmark Result
<details><summary>Benchmark diff with base branch</summary>
```
${{ steps.bench.outputs.result }}
```
</details>
25 changes: 17 additions & 8 deletions .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,25 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: golangci-lint
uses: golangci/golangci-lint-action@v2.3.0
uses: golangci/golangci-lint-action@v2.5.2
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
version: v1.32.2
version: v1.39.0

# Optional: working directory, useful for monorepos
# working-directory: somedir

# Optional: golangci-lint command line arguments.
# args: ./the-only-dir-to-analyze/...
# args: --issues-exit-code=0

# Optional: show only new issues if it's a pull request. The default value is `false`.
# only-new-issues: true

# Optional: if set to true then the action will use pre-installed Go.
# skip-go-installation: true

# Optional: if set to true then the action don't cache or restore ~/go/pkg.
# skip-pkg-cache: true

# Required: the token is used for fetching a list of releases of golangci-lint.
# The secret `GITHUB_TOKEN` is automatically created by GitHub,
# no need to create it manually.
# https://help.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token#about-the-github_token-secret
github-token: ${{ secrets.GITHUB_TOKEN }}
# Optional: if set to true then the action don't cache or restore ~/.cache/go-build.
# skip-build-cache: true
92 changes: 92 additions & 0 deletions .github/workflows/test-unit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
name: test-unit
on:
push:
branches:
- master
- main
pull_request:
env:
GO111MODULE: "on"
RUN_BASE_COVERAGE: "on" # Runs test for PR base in case base test coverage is missing.
jobs:
test:
strategy:
matrix:
go-version: [ 1.13.x, 1.14.x, 1.15.x, 1.16.x ]
runs-on: ubuntu-latest
steps:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@v2
- name: Go cache
uses: actions/cache@v2
with:
# In order:
# * Module download cache
# * Build cache (Linux)
path: |
~/go/pkg/mod
~/.cache/go-build
key: ${{ runner.os }}-go-cache-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-cache
- name: Restore base test coverage
if: matrix.go-version == '1.16.x'
uses: actions/cache@v2
with:
path: |
unit-base.txt
# Use base sha for PR or new commit hash for master/main push in test result key.
key: ${{ runner.os }}-unit-test-coverage-${{ (github.event.pull_request.base.sha != github.event.after) && github.event.pull_request.base.sha || github.event.after }}
- name: Checkout base code
if: matrix.go-version == '1.16.x' && env.RUN_BASE_COVERAGE == 'on' && steps.benchmark-base.outputs.cache-hit != 'true' && github.event.pull_request.base.sha != ''
uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.base.sha }}
path: __base
- name: Run test for base code
if: matrix.go-version == '1.16.x' && env.RUN_BASE_COVERAGE == 'on' && steps.benchmark-base.outputs.cache-hit != 'true' && github.event.pull_request.base.sha != ''
run: |
cd __base
make test-unit
go tool cover -func=./unit.coverprofile | sed -e 's/.go:[0-9]*:\t/.go\t/g' | sed -e 's/\t\t*/\t/g' > ../unit-base.txt
- name: Test
id: test
run: |
make test-unit
go tool cover -func=./unit.coverprofile | sed -e 's/.go:[0-9]*:\t/.go\t/g' | sed -e 's/\t\t*/\t/g' > unit.txt
OUTPUT=$(test -e unit-base.txt && (diff unit-base.txt unit.txt || exit 0) || cat unit.txt)
OUTPUT="${OUTPUT//'%'/'%25'}"
OUTPUT="${OUTPUT//$'\n'/'%0A'}"
OUTPUT="${OUTPUT//$'\r'/'%0D'}"
TOTAL=$(grep 'total:' unit.txt)
echo "::set-output name=diff::$OUTPUT"
echo "::set-output name=total::$TOTAL"
- name: Store base coverage
if: ${{ github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' }}
run: cp unit.txt unit-base.txt
- name: Comment Test Coverage
if: matrix.go-version == '1.16.x'
uses: marocchino/sticky-pull-request-comment@v2
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
header: unit-test
message: |
### Unit Test Coverage
${{ steps.test.outputs.total }}
<details><summary>Coverage diff with base branch</summary>
```diff
${{ steps.test.outputs.diff }}
```
</details>
- name: Upload code coverage
if: matrix.go-version == '1.16.x'
uses: codecov/codecov-action@v1
with:
file: ./unit.coverprofile
flags: unittests
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/.idea
/bench-*
/unit.coverprofile
/*.coverprofile
/.vscode
/bench-*.txt
/vendor
46 changes: 46 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# See https://github.com/golangci/golangci-lint/blob/master/.golangci.example.yml
run:
tests: true

linters-settings:
errcheck:
check-type-assertions: true
check-blank: true
gocyclo:
min-complexity: 20
dupl:
threshold: 100
misspell:
locale: US
unused:
check-exported: false
unparam:
check-exported: true

linters:
enable-all: true
disable:
- lll
- maligned
- gochecknoglobals
- gomnd
- wrapcheck
- paralleltest
- forbidigo
- exhaustivestruct
- interfacer
- forcetypeassert
- scopelint

issues:
exclude-use-default: false
exclude-rules:
- linters:
- gomnd
- goconst
- goerr113
- noctx
- funlen
- dupl
path: "_test.go"

10 changes: 5 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
GOLANGCI_LINT_VERSION := "v1.32.2"
#GOLANGCI_LINT_VERSION := "v1.39.0" # Optional configuration to pinpoint golangci-lint version.

# The head of Makefile determines location of dev-go to include standard targets.
GO ?= go
Expand Down Expand Up @@ -28,12 +28,12 @@ ifeq ($(DEVGO_PATH),)
endif

-include $(DEVGO_PATH)/makefiles/main.mk
-include $(DEVGO_PATH)/makefiles/test-unit.mk
-include $(DEVGO_PATH)/makefiles/lint.mk
-include $(DEVGO_PATH)/makefiles/test-unit.mk
-include $(DEVGO_PATH)/makefiles/bench.mk
-include $(DEVGO_PATH)/makefiles/github-actions.mk
-include $(DEVGO_PATH)/makefiles/reset-ci.mk

# Add your custom targets here.

## Run tests
test: test-unit


25 changes: 25 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package ctxd

// FieldNames defines standard field names.
//
// Default names are aligned with https://www.elastic.co/guide/en/ecs/current/ecs-field-reference.html.
type FieldNames struct {
Timestamp string `default:"@timestamp"`
Message string `default:"message"`

// ClientIP is an IP address of the client (IPv4 or IPv6).
ClientIP string `default:"client.ip"`

HTTPMethod string `default:"http.request.method"`
HTTPResponseBytes string `default:"http.response.bytes"`
HTTPResponseStatus string `default:"http.response.status_code"`

URL string `default:"url.original"`

// UserAgentOriginal is an unparsed user_agent string.
UserAgentOriginal string `default:"user_agent.original"`

SpanID string `default:"span.id"`
TraceID string `default:"trace.id"`
TransactionID string `default:"transaction.id"`
}
46 changes: 46 additions & 0 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,52 @@ func AddFields(ctx context.Context, keysAndValues ...interface{}) context.Contex
return context.WithValue(ctx, fieldsCtxKey{}, append(Fields(ctx), keysAndValues...))
}

// SetFields returns context with added loosely-typed key-value pairs as fields.
//
// Values of same keys that are already existing in parent context are replaced.
func SetFields(ctx context.Context, keysAndValues ...interface{}) context.Context {
fields := Fields(ctx)

var existing []int

for i := 0; i < len(keysAndValues); i += 2 {
for j := 0; j < len(fields); j += 2 {
if keysAndValues[i] == fields[j] {
existing = append(existing, j)
}
}
}

if len(existing) == 0 {
return context.WithValue(ctx, fieldsCtxKey{}, append(fields, keysAndValues...))
}

// Create result slice that will fit a copy of fields and will have a capacity for new keys and values.
result := make([]interface{}, len(fields), len(fields)+len(keysAndValues)-2*len(existing))
copy(result, fields)

for i := 0; i < len(keysAndValues); i += 2 {
found := false

for _, e := range existing {
if result[e] == keysAndValues[i] {
result[e+1] = keysAndValues[i+1]
found = true

break
}
}

if found {
continue
}

result = append(result, keysAndValues[i], keysAndValues[i+1])
}

return context.WithValue(ctx, fieldsCtxKey{}, result)
}

// ClearFields returns context without any fields.
func ClearFields(ctx context.Context) context.Context {
_, ok := ctx.Value(fieldsCtxKey{}).([]interface{})
Expand Down
Loading

0 comments on commit abb0344

Please sign in to comment.