6 Commits

Author SHA1 Message Date
vtolstov
18e1442299 Apply Code Coverage Badge 2025-05-01 16:22:17 +00:00
1d11e2292f update ci (#166)
All checks were successful
coverage / build (push) Successful in 6m54s
test / test (push) Successful in 10m36s
2025-05-01 19:15:28 +03:00
b689ebbd0a Merge pull request 'Update workflows' (#117) from atolstikhin/micro-meter-victoriametrics:v3 into v3
All checks were successful
test / test (push) Successful in 12m40s
Reviewed-on: #117
2024-12-15 18:02:30 +03:00
Aleksandr Tolstikhin
0fae124bf4 Update workflows
All checks were successful
automerge / automerge (pull_request) Has been skipped
autoapprove / autoapprove (pull_request) Successful in 7s
dependabot-automerge / automerge (pull_request) Has been skipped
lint / lint (pull_request) Successful in 1m42s
test / test (pull_request) Successful in 25s
2024-12-14 01:38:18 +07:00
dbcf52e590 fix clone with prometheus compat mode
Some checks failed
codeql / analyze (go) (push) Failing after 40s
build / test (push) Failing after 4m54s
build / lint (push) Successful in 9m28s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2024-11-10 17:49:01 +03:00
4fef299e78 add ability to use prometheus compat histogram
Some checks failed
codeql / analyze (go) (push) Failing after 45s
build / test (push) Failing after 4m52s
build / lint (push) Successful in 9m31s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2024-11-09 19:49:45 +03:00
17 changed files with 247 additions and 303 deletions

View File

@@ -1,19 +0,0 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
# Maintain dependencies for Golang
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "daily"

View File

@@ -1,20 +0,0 @@
name: "autoapprove"
on:
pull_request_target:
types: [assigned, opened, synchronize, reopened]
permissions:
pull-requests: write
contents: write
jobs:
autoapprove:
runs-on: ubuntu-latest
steps:
- name: approve
uses: hmarr/auto-approve-action@v3
if: github.actor == 'vtolstov' || github.actor == 'dependabot[bot]'
id: approve
with:
github-token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,21 +0,0 @@
name: "automerge"
on:
pull_request_target:
types: [assigned, opened, synchronize, reopened]
permissions:
pull-requests: write
contents: write
jobs:
automerge:
runs-on: ubuntu-latest
if: github.actor == 'vtolstov'
steps:
- name: merge
id: merge
run: gh pr merge --auto --merge "$PR_URL"
env:
PR_URL: ${{github.event.pull_request.html_url}}
GITHUB_TOKEN: ${{secrets.TOKEN}}

View File

@@ -1,47 +0,0 @@
name: build
on:
push:
branches:
- master
- v3
jobs:
test:
name: test
runs-on: ubuntu-latest
steps:
- name: setup
uses: actions/setup-go@v3
with:
go-version: 1.17
- name: checkout
uses: actions/checkout@v3
- name: cache
uses: actions/cache@v3
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-go-
- name: deps
run: go get -v -t -d ./...
- name: test
env:
INTEGRATION_TESTS: yes
run: go test -mod readonly -v ./...
lint:
name: lint
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
- name: lint
uses: golangci/golangci-lint-action@v3.4.0
continue-on-error: true
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.30
# Optional: working directory, useful for monorepos
# working-directory: somedir
# Optional: golangci-lint command line arguments.
# 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

View File

@@ -1,78 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "codeql"
on:
workflow_run:
workflows: ["prbuild"]
types:
- completed
push:
branches: [ master, v3 ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master, v3 ]
schedule:
- cron: '34 1 * * 0'
jobs:
analyze:
name: analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'go' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: checkout
uses: actions/checkout@v3
- name: setup
uses: actions/setup-go@v3
with:
go-version: 1.17
# Initializes the CodeQL tools for scanning.
- name: init
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: analyze
uses: github/codeql-action/analyze@v2

View File

@@ -1,27 +0,0 @@
name: "dependabot-automerge"
on:
pull_request_target:
types: [assigned, opened, synchronize, reopened]
permissions:
pull-requests: write
contents: write
jobs:
automerge:
runs-on: ubuntu-latest
if: github.actor == 'dependabot[bot]'
steps:
- name: metadata
id: metadata
uses: dependabot/fetch-metadata@v1.3.6
with:
github-token: "${{ secrets.TOKEN }}"
- name: merge
id: merge
if: ${{contains(steps.metadata.outputs.dependency-names, 'go.unistack.org')}}
run: gh pr merge --auto --merge "$PR_URL"
env:
PR_URL: ${{github.event.pull_request.html_url}}
GITHUB_TOKEN: ${{secrets.TOKEN}}

53
.github/workflows/job_coverage.yml vendored Normal file
View File

@@ -0,0 +1,53 @@
name: coverage
on:
push:
branches: [ main, v3, v4 ]
paths-ignore:
- '.github/**'
- '.gitea/**'
pull_request:
branches: [ main, v3, v4 ]
jobs:
build:
if: github.server_url != 'https://github.com'
runs-on: ubuntu-latest
steps:
- name: checkout code
uses: actions/checkout@v4
with:
filter: 'blob:none'
- name: setup go
uses: actions/setup-go@v5
with:
cache-dependency-path: "**/*.sum"
go-version: 'stable'
- name: test coverage
run: |
go test -v -cover ./... -covermode=count -coverprofile coverage.out -coverpkg ./...
go tool cover -func coverage.out -o coverage.out
- name: coverage badge
uses: tj-actions/coverage-badge-go@v2
with:
green: 80
filename: coverage.out
- uses: stefanzweifel/git-auto-commit-action@v4
name: autocommit
with:
commit_message: Apply Code Coverage Badge
skip_fetch: false
skip_checkout: false
file_pattern: ./README.md
- name: push
if: steps.auto-commit-action.outputs.changes_detected == 'true'
uses: ad-m/github-push-action@master
with:
github_token: ${{ github.token }}
branch: ${{ github.ref }}

29
.github/workflows/job_lint.yml vendored Normal file
View File

@@ -0,0 +1,29 @@
name: lint
on:
pull_request:
types: [opened, reopened, synchronize]
branches: [ master, v3, v4 ]
paths-ignore:
- '.github/**'
- '.gitea/**'
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: checkout code
uses: actions/checkout@v4
with:
filter: 'blob:none'
- name: setup go
uses: actions/setup-go@v5
with:
cache-dependency-path: "**/*.sum"
go-version: 'stable'
- name: setup deps
run: go get -v ./...
- name: run lint
uses: golangci/golangci-lint-action@v6
with:
version: 'latest'

31
.github/workflows/job_test.yml vendored Normal file
View File

@@ -0,0 +1,31 @@
name: test
on:
pull_request:
types: [opened, reopened, synchronize]
branches: [ master, v3, v4 ]
push:
branches: [ master, v3, v4 ]
paths-ignore:
- '.github/**'
- '.gitea/**'
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: checkout code
uses: actions/checkout@v4
with:
filter: 'blob:none'
- name: setup go
uses: actions/setup-go@v5
with:
cache-dependency-path: "**/*.sum"
go-version: 'stable'
- name: setup deps
run: go get -v ./...
- name: run test
env:
INTEGRATION_TESTS: yes
run: go test -mod readonly -v ./...

50
.github/workflows/job_tests.yml vendored Normal file
View File

@@ -0,0 +1,50 @@
name: test
on:
pull_request:
types: [opened, reopened, synchronize]
branches: [ master, v3, v4 ]
push:
branches: [ master, v3, v4 ]
paths-ignore:
- '.github/**'
- '.gitea/**'
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: checkout code
uses: actions/checkout@v4
with:
filter: 'blob:none'
- name: checkout tests
uses: actions/checkout@v4
with:
ref: master
filter: 'blob:none'
repository: unistack-org/micro-tests
path: micro-tests
- name: setup go
uses: actions/setup-go@v5
with:
cache-dependency-path: "**/*.sum"
go-version: 'stable'
- name: setup go work
env:
GOWORK: ${{ github.workspace }}/go.work
run: |
go work init
go work use .
go work use micro-tests
- name: setup deps
env:
GOWORK: ${{ github.workspace }}/go.work
run: go get -v ./...
- name: run tests
env:
INTEGRATION_TESTS: yes
GOWORK: ${{ github.workspace }}/go.work
run: |
cd micro-tests
go test -mod readonly -v ./... || true

View File

@@ -1,47 +0,0 @@
name: prbuild
on:
pull_request:
branches:
- master
- v3
jobs:
test:
name: test
runs-on: ubuntu-latest
steps:
- name: setup
uses: actions/setup-go@v3
with:
go-version: 1.17
- name: checkout
uses: actions/checkout@v3
- name: cache
uses: actions/cache@v3
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-go-
- name: deps
run: go get -v -t -d ./...
- name: test
env:
INTEGRATION_TESTS: yes
run: go test -mod readonly -v ./...
lint:
name: lint
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
- name: lint
uses: golangci/golangci-lint-action@v3.4.0
continue-on-error: true
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.30
# Optional: working directory, useful for monorepos
# working-directory: somedir
# Optional: golangci-lint command line arguments.
# 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

5
.golangci.yml Normal file
View File

@@ -0,0 +1,5 @@
run:
concurrency: 8
timeout: 5m
issues-exit-code: 1
tests: true

View File

@@ -1,4 +1,5 @@
# VictoriaMetrics # VictoriaMetrics
![Coverage](https://img.shields.io/badge/Coverage-39.2%25-yellow)
Wrappers are a form of middleware that can be used with go-micro services. They can wrap both the Client and Server handlers. Wrappers are a form of middleware that can be used with go-micro services. They can wrap both the Client and Server handlers.
This plugin implements the HandlerWrapper interface to provide automatic prometheus metric handling This plugin implements the HandlerWrapper interface to provide automatic prometheus metric handling
@@ -21,4 +22,3 @@ When creating your service, add the wrapper like so.
service.Init() service.Init()
``` ```

2
go.mod
View File

@@ -5,7 +5,7 @@ go 1.22
toolchain go1.23.2 toolchain go1.23.2
require ( require (
github.com/VictoriaMetrics/metrics v1.35.1 go.unistack.org/metrics v0.0.1
go.unistack.org/micro/v3 v3.10.100 go.unistack.org/micro/v3 v3.10.100
) )

4
go.sum
View File

@@ -1,9 +1,9 @@
github.com/VictoriaMetrics/metrics v1.35.1 h1:o84wtBKQbzLdDy14XeskkCZih6anG+veZ1SwJHFGwrU=
github.com/VictoriaMetrics/metrics v1.35.1/go.mod h1:r7hveu6xMdUACXvB8TYdAj8WEsKzWB0EkpJN+RDtOf8=
github.com/valyala/fastrand v1.1.0 h1:f+5HkLW4rsgzdNoleUOB69hyT9IlD2ZQh9GyDMfb5G8= github.com/valyala/fastrand v1.1.0 h1:f+5HkLW4rsgzdNoleUOB69hyT9IlD2ZQh9GyDMfb5G8=
github.com/valyala/fastrand v1.1.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ= github.com/valyala/fastrand v1.1.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ=
github.com/valyala/histogram v1.2.0 h1:wyYGAZZt3CpwUiIb9AU/Zbllg1llXyrtApRS815OLoQ= github.com/valyala/histogram v1.2.0 h1:wyYGAZZt3CpwUiIb9AU/Zbllg1llXyrtApRS815OLoQ=
github.com/valyala/histogram v1.2.0/go.mod h1:Hb4kBwb4UxsaNbbbh+RRz8ZR6pdodR57tzWUS3BUzXY= github.com/valyala/histogram v1.2.0/go.mod h1:Hb4kBwb4UxsaNbbbh+RRz8ZR6pdodR57tzWUS3BUzXY=
go.unistack.org/metrics v0.0.1 h1:sCnGO059ZccGC/D34iRH121eSk+7ci5+OY9cl5K7GKY=
go.unistack.org/metrics v0.0.1/go.mod h1:1FY4R7EKJa9Oz2D6wlGScNerpl6igRs9Cx/3et4Rgs4=
go.unistack.org/micro/v3 v3.10.100 h1:yWOaU0ImCGm5k5MUzlIobJUOr+KLfrR/BoDZvcHyKxM= go.unistack.org/micro/v3 v3.10.100 h1:yWOaU0ImCGm5k5MUzlIobJUOr+KLfrR/BoDZvcHyKxM=
go.unistack.org/micro/v3 v3.10.100/go.mod h1:YzMldzHN9Ei+zy5t/Psu7RUWDZwUfrNYiStSQtTz90g= go.unistack.org/micro/v3 v3.10.100/go.mod h1:YzMldzHN9Ei+zy5t/Psu7RUWDZwUfrNYiStSQtTz90g=
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=

View File

@@ -4,105 +4,129 @@ import (
"io" "io"
"time" "time"
"github.com/VictoriaMetrics/metrics" "go.unistack.org/metrics"
"go.unistack.org/micro/v3/meter" "go.unistack.org/micro/v3/meter"
) )
type victoriametricsMeter struct { type victoriametricsMeter struct {
set *metrics.Set set *metrics.Set
opts meter.Options opts meter.Options
prometheusCompat bool
}
type prometheusCompatKey struct{}
func PrometheusCompat(b bool) meter.Option {
return meter.SetOption(prometheusCompatKey{}, b)
} }
func NewMeter(opts ...meter.Option) meter.Meter { func NewMeter(opts ...meter.Option) meter.Meter {
return &victoriametricsMeter{set: metrics.NewSet(), opts: meter.NewOptions(opts...)} m := &victoriametricsMeter{set: metrics.NewSet(), opts: meter.NewOptions(opts...)}
if v, ok := m.opts.Context.Value(prometheusCompatKey{}).(bool); ok {
m.prometheusCompat = v
}
return m
} }
func (r *victoriametricsMeter) Name() string { func (m *victoriametricsMeter) Name() string {
return r.opts.Name return m.opts.Name
} }
func (r *victoriametricsMeter) Clone(opts ...meter.Option) meter.Meter { func (m *victoriametricsMeter) Clone(opts ...meter.Option) meter.Meter {
options := r.opts options := m.opts
for _, o := range opts { for _, o := range opts {
o(&options) o(&options)
} }
return &victoriametricsMeter{set: r.set, opts: options} nm := &victoriametricsMeter{set: m.set, opts: options, prometheusCompat: m.prometheusCompat}
if v, ok := m.opts.Context.Value(prometheusCompatKey{}).(bool); ok {
m.prometheusCompat = v
}
return nm
} }
func (r *victoriametricsMeter) buildName(name string, labels ...string) string { func (m *victoriametricsMeter) buildName(name string, labels ...string) string {
nl := len(r.opts.Labels) + len(labels) nl := len(m.opts.Labels) + len(labels)
if nl == 0 { if nl == 0 {
return name return name
} }
nlabels := make([]string, 0, nl) nlabels := make([]string, 0, nl)
nlabels = append(nlabels, r.opts.Labels...) nlabels = append(nlabels, m.opts.Labels...)
nlabels = append(nlabels, labels...) nlabels = append(nlabels, labels...)
return meter.BuildName(name, nlabels...) return meter.BuildName(name, nlabels...)
} }
func (r *victoriametricsMeter) Counter(name string, labels ...string) meter.Counter { func (m *victoriametricsMeter) Counter(name string, labels ...string) meter.Counter {
return r.set.GetOrCreateCounter(r.buildName(name, labels...)) return m.set.GetOrCreateCounter(m.buildName(name, labels...))
} }
func (r *victoriametricsMeter) FloatCounter(name string, labels ...string) meter.FloatCounter { func (m *victoriametricsMeter) FloatCounter(name string, labels ...string) meter.FloatCounter {
return r.set.GetOrCreateFloatCounter(r.buildName(name, labels...)) return m.set.GetOrCreateFloatCounter(m.buildName(name, labels...))
} }
func (r *victoriametricsMeter) Gauge(name string, f func() float64, labels ...string) meter.Gauge { func (m *victoriametricsMeter) Gauge(name string, f func() float64, labels ...string) meter.Gauge {
return r.set.GetOrCreateGauge(r.buildName(name, labels...), f) return m.set.GetOrCreateGauge(m.buildName(name, labels...), f)
} }
func (r *victoriametricsMeter) Histogram(name string, labels ...string) meter.Histogram { func (m *victoriametricsMeter) Histogram(name string, labels ...string) meter.Histogram {
return r.set.GetOrCreateHistogram(r.buildName(name, labels...)) if m.prometheusCompat {
return m.set.GetOrCreateCompatibleHistogram(m.buildName(name, labels...))
}
return m.set.GetOrCreateHistogram(m.buildName(name, labels...))
} }
func (r *victoriametricsMeter) Summary(name string, labels ...string) meter.Summary { func (m *victoriametricsMeter) Summary(name string, labels ...string) meter.Summary {
return r.set.GetOrCreateSummary(r.buildName(name, labels...)) return m.set.GetOrCreateSummary(m.buildName(name, labels...))
} }
func (r *victoriametricsMeter) SummaryExt(name string, window time.Duration, quantiles []float64, labels ...string) meter.Summary { func (m *victoriametricsMeter) SummaryExt(name string, window time.Duration, quantiles []float64, labels ...string) meter.Summary {
return r.set.GetOrCreateSummaryExt(r.buildName(name, labels...), window, quantiles) return m.set.GetOrCreateSummaryExt(m.buildName(name, labels...), window, quantiles)
} }
func (r *victoriametricsMeter) Set(opts ...meter.Option) meter.Meter { func (m *victoriametricsMeter) Set(opts ...meter.Option) meter.Meter {
m := &victoriametricsMeter{opts: r.opts} nm := &victoriametricsMeter{opts: m.opts}
for _, o := range opts {
o(&nm.opts)
}
nm.set = metrics.NewSet()
if v, ok := nm.opts.Context.Value(prometheusCompatKey{}).(bool); ok {
nm.prometheusCompat = v
}
return nm
}
func (m *victoriametricsMeter) Init(opts ...meter.Option) error {
for _, o := range opts { for _, o := range opts {
o(&m.opts) o(&m.opts)
} }
m.set = metrics.NewSet() if v, ok := m.opts.Context.Value(prometheusCompatKey{}).(bool); ok {
return m m.prometheusCompat = v
}
func (r *victoriametricsMeter) Init(opts ...meter.Option) error {
for _, o := range opts {
o(&r.opts)
} }
return nil return nil
} }
func (r *victoriametricsMeter) Write(w io.Writer, opts ...meter.Option) error { func (m *victoriametricsMeter) Write(w io.Writer, opts ...meter.Option) error {
options := r.opts options := m.opts
for _, o := range opts { for _, o := range opts {
o(&options) o(&options)
} }
r.set.WritePrometheus(w) m.set.WritePrometheus(w)
if options.WriteProcessMetrics { if options.WriteProcessMetrics {
metrics.WriteProcessMetrics(w) metrics.WriteProcessMetrics(w)
} }
if options.WriteFDMetrics { if options.WriteFDMetrics {
metrics.WriteFDMetrics(w) metrics.WriteFDMetrics(w)
} }
return nil return nil
} }
func (r *victoriametricsMeter) Options() meter.Options { func (m *victoriametricsMeter) Options() meter.Options {
return r.opts return m.opts
} }
func (r *victoriametricsMeter) String() string { func (m *victoriametricsMeter) String() string {
return "victoriametrics" return "victoriametrics"
} }

View File

@@ -1,6 +1,7 @@
package victoriametrics package victoriametrics
import ( import (
"bytes"
"testing" "testing"
) )
@@ -16,3 +17,13 @@ func TestBuildName(t *testing.T) {
cnt := m.Counter("counter", "key", "val") cnt := m.Counter("counter", "key", "val")
cnt.Inc() cnt.Inc()
} }
func TestPrometheusCompat(t *testing.T) {
m := NewMeter(PrometheusCompat(true))
m.Histogram("foo", "key", "val").Update(15)
buf := bytes.NewBuffer(nil)
_ = m.Write(buf)
t.Logf("\n%s", buf.Bytes())
}