├── .github └── FUNDING.yml ├── .travis.yml ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── booking ├── docs │ ├── api.raml │ └── index.html ├── instrumenting.go ├── logging.go ├── service.go └── service_test.go ├── cargo.go ├── cargo_test.go ├── cmd └── shippingsvc │ ├── main.go │ └── main_test.go ├── delivery.go ├── docker-compose.yml ├── go.mod ├── go.sum ├── handling.go ├── handling ├── docs │ ├── api.raml │ └── index.html ├── instrumenting.go ├── logging.go ├── service.go └── service_test.go ├── inmem └── inmem.go ├── inspection ├── inspection.go └── inspection_test.go ├── itinerary.go ├── itinerary_test.go ├── location.go ├── mock └── mock.go ├── mongo └── mongo.go ├── routing.go ├── routing └── proxying.go ├── sample_locations.go ├── sample_voyages.go ├── server ├── booking.go ├── handling.go ├── server.go ├── tracking.go └── tracking_test.go ├── tracking ├── docs │ ├── api.raml │ └── index.html ├── instrumenting.go ├── logging.go ├── service.go └── service_test.go ├── vendor ├── github.com │ ├── afex │ │ └── hystrix-go │ │ │ ├── LICENSE │ │ │ └── hystrix │ │ │ ├── circuit.go │ │ │ ├── doc.go │ │ │ ├── eventstream.go │ │ │ ├── hystrix.go │ │ │ ├── logger.go │ │ │ ├── metric_collector │ │ │ ├── default_metric_collector.go │ │ │ └── metric_collector.go │ │ │ ├── metrics.go │ │ │ ├── pool.go │ │ │ ├── pool_metrics.go │ │ │ ├── rolling │ │ │ ├── rolling.go │ │ │ └── rolling_timing.go │ │ │ └── settings.go │ ├── beorn7 │ │ └── perks │ │ │ ├── LICENSE │ │ │ └── quantile │ │ │ ├── exampledata.txt │ │ │ └── stream.go │ ├── go-chi │ │ └── chi │ │ │ ├── .gitignore │ │ │ ├── .travis.yml │ │ │ ├── CHANGELOG.md │ │ │ ├── CONTRIBUTING.md │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── chain.go │ │ │ ├── chi.go │ │ │ ├── context.go │ │ │ ├── mux.go │ │ │ └── tree.go │ ├── go-kit │ │ └── kit │ │ │ ├── LICENSE │ │ │ ├── circuitbreaker │ │ │ ├── doc.go │ │ │ ├── gobreaker.go │ │ │ ├── handy_breaker.go │ │ │ └── hystrix.go │ │ │ ├── endpoint │ │ │ ├── doc.go │ │ │ └── endpoint.go │ │ │ ├── log │ │ │ ├── README.md │ │ │ ├── doc.go │ │ │ ├── json_logger.go │ │ │ ├── log.go │ │ │ ├── logfmt_logger.go │ │ │ ├── nop_logger.go │ │ │ ├── stdlib.go │ │ │ ├── sync.go │ │ │ └── value.go │ │ │ ├── metrics │ │ │ ├── README.md │ │ │ ├── debug.test │ │ │ ├── doc.go │ │ │ ├── internal │ │ │ │ └── lv │ │ │ │ │ ├── labelvalues.go │ │ │ │ │ └── space.go │ │ │ ├── metrics.go │ │ │ ├── prometheus │ │ │ │ └── prometheus.go │ │ │ └── timer.go │ │ │ └── transport │ │ │ └── http │ │ │ ├── client.go │ │ │ ├── doc.go │ │ │ ├── encode_decode.go │ │ │ ├── request_response_funcs.go │ │ │ └── server.go │ ├── go-logfmt │ │ └── logfmt │ │ │ ├── .gitignore │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── decode.go │ │ │ ├── doc.go │ │ │ ├── encode.go │ │ │ ├── fuzz.go │ │ │ └── jsonstring.go │ ├── go-stack │ │ └── stack │ │ │ ├── .travis.yml │ │ │ ├── LICENSE.md │ │ │ ├── README.md │ │ │ ├── go.mod │ │ │ └── stack.go │ ├── golang │ │ └── protobuf │ │ │ ├── AUTHORS │ │ │ ├── CONTRIBUTORS │ │ │ ├── LICENSE │ │ │ └── proto │ │ │ ├── clone.go │ │ │ ├── decode.go │ │ │ ├── discard.go │ │ │ ├── encode.go │ │ │ ├── equal.go │ │ │ ├── extensions.go │ │ │ ├── lib.go │ │ │ ├── message_set.go │ │ │ ├── pointer_reflect.go │ │ │ ├── pointer_unsafe.go │ │ │ ├── properties.go │ │ │ ├── table_marshal.go │ │ │ ├── table_merge.go │ │ │ ├── table_unmarshal.go │ │ │ ├── text.go │ │ │ └── text_parser.go │ ├── kr │ │ ├── logfmt │ │ │ ├── .gitignore │ │ │ ├── Readme │ │ │ ├── decode.go │ │ │ ├── scanner.go │ │ │ └── unquote.go │ │ ├── pretty │ │ │ ├── .gitignore │ │ │ ├── License │ │ │ ├── Readme │ │ │ ├── diff.go │ │ │ ├── formatter.go │ │ │ ├── go.mod │ │ │ ├── pretty.go │ │ │ └── zero.go │ │ └── text │ │ │ ├── License │ │ │ ├── Readme │ │ │ ├── doc.go │ │ │ ├── go.mod │ │ │ ├── indent.go │ │ │ └── wrap.go │ ├── matttproud │ │ └── golang_protobuf_extensions │ │ │ ├── LICENSE │ │ │ ├── NOTICE │ │ │ └── pbutil │ │ │ ├── .gitignore │ │ │ ├── Makefile │ │ │ ├── decode.go │ │ │ ├── doc.go │ │ │ └── encode.go │ ├── pborman │ │ └── uuid │ │ │ ├── .travis.yml │ │ │ ├── CONTRIBUTING.md │ │ │ ├── CONTRIBUTORS │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── dce.go │ │ │ ├── doc.go │ │ │ ├── hash.go │ │ │ ├── marshal.go │ │ │ ├── node.go │ │ │ ├── node_js.go │ │ │ ├── node_net.go │ │ │ ├── sql.go │ │ │ ├── time.go │ │ │ ├── util.go │ │ │ ├── uuid.go │ │ │ ├── version1.go │ │ │ └── version4.go │ ├── prometheus │ │ ├── client_golang │ │ │ ├── AUTHORS.md │ │ │ ├── LICENSE │ │ │ ├── NOTICE │ │ │ └── prometheus │ │ │ │ ├── .gitignore │ │ │ │ ├── README.md │ │ │ │ ├── collector.go │ │ │ │ ├── counter.go │ │ │ │ ├── desc.go │ │ │ │ ├── doc.go │ │ │ │ ├── expvar_collector.go │ │ │ │ ├── fnv.go │ │ │ │ ├── gauge.go │ │ │ │ ├── go_collector.go │ │ │ │ ├── histogram.go │ │ │ │ ├── http.go │ │ │ │ ├── metric.go │ │ │ │ ├── process_collector.go │ │ │ │ ├── promhttp │ │ │ │ └── http.go │ │ │ │ ├── registry.go │ │ │ │ ├── summary.go │ │ │ │ ├── untyped.go │ │ │ │ ├── value.go │ │ │ │ └── vec.go │ │ ├── client_model │ │ │ ├── LICENSE │ │ │ ├── NOTICE │ │ │ └── go │ │ │ │ └── metrics.pb.go │ │ ├── common │ │ │ ├── LICENSE │ │ │ ├── NOTICE │ │ │ ├── expfmt │ │ │ │ ├── decode.go │ │ │ │ ├── encode.go │ │ │ │ ├── expfmt.go │ │ │ │ ├── fuzz.go │ │ │ │ ├── text_create.go │ │ │ │ └── text_parse.go │ │ │ ├── internal │ │ │ │ └── bitbucket.org │ │ │ │ │ └── ww │ │ │ │ │ └── goautoneg │ │ │ │ │ ├── README.txt │ │ │ │ │ └── autoneg.go │ │ │ └── model │ │ │ │ ├── alert.go │ │ │ │ ├── fingerprinting.go │ │ │ │ ├── fnv.go │ │ │ │ ├── labels.go │ │ │ │ ├── labelset.go │ │ │ │ ├── metric.go │ │ │ │ ├── model.go │ │ │ │ ├── signature.go │ │ │ │ ├── silence.go │ │ │ │ ├── time.go │ │ │ │ └── value.go │ │ └── procfs │ │ │ ├── .gitignore │ │ │ ├── .travis.yml │ │ │ ├── CONTRIBUTING.md │ │ │ ├── LICENSE │ │ │ ├── MAINTAINERS.md │ │ │ ├── Makefile │ │ │ ├── NOTICE │ │ │ ├── README.md │ │ │ ├── buddyinfo.go │ │ │ ├── doc.go │ │ │ ├── fixtures.ttar │ │ │ ├── fs.go │ │ │ ├── internal │ │ │ └── util │ │ │ │ └── parse.go │ │ │ ├── ipvs.go │ │ │ ├── mdstat.go │ │ │ ├── mountstats.go │ │ │ ├── net_dev.go │ │ │ ├── nfs │ │ │ ├── nfs.go │ │ │ ├── parse.go │ │ │ ├── parse_nfs.go │ │ │ └── parse_nfsd.go │ │ │ ├── proc.go │ │ │ ├── proc_io.go │ │ │ ├── proc_limits.go │ │ │ ├── proc_ns.go │ │ │ ├── proc_stat.go │ │ │ ├── stat.go │ │ │ ├── ttar │ │ │ ├── xfrm.go │ │ │ └── xfs │ │ │ ├── parse.go │ │ │ └── xfs.go │ ├── sony │ │ └── gobreaker │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ └── gobreaker.go │ └── streadway │ │ └── handy │ │ └── breaker │ │ ├── breaker.go │ │ ├── doc.go │ │ ├── handler.go │ │ ├── metrics.go │ │ └── transport.go ├── gopkg.in │ ├── check.v1 │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── README.md │ │ ├── TODO │ │ ├── benchmark.go │ │ ├── check.go │ │ ├── checkers.go │ │ ├── helpers.go │ │ ├── printer.go │ │ ├── reporter.go │ │ └── run.go │ └── mgo.v2 │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── Makefile │ │ ├── README.md │ │ ├── auth.go │ │ ├── bson │ │ ├── LICENSE │ │ ├── bson.go │ │ ├── decimal.go │ │ ├── decode.go │ │ ├── encode.go │ │ └── json.go │ │ ├── bulk.go │ │ ├── cluster.go │ │ ├── doc.go │ │ ├── gridfs.go │ │ ├── internal │ │ ├── json │ │ │ ├── LICENSE │ │ │ ├── decode.go │ │ │ ├── encode.go │ │ │ ├── extension.go │ │ │ ├── fold.go │ │ │ ├── indent.go │ │ │ ├── scanner.go │ │ │ ├── stream.go │ │ │ └── tags.go │ │ ├── sasl │ │ │ ├── sasl.c │ │ │ ├── sasl.go │ │ │ ├── sasl_windows.c │ │ │ ├── sasl_windows.go │ │ │ ├── sasl_windows.h │ │ │ ├── sspi_windows.c │ │ │ └── sspi_windows.h │ │ └── scram │ │ │ └── scram.go │ │ ├── log.go │ │ ├── queue.go │ │ ├── raceoff.go │ │ ├── raceon.go │ │ ├── saslimpl.go │ │ ├── saslstub.go │ │ ├── server.go │ │ ├── session.go │ │ ├── socket.go │ │ └── stats.go └── modules.txt └── voyage.go /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: https://buymeacoffee.com/marcusolsson 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | group: edge 2 | sudo: required 3 | 4 | language: go 5 | go: 6 | - 1.10.x 7 | - 1.11.x 8 | 9 | services: 10 | - docker 11 | 12 | env: 13 | - GO111MODULE=on 14 | 15 | install: 16 | - go get -u github.com/golang/lint/golint 17 | 18 | matrix: 19 | include: 20 | - go: "1.10.x" 21 | script: go test -v ./... 22 | - go: "1.11.x" 23 | script: go test -v -mod=vendor ./... 24 | 25 | after_success: 26 | - docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD 27 | - make docker-build 28 | - make docker-push 29 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing 2 | ============ 3 | 4 | So you want to contribute? Great! This project really is intended for the community. 5 | 6 | ## Questions 7 | 8 | If you have questions regarding the application, please consider asking it by [creating a new issue](https://github.com/marcusolsson/goddd/issues) so that others can join the discussion. 9 | 10 | ## Suggesting enhancements 11 | 12 | Since this project really is a proof-of-concept I would love to hear your ideas on how to improve it, but even if it is just a gut feeling, let me know! 13 | 14 | Feel free to start a discussion by [creating a new issue](https://github.com/marcusolsson/goddd/issues). 15 | 16 | ## Reporting bugs 17 | 18 | If you find any bugs, it would be very much appreciated if you would let me know by [creating a new issue](https://github.com/marcusolsson/goddd/issues). 19 | 20 | ## Pull request 21 | 22 | Pull requests are definitely welcome! 23 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.10.3-alpine as build-env 2 | WORKDIR /go/src/github.com/marcusolsson/goddd/ 3 | COPY . . 4 | RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o goapp ./cmd/shippingsvc 5 | 6 | FROM alpine:3.7 7 | WORKDIR /app 8 | COPY --from=build-env /go/src/github.com/marcusolsson/goddd/booking/docs ./booking/docs 9 | COPY --from=build-env /go/src/github.com/marcusolsson/goddd/tracking/docs ./tracking/docs 10 | COPY --from=build-env /go/src/github.com/marcusolsson/goddd/handling/docs ./handling/docs 11 | COPY --from=build-env /go/src/github.com/marcusolsson/goddd/goapp . 12 | EXPOSE 8080 13 | ENTRYPOINT ["./goapp"] 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Marcus Olsson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | BINARY=goddd 2 | 3 | DOCKER_IMAGE_NAME=marcusolsson/goddd 4 | 5 | .DEFAULT_GOAL := help 6 | 7 | check: test lint vet ## Runs all tests 8 | 9 | test: ## Run the unit tests 10 | go test -race -v $(shell go list ./... | grep -v /vendor/) 11 | 12 | lint: ## Lint all files 13 | go list ./... | grep -v /vendor/ | xargs -L1 golint -set_exit_status 14 | 15 | vet: ## Run the vet tool 16 | go vet $(shell go list ./... | grep -v /vendor/) 17 | 18 | clean: ## Clean up build artifacts 19 | go clean 20 | 21 | docker-build: ## Build Docker image 22 | docker build -t ${DOCKER_IMAGE_NAME} . 23 | 24 | docker-push: ## Push Docker image to registry 25 | docker push ${DOCKER_IMAGE_NAME} 26 | 27 | help: ## Display this help message 28 | @cat $(MAKEFILE_LIST) | grep -e "^[a-zA-Z_\-]*: *.*## *" | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' 29 | 30 | .SILENT: build test lint vet clean docker-build docker-push help 31 | -------------------------------------------------------------------------------- /booking/instrumenting.go: -------------------------------------------------------------------------------- 1 | package booking 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/go-kit/kit/metrics" 7 | 8 | shipping "github.com/marcusolsson/goddd" 9 | ) 10 | 11 | type instrumentingService struct { 12 | requestCount metrics.Counter 13 | requestLatency metrics.Histogram 14 | next Service 15 | } 16 | 17 | // NewInstrumentingService returns an instance of an instrumenting Service. 18 | func NewInstrumentingService(counter metrics.Counter, latency metrics.Histogram, s Service) Service { 19 | return &instrumentingService{ 20 | requestCount: counter, 21 | requestLatency: latency, 22 | next: s, 23 | } 24 | } 25 | 26 | func (s *instrumentingService) BookNewCargo(origin, destination shipping.UNLocode, deadline time.Time) (shipping.TrackingID, error) { 27 | defer func(begin time.Time) { 28 | s.requestCount.With("method", "book").Add(1) 29 | s.requestLatency.With("method", "book").Observe(time.Since(begin).Seconds()) 30 | }(time.Now()) 31 | 32 | return s.next.BookNewCargo(origin, destination, deadline) 33 | } 34 | 35 | func (s *instrumentingService) LoadCargo(id shipping.TrackingID) (c Cargo, err error) { 36 | defer func(begin time.Time) { 37 | s.requestCount.With("method", "load").Add(1) 38 | s.requestLatency.With("method", "load").Observe(time.Since(begin).Seconds()) 39 | }(time.Now()) 40 | 41 | return s.next.LoadCargo(id) 42 | } 43 | 44 | func (s *instrumentingService) RequestPossibleRoutesForCargo(id shipping.TrackingID) []shipping.Itinerary { 45 | defer func(begin time.Time) { 46 | s.requestCount.With("method", "request_routes").Add(1) 47 | s.requestLatency.With("method", "request_routes").Observe(time.Since(begin).Seconds()) 48 | }(time.Now()) 49 | 50 | return s.next.RequestPossibleRoutesForCargo(id) 51 | } 52 | 53 | func (s *instrumentingService) AssignCargoToRoute(id shipping.TrackingID, itinerary shipping.Itinerary) (err error) { 54 | defer func(begin time.Time) { 55 | s.requestCount.With("method", "assign_to_route").Add(1) 56 | s.requestLatency.With("method", "assign_to_route").Observe(time.Since(begin).Seconds()) 57 | }(time.Now()) 58 | 59 | return s.next.AssignCargoToRoute(id, itinerary) 60 | } 61 | 62 | func (s *instrumentingService) ChangeDestination(id shipping.TrackingID, l shipping.UNLocode) (err error) { 63 | defer func(begin time.Time) { 64 | s.requestCount.With("method", "change_destination").Add(1) 65 | s.requestLatency.With("method", "change_destination").Observe(time.Since(begin).Seconds()) 66 | }(time.Now()) 67 | 68 | return s.next.ChangeDestination(id, l) 69 | } 70 | 71 | func (s *instrumentingService) Cargos() []Cargo { 72 | defer func(begin time.Time) { 73 | s.requestCount.With("method", "list_cargos").Add(1) 74 | s.requestLatency.With("method", "list_cargos").Observe(time.Since(begin).Seconds()) 75 | }(time.Now()) 76 | 77 | return s.next.Cargos() 78 | } 79 | 80 | func (s *instrumentingService) Locations() []Location { 81 | defer func(begin time.Time) { 82 | s.requestCount.With("method", "list_locations").Add(1) 83 | s.requestLatency.With("method", "list_locations").Observe(time.Since(begin).Seconds()) 84 | }(time.Now()) 85 | 86 | return s.next.Locations() 87 | } 88 | -------------------------------------------------------------------------------- /booking/logging.go: -------------------------------------------------------------------------------- 1 | package booking 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/go-kit/kit/log" 7 | 8 | shipping "github.com/marcusolsson/goddd" 9 | ) 10 | 11 | type loggingService struct { 12 | logger log.Logger 13 | next Service 14 | } 15 | 16 | // NewLoggingService returns a new instance of a logging Service. 17 | func NewLoggingService(logger log.Logger, s Service) Service { 18 | return &loggingService{logger, s} 19 | } 20 | 21 | func (s *loggingService) BookNewCargo(origin shipping.UNLocode, destination shipping.UNLocode, deadline time.Time) (id shipping.TrackingID, err error) { 22 | defer func(begin time.Time) { 23 | s.logger.Log( 24 | "method", "book", 25 | "origin", origin, 26 | "destination", destination, 27 | "arrival_deadline", deadline, 28 | "took", time.Since(begin), 29 | "err", err, 30 | ) 31 | }(time.Now()) 32 | return s.next.BookNewCargo(origin, destination, deadline) 33 | } 34 | 35 | func (s *loggingService) LoadCargo(id shipping.TrackingID) (c Cargo, err error) { 36 | defer func(begin time.Time) { 37 | s.logger.Log( 38 | "method", "load", 39 | "tracking_id", id, 40 | "took", time.Since(begin), 41 | "err", err, 42 | ) 43 | }(time.Now()) 44 | return s.next.LoadCargo(id) 45 | } 46 | 47 | func (s *loggingService) RequestPossibleRoutesForCargo(id shipping.TrackingID) []shipping.Itinerary { 48 | defer func(begin time.Time) { 49 | s.logger.Log( 50 | "method", "request_routes", 51 | "tracking_id", id, 52 | "took", time.Since(begin), 53 | ) 54 | }(time.Now()) 55 | return s.next.RequestPossibleRoutesForCargo(id) 56 | } 57 | 58 | func (s *loggingService) AssignCargoToRoute(id shipping.TrackingID, itinerary shipping.Itinerary) (err error) { 59 | defer func(begin time.Time) { 60 | s.logger.Log( 61 | "method", "assign_to_route", 62 | "tracking_id", id, 63 | "took", time.Since(begin), 64 | "err", err, 65 | ) 66 | }(time.Now()) 67 | return s.next.AssignCargoToRoute(id, itinerary) 68 | } 69 | 70 | func (s *loggingService) ChangeDestination(id shipping.TrackingID, l shipping.UNLocode) (err error) { 71 | defer func(begin time.Time) { 72 | s.logger.Log( 73 | "method", "change_destination", 74 | "tracking_id", id, 75 | "destination", l, 76 | "took", time.Since(begin), 77 | "err", err, 78 | ) 79 | }(time.Now()) 80 | return s.next.ChangeDestination(id, l) 81 | } 82 | 83 | func (s *loggingService) Cargos() []Cargo { 84 | defer func(begin time.Time) { 85 | s.logger.Log( 86 | "method", "list_cargos", 87 | "took", time.Since(begin), 88 | ) 89 | }(time.Now()) 90 | return s.next.Cargos() 91 | } 92 | 93 | func (s *loggingService) Locations() []Location { 94 | defer func(begin time.Time) { 95 | s.logger.Log( 96 | "method", "list_locations", 97 | "took", time.Since(begin), 98 | ) 99 | }(time.Now()) 100 | return s.next.Locations() 101 | } 102 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | goddd: 2 | image: marcusolsson/goddd 3 | ports: 4 | - 8080:8080 5 | environment: 6 | ROUTINGSERVICE_URL: http://pathfinder:8080 7 | MONGODB_URL: mongodb 8 | links: 9 | - pathfinder 10 | - mongodb 11 | 12 | pathfinder: 13 | image: marcusolsson/pathfinder 14 | 15 | mongodb: 16 | image: mongo 17 | ports: 18 | - 27017:27017 19 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/marcusolsson/goddd 2 | 3 | require ( 4 | github.com/VividCortex/gohistogram v1.0.0 // indirect 5 | github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 // indirect 6 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 // indirect 7 | github.com/davecgh/go-spew v1.1.1 // indirect 8 | github.com/go-chi/chi v3.3.3+incompatible 9 | github.com/go-kit/kit v0.7.0 10 | github.com/go-logfmt/logfmt v0.3.0 // indirect 11 | github.com/go-stack/stack v1.8.0 // indirect 12 | github.com/golang/protobuf v1.2.0 // indirect 13 | github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c // indirect 14 | github.com/jtolds/gls v4.2.1+incompatible // indirect 15 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 // indirect 16 | github.com/kr/pretty v0.1.0 // indirect 17 | github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect 18 | github.com/pborman/uuid v0.0.0-20180827223501-4c1ecd6722e8 19 | github.com/pmezard/go-difflib v1.0.0 // indirect 20 | github.com/prometheus/client_golang v0.8.0 21 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 // indirect 22 | github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e // indirect 23 | github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273 // indirect 24 | github.com/smartystreets/assertions v0.0.0-20180820201707-7c9eb446e3cf // indirect 25 | github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a // indirect 26 | github.com/sony/gobreaker v0.0.0-20180905101324-b2a34562d02c // indirect 27 | github.com/streadway/handy v0.0.0-20160402200321-f450267a206e // indirect 28 | github.com/stretchr/testify v1.2.2 // indirect 29 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d // indirect 30 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f // indirect 31 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 32 | gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce 33 | gopkg.in/yaml.v2 v2.2.1 // indirect 34 | ) 35 | -------------------------------------------------------------------------------- /handling/docs/api.raml: -------------------------------------------------------------------------------- 1 | #%RAML 0.8 2 | title: Handling 3 | baseUri: http://dddsample.marcusoncode.se/handling/{version} 4 | version: v1 5 | 6 | /incidents: 7 | post: 8 | description: Register a handling incident. 9 | body: 10 | application/json: 11 | example: | 12 | { 13 | "completion_time": "0001-01-01T00:00:00Z", 14 | "tracking_id": "ABC123", 15 | "voyage": "V100", 16 | "location" "CNHKG", 17 | "event_type": "Unload" 18 | } 19 | -------------------------------------------------------------------------------- /handling/instrumenting.go: -------------------------------------------------------------------------------- 1 | package handling 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/go-kit/kit/metrics" 7 | 8 | shipping "github.com/marcusolsson/goddd" 9 | ) 10 | 11 | type instrumentingService struct { 12 | requestCount metrics.Counter 13 | requestLatency metrics.Histogram 14 | next Service 15 | } 16 | 17 | // NewInstrumentingService returns an instance of an instrumenting Service. 18 | func NewInstrumentingService(counter metrics.Counter, latency metrics.Histogram, s Service) Service { 19 | return &instrumentingService{ 20 | requestCount: counter, 21 | requestLatency: latency, 22 | next: s, 23 | } 24 | } 25 | 26 | func (s *instrumentingService) RegisterHandlingEvent(completed time.Time, id shipping.TrackingID, voyageNumber shipping.VoyageNumber, 27 | loc shipping.UNLocode, eventType shipping.HandlingEventType) error { 28 | 29 | defer func(begin time.Time) { 30 | s.requestCount.With("method", "register_incident").Add(1) 31 | s.requestLatency.With("method", "register_incident").Observe(time.Since(begin).Seconds()) 32 | }(time.Now()) 33 | 34 | return s.next.RegisterHandlingEvent(completed, id, voyageNumber, loc, eventType) 35 | } 36 | -------------------------------------------------------------------------------- /handling/logging.go: -------------------------------------------------------------------------------- 1 | package handling 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/go-kit/kit/log" 7 | 8 | shipping "github.com/marcusolsson/goddd" 9 | ) 10 | 11 | type loggingService struct { 12 | logger log.Logger 13 | next Service 14 | } 15 | 16 | // NewLoggingService returns a new instance of a logging Service. 17 | func NewLoggingService(logger log.Logger, s Service) Service { 18 | return &loggingService{logger, s} 19 | } 20 | 21 | func (s *loggingService) RegisterHandlingEvent(completed time.Time, id shipping.TrackingID, voyageNumber shipping.VoyageNumber, 22 | unLocode shipping.UNLocode, eventType shipping.HandlingEventType) (err error) { 23 | defer func(begin time.Time) { 24 | s.logger.Log( 25 | "method", "register_incident", 26 | "tracking_id", id, 27 | "location", unLocode, 28 | "voyage", voyageNumber, 29 | "event_type", eventType, 30 | "completion_time", completed, 31 | "took", time.Since(begin), 32 | "err", err, 33 | ) 34 | }(time.Now()) 35 | return s.next.RegisterHandlingEvent(completed, id, voyageNumber, unLocode, eventType) 36 | } 37 | -------------------------------------------------------------------------------- /handling/service.go: -------------------------------------------------------------------------------- 1 | // Package handling provides the use-case for registering incidents. Used by 2 | // views facing the people handling the cargo along its route. 3 | package handling 4 | 5 | import ( 6 | "errors" 7 | "time" 8 | 9 | shipping "github.com/marcusolsson/goddd" 10 | "github.com/marcusolsson/goddd/inspection" 11 | ) 12 | 13 | // ErrInvalidArgument is returned when one or more arguments are invalid. 14 | var ErrInvalidArgument = errors.New("invalid argument") 15 | 16 | // EventHandler provides a means of subscribing to registered handling events. 17 | type EventHandler interface { 18 | CargoWasHandled(shipping.HandlingEvent) 19 | } 20 | 21 | // Service provides handling operations. 22 | type Service interface { 23 | // RegisterHandlingEvent registers a handling event in the system, and 24 | // notifies interested parties that a cargo has been handled. 25 | RegisterHandlingEvent(completed time.Time, id shipping.TrackingID, voyageNumber shipping.VoyageNumber, 26 | unLocode shipping.UNLocode, eventType shipping.HandlingEventType) error 27 | } 28 | 29 | type service struct { 30 | handlingEventRepository shipping.HandlingEventRepository 31 | handlingEventFactory shipping.HandlingEventFactory 32 | handlingEventHandler EventHandler 33 | } 34 | 35 | func (s *service) RegisterHandlingEvent(completed time.Time, id shipping.TrackingID, voyageNumber shipping.VoyageNumber, 36 | loc shipping.UNLocode, eventType shipping.HandlingEventType) error { 37 | if completed.IsZero() || id == "" || loc == "" || eventType == shipping.NotHandled { 38 | return ErrInvalidArgument 39 | } 40 | 41 | e, err := s.handlingEventFactory.CreateHandlingEvent(time.Now(), completed, id, voyageNumber, loc, eventType) 42 | if err != nil { 43 | return err 44 | } 45 | 46 | s.handlingEventRepository.Store(e) 47 | s.handlingEventHandler.CargoWasHandled(e) 48 | 49 | return nil 50 | } 51 | 52 | // NewService creates a handling event service with necessary dependencies. 53 | func NewService(r shipping.HandlingEventRepository, f shipping.HandlingEventFactory, h EventHandler) Service { 54 | return &service{ 55 | handlingEventRepository: r, 56 | handlingEventFactory: f, 57 | handlingEventHandler: h, 58 | } 59 | } 60 | 61 | type handlingEventHandler struct { 62 | InspectionService inspection.Service 63 | } 64 | 65 | func (h *handlingEventHandler) CargoWasHandled(event shipping.HandlingEvent) { 66 | h.InspectionService.InspectCargo(event.TrackingID) 67 | } 68 | 69 | // NewEventHandler returns a new instance of a EventHandler. 70 | func NewEventHandler(s inspection.Service) EventHandler { 71 | return &handlingEventHandler{ 72 | InspectionService: s, 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /handling/service_test.go: -------------------------------------------------------------------------------- 1 | package handling 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | shipping "github.com/marcusolsson/goddd" 8 | "github.com/marcusolsson/goddd/mock" 9 | ) 10 | 11 | type stubEventHandler struct { 12 | events []interface{} 13 | } 14 | 15 | func (h *stubEventHandler) CargoWasHandled(e shipping.HandlingEvent) { 16 | h.events = append(h.events, e) 17 | } 18 | 19 | func TestRegisterHandlingEvent(t *testing.T) { 20 | var cargos mock.CargoRepository 21 | cargos.StoreFn = func(c *shipping.Cargo) error { 22 | return nil 23 | } 24 | cargos.FindFn = func(id shipping.TrackingID) (*shipping.Cargo, error) { 25 | if id == "no_such_id" { 26 | return nil, shipping.ErrUnknownCargo 27 | } 28 | return new(shipping.Cargo), nil 29 | } 30 | 31 | var voyages mock.VoyageRepository 32 | voyages.FindFn = func(n shipping.VoyageNumber) (*shipping.Voyage, error) { 33 | return new(shipping.Voyage), nil 34 | } 35 | 36 | var locations mock.LocationRepository 37 | locations.FindFn = func(l shipping.UNLocode) (*shipping.Location, error) { 38 | return nil, nil 39 | } 40 | 41 | var events mock.HandlingEventRepository 42 | events.StoreFn = func(e shipping.HandlingEvent) {} 43 | 44 | eh := &stubEventHandler{events: make([]interface{}, 0)} 45 | ef := shipping.HandlingEventFactory{ 46 | CargoRepository: &cargos, 47 | VoyageRepository: &voyages, 48 | LocationRepository: &locations, 49 | } 50 | 51 | s := NewService(&events, ef, eh) 52 | 53 | var ( 54 | completed = time.Date(2015, time.November, 10, 23, 0, 0, 0, time.UTC) 55 | id = shipping.TrackingID("ABC123") 56 | voyage = shipping.VoyageNumber("V100") 57 | ) 58 | 59 | var err error 60 | 61 | err = cargos.Store(shipping.NewCargo(id, shipping.RouteSpecification{})) 62 | if err != nil { 63 | t.Fatal(err) 64 | } 65 | 66 | err = s.RegisterHandlingEvent(completed, id, voyage, shipping.SESTO, shipping.Load) 67 | if err != nil { 68 | t.Fatal(err) 69 | } 70 | 71 | err = s.RegisterHandlingEvent(completed, "no_such_id", voyage, shipping.SESTO, shipping.Load) 72 | if err != shipping.ErrUnknownCargo { 73 | t.Errorf("err = %s; want = %s", err, shipping.ErrUnknownCargo) 74 | } 75 | 76 | if len(eh.events) != 1 { 77 | t.Errorf("len(eh.events) = %d; want = %d", len(eh.events), 1) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /inspection/inspection.go: -------------------------------------------------------------------------------- 1 | // Package inspection provides means to inspect cargos. 2 | package inspection 3 | 4 | import ( 5 | shipping "github.com/marcusolsson/goddd" 6 | ) 7 | 8 | // EventHandler provides means of subscribing to inspection events. 9 | type EventHandler interface { 10 | CargoWasMisdirected(*shipping.Cargo) 11 | CargoHasArrived(*shipping.Cargo) 12 | } 13 | 14 | // Service provides cargo inspection operations. 15 | type Service interface { 16 | // InspectCargo inspects cargo and send relevant notifications to 17 | // interested parties, for example if a cargo has been misdirected, or 18 | // unloaded at the final destination. 19 | InspectCargo(id shipping.TrackingID) 20 | } 21 | 22 | type service struct { 23 | cargos shipping.CargoRepository 24 | events shipping.HandlingEventRepository 25 | handler EventHandler 26 | } 27 | 28 | // TODO: Should be transactional 29 | func (s *service) InspectCargo(id shipping.TrackingID) { 30 | c, err := s.cargos.Find(id) 31 | if err != nil { 32 | return 33 | } 34 | 35 | h := s.events.QueryHandlingHistory(id) 36 | 37 | c.DeriveDeliveryProgress(h) 38 | 39 | if c.Delivery.IsMisdirected { 40 | s.handler.CargoWasMisdirected(c) 41 | } 42 | 43 | if c.Delivery.IsUnloadedAtDestination { 44 | s.handler.CargoHasArrived(c) 45 | } 46 | 47 | s.cargos.Store(c) 48 | } 49 | 50 | // NewService creates a inspection service with necessary dependencies. 51 | func NewService(cargos shipping.CargoRepository, events shipping.HandlingEventRepository, handler EventHandler) Service { 52 | return &service{cargos, events, handler} 53 | } 54 | -------------------------------------------------------------------------------- /itinerary.go: -------------------------------------------------------------------------------- 1 | package shipping 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // Leg describes the transportation between two locations on a voyage 8 | type Leg struct { 9 | VoyageNumber VoyageNumber `json:"voyage_number"` 10 | LoadLocation UNLocode `json:"from"` 11 | UnloadLocation UNLocode `json:"to"` 12 | LoadTime time.Time `json:"load_time"` 13 | UnloadTime time.Time `json:"unload_time"` 14 | } 15 | 16 | // NewLeg creates a new itinerary leg. 17 | func NewLeg(voyageNumber VoyageNumber, loadLocation, unloadLocation UNLocode, loadTime, unloadTime time.Time) Leg { 18 | return Leg{ 19 | VoyageNumber: voyageNumber, 20 | LoadLocation: loadLocation, 21 | UnloadLocation: unloadLocation, 22 | LoadTime: loadTime, 23 | UnloadTime: unloadTime, 24 | } 25 | } 26 | 27 | // Itinerary specifies steps required to transport a cargo from its origin to 28 | // destination. 29 | type Itinerary struct { 30 | Legs []Leg `json:"legs"` 31 | } 32 | 33 | // InitialDepartureLocation returns the start of the itinerary. 34 | func (i Itinerary) InitialDepartureLocation() UNLocode { 35 | if i.IsEmpty() { 36 | return UNLocode("") 37 | } 38 | return i.Legs[0].LoadLocation 39 | } 40 | 41 | // FinalArrivalLocation returns the end of the itinerary. 42 | func (i Itinerary) FinalArrivalLocation() UNLocode { 43 | if i.IsEmpty() { 44 | return UNLocode("") 45 | } 46 | return i.Legs[len(i.Legs)-1].UnloadLocation 47 | } 48 | 49 | // FinalArrivalTime returns the expected arrival time at final destination. 50 | func (i Itinerary) FinalArrivalTime() time.Time { 51 | return i.Legs[len(i.Legs)-1].UnloadTime 52 | } 53 | 54 | // IsEmpty checks if the itinerary contains at least one leg. 55 | func (i Itinerary) IsEmpty() bool { 56 | return i.Legs == nil || len(i.Legs) == 0 57 | } 58 | 59 | // IsExpected checks if the given handling event is expected when executing 60 | // this itinerary. 61 | func (i Itinerary) IsExpected(event HandlingEvent) bool { 62 | if i.IsEmpty() { 63 | return true 64 | } 65 | 66 | switch event.Activity.Type { 67 | case Receive: 68 | return i.InitialDepartureLocation() == event.Activity.Location 69 | case Load: 70 | for _, l := range i.Legs { 71 | if l.LoadLocation == event.Activity.Location && l.VoyageNumber == event.Activity.VoyageNumber { 72 | return true 73 | } 74 | } 75 | return false 76 | case Unload: 77 | for _, l := range i.Legs { 78 | if l.UnloadLocation == event.Activity.Location && l.VoyageNumber == event.Activity.VoyageNumber { 79 | return true 80 | } 81 | } 82 | return false 83 | case Claim: 84 | return i.FinalArrivalLocation() == event.Activity.Location 85 | } 86 | 87 | return true 88 | } 89 | -------------------------------------------------------------------------------- /itinerary_test.go: -------------------------------------------------------------------------------- 1 | package shipping 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | ) 7 | 8 | func TestItinerary_CreateEmpty(t *testing.T) { 9 | i := Itinerary{} 10 | 11 | var legs []Leg 12 | 13 | if !reflect.DeepEqual(i.Legs, legs) { 14 | t.Errorf("should be equal") 15 | } 16 | if i.InitialDepartureLocation() != "" { 17 | t.Errorf("InitialDepartureLocation() = %s; want = %s", 18 | i.InitialDepartureLocation(), "") 19 | } 20 | if i.FinalArrivalLocation() != "" { 21 | t.Errorf("FinalArrivalLocation() = %s; want = %s", 22 | i.FinalArrivalLocation(), "") 23 | } 24 | } 25 | 26 | func TestItinerary_IsExpected_EmptyItinerary(t *testing.T) { 27 | i := Itinerary{} 28 | e := HandlingEvent{} 29 | 30 | if got, want := i.IsExpected(e), true; got != want { 31 | t.Errorf("IsExpected() = %v; want = %v", got, want) 32 | } 33 | } 34 | 35 | type eventExpectedTest struct { 36 | act HandlingActivity 37 | exp bool 38 | } 39 | 40 | var eventExpectedTests = []eventExpectedTest{ 41 | {HandlingActivity{}, true}, 42 | {HandlingActivity{Type: Receive, Location: SESTO}, true}, 43 | {HandlingActivity{Type: Receive, Location: AUMEL}, false}, 44 | {HandlingActivity{Type: Load, Location: AUMEL, VoyageNumber: "001A"}, true}, 45 | {HandlingActivity{Type: Load, Location: CNHKG, VoyageNumber: "001A"}, false}, 46 | {HandlingActivity{Type: Unload, Location: CNHKG, VoyageNumber: "001A"}, true}, 47 | {HandlingActivity{Type: Unload, Location: SESTO, VoyageNumber: "001A"}, false}, 48 | {HandlingActivity{Type: Claim, Location: CNHKG}, true}, 49 | {HandlingActivity{Type: Claim, Location: SESTO}, false}, 50 | } 51 | 52 | func TestItinerary_IsExpected(t *testing.T) { 53 | i := Itinerary{Legs: []Leg{ 54 | { 55 | VoyageNumber: "001A", 56 | LoadLocation: SESTO, 57 | UnloadLocation: AUMEL, 58 | }, 59 | { 60 | VoyageNumber: "001A", 61 | LoadLocation: AUMEL, 62 | UnloadLocation: CNHKG, 63 | }, 64 | }} 65 | 66 | for _, tt := range eventExpectedTests { 67 | e := HandlingEvent{ 68 | Activity: tt.act, 69 | } 70 | 71 | if got := i.IsExpected(e); got != tt.exp { 72 | t.Errorf("IsExpected() = %v; want = %v", got, tt.exp) 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /location.go: -------------------------------------------------------------------------------- 1 | package shipping 2 | 3 | import "errors" 4 | 5 | // UNLocode is the United Nations location code that uniquely identifies a 6 | // particular location. 7 | // 8 | // http://www.unece.org/cefact/locode/ 9 | // http://www.unece.org/cefact/locode/DocColumnDescription.htm#LOCODE 10 | type UNLocode string 11 | 12 | // Location is a location is our model is stops on a journey, such as cargo 13 | // origin or destination, or carrier movement endpoints. 14 | type Location struct { 15 | UNLocode UNLocode 16 | Name string 17 | } 18 | 19 | // ErrUnknownLocation is used when a location could not be found. 20 | var ErrUnknownLocation = errors.New("unknown location") 21 | 22 | // LocationRepository provides access a location store. 23 | type LocationRepository interface { 24 | Find(locode UNLocode) (*Location, error) 25 | FindAll() []*Location 26 | } 27 | -------------------------------------------------------------------------------- /mock/mock.go: -------------------------------------------------------------------------------- 1 | package mock 2 | 3 | import ( 4 | shipping "github.com/marcusolsson/goddd" 5 | ) 6 | 7 | // CargoRepository is a mock cargo repository. 8 | type CargoRepository struct { 9 | StoreFn func(c *shipping.Cargo) error 10 | StoreInvoked bool 11 | 12 | FindFn func(id shipping.TrackingID) (*shipping.Cargo, error) 13 | FindInvoked bool 14 | 15 | FindAllFn func() []*shipping.Cargo 16 | FindAllInvoked bool 17 | } 18 | 19 | // Store calls the StoreFn. 20 | func (r *CargoRepository) Store(c *shipping.Cargo) error { 21 | r.StoreInvoked = true 22 | return r.StoreFn(c) 23 | } 24 | 25 | // Find calls the FindFn. 26 | func (r *CargoRepository) Find(id shipping.TrackingID) (*shipping.Cargo, error) { 27 | r.FindInvoked = true 28 | return r.FindFn(id) 29 | } 30 | 31 | // FindAll calls the FindAllFn. 32 | func (r *CargoRepository) FindAll() []*shipping.Cargo { 33 | r.FindAllInvoked = true 34 | return r.FindAllFn() 35 | } 36 | 37 | // LocationRepository is a mock location repository. 38 | type LocationRepository struct { 39 | FindFn func(shipping.UNLocode) (*shipping.Location, error) 40 | FindInvoked bool 41 | 42 | FindAllFn func() []*shipping.Location 43 | FindAllInvoked bool 44 | } 45 | 46 | // Find calls the FindFn. 47 | func (r *LocationRepository) Find(locode shipping.UNLocode) (*shipping.Location, error) { 48 | r.FindInvoked = true 49 | return r.FindFn(locode) 50 | } 51 | 52 | // FindAll calls the FindAllFn. 53 | func (r *LocationRepository) FindAll() []*shipping.Location { 54 | r.FindAllInvoked = true 55 | return r.FindAllFn() 56 | } 57 | 58 | // VoyageRepository is a mock voyage repository. 59 | type VoyageRepository struct { 60 | FindFn func(shipping.VoyageNumber) (*shipping.Voyage, error) 61 | FindInvoked bool 62 | } 63 | 64 | // Find calls the FindFn. 65 | func (r *VoyageRepository) Find(number shipping.VoyageNumber) (*shipping.Voyage, error) { 66 | r.FindInvoked = true 67 | return r.FindFn(number) 68 | } 69 | 70 | // HandlingEventRepository is a mock handling events repository. 71 | type HandlingEventRepository struct { 72 | StoreFn func(shipping.HandlingEvent) 73 | StoreInvoked bool 74 | 75 | QueryHandlingHistoryFn func(shipping.TrackingID) shipping.HandlingHistory 76 | QueryHandlingHistoryInvoked bool 77 | } 78 | 79 | // Store calls the StoreFn. 80 | func (r *HandlingEventRepository) Store(e shipping.HandlingEvent) { 81 | r.StoreInvoked = true 82 | r.StoreFn(e) 83 | } 84 | 85 | // QueryHandlingHistory calls the QueryHandlingHistoryFn. 86 | func (r *HandlingEventRepository) QueryHandlingHistory(id shipping.TrackingID) shipping.HandlingHistory { 87 | r.QueryHandlingHistoryInvoked = true 88 | return r.QueryHandlingHistoryFn(id) 89 | } 90 | 91 | // RoutingService provides a mock routing service. 92 | type RoutingService struct { 93 | FetchRoutesFn func(shipping.RouteSpecification) []shipping.Itinerary 94 | FetchRoutesInvoked bool 95 | } 96 | 97 | // FetchRoutesForSpecification calls the FetchRoutesFn. 98 | func (s *RoutingService) FetchRoutesForSpecification(rs shipping.RouteSpecification) []shipping.Itinerary { 99 | s.FetchRoutesInvoked = true 100 | return s.FetchRoutesFn(rs) 101 | } 102 | -------------------------------------------------------------------------------- /routing.go: -------------------------------------------------------------------------------- 1 | package shipping 2 | 3 | // RoutingService is a domain service for routing cargos. 4 | type RoutingService interface { 5 | // FetchRoutesForSpecification finds all possible routes that satisfy a 6 | // given specification. 7 | FetchRoutesForSpecification(rs RouteSpecification) []Itinerary 8 | } 9 | -------------------------------------------------------------------------------- /sample_locations.go: -------------------------------------------------------------------------------- 1 | package shipping 2 | 3 | // Sample UN locodes. 4 | var ( 5 | SESTO UNLocode = "SESTO" 6 | AUMEL UNLocode = "AUMEL" 7 | CNHKG UNLocode = "CNHKG" 8 | USNYC UNLocode = "USNYC" 9 | USCHI UNLocode = "USCHI" 10 | JNTKO UNLocode = "JNTKO" 11 | DEHAM UNLocode = "DEHAM" 12 | NLRTM UNLocode = "NLRTM" 13 | FIHEL UNLocode = "FIHEL" 14 | ) 15 | 16 | // Sample locations. 17 | var ( 18 | Stockholm = &Location{SESTO, "Stockholm"} 19 | Melbourne = &Location{AUMEL, "Melbourne"} 20 | Hongkong = &Location{CNHKG, "Hongkong"} 21 | NewYork = &Location{USNYC, "New York"} 22 | Chicago = &Location{USCHI, "Chicago"} 23 | Tokyo = &Location{JNTKO, "Tokyo"} 24 | Hamburg = &Location{DEHAM, "Hamburg"} 25 | Rotterdam = &Location{NLRTM, "Rotterdam"} 26 | Helsinki = &Location{FIHEL, "Helsinki"} 27 | ) 28 | -------------------------------------------------------------------------------- /sample_voyages.go: -------------------------------------------------------------------------------- 1 | package shipping 2 | 3 | // A set of sample voyages. 4 | var ( 5 | V100 = NewVoyage("V100", Schedule{ 6 | []CarrierMovement{ 7 | {DepartureLocation: CNHKG, ArrivalLocation: JNTKO}, 8 | {DepartureLocation: JNTKO, ArrivalLocation: USNYC}, 9 | }, 10 | }) 11 | 12 | V300 = NewVoyage("V300", Schedule{ 13 | []CarrierMovement{ 14 | {DepartureLocation: JNTKO, ArrivalLocation: NLRTM}, 15 | {DepartureLocation: NLRTM, ArrivalLocation: DEHAM}, 16 | {DepartureLocation: DEHAM, ArrivalLocation: AUMEL}, 17 | {DepartureLocation: AUMEL, ArrivalLocation: JNTKO}, 18 | }, 19 | }) 20 | 21 | V400 = NewVoyage("V400", Schedule{ 22 | []CarrierMovement{ 23 | {DepartureLocation: DEHAM, ArrivalLocation: SESTO}, 24 | {DepartureLocation: SESTO, ArrivalLocation: FIHEL}, 25 | {DepartureLocation: FIHEL, ArrivalLocation: DEHAM}, 26 | }, 27 | }) 28 | ) 29 | 30 | // These voyages are hard-coded into the current pathfinder. Make sure 31 | // they exist. 32 | var ( 33 | V0100S = NewVoyage("0100S", Schedule{[]CarrierMovement{}}) 34 | V0200T = NewVoyage("0200T", Schedule{[]CarrierMovement{}}) 35 | V0300A = NewVoyage("0300A", Schedule{[]CarrierMovement{}}) 36 | V0301S = NewVoyage("0301S", Schedule{[]CarrierMovement{}}) 37 | V0400S = NewVoyage("0400S", Schedule{[]CarrierMovement{}}) 38 | ) 39 | -------------------------------------------------------------------------------- /server/handling.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "net/http" 7 | "time" 8 | 9 | "github.com/go-chi/chi" 10 | kitlog "github.com/go-kit/kit/log" 11 | 12 | shipping "github.com/marcusolsson/goddd" 13 | "github.com/marcusolsson/goddd/handling" 14 | ) 15 | 16 | type handlingHandler struct { 17 | s handling.Service 18 | 19 | logger kitlog.Logger 20 | } 21 | 22 | func (h *handlingHandler) router() chi.Router { 23 | r := chi.NewRouter() 24 | r.Post("/incidents", h.registerIncident) 25 | r.Method("GET", "/docs", http.StripPrefix("/handling/v1/docs", http.FileServer(http.Dir("handling/docs")))) 26 | return r 27 | } 28 | 29 | func (h *handlingHandler) registerIncident(w http.ResponseWriter, r *http.Request) { 30 | ctx := context.Background() 31 | 32 | var request struct { 33 | CompletionTime time.Time `json:"completion_time"` 34 | TrackingID string `json:"tracking_id"` 35 | VoyageNumber string `json:"voyage"` 36 | Location string `json:"location"` 37 | EventType string `json:"event_type"` 38 | } 39 | 40 | if err := json.NewDecoder(r.Body).Decode(&request); err != nil { 41 | h.logger.Log("error", err) 42 | encodeError(ctx, err, w) 43 | return 44 | } 45 | 46 | err := h.s.RegisterHandlingEvent( 47 | request.CompletionTime, 48 | shipping.TrackingID(request.TrackingID), 49 | shipping.VoyageNumber(request.VoyageNumber), 50 | shipping.UNLocode(request.Location), 51 | stringToEventType(request.EventType), 52 | ) 53 | if err != nil { 54 | encodeError(ctx, err, w) 55 | return 56 | } 57 | } 58 | 59 | func stringToEventType(s string) shipping.HandlingEventType { 60 | types := map[string]shipping.HandlingEventType{ 61 | shipping.Receive.String(): shipping.Receive, 62 | shipping.Load.String(): shipping.Load, 63 | shipping.Unload.String(): shipping.Unload, 64 | shipping.Customs.String(): shipping.Customs, 65 | shipping.Claim.String(): shipping.Claim, 66 | } 67 | return types[s] 68 | } 69 | -------------------------------------------------------------------------------- /server/server.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "net/http" 7 | 8 | "github.com/go-chi/chi" 9 | kitlog "github.com/go-kit/kit/log" 10 | "github.com/prometheus/client_golang/prometheus/promhttp" 11 | 12 | shipping "github.com/marcusolsson/goddd" 13 | "github.com/marcusolsson/goddd/booking" 14 | "github.com/marcusolsson/goddd/handling" 15 | "github.com/marcusolsson/goddd/tracking" 16 | ) 17 | 18 | // Server holds the dependencies for a HTTP server. 19 | type Server struct { 20 | Booking booking.Service 21 | Tracking tracking.Service 22 | Handling handling.Service 23 | 24 | Logger kitlog.Logger 25 | 26 | router chi.Router 27 | } 28 | 29 | // New returns a new HTTP server. 30 | func New(bs booking.Service, ts tracking.Service, hs handling.Service, logger kitlog.Logger) *Server { 31 | s := &Server{ 32 | Booking: bs, 33 | Tracking: ts, 34 | Handling: hs, 35 | Logger: logger, 36 | } 37 | 38 | r := chi.NewRouter() 39 | 40 | r.Use(accessControl) 41 | 42 | r.Route("/booking", func(r chi.Router) { 43 | h := bookingHandler{s.Booking, s.Logger} 44 | r.Mount("/v1", h.router()) 45 | }) 46 | r.Route("/tracking", func(r chi.Router) { 47 | h := trackingHandler{s.Tracking, s.Logger} 48 | r.Mount("/v1", h.router()) 49 | }) 50 | r.Route("/handling", func(r chi.Router) { 51 | h := handlingHandler{s.Handling, s.Logger} 52 | r.Mount("/v1", h.router()) 53 | }) 54 | 55 | r.Method("GET", "/metrics", promhttp.Handler()) 56 | 57 | s.router = r 58 | 59 | return s 60 | } 61 | 62 | func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { 63 | s.router.ServeHTTP(w, r) 64 | } 65 | 66 | func accessControl(h http.Handler) http.Handler { 67 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 68 | w.Header().Set("Access-Control-Allow-Origin", "*") 69 | w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS") 70 | w.Header().Set("Access-Control-Allow-Headers", "Origin, Content-Type") 71 | 72 | if r.Method == "OPTIONS" { 73 | return 74 | } 75 | 76 | h.ServeHTTP(w, r) 77 | }) 78 | } 79 | 80 | func encodeError(_ context.Context, err error, w http.ResponseWriter) { 81 | w.Header().Set("Content-Type", "application/json; charset=utf-8") 82 | switch err { 83 | case shipping.ErrUnknownCargo: 84 | w.WriteHeader(http.StatusNotFound) 85 | case tracking.ErrInvalidArgument: 86 | w.WriteHeader(http.StatusBadRequest) 87 | default: 88 | w.WriteHeader(http.StatusInternalServerError) 89 | } 90 | json.NewEncoder(w).Encode(map[string]interface{}{ 91 | "error": err.Error(), 92 | }) 93 | } 94 | -------------------------------------------------------------------------------- /server/tracking.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "net/http" 7 | 8 | "github.com/go-chi/chi" 9 | kitlog "github.com/go-kit/kit/log" 10 | 11 | "github.com/marcusolsson/goddd/tracking" 12 | ) 13 | 14 | type trackingHandler struct { 15 | s tracking.Service 16 | 17 | logger kitlog.Logger 18 | } 19 | 20 | func (h *trackingHandler) router() chi.Router { 21 | r := chi.NewRouter() 22 | r.Get("/cargos/{trackingID}", h.track) 23 | r.Method("GET", "/docs", http.StripPrefix("/tracking/v1/docs", http.FileServer(http.Dir("tracking/docs")))) 24 | return r 25 | } 26 | 27 | func (h *trackingHandler) track(w http.ResponseWriter, r *http.Request) { 28 | ctx := context.Background() 29 | 30 | trackingID := chi.URLParam(r, "trackingID") 31 | 32 | c, err := h.s.Track(trackingID) 33 | if err != nil { 34 | encodeError(ctx, err, w) 35 | return 36 | } 37 | 38 | var response = struct { 39 | Cargo *tracking.Cargo `json:"cargo"` 40 | }{Cargo: &c} 41 | 42 | w.Header().Set("Content-Type", "application/json; charset=utf-8") 43 | if err := json.NewEncoder(w).Encode(response); err != nil { 44 | h.logger.Log("error", err) 45 | encodeError(ctx, err, w) 46 | return 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /tracking/docs/api.raml: -------------------------------------------------------------------------------- 1 | #%RAML 0.8 2 | title: Tracking 3 | baseUri: http://dddsample.marcusoncode.se/tracking/{version} 4 | version: v1 5 | 6 | /cargos: 7 | /{trackingId}: 8 | uriParameters: 9 | trackingId: 10 | description: The tracking id of the cargo 11 | type: string 12 | get: 13 | description: A specific cargo 14 | responses: 15 | 200: 16 | body: 17 | application/json: 18 | example: | 19 | { 20 | "cargo": { 21 | "tracking_id": "B075CD13", 22 | "status_text": "Not received", 23 | "origin": "DEHAM", 24 | "destination": "SESTO", 25 | "eta": "2016-03-22T19:24:24.686283448Z", 26 | "next_expected_activity": "Next expected activity is to receive cargo in DEHAM.", 27 | "arrival_deadline": "2016-04-08T22:00:00Z", 28 | "events": null 29 | } 30 | } 31 | 404: 32 | body: 33 | application/json: 34 | example: | 35 | { 36 | "error": "unknown cargo" 37 | } 38 | -------------------------------------------------------------------------------- /tracking/instrumenting.go: -------------------------------------------------------------------------------- 1 | package tracking 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/go-kit/kit/metrics" 7 | ) 8 | 9 | type instrumentingService struct { 10 | requestCount metrics.Counter 11 | requestLatency metrics.Histogram 12 | next Service 13 | } 14 | 15 | // NewInstrumentingService returns an instance of an instrumenting Service. 16 | func NewInstrumentingService(counter metrics.Counter, latency metrics.Histogram, s Service) Service { 17 | return &instrumentingService{ 18 | requestCount: counter, 19 | requestLatency: latency, 20 | next: s, 21 | } 22 | } 23 | 24 | func (s *instrumentingService) Track(id string) (Cargo, error) { 25 | defer func(begin time.Time) { 26 | s.requestCount.With("method", "track").Add(1) 27 | s.requestLatency.With("method", "track").Observe(time.Since(begin).Seconds()) 28 | }(time.Now()) 29 | 30 | return s.next.Track(id) 31 | } 32 | -------------------------------------------------------------------------------- /tracking/logging.go: -------------------------------------------------------------------------------- 1 | package tracking 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/go-kit/kit/log" 7 | ) 8 | 9 | type loggingService struct { 10 | logger log.Logger 11 | next Service 12 | } 13 | 14 | // NewLoggingService returns a new instance of a logging Service. 15 | func NewLoggingService(logger log.Logger, s Service) Service { 16 | return &loggingService{logger, s} 17 | } 18 | 19 | func (s *loggingService) Track(id string) (c Cargo, err error) { 20 | defer func(begin time.Time) { 21 | s.logger.Log("method", "track", "tracking_id", id, "took", time.Since(begin), "err", err) 22 | }(time.Now()) 23 | return s.next.Track(id) 24 | } 25 | -------------------------------------------------------------------------------- /tracking/service_test.go: -------------------------------------------------------------------------------- 1 | package tracking 2 | 3 | import ( 4 | "testing" 5 | 6 | shipping "github.com/marcusolsson/goddd" 7 | "github.com/marcusolsson/goddd/mock" 8 | ) 9 | 10 | func TestTrack(t *testing.T) { 11 | var cargos mock.CargoRepository 12 | cargos.FindFn = func(id shipping.TrackingID) (*shipping.Cargo, error) { 13 | return shipping.NewCargo("FTL456", shipping.RouteSpecification{ 14 | Origin: shipping.AUMEL, 15 | Destination: shipping.SESTO, 16 | }), nil 17 | } 18 | 19 | var events mock.HandlingEventRepository 20 | events.QueryHandlingHistoryFn = func(id shipping.TrackingID) shipping.HandlingHistory { 21 | return shipping.HandlingHistory{} 22 | } 23 | 24 | s := NewService(&cargos, &events) 25 | 26 | c, err := s.Track("FTL456") 27 | if err != nil { 28 | t.Fatal(err) 29 | } 30 | 31 | if c.TrackingID != "FTL456" { 32 | t.Errorf("c.TrackingID = %v; want = %v", c.TrackingID, "FTL456") 33 | } 34 | if c.Origin != "AUMEL" { 35 | t.Errorf("c.Origin = %v; want = %v", c.Destination, "AUMEL") 36 | } 37 | if c.Destination != "SESTO" { 38 | t.Errorf("c.Destination = %v; want = %v", c.Destination, "SESTO") 39 | } 40 | if c.StatusText != shipping.NotReceived.String() { 41 | t.Errorf("c.StatusText = %v; want = %v", c.StatusText, shipping.NotReceived.String()) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /vendor/github.com/afex/hystrix-go/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 keith 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /vendor/github.com/afex/hystrix-go/hystrix/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package hystrix is a latency and fault tolerance library designed to isolate 3 | points of access to remote systems, services and 3rd party libraries, stop 4 | cascading failure and enable resilience in complex distributed systems where 5 | failure is inevitable. 6 | 7 | Based on the java project of the same name, by Netflix. https://github.com/Netflix/Hystrix 8 | 9 | Execute code as a Hystrix command 10 | 11 | Define your application logic which relies on external systems, passing your function to Go. When that system is healthy this will be the only thing which executes. 12 | 13 | hystrix.Go("my_command", func() error { 14 | // talk to other services 15 | return nil 16 | }, nil) 17 | 18 | Defining fallback behavior 19 | 20 | If you want code to execute during a service outage, pass in a second function to Go. Ideally, the logic here will allow your application to gracefully handle external services being unavailable. 21 | 22 | This triggers when your code returns an error, or whenever it is unable to complete based on a variety of health checks https://github.com/Netflix/Hystrix/wiki/How-it-Works. 23 | 24 | hystrix.Go("my_command", func() error { 25 | // talk to other services 26 | return nil 27 | }, func(err error) error { 28 | // do this when services are down 29 | return nil 30 | }) 31 | 32 | Waiting for output 33 | 34 | Calling Go is like launching a goroutine, except you receive a channel of errors you can choose to monitor. 35 | 36 | output := make(chan bool, 1) 37 | errors := hystrix.Go("my_command", func() error { 38 | // talk to other services 39 | output <- true 40 | return nil 41 | }, nil) 42 | 43 | select { 44 | case out := <-output: 45 | // success 46 | case err := <-errors: 47 | // failure 48 | } 49 | 50 | Synchronous API 51 | 52 | Since calling a command and immediately waiting for it to finish is a common pattern, a synchronous API is available with the Do function which returns a single error. 53 | 54 | err := hystrix.Do("my_command", func() error { 55 | // talk to other services 56 | return nil 57 | }, nil) 58 | 59 | Configure settings 60 | 61 | During application boot, you can call ConfigureCommand to tweak the settings for each command. 62 | 63 | hystrix.ConfigureCommand("my_command", hystrix.CommandConfig{ 64 | Timeout: 1000, 65 | MaxConcurrentRequests: 100, 66 | ErrorPercentThreshold: 25, 67 | }) 68 | 69 | You can also use Configure which accepts a map[string]CommandConfig. 70 | 71 | Enable dashboard metrics 72 | 73 | In your main.go, register the event stream HTTP handler on a port and launch it in a goroutine. Once you configure turbine for your Hystrix Dashboard https://github.com/Netflix/Hystrix/tree/master/hystrix-dashboard to start streaming events, your commands will automatically begin appearing. 74 | 75 | hystrixStreamHandler := hystrix.NewStreamHandler() 76 | hystrixStreamHandler.Start() 77 | go http.ListenAndServe(net.JoinHostPort("", "81"), hystrixStreamHandler) 78 | */ 79 | package hystrix 80 | -------------------------------------------------------------------------------- /vendor/github.com/afex/hystrix-go/hystrix/logger.go: -------------------------------------------------------------------------------- 1 | package hystrix 2 | 3 | type logger interface { 4 | Printf(format string, items ...interface{}) 5 | } 6 | 7 | // NoopLogger does not log anything. 8 | type NoopLogger struct{} 9 | 10 | // Printf does nothing. 11 | func (l NoopLogger) Printf(format string, items ...interface{}) {} 12 | -------------------------------------------------------------------------------- /vendor/github.com/afex/hystrix-go/hystrix/metric_collector/metric_collector.go: -------------------------------------------------------------------------------- 1 | package metricCollector 2 | 3 | import ( 4 | "sync" 5 | "time" 6 | ) 7 | 8 | // Registry is the default metricCollectorRegistry that circuits will use to 9 | // collect statistics about the health of the circuit. 10 | var Registry = metricCollectorRegistry{ 11 | lock: &sync.RWMutex{}, 12 | registry: []func(name string) MetricCollector{ 13 | newDefaultMetricCollector, 14 | }, 15 | } 16 | 17 | type metricCollectorRegistry struct { 18 | lock *sync.RWMutex 19 | registry []func(name string) MetricCollector 20 | } 21 | 22 | // InitializeMetricCollectors runs the registried MetricCollector Initializers to create an array of MetricCollectors. 23 | func (m *metricCollectorRegistry) InitializeMetricCollectors(name string) []MetricCollector { 24 | m.lock.RLock() 25 | defer m.lock.RUnlock() 26 | 27 | metrics := make([]MetricCollector, len(m.registry)) 28 | for i, metricCollectorInitializer := range m.registry { 29 | metrics[i] = metricCollectorInitializer(name) 30 | } 31 | return metrics 32 | } 33 | 34 | // Register places a MetricCollector Initializer in the registry maintained by this metricCollectorRegistry. 35 | func (m *metricCollectorRegistry) Register(initMetricCollector func(string) MetricCollector) { 36 | m.lock.Lock() 37 | defer m.lock.Unlock() 38 | 39 | m.registry = append(m.registry, initMetricCollector) 40 | } 41 | 42 | type MetricResult struct { 43 | Attempts float64 44 | Errors float64 45 | Successes float64 46 | Failures float64 47 | Rejects float64 48 | ShortCircuits float64 49 | Timeouts float64 50 | FallbackSuccesses float64 51 | FallbackFailures float64 52 | ContextCanceled float64 53 | ContextDeadlineExceeded float64 54 | TotalDuration time.Duration 55 | RunDuration time.Duration 56 | ConcurrencyInUse float64 57 | } 58 | 59 | // MetricCollector represents the contract that all collectors must fulfill to gather circuit statistics. 60 | // Implementations of this interface do not have to maintain locking around thier data stores so long as 61 | // they are not modified outside of the hystrix context. 62 | type MetricCollector interface { 63 | // Update accepts a set of metrics from a command execution for remote instrumentation 64 | Update(MetricResult) 65 | // Reset resets the internal counters and timers. 66 | Reset() 67 | } 68 | -------------------------------------------------------------------------------- /vendor/github.com/afex/hystrix-go/hystrix/pool.go: -------------------------------------------------------------------------------- 1 | package hystrix 2 | 3 | type executorPool struct { 4 | Name string 5 | Metrics *poolMetrics 6 | Max int 7 | Tickets chan *struct{} 8 | } 9 | 10 | func newExecutorPool(name string) *executorPool { 11 | p := &executorPool{} 12 | p.Name = name 13 | p.Metrics = newPoolMetrics(name) 14 | p.Max = getSettings(name).MaxConcurrentRequests 15 | 16 | p.Tickets = make(chan *struct{}, p.Max) 17 | for i := 0; i < p.Max; i++ { 18 | p.Tickets <- &struct{}{} 19 | } 20 | 21 | return p 22 | } 23 | 24 | func (p *executorPool) Return(ticket *struct{}) { 25 | if ticket == nil { 26 | return 27 | } 28 | 29 | p.Metrics.Updates <- poolMetricsUpdate{ 30 | activeCount: p.ActiveCount(), 31 | } 32 | p.Tickets <- ticket 33 | } 34 | 35 | func (p *executorPool) ActiveCount() int { 36 | return p.Max - len(p.Tickets) 37 | } 38 | -------------------------------------------------------------------------------- /vendor/github.com/afex/hystrix-go/hystrix/pool_metrics.go: -------------------------------------------------------------------------------- 1 | package hystrix 2 | 3 | import ( 4 | "sync" 5 | 6 | "github.com/afex/hystrix-go/hystrix/rolling" 7 | ) 8 | 9 | type poolMetrics struct { 10 | Mutex *sync.RWMutex 11 | Updates chan poolMetricsUpdate 12 | 13 | Name string 14 | MaxActiveRequests *rolling.Number 15 | Executed *rolling.Number 16 | } 17 | 18 | type poolMetricsUpdate struct { 19 | activeCount int 20 | } 21 | 22 | func newPoolMetrics(name string) *poolMetrics { 23 | m := &poolMetrics{} 24 | m.Name = name 25 | m.Updates = make(chan poolMetricsUpdate) 26 | m.Mutex = &sync.RWMutex{} 27 | 28 | m.Reset() 29 | 30 | go m.Monitor() 31 | 32 | return m 33 | } 34 | 35 | func (m *poolMetrics) Reset() { 36 | m.Mutex.Lock() 37 | defer m.Mutex.Unlock() 38 | 39 | m.MaxActiveRequests = rolling.NewNumber() 40 | m.Executed = rolling.NewNumber() 41 | } 42 | 43 | func (m *poolMetrics) Monitor() { 44 | for u := range m.Updates { 45 | m.Mutex.RLock() 46 | 47 | m.Executed.Increment(1) 48 | m.MaxActiveRequests.UpdateMax(float64(u.activeCount)) 49 | 50 | m.Mutex.RUnlock() 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /vendor/github.com/afex/hystrix-go/hystrix/rolling/rolling.go: -------------------------------------------------------------------------------- 1 | package rolling 2 | 3 | import ( 4 | "sync" 5 | "time" 6 | ) 7 | 8 | // Number tracks a numberBucket over a bounded number of 9 | // time buckets. Currently the buckets are one second long and only the last 10 seconds are kept. 10 | type Number struct { 11 | Buckets map[int64]*numberBucket 12 | Mutex *sync.RWMutex 13 | } 14 | 15 | type numberBucket struct { 16 | Value float64 17 | } 18 | 19 | // NewNumber initializes a RollingNumber struct. 20 | func NewNumber() *Number { 21 | r := &Number{ 22 | Buckets: make(map[int64]*numberBucket), 23 | Mutex: &sync.RWMutex{}, 24 | } 25 | return r 26 | } 27 | 28 | func (r *Number) getCurrentBucket() *numberBucket { 29 | now := time.Now().Unix() 30 | var bucket *numberBucket 31 | var ok bool 32 | 33 | if bucket, ok = r.Buckets[now]; !ok { 34 | bucket = &numberBucket{} 35 | r.Buckets[now] = bucket 36 | } 37 | 38 | return bucket 39 | } 40 | 41 | func (r *Number) removeOldBuckets() { 42 | now := time.Now().Unix() - 10 43 | 44 | for timestamp := range r.Buckets { 45 | // TODO: configurable rolling window 46 | if timestamp <= now { 47 | delete(r.Buckets, timestamp) 48 | } 49 | } 50 | } 51 | 52 | // Increment increments the number in current timeBucket. 53 | func (r *Number) Increment(i float64) { 54 | if i == 0 { 55 | return 56 | } 57 | 58 | r.Mutex.Lock() 59 | defer r.Mutex.Unlock() 60 | 61 | b := r.getCurrentBucket() 62 | b.Value += i 63 | r.removeOldBuckets() 64 | } 65 | 66 | // UpdateMax updates the maximum value in the current bucket. 67 | func (r *Number) UpdateMax(n float64) { 68 | r.Mutex.Lock() 69 | defer r.Mutex.Unlock() 70 | 71 | b := r.getCurrentBucket() 72 | if n > b.Value { 73 | b.Value = n 74 | } 75 | r.removeOldBuckets() 76 | } 77 | 78 | // Sum sums the values over the buckets in the last 10 seconds. 79 | func (r *Number) Sum(now time.Time) float64 { 80 | sum := float64(0) 81 | 82 | r.Mutex.RLock() 83 | defer r.Mutex.RUnlock() 84 | 85 | for timestamp, bucket := range r.Buckets { 86 | // TODO: configurable rolling window 87 | if timestamp >= now.Unix()-10 { 88 | sum += bucket.Value 89 | } 90 | } 91 | 92 | return sum 93 | } 94 | 95 | // Max returns the maximum value seen in the last 10 seconds. 96 | func (r *Number) Max(now time.Time) float64 { 97 | var max float64 98 | 99 | r.Mutex.RLock() 100 | defer r.Mutex.RUnlock() 101 | 102 | for timestamp, bucket := range r.Buckets { 103 | // TODO: configurable rolling window 104 | if timestamp >= now.Unix()-10 { 105 | if bucket.Value > max { 106 | max = bucket.Value 107 | } 108 | } 109 | } 110 | 111 | return max 112 | } 113 | 114 | func (r *Number) Avg(now time.Time) float64 { 115 | return r.Sum(now) / 10 116 | } 117 | -------------------------------------------------------------------------------- /vendor/github.com/beorn7/perks/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2013 Blake Mizerany 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /vendor/github.com/go-chi/chi/.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.sw? 3 | .vscode 4 | -------------------------------------------------------------------------------- /vendor/github.com/go-chi/chi/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.7.x 5 | - 1.8.x 6 | - 1.9.x 7 | - 1.10.x 8 | - 1.11.x 9 | 10 | install: 11 | - go get -u golang.org/x/tools/cmd/goimports 12 | - go get -u github.com/golang/lint/golint 13 | 14 | script: 15 | - go get -d -t ./... 16 | - go vet ./... 17 | - golint ./... 18 | - go test ./... 19 | - > 20 | go_version=$(go version); 21 | if [ ${go_version:13:4} = "1.11" ]; then 22 | goimports -d -e ./ | grep '.*' && { echo; echo "Aborting due to non-empty goimports output."; exit 1; } || :; 23 | fi 24 | 25 | -------------------------------------------------------------------------------- /vendor/github.com/go-chi/chi/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | ## Prerequisites 4 | 5 | 1. [Install Go][go-install]. 6 | 2. Download the sources and switch the working directory: 7 | 8 | ```bash 9 | go get -u -d github.com/go-chi/chi 10 | cd $GOPATH/src/github.com/go-chi/chi 11 | ``` 12 | 13 | ## Submitting a Pull Request 14 | 15 | A typical workflow is: 16 | 17 | 1. [Fork the repository.][fork] [This tip maybe also helpful.][go-fork-tip] 18 | 2. [Create a topic branch.][branch] 19 | 3. Add tests for your change. 20 | 4. Run `go test`. If your tests pass, return to the step 3. 21 | 5. Implement the change and ensure the steps from the previous step pass. 22 | 6. Run `goimports -w .`, to ensure the new code conforms to Go formatting guideline. 23 | 7. [Add, commit and push your changes.][git-help] 24 | 8. [Submit a pull request.][pull-req] 25 | 26 | [go-install]: https://golang.org/doc/install 27 | [go-fork-tip]: http://blog.campoy.cat/2014/03/github-and-go-forking-pull-requests-and.html 28 | [fork]: https://help.github.com/articles/fork-a-repo 29 | [branch]: http://learn.github.com/p/branching.html 30 | [git-help]: https://guides.github.com 31 | [pull-req]: https://help.github.com/articles/using-pull-requests 32 | -------------------------------------------------------------------------------- /vendor/github.com/go-chi/chi/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015-present Peter Kieltyka (https://github.com/pkieltyka), Google Inc. 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /vendor/github.com/go-chi/chi/chain.go: -------------------------------------------------------------------------------- 1 | package chi 2 | 3 | import "net/http" 4 | 5 | // Chain returns a Middlewares type from a slice of middleware handlers. 6 | func Chain(middlewares ...func(http.Handler) http.Handler) Middlewares { 7 | return Middlewares(middlewares) 8 | } 9 | 10 | // Handler builds and returns a http.Handler from the chain of middlewares, 11 | // with `h http.Handler` as the final handler. 12 | func (mws Middlewares) Handler(h http.Handler) http.Handler { 13 | return &ChainHandler{mws, h, chain(mws, h)} 14 | } 15 | 16 | // HandlerFunc builds and returns a http.Handler from the chain of middlewares, 17 | // with `h http.Handler` as the final handler. 18 | func (mws Middlewares) HandlerFunc(h http.HandlerFunc) http.Handler { 19 | return &ChainHandler{mws, h, chain(mws, h)} 20 | } 21 | 22 | // ChainHandler is a http.Handler with support for handler composition and 23 | // execution. 24 | type ChainHandler struct { 25 | Middlewares Middlewares 26 | Endpoint http.Handler 27 | chain http.Handler 28 | } 29 | 30 | func (c *ChainHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 31 | c.chain.ServeHTTP(w, r) 32 | } 33 | 34 | // chain builds a http.Handler composed of an inline middleware stack and endpoint 35 | // handler in the order they are passed. 36 | func chain(middlewares []func(http.Handler) http.Handler, endpoint http.Handler) http.Handler { 37 | // Return ahead of time if there aren't any middlewares for the chain 38 | if len(middlewares) == 0 { 39 | return endpoint 40 | } 41 | 42 | // Wrap the end handler with the middleware chain 43 | h := middlewares[len(middlewares)-1](endpoint) 44 | for i := len(middlewares) - 2; i >= 0; i-- { 45 | h = middlewares[i](h) 46 | } 47 | 48 | return h 49 | } 50 | -------------------------------------------------------------------------------- /vendor/github.com/go-kit/kit/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Peter Bourgon 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /vendor/github.com/go-kit/kit/circuitbreaker/doc.go: -------------------------------------------------------------------------------- 1 | // Package circuitbreaker implements the circuit breaker pattern. 2 | // 3 | // Circuit breakers prevent thundering herds, and improve resiliency against 4 | // intermittent errors. Every client-side endpoint should be wrapped in a 5 | // circuit breaker. 6 | // 7 | // We provide several implementations in this package, but if you're looking 8 | // for guidance, Gobreaker is probably the best place to start. It has a 9 | // simple and intuitive API, and is well-tested. 10 | package circuitbreaker 11 | -------------------------------------------------------------------------------- /vendor/github.com/go-kit/kit/circuitbreaker/gobreaker.go: -------------------------------------------------------------------------------- 1 | package circuitbreaker 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/sony/gobreaker" 7 | 8 | "github.com/go-kit/kit/endpoint" 9 | ) 10 | 11 | // Gobreaker returns an endpoint.Middleware that implements the circuit 12 | // breaker pattern using the sony/gobreaker package. Only errors returned by 13 | // the wrapped endpoint count against the circuit breaker's error count. 14 | // 15 | // See http://godoc.org/github.com/sony/gobreaker for more information. 16 | func Gobreaker(cb *gobreaker.CircuitBreaker) endpoint.Middleware { 17 | return func(next endpoint.Endpoint) endpoint.Endpoint { 18 | return func(ctx context.Context, request interface{}) (interface{}, error) { 19 | return cb.Execute(func() (interface{}, error) { return next(ctx, request) }) 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /vendor/github.com/go-kit/kit/circuitbreaker/handy_breaker.go: -------------------------------------------------------------------------------- 1 | package circuitbreaker 2 | 3 | import ( 4 | "context" 5 | "time" 6 | 7 | "github.com/streadway/handy/breaker" 8 | 9 | "github.com/go-kit/kit/endpoint" 10 | ) 11 | 12 | // HandyBreaker returns an endpoint.Middleware that implements the circuit 13 | // breaker pattern using the streadway/handy/breaker package. Only errors 14 | // returned by the wrapped endpoint count against the circuit breaker's error 15 | // count. 16 | // 17 | // See http://godoc.org/github.com/streadway/handy/breaker for more 18 | // information. 19 | func HandyBreaker(cb breaker.Breaker) endpoint.Middleware { 20 | return func(next endpoint.Endpoint) endpoint.Endpoint { 21 | return func(ctx context.Context, request interface{}) (response interface{}, err error) { 22 | if !cb.Allow() { 23 | return nil, breaker.ErrCircuitOpen 24 | } 25 | 26 | defer func(begin time.Time) { 27 | if err == nil { 28 | cb.Success(time.Since(begin)) 29 | } else { 30 | cb.Failure(time.Since(begin)) 31 | } 32 | }(time.Now()) 33 | 34 | response, err = next(ctx, request) 35 | return 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /vendor/github.com/go-kit/kit/circuitbreaker/hystrix.go: -------------------------------------------------------------------------------- 1 | package circuitbreaker 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/afex/hystrix-go/hystrix" 7 | 8 | "github.com/go-kit/kit/endpoint" 9 | ) 10 | 11 | // Hystrix returns an endpoint.Middleware that implements the circuit 12 | // breaker pattern using the afex/hystrix-go package. 13 | // 14 | // When using this circuit breaker, please configure your commands separately. 15 | // 16 | // See https://godoc.org/github.com/afex/hystrix-go/hystrix for more 17 | // information. 18 | func Hystrix(commandName string) endpoint.Middleware { 19 | return func(next endpoint.Endpoint) endpoint.Endpoint { 20 | return func(ctx context.Context, request interface{}) (response interface{}, err error) { 21 | var resp interface{} 22 | if err := hystrix.Do(commandName, func() (err error) { 23 | resp, err = next(ctx, request) 24 | return err 25 | }, nil); err != nil { 26 | return nil, err 27 | } 28 | return resp, nil 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /vendor/github.com/go-kit/kit/endpoint/doc.go: -------------------------------------------------------------------------------- 1 | // Package endpoint defines an abstraction for RPCs. 2 | // 3 | // Endpoints are a fundamental building block for many Go kit components. 4 | // Endpoints are implemented by servers, and called by clients. 5 | package endpoint 6 | -------------------------------------------------------------------------------- /vendor/github.com/go-kit/kit/endpoint/endpoint.go: -------------------------------------------------------------------------------- 1 | package endpoint 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | // Endpoint is the fundamental building block of servers and clients. 8 | // It represents a single RPC method. 9 | type Endpoint func(ctx context.Context, request interface{}) (response interface{}, err error) 10 | 11 | // Nop is an endpoint that does nothing and returns a nil error. 12 | // Useful for tests. 13 | func Nop(context.Context, interface{}) (interface{}, error) { return struct{}{}, nil } 14 | 15 | // Middleware is a chainable behavior modifier for endpoints. 16 | type Middleware func(Endpoint) Endpoint 17 | 18 | // Chain is a helper function for composing middlewares. Requests will 19 | // traverse them in the order they're declared. That is, the first middleware 20 | // is treated as the outermost middleware. 21 | func Chain(outer Middleware, others ...Middleware) Middleware { 22 | return func(next Endpoint) Endpoint { 23 | for i := len(others) - 1; i >= 0; i-- { // reverse 24 | next = others[i](next) 25 | } 26 | return outer(next) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /vendor/github.com/go-kit/kit/log/json_logger.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "encoding" 5 | "encoding/json" 6 | "fmt" 7 | "io" 8 | "reflect" 9 | ) 10 | 11 | type jsonLogger struct { 12 | io.Writer 13 | } 14 | 15 | // NewJSONLogger returns a Logger that encodes keyvals to the Writer as a 16 | // single JSON object. Each log event produces no more than one call to 17 | // w.Write. The passed Writer must be safe for concurrent use by multiple 18 | // goroutines if the returned Logger will be used concurrently. 19 | func NewJSONLogger(w io.Writer) Logger { 20 | return &jsonLogger{w} 21 | } 22 | 23 | func (l *jsonLogger) Log(keyvals ...interface{}) error { 24 | n := (len(keyvals) + 1) / 2 // +1 to handle case when len is odd 25 | m := make(map[string]interface{}, n) 26 | for i := 0; i < len(keyvals); i += 2 { 27 | k := keyvals[i] 28 | var v interface{} = ErrMissingValue 29 | if i+1 < len(keyvals) { 30 | v = keyvals[i+1] 31 | } 32 | merge(m, k, v) 33 | } 34 | return json.NewEncoder(l.Writer).Encode(m) 35 | } 36 | 37 | func merge(dst map[string]interface{}, k, v interface{}) { 38 | var key string 39 | switch x := k.(type) { 40 | case string: 41 | key = x 42 | case fmt.Stringer: 43 | key = safeString(x) 44 | default: 45 | key = fmt.Sprint(x) 46 | } 47 | 48 | // We want json.Marshaler and encoding.TextMarshaller to take priority over 49 | // err.Error() and v.String(). But json.Marshall (called later) does that by 50 | // default so we force a no-op if it's one of those 2 case. 51 | switch x := v.(type) { 52 | case json.Marshaler: 53 | case encoding.TextMarshaler: 54 | case error: 55 | v = safeError(x) 56 | case fmt.Stringer: 57 | v = safeString(x) 58 | } 59 | 60 | dst[key] = v 61 | } 62 | 63 | func safeString(str fmt.Stringer) (s string) { 64 | defer func() { 65 | if panicVal := recover(); panicVal != nil { 66 | if v := reflect.ValueOf(str); v.Kind() == reflect.Ptr && v.IsNil() { 67 | s = "NULL" 68 | } else { 69 | panic(panicVal) 70 | } 71 | } 72 | }() 73 | s = str.String() 74 | return 75 | } 76 | 77 | func safeError(err error) (s interface{}) { 78 | defer func() { 79 | if panicVal := recover(); panicVal != nil { 80 | if v := reflect.ValueOf(err); v.Kind() == reflect.Ptr && v.IsNil() { 81 | s = nil 82 | } else { 83 | panic(panicVal) 84 | } 85 | } 86 | }() 87 | s = err.Error() 88 | return 89 | } 90 | -------------------------------------------------------------------------------- /vendor/github.com/go-kit/kit/log/logfmt_logger.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "sync" 7 | 8 | "github.com/go-logfmt/logfmt" 9 | ) 10 | 11 | type logfmtEncoder struct { 12 | *logfmt.Encoder 13 | buf bytes.Buffer 14 | } 15 | 16 | func (l *logfmtEncoder) Reset() { 17 | l.Encoder.Reset() 18 | l.buf.Reset() 19 | } 20 | 21 | var logfmtEncoderPool = sync.Pool{ 22 | New: func() interface{} { 23 | var enc logfmtEncoder 24 | enc.Encoder = logfmt.NewEncoder(&enc.buf) 25 | return &enc 26 | }, 27 | } 28 | 29 | type logfmtLogger struct { 30 | w io.Writer 31 | } 32 | 33 | // NewLogfmtLogger returns a logger that encodes keyvals to the Writer in 34 | // logfmt format. Each log event produces no more than one call to w.Write. 35 | // The passed Writer must be safe for concurrent use by multiple goroutines if 36 | // the returned Logger will be used concurrently. 37 | func NewLogfmtLogger(w io.Writer) Logger { 38 | return &logfmtLogger{w} 39 | } 40 | 41 | func (l logfmtLogger) Log(keyvals ...interface{}) error { 42 | enc := logfmtEncoderPool.Get().(*logfmtEncoder) 43 | enc.Reset() 44 | defer logfmtEncoderPool.Put(enc) 45 | 46 | if err := enc.EncodeKeyvals(keyvals...); err != nil { 47 | return err 48 | } 49 | 50 | // Add newline to the end of the buffer 51 | if err := enc.EndRecord(); err != nil { 52 | return err 53 | } 54 | 55 | // The Logger interface requires implementations to be safe for concurrent 56 | // use by multiple goroutines. For this implementation that means making 57 | // only one call to l.w.Write() for each call to Log. 58 | if _, err := l.w.Write(enc.buf.Bytes()); err != nil { 59 | return err 60 | } 61 | return nil 62 | } 63 | -------------------------------------------------------------------------------- /vendor/github.com/go-kit/kit/log/nop_logger.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | type nopLogger struct{} 4 | 5 | // NewNopLogger returns a logger that doesn't do anything. 6 | func NewNopLogger() Logger { return nopLogger{} } 7 | 8 | func (nopLogger) Log(...interface{}) error { return nil } 9 | -------------------------------------------------------------------------------- /vendor/github.com/go-kit/kit/metrics/README.md: -------------------------------------------------------------------------------- 1 | # package metrics 2 | 3 | `package metrics` provides a set of uniform interfaces for service instrumentation. 4 | It has 5 | [counters](http://prometheus.io/docs/concepts/metric_types/#counter), 6 | [gauges](http://prometheus.io/docs/concepts/metric_types/#gauge), and 7 | [histograms](http://prometheus.io/docs/concepts/metric_types/#histogram), 8 | and provides adapters to popular metrics packages, like 9 | [expvar](https://golang.org/pkg/expvar), 10 | [StatsD](https://github.com/etsy/statsd), and 11 | [Prometheus](https://prometheus.io). 12 | 13 | ## Rationale 14 | 15 | Code instrumentation is absolutely essential to achieve 16 | [observability](https://speakerdeck.com/mattheath/observability-in-micro-service-architectures) 17 | into a distributed system. 18 | Metrics and instrumentation tools have coalesced around a few well-defined idioms. 19 | `package metrics` provides a common, minimal interface those idioms for service authors. 20 | 21 | ## Usage 22 | 23 | A simple counter, exported via expvar. 24 | 25 | ```go 26 | import ( 27 | "github.com/go-kit/kit/metrics" 28 | "github.com/go-kit/kit/metrics/expvar" 29 | ) 30 | 31 | func main() { 32 | var myCount metrics.Counter 33 | myCount = expvar.NewCounter("my_count") 34 | myCount.Add(1) 35 | } 36 | ``` 37 | 38 | A histogram for request duration, 39 | exported via a Prometheus summary with dynamically-computed quantiles. 40 | 41 | ```go 42 | import ( 43 | "time" 44 | 45 | stdprometheus "github.com/prometheus/client_golang/prometheus" 46 | 47 | "github.com/go-kit/kit/metrics" 48 | "github.com/go-kit/kit/metrics/prometheus" 49 | ) 50 | 51 | func main() { 52 | var dur metrics.Histogram = prometheus.NewSummaryFrom(stdprometheus.SummaryOpts{ 53 | Namespace: "myservice", 54 | Subsystem: "api", 55 | Name: "request_duration_seconds", 56 | Help: "Total time spent serving requests.", 57 | }, []string{}) 58 | // ... 59 | } 60 | 61 | func handleRequest(dur metrics.Histogram) { 62 | defer func(begin time.Time) { dur.Observe(time.Since(begin).Seconds()) }(time.Now()) 63 | // handle request 64 | } 65 | ``` 66 | 67 | A gauge for the number of goroutines currently running, exported via StatsD. 68 | 69 | ```go 70 | import ( 71 | "net" 72 | "os" 73 | "runtime" 74 | "time" 75 | 76 | "github.com/go-kit/kit/metrics" 77 | "github.com/go-kit/kit/metrics/statsd" 78 | ) 79 | 80 | func main() { 81 | statsd := statsd.New("foo_svc.", log.NewNopLogger()) 82 | report := time.NewTicker(5 * time.Second) 83 | defer report.Stop() 84 | go statsd.SendLoop(report.C, "tcp", "statsd.internal:8125") 85 | goroutines := statsd.NewGauge("goroutine_count") 86 | go exportGoroutines(goroutines) 87 | // ... 88 | } 89 | 90 | func exportGoroutines(g metrics.Gauge) { 91 | for range time.Tick(time.Second) { 92 | g.Set(float64(runtime.NumGoroutine())) 93 | } 94 | } 95 | ``` 96 | 97 | For more information, see [the package documentation](https://godoc.org/github.com/go-kit/kit/metrics). 98 | -------------------------------------------------------------------------------- /vendor/github.com/go-kit/kit/metrics/debug.test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marcusolsson/goddd/7c414addc7a127df0b4ea38653be6a7c6380a37a/vendor/github.com/go-kit/kit/metrics/debug.test -------------------------------------------------------------------------------- /vendor/github.com/go-kit/kit/metrics/internal/lv/labelvalues.go: -------------------------------------------------------------------------------- 1 | package lv 2 | 3 | // LabelValues is a type alias that provides validation on its With method. 4 | // Metrics may include it as a member to help them satisfy With semantics and 5 | // save some code duplication. 6 | type LabelValues []string 7 | 8 | // With validates the input, and returns a new aggregate labelValues. 9 | func (lvs LabelValues) With(labelValues ...string) LabelValues { 10 | if len(labelValues)%2 != 0 { 11 | labelValues = append(labelValues, "unknown") 12 | } 13 | return append(lvs, labelValues...) 14 | } 15 | -------------------------------------------------------------------------------- /vendor/github.com/go-kit/kit/metrics/metrics.go: -------------------------------------------------------------------------------- 1 | package metrics 2 | 3 | // Counter describes a metric that accumulates values monotonically. 4 | // An example of a counter is the number of received HTTP requests. 5 | type Counter interface { 6 | With(labelValues ...string) Counter 7 | Add(delta float64) 8 | } 9 | 10 | // Gauge describes a metric that takes specific values over time. 11 | // An example of a gauge is the current depth of a job queue. 12 | type Gauge interface { 13 | With(labelValues ...string) Gauge 14 | Set(value float64) 15 | Add(delta float64) 16 | } 17 | 18 | // Histogram describes a metric that takes repeated observations of the same 19 | // kind of thing, and produces a statistical summary of those observations, 20 | // typically expressed as quantiles or buckets. An example of a histogram is 21 | // HTTP request latencies. 22 | type Histogram interface { 23 | With(labelValues ...string) Histogram 24 | Observe(value float64) 25 | } 26 | -------------------------------------------------------------------------------- /vendor/github.com/go-kit/kit/metrics/timer.go: -------------------------------------------------------------------------------- 1 | package metrics 2 | 3 | import "time" 4 | 5 | // Timer acts as a stopwatch, sending observations to a wrapped histogram. 6 | // It's a bit of helpful syntax sugar for h.Observe(time.Since(x)). 7 | type Timer struct { 8 | h Histogram 9 | t time.Time 10 | u time.Duration 11 | } 12 | 13 | // NewTimer wraps the given histogram and records the current time. 14 | func NewTimer(h Histogram) *Timer { 15 | return &Timer{ 16 | h: h, 17 | t: time.Now(), 18 | u: time.Second, 19 | } 20 | } 21 | 22 | // ObserveDuration captures the number of seconds since the timer was 23 | // constructed, and forwards that observation to the histogram. 24 | func (t *Timer) ObserveDuration() { 25 | d := float64(time.Since(t.t).Nanoseconds()) / float64(t.u) 26 | if d < 0 { 27 | d = 0 28 | } 29 | t.h.Observe(d) 30 | } 31 | 32 | // Unit sets the unit of the float64 emitted by the timer. 33 | // By default, the timer emits seconds. 34 | func (t *Timer) Unit(u time.Duration) { 35 | t.u = u 36 | } 37 | -------------------------------------------------------------------------------- /vendor/github.com/go-kit/kit/transport/http/doc.go: -------------------------------------------------------------------------------- 1 | // Package http provides a general purpose HTTP binding for endpoints. 2 | package http 3 | -------------------------------------------------------------------------------- /vendor/github.com/go-kit/kit/transport/http/encode_decode.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | ) 7 | 8 | // DecodeRequestFunc extracts a user-domain request object from an HTTP 9 | // request object. It's designed to be used in HTTP servers, for server-side 10 | // endpoints. One straightforward DecodeRequestFunc could be something that 11 | // JSON decodes from the request body to the concrete response type. 12 | type DecodeRequestFunc func(context.Context, *http.Request) (request interface{}, err error) 13 | 14 | // EncodeRequestFunc encodes the passed request object into the HTTP request 15 | // object. It's designed to be used in HTTP clients, for client-side 16 | // endpoints. One straightforward EncodeRequestFunc could something that JSON 17 | // encodes the object directly to the request body. 18 | type EncodeRequestFunc func(context.Context, *http.Request, interface{}) error 19 | 20 | // EncodeResponseFunc encodes the passed response object to the HTTP response 21 | // writer. It's designed to be used in HTTP servers, for server-side 22 | // endpoints. One straightforward EncodeResponseFunc could be something that 23 | // JSON encodes the object directly to the response body. 24 | type EncodeResponseFunc func(context.Context, http.ResponseWriter, interface{}) error 25 | 26 | // DecodeResponseFunc extracts a user-domain response object from an HTTP 27 | // response object. It's designed to be used in HTTP clients, for client-side 28 | // endpoints. One straightforward DecodeResponseFunc could be something that 29 | // JSON decodes from the response body to the concrete response type. 30 | type DecodeResponseFunc func(context.Context, *http.Response) (response interface{}, err error) 31 | -------------------------------------------------------------------------------- /vendor/github.com/go-logfmt/logfmt/.gitignore: -------------------------------------------------------------------------------- 1 | _testdata/ 2 | _testdata2/ 3 | logfmt-fuzz.zip 4 | logfmt.test.exe 5 | -------------------------------------------------------------------------------- /vendor/github.com/go-logfmt/logfmt/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | go: 4 | - 1.3 5 | - 1.4 6 | - 1.5 7 | - 1.6 8 | - tip 9 | 10 | before_install: 11 | - go get github.com/mattn/goveralls 12 | - go get golang.org/x/tools/cmd/cover 13 | 14 | script: 15 | - goveralls -service=travis-ci 16 | -------------------------------------------------------------------------------- /vendor/github.com/go-logfmt/logfmt/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 go-logfmt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /vendor/github.com/go-logfmt/logfmt/README.md: -------------------------------------------------------------------------------- 1 | [![GoDoc](https://godoc.org/github.com/go-logfmt/logfmt?status.svg)](https://godoc.org/github.com/go-logfmt/logfmt) 2 | [![Go Report Card](https://goreportcard.com/badge/go-logfmt/logfmt)](https://goreportcard.com/report/go-logfmt/logfmt) 3 | [![TravisCI](https://travis-ci.org/go-logfmt/logfmt.svg?branch=master)](https://travis-ci.org/go-logfmt/logfmt) 4 | [![Coverage Status](https://coveralls.io/repos/github/go-logfmt/logfmt/badge.svg?branch=master)](https://coveralls.io/github/go-logfmt/logfmt?branch=master) 5 | 6 | # logfmt 7 | 8 | Package logfmt implements utilities to marshal and unmarshal data in the [logfmt 9 | format](https://brandur.org/logfmt). It provides an API similar to 10 | [encoding/json](http://golang.org/pkg/encoding/json/) and 11 | [encoding/xml](http://golang.org/pkg/encoding/xml/). 12 | 13 | The logfmt format was first documented by Brandur Leach in [this 14 | article](https://brandur.org/logfmt). The format has not been formally 15 | standardized. The most authoritative public specification to date has been the 16 | documentation of a Go Language [package](http://godoc.org/github.com/kr/logfmt) 17 | written by Blake Mizerany and Keith Rarick. 18 | 19 | ## Goals 20 | 21 | This project attempts to conform as closely as possible to the prior art, while 22 | also removing ambiguity where necessary to provide well behaved encoder and 23 | decoder implementations. 24 | 25 | ## Non-goals 26 | 27 | This project does not attempt to formally standardize the logfmt format. In the 28 | event that logfmt is standardized this project would take conforming to the 29 | standard as a goal. 30 | 31 | ## Versioning 32 | 33 | Package logfmt publishes releases via [semver](http://semver.org/) compatible Git tags prefixed with a single 'v'. 34 | -------------------------------------------------------------------------------- /vendor/github.com/go-logfmt/logfmt/doc.go: -------------------------------------------------------------------------------- 1 | // Package logfmt implements utilities to marshal and unmarshal data in the 2 | // logfmt format. The logfmt format records key/value pairs in a way that 3 | // balances readability for humans and simplicity of computer parsing. It is 4 | // most commonly used as a more human friendly alternative to JSON for 5 | // structured logging. 6 | package logfmt 7 | -------------------------------------------------------------------------------- /vendor/github.com/go-logfmt/logfmt/fuzz.go: -------------------------------------------------------------------------------- 1 | // +build gofuzz 2 | 3 | package logfmt 4 | 5 | import ( 6 | "bufio" 7 | "bytes" 8 | "fmt" 9 | "io" 10 | "reflect" 11 | 12 | kr "github.com/kr/logfmt" 13 | ) 14 | 15 | // Fuzz checks reserialized data matches 16 | func Fuzz(data []byte) int { 17 | parsed, err := parse(data) 18 | if err != nil { 19 | return 0 20 | } 21 | var w1 bytes.Buffer 22 | if err = write(parsed, &w1); err != nil { 23 | panic(err) 24 | } 25 | parsed, err = parse(w1.Bytes()) 26 | if err != nil { 27 | panic(err) 28 | } 29 | var w2 bytes.Buffer 30 | if err = write(parsed, &w2); err != nil { 31 | panic(err) 32 | } 33 | if !bytes.Equal(w1.Bytes(), w2.Bytes()) { 34 | panic(fmt.Sprintf("reserialized data does not match:\n%q\n%q\n", w1.Bytes(), w2.Bytes())) 35 | } 36 | return 1 37 | } 38 | 39 | // FuzzVsKR checks go-logfmt/logfmt against kr/logfmt 40 | func FuzzVsKR(data []byte) int { 41 | parsed, err := parse(data) 42 | parsedKR, errKR := parseKR(data) 43 | 44 | // github.com/go-logfmt/logfmt is a stricter parser. It returns errors for 45 | // more inputs than github.com/kr/logfmt. Ignore any inputs that have a 46 | // stict error. 47 | if err != nil { 48 | return 0 49 | } 50 | 51 | // Fail if the more forgiving parser finds an error not found by the 52 | // stricter parser. 53 | if errKR != nil { 54 | panic(fmt.Sprintf("unmatched error: %v", errKR)) 55 | } 56 | 57 | if !reflect.DeepEqual(parsed, parsedKR) { 58 | panic(fmt.Sprintf("parsers disagree:\n%+v\n%+v\n", parsed, parsedKR)) 59 | } 60 | return 1 61 | } 62 | 63 | type kv struct { 64 | k, v []byte 65 | } 66 | 67 | func parse(data []byte) ([][]kv, error) { 68 | var got [][]kv 69 | dec := NewDecoder(bytes.NewReader(data)) 70 | for dec.ScanRecord() { 71 | var kvs []kv 72 | for dec.ScanKeyval() { 73 | kvs = append(kvs, kv{dec.Key(), dec.Value()}) 74 | } 75 | got = append(got, kvs) 76 | } 77 | return got, dec.Err() 78 | } 79 | 80 | func parseKR(data []byte) ([][]kv, error) { 81 | var ( 82 | s = bufio.NewScanner(bytes.NewReader(data)) 83 | err error 84 | h saveHandler 85 | got [][]kv 86 | ) 87 | for err == nil && s.Scan() { 88 | h.kvs = nil 89 | err = kr.Unmarshal(s.Bytes(), &h) 90 | got = append(got, h.kvs) 91 | } 92 | if err == nil { 93 | err = s.Err() 94 | } 95 | return got, err 96 | } 97 | 98 | type saveHandler struct { 99 | kvs []kv 100 | } 101 | 102 | func (h *saveHandler) HandleLogfmt(key, val []byte) error { 103 | if len(key) == 0 { 104 | key = nil 105 | } 106 | if len(val) == 0 { 107 | val = nil 108 | } 109 | h.kvs = append(h.kvs, kv{key, val}) 110 | return nil 111 | } 112 | 113 | func write(recs [][]kv, w io.Writer) error { 114 | enc := NewEncoder(w) 115 | for _, rec := range recs { 116 | for _, f := range rec { 117 | if err := enc.EncodeKeyval(f.k, f.v); err != nil { 118 | return err 119 | } 120 | } 121 | if err := enc.EndRecord(); err != nil { 122 | return err 123 | } 124 | } 125 | return nil 126 | } 127 | -------------------------------------------------------------------------------- /vendor/github.com/go-stack/stack/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | go: 4 | - 1.7.x 5 | - 1.8.x 6 | - 1.9.x 7 | - 1.10.x 8 | - 1.11.x 9 | - tip 10 | 11 | before_install: 12 | - go get github.com/mattn/goveralls 13 | 14 | script: 15 | - goveralls -service=travis-ci 16 | -------------------------------------------------------------------------------- /vendor/github.com/go-stack/stack/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Chris Hines 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/go-stack/stack/README.md: -------------------------------------------------------------------------------- 1 | [![GoDoc](https://godoc.org/github.com/go-stack/stack?status.svg)](https://godoc.org/github.com/go-stack/stack) 2 | [![Go Report Card](https://goreportcard.com/badge/go-stack/stack)](https://goreportcard.com/report/go-stack/stack) 3 | [![TravisCI](https://travis-ci.org/go-stack/stack.svg?branch=master)](https://travis-ci.org/go-stack/stack) 4 | [![Coverage Status](https://coveralls.io/repos/github/go-stack/stack/badge.svg?branch=master)](https://coveralls.io/github/go-stack/stack?branch=master) 5 | 6 | # stack 7 | 8 | Package stack implements utilities to capture, manipulate, and format call 9 | stacks. It provides a simpler API than package runtime. 10 | 11 | The implementation takes care of the minutia and special cases of interpreting 12 | the program counter (pc) values returned by runtime.Callers. 13 | 14 | ## Versioning 15 | 16 | Package stack publishes releases via [semver](http://semver.org/) compatible Git 17 | tags prefixed with a single 'v'. The master branch always contains the latest 18 | release. The develop branch contains unreleased commits. 19 | 20 | ## Formatting 21 | 22 | Package stack's types implement fmt.Formatter, which provides a simple and 23 | flexible way to declaratively configure formatting when used with logging or 24 | error tracking packages. 25 | 26 | ```go 27 | func DoTheThing() { 28 | c := stack.Caller(0) 29 | log.Print(c) // "source.go:10" 30 | log.Printf("%+v", c) // "pkg/path/source.go:10" 31 | log.Printf("%n", c) // "DoTheThing" 32 | 33 | s := stack.Trace().TrimRuntime() 34 | log.Print(s) // "[source.go:15 caller.go:42 main.go:14]" 35 | } 36 | ``` 37 | 38 | See the docs for all of the supported formatting options. 39 | -------------------------------------------------------------------------------- /vendor/github.com/go-stack/stack/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-stack/stack 2 | -------------------------------------------------------------------------------- /vendor/github.com/golang/protobuf/AUTHORS: -------------------------------------------------------------------------------- 1 | # This source code refers to The Go Authors for copyright purposes. 2 | # The master list of authors is in the main Go distribution, 3 | # visible at http://tip.golang.org/AUTHORS. 4 | -------------------------------------------------------------------------------- /vendor/github.com/golang/protobuf/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This source code was written by the Go contributors. 2 | # The master list of contributors is in the main Go distribution, 3 | # visible at http://tip.golang.org/CONTRIBUTORS. 4 | -------------------------------------------------------------------------------- /vendor/github.com/golang/protobuf/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2010 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | -------------------------------------------------------------------------------- /vendor/github.com/kr/logfmt/.gitignore: -------------------------------------------------------------------------------- 1 | *.test 2 | *.swp 3 | *.prof 4 | -------------------------------------------------------------------------------- /vendor/github.com/kr/logfmt/Readme: -------------------------------------------------------------------------------- 1 | Go package for parsing (and, eventually, generating) 2 | log lines in the logfmt style. 3 | 4 | See http://godoc.org/github.com/kr/logfmt for format, and other documentation and examples. 5 | 6 | Copyright (C) 2013 Keith Rarick, Blake Mizerany 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 13 | -------------------------------------------------------------------------------- /vendor/github.com/kr/logfmt/scanner.go: -------------------------------------------------------------------------------- 1 | package logfmt 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | ) 7 | 8 | var ErrUnterminatedString = errors.New("logfmt: unterminated string") 9 | 10 | func gotoScanner(data []byte, h Handler) (err error) { 11 | saveError := func(e error) { 12 | if err == nil { 13 | err = e 14 | } 15 | } 16 | 17 | var c byte 18 | var i int 19 | var m int 20 | var key []byte 21 | var val []byte 22 | var ok bool 23 | var esc bool 24 | 25 | garbage: 26 | if i == len(data) { 27 | return 28 | } 29 | 30 | c = data[i] 31 | switch { 32 | case c > ' ' && c != '"' && c != '=': 33 | key, val = nil, nil 34 | m = i 35 | i++ 36 | goto key 37 | default: 38 | i++ 39 | goto garbage 40 | } 41 | 42 | key: 43 | if i >= len(data) { 44 | if m >= 0 { 45 | key = data[m:i] 46 | saveError(h.HandleLogfmt(key, nil)) 47 | } 48 | return 49 | } 50 | 51 | c = data[i] 52 | switch { 53 | case c > ' ' && c != '"' && c != '=': 54 | i++ 55 | goto key 56 | case c == '=': 57 | key = data[m:i] 58 | i++ 59 | goto equal 60 | default: 61 | key = data[m:i] 62 | i++ 63 | saveError(h.HandleLogfmt(key, nil)) 64 | goto garbage 65 | } 66 | 67 | equal: 68 | if i >= len(data) { 69 | if m >= 0 { 70 | i-- 71 | key = data[m:i] 72 | saveError(h.HandleLogfmt(key, nil)) 73 | } 74 | return 75 | } 76 | 77 | c = data[i] 78 | switch { 79 | case c > ' ' && c != '"' && c != '=': 80 | m = i 81 | i++ 82 | goto ivalue 83 | case c == '"': 84 | m = i 85 | i++ 86 | esc = false 87 | goto qvalue 88 | default: 89 | if key != nil { 90 | saveError(h.HandleLogfmt(key, val)) 91 | } 92 | i++ 93 | goto garbage 94 | } 95 | 96 | ivalue: 97 | if i >= len(data) { 98 | if m >= 0 { 99 | val = data[m:i] 100 | saveError(h.HandleLogfmt(key, val)) 101 | } 102 | return 103 | } 104 | 105 | c = data[i] 106 | switch { 107 | case c > ' ' && c != '"' && c != '=': 108 | i++ 109 | goto ivalue 110 | default: 111 | val = data[m:i] 112 | saveError(h.HandleLogfmt(key, val)) 113 | i++ 114 | goto garbage 115 | } 116 | 117 | qvalue: 118 | if i >= len(data) { 119 | if m >= 0 { 120 | saveError(ErrUnterminatedString) 121 | } 122 | return 123 | } 124 | 125 | c = data[i] 126 | switch c { 127 | case '\\': 128 | i += 2 129 | esc = true 130 | goto qvalue 131 | case '"': 132 | i++ 133 | val = data[m:i] 134 | if esc { 135 | val, ok = unquoteBytes(val) 136 | if !ok { 137 | saveError(fmt.Errorf("logfmt: error unquoting bytes %q", string(val))) 138 | goto garbage 139 | } 140 | } else { 141 | val = val[1 : len(val)-1] 142 | } 143 | saveError(h.HandleLogfmt(key, val)) 144 | goto garbage 145 | default: 146 | i++ 147 | goto qvalue 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /vendor/github.com/kr/pretty/.gitignore: -------------------------------------------------------------------------------- 1 | [568].out 2 | _go* 3 | _test* 4 | _obj 5 | -------------------------------------------------------------------------------- /vendor/github.com/kr/pretty/License: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright 2012 Keith Rarick 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/kr/pretty/Readme: -------------------------------------------------------------------------------- 1 | package pretty 2 | 3 | import "github.com/kr/pretty" 4 | 5 | Package pretty provides pretty-printing for Go values. 6 | 7 | Documentation 8 | 9 | http://godoc.org/github.com/kr/pretty 10 | -------------------------------------------------------------------------------- /vendor/github.com/kr/pretty/go.mod: -------------------------------------------------------------------------------- 1 | module "github.com/kr/pretty" 2 | 3 | require "github.com/kr/text" v0.1.0 4 | -------------------------------------------------------------------------------- /vendor/github.com/kr/pretty/zero.go: -------------------------------------------------------------------------------- 1 | package pretty 2 | 3 | import ( 4 | "reflect" 5 | ) 6 | 7 | func nonzero(v reflect.Value) bool { 8 | switch v.Kind() { 9 | case reflect.Bool: 10 | return v.Bool() 11 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 12 | return v.Int() != 0 13 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 14 | return v.Uint() != 0 15 | case reflect.Float32, reflect.Float64: 16 | return v.Float() != 0 17 | case reflect.Complex64, reflect.Complex128: 18 | return v.Complex() != complex(0, 0) 19 | case reflect.String: 20 | return v.String() != "" 21 | case reflect.Struct: 22 | for i := 0; i < v.NumField(); i++ { 23 | if nonzero(getField(v, i)) { 24 | return true 25 | } 26 | } 27 | return false 28 | case reflect.Array: 29 | for i := 0; i < v.Len(); i++ { 30 | if nonzero(v.Index(i)) { 31 | return true 32 | } 33 | } 34 | return false 35 | case reflect.Map, reflect.Interface, reflect.Slice, reflect.Ptr, reflect.Chan, reflect.Func: 36 | return !v.IsNil() 37 | case reflect.UnsafePointer: 38 | return v.Pointer() != 0 39 | } 40 | return true 41 | } 42 | -------------------------------------------------------------------------------- /vendor/github.com/kr/text/License: -------------------------------------------------------------------------------- 1 | Copyright 2012 Keith Rarick 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /vendor/github.com/kr/text/Readme: -------------------------------------------------------------------------------- 1 | This is a Go package for manipulating paragraphs of text. 2 | 3 | See http://go.pkgdoc.org/github.com/kr/text for full documentation. 4 | -------------------------------------------------------------------------------- /vendor/github.com/kr/text/doc.go: -------------------------------------------------------------------------------- 1 | // Package text provides rudimentary functions for manipulating text in 2 | // paragraphs. 3 | package text 4 | -------------------------------------------------------------------------------- /vendor/github.com/kr/text/go.mod: -------------------------------------------------------------------------------- 1 | module "github.com/kr/text" 2 | 3 | require "github.com/kr/pty" v1.1.1 4 | -------------------------------------------------------------------------------- /vendor/github.com/kr/text/indent.go: -------------------------------------------------------------------------------- 1 | package text 2 | 3 | import ( 4 | "io" 5 | ) 6 | 7 | // Indent inserts prefix at the beginning of each non-empty line of s. The 8 | // end-of-line marker is NL. 9 | func Indent(s, prefix string) string { 10 | return string(IndentBytes([]byte(s), []byte(prefix))) 11 | } 12 | 13 | // IndentBytes inserts prefix at the beginning of each non-empty line of b. 14 | // The end-of-line marker is NL. 15 | func IndentBytes(b, prefix []byte) []byte { 16 | var res []byte 17 | bol := true 18 | for _, c := range b { 19 | if bol && c != '\n' { 20 | res = append(res, prefix...) 21 | } 22 | res = append(res, c) 23 | bol = c == '\n' 24 | } 25 | return res 26 | } 27 | 28 | // Writer indents each line of its input. 29 | type indentWriter struct { 30 | w io.Writer 31 | bol bool 32 | pre [][]byte 33 | sel int 34 | off int 35 | } 36 | 37 | // NewIndentWriter makes a new write filter that indents the input 38 | // lines. Each line is prefixed in order with the corresponding 39 | // element of pre. If there are more lines than elements, the last 40 | // element of pre is repeated for each subsequent line. 41 | func NewIndentWriter(w io.Writer, pre ...[]byte) io.Writer { 42 | return &indentWriter{ 43 | w: w, 44 | pre: pre, 45 | bol: true, 46 | } 47 | } 48 | 49 | // The only errors returned are from the underlying indentWriter. 50 | func (w *indentWriter) Write(p []byte) (n int, err error) { 51 | for _, c := range p { 52 | if w.bol { 53 | var i int 54 | i, err = w.w.Write(w.pre[w.sel][w.off:]) 55 | w.off += i 56 | if err != nil { 57 | return n, err 58 | } 59 | } 60 | _, err = w.w.Write([]byte{c}) 61 | if err != nil { 62 | return n, err 63 | } 64 | n++ 65 | w.bol = c == '\n' 66 | if w.bol { 67 | w.off = 0 68 | if w.sel < len(w.pre)-1 { 69 | w.sel++ 70 | } 71 | } 72 | } 73 | return n, nil 74 | } 75 | -------------------------------------------------------------------------------- /vendor/github.com/kr/text/wrap.go: -------------------------------------------------------------------------------- 1 | package text 2 | 3 | import ( 4 | "bytes" 5 | "math" 6 | ) 7 | 8 | var ( 9 | nl = []byte{'\n'} 10 | sp = []byte{' '} 11 | ) 12 | 13 | const defaultPenalty = 1e5 14 | 15 | // Wrap wraps s into a paragraph of lines of length lim, with minimal 16 | // raggedness. 17 | func Wrap(s string, lim int) string { 18 | return string(WrapBytes([]byte(s), lim)) 19 | } 20 | 21 | // WrapBytes wraps b into a paragraph of lines of length lim, with minimal 22 | // raggedness. 23 | func WrapBytes(b []byte, lim int) []byte { 24 | words := bytes.Split(bytes.Replace(bytes.TrimSpace(b), nl, sp, -1), sp) 25 | var lines [][]byte 26 | for _, line := range WrapWords(words, 1, lim, defaultPenalty) { 27 | lines = append(lines, bytes.Join(line, sp)) 28 | } 29 | return bytes.Join(lines, nl) 30 | } 31 | 32 | // WrapWords is the low-level line-breaking algorithm, useful if you need more 33 | // control over the details of the text wrapping process. For most uses, either 34 | // Wrap or WrapBytes will be sufficient and more convenient. 35 | // 36 | // WrapWords splits a list of words into lines with minimal "raggedness", 37 | // treating each byte as one unit, accounting for spc units between adjacent 38 | // words on each line, and attempting to limit lines to lim units. Raggedness 39 | // is the total error over all lines, where error is the square of the 40 | // difference of the length of the line and lim. Too-long lines (which only 41 | // happen when a single word is longer than lim units) have pen penalty units 42 | // added to the error. 43 | func WrapWords(words [][]byte, spc, lim, pen int) [][][]byte { 44 | n := len(words) 45 | 46 | length := make([][]int, n) 47 | for i := 0; i < n; i++ { 48 | length[i] = make([]int, n) 49 | length[i][i] = len(words[i]) 50 | for j := i + 1; j < n; j++ { 51 | length[i][j] = length[i][j-1] + spc + len(words[j]) 52 | } 53 | } 54 | 55 | nbrk := make([]int, n) 56 | cost := make([]int, n) 57 | for i := range cost { 58 | cost[i] = math.MaxInt32 59 | } 60 | for i := n - 1; i >= 0; i-- { 61 | if length[i][n-1] <= lim || i == n-1 { 62 | cost[i] = 0 63 | nbrk[i] = n 64 | } else { 65 | for j := i + 1; j < n; j++ { 66 | d := lim - length[i][j-1] 67 | c := d*d + cost[j] 68 | if length[i][j-1] > lim { 69 | c += pen // too-long lines get a worse penalty 70 | } 71 | if c < cost[i] { 72 | cost[i] = c 73 | nbrk[i] = j 74 | } 75 | } 76 | } 77 | } 78 | 79 | var lines [][][]byte 80 | i := 0 81 | for i < n { 82 | lines = append(lines, words[i:nbrk[i]]) 83 | i = nbrk[i] 84 | } 85 | return lines 86 | } 87 | -------------------------------------------------------------------------------- /vendor/github.com/matttproud/golang_protobuf_extensions/NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2012 Matt T. Proud (matt.proud@gmail.com) 2 | -------------------------------------------------------------------------------- /vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/.gitignore: -------------------------------------------------------------------------------- 1 | cover.dat 2 | -------------------------------------------------------------------------------- /vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | 3 | cover: 4 | go test -cover -v -coverprofile=cover.dat ./... 5 | go tool cover -func cover.dat 6 | 7 | .PHONY: cover 8 | -------------------------------------------------------------------------------- /vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/decode.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Matt T. Proud 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package pbutil 16 | 17 | import ( 18 | "encoding/binary" 19 | "errors" 20 | "io" 21 | 22 | "github.com/golang/protobuf/proto" 23 | ) 24 | 25 | var errInvalidVarint = errors.New("invalid varint32 encountered") 26 | 27 | // ReadDelimited decodes a message from the provided length-delimited stream, 28 | // where the length is encoded as 32-bit varint prefix to the message body. 29 | // It returns the total number of bytes read and any applicable error. This is 30 | // roughly equivalent to the companion Java API's 31 | // MessageLite#parseDelimitedFrom. As per the reader contract, this function 32 | // calls r.Read repeatedly as required until exactly one message including its 33 | // prefix is read and decoded (or an error has occurred). The function never 34 | // reads more bytes from the stream than required. The function never returns 35 | // an error if a message has been read and decoded correctly, even if the end 36 | // of the stream has been reached in doing so. In that case, any subsequent 37 | // calls return (0, io.EOF). 38 | func ReadDelimited(r io.Reader, m proto.Message) (n int, err error) { 39 | // Per AbstractParser#parsePartialDelimitedFrom with 40 | // CodedInputStream#readRawVarint32. 41 | var headerBuf [binary.MaxVarintLen32]byte 42 | var bytesRead, varIntBytes int 43 | var messageLength uint64 44 | for varIntBytes == 0 { // i.e. no varint has been decoded yet. 45 | if bytesRead >= len(headerBuf) { 46 | return bytesRead, errInvalidVarint 47 | } 48 | // We have to read byte by byte here to avoid reading more bytes 49 | // than required. Each read byte is appended to what we have 50 | // read before. 51 | newBytesRead, err := r.Read(headerBuf[bytesRead : bytesRead+1]) 52 | if newBytesRead == 0 { 53 | if err != nil { 54 | return bytesRead, err 55 | } 56 | // A Reader should not return (0, nil), but if it does, 57 | // it should be treated as no-op (according to the 58 | // Reader contract). So let's go on... 59 | continue 60 | } 61 | bytesRead += newBytesRead 62 | // Now present everything read so far to the varint decoder and 63 | // see if a varint can be decoded already. 64 | messageLength, varIntBytes = proto.DecodeVarint(headerBuf[:bytesRead]) 65 | } 66 | 67 | messageBuf := make([]byte, messageLength) 68 | newBytesRead, err := io.ReadFull(r, messageBuf) 69 | bytesRead += newBytesRead 70 | if err != nil { 71 | return bytesRead, err 72 | } 73 | 74 | return bytesRead, proto.Unmarshal(messageBuf, m) 75 | } 76 | -------------------------------------------------------------------------------- /vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Matt T. Proud 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package pbutil provides record length-delimited Protocol Buffer streaming. 16 | package pbutil 17 | -------------------------------------------------------------------------------- /vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/encode.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Matt T. Proud 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package pbutil 16 | 17 | import ( 18 | "encoding/binary" 19 | "io" 20 | 21 | "github.com/golang/protobuf/proto" 22 | ) 23 | 24 | // WriteDelimited encodes and dumps a message to the provided writer prefixed 25 | // with a 32-bit varint indicating the length of the encoded message, producing 26 | // a length-delimited record stream, which can be used to chain together 27 | // encoded messages of the same type together in a file. It returns the total 28 | // number of bytes written and any applicable error. This is roughly 29 | // equivalent to the companion Java API's MessageLite#writeDelimitedTo. 30 | func WriteDelimited(w io.Writer, m proto.Message) (n int, err error) { 31 | buffer, err := proto.Marshal(m) 32 | if err != nil { 33 | return 0, err 34 | } 35 | 36 | var buf [binary.MaxVarintLen32]byte 37 | encodedLength := binary.PutUvarint(buf[:], uint64(len(buffer))) 38 | 39 | sync, err := w.Write(buf[:encodedLength]) 40 | if err != nil { 41 | return sync, err 42 | } 43 | 44 | n, err = w.Write(buffer) 45 | return n + sync, err 46 | } 47 | -------------------------------------------------------------------------------- /vendor/github.com/pborman/uuid/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.9 5 | - tip 6 | 7 | script: 8 | - go test -v ./... 9 | -------------------------------------------------------------------------------- /vendor/github.com/pborman/uuid/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | We definitely welcome patches and contribution to this project! 4 | 5 | ### Legal requirements 6 | 7 | In order to protect both you and ourselves, you will need to sign the 8 | [Contributor License Agreement](https://cla.developers.google.com/clas). 9 | 10 | You may have already signed it for other Google projects. 11 | -------------------------------------------------------------------------------- /vendor/github.com/pborman/uuid/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | Paul Borman 2 | -------------------------------------------------------------------------------- /vendor/github.com/pborman/uuid/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009,2014 Google Inc. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/pborman/uuid/README.md: -------------------------------------------------------------------------------- 1 | This project was automatically exported from code.google.com/p/go-uuid 2 | 3 | # uuid ![build status](https://travis-ci.org/pborman/uuid.svg?branch=master) 4 | The uuid package generates and inspects UUIDs based on [RFC 4122](http://tools.ietf.org/html/rfc4122) and DCE 1.1: Authentication and Security Services. 5 | 6 | ###### Install 7 | `go get github.com/pborman/uuid` 8 | 9 | ###### Documentation 10 | [![GoDoc](https://godoc.org/github.com/pborman/uuid?status.svg)](http://godoc.org/github.com/pborman/uuid) 11 | 12 | Full `go doc` style documentation for the package can be viewed online without installing this package by using the GoDoc site here: 13 | http://godoc.org/github.com/pborman/uuid 14 | -------------------------------------------------------------------------------- /vendor/github.com/pborman/uuid/dce.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package uuid 6 | 7 | import ( 8 | "encoding/binary" 9 | "fmt" 10 | "os" 11 | ) 12 | 13 | // A Domain represents a Version 2 domain 14 | type Domain byte 15 | 16 | // Domain constants for DCE Security (Version 2) UUIDs. 17 | const ( 18 | Person = Domain(0) 19 | Group = Domain(1) 20 | Org = Domain(2) 21 | ) 22 | 23 | // NewDCESecurity returns a DCE Security (Version 2) UUID. 24 | // 25 | // The domain should be one of Person, Group or Org. 26 | // On a POSIX system the id should be the users UID for the Person 27 | // domain and the users GID for the Group. The meaning of id for 28 | // the domain Org or on non-POSIX systems is site defined. 29 | // 30 | // For a given domain/id pair the same token may be returned for up to 31 | // 7 minutes and 10 seconds. 32 | func NewDCESecurity(domain Domain, id uint32) UUID { 33 | uuid := NewUUID() 34 | if uuid != nil { 35 | uuid[6] = (uuid[6] & 0x0f) | 0x20 // Version 2 36 | uuid[9] = byte(domain) 37 | binary.BigEndian.PutUint32(uuid[0:], id) 38 | } 39 | return uuid 40 | } 41 | 42 | // NewDCEPerson returns a DCE Security (Version 2) UUID in the person 43 | // domain with the id returned by os.Getuid. 44 | // 45 | // NewDCEPerson(Person, uint32(os.Getuid())) 46 | func NewDCEPerson() UUID { 47 | return NewDCESecurity(Person, uint32(os.Getuid())) 48 | } 49 | 50 | // NewDCEGroup returns a DCE Security (Version 2) UUID in the group 51 | // domain with the id returned by os.Getgid. 52 | // 53 | // NewDCEGroup(Group, uint32(os.Getgid())) 54 | func NewDCEGroup() UUID { 55 | return NewDCESecurity(Group, uint32(os.Getgid())) 56 | } 57 | 58 | // Domain returns the domain for a Version 2 UUID or false. 59 | func (uuid UUID) Domain() (Domain, bool) { 60 | if v, _ := uuid.Version(); v != 2 { 61 | return 0, false 62 | } 63 | return Domain(uuid[9]), true 64 | } 65 | 66 | // Id returns the id for a Version 2 UUID or false. 67 | func (uuid UUID) Id() (uint32, bool) { 68 | if v, _ := uuid.Version(); v != 2 { 69 | return 0, false 70 | } 71 | return binary.BigEndian.Uint32(uuid[0:4]), true 72 | } 73 | 74 | func (d Domain) String() string { 75 | switch d { 76 | case Person: 77 | return "Person" 78 | case Group: 79 | return "Group" 80 | case Org: 81 | return "Org" 82 | } 83 | return fmt.Sprintf("Domain%d", int(d)) 84 | } 85 | -------------------------------------------------------------------------------- /vendor/github.com/pborman/uuid/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // The uuid package generates and inspects UUIDs. 6 | // 7 | // UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security Services. 8 | package uuid 9 | -------------------------------------------------------------------------------- /vendor/github.com/pborman/uuid/hash.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package uuid 6 | 7 | import ( 8 | "crypto/md5" 9 | "crypto/sha1" 10 | "hash" 11 | ) 12 | 13 | // Well known Name Space IDs and UUIDs 14 | var ( 15 | NameSpace_DNS = Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8") 16 | NameSpace_URL = Parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8") 17 | NameSpace_OID = Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8") 18 | NameSpace_X500 = Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8") 19 | NIL = Parse("00000000-0000-0000-0000-000000000000") 20 | ) 21 | 22 | // NewHash returns a new UUID derived from the hash of space concatenated with 23 | // data generated by h. The hash should be at least 16 byte in length. The 24 | // first 16 bytes of the hash are used to form the UUID. The version of the 25 | // UUID will be the lower 4 bits of version. NewHash is used to implement 26 | // NewMD5 and NewSHA1. 27 | func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID { 28 | h.Reset() 29 | h.Write(space) 30 | h.Write([]byte(data)) 31 | s := h.Sum(nil) 32 | uuid := make([]byte, 16) 33 | copy(uuid, s) 34 | uuid[6] = (uuid[6] & 0x0f) | uint8((version&0xf)<<4) 35 | uuid[8] = (uuid[8] & 0x3f) | 0x80 // RFC 4122 variant 36 | return uuid 37 | } 38 | 39 | // NewMD5 returns a new MD5 (Version 3) UUID based on the 40 | // supplied name space and data. 41 | // 42 | // NewHash(md5.New(), space, data, 3) 43 | func NewMD5(space UUID, data []byte) UUID { 44 | return NewHash(md5.New(), space, data, 3) 45 | } 46 | 47 | // NewSHA1 returns a new SHA1 (Version 5) UUID based on the 48 | // supplied name space and data. 49 | // 50 | // NewHash(sha1.New(), space, data, 5) 51 | func NewSHA1(space UUID, data []byte) UUID { 52 | return NewHash(sha1.New(), space, data, 5) 53 | } 54 | -------------------------------------------------------------------------------- /vendor/github.com/pborman/uuid/marshal.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Google Inc. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package uuid 6 | 7 | import ( 8 | "errors" 9 | "fmt" 10 | ) 11 | 12 | // MarshalText implements encoding.TextMarshaler. 13 | func (u UUID) MarshalText() ([]byte, error) { 14 | if len(u) != 16 { 15 | return nil, nil 16 | } 17 | var js [36]byte 18 | encodeHex(js[:], u) 19 | return js[:], nil 20 | } 21 | 22 | // UnmarshalText implements encoding.TextUnmarshaler. 23 | func (u *UUID) UnmarshalText(data []byte) error { 24 | if len(data) == 0 { 25 | return nil 26 | } 27 | id := Parse(string(data)) 28 | if id == nil { 29 | return errors.New("invalid UUID") 30 | } 31 | *u = id 32 | return nil 33 | } 34 | 35 | // MarshalBinary implements encoding.BinaryMarshaler. 36 | func (u UUID) MarshalBinary() ([]byte, error) { 37 | return u[:], nil 38 | } 39 | 40 | // UnmarshalBinary implements encoding.BinaryUnmarshaler. 41 | func (u *UUID) UnmarshalBinary(data []byte) error { 42 | if len(data) == 0 { 43 | return nil 44 | } 45 | if len(data) != 16 { 46 | return fmt.Errorf("invalid UUID (got %d bytes)", len(data)) 47 | } 48 | var id [16]byte 49 | copy(id[:], data) 50 | *u = id[:] 51 | return nil 52 | } 53 | 54 | // MarshalText implements encoding.TextMarshaler. 55 | func (u Array) MarshalText() ([]byte, error) { 56 | var js [36]byte 57 | encodeHex(js[:], u[:]) 58 | return js[:], nil 59 | } 60 | 61 | // UnmarshalText implements encoding.TextUnmarshaler. 62 | func (u *Array) UnmarshalText(data []byte) error { 63 | id := Parse(string(data)) 64 | if id == nil { 65 | return errors.New("invalid UUID") 66 | } 67 | *u = id.Array() 68 | return nil 69 | } 70 | 71 | // MarshalBinary implements encoding.BinaryMarshaler. 72 | func (u Array) MarshalBinary() ([]byte, error) { 73 | return u[:], nil 74 | } 75 | 76 | // UnmarshalBinary implements encoding.BinaryUnmarshaler. 77 | func (u *Array) UnmarshalBinary(data []byte) error { 78 | if len(data) != 16 { 79 | return fmt.Errorf("invalid UUID (got %d bytes)", len(data)) 80 | } 81 | copy(u[:], data) 82 | return nil 83 | } 84 | -------------------------------------------------------------------------------- /vendor/github.com/pborman/uuid/node.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package uuid 6 | 7 | import ( 8 | "sync" 9 | ) 10 | 11 | var ( 12 | nodeMu sync.Mutex 13 | ifname string // name of interface being used 14 | nodeID []byte // hardware for version 1 UUIDs 15 | ) 16 | 17 | // NodeInterface returns the name of the interface from which the NodeID was 18 | // derived. The interface "user" is returned if the NodeID was set by 19 | // SetNodeID. 20 | func NodeInterface() string { 21 | defer nodeMu.Unlock() 22 | nodeMu.Lock() 23 | return ifname 24 | } 25 | 26 | // SetNodeInterface selects the hardware address to be used for Version 1 UUIDs. 27 | // If name is "" then the first usable interface found will be used or a random 28 | // Node ID will be generated. If a named interface cannot be found then false 29 | // is returned. 30 | // 31 | // SetNodeInterface never fails when name is "". 32 | func SetNodeInterface(name string) bool { 33 | defer nodeMu.Unlock() 34 | nodeMu.Lock() 35 | if nodeID != nil { 36 | return true 37 | } 38 | return setNodeInterface(name) 39 | } 40 | 41 | func setNodeInterface(name string) bool { 42 | 43 | iname, addr := getHardwareInterface(name) // null implementation for js 44 | if iname != "" && setNodeID(addr) { 45 | ifname = iname 46 | return true 47 | } 48 | 49 | // We found no interfaces with a valid hardware address. If name 50 | // does not specify a specific interface generate a random Node ID 51 | // (section 4.1.6) 52 | if name == "" { 53 | if nodeID == nil { 54 | nodeID = make([]byte, 6) 55 | } 56 | randomBits(nodeID) 57 | return true 58 | } 59 | return false 60 | } 61 | 62 | // NodeID returns a slice of a copy of the current Node ID, setting the Node ID 63 | // if not already set. 64 | func NodeID() []byte { 65 | defer nodeMu.Unlock() 66 | nodeMu.Lock() 67 | if nodeID == nil { 68 | setNodeInterface("") 69 | } 70 | nid := make([]byte, 6) 71 | copy(nid, nodeID) 72 | return nid 73 | } 74 | 75 | // SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes 76 | // of id are used. If id is less than 6 bytes then false is returned and the 77 | // Node ID is not set. 78 | func SetNodeID(id []byte) bool { 79 | defer nodeMu.Unlock() 80 | nodeMu.Lock() 81 | if setNodeID(id) { 82 | ifname = "user" 83 | return true 84 | } 85 | return false 86 | } 87 | 88 | func setNodeID(id []byte) bool { 89 | if len(id) < 6 { 90 | return false 91 | } 92 | if nodeID == nil { 93 | nodeID = make([]byte, 6) 94 | } 95 | copy(nodeID, id) 96 | return true 97 | } 98 | 99 | // NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is 100 | // not valid. The NodeID is only well defined for version 1 and 2 UUIDs. 101 | func (uuid UUID) NodeID() []byte { 102 | if len(uuid) != 16 { 103 | return nil 104 | } 105 | node := make([]byte, 6) 106 | copy(node, uuid[10:]) 107 | return node 108 | } 109 | -------------------------------------------------------------------------------- /vendor/github.com/pborman/uuid/node_js.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build js 6 | 7 | package uuid 8 | 9 | // getHardwareInterface returns nil values for the JS version of the code. 10 | // This remvoves the "net" dependency, because it is not used in the browser. 11 | // Using the "net" library inflates the size of the transpiled JS code by 673k bytes. 12 | func getHardwareInterface(name string) (string, []byte) { return "", nil } 13 | -------------------------------------------------------------------------------- /vendor/github.com/pborman/uuid/node_net.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !js 6 | 7 | package uuid 8 | 9 | import "net" 10 | 11 | var interfaces []net.Interface // cached list of interfaces 12 | 13 | // getHardwareInterface returns the name and hardware address of interface name. 14 | // If name is "" then the name and hardware address of one of the system's 15 | // interfaces is returned. If no interfaces are found (name does not exist or 16 | // there are no interfaces) then "", nil is returned. 17 | // 18 | // Only addresses of at least 6 bytes are returned. 19 | func getHardwareInterface(name string) (string, []byte) { 20 | if interfaces == nil { 21 | var err error 22 | interfaces, err = net.Interfaces() 23 | if err != nil { 24 | return "", nil 25 | } 26 | } 27 | for _, ifs := range interfaces { 28 | if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) { 29 | if setNodeID(ifs.HardwareAddr) { 30 | ifname = ifs.Name 31 | return ifname, nodeID 32 | } 33 | } 34 | } 35 | return "", nil 36 | } 37 | -------------------------------------------------------------------------------- /vendor/github.com/pborman/uuid/sql.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google Inc. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package uuid 6 | 7 | import ( 8 | "database/sql/driver" 9 | "errors" 10 | "fmt" 11 | ) 12 | 13 | // Scan implements sql.Scanner so UUIDs can be read from databases transparently 14 | // Currently, database types that map to string and []byte are supported. Please 15 | // consult database-specific driver documentation for matching types. 16 | func (uuid *UUID) Scan(src interface{}) error { 17 | switch src.(type) { 18 | case string: 19 | // if an empty UUID comes from a table, we return a null UUID 20 | if src.(string) == "" { 21 | return nil 22 | } 23 | 24 | // see uuid.Parse for required string format 25 | parsed := Parse(src.(string)) 26 | 27 | if parsed == nil { 28 | return errors.New("Scan: invalid UUID format") 29 | } 30 | 31 | *uuid = parsed 32 | case []byte: 33 | b := src.([]byte) 34 | 35 | // if an empty UUID comes from a table, we return a null UUID 36 | if len(b) == 0 { 37 | return nil 38 | } 39 | 40 | // assumes a simple slice of bytes if 16 bytes 41 | // otherwise attempts to parse 42 | if len(b) == 16 { 43 | parsed := make([]byte, 16) 44 | copy(parsed, b) 45 | *uuid = UUID(parsed) 46 | } else { 47 | u := Parse(string(b)) 48 | 49 | if u == nil { 50 | return errors.New("Scan: invalid UUID format") 51 | } 52 | 53 | *uuid = u 54 | } 55 | 56 | default: 57 | return fmt.Errorf("Scan: unable to scan type %T into UUID", src) 58 | } 59 | 60 | return nil 61 | } 62 | 63 | // Value implements sql.Valuer so that UUIDs can be written to databases 64 | // transparently. Currently, UUIDs map to strings. Please consult 65 | // database-specific driver documentation for matching types. 66 | func (uuid UUID) Value() (driver.Value, error) { 67 | return uuid.String(), nil 68 | } 69 | -------------------------------------------------------------------------------- /vendor/github.com/pborman/uuid/util.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package uuid 6 | 7 | import ( 8 | "io" 9 | ) 10 | 11 | // randomBits completely fills slice b with random data. 12 | func randomBits(b []byte) { 13 | if _, err := io.ReadFull(rander, b); err != nil { 14 | panic(err.Error()) // rand should never fail 15 | } 16 | } 17 | 18 | // xvalues returns the value of a byte as a hexadecimal digit or 255. 19 | var xvalues = [256]byte{ 20 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 21 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 22 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 23 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255, 24 | 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, 25 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 26 | 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, 27 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 28 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 29 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 30 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 31 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 32 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 33 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 34 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 35 | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 36 | } 37 | 38 | // xtob converts the the first two hex bytes of x into a byte. 39 | func xtob(x string) (byte, bool) { 40 | b1 := xvalues[x[0]] 41 | b2 := xvalues[x[1]] 42 | return (b1 << 4) | b2, b1 != 255 && b2 != 255 43 | } 44 | -------------------------------------------------------------------------------- /vendor/github.com/pborman/uuid/version1.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package uuid 6 | 7 | import ( 8 | "encoding/binary" 9 | ) 10 | 11 | // NewUUID returns a Version 1 UUID based on the current NodeID and clock 12 | // sequence, and the current time. If the NodeID has not been set by SetNodeID 13 | // or SetNodeInterface then it will be set automatically. If the NodeID cannot 14 | // be set NewUUID returns nil. If clock sequence has not been set by 15 | // SetClockSequence then it will be set automatically. If GetTime fails to 16 | // return the current NewUUID returns nil. 17 | func NewUUID() UUID { 18 | SetNodeInterface("") 19 | 20 | now, seq, err := GetTime() 21 | if err != nil { 22 | return nil 23 | } 24 | 25 | uuid := make([]byte, 16) 26 | 27 | time_low := uint32(now & 0xffffffff) 28 | time_mid := uint16((now >> 32) & 0xffff) 29 | time_hi := uint16((now >> 48) & 0x0fff) 30 | time_hi |= 0x1000 // Version 1 31 | 32 | binary.BigEndian.PutUint32(uuid[0:], time_low) 33 | binary.BigEndian.PutUint16(uuid[4:], time_mid) 34 | binary.BigEndian.PutUint16(uuid[6:], time_hi) 35 | binary.BigEndian.PutUint16(uuid[8:], seq) 36 | copy(uuid[10:], nodeID) 37 | 38 | return uuid 39 | } 40 | -------------------------------------------------------------------------------- /vendor/github.com/pborman/uuid/version4.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package uuid 6 | 7 | // Random returns a Random (Version 4) UUID or panics. 8 | // 9 | // The strength of the UUIDs is based on the strength of the crypto/rand 10 | // package. 11 | // 12 | // A note about uniqueness derived from the UUID Wikipedia entry: 13 | // 14 | // Randomly generated UUIDs have 122 random bits. One's annual risk of being 15 | // hit by a meteorite is estimated to be one chance in 17 billion, that 16 | // means the probability is about 0.00000000006 (6 × 10−11), 17 | // equivalent to the odds of creating a few tens of trillions of UUIDs in a 18 | // year and having one duplicate. 19 | func NewRandom() UUID { 20 | uuid := make([]byte, 16) 21 | randomBits([]byte(uuid)) 22 | uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4 23 | uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10 24 | return uuid 25 | } 26 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/client_golang/AUTHORS.md: -------------------------------------------------------------------------------- 1 | The Prometheus project was started by Matt T. Proud (emeritus) and 2 | Julius Volz in 2012. 3 | 4 | Maintainers of this repository: 5 | 6 | * Björn Rabenstein 7 | 8 | The following individuals have contributed code to this repository 9 | (listed in alphabetical order): 10 | 11 | * Bernerd Schaefer 12 | * Björn Rabenstein 13 | * Daniel Bornkessel 14 | * Jeff Younker 15 | * Julius Volz 16 | * Matt T. Proud 17 | * Tobias Schmidt 18 | 19 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/client_golang/NOTICE: -------------------------------------------------------------------------------- 1 | Prometheus instrumentation library for Go applications 2 | Copyright 2012-2015 The Prometheus Authors 3 | 4 | This product includes software developed at 5 | SoundCloud Ltd. (http://soundcloud.com/). 6 | 7 | 8 | The following components are included in this product: 9 | 10 | perks - a fork of https://github.com/bmizerany/perks 11 | https://github.com/beorn7/perks 12 | Copyright 2013-2015 Blake Mizerany, Björn Rabenstein 13 | See https://github.com/beorn7/perks/blob/master/README.md for license details. 14 | 15 | Go support for Protocol Buffers - Google's data interchange format 16 | http://github.com/golang/protobuf/ 17 | Copyright 2010 The Go Authors 18 | See source code for license details. 19 | 20 | Support for streaming Protocol Buffer messages for the Go language (golang). 21 | https://github.com/matttproud/golang_protobuf_extensions 22 | Copyright 2013 Matt T. Proud 23 | Licensed under the Apache License, Version 2.0 24 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/client_golang/prometheus/.gitignore: -------------------------------------------------------------------------------- 1 | command-line-arguments.test 2 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/client_golang/prometheus/README.md: -------------------------------------------------------------------------------- 1 | See [![go-doc](https://godoc.org/github.com/prometheus/client_golang/prometheus?status.svg)](https://godoc.org/github.com/prometheus/client_golang/prometheus). 2 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/client_golang/prometheus/fnv.go: -------------------------------------------------------------------------------- 1 | package prometheus 2 | 3 | // Inline and byte-free variant of hash/fnv's fnv64a. 4 | 5 | const ( 6 | offset64 = 14695981039346656037 7 | prime64 = 1099511628211 8 | ) 9 | 10 | // hashNew initializies a new fnv64a hash value. 11 | func hashNew() uint64 { 12 | return offset64 13 | } 14 | 15 | // hashAdd adds a string to a fnv64a hash value, returning the updated hash. 16 | func hashAdd(h uint64, s string) uint64 { 17 | for i := 0; i < len(s); i++ { 18 | h ^= uint64(s[i]) 19 | h *= prime64 20 | } 21 | return h 22 | } 23 | 24 | // hashAddByte adds a byte to a fnv64a hash value, returning the updated hash. 25 | func hashAddByte(h uint64, b byte) uint64 { 26 | h ^= uint64(b) 27 | h *= prime64 28 | return h 29 | } 30 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/client_model/NOTICE: -------------------------------------------------------------------------------- 1 | Data model artifacts for Prometheus. 2 | Copyright 2012-2015 The Prometheus Authors 3 | 4 | This product includes software developed at 5 | SoundCloud Ltd. (http://soundcloud.com/). 6 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/NOTICE: -------------------------------------------------------------------------------- 1 | Common libraries shared by Prometheus Go components. 2 | Copyright 2015 The Prometheus Authors 3 | 4 | This product includes software developed at 5 | SoundCloud Ltd. (http://soundcloud.com/). 6 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/expfmt/encode.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package expfmt 15 | 16 | import ( 17 | "fmt" 18 | "io" 19 | "net/http" 20 | 21 | "github.com/golang/protobuf/proto" 22 | "github.com/matttproud/golang_protobuf_extensions/pbutil" 23 | "github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg" 24 | 25 | dto "github.com/prometheus/client_model/go" 26 | ) 27 | 28 | // Encoder types encode metric families into an underlying wire protocol. 29 | type Encoder interface { 30 | Encode(*dto.MetricFamily) error 31 | } 32 | 33 | type encoder func(*dto.MetricFamily) error 34 | 35 | func (e encoder) Encode(v *dto.MetricFamily) error { 36 | return e(v) 37 | } 38 | 39 | // Negotiate returns the Content-Type based on the given Accept header. 40 | // If no appropriate accepted type is found, FmtText is returned. 41 | func Negotiate(h http.Header) Format { 42 | for _, ac := range goautoneg.ParseAccept(h.Get(hdrAccept)) { 43 | // Check for protocol buffer 44 | if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol { 45 | switch ac.Params["encoding"] { 46 | case "delimited": 47 | return FmtProtoDelim 48 | case "text": 49 | return FmtProtoText 50 | case "compact-text": 51 | return FmtProtoCompact 52 | } 53 | } 54 | // Check for text format. 55 | ver := ac.Params["version"] 56 | if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") { 57 | return FmtText 58 | } 59 | } 60 | return FmtText 61 | } 62 | 63 | // NewEncoder returns a new encoder based on content type negotiation. 64 | func NewEncoder(w io.Writer, format Format) Encoder { 65 | switch format { 66 | case FmtProtoDelim: 67 | return encoder(func(v *dto.MetricFamily) error { 68 | _, err := pbutil.WriteDelimited(w, v) 69 | return err 70 | }) 71 | case FmtProtoCompact: 72 | return encoder(func(v *dto.MetricFamily) error { 73 | _, err := fmt.Fprintln(w, v.String()) 74 | return err 75 | }) 76 | case FmtProtoText: 77 | return encoder(func(v *dto.MetricFamily) error { 78 | _, err := fmt.Fprintln(w, proto.MarshalTextString(v)) 79 | return err 80 | }) 81 | case FmtText: 82 | return encoder(func(v *dto.MetricFamily) error { 83 | _, err := MetricFamilyToText(w, v) 84 | return err 85 | }) 86 | } 87 | panic("expfmt.NewEncoder: unknown format") 88 | } 89 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/expfmt/expfmt.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // Package expfmt contains tools for reading and writing Prometheus metrics. 15 | package expfmt 16 | 17 | // Format specifies the HTTP content type of the different wire protocols. 18 | type Format string 19 | 20 | // Constants to assemble the Content-Type values for the different wire protocols. 21 | const ( 22 | TextVersion = "0.0.4" 23 | ProtoType = `application/vnd.google.protobuf` 24 | ProtoProtocol = `io.prometheus.client.MetricFamily` 25 | ProtoFmt = ProtoType + "; proto=" + ProtoProtocol + ";" 26 | 27 | // The Content-Type values for the different wire protocols. 28 | FmtUnknown Format = `` 29 | FmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8` 30 | FmtProtoDelim Format = ProtoFmt + ` encoding=delimited` 31 | FmtProtoText Format = ProtoFmt + ` encoding=text` 32 | FmtProtoCompact Format = ProtoFmt + ` encoding=compact-text` 33 | ) 34 | 35 | const ( 36 | hdrContentType = "Content-Type" 37 | hdrAccept = "Accept" 38 | ) 39 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/expfmt/fuzz.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // Build only when actually fuzzing 15 | // +build gofuzz 16 | 17 | package expfmt 18 | 19 | import "bytes" 20 | 21 | // Fuzz text metric parser with with github.com/dvyukov/go-fuzz: 22 | // 23 | // go-fuzz-build github.com/prometheus/common/expfmt 24 | // go-fuzz -bin expfmt-fuzz.zip -workdir fuzz 25 | // 26 | // Further input samples should go in the folder fuzz/corpus. 27 | func Fuzz(in []byte) int { 28 | parser := TextParser{} 29 | _, err := parser.TextToMetricFamilies(bytes.NewReader(in)) 30 | 31 | if err != nil { 32 | return 0 33 | } 34 | 35 | return 1 36 | } 37 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/README.txt: -------------------------------------------------------------------------------- 1 | PACKAGE 2 | 3 | package goautoneg 4 | import "bitbucket.org/ww/goautoneg" 5 | 6 | HTTP Content-Type Autonegotiation. 7 | 8 | The functions in this package implement the behaviour specified in 9 | http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html 10 | 11 | Copyright (c) 2011, Open Knowledge Foundation Ltd. 12 | All rights reserved. 13 | 14 | Redistribution and use in source and binary forms, with or without 15 | modification, are permitted provided that the following conditions are 16 | met: 17 | 18 | Redistributions of source code must retain the above copyright 19 | notice, this list of conditions and the following disclaimer. 20 | 21 | Redistributions in binary form must reproduce the above copyright 22 | notice, this list of conditions and the following disclaimer in 23 | the documentation and/or other materials provided with the 24 | distribution. 25 | 26 | Neither the name of the Open Knowledge Foundation Ltd. nor the 27 | names of its contributors may be used to endorse or promote 28 | products derived from this software without specific prior written 29 | permission. 30 | 31 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 34 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 36 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 37 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 38 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 39 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 40 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 41 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 | 43 | 44 | FUNCTIONS 45 | 46 | func Negotiate(header string, alternatives []string) (content_type string) 47 | Negotiate the most appropriate content_type given the accept header 48 | and a list of alternatives. 49 | 50 | func ParseAccept(header string) (accept []Accept) 51 | Parse an Accept Header string returning a sorted list 52 | of clauses 53 | 54 | 55 | TYPES 56 | 57 | type Accept struct { 58 | Type, SubType string 59 | Q float32 60 | Params map[string]string 61 | } 62 | Structure to represent a clause in an HTTP Accept Header 63 | 64 | 65 | SUBDIRECTORIES 66 | 67 | .hg 68 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/model/fingerprinting.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package model 15 | 16 | import ( 17 | "fmt" 18 | "strconv" 19 | ) 20 | 21 | // Fingerprint provides a hash-capable representation of a Metric. 22 | // For our purposes, FNV-1A 64-bit is used. 23 | type Fingerprint uint64 24 | 25 | // FingerprintFromString transforms a string representation into a Fingerprint. 26 | func FingerprintFromString(s string) (Fingerprint, error) { 27 | num, err := strconv.ParseUint(s, 16, 64) 28 | return Fingerprint(num), err 29 | } 30 | 31 | // ParseFingerprint parses the input string into a fingerprint. 32 | func ParseFingerprint(s string) (Fingerprint, error) { 33 | num, err := strconv.ParseUint(s, 16, 64) 34 | if err != nil { 35 | return 0, err 36 | } 37 | return Fingerprint(num), nil 38 | } 39 | 40 | func (f Fingerprint) String() string { 41 | return fmt.Sprintf("%016x", uint64(f)) 42 | } 43 | 44 | // Fingerprints represents a collection of Fingerprint subject to a given 45 | // natural sorting scheme. It implements sort.Interface. 46 | type Fingerprints []Fingerprint 47 | 48 | // Len implements sort.Interface. 49 | func (f Fingerprints) Len() int { 50 | return len(f) 51 | } 52 | 53 | // Less implements sort.Interface. 54 | func (f Fingerprints) Less(i, j int) bool { 55 | return f[i] < f[j] 56 | } 57 | 58 | // Swap implements sort.Interface. 59 | func (f Fingerprints) Swap(i, j int) { 60 | f[i], f[j] = f[j], f[i] 61 | } 62 | 63 | // FingerprintSet is a set of Fingerprints. 64 | type FingerprintSet map[Fingerprint]struct{} 65 | 66 | // Equal returns true if both sets contain the same elements (and not more). 67 | func (s FingerprintSet) Equal(o FingerprintSet) bool { 68 | if len(s) != len(o) { 69 | return false 70 | } 71 | 72 | for k := range s { 73 | if _, ok := o[k]; !ok { 74 | return false 75 | } 76 | } 77 | 78 | return true 79 | } 80 | 81 | // Intersection returns the elements contained in both sets. 82 | func (s FingerprintSet) Intersection(o FingerprintSet) FingerprintSet { 83 | myLength, otherLength := len(s), len(o) 84 | if myLength == 0 || otherLength == 0 { 85 | return FingerprintSet{} 86 | } 87 | 88 | subSet := s 89 | superSet := o 90 | 91 | if otherLength < myLength { 92 | subSet = o 93 | superSet = s 94 | } 95 | 96 | out := FingerprintSet{} 97 | 98 | for k := range subSet { 99 | if _, ok := superSet[k]; ok { 100 | out[k] = struct{}{} 101 | } 102 | } 103 | 104 | return out 105 | } 106 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/model/fnv.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package model 15 | 16 | // Inline and byte-free variant of hash/fnv's fnv64a. 17 | 18 | const ( 19 | offset64 = 14695981039346656037 20 | prime64 = 1099511628211 21 | ) 22 | 23 | // hashNew initializies a new fnv64a hash value. 24 | func hashNew() uint64 { 25 | return offset64 26 | } 27 | 28 | // hashAdd adds a string to a fnv64a hash value, returning the updated hash. 29 | func hashAdd(h uint64, s string) uint64 { 30 | for i := 0; i < len(s); i++ { 31 | h ^= uint64(s[i]) 32 | h *= prime64 33 | } 34 | return h 35 | } 36 | 37 | // hashAddByte adds a byte to a fnv64a hash value, returning the updated hash. 38 | func hashAddByte(h uint64, b byte) uint64 { 39 | h ^= uint64(b) 40 | h *= prime64 41 | return h 42 | } 43 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/common/model/model.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // Package model contains common data structures that are shared across 15 | // Prometheus components and libraries. 16 | package model 17 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/.gitignore: -------------------------------------------------------------------------------- 1 | /fixtures/ 2 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: go 4 | 5 | go: 6 | - 1.9.x 7 | - 1.10.x 8 | 9 | go_import_path: github.com/prometheus/procfs 10 | 11 | script: 12 | - make style check_license vet test staticcheck 13 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Prometheus uses GitHub to manage reviews of pull requests. 4 | 5 | * If you have a trivial fix or improvement, go ahead and create a pull request, 6 | addressing (with `@...`) the maintainer of this repository (see 7 | [MAINTAINERS.md](MAINTAINERS.md)) in the description of the pull request. 8 | 9 | * If you plan to do something more involved, first discuss your ideas 10 | on our [mailing list](https://groups.google.com/forum/?fromgroups#!forum/prometheus-developers). 11 | This will avoid unnecessary work and surely give you and us a good deal 12 | of inspiration. 13 | 14 | * Relevant coding style guidelines are the [Go Code Review 15 | Comments](https://code.google.com/p/go-wiki/wiki/CodeReviewComments) 16 | and the _Formatting and style_ section of Peter Bourgon's [Go: Best 17 | Practices for Production 18 | Environments](http://peter.bourgon.org/go-in-production/#formatting-and-style). 19 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/MAINTAINERS.md: -------------------------------------------------------------------------------- 1 | * Tobias Schmidt 2 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2018 The Prometheus Authors 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License. 13 | 14 | # Ensure GOBIN is not set during build so that promu is installed to the correct path 15 | unexport GOBIN 16 | 17 | GO ?= go 18 | GOFMT ?= $(GO)fmt 19 | FIRST_GOPATH := $(firstword $(subst :, ,$(shell $(GO) env GOPATH))) 20 | STATICCHECK := $(FIRST_GOPATH)/bin/staticcheck 21 | pkgs = $(shell $(GO) list ./... | grep -v /vendor/) 22 | 23 | PREFIX ?= $(shell pwd) 24 | BIN_DIR ?= $(shell pwd) 25 | 26 | ifdef DEBUG 27 | bindata_flags = -debug 28 | endif 29 | 30 | STATICCHECK_IGNORE = 31 | 32 | all: format staticcheck build test 33 | 34 | style: 35 | @echo ">> checking code style" 36 | @! $(GOFMT) -d $(shell find . -path ./vendor -prune -o -name '*.go' -print) | grep '^' 37 | 38 | check_license: 39 | @echo ">> checking license header" 40 | @./scripts/check_license.sh 41 | 42 | test: fixtures/.unpacked sysfs/fixtures/.unpacked 43 | @echo ">> running all tests" 44 | @$(GO) test -race $(shell $(GO) list ./... | grep -v /vendor/ | grep -v examples) 45 | 46 | format: 47 | @echo ">> formatting code" 48 | @$(GO) fmt $(pkgs) 49 | 50 | vet: 51 | @echo ">> vetting code" 52 | @$(GO) vet $(pkgs) 53 | 54 | staticcheck: $(STATICCHECK) 55 | @echo ">> running staticcheck" 56 | @$(STATICCHECK) -ignore "$(STATICCHECK_IGNORE)" $(pkgs) 57 | 58 | %/.unpacked: %.ttar 59 | ./ttar -C $(dir $*) -x -f $*.ttar 60 | touch $@ 61 | 62 | update_fixtures: fixtures.ttar sysfs/fixtures.ttar 63 | 64 | %fixtures.ttar: %/fixtures 65 | rm -v $(dir $*)fixtures/.unpacked 66 | ./ttar -C $(dir $*) -c -f $*fixtures.ttar fixtures/ 67 | 68 | $(FIRST_GOPATH)/bin/staticcheck: 69 | @GOOS= GOARCH= $(GO) get -u honnef.co/go/tools/cmd/staticcheck 70 | 71 | .PHONY: all style check_license format test vet staticcheck 72 | 73 | # Declaring the binaries at their default locations as PHONY targets is a hack 74 | # to ensure the latest version is downloaded on every make execution. 75 | # If this is not desired, copy/symlink these binaries to a different path and 76 | # set the respective environment variables. 77 | .PHONY: $(GOPATH)/bin/staticcheck 78 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/NOTICE: -------------------------------------------------------------------------------- 1 | procfs provides functions to retrieve system, kernel and process 2 | metrics from the pseudo-filesystem proc. 3 | 4 | Copyright 2014-2015 The Prometheus Authors 5 | 6 | This product includes software developed at 7 | SoundCloud Ltd. (http://soundcloud.com/). 8 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/README.md: -------------------------------------------------------------------------------- 1 | # procfs 2 | 3 | This procfs package provides functions to retrieve system, kernel and process 4 | metrics from the pseudo-filesystem proc. 5 | 6 | *WARNING*: This package is a work in progress. Its API may still break in 7 | backwards-incompatible ways without warnings. Use it at your own risk. 8 | 9 | [![GoDoc](https://godoc.org/github.com/prometheus/procfs?status.png)](https://godoc.org/github.com/prometheus/procfs) 10 | [![Build Status](https://travis-ci.org/prometheus/procfs.svg?branch=master)](https://travis-ci.org/prometheus/procfs) 11 | [![Go Report Card](https://goreportcard.com/badge/github.com/prometheus/procfs)](https://goreportcard.com/report/github.com/prometheus/procfs) 12 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/buddyinfo.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package procfs 15 | 16 | import ( 17 | "bufio" 18 | "fmt" 19 | "io" 20 | "os" 21 | "strconv" 22 | "strings" 23 | ) 24 | 25 | // A BuddyInfo is the details parsed from /proc/buddyinfo. 26 | // The data is comprised of an array of free fragments of each size. 27 | // The sizes are 2^n*PAGE_SIZE, where n is the array index. 28 | type BuddyInfo struct { 29 | Node string 30 | Zone string 31 | Sizes []float64 32 | } 33 | 34 | // NewBuddyInfo reads the buddyinfo statistics. 35 | func NewBuddyInfo() ([]BuddyInfo, error) { 36 | fs, err := NewFS(DefaultMountPoint) 37 | if err != nil { 38 | return nil, err 39 | } 40 | 41 | return fs.NewBuddyInfo() 42 | } 43 | 44 | // NewBuddyInfo reads the buddyinfo statistics from the specified `proc` filesystem. 45 | func (fs FS) NewBuddyInfo() ([]BuddyInfo, error) { 46 | file, err := os.Open(fs.Path("buddyinfo")) 47 | if err != nil { 48 | return nil, err 49 | } 50 | defer file.Close() 51 | 52 | return parseBuddyInfo(file) 53 | } 54 | 55 | func parseBuddyInfo(r io.Reader) ([]BuddyInfo, error) { 56 | var ( 57 | buddyInfo = []BuddyInfo{} 58 | scanner = bufio.NewScanner(r) 59 | bucketCount = -1 60 | ) 61 | 62 | for scanner.Scan() { 63 | var err error 64 | line := scanner.Text() 65 | parts := strings.Fields(line) 66 | 67 | if len(parts) < 4 { 68 | return nil, fmt.Errorf("invalid number of fields when parsing buddyinfo") 69 | } 70 | 71 | node := strings.TrimRight(parts[1], ",") 72 | zone := strings.TrimRight(parts[3], ",") 73 | arraySize := len(parts[4:]) 74 | 75 | if bucketCount == -1 { 76 | bucketCount = arraySize 77 | } else { 78 | if bucketCount != arraySize { 79 | return nil, fmt.Errorf("mismatch in number of buddyinfo buckets, previous count %d, new count %d", bucketCount, arraySize) 80 | } 81 | } 82 | 83 | sizes := make([]float64, arraySize) 84 | for i := 0; i < arraySize; i++ { 85 | sizes[i], err = strconv.ParseFloat(parts[i+4], 64) 86 | if err != nil { 87 | return nil, fmt.Errorf("invalid value in buddyinfo: %s", err) 88 | } 89 | } 90 | 91 | buddyInfo = append(buddyInfo, BuddyInfo{node, zone, sizes}) 92 | } 93 | 94 | return buddyInfo, scanner.Err() 95 | } 96 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Prometheus Team 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // Package procfs provides functions to retrieve system, kernel and process 15 | // metrics from the pseudo-filesystem proc. 16 | // 17 | // Example: 18 | // 19 | // package main 20 | // 21 | // import ( 22 | // "fmt" 23 | // "log" 24 | // 25 | // "github.com/prometheus/procfs" 26 | // ) 27 | // 28 | // func main() { 29 | // p, err := procfs.Self() 30 | // if err != nil { 31 | // log.Fatalf("could not get process: %s", err) 32 | // } 33 | // 34 | // stat, err := p.NewStat() 35 | // if err != nil { 36 | // log.Fatalf("could not get process stat: %s", err) 37 | // } 38 | // 39 | // fmt.Printf("command: %s\n", stat.Comm) 40 | // fmt.Printf("cpu time: %fs\n", stat.CPUTime()) 41 | // fmt.Printf("vsize: %dB\n", stat.VirtualMemory()) 42 | // fmt.Printf("rss: %dB\n", stat.ResidentMemory()) 43 | // } 44 | // 45 | package procfs 46 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/fs.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package procfs 15 | 16 | import ( 17 | "fmt" 18 | "os" 19 | "path" 20 | 21 | "github.com/prometheus/procfs/nfs" 22 | "github.com/prometheus/procfs/xfs" 23 | ) 24 | 25 | // FS represents the pseudo-filesystem proc, which provides an interface to 26 | // kernel data structures. 27 | type FS string 28 | 29 | // DefaultMountPoint is the common mount point of the proc filesystem. 30 | const DefaultMountPoint = "/proc" 31 | 32 | // NewFS returns a new FS mounted under the given mountPoint. It will error 33 | // if the mount point can't be read. 34 | func NewFS(mountPoint string) (FS, error) { 35 | info, err := os.Stat(mountPoint) 36 | if err != nil { 37 | return "", fmt.Errorf("could not read %s: %s", mountPoint, err) 38 | } 39 | if !info.IsDir() { 40 | return "", fmt.Errorf("mount point %s is not a directory", mountPoint) 41 | } 42 | 43 | return FS(mountPoint), nil 44 | } 45 | 46 | // Path returns the path of the given subsystem relative to the procfs root. 47 | func (fs FS) Path(p ...string) string { 48 | return path.Join(append([]string{string(fs)}, p...)...) 49 | } 50 | 51 | // XFSStats retrieves XFS filesystem runtime statistics. 52 | func (fs FS) XFSStats() (*xfs.Stats, error) { 53 | f, err := os.Open(fs.Path("fs/xfs/stat")) 54 | if err != nil { 55 | return nil, err 56 | } 57 | defer f.Close() 58 | 59 | return xfs.ParseStats(f) 60 | } 61 | 62 | // NFSClientRPCStats retrieves NFS client RPC statistics. 63 | func (fs FS) NFSClientRPCStats() (*nfs.ClientRPCStats, error) { 64 | f, err := os.Open(fs.Path("net/rpc/nfs")) 65 | if err != nil { 66 | return nil, err 67 | } 68 | defer f.Close() 69 | 70 | return nfs.ParseClientRPCStats(f) 71 | } 72 | 73 | // NFSdServerRPCStats retrieves NFS daemon RPC statistics. 74 | func (fs FS) NFSdServerRPCStats() (*nfs.ServerRPCStats, error) { 75 | f, err := os.Open(fs.Path("net/rpc/nfsd")) 76 | if err != nil { 77 | return nil, err 78 | } 79 | defer f.Close() 80 | 81 | return nfs.ParseServerRPCStats(f) 82 | } 83 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/internal/util/parse.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package util 15 | 16 | import "strconv" 17 | 18 | // ParseUint32s parses a slice of strings into a slice of uint32s. 19 | func ParseUint32s(ss []string) ([]uint32, error) { 20 | us := make([]uint32, 0, len(ss)) 21 | for _, s := range ss { 22 | u, err := strconv.ParseUint(s, 10, 32) 23 | if err != nil { 24 | return nil, err 25 | } 26 | 27 | us = append(us, uint32(u)) 28 | } 29 | 30 | return us, nil 31 | } 32 | 33 | // ParseUint64s parses a slice of strings into a slice of uint64s. 34 | func ParseUint64s(ss []string) ([]uint64, error) { 35 | us := make([]uint64, 0, len(ss)) 36 | for _, s := range ss { 37 | u, err := strconv.ParseUint(s, 10, 64) 38 | if err != nil { 39 | return nil, err 40 | } 41 | 42 | us = append(us, u) 43 | } 44 | 45 | return us, nil 46 | } 47 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/nfs/parse_nfs.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package nfs 15 | 16 | import ( 17 | "bufio" 18 | "fmt" 19 | "io" 20 | "strings" 21 | 22 | "github.com/prometheus/procfs/internal/util" 23 | ) 24 | 25 | // ParseClientRPCStats returns stats read from /proc/net/rpc/nfs 26 | func ParseClientRPCStats(r io.Reader) (*ClientRPCStats, error) { 27 | stats := &ClientRPCStats{} 28 | 29 | scanner := bufio.NewScanner(r) 30 | for scanner.Scan() { 31 | line := scanner.Text() 32 | parts := strings.Fields(scanner.Text()) 33 | // require at least 34 | if len(parts) < 2 { 35 | return nil, fmt.Errorf("invalid NFS metric line %q", line) 36 | } 37 | 38 | values, err := util.ParseUint64s(parts[1:]) 39 | if err != nil { 40 | return nil, fmt.Errorf("error parsing NFS metric line: %s", err) 41 | } 42 | 43 | switch metricLine := parts[0]; metricLine { 44 | case "net": 45 | stats.Network, err = parseNetwork(values) 46 | case "rpc": 47 | stats.ClientRPC, err = parseClientRPC(values) 48 | case "proc2": 49 | stats.V2Stats, err = parseV2Stats(values) 50 | case "proc3": 51 | stats.V3Stats, err = parseV3Stats(values) 52 | case "proc4": 53 | stats.ClientV4Stats, err = parseClientV4Stats(values) 54 | default: 55 | return nil, fmt.Errorf("unknown NFS metric line %q", metricLine) 56 | } 57 | if err != nil { 58 | return nil, fmt.Errorf("errors parsing NFS metric line: %s", err) 59 | } 60 | } 61 | 62 | if err := scanner.Err(); err != nil { 63 | return nil, fmt.Errorf("error scanning NFS file: %s", err) 64 | } 65 | 66 | return stats, nil 67 | } 68 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/nfs/parse_nfsd.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package nfs 15 | 16 | import ( 17 | "bufio" 18 | "fmt" 19 | "io" 20 | "strings" 21 | 22 | "github.com/prometheus/procfs/internal/util" 23 | ) 24 | 25 | // ParseServerRPCStats returns stats read from /proc/net/rpc/nfsd 26 | func ParseServerRPCStats(r io.Reader) (*ServerRPCStats, error) { 27 | stats := &ServerRPCStats{} 28 | 29 | scanner := bufio.NewScanner(r) 30 | for scanner.Scan() { 31 | line := scanner.Text() 32 | parts := strings.Fields(scanner.Text()) 33 | // require at least 34 | if len(parts) < 2 { 35 | return nil, fmt.Errorf("invalid NFSd metric line %q", line) 36 | } 37 | label := parts[0] 38 | 39 | var values []uint64 40 | var err error 41 | if label == "th" { 42 | if len(parts) < 3 { 43 | return nil, fmt.Errorf("invalid NFSd th metric line %q", line) 44 | } 45 | values, err = util.ParseUint64s(parts[1:3]) 46 | } else { 47 | values, err = util.ParseUint64s(parts[1:]) 48 | } 49 | if err != nil { 50 | return nil, fmt.Errorf("error parsing NFSd metric line: %s", err) 51 | } 52 | 53 | switch metricLine := parts[0]; metricLine { 54 | case "rc": 55 | stats.ReplyCache, err = parseReplyCache(values) 56 | case "fh": 57 | stats.FileHandles, err = parseFileHandles(values) 58 | case "io": 59 | stats.InputOutput, err = parseInputOutput(values) 60 | case "th": 61 | stats.Threads, err = parseThreads(values) 62 | case "ra": 63 | stats.ReadAheadCache, err = parseReadAheadCache(values) 64 | case "net": 65 | stats.Network, err = parseNetwork(values) 66 | case "rpc": 67 | stats.ServerRPC, err = parseServerRPC(values) 68 | case "proc2": 69 | stats.V2Stats, err = parseV2Stats(values) 70 | case "proc3": 71 | stats.V3Stats, err = parseV3Stats(values) 72 | case "proc4": 73 | stats.ServerV4Stats, err = parseServerV4Stats(values) 74 | case "proc4ops": 75 | stats.V4Ops, err = parseV4Ops(values) 76 | default: 77 | return nil, fmt.Errorf("unknown NFSd metric line %q", metricLine) 78 | } 79 | if err != nil { 80 | return nil, fmt.Errorf("errors parsing NFSd metric line: %s", err) 81 | } 82 | } 83 | 84 | if err := scanner.Err(); err != nil { 85 | return nil, fmt.Errorf("error scanning NFSd file: %s", err) 86 | } 87 | 88 | return stats, nil 89 | } 90 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/proc_io.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package procfs 15 | 16 | import ( 17 | "fmt" 18 | "io/ioutil" 19 | "os" 20 | ) 21 | 22 | // ProcIO models the content of /proc//io. 23 | type ProcIO struct { 24 | // Chars read. 25 | RChar uint64 26 | // Chars written. 27 | WChar uint64 28 | // Read syscalls. 29 | SyscR uint64 30 | // Write syscalls. 31 | SyscW uint64 32 | // Bytes read. 33 | ReadBytes uint64 34 | // Bytes written. 35 | WriteBytes uint64 36 | // Bytes written, but taking into account truncation. See 37 | // Documentation/filesystems/proc.txt in the kernel sources for 38 | // detailed explanation. 39 | CancelledWriteBytes int64 40 | } 41 | 42 | // NewIO creates a new ProcIO instance from a given Proc instance. 43 | func (p Proc) NewIO() (ProcIO, error) { 44 | pio := ProcIO{} 45 | 46 | f, err := os.Open(p.path("io")) 47 | if err != nil { 48 | return pio, err 49 | } 50 | defer f.Close() 51 | 52 | data, err := ioutil.ReadAll(f) 53 | if err != nil { 54 | return pio, err 55 | } 56 | 57 | ioFormat := "rchar: %d\nwchar: %d\nsyscr: %d\nsyscw: %d\n" + 58 | "read_bytes: %d\nwrite_bytes: %d\n" + 59 | "cancelled_write_bytes: %d\n" 60 | 61 | _, err = fmt.Sscanf(string(data), ioFormat, &pio.RChar, &pio.WChar, &pio.SyscR, 62 | &pio.SyscW, &pio.ReadBytes, &pio.WriteBytes, &pio.CancelledWriteBytes) 63 | 64 | return pio, err 65 | } 66 | -------------------------------------------------------------------------------- /vendor/github.com/prometheus/procfs/proc_ns.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Prometheus Authors 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package procfs 15 | 16 | import ( 17 | "fmt" 18 | "os" 19 | "strconv" 20 | "strings" 21 | ) 22 | 23 | // Namespace represents a single namespace of a process. 24 | type Namespace struct { 25 | Type string // Namespace type. 26 | Inode uint32 // Inode number of the namespace. If two processes are in the same namespace their inodes will match. 27 | } 28 | 29 | // Namespaces contains all of the namespaces that the process is contained in. 30 | type Namespaces map[string]Namespace 31 | 32 | // NewNamespaces reads from /proc/[pid/ns/* to get the namespaces of which the 33 | // process is a member. 34 | func (p Proc) NewNamespaces() (Namespaces, error) { 35 | d, err := os.Open(p.path("ns")) 36 | if err != nil { 37 | return nil, err 38 | } 39 | defer d.Close() 40 | 41 | names, err := d.Readdirnames(-1) 42 | if err != nil { 43 | return nil, fmt.Errorf("failed to read contents of ns dir: %v", err) 44 | } 45 | 46 | ns := make(Namespaces, len(names)) 47 | for _, name := range names { 48 | target, err := os.Readlink(p.path("ns", name)) 49 | if err != nil { 50 | return nil, err 51 | } 52 | 53 | fields := strings.SplitN(target, ":", 2) 54 | if len(fields) != 2 { 55 | return nil, fmt.Errorf("failed to parse namespace type and inode from '%v'", target) 56 | } 57 | 58 | typ := fields[0] 59 | inode, err := strconv.ParseUint(strings.Trim(fields[1], "[]"), 10, 32) 60 | if err != nil { 61 | return nil, fmt.Errorf("failed to parse inode from '%v': %v", fields[1], err) 62 | } 63 | 64 | ns[name] = Namespace{typ, uint32(inode)} 65 | } 66 | 67 | return ns, nil 68 | } 69 | -------------------------------------------------------------------------------- /vendor/github.com/sony/gobreaker/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.7.x 4 | - 1.8.x 5 | - 1.9.x 6 | - 1.10.x 7 | - 1.11.x 8 | sudo: false 9 | before_install: 10 | - go get -u github.com/golang/lint/golint 11 | - go get github.com/axw/gocov/gocov 12 | - go get github.com/mattn/goveralls 13 | script: 14 | - test -z "`gofmt -l .`" 15 | - test -z "`golint ./...`" 16 | - $GOPATH/bin/goveralls -service=travis-ci 17 | - cd example && go build -o http_breaker && ./http_breaker 18 | -------------------------------------------------------------------------------- /vendor/github.com/sony/gobreaker/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright 2015 Sony Corporation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/streadway/handy/breaker/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package breaker implements a circuit breaker with configurable failure 3 | thresholds. It provides a Handler, to circuit break in HTTP servers, and a 4 | Transport, to circuit break in HTTP clients. 5 | */ 6 | package breaker 7 | -------------------------------------------------------------------------------- /vendor/github.com/streadway/handy/breaker/handler.go: -------------------------------------------------------------------------------- 1 | package breaker 2 | 3 | import ( 4 | "net/http" 5 | "time" 6 | ) 7 | 8 | // StatusCodeValidator is a function that determines if a status code written 9 | // to a client by a circuit breaking Handler should count as a success or 10 | // failure. The DefaultStatusCodeValidator can be used in most situations. 11 | type StatusCodeValidator func(int) bool 12 | 13 | // Middleware produces an http.Handler factory like Handler to be composed. 14 | func Middleware(breaker Breaker, validator StatusCodeValidator) func(http.Handler) http.Handler { 15 | return func(next http.Handler) http.Handler { 16 | return Handler(breaker, validator, next) 17 | } 18 | } 19 | 20 | // Handler produces an http.Handler that's governed by the passed Breaker and 21 | // StatusCodeValidator. Responses written by the next http.Handler whose 22 | // status codes fail the validator signal failures to the breaker. Once the 23 | // breaker opens, incoming requests are terminated before being forwarded with 24 | // HTTP 503. 25 | func Handler(breaker Breaker, validator StatusCodeValidator, next http.Handler) http.Handler { 26 | return &handler{ 27 | breaker: breaker, 28 | validator: validator, 29 | next: next, 30 | } 31 | } 32 | 33 | type handler struct { 34 | breaker Breaker 35 | validator StatusCodeValidator 36 | next http.Handler 37 | } 38 | 39 | func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 40 | if h.breaker.Allow() { 41 | h.serveClosed(w, r) 42 | } else { 43 | h.serveOpened(w, r) 44 | } 45 | } 46 | 47 | func (h *handler) serveClosed(w http.ResponseWriter, r *http.Request) { 48 | cw := &codeWriter{w, 200} 49 | begin := time.Now() 50 | 51 | h.next.ServeHTTP(cw, r) 52 | 53 | duration := time.Since(begin) 54 | if h.validator(cw.code) { 55 | h.breaker.Success(duration) 56 | } else { 57 | h.breaker.Failure(duration) 58 | } 59 | } 60 | 61 | func (h *handler) serveOpened(w http.ResponseWriter, r *http.Request) { 62 | w.WriteHeader(http.StatusServiceUnavailable) 63 | } 64 | 65 | type codeWriter struct { 66 | http.ResponseWriter 67 | code int 68 | } 69 | 70 | func (w *codeWriter) WriteHeader(code int) { 71 | w.code = code 72 | w.ResponseWriter.WriteHeader(code) 73 | } 74 | 75 | // DefaultStatusCodeValidator considers any status code less than 500 to be a 76 | // success, from the perspective of a server. All other codes are failures. 77 | func DefaultStatusCodeValidator(code int) bool { 78 | return code < 500 79 | } 80 | -------------------------------------------------------------------------------- /vendor/github.com/streadway/handy/breaker/metrics.go: -------------------------------------------------------------------------------- 1 | package breaker 2 | 3 | import ( 4 | "container/ring" 5 | "fmt" 6 | "time" 7 | ) 8 | 9 | type counter struct { 10 | second int64 11 | success uint 12 | failure uint 13 | } 14 | 15 | type summary struct { 16 | total uint 17 | errors uint 18 | rate float64 19 | } 20 | 21 | type metric struct { 22 | r *ring.Ring 23 | seconds uint 24 | now func() time.Time 25 | } 26 | 27 | func newMetric(window time.Duration, now func() time.Time) *metric { 28 | seconds := int(window / time.Second) 29 | 30 | if seconds <= 0 { 31 | panic("metrics must have a window of at least 1 Second") 32 | } 33 | 34 | r := ring.New(seconds) 35 | for i := 0; i < seconds; i++ { 36 | r.Value = &counter{} 37 | r = r.Next() 38 | } 39 | 40 | return &metric{r: r, seconds: uint(seconds), now: now} 41 | } 42 | 43 | func (m *metric) String() string { 44 | counters := []counter{} 45 | m.r.Do(func(v interface{}) { counters = append(counters, *v.(*counter)) }) 46 | return fmt.Sprint(counters) 47 | } 48 | 49 | func (m *metric) next() *counter { 50 | bucket := m.now().Unix() 51 | c := m.r.Value.(*counter) 52 | if c.second != bucket { 53 | m.r = m.r.Next() 54 | *m.r.Value.(*counter) = counter{second: bucket} 55 | } 56 | return c 57 | } 58 | 59 | func (m *metric) Success(time.Duration) { 60 | m.next().success++ 61 | } 62 | 63 | func (m *metric) Failure(time.Duration) { 64 | m.next().failure++ 65 | } 66 | 67 | func (m metric) Summary() summary { 68 | var sum summary 69 | 70 | m.r.Do(func(v interface{}) { 71 | c := v.(*counter) 72 | sum.total += c.success + c.failure 73 | sum.errors += c.failure 74 | }) 75 | 76 | if sum.total > 0 { 77 | sum.rate = float64(sum.errors) / float64(sum.total) 78 | } 79 | 80 | return sum 81 | } 82 | -------------------------------------------------------------------------------- /vendor/github.com/streadway/handy/breaker/transport.go: -------------------------------------------------------------------------------- 1 | package breaker 2 | 3 | import ( 4 | "errors" 5 | "net/http" 6 | "time" 7 | ) 8 | 9 | var ( 10 | // ErrCircuitOpen is returned by the transport when the downstream is 11 | // unavailable due to a broken circuit. 12 | ErrCircuitOpen = errors.New("circuit open") 13 | ) 14 | 15 | // ResponseValidator is a function that determines if an http.Response 16 | // received by a circuit breaking Transport should count as a success or a 17 | // failure. The DefaultResponseValidator can be used in most situations. 18 | type ResponseValidator func(*http.Response) bool 19 | 20 | // Transport produces an http.RoundTripper that's governed by the passed 21 | // Breaker and ResponseValidator. Responses that fail the validator signal 22 | // failures to the breaker. Once the breaker opens, outgoing requests are 23 | // terminated before being forwarded with ErrCircuitOpen. 24 | func Transport(breaker Breaker, validator ResponseValidator, next http.RoundTripper) http.RoundTripper { 25 | return &transport{ 26 | breaker: breaker, 27 | validator: validator, 28 | next: next, 29 | } 30 | } 31 | 32 | type transport struct { 33 | breaker Breaker 34 | validator ResponseValidator 35 | next http.RoundTripper 36 | } 37 | 38 | func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) { 39 | if !t.breaker.Allow() { 40 | return nil, ErrCircuitOpen 41 | } 42 | 43 | begin := time.Now() 44 | resp, err := t.next.RoundTrip(req) 45 | 46 | duration := time.Since(begin) 47 | if err != nil || !t.validator(resp) { 48 | t.breaker.Failure(duration) 49 | } else { 50 | t.breaker.Success(duration) 51 | } 52 | 53 | return resp, err 54 | } 55 | 56 | // DefaultResponseValidator considers any status code less than 400 to be a 57 | // success, from the perspective of a client. All other codes are failures. 58 | func DefaultResponseValidator(resp *http.Response) bool { 59 | return resp.StatusCode < 400 60 | } 61 | -------------------------------------------------------------------------------- /vendor/gopkg.in/check.v1/.gitignore: -------------------------------------------------------------------------------- 1 | _* 2 | *.swp 3 | *.[568] 4 | [568].out 5 | -------------------------------------------------------------------------------- /vendor/gopkg.in/check.v1/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go_import_path: gopkg.in/check.v1 4 | -------------------------------------------------------------------------------- /vendor/gopkg.in/check.v1/LICENSE: -------------------------------------------------------------------------------- 1 | Gocheck - A rich testing framework for Go 2 | 3 | Copyright (c) 2010-2013 Gustavo Niemeyer 4 | 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /vendor/gopkg.in/check.v1/README.md: -------------------------------------------------------------------------------- 1 | Instructions 2 | ============ 3 | 4 | Install the package with: 5 | 6 | go get gopkg.in/check.v1 7 | 8 | Import it with: 9 | 10 | import "gopkg.in/check.v1" 11 | 12 | and use _check_ as the package name inside the code. 13 | 14 | For more details, visit the project page: 15 | 16 | * http://labix.org/gocheck 17 | 18 | and the API documentation: 19 | 20 | * https://gopkg.in/check.v1 21 | -------------------------------------------------------------------------------- /vendor/gopkg.in/check.v1/TODO: -------------------------------------------------------------------------------- 1 | - Assert(slice, Contains, item) 2 | - Parallel test support 3 | -------------------------------------------------------------------------------- /vendor/gopkg.in/check.v1/reporter.go: -------------------------------------------------------------------------------- 1 | package check 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "sync" 7 | ) 8 | 9 | // ----------------------------------------------------------------------- 10 | // Output writer manages atomic output writing according to settings. 11 | 12 | type outputWriter struct { 13 | m sync.Mutex 14 | writer io.Writer 15 | wroteCallProblemLast bool 16 | Stream bool 17 | Verbose bool 18 | } 19 | 20 | func newOutputWriter(writer io.Writer, stream, verbose bool) *outputWriter { 21 | return &outputWriter{writer: writer, Stream: stream, Verbose: verbose} 22 | } 23 | 24 | func (ow *outputWriter) Write(content []byte) (n int, err error) { 25 | ow.m.Lock() 26 | n, err = ow.writer.Write(content) 27 | ow.m.Unlock() 28 | return 29 | } 30 | 31 | func (ow *outputWriter) WriteCallStarted(label string, c *C) { 32 | if ow.Stream { 33 | header := renderCallHeader(label, c, "", "\n") 34 | ow.m.Lock() 35 | ow.writer.Write([]byte(header)) 36 | ow.m.Unlock() 37 | } 38 | } 39 | 40 | func (ow *outputWriter) WriteCallProblem(label string, c *C) { 41 | var prefix string 42 | if !ow.Stream { 43 | prefix = "\n-----------------------------------" + 44 | "-----------------------------------\n" 45 | } 46 | header := renderCallHeader(label, c, prefix, "\n\n") 47 | ow.m.Lock() 48 | ow.wroteCallProblemLast = true 49 | ow.writer.Write([]byte(header)) 50 | if !ow.Stream { 51 | c.logb.WriteTo(ow.writer) 52 | } 53 | ow.m.Unlock() 54 | } 55 | 56 | func (ow *outputWriter) WriteCallSuccess(label string, c *C) { 57 | if ow.Stream || (ow.Verbose && c.kind == testKd) { 58 | // TODO Use a buffer here. 59 | var suffix string 60 | if c.reason != "" { 61 | suffix = " (" + c.reason + ")" 62 | } 63 | if c.status() == succeededSt { 64 | suffix += "\t" + c.timerString() 65 | } 66 | suffix += "\n" 67 | if ow.Stream { 68 | suffix += "\n" 69 | } 70 | header := renderCallHeader(label, c, "", suffix) 71 | ow.m.Lock() 72 | // Resist temptation of using line as prefix above due to race. 73 | if !ow.Stream && ow.wroteCallProblemLast { 74 | header = "\n-----------------------------------" + 75 | "-----------------------------------\n" + 76 | header 77 | } 78 | ow.wroteCallProblemLast = false 79 | ow.writer.Write([]byte(header)) 80 | ow.m.Unlock() 81 | } 82 | } 83 | 84 | func renderCallHeader(label string, c *C, prefix, suffix string) string { 85 | pc := c.method.PC() 86 | return fmt.Sprintf("%s%s: %s: %s%s", prefix, label, niceFuncPath(pc), 87 | niceFuncName(pc), suffix) 88 | } 89 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go_import_path: gopkg.in/mgo.v2 4 | 5 | addons: 6 | apt: 7 | packages: 8 | 9 | env: 10 | global: 11 | - BUCKET=https://niemeyer.s3.amazonaws.com 12 | matrix: 13 | - GO=1.4.1 MONGODB=x86_64-2.2.7 14 | - GO=1.4.1 MONGODB=x86_64-2.4.14 15 | - GO=1.4.1 MONGODB=x86_64-2.6.11 16 | - GO=1.4.1 MONGODB=x86_64-3.0.9 17 | - GO=1.4.1 MONGODB=x86_64-3.2.3-nojournal 18 | - GO=1.5.3 MONGODB=x86_64-3.0.9 19 | - GO=1.6 MONGODB=x86_64-3.0.9 20 | 21 | install: 22 | - eval "$(gimme $GO)" 23 | 24 | - wget $BUCKET/mongodb-linux-$MONGODB.tgz 25 | - tar xzvf mongodb-linux-$MONGODB.tgz 26 | - export PATH=$PWD/mongodb-linux-$MONGODB/bin:$PATH 27 | 28 | - wget $BUCKET/daemontools.tar.gz 29 | - tar xzvf daemontools.tar.gz 30 | - export PATH=$PWD/daemontools:$PATH 31 | 32 | - go get gopkg.in/check.v1 33 | - go get gopkg.in/yaml.v2 34 | - go get gopkg.in/tomb.v2 35 | 36 | before_script: 37 | - export NOIPV6=1 38 | - make startdb 39 | 40 | script: 41 | - (cd bson && go test -check.v) 42 | - go test -check.v -fast 43 | - (cd txn && go test -check.v) 44 | 45 | # vim:sw=4:ts=4:et 46 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/LICENSE: -------------------------------------------------------------------------------- 1 | mgo - MongoDB driver for Go 2 | 3 | Copyright (c) 2010-2013 - Gustavo Niemeyer 4 | 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/Makefile: -------------------------------------------------------------------------------- 1 | startdb: 2 | @harness/setup.sh start 3 | 4 | stopdb: 5 | @harness/setup.sh stop 6 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/README.md: -------------------------------------------------------------------------------- 1 | The MongoDB driver for Go 2 | ------------------------- 3 | 4 | Please go to [http://labix.org/mgo](http://labix.org/mgo) for all project details. 5 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/bson/LICENSE: -------------------------------------------------------------------------------- 1 | BSON library for Go 2 | 3 | Copyright (c) 2010-2012 - Gustavo Niemeyer 4 | 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/doc.go: -------------------------------------------------------------------------------- 1 | // Package mgo offers a rich MongoDB driver for Go. 2 | // 3 | // ######################################################### 4 | // 5 | // THIS DRIVER IS UNMAINTAINED! See here for details: 6 | // 7 | // https://github.com/go-mgo/mgo/blob/v2-unstable/README.md 8 | // 9 | // ######################################################### 10 | // 11 | // Usage of the driver revolves around the concept of sessions. To 12 | // get started, obtain a session using the Dial function: 13 | // 14 | // session, err := mgo.Dial(url) 15 | // 16 | // This will establish one or more connections with the cluster of 17 | // servers defined by the url parameter. From then on, the cluster 18 | // may be queried with multiple consistency rules (see SetMode) and 19 | // documents retrieved with statements such as: 20 | // 21 | // c := session.DB(database).C(collection) 22 | // err := c.Find(query).One(&result) 23 | // 24 | // New sessions are typically created by calling session.Copy on the 25 | // initial session obtained at dial time. These new sessions will share 26 | // the same cluster information and connection pool, and may be easily 27 | // handed into other methods and functions for organizing logic. 28 | // Every session created must have its Close method called at the end 29 | // of its life time, so its resources may be put back in the pool or 30 | // collected, depending on the case. 31 | // 32 | // For more details, see the documentation for the types and methods. 33 | // 34 | package mgo 35 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/internal/json/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/internal/json/extension.go: -------------------------------------------------------------------------------- 1 | package json 2 | 3 | import ( 4 | "reflect" 5 | ) 6 | 7 | // Extension holds a set of additional rules to be used when unmarshaling 8 | // strict JSON or JSON-like content. 9 | type Extension struct { 10 | funcs map[string]funcExt 11 | consts map[string]interface{} 12 | keyed map[string]func([]byte) (interface{}, error) 13 | encode map[reflect.Type]func(v interface{}) ([]byte, error) 14 | 15 | unquotedKeys bool 16 | trailingCommas bool 17 | } 18 | 19 | type funcExt struct { 20 | key string 21 | args []string 22 | } 23 | 24 | // Extend changes the decoder behavior to consider the provided extension. 25 | func (dec *Decoder) Extend(ext *Extension) { dec.d.ext = *ext } 26 | 27 | // Extend changes the encoder behavior to consider the provided extension. 28 | func (enc *Encoder) Extend(ext *Extension) { enc.ext = *ext } 29 | 30 | // Extend includes in e the extensions defined in ext. 31 | func (e *Extension) Extend(ext *Extension) { 32 | for name, fext := range ext.funcs { 33 | e.DecodeFunc(name, fext.key, fext.args...) 34 | } 35 | for name, value := range ext.consts { 36 | e.DecodeConst(name, value) 37 | } 38 | for key, decode := range ext.keyed { 39 | e.DecodeKeyed(key, decode) 40 | } 41 | for typ, encode := range ext.encode { 42 | if e.encode == nil { 43 | e.encode = make(map[reflect.Type]func(v interface{}) ([]byte, error)) 44 | } 45 | e.encode[typ] = encode 46 | } 47 | } 48 | 49 | // DecodeFunc defines a function call that may be observed inside JSON content. 50 | // A function with the provided name will be unmarshaled as the document 51 | // {key: {args[0]: ..., args[N]: ...}}. 52 | func (e *Extension) DecodeFunc(name string, key string, args ...string) { 53 | if e.funcs == nil { 54 | e.funcs = make(map[string]funcExt) 55 | } 56 | e.funcs[name] = funcExt{key, args} 57 | } 58 | 59 | // DecodeConst defines a constant name that may be observed inside JSON content 60 | // and will be decoded with the provided value. 61 | func (e *Extension) DecodeConst(name string, value interface{}) { 62 | if e.consts == nil { 63 | e.consts = make(map[string]interface{}) 64 | } 65 | e.consts[name] = value 66 | } 67 | 68 | // DecodeKeyed defines a key that when observed as the first element inside a 69 | // JSON document triggers the decoding of that document via the provided 70 | // decode function. 71 | func (e *Extension) DecodeKeyed(key string, decode func(data []byte) (interface{}, error)) { 72 | if e.keyed == nil { 73 | e.keyed = make(map[string]func([]byte) (interface{}, error)) 74 | } 75 | e.keyed[key] = decode 76 | } 77 | 78 | // DecodeUnquotedKeys defines whether to accept map keys that are unquoted strings. 79 | func (e *Extension) DecodeUnquotedKeys(accept bool) { 80 | e.unquotedKeys = accept 81 | } 82 | 83 | // DecodeTrailingCommas defines whether to accept trailing commas in maps and arrays. 84 | func (e *Extension) DecodeTrailingCommas(accept bool) { 85 | e.trailingCommas = accept 86 | } 87 | 88 | // EncodeType registers a function to encode values with the same type of the 89 | // provided sample. 90 | func (e *Extension) EncodeType(sample interface{}, encode func(v interface{}) ([]byte, error)) { 91 | if e.encode == nil { 92 | e.encode = make(map[reflect.Type]func(v interface{}) ([]byte, error)) 93 | } 94 | e.encode[reflect.TypeOf(sample)] = encode 95 | } 96 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/internal/json/tags.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package json 6 | 7 | import ( 8 | "strings" 9 | ) 10 | 11 | // tagOptions is the string following a comma in a struct field's "json" 12 | // tag, or the empty string. It does not include the leading comma. 13 | type tagOptions string 14 | 15 | // parseTag splits a struct field's json tag into its name and 16 | // comma-separated options. 17 | func parseTag(tag string) (string, tagOptions) { 18 | if idx := strings.Index(tag, ","); idx != -1 { 19 | return tag[:idx], tagOptions(tag[idx+1:]) 20 | } 21 | return tag, tagOptions("") 22 | } 23 | 24 | // Contains reports whether a comma-separated list of options 25 | // contains a particular substr flag. substr must be surrounded by a 26 | // string boundary or commas. 27 | func (o tagOptions) Contains(optionName string) bool { 28 | if len(o) == 0 { 29 | return false 30 | } 31 | s := string(o) 32 | for s != "" { 33 | var next string 34 | i := strings.Index(s, ",") 35 | if i >= 0 { 36 | s, next = s[:i], s[i+1:] 37 | } 38 | if s == optionName { 39 | return true 40 | } 41 | s = next 42 | } 43 | return false 44 | } 45 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/internal/sasl/sasl.c: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | static int mgo_sasl_simple(void *context, int id, const char **result, unsigned int *len) 9 | { 10 | if (!result) { 11 | return SASL_BADPARAM; 12 | } 13 | switch (id) { 14 | case SASL_CB_USER: 15 | *result = (char *)context; 16 | break; 17 | case SASL_CB_AUTHNAME: 18 | *result = (char *)context; 19 | break; 20 | case SASL_CB_LANGUAGE: 21 | *result = NULL; 22 | break; 23 | default: 24 | return SASL_BADPARAM; 25 | } 26 | if (len) { 27 | *len = *result ? strlen(*result) : 0; 28 | } 29 | return SASL_OK; 30 | } 31 | 32 | typedef int (*callback)(void); 33 | 34 | static int mgo_sasl_secret(sasl_conn_t *conn, void *context, int id, sasl_secret_t **result) 35 | { 36 | if (!conn || !result || id != SASL_CB_PASS) { 37 | return SASL_BADPARAM; 38 | } 39 | *result = (sasl_secret_t *)context; 40 | return SASL_OK; 41 | } 42 | 43 | sasl_callback_t *mgo_sasl_callbacks(const char *username, const char *password) 44 | { 45 | sasl_callback_t *cb = malloc(4 * sizeof(sasl_callback_t)); 46 | int n = 0; 47 | 48 | size_t len = strlen(password); 49 | sasl_secret_t *secret = (sasl_secret_t*)malloc(sizeof(sasl_secret_t) + len); 50 | if (!secret) { 51 | free(cb); 52 | return NULL; 53 | } 54 | strcpy((char *)secret->data, password); 55 | secret->len = len; 56 | 57 | cb[n].id = SASL_CB_PASS; 58 | cb[n].proc = (callback)&mgo_sasl_secret; 59 | cb[n].context = secret; 60 | n++; 61 | 62 | cb[n].id = SASL_CB_USER; 63 | cb[n].proc = (callback)&mgo_sasl_simple; 64 | cb[n].context = (char*)username; 65 | n++; 66 | 67 | cb[n].id = SASL_CB_AUTHNAME; 68 | cb[n].proc = (callback)&mgo_sasl_simple; 69 | cb[n].context = (char*)username; 70 | n++; 71 | 72 | cb[n].id = SASL_CB_LIST_END; 73 | cb[n].proc = NULL; 74 | cb[n].context = NULL; 75 | 76 | return cb; 77 | } 78 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/internal/sasl/sasl_windows.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "sspi_windows.h" 4 | 5 | SECURITY_STATUS SEC_ENTRY sspi_acquire_credentials_handle(CredHandle* cred_handle, char* username, char* password, char* domain); 6 | int sspi_step(CredHandle* cred_handle, int has_context, CtxtHandle* context, PVOID buffer, ULONG buffer_length, PVOID* out_buffer, ULONG* out_buffer_length, char* target); 7 | int sspi_send_client_authz_id(CtxtHandle* context, PVOID* buffer, ULONG* buffer_length, char* user_plus_realm); 8 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/internal/sasl/sspi_windows.h: -------------------------------------------------------------------------------- 1 | // Code adapted from the NodeJS kerberos library: 2 | // 3 | // https://github.com/christkv/kerberos/tree/master/lib/win32/kerberos_sspi.h 4 | // 5 | // Under the terms of the Apache License, Version 2.0: 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | #ifndef SSPI_WINDOWS_H 10 | #define SSPI_WINDOWS_H 11 | 12 | #define SECURITY_WIN32 1 13 | 14 | #include 15 | #include 16 | 17 | int load_secur32_dll(); 18 | 19 | SECURITY_STATUS SEC_ENTRY call_sspi_encrypt_message(PCtxtHandle phContext, unsigned long fQOP, PSecBufferDesc pMessage, unsigned long MessageSeqNo); 20 | 21 | typedef DWORD (WINAPI *encryptMessage_fn)(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo); 22 | 23 | SECURITY_STATUS SEC_ENTRY call_sspi_acquire_credentials_handle( 24 | LPSTR pszPrincipal, // Name of principal 25 | LPSTR pszPackage, // Name of package 26 | unsigned long fCredentialUse, // Flags indicating use 27 | void *pvLogonId, // Pointer to logon ID 28 | void *pAuthData, // Package specific data 29 | SEC_GET_KEY_FN pGetKeyFn, // Pointer to GetKey() func 30 | void *pvGetKeyArgument, // Value to pass to GetKey() 31 | PCredHandle phCredential, // (out) Cred Handle 32 | PTimeStamp ptsExpiry // (out) Lifetime (optional) 33 | ); 34 | 35 | typedef DWORD (WINAPI *acquireCredentialsHandle_fn)( 36 | LPSTR pszPrincipal, LPSTR pszPackage, unsigned long fCredentialUse, 37 | void *pvLogonId, void *pAuthData, SEC_GET_KEY_FN pGetKeyFn, void *pvGetKeyArgument, 38 | PCredHandle phCredential, PTimeStamp ptsExpiry 39 | ); 40 | 41 | SECURITY_STATUS SEC_ENTRY call_sspi_initialize_security_context( 42 | PCredHandle phCredential, // Cred to base context 43 | PCtxtHandle phContext, // Existing context (OPT) 44 | LPSTR pszTargetName, // Name of target 45 | unsigned long fContextReq, // Context Requirements 46 | unsigned long Reserved1, // Reserved, MBZ 47 | unsigned long TargetDataRep, // Data rep of target 48 | PSecBufferDesc pInput, // Input Buffers 49 | unsigned long Reserved2, // Reserved, MBZ 50 | PCtxtHandle phNewContext, // (out) New Context handle 51 | PSecBufferDesc pOutput, // (inout) Output Buffers 52 | unsigned long *pfContextAttr, // (out) Context attrs 53 | PTimeStamp ptsExpiry // (out) Life span (OPT) 54 | ); 55 | 56 | typedef DWORD (WINAPI *initializeSecurityContext_fn)( 57 | PCredHandle phCredential, PCtxtHandle phContext, LPSTR pszTargetName, unsigned long fContextReq, 58 | unsigned long Reserved1, unsigned long TargetDataRep, PSecBufferDesc pInput, unsigned long Reserved2, 59 | PCtxtHandle phNewContext, PSecBufferDesc pOutput, unsigned long *pfContextAttr, PTimeStamp ptsExpiry); 60 | 61 | SECURITY_STATUS SEC_ENTRY call_sspi_query_context_attributes( 62 | PCtxtHandle phContext, // Context to query 63 | unsigned long ulAttribute, // Attribute to query 64 | void *pBuffer // Buffer for attributes 65 | ); 66 | 67 | typedef DWORD (WINAPI *queryContextAttributes_fn)( 68 | PCtxtHandle phContext, unsigned long ulAttribute, void *pBuffer); 69 | 70 | #endif // SSPI_WINDOWS_H 71 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/queue.go: -------------------------------------------------------------------------------- 1 | // mgo - MongoDB driver for Go 2 | // 3 | // Copyright (c) 2010-2012 - Gustavo Niemeyer 4 | // 5 | // All rights reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are met: 9 | // 10 | // 1. Redistributions of source code must retain the above copyright notice, this 11 | // list of conditions and the following disclaimer. 12 | // 2. Redistributions in binary form must reproduce the above copyright notice, 13 | // this list of conditions and the following disclaimer in the documentation 14 | // and/or other materials provided with the distribution. 15 | // 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 | // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | 27 | package mgo 28 | 29 | type queue struct { 30 | elems []interface{} 31 | nelems, popi, pushi int 32 | } 33 | 34 | func (q *queue) Len() int { 35 | return q.nelems 36 | } 37 | 38 | func (q *queue) Push(elem interface{}) { 39 | //debugf("Pushing(pushi=%d popi=%d cap=%d): %#v\n", 40 | // q.pushi, q.popi, len(q.elems), elem) 41 | if q.nelems == len(q.elems) { 42 | q.expand() 43 | } 44 | q.elems[q.pushi] = elem 45 | q.nelems++ 46 | q.pushi = (q.pushi + 1) % len(q.elems) 47 | //debugf(" Pushed(pushi=%d popi=%d cap=%d): %#v\n", 48 | // q.pushi, q.popi, len(q.elems), elem) 49 | } 50 | 51 | func (q *queue) Pop() (elem interface{}) { 52 | //debugf("Popping(pushi=%d popi=%d cap=%d)\n", 53 | // q.pushi, q.popi, len(q.elems)) 54 | if q.nelems == 0 { 55 | return nil 56 | } 57 | elem = q.elems[q.popi] 58 | q.elems[q.popi] = nil // Help GC. 59 | q.nelems-- 60 | q.popi = (q.popi + 1) % len(q.elems) 61 | //debugf(" Popped(pushi=%d popi=%d cap=%d): %#v\n", 62 | // q.pushi, q.popi, len(q.elems), elem) 63 | return elem 64 | } 65 | 66 | func (q *queue) expand() { 67 | curcap := len(q.elems) 68 | var newcap int 69 | if curcap == 0 { 70 | newcap = 8 71 | } else if curcap < 1024 { 72 | newcap = curcap * 2 73 | } else { 74 | newcap = curcap + (curcap / 4) 75 | } 76 | elems := make([]interface{}, newcap) 77 | 78 | if q.popi == 0 { 79 | copy(elems, q.elems) 80 | q.pushi = curcap 81 | } else { 82 | newpopi := newcap - (curcap - q.popi) 83 | copy(elems, q.elems[:q.popi]) 84 | copy(elems[newpopi:], q.elems[q.popi:]) 85 | q.popi = newpopi 86 | } 87 | for i := range q.elems { 88 | q.elems[i] = nil // Help GC. 89 | } 90 | q.elems = elems 91 | } 92 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/raceoff.go: -------------------------------------------------------------------------------- 1 | // +build !race 2 | 3 | package mgo 4 | 5 | const raceDetector = false 6 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/raceon.go: -------------------------------------------------------------------------------- 1 | // +build race 2 | 3 | package mgo 4 | 5 | const raceDetector = true 6 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/saslimpl.go: -------------------------------------------------------------------------------- 1 | //+build sasl 2 | 3 | package mgo 4 | 5 | import ( 6 | "gopkg.in/mgo.v2/internal/sasl" 7 | ) 8 | 9 | func saslNew(cred Credential, host string) (saslStepper, error) { 10 | return sasl.New(cred.Username, cred.Password, cred.Mechanism, cred.Service, host) 11 | } 12 | -------------------------------------------------------------------------------- /vendor/gopkg.in/mgo.v2/saslstub.go: -------------------------------------------------------------------------------- 1 | //+build !sasl 2 | 3 | package mgo 4 | 5 | import ( 6 | "fmt" 7 | ) 8 | 9 | func saslNew(cred Credential, host string) (saslStepper, error) { 10 | return nil, fmt.Errorf("SASL support not enabled during build (-tags sasl)") 11 | } 12 | -------------------------------------------------------------------------------- /vendor/modules.txt: -------------------------------------------------------------------------------- 1 | # github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 2 | github.com/afex/hystrix-go/hystrix 3 | github.com/afex/hystrix-go/hystrix/metric_collector 4 | github.com/afex/hystrix-go/hystrix/rolling 5 | # github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 6 | github.com/beorn7/perks/quantile 7 | # github.com/go-chi/chi v3.3.3+incompatible 8 | github.com/go-chi/chi 9 | # github.com/go-kit/kit v0.7.0 10 | github.com/go-kit/kit/log 11 | github.com/go-kit/kit/metrics 12 | github.com/go-kit/kit/metrics/prometheus 13 | github.com/go-kit/kit/circuitbreaker 14 | github.com/go-kit/kit/endpoint 15 | github.com/go-kit/kit/transport/http 16 | github.com/go-kit/kit/metrics/internal/lv 17 | # github.com/go-logfmt/logfmt v0.3.0 18 | github.com/go-logfmt/logfmt 19 | # github.com/go-stack/stack v1.8.0 20 | github.com/go-stack/stack 21 | # github.com/golang/protobuf v1.2.0 22 | github.com/golang/protobuf/proto 23 | # github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 24 | github.com/kr/logfmt 25 | # github.com/kr/pretty v0.1.0 26 | github.com/kr/pretty 27 | # github.com/kr/text v0.1.0 28 | github.com/kr/text 29 | # github.com/matttproud/golang_protobuf_extensions v1.0.1 30 | github.com/matttproud/golang_protobuf_extensions/pbutil 31 | # github.com/pborman/uuid v0.0.0-20180827223501-4c1ecd6722e8 32 | github.com/pborman/uuid 33 | # github.com/prometheus/client_golang v0.8.0 34 | github.com/prometheus/client_golang/prometheus 35 | github.com/prometheus/client_golang/prometheus/promhttp 36 | # github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 37 | github.com/prometheus/client_model/go 38 | # github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e 39 | github.com/prometheus/common/expfmt 40 | github.com/prometheus/common/model 41 | github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg 42 | # github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273 43 | github.com/prometheus/procfs 44 | github.com/prometheus/procfs/nfs 45 | github.com/prometheus/procfs/xfs 46 | github.com/prometheus/procfs/internal/util 47 | # github.com/sony/gobreaker v0.0.0-20180905101324-b2a34562d02c 48 | github.com/sony/gobreaker 49 | # github.com/streadway/handy v0.0.0-20160402200321-f450267a206e 50 | github.com/streadway/handy/breaker 51 | # gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 52 | gopkg.in/check.v1 53 | # gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce 54 | gopkg.in/mgo.v2 55 | gopkg.in/mgo.v2/bson 56 | gopkg.in/mgo.v2/internal/sasl 57 | gopkg.in/mgo.v2/internal/scram 58 | gopkg.in/mgo.v2/internal/json 59 | -------------------------------------------------------------------------------- /voyage.go: -------------------------------------------------------------------------------- 1 | package shipping 2 | 3 | import ( 4 | "errors" 5 | "time" 6 | ) 7 | 8 | // VoyageNumber uniquely identifies a particular Voyage. 9 | type VoyageNumber string 10 | 11 | // Voyage is a uniquely identifiable series of carrier movements. 12 | type Voyage struct { 13 | VoyageNumber VoyageNumber 14 | Schedule Schedule 15 | } 16 | 17 | // NewVoyage creates a voyage with a voyage number and a provided schedule. 18 | func NewVoyage(n VoyageNumber, s Schedule) *Voyage { 19 | return &Voyage{VoyageNumber: n, Schedule: s} 20 | } 21 | 22 | // Schedule describes a voyage schedule. 23 | type Schedule struct { 24 | CarrierMovements []CarrierMovement 25 | } 26 | 27 | // CarrierMovement is a vessel voyage from one location to another. 28 | type CarrierMovement struct { 29 | DepartureLocation UNLocode 30 | ArrivalLocation UNLocode 31 | DepartureTime time.Time 32 | ArrivalTime time.Time 33 | } 34 | 35 | // ErrUnknownVoyage is used when a voyage could not be found. 36 | var ErrUnknownVoyage = errors.New("unknown voyage") 37 | 38 | // VoyageRepository provides access a voyage store. 39 | type VoyageRepository interface { 40 | Find(VoyageNumber) (*Voyage, error) 41 | } 42 | --------------------------------------------------------------------------------