-
Notifications
You must be signed in to change notification settings - Fork 887
Daily Active User Metrics #3735
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
Conversation
@kylecarbs most of the backend is complete. I plan on adding the frontend tomorrow. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Putting this in the agent solves a lot of the issues we had with v1 👍.
This does only catch long lived connections. Like I would assume most ProtocolDial
s will be short http requests, right? Those would never likely be picked up.
codersdk/metrics.go
Outdated
return err | ||
} | ||
|
||
s := stats() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am guessing this returns a threadsafe copy for the later json marshal. Would be nice if this copy didn't have a mutex in it. Can be misleading to see a mutex, and might assume to use it.
8dbf511
to
df5d596
Compare
618cd92
to
7c1a63f
Compare
Socket Security ReportDependency issues detected. If you merge this pull request, you will not be alerted to the instances of these issues again. 📜 New install scripts detectedA dependency change in this PR is introducing new install scripts to your install step.
🫣 Native codeContains native code which could be a vector to obscure malicious code, and generally decrease the likelihood of reproducible or reliable installs.
Socket.dev scan summary
Powered by socket.dev |
d593346
to
4b285fa
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FE: Didn't review the whole thing yet but can later today. So far looking good, just some housekeeping stuff mostly that we should address
@@ -113,6 +117,7 @@ | |||
"prettier": "2.7.1", | |||
"prettier-plugin-organize-imports": "3.0.0", | |||
"react-hot-loader": "4.13.0", | |||
"resize-observer": "^1.0.4", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we update the PR description explaining the new libraries added and the reason behind them? That'll help the rest of the team aware 👍🏼
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I shall explain in the comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ugh... can't comment package.json...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PR description works well too
site/src/api/typesGenerated.ts
Outdated
// From codersdk/metrics.go | ||
export interface DAUEntry { | ||
readonly date: string | ||
readonly daus: number |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: DAUEntry.daus
feels a bit weird. Would also prefer for us to use consistent casing if possible: DAU
vs. dau
Maybe total
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The casing is an unfortunate side effect of the code generator, which is outside the scope of this PR. I can rename to total
if you feel strongly, but I think daus
is clear enough.
Object.defineProperty(window, "ResizeObserver", { | ||
value: ResizeObserver, | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we adding this to the window
? Feels like a codesmell but I blame my lack of context and understanding here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is needed, could we add it in a beforeEach
or beforeAll
block inside your describe
block?
We also need to remove it from the window
or it could affect other tests so it should be removed in a teardown function like afterAll
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, there's no way to do this w/o modifying the global state. Since jest runs parallel, even if we use beforeAll I believe we may have state issues.
export const Language = { | ||
loadingText: "DAU stats are loading. Check back later.", | ||
chartTitle: "Daily Active Users", | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think now that we have internationalization, we're not using this pattern anymore and instead using the t()
and then referencing strings from a json
file. There should be some examples in the codebase but if you want specifics, let me know!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Slightly off-topic, but why are we pursuing internationalization? That seems like a feature that is 3+ years out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @ammario I was on vacation when you asked this, but I wanted to follow up. There are a couple reasons we're using this pattern, and some are outlined below:
- It's helpful to have all strings colocated. We can be better about using consistent language, and we can re-use strings more easily.
- Translation libraries have features like string interpolation or pluralization built into them, which helps us avoid a bunch of boilerplate JSX, keeping our component files lightweight.
- We've actually had an internationalization solution in our app since I started, but prior to using i18n, we were using
Language
objects which is a problematic pattern for several reasons -you can read more in our FE Variety notes if you're interested - Even if translation is a long way off, it's best to establish a pattern before the app grows large.
Anyway, let me know if you want to chat about it further!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Take a look at my comments before merge, but overall LGTM!
agent_id uuid NOT NULL, | ||
workspace_id uuid NOT NULL, | ||
template_id uuid NOT NULL, | ||
payload jsonb NOT NULL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Payload is weird since this is a specific stat type. Why not structure the data?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I anticipate significant churn in this structure, and there can be many agent versions simultaneously reporting to the same coderd. I'm thinking about long-lived workspaces that never stop.
This primarily resolves delete template conflicts.
@@ -38,6 +38,7 @@ | |||
"@xstate/react": "3.0.1", | |||
"axios": "0.26.1", | |||
"can-ndjson-stream": "1.0.2", | |||
"chart.js": "^3.5.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like we still have a ^
here
"react": "18.2.0", | ||
"react-chartjs-2": "^4.3.1", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One here as well
"react-dom": "18.2.0", | ||
"react-helmet-async": "1.3.0", | ||
"react-i18next": "11.18.4", | ||
"react-markdown": "8.0.3", | ||
"react-router-dom": "6.3.0", | ||
"react-router-dom": "^6.3.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and here as well
@@ -87,6 +89,7 @@ | |||
"@typescript-eslint/eslint-plugin": "5.31.0", | |||
"@typescript-eslint/parser": "5.31.0", | |||
"@xstate/cli": "0.3.0", | |||
"canvas": "^2.9.3", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and here
@@ -113,6 +117,7 @@ | |||
"prettier": "2.7.1", | |||
"prettier-plugin-organize-imports": "3.0.0", | |||
"react-hot-loader": "4.13.0", | |||
"resize-observer": "^1.0.4", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PR description works well too
// The Chart performs dynamic resizes which fail in tests without this. | ||
Object.defineProperty(window, "ResizeObserver", { | ||
value: ResizeObserver, | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is needed for these tests, it's usually best to put it in a setup function like beforeEach
or beforeAll
. Otherwise it can have unintended side effects.
export const Language = { | ||
loadingText: "DAU stats are loading. Check back later.", | ||
chartTitle: "Daily Active Users", | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Object.defineProperty(window, "ResizeObserver", { | ||
value: ResizeObserver, | ||
}) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar comment as above, would be best to keep this in a setup and teardown function
User facing:
CODER_EXPERIMENTAL
is true.Plumbing:
agent_stats
table)AgentReportStats
context based cancellation withio.Closer
agent_stats
table (not doing this since there is nodeleted
for users)