-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into feat/annotations-in-data-management
# Conflicts: # frontend/__snapshots__/scenes-app-notebooks--recordings-playlist.png # frontend/src/scenes/persons/Persons.tsx
- Loading branch information
Showing
74 changed files
with
501 additions
and
221 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import http.client | ||
import json | ||
from prometheus_client import CollectorRegistry, Gauge, multiprocess, generate_latest | ||
|
||
UNIT_CONNECTIONS_ACCEPTED_TOTAL = Gauge( | ||
"unit_connections_accepted_total", | ||
"", | ||
multiprocess_mode="livesum", | ||
) | ||
UNIT_CONNECTIONS_ACTIVE = Gauge( | ||
"unit_connections_active", | ||
"", | ||
multiprocess_mode="livesum", | ||
) | ||
UNIT_CONNECTIONS_CLOSED = Gauge( | ||
"unit_connections_closed", | ||
"", | ||
multiprocess_mode="livesum", | ||
) | ||
UNIT_CONNECTIONS_IDLE = Gauge( | ||
"unit_connections_idle", | ||
"", | ||
multiprocess_mode="livesum", | ||
) | ||
UNIT_CONNECTIONS_TOTAL = Gauge( | ||
"unit_requests_total", | ||
"", | ||
multiprocess_mode="livesum", | ||
) | ||
UNIT_PROCESSES_RUNNING_GAUGE = Gauge( | ||
"unit_application_processes_running", "", multiprocess_mode="livesum", labelnames=["application"] | ||
) | ||
UNIT_PROCESSES_STARTING_GAUGE = Gauge( | ||
"unit_application_processes_starting", "", multiprocess_mode="livesum", labelnames=["application"] | ||
) | ||
UNIT_PROCESSES_IDLE_GAUGE = Gauge( | ||
"unit_application_processes_idle", "", multiprocess_mode="livesum", labelnames=["application"] | ||
) | ||
UNIT_REQUESTS_ACTIVE_GAUGE = Gauge( | ||
"unit_application_requests_active", "", multiprocess_mode="livesum", labelnames=["application"] | ||
) | ||
|
||
|
||
def application(environ, start_response): | ||
connection = http.client.HTTPConnection("localhost:8081") | ||
connection.request("GET", "/status") | ||
response = connection.getresponse() | ||
|
||
statj = json.loads(response.read()) | ||
connection.close() | ||
|
||
UNIT_CONNECTIONS_ACCEPTED_TOTAL.set(statj["connections"]["accepted"]) | ||
UNIT_CONNECTIONS_ACTIVE.set(statj["connections"]["active"]) | ||
UNIT_CONNECTIONS_IDLE.set(statj["connections"]["idle"]) | ||
UNIT_CONNECTIONS_CLOSED.set(statj["connections"]["closed"]) | ||
UNIT_CONNECTIONS_TOTAL.set(statj["requests"]["total"]) | ||
|
||
for application in statj["applications"].keys(): | ||
UNIT_PROCESSES_RUNNING_GAUGE.labels(application=application).set( | ||
statj["applications"][application]["processes"]["running"] | ||
) | ||
UNIT_PROCESSES_STARTING_GAUGE.labels(application=application).set( | ||
statj["applications"][application]["processes"]["starting"] | ||
) | ||
UNIT_PROCESSES_IDLE_GAUGE.labels(application=application).set( | ||
statj["applications"][application]["processes"]["idle"] | ||
) | ||
UNIT_REQUESTS_ACTIVE_GAUGE.labels(application=application).set( | ||
statj["applications"][application]["requests"]["active"] | ||
) | ||
|
||
start_response("200 OK", [("Content-Type", "text/plain")]) | ||
# Create the prometheus multi-process metric registry here | ||
# This will aggregate metrics we send from the Django app | ||
# We prepend our unit metrics here. | ||
registry = CollectorRegistry() | ||
multiprocess.MultiProcessCollector(registry) | ||
yield generate_latest(registry) |
Binary file modified
BIN
+3.81 KB
(200%)
frontend/__snapshots__/filters-propertyfilters--with-no-close-button.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified
BIN
+21.8 KB
(130%)
...tend/__snapshots__/scenes-app-insights--funnel-time-to-convert-edit--webkit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified
BIN
+168 Bytes
(100%)
...tend/__snapshots__/scenes-app-insights--funnel-top-to-bottom-breakdown-edit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified
BIN
+180 Bytes
(100%)
frontend/__snapshots__/scenes-app-insights--funnel-top-to-bottom-breakdown.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified
BIN
+1 Byte
(100%)
frontend/__snapshots__/scenes-other-billing-v2--billing-v-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
144 changes: 144 additions & 0 deletions
144
frontend/src/lib/components/IntervalFilter/intervalFilterLogic.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
import { kea, props, key, path, connect, actions, reducers, listeners } from 'kea' | ||
import { objectsEqual, dateMapping } from 'lib/utils' | ||
import type { intervalFilterLogicType } from './intervalFilterLogicType' | ||
import { IntervalKeyType, Intervals, intervals } from 'lib/components/IntervalFilter/intervals' | ||
import { BaseMathType, InsightLogicProps, IntervalType } from '~/types' | ||
import { keyForInsightLogicProps } from 'scenes/insights/sharedUtils' | ||
import { dayjs } from 'lib/dayjs' | ||
import { InsightQueryNode, TrendsQuery } from '~/queries/schema' | ||
import { lemonToast } from 'lib/lemon-ui/lemonToast' | ||
import { BASE_MATH_DEFINITIONS } from 'scenes/trends/mathsLogic' | ||
import { insightVizDataLogic } from 'scenes/insights/insightVizDataLogic' | ||
|
||
export const intervalFilterLogic = kea<intervalFilterLogicType>([ | ||
props({} as InsightLogicProps), | ||
key(keyForInsightLogicProps('new')), | ||
path((key) => ['lib', 'components', 'IntervalFilter', 'intervalFilterLogic', key]), | ||
connect((props: InsightLogicProps) => ({ | ||
actions: [insightVizDataLogic(props), ['updateQuerySource']], | ||
values: [insightVizDataLogic(props), ['interval', 'querySource']], | ||
})), | ||
actions(() => ({ | ||
setInterval: (interval: IntervalKeyType) => ({ interval }), | ||
setEnabledIntervals: (enabledIntervals: Intervals) => ({ enabledIntervals }), | ||
})), | ||
reducers(() => ({ | ||
enabledIntervals: [ | ||
{ ...intervals } as Intervals, | ||
{ | ||
setEnabledIntervals: (_, { enabledIntervals }) => enabledIntervals, | ||
}, | ||
], | ||
})), | ||
listeners(({ values, actions, selectors }) => ({ | ||
setInterval: ({ interval }) => { | ||
if (values.interval !== interval) { | ||
actions.updateQuerySource({ interval } as Partial<InsightQueryNode>) | ||
} | ||
}, | ||
updateQuerySource: ({ querySource }, _, __, previousState) => { | ||
const { date_from, date_to } = querySource.dateRange || {} | ||
const previousDateRange = selectors.querySource(previousState)?.dateRange || {} | ||
|
||
let activeUsersMath: BaseMathType.WeeklyActiveUsers | BaseMathType.MonthlyActiveUsers | null = null | ||
|
||
// We disallow grouping by certain intervals for weekly active users and monthly active users views | ||
// e.g. WAUs grouped by month. Here, look for the first event/action running WAUs/MAUs math and | ||
// pass that down to the interval filter to determine what groupings are allowed. | ||
for (const series of (values.querySource as TrendsQuery)?.series || []) { | ||
if (series.math === BaseMathType.WeeklyActiveUsers) { | ||
activeUsersMath = BaseMathType.WeeklyActiveUsers | ||
break | ||
} | ||
|
||
if (series.math === BaseMathType.MonthlyActiveUsers) { | ||
activeUsersMath = BaseMathType.MonthlyActiveUsers | ||
break | ||
} | ||
} | ||
|
||
const enabledIntervals: Intervals = { ...intervals } | ||
|
||
if (activeUsersMath) { | ||
// Disallow grouping by hour for WAUs/MAUs as it's an expensive query that produces a view that's not useful for users | ||
enabledIntervals.hour = { | ||
...enabledIntervals.hour, | ||
disabledReason: | ||
'Grouping by hour is not supported on insights with weekly or monthly active users series.', | ||
} | ||
|
||
// Disallow grouping by month for WAUs as the resulting view is misleading to users | ||
if (activeUsersMath === BaseMathType.WeeklyActiveUsers) { | ||
enabledIntervals.month = { | ||
...enabledIntervals.month, | ||
disabledReason: | ||
'Grouping by month is not supported on insights with weekly active users series.', | ||
} | ||
} | ||
} | ||
|
||
actions.setEnabledIntervals(enabledIntervals) | ||
|
||
// If the user just flipped an event action to use WAUs/MAUs math and their | ||
// current interval is unsupported by the math type, switch their interval | ||
// to an appropriate allowed interval and inform them of the change via a toast | ||
if ( | ||
activeUsersMath && | ||
(values.querySource as TrendsQuery)?.interval && | ||
enabledIntervals[(values.querySource as TrendsQuery).interval as IntervalType].disabledReason | ||
) { | ||
if (values.interval === 'hour') { | ||
lemonToast.info( | ||
`Switched to grouping by day, because "${BASE_MATH_DEFINITIONS[activeUsersMath].name}" does not support grouping by ${values.interval}.` | ||
) | ||
actions.updateQuerySource({ interval: 'day' } as Partial<InsightQueryNode>) | ||
} else { | ||
lemonToast.info( | ||
`Switched to grouping by week, because "${BASE_MATH_DEFINITIONS[activeUsersMath].name}" does not support grouping by ${values.interval}.` | ||
) | ||
actions.updateQuerySource({ interval: 'week' } as Partial<InsightQueryNode>) | ||
} | ||
return | ||
} | ||
|
||
if ( | ||
!date_from || | ||
(objectsEqual(date_from, previousDateRange.date_from) && | ||
objectsEqual(date_to, previousDateRange.date_to)) | ||
) { | ||
return | ||
} | ||
|
||
// automatically set an interval for fixed date ranges | ||
if ( | ||
date_from && | ||
date_to && | ||
dayjs(querySource.dateRange?.date_from).isValid() && | ||
dayjs(querySource.dateRange?.date_to).isValid() | ||
) { | ||
if (dayjs(date_to).diff(dayjs(date_from), 'day') <= 3) { | ||
actions.updateQuerySource({ interval: 'hour' } as Partial<InsightQueryNode>) | ||
} else if (dayjs(date_to).diff(dayjs(date_from), 'month') <= 3) { | ||
actions.updateQuerySource({ interval: 'day' } as Partial<InsightQueryNode>) | ||
} else { | ||
actions.updateQuerySource({ interval: 'month' } as Partial<InsightQueryNode>) | ||
} | ||
return | ||
} | ||
// get a defaultInterval for dateOptions that have a default value | ||
let interval: IntervalType = 'day' | ||
for (const { key, values, defaultInterval } of dateMapping) { | ||
if ( | ||
values[0] === date_from && | ||
values[1] === (date_to || undefined) && | ||
key !== 'Custom' && | ||
defaultInterval | ||
) { | ||
interval = defaultInterval | ||
break | ||
} | ||
} | ||
actions.updateQuerySource({ interval } as Partial<InsightQueryNode>) | ||
}, | ||
})), | ||
]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 2 additions & 8 deletions
10
frontend/src/lib/components/PropertyFilters/components/PropertyFiltersDisplay.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.