Skip to content

Commit 29246f6

Browse files
authored
Add initial implementation (#1)
1 parent eb5436f commit 29246f6

17 files changed

+1415
-2
lines changed

.github/workflows/bench.yml

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
name: bench
2+
on:
3+
push:
4+
tags:
5+
- v*
6+
branches:
7+
- master
8+
- main
9+
pull_request:
10+
env:
11+
GO111MODULE: "on"
12+
jobs:
13+
bench:
14+
strategy:
15+
matrix:
16+
go-version: [ 1.16.x ]
17+
runs-on: ubuntu-latest
18+
steps:
19+
- name: Install Go
20+
uses: actions/setup-go@v2
21+
with:
22+
go-version: ${{ matrix.go-version }}
23+
- name: Checkout code
24+
uses: actions/checkout@v2
25+
- name: Restore vendor
26+
uses: actions/cache@v2
27+
with:
28+
path: |
29+
vendor
30+
key: ${{ runner.os }}-go${{ matrix.go-version }}-vendor-${{ hashFiles('**/go.mod') }}
31+
- name: Populate dependencies
32+
run: |
33+
(test -d vendor && echo vendor found) || (go mod vendor && du -sh vendor && du -sh ~/go/pkg/mod)
34+
- name: Restore benchstat
35+
uses: actions/cache@v2
36+
with:
37+
path: ~/go/bin/benchstat
38+
key: ${{ runner.os }}-benchstat
39+
- name: Restore base benchmark result
40+
uses: actions/cache@v2
41+
with:
42+
path: |
43+
bench-master.txt
44+
bench-main.txt
45+
# Use base sha for PR or new commit hash for master/main push in benchmark result key.
46+
key: ${{ runner.os }}-bench-${{ (github.event.pull_request.base.sha != github.event.after) && github.event.pull_request.base.sha || github.event.after }}
47+
- name: Benchmark
48+
id: bench
49+
run: |
50+
export REF_NAME=${GITHUB_REF##*/}
51+
BENCH_COUNT=5 make bench-run bench-stat
52+
OUTPUT=$(make bench-stat)
53+
OUTPUT="${OUTPUT//'%'/'%25'}"
54+
OUTPUT="${OUTPUT//$'\n'/'%0A'}"
55+
OUTPUT="${OUTPUT//$'\r'/'%0D'}"
56+
echo "::set-output name=result::$OUTPUT"
57+
- name: Comment Benchmark Result
58+
uses: marocchino/sticky-pull-request-comment@v2
59+
with:
60+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
61+
header: bench
62+
message: |
63+
### Benchmark Result
64+
<details><summary>Benchmark diff with base branch</summary>
65+
66+
```
67+
${{ steps.bench.outputs.result }}
68+
```
69+
</details>

.github/workflows/golangci-lint.yml

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: lint
2+
on:
3+
push:
4+
tags:
5+
- v*
6+
branches:
7+
- master
8+
- main
9+
pull_request:
10+
jobs:
11+
golangci:
12+
name: golangci-lint
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v2
16+
- name: golangci-lint
17+
uses: golangci/[email protected]
18+
with:
19+
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
20+
version: v1.37.1
21+
22+
# Optional: working directory, useful for monorepos
23+
# working-directory: somedir
24+
25+
# Optional: golangci-lint command line arguments.
26+
# args: --issues-exit-code=0
27+
28+
# Optional: show only new issues if it's a pull request. The default value is `false`.
29+
# only-new-issues: true
30+
31+
# Optional: if set to true then the action will use pre-installed Go.
32+
# skip-go-installation: true
33+
34+
# Optional: if set to true then the action don't cache or restore ~/go/pkg.
35+
# skip-pkg-cache: true
36+
37+
# Optional: if set to true then the action don't cache or restore ~/.cache/go-build.
38+
# skip-build-cache: true

.github/workflows/test-unit.yml

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
name: test-unit
2+
on:
3+
push:
4+
branches:
5+
- master
6+
- main
7+
pull_request:
8+
env:
9+
GO111MODULE: "on"
10+
jobs:
11+
test:
12+
strategy:
13+
matrix:
14+
go-version: [ 1.13.x, 1.14.x, 1.15.x, 1.16.x ]
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Install Go
18+
uses: actions/setup-go@v2
19+
with:
20+
go-version: ${{ matrix.go-version }}
21+
- name: Checkout code
22+
uses: actions/checkout@v2
23+
- name: Restore base test coverage
24+
uses: actions/cache@v2
25+
with:
26+
path: |
27+
unit-base.txt
28+
# Use base sha for PR or new commit hash for master/main push in test result key.
29+
key: ${{ runner.os }}-unit-test-coverage-${{ (github.event.pull_request.base.sha != github.event.after) && github.event.pull_request.base.sha || github.event.after }}
30+
- name: Restore vendor
31+
uses: actions/cache@v2
32+
with:
33+
path: |
34+
vendor
35+
key: ${{ runner.os }}-go${{ matrix.go-version }}-vendor-${{ hashFiles('**/go.mod') }}
36+
- name: Populate dependencies
37+
run: |
38+
(test -d vendor && echo vendor found) || (go mod vendor && du -sh vendor && du -sh ~/go/pkg/mod)
39+
- name: Test
40+
id: test
41+
run: |
42+
make test-unit
43+
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
44+
OUTPUT=$(test -e unit-base.txt && (diff unit-base.txt unit.txt || exit 0) || cat unit.txt)
45+
OUTPUT="${OUTPUT//'%'/'%25'}"
46+
OUTPUT="${OUTPUT//$'\n'/'%0A'}"
47+
OUTPUT="${OUTPUT//$'\r'/'%0D'}"
48+
TOTAL=$(grep 'total:' unit.txt)
49+
echo "::set-output name=diff::$OUTPUT"
50+
echo "::set-output name=total::$TOTAL"
51+
- name: Store base coverage
52+
if: ${{ github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' }}
53+
run: cp unit.txt unit-base.txt
54+
- name: Comment Test Coverage
55+
if: matrix.go-version == '1.16.x'
56+
uses: marocchino/sticky-pull-request-comment@v2
57+
with:
58+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
59+
header: unit-test
60+
message: |
61+
### Unit Test Coverage
62+
${{ steps.test.outputs.total }}
63+
<details><summary>Coverage diff with base branch</summary>
64+
65+
```diff
66+
${{ steps.test.outputs.diff }}
67+
```
68+
</details>
69+
70+
- name: Upload code coverage
71+
if: matrix.go-version == '1.16.x'
72+
uses: codecov/codecov-action@v1
73+
with:
74+
file: ./unit.coverprofile
75+
flags: unittests

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/.idea
2+
/bench-*
3+
/unit.coverprofile

Makefile

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# The head of Makefile determines location of dev-go to include standard targets.
2+
GO ?= go
3+
export GO111MODULE = on
4+
5+
ifneq "$(GOFLAGS)" ""
6+
$(info GOFLAGS: ${GOFLAGS})
7+
endif
8+
9+
ifneq "$(wildcard ./vendor )" ""
10+
$(info Using vendor)
11+
modVendor = -mod=vendor
12+
ifeq (,$(findstring -mod,$(GOFLAGS)))
13+
export GOFLAGS := ${GOFLAGS} ${modVendor}
14+
endif
15+
ifneq "$(wildcard ./vendor/github.com/bool64/dev)" ""
16+
DEVGO_PATH := ./vendor/github.com/bool64/dev
17+
endif
18+
endif
19+
20+
ifeq ($(DEVGO_PATH),)
21+
DEVGO_PATH := $(shell GO111MODULE=on $(GO) list ${modVendor} -f '{{.Dir}}' -m github.com/bool64/dev)
22+
ifeq ($(DEVGO_PATH),)
23+
$(info Module github.com/bool64/dev not found, downloading.)
24+
DEVGO_PATH := $(shell export GO111MODULE=on && $(GO) mod tidy && $(GO) list -f '{{.Dir}}' -m github.com/bool64/dev)
25+
endif
26+
endif
27+
28+
-include $(DEVGO_PATH)/makefiles/main.mk
29+
-include $(DEVGO_PATH)/makefiles/test-unit.mk
30+
-include $(DEVGO_PATH)/makefiles/bench.mk
31+
-include $(DEVGO_PATH)/makefiles/lint.mk
32+
-include $(DEVGO_PATH)/makefiles/github-actions.mk
33+
34+
## Run tests
35+
test: test-unit

README.md

+84-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,84 @@
1-
# prom-stats
2-
Prometheus adapter for bool64/stats
1+
# Prometheus Adapter for Contextualized Stats Tracker
2+
3+
This library provides context-driven stats tracker implementation.
4+
5+
[![Build Status](https://github.com/bool64/prom-stats/workflows/test-unit/badge.svg)](https://github.com/bool64/prom-stats/actions?query=branch%3Amaster+workflow%3Atest-unit)
6+
[![Coverage Status](https://codecov.io/gh/bool64/prom-stats/branch/master/graph/badge.svg)](https://codecov.io/gh/bool64/prom-stats)
7+
[![GoDevDoc](https://img.shields.io/badge/dev-doc-00ADD8?logo=go)](https://pkg.go.dev/github.com/bool64/prom-stats)
8+
[![time tracker](https://wakatime.com/badge/github/bool64/prom-stats.svg)](https://wakatime.com/badge/github/bool64/prom-stats)
9+
![Code lines](https://sloc.xyz/github/bool64/prom-stats/?category=code)
10+
![Comments](https://sloc.xyz/github/bool64/prom-stats/?category=comments)
11+
12+
## Features
13+
14+
* Context-driven labels control.
15+
* Zero allocation.
16+
* A simple interface with variadic number of key-value pairs for labels.
17+
* Easily mockable interface free from 3rd party dependencies.
18+
19+
## Example
20+
21+
```go
22+
// Bring your own Prometheus registry.
23+
registry := prometheus.NewRegistry()
24+
tr := prom.Tracker{
25+
Registry: registry,
26+
}
27+
28+
// Add custom Prometheus configuration where necessary.
29+
tr.DeclareHistogram("my_latency_seconds", prometheus.HistogramOpts{
30+
Buckets: []float64{1e-4, 1e-3, 1e-2, 1e-1, 1, 10, 100},
31+
})
32+
33+
ctx := context.Background()
34+
35+
// Add labels to context.
36+
ctx = stats.AddKeysAndValues(ctx, "ctx-label", "ctx-value0")
37+
38+
// Override label values.
39+
ctx = stats.AddKeysAndValues(ctx, "ctx-label", "ctx-value1")
40+
41+
// Collect stats with last mile labels.
42+
tr.Add(ctx, "my_count", 1,
43+
"some-label", "some-value",
44+
)
45+
46+
tr.Add(ctx, "my_latency_seconds", 1.23)
47+
48+
tr.Set(ctx, "temperature", 33.3)
49+
```
50+
51+
## Performance
52+
53+
Sample benchmark result with go1.16.
54+
```
55+
goos: darwin
56+
goarch: amd64
57+
pkg: github.com/bool64/stats/prom-stats
58+
cpu: Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz
59+
```
60+
```
61+
name time/op
62+
Tracker_Add-8 635ns ± 3%
63+
RawPrometheus-8 472ns ± 2%
64+
65+
name alloc/op
66+
Tracker_Add-8 0.00B
67+
RawPrometheus-8 336B ± 0%
68+
69+
name allocs/op
70+
Tracker_Add-8 0.00
71+
RawPrometheus-8 2.00 ± 0%
72+
```
73+
74+
## Caveats
75+
76+
Prometheus client does not support metrics with same name and different label sets.
77+
If you add a label to context, make sure you have it in all cases, at least with an empty value `""`.
78+
79+
## Versioning
80+
81+
This project adheres to [Semantic Versioning](https://semver.org/#semantic-versioning-200).
82+
83+
Before version `1.0.0`, breaking changes are tagged with `MINOR` bump, features and fixes are tagged with `PATCH` bump.
84+
After version `1.0.0`, breaking changes are tagged with `MAJOR` bump.

0 commit comments

Comments
 (0)