Deep Dive into Metrics and Monitoring with Prometheus and Grafana - JSJ 645 - podcast episode cover

Deep Dive into Metrics and Monitoring with Prometheus and Grafana - JSJ 645

Aug 20, 20241 hr 26 min
--:--
--:--
Download Metacast podcast app
Listen to this episode in Metacast mobile app
Don't just listen to podcasts. Learn from them with transcripts, summaries, and chapters for every episode. Skim, search, and bookmark insights. Learn more

Episode description

Dive into a fascinating discussion blending the worlds of literature, gaming, and tech. In this episode, Chuck and Dan explore the intriguing connections between The Hobbit and The Lord of the Rings, including an extraordinary tale about Israeli pilots translating The Hobbit during wartime. They share insights into Guy Gavriel Kaye’s standalone novel Tigana, inspired by Renaissance Italy, and discuss the complexities and strategies of board games like Monopoly and Letters from Whitechapel.
But that’s not all. The episode takes a technical turn as the speakers delve into the dynamic world of application monitoring with Prometheus. They unpack the mechanics of event loop lag, heap usage, and GC storms, and share how Prometheus's query language (PromQL) and integration with Grafana can proactively manage and solve performance issues. Hear about real-time alerting, sophisticated querying, and the practical applications of these tools in companies like Next Insurance and Sisense.
This episode is packed with information - from managing performance metrics and alerting systems to insightful discussions on favorite standalone fantasy novels and the productivity hacks that keep our hosts on top of their game. So, sit back and join us for an engaging and informative session on Top End Devs!


Socials

Picks


Become a supporter of this podcast: https://www.spreaker.com/podcast/javascript-jabber--6102064/support.

Transcript

Speaker 1

Hey, welcome back to another episode of JavaScript Jabber. This week, on our panel, we have Dan Shapiir.

Speaker 2

Hello, from this very hot Tel Aviv. Well, isn't that a surprise somewhere in Israel? Right?

Speaker 1

It's it's also pretty hot here. It spaghetting up to one hundred degrees which is like forty forty one degrees celsius.

Speaker 2

Oh, that's actually hotter than it is here. So we've got better.

Speaker 1

It's been that way here for over a month.

Speaker 2

It's been trying your eyeballs.

Speaker 1

Just about anyway, I'm Charles Maxwood from top Endevs, and we're going to be talking about monitoring and alerting using Prometheus and Gryfauna. Now I've played with Graffana this. This was proposed by Dan, and so I figure he's probably gonna do more the talking. But yeah, just to give a little context, I don't even know what freak this is.

Speaker 2

So yeah, yeah, So to backtrack a little bit before we get into specifically what Prometheus and Grafana are, I want to talk a little bit about monitoring alerting in general.

You know, I've been working on stuff like performance monitoring and performance optimizations for a good number of years now, as you all know if you've been listening to this podcast, and probably one of the most important lessons that I've learned is that you need to have monitoring in place and alerting in place before you start any work on improving things. And in this context, I love a quote

from Peter Drucker. Peter Drucker more or less created the field of business management, and the quote is, if you can't measure it, you can't improve it. And I'm really a big fan of that. If you're unable to measure something, there's really no way for you to know if you're making progress, if you're improving things, or if you're actually

degrading things or making no impact at all. And one of the things that I've done in this context is that whenever I, like say, I join a new company or start a new project, I often find myself under pressure to start delivering improvements, you know, from the get go as quickly as possible, and I always push back on that in order to make sure that we have proper data collection and proper moneying in place before we

start making any improvements. By the way, in this context, is probably not surprising that I joined Size Sense, which is a bi analytics company because I'm really a big believer in that. And you know, as an extra benefit if you're doing this kind of work, one of the big benefits of having some sort of measurement and monitoring solution in place is that after you've made improvements, you have graphs to show the impact of your hard work.

And from my experience, that's really beneficial when you're let's say you're looking for raise or advancement or something like that. But really in order to be successful in any project that requires taking a system and trying to let's say, improve it, then having some sort of a monitoring capability place is crucial. Now the question obviously then becomes what do I actually use for that. I mean, you know, it's fairly straightforward to collect a lot of data these days,

but what do you do with it? Where do you put it, how do you process it, how do you visualize it, et cetera. And And in this context, I want to talk specifically about two things, which are Prometheus and Gofana. And first I'll start with a riddle for you, Chuck, do you know like who Prometheus was?

Speaker 1

Like you know, he was a titan that brought us fire? Right, wow mythology, and he was he was punished by having what an eagle eat his entrails out.

Speaker 2

Exactly that he was tied to a mountain on the well, I think with the Tartarus mountains, and then Zeus's eagle will would come once a day and eat his entrails, and because he's immortally he cannot die, so he suffers forever. By the way, later times Greeks or Romans kind of thought that this was like too bad of a fate, so they had Hercules release him or something along these lines.

But the no, I can't prove it. But I think that the reason that this project was called Prometheus is because it's about bringing knowledge, because fire in this context is like synonymous with knowledge, knowledge from the gods to the humans. So it's about bringing knowledge to us developers about how our systems are operating. So that's the mythology of what Prometheus is. Now let's talk about what Prometheus

the service is. So Prometheus is free software as an open source that you can install on premises or you can use as a service I think as well that is used for event monitoring alerting. It was originally created something like twelve years ago at SoundCloud when they came to the conclusion that none of the third party solutions

for monitoring were sufficient for their needs. And after they built their system and used it internally, about four years later, they donated it to the Cloud Native Computing Foundation, which is the same foundation that also hosts the cumbernitese project. So you know, this is another successful project from that foundation. I think the people who are mostly working on it these days are the people from the company that does Grafana.

But again it's open source and you can see the source code on GitHub and there are a lot of contributors. I actually personally contributed to one of the satellite projects around Prometheus, which is the Prometheus client for node which makes it possible to connect node js to Prometheus in order to monitor NOE. So I contributed specifically specifically to that part of the project.

Speaker 1

I'm gonna stop you just for a minute. I've been posting the links in the comments, but they don't go to x and that's where most of our live listeners are. So Prometheus is Prometheus dot io and Graffana is at graffana dot com.

Speaker 2

So anyway, yeah, that's true. Okay, So, so where were we So we were talking about a little bit about the history of Prometheus, both the pathological figure and the project. Now let's talk a little bit about what it actually is.

So it's a service used for event monitoring, alerting. It records real time metrics in something called a time series database, which is kind of a special type of database, and we'll talk about it in more detail and how it differs from the databases that most of us are familiar with. It allows for something called high dimensionality, which I also will try to explain. It supports flexible queries and real time alerting. And as I said, it's free software. It's

licensed under the Apache two license. So that's what Prometheus is. So let's say you want to use Prometheus in your organization. What you would do is that you would install the Prometheus service and then hook it up to your various services that you want to monitor. Now, it's a monitoring solution for back end infrastructure, so things like no JS or for you know, the JVM, or for something that's say written in Go. Because that's not surprising because Prometheus

itself is actually written in Go. So maybe it's a shame that we don't have aj on the show this time.

Speaker 1

Yeah. Maybe, but but your point is is that you know, any any language or system could have a driver that yes.

Speaker 2

There's basically a connector for anything. There are also connectors for a lot of general services. So if you want to monitor, let's say we were talking about Kubernetes, you can monitor Kubernetes. Kubernetes has a built in connector for Prometheus, so you can look at how pods are functioning, or

the Kubernetes cluster itself. There are connectors for various AWS services and so on and so forth, so you can collect a lot of data from third party services and infrastructure, and you can also attach it like create applicative level monitoring, so you can monitor the behavior of your own applications that are running on platforms such as the JVM, such as no JS or in Go, etc. Well more or less any programming language that you can think of. Now.

The way that you configure the system, so again not very surprising, given perhaps that it's certain in Go the configuration are yamal files, and again this is kind of correlated with Kubernetes. So Yamal, for those of our listeners who somehow don't know, is a configuration format. You can think of it to an extent kind of sort of similar to what we usually do with Jason files, but it's a different format. It has certain advantages over JSON. For example, it supports comments. It's used by a lot

for a lot of administrative stuff. So any DevOps person is likely very familiar with Yamo.

Speaker 1

The default configus for rails were all done in Yammo as well.

Speaker 2

So yeah, so you basically create configuration files for Prometheus in Yamel. And the way that Prometheus works is kind of the reverse of what you might expect. So you might think that you somehow configure various systems to push data into Prometheus, but that's not how it works. The way that it actually works is that Prometheus data into itself.

So in the yamal file, you tell Prometheus the address of the various addresses of the various services that you wanted to monitor and the rate at which it should effectively ping those services, and it effectively does an HTTP get to an end points exposed by these services and downloads data from them. So it actually pulls the data from them into itself. Now, the advantage of this approach is that first of all, they don't need to be aware of where the Prometheus server is, so it's all

the configuration is centralized. They just need to open the port, you know, listen on it, and that's more or less. It also means that they can work with multiple Prometheus service servers at the same time because they all just pull the data, because pulling the data doesn't clear the data. It's not as if, you know, they give the data and then forget it it. They retain the data. Those services are expected to retain their data in memory, so you can just hit any one of them at any

time and pull from them their current situation state. I hope that's clear.

Speaker 1

Yeap makes sense to me. I kind of like it too, just from the standpoint of so I've used other systems, paid systems, you know, we've been sponsored in the past by Century and ray Gun and stuff like that that grab a lot of this information. Though I think we're talking kind of a level below that right where we're not talking specifically about the information that's being sent. We're just talking about how the information gets into the system.

At this point, I like the fact that it's like, Okay, I'm gonna periodically check and then I don't have ten million hits on the service on the other end, right, because I'm not pushing it to it, it's pulling it, and so it only does the work that it has to do, right Yeah, Yeah, I don't have all this extra network crap going on.

Speaker 2

Yeah. So it basically does an AGTP get let's say once every minute to any one of those services. The response is essentially texts in their own format. It's quite readable actually, so you could literally go to one of those endpoints and just hit it with your browser and see what the response would be. By the way, obviously you probably want to make sure that those endpoints are not externally exposed, so you know that everything stays behind

the firewall. The one kind of caveat to that is that sometimes you have like short lived services, think about something like a lambda. In that case, what they have is something called a push gateway, which is like a standalone service that those show or lived jobs can push data in. Because they are really short lived, so you can't assume that they'll hang around until they're they're pulled again.

So they can push their data into that push gateway, which holds onto that data, and then Prometheus pulls that data from that push gateway. So it's kind of an intermediary service that that you know, for those special cases. But in most cases and the cases that I've used it in, you know, it was with long lived servers or services, and then you know that's just the way it worked, right.

Speaker 1

That makes a lot of sense too, just in the yeah, like I'm thinking like serviles functions and things like that, or you know, if you we've also run background jobs a lot in the apps that I have right where it pulls it off the queue and then runs it. And so yeah, in either of those cases, Yeah, you don't want or necessarily need something hanging out so that it can say, oh, you're going to query me within the next minute or so, it just says poof, I'm done and then hands it off, right.

Speaker 2

Yeah. So there's for example, in the case of node JS, there's a Prometheus client for node I think it's literally the project is really literally as I recall, called Prome client. So you just NPM install it and then you know it's in there. You just give it to the port to listen on and then it does you know, just let's say it uses express or something like that, and then it basically collects the information and exposes that to that port for you, and you don't really need to

do anything to start monitoring basic system level stuff. Now, the Prometheus server gets the data in and then put saves it into its own percise database, right, and that database is what I call the time series database. And what I mean by that is that Prometheus doesn't store data, Like, don't think of it something like a database, you know, we tend to think of something like a relational database or maybe a low sequel database. That's not really that

sort of a thing. It's something called the time series database. So basically it has metrics, and it basically saves the value of a metric at every point in time, so it's really like keeps on collecting metric data. So there's no such thing really as schemas or something like that. It just has metrics that it collects data into, and it's data collected over time. So like think of I don't know, let's say you're let's say you're a farmer and you've got a field and you're measuring the temperature

in the field. So you've got the temperature measurement. Let's say every minute that you got from from the whatever, you know, the thermonitor device that you use to monitor the temperature, and it just gets recorded into that persistent storage and you can go backward and forward in time and look at any point in time what the temperature was. Right.

Speaker 1

So I'm trying to imagine what this looks like for an app. So is it measuring like how much CPU it's using and how much memory? Oh we'll get into that.

Speaker 2

Okay, yeah, we'll get into that. But basically, as I was saying, you can.

Speaker 1

I'll keep my enthusiasm down for a minute.

Speaker 2

Then it's it's you know what, let's talk about that a little bit. So it's really monitoring two types of information. One you can think about it as system level stuff. So in these context of node a node server, that might be CPU usage or memory slash heap usage, or the event loop lag or if it's an express service, the number of requests per period of time or the duration of the responses stuff like that. So those are

system level things and they're collected for you automatically. So as soon as you NPM install the prompt client for node and it is loaded into your project, your node server, then all that stuff is automatically collected for you, and when the promitth your server hits that port that information, those metrics are available from the get go. On top of that, you can add applicative level metrics that you

push into Prometheus using an API. So, for example, if you've got like your own let's say QUES internal cues that you want to monitor the usage of, or your own business logic processes that you want to measure the duration of, you can measure those as well. Okay, so you've got both the system level stuff and the applicative stuff. And by the way, one system level stuff that is really important in the context of no that may be less obvious or familiar to some of our listeners is

something called the event loop LAG. Are you familiar with that?

Speaker 1

I am not.

Speaker 2

So, as you know, the way the JavaScript works is that it's all based on an event loop, be it either in the browser or in node JavaScript. The way that it works is you've got whenever something happens, like if it's a browser, then it's something arrives over the network or the user does some sort of an interaction

a mouse click, a keyboard press. Whenever something happens, an event is triggered and that puts the event information in a queue, and JavaScript which behaves is in a runs kind of in a single threaded type approach, pulls data out the most the top data out of the queue, processes it, and then moves to the next item in the queue, the next item in the queue, and so forth until you know. If the queue becomes empty, then it effectively idles until another stuff is put into the queue.

Speaker 1

So far, so good, yep.

Speaker 2

Now, the problem is that usually rather than idling, what happens really is that information comes into gets into the queue at a very rapid pace, at a high clip. So it might new new events are placed into the queue before the the before the jobscript engine is ready to process them, because it's still busy processing other stuff. Like you think about, Let's say a node server running express the events coming in are are the HDP requests.

If HDP requests arrive at a too high rate, then then the node service might not be able to process them quickly enough and will get overloaded. Right, So, what the event loop plaque actually measures is the amount of time from when a message is placed into the queue until it's taken out of the queue in order to be processed. So If that period of time is small,

then you know that your service is really responsive. If it gets to be too high, that it means you know, your your system is overloaded and and it's not responsive enough. You know, if think about think about a service, an express service that takes I don't know two seconds to get to pull something out of the queue, it means that the browser, the client side, is waiting for two

seconds before it's it's event is even processed. So obviously that's a bad thing, and it's especially bad if it keeps on growing, because then eventually your service server will just become a response right. So that's information that Prometheus that the system, the prompt client is actually able to extract out of node and exposes that into Prometheus. So that's one of the system monitoring things that's really useful

to look at when you're monitoring a node service. Another thing that's really useful to look at is, for example, heap usage, because if you've got let's say, some sort of memory leak, then you'll see that after a garbage collection a GC, rather than going all the way down your memory, just utilization keeps going up and up and up and up and again. That if it keeps on going. What will happen is that the node service will try to do GCS more and more and more and more

in order to free memory. But to do so and you get what's known as a GC storm, or effectively, the service all it does is just try to free up memory that it can't and it becomes totally stuck. So that's another thing that you can look at in the context of Prometheus.

Speaker 1

Well, it seems like on both of those measures, on the lag in what is it node event loop lag, it seems like because I'm sitting here and I'm thinking, okay, so it's gonna tell me if it doesn't have the resources to handle whatever's coming at it. But for me, I find it useful because I mean, let's just take podcasting for an example, Right, Like I don't go and religiously obsess over the numbers, right, I don't go look

at the metrics. But for an app, if you're checking the metrics on a regular basis, it seems like you could start to see this lag event loop flag steadily increasing and go, Okay, we are getting to the point where we need to start looking at right, instead of all of a sudden being whoa, whoa, whoa. We're you know, we're way over the edge, right, And so it allows you to be proactive, right instead of reacting to people are complaining it's slow.

Speaker 2

Yeah. And actually, what you really want is to have good alerting, and we'll get to that as well, because yeah, yeah, because realistically, you're not going to check the graphs for all your services every morning or every afternoon. What you really want is you want a system that alerts you in case something is wrong. And you usually want an alert to say not that you know system is broken.

You want an alert to tell you you know, system is running hot, you should you should do something before it breaks, right, And yeah, and and Prometheus is great for that as well because you can specify alerts. And so that's the other part. So I was talking about how all the data is collected into the Prometheus service and then saved into persistent storage. But then you can also do queries on top of that data. Prometheus has its own query language. It's called prom ql, and it

looks nothing like SQL. You know, even though it's a query language, it's a totally different query language as well.

Speaker 1

As a query language, and it doesn't look.

Speaker 2

Like exactly, and you can do two sort of things. You can have Graffana as a visualization environment. So Graffana is the service so that you run in the browser and it can show you all sorts of graphs from various data sources, and one of the data sources is Prometheus, and you can write prom ql queries that extract data and then graph this data in whatever dashboard you're using.

So that's one possible usage. Another possible usage is something called the alert Manager, which is another component of Prometheus that comes along with it. It's a standalone service that does regular that every at regular intervals, it runs uh prom ql queries, gets the data from them, and sees if they're if alerting criteria are met, and if they are, it can then push alerts into emails or Slack or page your duty or whatever, so that you can generate

alerts out of the promit out of the Prometheus data. So, for example, going back to that farmer and field and thermometer example, you could say that if the temperature goes above I don't know, thirty degrees on the ground, send an alert something along these thoughts.

Speaker 1

Yeah, that makes sense.

Speaker 2

Yeah, So.

Speaker 1

I just want to throw in here real quick, because I think sometimes we kind of treat the time series data as kind of monolithic in ways, like treating it like for the day or the week.

Speaker 2

Right.

Speaker 1

I was actually looking on the Discord server that we use for the hosts and Adventures and DevOps. They were going to do an episode where they were talking about holiday rushes, right, And so one day to the next, it may vary, or you may get a lot of your traffic in the morning or the evening, and so you know, by having these alerts, you can start to

pick up some of the patterns. And the other thing is is you can turn around and you can say, Okay, not only do I know that something's happening now, but I can go look at the current state of things or get a snapshot from the Prometheus data, and then start to solve whatever is the issue is, right, whether it's I need more resources or oh I didn't realize, but I built something into the application that makes it memory heavy, and so my heap size is going out

of control and I'm running out of memory or whatever.

Speaker 2

For sure, But definitely also the fact that data can vary over time, even if regularly, can make some of this stuff pretty challenging, but still doable. PROMQL is a very sophisticated QUERI language, and I'll give examples of some of the challenges that I've run into when creating alerts. So, for example, a lot of companies that I've worked for, companies like Wix or Next Insurance, there was a lot more traffic let's say, over the week days than over

the week ends, which is not surprising. But the downside of that was that data over the weekend would fluctuate a lot a lot more because the sampling size was significantly lower. When you think about it, let's say you have let's say talk about Next Insurance. You might have ten thousand sessions in a week, you know, working in a week day in a working day, but only one hundred over the weekend. And when you've got only one hundred sessions, then ten bad sessions can really impact your

performance numbers. So and then we would see that if we weren't careful, we would start getting alerts over the weekends because the data was less stable because there were just fewer sessions. So we basically kind of had to come up with queries that were also dependent on the number of sessions, not just the duration of the sessions, So if there were too few sessions, we would ignore the other criteria of the duration of the sessions. So that might be something. You know, it makes the queries

more challenging. But you want to take these sort of things into account. So quickly going back to when is Prometheus a good match and when isn't it a good match? What type of data would you want to put into Prometheus and what kind of data you would probably want to put somewhere else. So Prometheus is a good match

when you're recording pure numeric time series data. It's appropriate for machine centric monitoring, you're monitoring systems when it's highly dynamic service oriented architectures, because you know, this whole pull type mechanism makes it very easy to adjust to additional instances coming up or going down in a very dynamic

sort of a manner. And again i'll talk about it assuming we have the time something, but it's very important when the data is multi dimensional and both in the collection and the querying, and I'll explain what that is a bit later on. Now, when is it not a good match. First of all, it's not a good match when you need one hundred percent accuracy So for example, if you're looking at stuff like billing, when the numbers have to be perfect, then Prometheus is not a good solution.

Prometheus in most cases kind of averages out data because again, when you're looking at stuff like CPU usage, it doesn't really matter if you're running at ninety three or ninety three point two or even ninety four percent. But if you know, obviously, if you're looking at stuff like, you know, your taxes, you probably need to be accurate. Uh, it's not approprix.

Speaker 1

Sorry you said, don't talk to me about taxes right now.

Speaker 2

Yeah, yeah, anyway, Uh, it's not. It's also not appropriate when you're recording non numeric data. So for example, if you're recording stuff like email addresses or phone numbers, even even though they seem like they're numeric, they're not really, or you know, street addresses, stuff like that, that's not appropriate. And it's also not appropriate when the data has to be totally persistent, when you know when it's you can't

afford to lose any data. As I said, Prometheus pulls the data, pulls the data out of the very services at regular intervals, let's say every one minute. If that service crashes during that one minute, you've lost the data since you previously pulled it. And that's obviously not something that you can live with in a lot of cases where you need persistent data and you know, if it's if you're dealing with bank accounts and stuff like that, you can't afford to lose transactions or stuff like that.

Speaker 1

So yeah, but it seems like most people are pulling or using it by putting this client onto their application, and so it's it's only recording those specific kinds of data. You're talking about a custom use of Prometheus where you might push other data into it as.

Speaker 2

Well, exactly exactly. Now, it can be a challenge because again, let's say you're pulling, you're pulling the data or pulling it in every minute, and if your server has a problem that in a certain scenario, memory consumption like rockets out of control and then the server crashes, then you might not be able to catch that if it, you know, if it happens within the spence of the span of a few seconds. So you can either then try to increase the rate at which you pull and hope that

you're lucky, or look at for some other solution. Right, as I said, it has integrations for no JVM, Go, Python, Ruby, and in terms of systems, stuff like Kubernetes, git Lab, AWS, Gira, mongo dB, reddis. For visualization, usually you'd use Gofana, even though it also has its own built in simple visualization capabilities.

AH And it's compatible with open Telemetry, so if you're using open telemetry for collecting telemetry information, you can also use open Telemetry on top of Promethea and have open Telemetry put it data, put its data the data that it collects into the relevant data, the time series data into Prometheus. So there are several types of metrics and they're appropriate for different scenarios. So very quickly going over the different metric types, you've got something called a counter counter.

Think about you know, the if you're let's say, think

about a club. Let's say that you want to go into and there's somebody at the door with this kind of a counter device clicking it every time somebody goes in, like counting the number of people inside, because you know, the fire regulations only allow up to x number of people to be inside at the same time, and they so they need to count the number of people going in and the number of number people coming out to make sure that you know they don't exceed those limits.

So counter is really something like that. It's a metric that that can only increase and you basically add one or add an your end, which is like adding one end times, so you basically just add add into it and it keeps on getting higher. Can you think about things that you would measure using something like like a counter.

Speaker 1

Yeah, like the number of requests that come in or so.

Speaker 2

Funnily that that's that's that's literally the first example that I have. So the request count is exactly such a such a thing, tasks completed, error count, all these kind of things that only go up. They only increase until

at least until you restart the service, right. And the cool thing about a counter is that because of this behavior of only increasing, you can compute the rate of increase, which makes it possible to have predictions because if you can calculate the rate, then you can also predict where you'll be in a certain amount of time.

Speaker 1

Makes sense.

Speaker 2

Yeah, So that's the simplest type of metric. Again, it's used automatically for things like a request counter or a task complete counters, or an error counter or stuff like that, But you can also create your own applicative counter if you want to count your own stuff. Right. The next type of metric is called a gauge, and it records a value that can go up or down or literally

be set at any value that you want. So you can literally say, say, the value of this gauge right now is x. Again, can you think of when you might use a gauge? This would be like Q size or shuck, are you looking at my slides? No?

Speaker 3

Because again that's the first item that I have on my slide for using it is the Q is Q size exactly Q size, memory usage, CPU usage, number of requests in currently in progress, all these sort of things that.

Speaker 2

You just set it to a particular value at each point in time now the key, so it can go up and down or be set to particular value. The thing about it, though, is that because it's so arbitrary, you can't use it to assess rate of change, because if you can just jump between numbers, there's no really meaningful rate that you can think about.

Speaker 1

Yeah, you can average it out, but yeah, the next.

Speaker 2

One is slightly more complicated. And when I actually have presentations that I do that I so far have done internally, I'm kind of looking for conference who wants to talk about this. But if you want to be able to measure things like histogram like sorry, like averages or even more importantly, percentages like the median or the ninety eighth percentage or stuff like that, then you use a metric

called a histogram. Now that might seem surprising why it's called a histogram if it's used to measure percentiles for example, And I'll explain it. I'll try to explain it in a minute. But can you think about when you want something like percentiles.

Speaker 1

I would think like memory usage or.

Speaker 2

No memory usage. We talked about counter Well what.

Speaker 1

I what I meant was, you know, or percentage of like memory used or percentage of resources used. So what they have is something I'm not understanding.

Speaker 2

What it is, so I'll give it. I'll give examples, and I think that then it will click for you. So think about something like request duration, like oh I gotcha, So you want to say, like my median request I got yeah, ndering duration is x or the ninetieth percentile is why. Another example might be the response size, So you might say my average response size or my median response size is such and such, it goes up to something else when I'm looking looking at the ninety ninth percentile.

So you kind of want to be able to get the measurements but then use them in order to calculate, as I said, percentiles right now, though, it's called a histogram because the way that it's actually implemented is that internally you create buckets. You can say, let's say, like

let's say you're talking about request duration. You'd say, I have a bucket from zero to ten milliseconds, from ten million seconds to fifty million seconds, from fifty million seconds to one hundred million seconds, and anything above one hundred million seconds, okay, And each measurement goes into one of these buckets, and then you look at how many fell into each one of those buckets, and then you can use it to calculate percentiles.

Speaker 1

Right, No, that makes sense.

Speaker 2

So it's like a dist for each point in time. Right.

Speaker 1

The thing that I'm imagining is anything that you would put like on a bell curve or something like that, right, And so then then you're, yeah, your ninetieth percentile is you know, out on the end.

Speaker 2

Right.

Speaker 1

But so these are kind of rare, but they're also kind of the extreme that you have to deal with. Right, So it's a histogram.

Speaker 2

It's a histogram that gets recorded and updated at every interval, so it's like a histogram over time.

Speaker 1

Oh interesting, so you could you could literally see like the hump move or whatever exactly.

Speaker 2

You say, this is my histogram, now, this is my Instagram a minute later, this is my Instagram another minute later, and so interesting. Okay, so hopefully that's kind of clear. Now there's another metrical summary. I don't want to get into it. It's it's it's more rarely and uncommonly used, so we'll skip it for now. You know, we're starting to run long in any event, because what I really wanted to talk about was the concept of labels and dimensionality.

So let's go back again to that field example of the farmer wanting to measure let's say, humidity and temperature in the field in their field. But it's a big field, so they're not using just a single measurement device. They've got devices spread out in different locations in the field. So one way in which you might think about it is that we'll create a separate metric for each one

of those measurement devices. But the way that Prometheus looks at it is that we've got a single temperature metric, but for each measurement we associate labels with it, and that label is textual value. It might be the name or the idea of the specific measurement device. So let's say I've got four devices in the field. They're called ABC and D. I've got the single temperature metric, but each measurement is associated with either A or B or C or D. Mm hmmm is that clear?

Speaker 1

Yep.

Speaker 2

So now what's the benefit of this approach is that it's very dynamic. If if I, if I add and if I you know, if I buy some more land and I now need also an E N f U measurements, I don't need to create new metrics. It's the same metric, but it's associated, but there are the new values coming in are associated with new label values. So I've got a label called you know, the device name, but it

can come in with any any arbitrary textual value. And then when I querry the data, I can say, show me just the values for the metric for measurement for when the label is equal to A or to A or B or A and B because when you do queries in the prom ql query language, you can either set a label like in the query to have a specific value or use a regular expression.

Speaker 1

Okay, So I'm imagining that you could do this if you're spinning up say another doctor container or server exactly.

Speaker 2

So you might have the pod name. You would have a label called pod name, and the value is the name of the pod, right yep. And you can have any number of labels associated with each metric, and those labels can have any number of values.

Speaker 1

Okay.

Speaker 2

Now that I think highlights the potential issue of dimensionality because it makes the system very flexible. But you'll see the problem in a minute. So let's say I have a metric and I have three labels associated with it. So it's actually they defined a three dimensional space for that metric because each measurement has a coordinate that is specified by the values of those three labels. Okay, is that clear? I'm kind of waving my hands, think about it.

So think about again, going back to the field example, and let's say that instead of having each measurement in the field have its own aim, it has a coordinate in the field, so it has an x access, an x value, and a y value, So it's a two dimensional space.

Speaker 1

Okay.

Speaker 2

Now, now in reality, like again, when you're measuring things, you might have many more labels than that, so it becomes an n dimensional space. Right And if for any so and the the the for each access, the number of points on that access is the number of different values that label might have. Okay, So let's say I have three labels and each one has ten potential values? How many how many points? How many different numbers in that space?

Speaker 1

Can I have thousand?

Speaker 2

Exactly? So I need to remember one thousand different numbers.

Speaker 1

For that single metric, right and make sense of it hopefully.

Speaker 2

Yeah, But the problem is that if I'm not careful with the number of labels that I used, and especially the number of different values that each label might have, I can literally blow up my memory. Right and again going back to how Prometheus works, that Prometheus pools that say you have a note server, and Prometheus pulls the data from the node server once every minute. So no, that node server keeps all that data in its memory. Oh okay, if you're not careful, you'll blow up notes memory.

If you've got if you've got so I'll given a real example. We were using Prometheus to monitor data associated with the with the page performance at her next insurance, and so one of the labels was the r L.

Speaker 1

H.

Speaker 2

We had something like two thousand different pages, Okay, so we had a label call. So one of the dimensions was was the r L and it had two thousand possible different values. Actually, if we weren't careful, it could have had a lot worse if we didn't filter out parameters, query parameters and stuff like that exactly. And another label that we had was device type because we wanted to

distinguish between desktop and mobile. And another label that we had was the browser the browser type because we wanted to distinguish between performance at say on chroman on Safari. Right, So think about it. It's two thousand different URLs times ten different browsers, times three or four different types of devices or five types of devices, and all of a sudden, and for each one of those three dimension coordinates, you

need to remember a metric, so it's a number. So it's millions of numbers that I need to that you're holding on in memory, and we literally kind of blew up the memory space. So yeah, so you need to be careful when when you're like Cavalier about the number of labels and dimensions that you're using. So it's called cardinality, and basically you need to be beware of high cardinality. Right. But the the benefit is that that system is extremely flexible.

Like if there's a new if there's a new r L, you don't need to do any modification in the system. It automatically adjusts to that because it just associates a label value with that particular and another label value with that particular metric. Right now, there's all sorts of things about naming conventions. I won't go into that about how you name your metrics and how you name your labels, I won't go into that. I will say that there's a really cool API for working with all the different

UH metric types. So we talked about counter engage and histogram, so you can there's a if you import the prom UH PROM Client uh NPM package, then you get those APIs that you can push your numbers with associated labels into the system and they just get recorded. Right. So again, you might have let's say, UH some sort of business logic process that UH that you know hits does all sorts of things go to it goes to one database, goes to another database does all sorts of things, and

you want to measure its duration overall. Or maybe you've got your own like custom queue for something and you want to measure the size of that queue, or you've got something like that or a pool that you want. Let's say you're you're you're utilizing your own custom pool of resources, and you want to make sure that you've

made the pool not too big, not too small. Then again you could be looking at the size of that pool and how many what's what's its utilization at each point in time, So you can, through those APIs measure your own business logic values. And the example that I gave is we were actually using it to measure core web vitals. If you remember, we've had a lot of uh yeah, exactly. Now, those are metrics that are actually measured on the browser side. So you might ask how

did they make their way into PROMI. Well, we would collect this data on the client side, post it to the node server, and the node server would use that API to put it into Prometheus. Right, So this way you can collect data not just from the node side, but also from the browser side. Again, it could be a system level stuff like corere vitals, or it could be applicative stuff. You know, whatever your web application happens to be doing that you would like to measure and monitor.

Speaker 1

That's cool.

Speaker 2

Yeah. So now the final piece that I wanted to mention is how to get data out of Prometheus. So, as I mentioned, there's a query language called prom ql. That's prom Ql, and like I said, it's definitely not SQL. It can do stuff like factoring data, aggregating data, run all sorts of predictive functions tech quantiles, which is a

fancy name for percentiles and averages and whatnot. And it can be used to answer questions like what's the ninety fifth pers centile latency in each data center over the past months, right, you know, so very sophisticated queries, or how full will the discs be in four days? So here's an example of a predictive query, or which servers are the top five users of CPU? All these sorts of queries, and you can either use these queries in order to graph things or in order to create alerts.

Speaker 1

M okay, And that's what Rawana does. Yes, it uses Promql to do this stuff exactly.

Speaker 2

So in Gafana, what you do is you create a graph, and in the graph you specify Prometheus as the data source, and you write the prom ql query, and then it basically graphs that query over time m and it has all sorts of fancy graphs, so you can do like line sharts and bar charts and heat maps and all sorts of really fancy, fancy graphs, and it's really powerful. If you're interested in this sort of stuff, I highly recommend just going into YouTube, let's say, and searching for

for pomql. There's also on the Prometheus website there's like there's documentation and tutorials for prom ql as well, so we can post links to that later on in the in the notes. Obviously, if this was a talk, then I would actually be showing examples of a prom ql but you know, I can't really do that. But exactly so, you would put prom ql in one of two places,

either in something so actually one of three places. So the Prometheus itself has its own simple web interface where you can put in prom q ol queries and get data either in tabular as basically just numbers tabular representation of numbers or in simple graphs. If you want much more sophisticated graphs, then you can use gfana, and gfana actually has a pretty sophisticated editor for prom ql, so

it does automatic completion for you. It knows all the metrics in the system and the labels and the different label values, so it can actually do autocomplete for you when you're typing in the queries. Yeah, it's it's it's really nice. It's as I think I said, it's kind of they're kind of sister projects, so it's it's the same people working on both of them, so they made

sure that the integration is really nice. And you can also use the prom ql in the alert manager where you would type the queries in the YAMO files and then you they get run automatically at periods and if they come back with data that matches the query, then an alert gets raised. So you run a query. If it comes back no data, no alert. If it comes back with data, then there's an alert. So the an alert query might be do I the number of CPUs

that are at utilization higher than eighty percent? Right? And if the number is zero, then there's no alert. If the number is greater than zero than there would be an alert makes sense something like that, And it's actually even more sophisticated than that because you can say you want to avoid like peaks, momentary peaks, so you might say it needs to be higher than eighty percent over a period of two minutes.

Speaker 1

Right, stuff like that makes sense.

Speaker 2

Yeah, so it's it's a very sophisticated and powerful system.

Speaker 1

So is this something it sounds like something used at next Insurance. Is this something that you're using.

Speaker 2

Well, yeah, we're also using it as license. So for example, when we deploy our service, our customers have the ability to run our services on premises and then they can collect monitoring data for our own services inside an instance of Prometheus that do that we installed with it.

Speaker 1

That's cool.

Speaker 2

But like I said, it's a really powerful system and and it's really flexible. And again if you want to do monitoring or alerting, probably want to do both, then it's a very good solution for that.

Speaker 1

Nice and that more or less covers it.

Speaker 2

Like I said, I have a talk presentation on it in which I, you know, I am able to show actual examples and and and and visuals, so it's you know, more more more informative if you're interested in that, if you're running a conference and you're interested in that, I'm shopping this talk out.

Speaker 1

Nice. Well, I mean this is something that I've kind of been contemplating figuring out how to put into my own systems, right, I mean, I I send data into I have a self hosted version of Century is the thing I've been using lately, and it collects some of

this kind of data. But you know, I've gotten more and more into self hosting my own kind of thing and and running through some of this, right, and it sounds like this this is right kind of right up that alley too, where it's okay when I deploy right, it just you know, it makes sure that I have a Grafana and a Prometheus instance setup that it just reports to exactly.

Speaker 2

Now, obviously there are overlap between these sort of systems, but I think their focus is kind of like not exactly the same. So let's say, if you're doing like error logging, then you know Century is the tool for you. I think I said that Prometheus is not the appropriate tool for textual information. So if you're looking and stuff like keeping stuff like stack traces and stuff like that,

then you want to use something like Centric. You know, you could theoretically count the occurrences of a particular type of error, but yeah, you probably want to use Centric for something like that. Also, Centriy has the stuff that's specifically intended for performance monitoring a certain scenarios. But if you want to do more general purpose monitoring and system level monitoring and and monitoring applicative stuff, then Prometheus could be the solution for you.

Speaker 1

Right. I also like that, you know, as it aggregates that data effectively, what you can learn from it is only limited by I guess what it's measuring, but also what you can come up with the query out of it.

Speaker 2

Oh yeah, for sure, I created some amazing query using prom QA. Like so I'll give that example. So at the next insurance, we had something like fifty services in a service oriented architecture which we're communicating with each other over various API end points, and we wanted alerts to be fired when, certainly when any endpoint in the system became too slow. But then the question was what does

too slow mean? Because you know, it can't be absolute numbers, because if something it usually takes fifty milliseconds, and then all of a sudden it grows to one hundred milliseconds, that means it's too slow. But if something always runs at one hundred milliseconds and then becomes one hundred and ten, well that's a smaller change than you might want to

ignore it. So you can't look at absolute numbers. So we I created really sophisticated queries that basically looked at behavior over time and tried to see if something became significantly slower compared to its own specific behavior from you know, previous durations. And also again wanted to only look at those endpoints which were sufficiently used, because if there was some endpoint that was hardly ever used and we probably don't care about it, right, So yes, so you can

create really sophisticated queries like that. And it was exactly because with all these end points, you don't want to have to tell somebody a developer where well, you know, you're in charge of a service that has one hundred different API en points. You need to look every day at one hundred different graphs to figure out if there's a problem. You want it so you want you want an alert to be sent to their right to the

Slack channel. Let's say, of that particular team, if any one of those end points all of a sudden became slower in a way that really impacts potentially impacts the system as a whole. Right, and and yeah that's what that's one of the projects that I did at Next Insurance, and we use cool and we use Prometheus and go fun of that.

Speaker 1

Very cool.

Speaker 2

So when when alert like that was sent to the Slack channel, the on call member of the team could actually click a link see the graph for that the performance of that endpoint in GOFANA over time, and say, okay, we actually have a problem, or no, this is just you know, a fluke or something that we can ignore.

Speaker 1

Yeah, yeah, it spiked for such and such a thing and no big deal.

Speaker 2

Yeah we were doing something. We ran some sort of a backup service and you know that's why it impacted everything.

Speaker 1

And right, or you migrated some data on the back end and it slowed it down for two minutes.

Speaker 4

And then exactly yeah, awesome, all right, Well, we put some links into the the comments on twitch and YouTube and Facebook if you want to go find those.

Speaker 1

We'll try and get them into the show notes as well. But let's go ahead and do some pics.

Speaker 2

For sure, although I don't have that many. Okay, I actually do have something. So for some inexplicable reason, I decided to start tweeting out my favorite standalone fantasy novels or books. You know, fantasy tends to be written as a lengthy series of books or at least trilogies, but occasionally I just want to read one book that stands on its own, merit on its own, because you know, it starts and it ends and you can move on

to something, to the next thing. So I started to tweet out the collect my list of the top standalone fantasy books, and you know what, I'll use each I'll pick each one at the time. So let's see which one one was my first? Can you think of one? There's the obvious choice, by the way, which is I think the Hobbit's I.

Speaker 1

Was thinking that, but then I was like, I don't know if he considers that part of a series, because it is sort of a prequel to Fellowship of the Ring and that series.

Speaker 2

Yeah, yeah, I think it's.

Speaker 1

Yeah.

Speaker 2

Yeah. First of all, it's totally self contained, and the second important thing is that it was written well before a lot of the Rings was written. Yes, So Tolkien actually wrote a lot of the Rings because there the publisher was so happy with the success of The Hobbit that they wanted more stories in that world, and it was his idea to transform it from a child's story to a story for grown ups. But so the Hobbit was originally written for his written for his children, although

a lot of adults like that story as well. Oh yeah, you know what, I'll tell you another interesting story about about the Hobbit. So there's a So, there are a couple of translations of The Hobbit into Hebrew. But the

one of the translations is especially interesting. It's called the Pilot's translation because because during so there was a war between Israel and Egypt in the early in the early seventies, like in between the Sixth Day War and the Young Keeper War that was kind of it's called the War of Attrition, and various pilots were down and captured by Egyptians and held as POWs for several years, kind of like the American peow's in Vietnam, and they were looking

for ways to pass the time, and one of them got their hands on the English version of The Hobbit. The original Hobbit, and and they decided to translate it into Hebrew as a way to pass the time. So and when they were released, they they took their the translation with them and it literally got published and it's called the Pilot's Translation Translation of the Hobbit from from English into Hebrew. So anyway, so the Hobbit would be one.

So but because that's the obvious one, I'll give another one, and that that book is called Tigana. It's by Guy gravel K. Interestingly, to kind of close the loop. He's the person that worked with the with Tolkien's son on on bringing it on, you know, publishing the Simarillion. So they had a lot of notes over. Yeah, they had

a lot of notes over from Tolkien. So they actually took all those notes and and kind of rounded out and filled up the story and then released it as a Simarillion after Tolkien had died, and he worked with it on it with Tolkien's son, But he also wrote several books on his own. One of them is a

standalone novel called Tigana. You might actually find it especially interesting because it's very much inspired by by the Renaissance Italy, so the setting there, it's a fictional world, obviously with magic and you know, and stuff like that, but it's it's the situation. The scenario is very reminiscent of Italy in the Renaissance, with the little country of warring principalities and influenced by by larger external powers and and so on and so forth, and and the culture and whatnot,

and and it's it's a great book. It's amazing the amount of story and settings and scenery and characters that he was able to cram into this one book. It's a pretty thick book, but still one book. And it's very highly recommended. As I said, it's called Tigana. That's t I G A n A by Guy gabrielle K And that would be my pick for today.

Speaker 1

Awesome. I'll have to check that one out. We were watching the Lord of the Rings movies and my daughter was saying that she'd never read them, and so I had it on audible and so she's been listening to it.

Speaker 2

So but if she's already watched the movie, can she can she get into it?

Speaker 1

I think so. She's pretty into other like Harry Potter and Percy Accent, and she she got into the books too. After she'd seen the movies. So yeah, I'm gonna jump in with some picks. Now. I have to say my board game group hasn't gotten together in a little bit. It's just it's just kind of that season of life. But uh, what I'm trying to think of a game? I should pick? What was the game that we played

last Sunday with with the kids? I don't remember anyway that I mean, there are all kinds of games out there that you can play. I'll just go with one of my favorites. It's funny because I've never actually completely played through this game. No, I take it back, I have played through it once. It's called.

Speaker 2

Monopoly. Does anybody ever play Monopoly all the way through?

Speaker 1

My My kids do all the way through.

Speaker 2

Yeah.

Speaker 1

I haven't played Monopoly in a long time. There there are reasons that I don't.

Speaker 2

I played nostalgia, but notably because it's a it's not such a fun game. Yeah.

Speaker 1

The game that I'm thinking, yeah, well, there there are a number of issues that make it anyway.

Speaker 2

I think I seem to recall that somebody somebody once told me that the original motivation for the creation of the game Monopoly was to show them to prove the futility of capitalism.

Speaker 1

Yeah, well it's not. It's not pure capitalism.

Speaker 2

So yeah.

Speaker 1

Anyway, So the game that I'm gonna pick has called Letters from Whitechapel, and I understand it's like Scotland Yard, but I've never played Scotland Yard. So one player plays as Jack the Ripper, and then the other players play as the police deputies. So they're trying to catch Jack.

Speaker 2

Is it kind of like glue or something.

Speaker 1

No, in the sense that you're not you're not trying to figure out who did it or anything like that. You're it's literally So what the way it works is you have the women that Jack the Ripper kills, and so when he murders somebody, I just dropped the link, but I didn't label it. When he murders somebody in the game, he has so many moves that he can

make to get back to his hideout. And you play it in five rounds, and so the police deputies are trying to block him off, and so they'll go investigate different spots on the board, and there are hundreds of spots on the board, and so they'll investigate a spot and they'll either find a clue, which means that Jack was there, and Jack writes down when he moves through

a space, he writes it down on his thing. And one of my favorite things to do when I'm Jack the Ripper is actually to loop back around and so they'll find clues. They'll find clues all around this spot where I went through twice, and so then they don't know which direction I went coming out of there. But anyway, if you manage to get back to your height out after all five rounds, then you win as Jack the Ripper.

And then if if the deputies investigate a spot in Jack's there and they have to specifically say that they're staging in arrest at that spot that if they do that properly where Jack is at, then then they win.

Speaker 2

And I have to tell you that the sub the subject matter seems a bit dark for a game. I have to tell you it is, but.

Speaker 1

The the overall gameplay is is fun. And so what happens is you start to narrow down where the hideout is right, and so you can you can then start to uh, you know, where he's going, and so wherever the murder happens at right, then you can start to you know, kind of fan out along where he might travel through and get get a sense of where he's at and then be able to arrest him. And so that's that's kind of the gameplay. Let me look it up on board game Geek, so I get the weight.

The reason that I've finished with this guy tried to play it with my family, and it's it's kind of a longer game. I mean, it can run like two hours or longer, and so they just kind of especially my kids, just lose interest. And it's not the kind of My wife likes to play the kind of light, airy games, and this one's a heavier game, and so, you know, all this strategizing and stuff, she just doesn't love. It has a board game weight of two point sixty four, so it is on the heavier side of a game

that a casual player would play. But anyway, it's it's a fun one. So yeah, I'll pick Letters from Whitechapel as my board game pick.

Speaker 2

And then.

Speaker 1

I've been doing a whole bunch of stuff with just being more. I took way too long on that pick, so I'll be quit brief on these other ones. I've been trying to be a little bit more efficient with my time. And I've also been working on getting back into shape. So you know, I picked a marathon and started training for it. So a few picks that I've got here that I'm just going to put out there. So my training program I do in training Peaks and that's just training peaks dot com. I'm gonna put it

in the comments as well. And effectively, it just gives you a calendar. You can buy workout plans. The ones I've bought cost anywhere from five dollars all the way up to like fifty dollars. I think the marathon and triathlon ones were more expensive. But it literally just puts the workouts into your thing. And then I have a garment for runner watch and so it just sinks it down to my watch. So all I have to do is tell it go into my training calendar, pull the workout,

run it through the watch. Right, So I did that this morning, went for a run.

Speaker 2

It was awesome.

Speaker 1

As far as being more efficient, I've also picked up and been using Linear, which seems to be pretty popular in in the development circles. Linear dot app I'll put that in the comments as well, And I mean it's basically a project management board like any of the other ones that you're used to. And then what I've been doing is I've been anything that I intend to do anytime soon out of linear or if it's other stuff

that I need to be doing. Like for example, when Dan and I were talking before the show, he was like, Hey, we ought to get people like this on the show, or Hey, I was going to reach out to so and so, you know, and I was like, oh, I know them, and so as we were having that conversation, I put them into another system called Motion and I kind of I'll look and see if they have an affiliate program, but I'm just going to put the link in.

It's Usmotion dot Com is the app. And the way that this works is so you put your tasks in let me put it usemotion dot Com. Sorry I'm typing in talking at the same time. So you put your tasks in and then it pulls like it pulls from my Google calendar, and so it knows when I have

something scheduled like this episode. And then what it does is it says, Okay, I'm going to put the other tasks that you've put into Motion into your calendar and so and you can set it up so that it'll actually add them to the Google calendar, which is what I did, and then I told it not to market as busy, so they show up as free time. So it's got tasks set up for Tuesday, Wednesday, Thursday, and Friday this week as well, but they show up as

free time. And so what that means is is that if somebody books a time on my calendar, it'll just shift everything around it, and so it essentially tells me what to work on. And then finally, the last thing that I've been using is Focus Blocks and I'm actually going to do another premium episode with Manny who's the

guy that created it. But effectively, what it does is you get on Focus, you get on a zoom call and that you do a breathing exercise before you start, and you commit to this is what I'm going to do this hour. And sometimes I hit it. Sometimes I don't, and it's things out of my control, or it turns out to be harder than I thought it was going to be or whatever. But it keeps me on tasks because what they make you do is they make you put your phone away from your desk and so you

focus on it. And then at the end of the hour, you do another breathing exercise, you report on whether or not you got your thing done, and then you do it over again. And I usually get two, three, four focus blocks in in an afternoon. I try and schedule all the regular stuff in the mornings, but yeah, I'll do that in the afternoons and then Yeah, so a

lot of my like prospecting. So if I'm trying to find sponsors or stuff you know that's on their first thing in the morning, getting through my inbox is a first thing in the morning thing. So after I go for a run and things like that, that's.

Speaker 2

What we do.

Speaker 1

So anyway, those are my picks. I think his focus blocks dot com and I know I have an affiliate link for that, but so we'll put that in the show notes and it doesn't cost you anything extra, but I get a kick back if you use it. But ultimately, I mean, if these things save you a bunch of time and make you more effective, great, and then if I get a kickback because I found an affiliate link for it, even better. But ultimately, this is what I'm using.

So yeah, that's what I've got for picks. So we'll wrap it up until next time.

Speaker 2

Folks back sou

Transcript source: Provided by creator in RSS feed: download file
For the best experience, listen in Metacast app for iOS or Android