Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(backend): telemetry service interface #2807

Merged
merged 10 commits into from
Jul 22, 2024

Conversation

BlairCurrey
Copy link
Contributor

@BlairCurrey BlairCurrey commented Jul 12, 2024

Changes proposed in this pull request

  • abstracts counter/histogram metric recording behind new incrementCounter, incrementCounterWithAmount, recordHistogram.
    • in addition to doing the counter .add method, incrementCounterWithAmount handles the amount conversion and privacy obfuscation
  • removes/makes private methods no longer used due to above refactor, leaving telemetry service interface with only: shutdown, incrementCounter, incrementCounterWithAmount, and recordHistogram methods

Context

Fixes: #2799

Checklist

  • Related issues linked using fixes #number
  • Tests added/updated
  • Documentation added
  • Make sure that all checks pass
  • Bruno collection updated

@github-actions github-actions bot added type: tests Testing related pkg: backend Changes in the backend package. type: source Changes business logic labels Jul 12, 2024
Copy link

netlify bot commented Jul 12, 2024

Deploy Preview for brilliant-pasca-3e80ec canceled.

Name Link
🔨 Latest commit a9feb43
🔍 Latest deploy log https://app.netlify.com/sites/brilliant-pasca-3e80ec/deploys/6697e27e1a07810008b6b6f9

opentelemetry deprecation message: "This method will be removed in SDK 2.0. Please use MeterProviderOptions.readers via the MeterProvider constructor instead"
@BlairCurrey BlairCurrey marked this pull request as ready for review July 15, 2024 18:41
@JoblersTune
Copy link
Collaborator

I'm also thinking about the wording incrementCounterWithAmount, we're always incrementing a counter by an amount. Maybe we could make it clearer by saying something like incrementCounterWithValue or incrementTransactionValueCounter or something else.

@JoblersTune
Copy link
Collaborator

JoblersTune commented Jul 16, 2024

Other than that LGTM, I'll just need to make a few tweaks with the introduction of my PR here as well. But now that I've seen all the changes that shouldn't be too big of a job :)

So let's get this in first. Then we have a clear plan on how to manage the conflicts.

Co-authored-by: Sarah Jones <sarah38186@gmail.com>
@BlairCurrey
Copy link
Contributor Author

BlairCurrey commented Jul 16, 2024

I'm also thinking about the wording incrementCounterWithAmount, we're always incrementing a counter by an amount. Maybe we could make it clearer by saying something like incrementCounterWithValue or incrementTransactionValueCounter or something else.

I somewhat agree but I'm struggling to come up with something better because "amount" is what we call objects like this across our code, which is what Amount in incrementCounterWithAmount is referring to:

interface Amount {
  value: string
  assetCode: string
  assetScale: number
}

So I think part of the problem is we just use a generic name for our specific concept of the above Amount. But here we are.

This is why I don't really like incrementCounterWithValue - because we need to pass in something like Amount (with the asset info), not just the string/number/bigint value. In fact perhaps value would be a better name for the argument in incrementCounter to help distinguish it. In fact, I'm already using value in recordHistogram. I wouldn't want to specify that it's transaction specific either (such as incrementTransactionValueCounter), because this method should work with any sort of Amount (fees, limits, etc).

But still I don't love it as-is. incrementCounter takes an amount: number but incrementCounterWithAmount takes this different kind of amount (yuck).

And in this case the amount in incrementCounterWithAmount is not actually Amount, but { sourceAmount: bigint, sourceAsset: Asset }. This was driven by the underlying convert call but I think not well-named (amount.sourceAmount kinda sucks in this context because it's the value not an Amount object and there is no non-source amount).

I'm warming up to something more like this which changes the type of amount in incrementCounterWithAmount and renames amount to value in incrementCounter. I think these keeps things consistent with our naming conventions and helps distinguish between the two increment counter methods. What do you think?

export interface TelemetryService {
  incrementCounter(
    name: string,
    value: number,
    attributes?: Record<string, unknown>
  ): void
  incrementCounterWithAmount(
    name: string,
    // value could be string or number instead, depending on what ends up making the most sense
    amount: { value: bigint, assetCode: string, assetScale, number },
    attributes?: Record<string, unknown>
  ): Promise<void>
 }

Or does it still seem unclear because we're always incrementing an amount in the generic sense? I could see that, but I would argue we need a better name for our amount like AssetAmount or something. But this introduces a new name for the same thing we have all over the place which I don't like. 🤷

const metricReader = new PeriodicExportingMetricReader({
exporter: metricExporter,
exportIntervalMillis: deps.exportIntervalMillis ?? 15000
this.meterProvider = new MeterProvider({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can delete the setting of this.meterProvider on L74 now

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whoops, yes. good catch


incrementCounter(): void {}
async incrementCounterWithAmount(): Promise<void> {}
recordHistogram(): void {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can also get rid of the getBaseAssetCode & getBaseAssetCode here as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup, removed

@mkurapov
Copy link
Contributor

I think incrementCounterWithAmount is ok based on the signature, maybe a (long) alternative is incrementCounterWithTransactionAmount?

Likewise, we can also have the incrementCounter function not take in a value: number, since incrementing counter implies its going up by one? Then we can have a private method just use '1' under the hood when doing the actual metric incrementation.

Not too big of a deal though.

@JoblersTune
Copy link
Collaborator

I was also leaning toward incrementCounterWithTransactionAmount then. It's better to have something long but clear in my opinion.

@BlairCurrey
Copy link
Contributor Author

BlairCurrey commented Jul 17, 2024

@JoblersTune @mkurapov updated to incrementCounterWithTransactionAmount.

We can leave it there if we like, although I still wonder if this is making the function name more opinionated (that the amount is a transaction amount) than the actual function body does (and should). I mean shouldn't this same method be used for other amounts, such as fees (which might actually be right around the corner)? In which case the call would be something like:

incrementCounterWithTransactionAmount('fees_amount', feeAmount)

I think the function should signify this is our concept of amount and avoid signify its for a specific use-case. The incrementCounterWithAmount name doesnt signify this is our amount currently, but the whole function signature (with arg type) does. Again, I wish we had a less generic term than "amount" for the value/asset pair concept. AssetAmount maybe, which would make this incrementCounterWithAssetAmount. I guess I dont expect that to make sense to anyone either though, since its a new convention and elsewhere we just use "amount".

Likewise, we can also have the incrementCounter function not take in a value: number, since incrementing counter implies its going up by one? Then we can have a private method just use '1' under the hood when doing the actual metric incrementation.

Didn't do this one... our incrementCounter is calling counter.add under the hood so I think we should allow passing in whatever we need to. We are using this currently in incrementCounterWithTransactionAmount and could conceivable use it outside the service via incrementCounter as well. Also seems incongruent to assume 1 in incrementCounter but then not incrementCounterWithTransactionAmount IMO. I agree there is some un-intuitiveness but for me this traces back to the opentelemetry api. I don't think "incrementing" (our word choice) implies +1, but I do think a "counter" (their name) kind of does - and obviously there is nothing we can do about that. Perhaps if anything we change our name from incrementCounter -> addToCounter (and similar).

@JoblersTune
Copy link
Collaborator

@BlairCurrey wouldn't we use a different exposed function for fees? Since I assume we don't need to do privacy stuff on fees, only asset conversions. In which case incrementCounterWithTransactionAmount and incrementCounterWitFeesAmount would arguably add more clarity?

@mkurapov
Copy link
Contributor

Didn't do this one... our incrementCounter is calling counter.add under the hood so I think we should allow passing in whatever we need to.

Makes sense, I think that's fine.

@BlairCurrey @JoblersTune for privacy preserving amounts, we can have
incrementCounterWithPrivacyTransactionAmount or just add a preservePrivacy arg into incrementCounterWithTransactionAmount

@BlairCurrey
Copy link
Contributor Author

@BlairCurrey wouldn't we use a different exposed function for fees? Since I assume we don't need to do privacy stuff on fees, only asset conversions. In which case incrementCounterWithTransactionAmount and incrementCounterWitFeesAmount would arguably add more clarity?

That's a fair point... I feel like an new arg (like @mkurapov suggested) might work well since everything else in the function would be the same (doesnt really add any complicated logic and will re-use the conversion stuff). But I could also see a new explicit method if the difference ends up being more than that... I guess we can roll with this for now and cross that bridge when we come to it.

Copy link
Contributor

@mkurapov mkurapov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, just a single comment

Comment on lines +88 to 96
deps.telemetry.incrementCounter('transactions_total', 1, {
description: 'Count of funded transactions'
})

const payDuration = payEndTime - payStartTime
deps.telemetry
.getOrCreateHistogramMetric('ilp_pay_time_ms', {
description: 'Time to complete an ILP payment'
})
.record(payDuration, {
source: deps.telemetry.getInstanceName()
})
deps.telemetry.recordHistogram('ilp_pay_time_ms', payDuration, {
description: 'Time to complete an ILP payment'
})
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should actually move these promises into a Promise.all

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they arent promises 😄. the underlying add/record sdk methods are synchronous.

incrementCounterWithTransactionAmount returns a promise due to the amount conversion.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, that's right. LGTM now

@BlairCurrey BlairCurrey merged commit 15c6ac2 into main Jul 22, 2024
36 of 42 checks passed
@BlairCurrey BlairCurrey deleted the bc/2799/tel-service-refactor branch July 22, 2024 13:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pkg: backend Changes in the backend package. type: source Changes business logic type: tests Testing related
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Update telemetryService counter collection
3 participants