Skip to content
3 changes: 3 additions & 0 deletions extension/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package extension

import (
"github.com/google/trillian/crypto/keys"
"github.com/google/trillian/monitoring"
"github.com/google/trillian/quota"
"github.com/google/trillian/storage"
"github.com/google/trillian/util"
Expand All @@ -39,4 +40,6 @@ type Registry struct {
util.ElectionFactory
// QuotaManager provides rate limiting capabilities for Trillian.
QuotaManager quota.Manager
// MetricFactory provides metrics for monitoring.
monitoring.MetricFactory
}
36 changes: 24 additions & 12 deletions integration/functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,13 @@ wait_for_server_startup() {

# pick_unused_port selects an apparently unused port.
pick_unused_port() {
local avoid=${1:-0}
local base=6962
local port
for (( port = "${base}" ; port <= 61000 ; port++ )); do
if [[ $port == $avoid ]]; then
continue
fi
if ! lsof -i :$port > /dev/null; then
echo $port
break
Expand Down Expand Up @@ -111,21 +115,24 @@ log_prep_test() {
ETCD_OPTS="--etcd_servers=${etcd_server}"
ETCD_DB_DIR=default.etcd
wait_for_server_startup ${etcd_port}
local signer_election_opts=
local logserver_opts="--etcd_http_service=trillian-logserver-http --etcd_service=trillian-logserver"
local logsigner_opts="--etcd_http_service=trillian-logsigner-http"
else
if [[ ${log_signer_count} > 1 ]]; then
echo "*** Warning: running multiple signers with no etcd instance ***"
fi
local signer_election_opts="--force_master"
local logserver_opts=
local logsigner_opts="--force_master"
fi

# Start a set of Log RPC servers.
for ((i=0; i < rpc_server_count; i++)); do
port=$(pick_unused_port)
RPC_SERVERS="${RPC_SERVERS},localhost:${port}"
http=$(pick_unused_port ${port})

echo "Starting Log RPC server on localhost:${port}"
./trillian_log_server ${ETCD_OPTS} --rpc_endpoint="localhost:${port}" --http_endpoint='' &
echo "Starting Log RPC server on localhost:${port}, HTTP on localhost:${http}"
./trillian_log_server ${ETCD_OPTS} ${logserver_opts} --rpc_endpoint="localhost:${port}" --http_endpoint="localhost:${http}" &
pid=$!
RPC_SERVER_PIDS+=(${pid})
wait_for_server_startup ${port}
Expand All @@ -137,19 +144,24 @@ log_prep_test() {
done
RPC_SERVERS="${RPC_SERVERS:1}"

if [[ ! -z "${ETCD_OPTS}" ]]; then
RPC_SERVERS="trillian-log"
echo "Registered log servers @${RPC_SERVERS}/"
ETCDCTL_API=3 etcdctl get ${RPC_SERVERS} --prefix
fi

# Start a set of signers.
for ((i=0; i < log_signer_count; i++)); do
echo "Starting Log signer"
./trillian_log_signer ${ETCD_OPTS} ${signer_election_opts} --sequencer_interval="1s" --batch_size=500 --http_endpoint='' --num_sequencers 2 &
http=$(pick_unused_port)
echo "Starting Log signer, HTTP on localhost:${http}"
./trillian_log_signer ${ETCD_OPTS} ${logsigner_opts} --sequencer_interval="1s" --batch_size=500 --http_endpoint="localhost:${http}" --num_sequencers 2 &
pid=$!
LOG_SIGNER_PIDS+=(${pid})
wait_for_server_startup ${http}
done

if [[ ! -z "${ETCD_OPTS}" ]]; then
RPC_SERVERS="trillian-logserver"
echo "Registered log servers @${RPC_SERVERS}/"
ETCDCTL_API=3 etcdctl get ${RPC_SERVERS}/ --prefix
echo "Registered HTTP endpoints"
ETCDCTL_API=3 etcdctl get trillian-logserver-http/ --prefix
ETCDCTL_API=3 etcdctl get trillian-logsigner-http/ --prefix
fi
}

# log_stop_tests closes down a set of running processes for a log test.
Expand Down
122 changes: 122 additions & 0 deletions monitoring/inert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package monitoring

import (
"fmt"
"strings"
"sync"
)

// InertMetricFactory creates inert metrics for testing.
type InertMetricFactory struct{}

// NewCounter creates a new inert Counter.
func (imf InertMetricFactory) NewCounter(name, help string, labelNames ...string) Counter {
return &InertFloat{
labelCount: len(labelNames),
vals: make(map[string]float64),
}
}

// NewGauge creates a new inert Gauge.
func (imf InertMetricFactory) NewGauge(name, help string, labelNames ...string) Gauge {
return &InertFloat{
labelCount: len(labelNames),
vals: make(map[string]float64),
}
}

// NewHistogram creates a new inert Histogram.
func (imf InertMetricFactory) NewHistogram(name, help string, labelNames ...string) Histogram {
return &InertDistribution{
labelCount: len(labelNames),
counts: make(map[string]uint64),
sums: make(map[string]float64),
}
}

// InertFloat is an internal-only implementation of both the Counter and Gauge interfaces.
type InertFloat struct {
labelCount int
mu sync.Mutex
vals map[string]float64
}

// Inc adds 1 to the value.
func (m *InertFloat) Inc(labelVals ...string) {
m.Add(1.0, labelVals...)
}

// Dec subtracts 1 from the value.
func (m *InertFloat) Dec(labelVals ...string) {
m.Add(-1.0, labelVals...)
}

// Add adds the given amount to the value.
func (m *InertFloat) Add(val float64, labelVals ...string) {
m.mu.Lock()
defer m.mu.Unlock()
key := keyForLabels(labelVals, m.labelCount)
m.vals[key] += val
}

// Set sets the value.
func (m *InertFloat) Set(val float64, labelVals ...string) {
m.mu.Lock()
defer m.mu.Unlock()
key := keyForLabels(labelVals, m.labelCount)
m.vals[key] = val
}

// Value returns the current value.
func (m *InertFloat) Value(labelVals ...string) float64 {
m.mu.Lock()
defer m.mu.Unlock()
key := keyForLabels(labelVals, m.labelCount)
return m.vals[key]
}

// InertDistribution is an internal-only implementation of the Distribution interface.
type InertDistribution struct {
labelCount int
mu sync.Mutex
counts map[string]uint64
sums map[string]float64
}

// Observe adds a single observation to the distribution.
func (m *InertDistribution) Observe(val float64, labelVals ...string) {
m.mu.Lock()
defer m.mu.Unlock()
key := keyForLabels(labelVals, m.labelCount)
m.counts[key]++
m.sums[key] += val
}

// Info returns count, sum for the distribution.
func (m *InertDistribution) Info(labelVals ...string) (uint64, float64) {
m.mu.Lock()
defer m.mu.Unlock()
key := keyForLabels(labelVals, m.labelCount)
return m.counts[key], m.sums[key]
}

func keyForLabels(labelVals []string, count int) string {
if len(labelVals) != count {
panic(fmt.Sprintf("invalid label count %d; want %d", len(labelVals), count))
}
return strings.Join(labelVals, "|")
}
107 changes: 0 additions & 107 deletions monitoring/metric/counter.go

This file was deleted.

49 changes: 49 additions & 0 deletions monitoring/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package monitoring

// MetricFactory allows the creation of different types of metric.
type MetricFactory interface {
NewCounter(name, help string, labelNames ...string) Counter
NewGauge(name, help string, labelNames ...string) Gauge
NewHistogram(name, help string, labelNames ...string) Histogram
}

// Counter is a metric class for numeric values that increase.
type Counter interface {
Inc(labelVals ...string)
Add(val float64, labelVals ...string)
Value(labelVals ...string) float64
}

// Gauge is a metric class for numeric values that can go up and down.
type Gauge interface {
Inc(labelVals ...string)
Dec(labelVals ...string)
Add(val float64, labelVals ...string)
Set(val float64, labelVals ...string)
// Value retrieves the value for a particular set of labels.
// This is only really useful for testing implementations.
Value(labelVals ...string) float64
}

// Histogram is a metric class that tracks the distribution of a collection
// of observations.
type Histogram interface {
Observe(val float64, labelVals ...string)
// Info retrieves the count and sum of observations for a particular set of labels.
// This is only really useful for testing implementations.
Info(labelVals ...string) (uint64, float64)
}
Loading