Git Product home page Git Product logo

Comments (2)

izgeri avatar izgeri commented on July 22, 2024 1

In the feature spec we are focused on TCP - can we focus on TCP here as well? Can we also ensure scope is clear, eg right now we only need to measure post-connection streaming latency and throughput. In particular, from the doc we have:

Secretless latency under ‘light’ load and maximum throughput (Mbps) per single Secretless container has been measured. ‘Light’ load or operating profile is defined as above, where Secretless is communicating with a database cluster with variable data size per request.

I think in this card we are asking: how can we measure post-authentication handshake latency / throughput?

One other relevant requirement:

The telemetry data output by Secretless must be easy to query across an arbitrary period of time with at least a week of history, and related events should be tagged in a way that makes it easy to aggregate them.

So at a minimum, the data that's output has to be timestamped and tagged to indicate which specific connection the datapoint is relevant to.

from secretless-broker.

doodlesbykumbi avatar doodlesbykumbi commented on July 22, 2024

The outcome from this spike is captured in the telemetry branch, where there is a reference implementation of metric measurement, collection, export and analysis.


For making measurements we start by noting that network I/O in Go is blocking. That means reads will block a goroutine until the buffer has something. We use io.Copy to implement unidirectional streaming, it takes as input a destination io.Writer and a source io.Reader. Bidirectional TCP streaming in Secretless (see duplexStream) is the result of 2 Go routines each carrying out streaming (via io.Copy) in a particular direction, taking as input the client and target TCP connections. io.Copy handles all the reading, writing and buffering. The io.Copy for each direction blocks in its goroutine for the lifetime of the streaming.

In order to take measurements, we must instrument each TCP connection instance by wrapping it to intercept reads and writes.

Metrics definitions

The metrics are defined below. NOTE that each metric is e

TCP streaming latency

The time between when a source connection's Read unblocks from the arrival of some packet to when the destination connection's Write for that packet returns.

NOTE: some small experiments indicate that the order of events in Secretless is that there is always a source connection Read followed by a destination connection's Write.

TCP streaming throughput

The ongoing sum of the number of bytes written in any direction.

POC implementation

The POC implementation follows the ideas above.

The metrics are defined and labelled with connector specific information like the Secretless service name and connector type.

meter := metric.Must(s.meter)
labels := []attribute.KeyValue{
attribute.String("service.name", config.Connector + ":" + "secretless"),
attribute.String("secretless.service_name", config.Name),
attribute.String("secretless.connector_name", config.Connector),
}
throughputCounter := meter.NewInt64Counter(
"secretless.tcp.stream.bytes",
metric.WithUnit(unit.Bytes),
).Bind(labels...)
latencyRecorder := meter.NewInt64ValueRecorder(
"secretless.tcp.stream.latency",
).Bind(labels...)

The connections are instrumented to allow measurement of latency and throughput, and measurements are taken via OpenTelemetry.

clientErrChan, destErrChan := duplexStream(
&ReadWriteNotifier{
readWriter: clientConn,
onWrite: func(bytesWritten int, timeToHandoff time.Duration) {
// clientWrite
streamLatency := time.Now().Sub(lastTargetRead)
ctx := context.Background()
proxy.throughputCounter.Add(ctx, int64(bytesWritten))
proxy.latencyRecorder.Record(ctx, streamLatency.Microseconds())
},
onRead: func(bytesRead int, timeSpentBlocking time.Duration) {
// clientRead
lastClientRead = time.Now()
},
}, &ReadWriteNotifier{
readWriter: targetConn,
onWrite: func(bytesWritten int, timeToHandoff time.Duration) {
// targetWrite
streamLatency := time.Now().Sub(lastClientRead)
ctx := context.Background()
proxy.throughputCounter.Add(ctx, int64(bytesWritten))
proxy.latencyRecorder.Record(ctx, streamLatency.Microseconds())
},
onRead: func(bytesRead int, timeSpentBlocking time.Duration) {
// targetRead
lastTargetRead = time.Now()
},
},
)

from secretless-broker.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.