Skip to content
Snippets Groups Projects
Commit d987c247 authored by renovate's avatar renovate
Browse files

Update git.autistici.org/ai3/go-common digest to 39e01d3

parent 305f3cb4
No related branches found
No related tags found
1 merge request!23Update git.autistici.org/ai3/go-common digest to 39e01d3
Showing
with 1828 additions and 587 deletions
...@@ -3,10 +3,10 @@ module git.autistici.org/ai3/tools/acmeserver ...@@ -3,10 +3,10 @@ module git.autistici.org/ai3/tools/acmeserver
go 1.14 go 1.14
require ( require (
git.autistici.org/ai3/go-common v0.0.0-20210118064555-73f00db54723 git.autistici.org/ai3/go-common v0.0.0-20220814151247-39e01d32d5ee
git.autistici.org/ai3/tools/replds v0.0.0-20210117165138-e6368d266143 git.autistici.org/ai3/tools/replds v0.0.0-20210117165138-e6368d266143
github.com/miekg/dns v1.1.43 github.com/miekg/dns v1.1.43
github.com/prometheus/client_golang v1.12.2 github.com/prometheus/client_golang v1.12.2
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
) )
This diff is collapsed.
language: go
go_import_path: contrib.go.opencensus.io
go:
- 1.11.x
env:
global:
GO111MODULE=on
before_script:
- make install-tools
script:
- make travis-ci
# TODO: Fix this on windows.
ALL_SRC := $(shell find . -name '*.go' \
-not -path './vendor/*' \
-not -path '*/gen-go/*' \
-type f | sort)
ALL_PKGS := $(shell go list $(sort $(dir $(ALL_SRC))))
GOTEST_OPT?=-v -race -timeout 30s
GOTEST_OPT_WITH_COVERAGE = $(GOTEST_OPT) -coverprofile=coverage.txt -covermode=atomic
GOTEST=go test
GOFMT=gofmt
GOLINT=golint
GOVET=go vet
EMBEDMD=embedmd
# TODO decide if we need to change these names.
README_FILES := $(shell find . -name '*README.md' | sort | tr '\n' ' ')
.DEFAULT_GOAL := fmt-lint-vet-embedmd-test
.PHONY: fmt-lint-vet-embedmd-test
fmt-lint-vet-embedmd-test: fmt lint vet embedmd test
# TODO enable test-with-coverage in tavis
.PHONY: travis-ci
travis-ci: fmt lint vet embedmd test test-386
all-pkgs:
@echo $(ALL_PKGS) | tr ' ' '\n' | sort
all-srcs:
@echo $(ALL_SRC) | tr ' ' '\n' | sort
.PHONY: test
test:
$(GOTEST) $(GOTEST_OPT) $(ALL_PKGS)
.PHONY: test-386
test-386:
GOARCH=386 $(GOTEST) -v -timeout 30s $(ALL_PKGS)
.PHONY: test-with-coverage
test-with-coverage:
$(GOTEST) $(GOTEST_OPT_WITH_COVERAGE) $(ALL_PKGS)
.PHONY: fmt
fmt:
@FMTOUT=`$(GOFMT) -s -l $(ALL_SRC) 2>&1`; \
if [ "$$FMTOUT" ]; then \
echo "$(GOFMT) FAILED => gofmt the following files:\n"; \
echo "$$FMTOUT\n"; \
exit 1; \
else \
echo "Fmt finished successfully"; \
fi
.PHONY: lint
lint:
@LINTOUT=`$(GOLINT) $(ALL_PKGS) 2>&1`; \
if [ "$$LINTOUT" ]; then \
echo "$(GOLINT) FAILED => clean the following lint errors:\n"; \
echo "$$LINTOUT\n"; \
exit 1; \
else \
echo "Lint finished successfully"; \
fi
.PHONY: vet
vet:
# TODO: Understand why go vet downloads "github.com/google/go-cmp v0.2.0"
@VETOUT=`$(GOVET) ./... | grep -v "go: downloading" 2>&1`; \
if [ "$$VETOUT" ]; then \
echo "$(GOVET) FAILED => go vet the following files:\n"; \
echo "$$VETOUT\n"; \
exit 1; \
else \
echo "Vet finished successfully"; \
fi
.PHONY: embedmd
embedmd:
@EMBEDMDOUT=`$(EMBEDMD) -d $(README_FILES) 2>&1`; \
if [ "$$EMBEDMDOUT" ]; then \
echo "$(EMBEDMD) FAILED => embedmd the following files:\n"; \
echo "$$EMBEDMDOUT\n"; \
exit 1; \
else \
echo "Embedmd finished successfully"; \
fi
.PHONY: install-tools
install-tools:
go get -u golang.org/x/tools/cmd/cover
go get -u golang.org/x/lint/golint
go get -u github.com/rakyll/embedmd
# OpenCensus Go Zipkin Exporter
[![Build Status](https://travis-ci.org/census-ecosystem/opencensus-go-exporter-zipkin.svg?branch=master)](https://travis-ci.org/census-ecosystem/opencensus-go-exporter-zipkin) [![GoDoc][godoc-image]][godoc-url]
Provides OpenCensus exporter support for Zipkin.
## Installation
```
$ go get -u contrib.go.opencensus.io/exporter/zipkin
```
[godoc-image]: https://godoc.org/contrib.go.opencensus.io/exporter/zipkin?status.svg
[godoc-url]: https://godoc.org/contrib.go.opencensus.io/exporter/zipkin
module contrib.go.opencensus.io/exporter/zipkin
require (
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
github.com/openzipkin/zipkin-go v0.2.2
go.opencensus.io v0.22.4
)
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/openzipkin/zipkin-go v0.2.2 h1:nY8Hti+WKaP0cRsSeQ026wU03QsM762XBeCXBb9NAWI=
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
go.opencensus.io v0.22.4 h1:LYy1Hy3MJdrCdMwwzxA/dRok4ejH+RwNGbuoD9fCjto=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/grpc v1.19.0 h1:cfg4PD8YEdSFnm7qLV4++93WcmhH2nIUhMjhdCvl3j8=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
google.golang.org/grpc v1.20.1 h1:Hz2g2wirWK7H0qIIhGIqRGTuMwTE8HEKFnDZZ7lm9NU=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
// Copyright 2017, OpenCensus Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package zipkin contains an trace exporter for Zipkin.
package zipkin // import "contrib.go.opencensus.io/exporter/zipkin"
import (
"encoding/binary"
"fmt"
"strconv"
"github.com/openzipkin/zipkin-go/model"
"github.com/openzipkin/zipkin-go/reporter"
"go.opencensus.io/trace"
)
// Exporter is an implementation of trace.Exporter that uploads spans to a
// Zipkin server.
type Exporter struct {
reporter reporter.Reporter
localEndpoint *model.Endpoint
}
// NewExporter returns an implementation of trace.Exporter that uploads spans
// to a Zipkin server.
//
// reporter is a Zipkin Reporter which will be used to send the spans. These
// can be created with the openzipkin library, using one of the packages under
// github.com/openzipkin/zipkin-go/reporter.
//
// localEndpoint sets the local endpoint of exported spans. It can be
// constructed with github.com/openzipkin/zipkin-go.NewEndpoint, e.g.:
// localEndpoint, err := NewEndpoint("my server", listener.Addr().String())
// localEndpoint can be nil.
func NewExporter(reporter reporter.Reporter, localEndpoint *model.Endpoint) *Exporter {
return &Exporter{
reporter: reporter,
localEndpoint: localEndpoint,
}
}
// ExportSpan exports a span to a Zipkin server.
func (e *Exporter) ExportSpan(s *trace.SpanData) {
e.reporter.Send(zipkinSpan(s, e.localEndpoint))
}
const (
statusCodeTagKey = "error"
statusDescriptionTagKey = "opencensus.status_description"
)
var (
sampledTrue = true
canonicalCodes = [...]string{
"OK",
"CANCELLED",
"UNKNOWN",
"INVALID_ARGUMENT",
"DEADLINE_EXCEEDED",
"NOT_FOUND",
"ALREADY_EXISTS",
"PERMISSION_DENIED",
"RESOURCE_EXHAUSTED",
"FAILED_PRECONDITION",
"ABORTED",
"OUT_OF_RANGE",
"UNIMPLEMENTED",
"INTERNAL",
"UNAVAILABLE",
"DATA_LOSS",
"UNAUTHENTICATED",
}
)
func canonicalCodeString(code int32) string {
if code < 0 || int(code) >= len(canonicalCodes) {
return "error code " + strconv.FormatInt(int64(code), 10)
}
return canonicalCodes[code]
}
func convertTraceID(t trace.TraceID) model.TraceID {
return model.TraceID{
High: binary.BigEndian.Uint64(t[:8]),
Low: binary.BigEndian.Uint64(t[8:]),
}
}
func convertSpanID(s trace.SpanID) model.ID {
return model.ID(binary.BigEndian.Uint64(s[:]))
}
func spanKind(s *trace.SpanData) model.Kind {
switch s.SpanKind {
case trace.SpanKindClient:
return model.Client
case trace.SpanKindServer:
return model.Server
}
return model.Undetermined
}
func zipkinSpan(s *trace.SpanData, localEndpoint *model.Endpoint) model.SpanModel {
sc := s.SpanContext
z := model.SpanModel{
SpanContext: model.SpanContext{
TraceID: convertTraceID(sc.TraceID),
ID: convertSpanID(sc.SpanID),
Sampled: &sampledTrue,
},
Kind: spanKind(s),
Name: s.Name,
Timestamp: s.StartTime,
Shared: false,
LocalEndpoint: localEndpoint,
}
if s.ParentSpanID != (trace.SpanID{}) {
id := convertSpanID(s.ParentSpanID)
z.ParentID = &id
}
if s, e := s.StartTime, s.EndTime; !s.IsZero() && !e.IsZero() {
z.Duration = e.Sub(s)
}
// construct Tags from s.Attributes and s.Status.
if len(s.Attributes) != 0 {
m := make(map[string]string, len(s.Attributes)+2)
for key, value := range s.Attributes {
switch v := value.(type) {
case string:
m[key] = v
case bool:
if v {
m[key] = "true"
} else {
m[key] = "false"
}
case int64:
m[key] = strconv.FormatInt(v, 10)
case float64:
m[key] = strconv.FormatFloat(v, 'f', -1, 64)
}
}
z.Tags = m
}
if s.Status.Code != 0 || s.Status.Message != "" {
if z.Tags == nil {
z.Tags = make(map[string]string, 2)
}
if s.Status.Code != 0 {
z.Tags[statusCodeTagKey] = canonicalCodeString(s.Status.Code)
}
if s.Status.Message != "" {
z.Tags[statusDescriptionTagKey] = s.Status.Message
}
}
// construct Annotations from s.Annotations and s.MessageEvents.
if len(s.Annotations) != 0 || len(s.MessageEvents) != 0 {
z.Annotations = make([]model.Annotation, 0, len(s.Annotations)+len(s.MessageEvents))
for _, a := range s.Annotations {
z.Annotations = append(z.Annotations, model.Annotation{
Timestamp: a.Time,
Value: a.Message,
})
}
for _, m := range s.MessageEvents {
a := model.Annotation{
Timestamp: m.Time,
}
switch m.EventType {
case trace.MessageEventTypeSent:
a.Value = fmt.Sprintf("Sent %d bytes", m.UncompressedByteSize)
case trace.MessageEventTypeRecv:
a.Value = fmt.Sprintf("Received %d bytes", m.UncompressedByteSize)
default:
a.Value = "<?>"
}
z.Annotations = append(z.Annotations, a)
}
}
return z
}
...@@ -3,8 +3,14 @@ stages: ...@@ -3,8 +3,14 @@ stages:
run_tests: run_tests:
stage: test stage: test
image: "debian:bullseye" image: registry.git.autistici.org/ai3/docker/test/golang:master
script: script:
- "apt update" - run-go-test ./...
- "env DEBIAN_FRONTEND=noninteractive apt -y install golang git" artifacts:
- "go test -v ./..." when: always
reports:
coverage_report:
coverage_format: cobertura
path: cover.xml
junit: report.xml
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"fmt" "fmt"
"log" "log"
"math/rand" "math/rand"
"mime"
"net/http" "net/http"
"net/url" "net/url"
"os" "os"
...@@ -158,7 +159,7 @@ func (b *balancedBackend) Call(ctx context.Context, shard, path string, req, res ...@@ -158,7 +159,7 @@ func (b *balancedBackend) Call(ctx context.Context, shard, path string, req, res
defer httpResp.Body.Close() // nolint defer httpResp.Body.Close() // nolint
// Decode the response, unless the 'resp' output is nil. // Decode the response, unless the 'resp' output is nil.
if httpResp.Header.Get("Content-Type") != "application/json" { if ct, _, _ := mime.ParseMediaType(httpResp.Header.Get("Content-Type")); ct != "application/json" {
return errors.New("not a JSON response") return errors.New("not a JSON response")
} }
if resp == nil { if resp == nil {
......
module git.autistici.org/ai3/go-common module git.autistici.org/ai3/go-common
go 1.11 go 1.14
require ( require (
contrib.go.opencensus.io/exporter/zipkin v0.1.2 github.com/NYTimes/gziphandler v1.1.1
github.com/amoghe/go-crypt v0.0.0-20191109212615-b2ff80594b7f github.com/amoghe/go-crypt v0.0.0-20220222110647-20eada5f5964
github.com/bbrks/wrap/v2 v2.5.0 github.com/bbrks/wrap/v2 v2.5.0
github.com/cenkalti/backoff/v4 v4.1.0 github.com/cenkalti/backoff/v4 v4.1.3
github.com/coreos/go-systemd/v22 v22.1.0 github.com/coreos/go-systemd/v22 v22.3.2
github.com/duo-labs/webauthn v0.0.0-20220330035159-03696f3d4499
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594 github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594
github.com/go-asn1-ber/asn1-ber v1.5.3 github.com/fxamacker/cbor/v2 v2.4.0
github.com/go-ldap/ldap/v3 v3.2.4 github.com/go-asn1-ber/asn1-ber v1.5.4
github.com/go-ldap/ldap/v3 v3.4.4
github.com/gofrs/flock v0.8.0 // indirect github.com/gofrs/flock v0.8.0 // indirect
github.com/google/go-cmp v0.5.4 github.com/google/go-cmp v0.5.8
github.com/gorilla/handlers v1.5.1
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40
github.com/mattn/go-sqlite3 v1.14.14
github.com/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75 github.com/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75
github.com/openzipkin/zipkin-go v0.2.5 github.com/prometheus/client_golang v1.12.2
github.com/prometheus/client_golang v1.9.0
github.com/russross/blackfriday/v2 v2.1.0 github.com/russross/blackfriday/v2 v2.1.0
github.com/theckman/go-flock v0.8.0 github.com/theckman/go-flock v0.8.1
github.com/tstranex/u2f v1.0.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.34.0
go.opencensus.io v0.22.5 go.opentelemetry.io/otel v1.9.0
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad go.opentelemetry.io/otel/exporters/zipkin v1.9.0
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a go.opentelemetry.io/otel/sdk v1.9.0
go.opentelemetry.io/otel/trace v1.9.0
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4
) )
This diff is collapsed.
package serverutil package serverutil
import ( import (
"compress/gzip"
"context" "context"
"crypto/tls" "crypto/tls"
"fmt" "fmt"
...@@ -16,12 +17,25 @@ import ( ...@@ -16,12 +17,25 @@ import (
"time" "time"
"git.autistici.org/ai3/go-common/tracing" "git.autistici.org/ai3/go-common/tracing"
"github.com/NYTimes/gziphandler"
"github.com/coreos/go-systemd/v22/daemon" "github.com/coreos/go-systemd/v22/daemon"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/client_golang/prometheus/promhttp"
) )
var gracefulShutdownTimeout = 3 * time.Second var (
gracefulShutdownTimeout = 3 * time.Second
gzipLevel = gzip.BestSpeed
gzipMinSize = 1300
gzipContentTypes = []string{
"application/json",
"application/javascript",
"text/html",
"text/plain",
"text/css",
}
)
// ServerConfig stores common HTTP/HTTPS server configuration parameters. // ServerConfig stores common HTTP/HTTPS server configuration parameters.
type ServerConfig struct { type ServerConfig struct {
...@@ -29,20 +43,23 @@ type ServerConfig struct { ...@@ -29,20 +43,23 @@ type ServerConfig struct {
MaxInflightRequests int `yaml:"max_inflight_requests"` MaxInflightRequests int `yaml:"max_inflight_requests"`
RequestTimeoutSecs int `yaml:"request_timeout"` RequestTimeoutSecs int `yaml:"request_timeout"`
TrustedForwarders []string `yaml:"trusted_forwarders"` TrustedForwarders []string `yaml:"trusted_forwarders"`
// TODO: switch do disable_compression (flip default) later.
EnableCompression bool `yaml:"enable_compression"`
} }
func (config *ServerConfig) buildHTTPServer(h http.Handler) (*http.Server, error) { func (config *ServerConfig) buildHTTPHandler(h http.Handler) (http.Handler, *tls.Config, error) {
var tlsConfig *tls.Config var tlsConfig *tls.Config
var err error var err error
if config != nil { if config != nil {
if config.TLS != nil { if config.TLS != nil {
tlsConfig, err = config.TLS.TLSConfig() tlsConfig, err = config.TLS.TLSConfig()
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
h, err = config.TLS.TLSAuthWrapper(h) h, err = config.TLS.TLSAuthWrapper(h)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
} }
...@@ -51,7 +68,7 @@ func (config *ServerConfig) buildHTTPServer(h http.Handler) (*http.Server, error ...@@ -51,7 +68,7 @@ func (config *ServerConfig) buildHTTPServer(h http.Handler) (*http.Server, error
if len(config.TrustedForwarders) > 0 { if len(config.TrustedForwarders) > 0 {
h, err = newProxyHeaders(h, config.TrustedForwarders) h, err = newProxyHeaders(h, config.TrustedForwarders)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
} }
...@@ -68,16 +85,23 @@ func (config *ServerConfig) buildHTTPServer(h http.Handler) (*http.Server, error ...@@ -68,16 +85,23 @@ func (config *ServerConfig) buildHTTPServer(h http.Handler) (*http.Server, error
} }
} }
// These are not meant to be external-facing servers, so we // Add all the default handlers (health, monitoring, etc).
// can be generous with the timeouts to keep the number of h = addDefaultHandlers(h)
// reconnections low.
return &http.Server{ // Optionally enable compression.
Handler: addDefaultHandlers(h), if config != nil && config.EnableCompression {
ReadTimeout: 30 * time.Second, gzwrap, err := gziphandler.GzipHandlerWithOpts(
WriteTimeout: 30 * time.Second, gziphandler.CompressionLevel(gzipLevel),
IdleTimeout: 600 * time.Second, gziphandler.MinSize(gzipMinSize),
TLSConfig: tlsConfig, gziphandler.ContentTypes(gzipContentTypes),
}, nil )
if err != nil {
return nil, nil, err
}
h = gzwrap(h)
}
return h, tlsConfig, nil
} }
// Serve HTTP(S) content on the specified address. If config.TLS is // Serve HTTP(S) content on the specified address. If config.TLS is
...@@ -91,12 +115,22 @@ func Serve(h http.Handler, config *ServerConfig, addr string) error { ...@@ -91,12 +115,22 @@ func Serve(h http.Handler, config *ServerConfig, addr string) error {
// debugging endpoints). // debugging endpoints).
h = tracing.WrapHandler(h, guessEndpointName(addr)) h = tracing.WrapHandler(h, guessEndpointName(addr))
// Create the HTTP server. // Create the top-level HTTP handler with all our additions.
srv, err := config.buildHTTPServer(h) hh, tlsConfig, err := config.buildHTTPHandler(h)
if err != nil { if err != nil {
return err return err
} }
// These are not meant to be external-facing servers, so we
// can be generous with the timeouts to keep the number of
// reconnections low.
srv := &http.Server{
Handler: hh,
ReadHeaderTimeout: 30 * time.Second,
IdleTimeout: 600 * time.Second,
TLSConfig: tlsConfig,
}
// Create the net.Listener first, so we can detect // Create the net.Listener first, so we can detect
// initialization-time errors safely. // initialization-time errors safely.
l, err := net.Listen("tcp", addr) l, err := net.Listen("tcp", addr)
......
...@@ -3,6 +3,7 @@ package serverutil ...@@ -3,6 +3,7 @@ package serverutil
import ( import (
"encoding/json" "encoding/json"
"log" "log"
"mime"
"net/http" "net/http"
) )
...@@ -14,7 +15,7 @@ func DecodeJSONRequest(w http.ResponseWriter, r *http.Request, obj interface{}) ...@@ -14,7 +15,7 @@ func DecodeJSONRequest(w http.ResponseWriter, r *http.Request, obj interface{})
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return false return false
} }
if r.Header.Get("Content-Type") != "application/json" { if ct, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type")); ct != "application/json" {
http.Error(w, "Need JSON request", http.StatusBadRequest) http.Error(w, "Need JSON request", http.StatusBadRequest)
return false return false
} }
...@@ -29,19 +30,15 @@ func DecodeJSONRequest(w http.ResponseWriter, r *http.Request, obj interface{}) ...@@ -29,19 +30,15 @@ func DecodeJSONRequest(w http.ResponseWriter, r *http.Request, obj interface{})
// EncodeJSONResponse writes an application/json response to w. // EncodeJSONResponse writes an application/json response to w.
func EncodeJSONResponse(w http.ResponseWriter, obj interface{}) { func EncodeJSONResponse(w http.ResponseWriter, obj interface{}) {
data, err := json.Marshal(obj)
if err != nil {
log.Printf("JSON serialization error: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
w.Header().Set("Pragma", "no-cache") w.Header().Set("Pragma", "no-cache")
w.Header().Set("Cache-Control", "no-store") w.Header().Set("Cache-Control", "no-store")
w.Header().Set("Expires", "-1") w.Header().Set("Expires", "-1")
w.Header().Set("X-Content-Type-Options", "nosniff") w.Header().Set("X-Content-Type-Options", "nosniff")
if _, err = w.Write(data); err != nil {
log.Printf("error writing response: %v", err) err := json.NewEncoder(w).Encode(obj)
if err != nil {
log.Printf("error writing JSON response: %v", err)
// Too late to return an error to the client now.
} }
} }
...@@ -4,13 +4,12 @@ import ( ...@@ -4,13 +4,12 @@ import (
"fmt" "fmt"
"net" "net"
"net/http" "net/http"
"strings"
"github.com/gorilla/handlers"
) )
type proxyHeaders struct { type proxyHeaders struct {
wrap, phWrap http.Handler wrap http.Handler
forwarders []net.IPNet forwarders []net.IPNet
} }
func newProxyHeaders(h http.Handler, trustedForwarders []string) (http.Handler, error) { func newProxyHeaders(h http.Handler, trustedForwarders []string) (http.Handler, error) {
...@@ -20,7 +19,6 @@ func newProxyHeaders(h http.Handler, trustedForwarders []string) (http.Handler, ...@@ -20,7 +19,6 @@ func newProxyHeaders(h http.Handler, trustedForwarders []string) (http.Handler,
} }
return &proxyHeaders{ return &proxyHeaders{
wrap: h, wrap: h,
phWrap: handlers.ProxyHeaders(h),
forwarders: f, forwarders: f,
}, nil }, nil
} }
...@@ -32,12 +30,28 @@ func (p *proxyHeaders) ServeHTTP(w http.ResponseWriter, r *http.Request) { ...@@ -32,12 +30,28 @@ func (p *proxyHeaders) ServeHTTP(w http.ResponseWriter, r *http.Request) {
} }
ip := net.ParseIP(host) ip := net.ParseIP(host)
if ip != nil && matchIPNetList(ip, p.forwarders) { if ip != nil && matchIPNetList(ip, p.forwarders) {
p.phWrap.ServeHTTP(w, r) if fwd := getForwardedIP(r); fwd != "" {
return r.RemoteAddr = fwd
}
} }
p.wrap.ServeHTTP(w, r) p.wrap.ServeHTTP(w, r)
} }
// Parse the X-Real-IP or X-Forwarded-For headers, if present, to get
// the original client IP.
func getForwardedIP(r *http.Request) string {
if s := r.Header.Get("X-Real-IP"); s != "" {
return s
}
if s := r.Header.Get("X-Forwarded-For"); s != "" {
if n := strings.IndexByte(s, ','); n > 0 {
s = s[:n]
}
return s
}
return ""
}
func fullMask(ip net.IP) net.IPMask { func fullMask(ip net.IP) net.IPMask {
if ip.To4() == nil { if ip.To4() == nil {
return net.CIDRMask(128, 128) return net.CIDRMask(128, 128)
......
...@@ -14,7 +14,8 @@ import ( ...@@ -14,7 +14,8 @@ import (
// TLSAuthACL describes a single access control entry. Path and // TLSAuthACL describes a single access control entry. Path and
// CommonName are anchored regular expressions (they must match the // CommonName are anchored regular expressions (they must match the
// entire string). // entire string). The first path to match in a list of ACLs will
// identify the ACL to be applied.
type TLSAuthACL struct { type TLSAuthACL struct {
Path string `yaml:"path"` Path string `yaml:"path"`
CommonName string `yaml:"cn"` CommonName string `yaml:"cn"`
...@@ -32,10 +33,11 @@ func (p *TLSAuthACL) compile() error { ...@@ -32,10 +33,11 @@ func (p *TLSAuthACL) compile() error {
return err return err
} }
func (p *TLSAuthACL) match(req *http.Request) bool { func (p *TLSAuthACL) matchPath(req *http.Request) bool {
if !p.pathRx.MatchString(req.URL.Path) { return p.pathRx.MatchString(req.URL.Path)
return false }
}
func (p *TLSAuthACL) matchCN(req *http.Request) bool {
for _, cert := range req.TLS.PeerCertificates { for _, cert := range req.TLS.PeerCertificates {
if p.cnRx.MatchString(cert.Subject.CommonName) { if p.cnRx.MatchString(cert.Subject.CommonName) {
return true return true
...@@ -81,9 +83,13 @@ func (c *TLSAuthConfig) match(req *http.Request) bool { ...@@ -81,9 +83,13 @@ func (c *TLSAuthConfig) match(req *http.Request) bool {
if c == nil || len(c.Allow) == 0 { if c == nil || len(c.Allow) == 0 {
return true return true
} }
for _, acl := range c.Allow { for _, acl := range c.Allow {
if acl.match(req) { if acl.matchPath(req) {
return true if acl.matchCN(req) {
return true
}
break
} }
} }
return false return false
...@@ -157,7 +163,7 @@ func (c *TLSServerConfig) TLSAuthWrapper(h http.Handler) (http.Handler, error) { ...@@ -157,7 +163,7 @@ func (c *TLSServerConfig) TLSAuthWrapper(h http.Handler) (http.Handler, error) {
// Log the failed access, useful for debugging. // Log the failed access, useful for debugging.
var tlsmsg string var tlsmsg string
if r.TLS != nil && len(r.TLS.PeerCertificates) > 0 { if r.TLS != nil && len(r.TLS.PeerCertificates) > 0 {
tlsmsg = fmt.Sprintf(" TLS client '%s' at", r.TLS.PeerCertificates[0].Subject.CommonName) tlsmsg = fmt.Sprintf("TLS client '%s' at", r.TLS.PeerCertificates[0].Subject.CommonName)
} }
log.Printf("unauthorized access to %s from %s%s", r.URL.Path, tlsmsg, r.RemoteAddr) log.Printf("unauthorized access to %s from %s%s", r.URL.Path, tlsmsg, r.RemoteAddr)
http.Error(w, "Forbidden", http.StatusForbidden) http.Error(w, "Forbidden", http.StatusForbidden)
......
...@@ -11,19 +11,21 @@ import ( ...@@ -11,19 +11,21 @@ import (
"strconv" "strconv"
"sync" "sync"
openzipkin "github.com/openzipkin/zipkin-go" othttp "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
zipkinHTTP "github.com/openzipkin/zipkin-go/reporter/http" "go.opentelemetry.io/otel"
"contrib.go.opencensus.io/exporter/zipkin" "go.opentelemetry.io/otel/exporters/zipkin"
"go.opencensus.io/plugin/ochttp" "go.opentelemetry.io/otel/sdk/resource"
"go.opencensus.io/trace" "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
apitrace "go.opentelemetry.io/otel/trace"
) )
var ( var (
// Enabled reports whether tracing is globally enabled or not. // Enabled reports whether tracing is globally enabled or not.
Enabled bool Enabled bool
// The active tracing configuration, if Enabled is true. // Global Tracer instance.
config tracingConfig Tracer apitrace.Tracer
initOnce sync.Once initOnce sync.Once
) )
...@@ -38,7 +40,7 @@ type tracingConfig struct { ...@@ -38,7 +40,7 @@ type tracingConfig struct {
// Read the global tracing configuration file. Its location is // Read the global tracing configuration file. Its location is
// hardcoded, but it can be overriden using the TRACING_CONFIG // hardcoded, but it can be overriden using the TRACING_CONFIG
// environment variable. // environment variable.
func readTracingConfig() error { func readTracingConfig() (*tracingConfig, error) {
// Read and decode configuration. // Read and decode configuration.
cfgPath := globalTracingConfigPath cfgPath := globalTracingConfigPath
if s := os.Getenv("TRACING_CONFIG"); s != "" { if s := os.Getenv("TRACING_CONFIG"); s != "" {
...@@ -46,20 +48,21 @@ func readTracingConfig() error { ...@@ -46,20 +48,21 @@ func readTracingConfig() error {
} }
data, err := ioutil.ReadFile(cfgPath) data, err := ioutil.ReadFile(cfgPath)
if err != nil { if err != nil {
return err return nil, err
} }
var config tracingConfig
if err := json.Unmarshal(data, &config); err != nil { if err := json.Unmarshal(data, &config); err != nil {
log.Printf("warning: error in tracing configuration: %v, tracing disabled", err) log.Printf("warning: error in tracing configuration: %v, tracing disabled", err)
return err return nil, err
} }
if config.ReportURL == "" { if config.ReportURL == "" {
log.Printf("warning: tracing configuration contains no report_url, tracing disabled") log.Printf("warning: tracing configuration contains no report_url, tracing disabled")
return errors.New("no report_url") return nil, errors.New("no report_url")
} }
return nil return &config, nil
} }
// Compute the service name for Zipkin: this is usually the program // Compute the service name for Zipkin: this is usually the program
...@@ -72,6 +75,17 @@ func getServiceName() string { ...@@ -72,6 +75,17 @@ func getServiceName() string {
return filepath.Base(os.Args[0]) return filepath.Base(os.Args[0])
} }
func defaultResource() *resource.Resource {
r, _ := resource.Merge(
resource.Default(),
resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceNameKey.String(getServiceName()),
),
)
return r
}
// Initialize tracing. Tracing will be enabled if the system-wide // Initialize tracing. Tracing will be enabled if the system-wide
// tracing configuration file is present and valid. Explicitly set // tracing configuration file is present and valid. Explicitly set
// TRACING_ENABLE=0 in the environment to disable tracing. // TRACING_ENABLE=0 in the environment to disable tracing.
...@@ -79,49 +93,47 @@ func getServiceName() string { ...@@ -79,49 +93,47 @@ func getServiceName() string {
// We need to check the configuration as soon as possible, because // We need to check the configuration as soon as possible, because
// it's likely that client transports are created before HTTP servers, // it's likely that client transports are created before HTTP servers,
// and we need to wrap them with opencensus at creation time. // and we need to wrap them with opencensus at creation time.
func init() { func initTracing(serviceName string) {
// Kill switch from environment.
if s := os.Getenv("TRACING_ENABLE"); s == "0" {
return
}
if err := readTracingConfig(); err != nil {
return
}
Enabled = true
}
func initTracing(endpointAddr string) {
if !Enabled {
return
}
initOnce.Do(func() { initOnce.Do(func() {
localEndpoint, err := openzipkin.NewEndpoint(getServiceName(), endpointAddr) // Kill switch from environment.
if s := os.Getenv("TRACING_ENABLE"); s == "0" {
return
}
config, err := readTracingConfig()
if err != nil { if err != nil {
log.Printf("warning: error creating tracing endpoint: %v, tracing disabled", err)
return return
} }
reporter := zipkinHTTP.NewReporter(config.ReportURL) ze, err := zipkin.New(config.ReportURL)
ze := zipkin.NewExporter(reporter, localEndpoint) if err != nil {
trace.RegisterExporter(ze) log.Printf("error creating Zipkin exporter: %v", err)
return
}
var tc trace.Config var sampler trace.Sampler
switch config.Sample { switch config.Sample {
case "", "always": case "", "always":
tc.DefaultSampler = trace.AlwaysSample() sampler = trace.AlwaysSample()
case "never": case "never":
tc.DefaultSampler = trace.NeverSample() sampler = trace.NeverSample()
default: default:
frac, err := strconv.ParseFloat(config.Sample, 64) frac, err := strconv.ParseFloat(config.Sample, 64)
if err != nil { if err != nil {
log.Printf("warning: error in tracing configuration: sample: %v, tracing disabled", err) log.Printf("warning: error in tracing configuration: sample: %v, tracing disabled", err)
return return
} }
tc.DefaultSampler = trace.ProbabilitySampler(frac) sampler = trace.TraceIDRatioBased(frac)
} }
trace.ApplyConfig(tc)
tp := trace.NewTracerProvider(
trace.WithSampler(sampler),
trace.WithResource(defaultResource()),
trace.WithBatcher(ze),
)
otel.SetTracerProvider(tp)
Tracer = tp.Tracer(serviceName)
log.Printf("tracing enabled (report_url %s)", config.ReportURL) log.Printf("tracing enabled (report_url %s)", config.ReportURL)
...@@ -136,9 +148,11 @@ func Init() { ...@@ -136,9 +148,11 @@ func Init() {
// WrapTransport optionally wraps a http.RoundTripper with OpenCensus // WrapTransport optionally wraps a http.RoundTripper with OpenCensus
// tracing functionality, if it is globally enabled. // tracing functionality, if it is globally enabled.
//
// Must call Init() first.
func WrapTransport(t http.RoundTripper) http.RoundTripper { func WrapTransport(t http.RoundTripper) http.RoundTripper {
if Enabled { if Enabled {
t = &ochttp.Transport{Base: t} t = othttp.NewTransport(t)
} }
return t return t
} }
...@@ -146,9 +160,10 @@ func WrapTransport(t http.RoundTripper) http.RoundTripper { ...@@ -146,9 +160,10 @@ func WrapTransport(t http.RoundTripper) http.RoundTripper {
// WrapHandler wraps a http.Handler with OpenCensus tracing // WrapHandler wraps a http.Handler with OpenCensus tracing
// functionality, if globally enabled. Automatically calls Init(). // functionality, if globally enabled. Automatically calls Init().
func WrapHandler(h http.Handler, endpointAddr string) http.Handler { func WrapHandler(h http.Handler, endpointAddr string) http.Handler {
if Enabled { serviceName := getServiceName()
initTracing(endpointAddr) initTracing(serviceName)
h = &ochttp.Handler{Handler: h} if !Enabled {
return h
} }
return h return othttp.NewHandler(h, serviceName)
} }
*.swp
language: go
go:
- 1.x
- tip
env:
- GO111MODULE=on
install:
- go mod download
script:
- go test -race -v
---
layout: code-of-conduct
version: v1.0
---
This code of conduct outlines our expectations for participants within the **NYTimes/gziphandler** community, as well as steps to reporting unacceptable behavior. We are committed to providing a welcoming and inspiring community for all and expect our code of conduct to be honored. Anyone who violates this code of conduct may be banned from the community.
Our open source community strives to:
* **Be friendly and patient.**
* **Be welcoming**: We strive to be a community that welcomes and supports people of all backgrounds and identities. This includes, but is not limited to members of any race, ethnicity, culture, national origin, colour, immigration status, social and economic class, educational level, sex, sexual orientation, gender identity and expression, age, size, family status, political belief, religion, and mental and physical ability.
* **Be considerate**: Your work will be used by other people, and you in turn will depend on the work of others. Any decision you take will affect users and colleagues, and you should take those consequences into account when making decisions. Remember that we're a world-wide community, so you might not be communicating in someone else's primary language.
* **Be respectful**: Not all of us will agree all the time, but disagreement is no excuse for poor behavior and poor manners. We might all experience some frustration now and then, but we cannot allow that frustration to turn into a personal attack. It’s important to remember that a community where people feel uncomfortable or threatened is not a productive one.
* **Be careful in the words that we choose**: we are a community of professionals, and we conduct ourselves professionally. Be kind to others. Do not insult or put down other participants. Harassment and other exclusionary behavior aren't acceptable.
* **Try to understand why we disagree**: Disagreements, both social and technical, happen all the time. It is important that we resolve disagreements and differing views constructively. Remember that we’re different. The strength of our community comes from its diversity, people from a wide range of backgrounds. Different people have different perspectives on issues. Being unable to understand why someone holds a viewpoint doesn’t mean that they’re wrong. Don’t forget that it is human to err and blaming each other doesn’t get us anywhere. Instead, focus on helping to resolve issues and learning from mistakes.
## Definitions
Harassment includes, but is not limited to:
- Offensive comments related to gender, gender identity and expression, sexual orientation, disability, mental illness, neuro(a)typicality, physical appearance, body size, race, age, regional discrimination, political or religious affiliation
- Unwelcome comments regarding a person’s lifestyle choices and practices, including those related to food, health, parenting, drugs, and employment
- Deliberate misgendering. This includes deadnaming or persistently using a pronoun that does not correctly reflect a person's gender identity. You must address people by the name they give you when not addressing them by their username or handle
- Physical contact and simulated physical contact (eg, textual descriptions like “*hug*” or “*backrub*”) without consent or after a request to stop
- Threats of violence, both physical and psychological
- Incitement of violence towards any individual, including encouraging a person to commit suicide or to engage in self-harm
- Deliberate intimidation
- Stalking or following
- Harassing photography or recording, including logging online activity for harassment purposes
- Sustained disruption of discussion
- Unwelcome sexual attention, including gratuitous or off-topic sexual images or behaviour
- Pattern of inappropriate social contact, such as requesting/assuming inappropriate levels of intimacy with others
- Continued one-on-one communication after requests to cease
- Deliberate “outing” of any aspect of a person’s identity without their consent except as necessary to protect others from intentional abuse
- Publication of non-harassing private communication
Our open source community prioritizes marginalized people’s safety over privileged people’s comfort. We will not act on complaints regarding:
- ‘Reverse’ -isms, including ‘reverse racism,’ ‘reverse sexism,’ and ‘cisphobia’
- Reasonable communication of boundaries, such as “leave me alone,” “go away,” or “I’m not discussing this with you”
- Refusal to explain or debate social justice concepts
- Communicating in a ‘tone’ you don’t find congenial
- Criticizing racist, sexist, cissexist, or otherwise oppressive behavior or assumptions
### Diversity Statement
We encourage everyone to participate and are committed to building a community for all. Although we will fail at times, we seek to treat everyone both as fairly and equally as possible. Whenever a participant has made a mistake, we expect them to take responsibility for it. If someone has been harmed or offended, it is our responsibility to listen carefully and respectfully, and do our best to right the wrong.
Although this list cannot be exhaustive, we explicitly honor diversity in age, gender, gender identity or expression, culture, ethnicity, language, national origin, political beliefs, profession, race, religion, sexual orientation, socioeconomic status, and technical ability. We will not tolerate discrimination based on any of the protected
characteristics above, including participants with disabilities.
### Reporting Issues
If you experience or witness unacceptable behavior—or have any other concerns—please report it by contacting us via **code@nytimes.com**. All reports will be handled with discretion. In your report please include:
- Your contact information.
- Names (real, nicknames, or pseudonyms) of any individuals involved. If there are additional witnesses, please
include them as well. Your account of what occurred, and if you believe the incident is ongoing. If there is a publicly available record (e.g. a mailing list archive or a public IRC logger), please include a link.
- Any additional information that may be helpful.
After filing a report, a representative will contact you personally, review the incident, follow up with any additional questions, and make a decision as to how to respond. If the person who is harassing you is part of the response team, they will recuse themselves from handling your incident. If the complaint originates from a member of the response team, it will be handled by a different member of the response team. We will respect confidentiality requests for the purpose of protecting victims of abuse.
### Attribution & Acknowledgements
We all stand on the shoulders of giants across many open source communities. We'd like to thank the communities and projects that established code of conducts and diversity statements as our inspiration:
* [Django](https://www.djangoproject.com/conduct/reporting/)
* [Python](https://www.python.org/community/diversity/)
* [Ubuntu](http://www.ubuntu.com/about/about-ubuntu/conduct)
* [Contributor Covenant](http://contributor-covenant.org/)
* [Geek Feminism](http://geekfeminism.org/about/code-of-conduct/)
* [Citizen Code of Conduct](http://citizencodeofconduct.org/)
This Code of Conduct was based on https://github.com/todogroup/opencodeofconduct
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment