* change(ui) - redirect to the landing url on SSO login
* fix(ui): fix share popup styles
* change(ui) - non admin user preference restrictions
* fix(ui) - redirect fix
* change(ui) - show installation btn without mouse hover
* feat(api): api-v1 handle wrong projectKey
feat(api): api-v1 get live sessions
* change(ui) - show role edit on hover
* change(ui) - audit trail count with comma
* fix(ui) - audit trail date range custom picker alignment
* change(ui) - show a message when mob file not found
* feat(api): api-v1 fixed search live sessions
* feat(api): api-v1 handle wrong projectKey
* feat(api): fixed assist error response
* fix(tracker): check node scrolls only on start
* fixup! fix(tracker): check node scrolls only on start
* feat(ui/player): scroll view in click map
* feat(ui/player): rm unused check
* New configuration module (#558)
* ci(dbmigrate): Create db migrate when there is change
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* fix(ui): fix login error/button margins
* fix(ui) - checkbox click
* fix(ui) - search rename and save fixes
* change(ui) - text changes
* fix(ui) - button text nowrap
* fix(ui): fix slowestdomains widget height
* change(ui) - ignore clicks while annotating
* change(ui) - if block with braces
* change(ui) - capitalize first letter in breadcrumb
* feat(db): remove errors from permissions
feat(api): remove errors from permissions
* feat(api): changed reset password response
* fix(ui) - assist active tab list, broken after with new api changes (pagination)
* fix(ui) - assist active tab list, broken after with new api changes (pagination)
* change(ui) - search compare
* fix(ui): last fixes for 1.7
* fix(ui): fix timeline
* fix(ui): small code fixes
* fix(ui): remove unused
* feat(frontend/assist): show when client tab is inactive + fix reconnection status update
* fix(ui) - visibility settings
* feat(assist): refactored extractSessionInfo
feat(assist): hardcoded session's attributes
* Added snabbdom (JS)
* fix(tracker): version check works with x.x.x-beta versions
* fix(backend): keep the highest user's timestamp instead of the latest message timestamp for correct session duration value
* feat(backend/s3): added file tag RETENTION (#561)
* change(ui) - search optimization and autocomplete improvements
* feat(backend/assets): added new metrics assets_downloaded
* change(ui) - show back the date range in bookmarks since the api is filtering by daterange
* feat(backend-assets): custom headers for cacher requests
* chore(backend): no tidy in dockerfile (local build speed up)
* feat(backend/assets): added proxy support for cacher module
* feat(backend/storage): set retention env variable as not required
* fix(ui): fix jira issues
* ci(helm): use kubectl for deployment
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* feat(tracker):3.5.13: performance improvements for a case of extensive dom
* fix(backend): added missed err var and continue statement
* ci(helm): forcing namespace
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* feat(api): fixed slowest_domains query
* ci(helm): update helm deployment method
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* change(ui) - filter dropdown colros
* fix(ui) - speed index location avg attribute changed to value
* ci(api): enable kubectl apply
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* fix(ui) - widget y axis label
* feat(api): fixed slowest_domains query
* chore(helm): Adding namespaces to all templates (#565)
* feat(api): assist type-autocomplete
* feat(api): assist global-autocomplete
* feat(sourcemaps): include wasm file in build
* feat(sourcemaps-reader): refactored
* fix(ui): fix data for funnels
* fix(ui): fix all sessions section margin
* fix(ui) - assist loader flag
* fix(ui) - assist loader flag
* fix(ui): fix weird check
* feat(api): autocomplete accept unsupported types
* feat(ui): migrate to yarn v3
* feat(ui): minor fixes for installment
* feat(ui): add typescript plugin to yarn
* chore(helm): Ability to override image registry
* chore(helm): Overriding openreplay docker registry
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* fix(ui): fix control arrows on firefox
* feat(crons): EE crons
* feat(api): fixed build script
* feat(alerts): fixed build script
* feat(crons): fixed build script
* chore(helm): Updating cron version
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* feat(crons): changes
* chore(helm): optional minio ingress
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* feat(crons): fix build script
feat(alerts): fix build script
* Revert "chore(helm): Updating cron version"
This reverts commit 3ca190ea2f.
* feat(crons): fix build script
* feat(crons): fix Dockerfile
* feat(api): fixed metadata change-case
* change(ui) - remove capitalize for the meta value
* change(ui) - autocomplete improvements with custom textfield
* fix(tracker):3.5.13+:reuse metadata on internal-caused restarts
* fix(tracker-assist):3.5.13:send active:true on start; scroll behavior fix
* change(ui) - filters autocomplete blur on pressing Enter key
* fix(tracker): fix node v to lower
* fix(tracker): fix deps
* fix(tracker): fix deps
* fix(ui) - dashboard modal width
* change(ui) - filter dropdown overflow
* chore(helm): clickhouse reclaim polity to retain
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* fix(tracker): fix engine max v
* fix(ui): load metadata in assist tab for sorting
* fix(ui): rm unneeded api call
* fix(tracker): build script to cjs
* change(ui) - removed sample data
* chore(tracker): remove upper node version limit
* Updating Beacon size
Beacon size should be <= QUEUE_MESSAGE_SIZE_LIMIT
* feat(crons): run 24/7
feat(alerts): support env-file override
* feat(api): changed EE env handler
* fix(ui): fix sessions search modal
* change(ui) - margin for error message
* change(ui) - disable assist sort when there are no meta options to choose
* chore(helm): Adding utilities service namespace
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* fix(ui) - dashboard date range selection reload, metric not found message
* change(ui) - disable clearsearch in assist when there are no filters\
* feat(api): fixed EE env handler
* chore(helm): Adding migration namespaces
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* fix(ui) - report logo path
* chore(helm): Removing unnecessary SA
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* feat(api): changed EE env handler
* feat(api): changed EE env handler
* feat(api): changed EE env handler
* feat(api): changed EE env handler
* feat(crons): changed crons
* feat(api): accept wrong metric_id
* feat(crons): changed env handler
feat(api): changed env handler
feat(alerts): changed env handler
* feat(utilities): support old version of nodejs
* feat(crons): changed env handler
feat(api): changed env handler
feat(alerts): changed env handler
* fix(tracker): fix srcset tracking
* chore(build): Adding frontent
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* feat(assist): changed general helper
* feat(assist): changed general helper
* fix(ui): fix widget pagination (#570)
* feat(crons): changed entrypoint
* feat(player): dev-log on skipping message
* fix(tracker): removeNode mutation priority over attributes
* fix(tracker): capture relative img timing;use startsWith instead of substr; codestyle fix
* chore(build): fixing api build script
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* chore(ci): faster deployment
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* change(ui) - assist list show active status
* chore(actions): option to build all/specific services in GH
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* fix(ui) - slowest domain metric data as per the api changes
* ci(helm): updated variable name
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* ci(backend): cherrypick changes to ee
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* feat(backend): disabled pprof in http service
* fix(ui) - TimeToRender avg value as per the API change
* fix(ui) - ResponseTimeDistribution avg value as per the API change
* fix(ui) - MemoryConsumption avg value as per the API change
* fix(ui) - ResponseTime avg value as per the API change
* fix(ui) - DomBuildTime avg value as per the API change
* fix(ui) - FrameRate avg value as per the API change
* chore(helm): proper default tag
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* feat(backend): removed sensitive information from http logs
* ci(backend): adding default parameter value for workflow dispatch
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* fix(backend): deleted empty file
* fix(actions): creating image source file prior
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* fix(helm): variable substitution
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* change(ui) - project list item installation button text change
* fix(ui) - project create validation
* fix(backend): removed unsafe string logs in http service
* chore(kafka): Adding new topic
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* fix(efs-cron): variable name
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* fix(ui) - developer tools - hint links
* fix(ui) - session filters - country and platform dropdown values
* chore(helm): updating version
* chore(kafka): Update kafka default message size while provisioning
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* fix(tracker): fix dependency security
* change(ui) - webhook delete confirmation
* change(ui) - assist url to handle when empty
* feat(api): autocomplete replace console with errors
feat(DB): clean extra files
* chore(helm): Adding cron jobs
* change(ui) - set changed flag to false after the metric delete to avoid prompt
* chore(helm): enbaling cron only for ee
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* feat(api): autocomplete remove console
* change(ui) - removed Console filter type
* fix(ui) - timeline position
* fix(helm): RFC naming
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* fix(ui): let user change project in dashboards and select default dashboard
* chore(helm): update registry url
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* feat(DB): return pages_count to DB
* fix(ui) - account settings opt out checkbox
* fix(ui): fix modal width
* fix(ui) - explore circle bg
* fix(ui) - user name overlap
* fix(ui) - empty dashboards create button
* fix(ui): fix timeline position cursor for safari
* fix(ui) - custom metrics errors modal url reset on close
* fix(ui) - onboarding check for siteId
* change(ui) - tracker version
* Update local_deploy.sh
* fix(ui) - drilldown timestamp
* fix(tracker): fix deps for assist
* fix(tracker): update peerjs library
* fix(tracker): update assist v
* fix(tracker): fix type error
* fix(backend): no missing resource relying on resource zero-timing
* Update tracker to v3.5.15
* chore(helm): Adding CSP override variable.
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* feat(backend): added pem file support for kafka ssl setup
* feat(backend): added useBatch setup for kafka producer
* ci(backend): set verbose logging
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* fix(backend): using setKey instead of direct writes
* ci(backend): fix error code
* ci(deploy): Updating the image registry
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* feat(api): changed get user id alias
* ci(frontent): removing depricated steps
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* ci(fix): variable replace
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* ci(helm): creating image image_override
Signed-off-by: rjshrjndrn <rjshrjndrn@gmail.com>
* fix(ui): fix timezone settings
* Added failover mechanism for storage service (#576)
* fix(ui): fix typescript config to remove array iterator error
* fix(ui): refactor timezone settings store/comp
* feat(snippet): opensource snippet
* feat(assist): support multiple IPs
* fix(ui): fix type errors in select /timezones fix
* feat(backend): set size of first part of sessions at 500kb
* change(ui) - removed logs
* fix(ui) - custom metric errors reset url on modal close
* feat(DB): no funnel migration
* fix(ui): fix screensize bug
* feat(DB): migrate super old funnels support
* changed db-migration workflow
Co-authored-by: Shekar Siri <sshekarsiri@gmail.com>
Co-authored-by: sylenien <nikita@openreplay.com>
Co-authored-by: Alex Kaminskii <alex@openreplay.com>
Co-authored-by: Alexander <zavorotynskiy@pm.me>
Co-authored-by: rjshrjndrn <rjshrjndrn@gmail.com>
Co-authored-by: Mehdi Osman <estradino@users.noreply.github.com>
Co-authored-by: Alexander <alexander@openreplay.com>
Co-authored-by: Rajesh Rajendran <rjshrjndrn@users.noreply.github.com>
Co-authored-by: Delirium <sylenien@gmail.com>
244 lines
14 KiB
Python
244 lines
14 KiB
Python
from chalicelib.utils import pg_client, helper, email_helper
|
|
from chalicelib.utils.TimeUTC import TimeUTC
|
|
from chalicelib.utils.helper import get_issue_title
|
|
|
|
LOWEST_BAR_VALUE = 3
|
|
|
|
|
|
def get_config(user_id):
|
|
with pg_client.PostgresClient() as cur:
|
|
cur.execute(cur.mogrify("""\
|
|
SELECT users.weekly_report
|
|
FROM public.users
|
|
WHERE users.deleted_at ISNULL AND users.user_id=%(user_id)s
|
|
LIMIT 1;""", {"user_id": user_id}))
|
|
result = cur.fetchone()
|
|
return helper.dict_to_camel_case(result)
|
|
|
|
|
|
def edit_config(user_id, weekly_report):
|
|
with pg_client.PostgresClient() as cur:
|
|
cur.execute(cur.mogrify("""\
|
|
UPDATE public.users
|
|
SET weekly_report= %(weekly_report)s
|
|
WHERE users.deleted_at ISNULL
|
|
AND users.user_id=%(user_id)s
|
|
RETURNING weekly_report;""", {"user_id": user_id, "weekly_report": weekly_report}))
|
|
result = cur.fetchone()
|
|
return helper.dict_to_camel_case(result)
|
|
|
|
|
|
def cron():
|
|
if not helper.has_smtp():
|
|
print("!!! No SMTP configuration found, ignoring weekly report")
|
|
return
|
|
with pg_client.PostgresClient(long_query=True) as cur:
|
|
params = {"tomorrow": TimeUTC.midnight(delta_days=1),
|
|
"3_days_ago": TimeUTC.midnight(delta_days=-3),
|
|
"1_week_ago": TimeUTC.midnight(delta_days=-7),
|
|
"2_week_ago": TimeUTC.midnight(delta_days=-14),
|
|
"5_week_ago": TimeUTC.midnight(delta_days=-35)}
|
|
cur.execute(cur.mogrify("""\
|
|
SELECT project_id,
|
|
name AS project_name,
|
|
users.emails AS emails,
|
|
TO_CHAR(DATE_TRUNC('day', now()) - INTERVAL '1 week', 'Mon. DDth, YYYY') AS period_start,
|
|
TO_CHAR(DATE_TRUNC('day', now()), 'Mon. DDth, YYYY') AS period_end,
|
|
COALESCE(week_0_issues.count, 0) AS this_week_issues_count,
|
|
COALESCE(week_1_issues.count, 0) AS past_week_issues_count,
|
|
COALESCE(month_1_issues.count, 0) AS past_month_issues_count
|
|
FROM (SELECT project_id, name FROM public.projects WHERE projects.deleted_at ISNULL) AS projects
|
|
INNER JOIN LATERAL (
|
|
SELECT sessions.project_id
|
|
FROM public.sessions
|
|
WHERE sessions.project_id = projects.project_id
|
|
AND start_ts >= %(3_days_ago)s
|
|
AND start_ts < %(tomorrow)s
|
|
LIMIT 1) AS recently_active USING (project_id)
|
|
INNER JOIN LATERAL (
|
|
SELECT COALESCE(ARRAY_AGG(email), '{}') AS emails
|
|
FROM public.users
|
|
WHERE users.deleted_at ISNULL
|
|
AND users.weekly_report
|
|
) AS users ON (TRUE)
|
|
LEFT JOIN LATERAL (
|
|
SELECT COUNT(1) AS count
|
|
FROM events_common.issues
|
|
INNER JOIN public.sessions USING (session_id)
|
|
WHERE sessions.project_id = projects.project_id
|
|
AND issues.timestamp >= %(1_week_ago)s
|
|
AND issues.timestamp < %(tomorrow)s
|
|
) AS week_0_issues ON (TRUE)
|
|
LEFT JOIN LATERAL (
|
|
SELECT COUNT(1) AS count
|
|
FROM events_common.issues
|
|
INNER JOIN public.sessions USING (session_id)
|
|
WHERE sessions.project_id = projects.project_id
|
|
AND issues.timestamp <= %(1_week_ago)s
|
|
AND issues.timestamp >= %(2_week_ago)s
|
|
) AS week_1_issues ON (TRUE)
|
|
LEFT JOIN LATERAL (
|
|
SELECT COUNT(1) AS count
|
|
FROM events_common.issues
|
|
INNER JOIN public.sessions USING (session_id)
|
|
WHERE sessions.project_id = projects.project_id
|
|
AND issues.timestamp <= %(1_week_ago)s
|
|
AND issues.timestamp >= %(5_week_ago)s
|
|
) AS month_1_issues ON (TRUE);"""), params)
|
|
projects_data = cur.fetchall()
|
|
emails_to_send = []
|
|
for p in projects_data:
|
|
params["project_id"] = p["project_id"]
|
|
print(f"checking {p['project_name']} : {p['project_id']}")
|
|
if len(p["emails"]) == 0 \
|
|
or p["this_week_issues_count"] + p["past_week_issues_count"] + p["past_month_issues_count"] == 0:
|
|
print('ignore')
|
|
continue
|
|
print("valid")
|
|
p["past_week_issues_evolution"] = helper.__decimal_limit(
|
|
helper.__progress(p["this_week_issues_count"], p["past_week_issues_count"]), 1)
|
|
p["past_month_issues_evolution"] = helper.__decimal_limit(
|
|
helper.__progress(p["this_week_issues_count"], p["past_month_issues_count"]), 1)
|
|
cur.execute(cur.mogrify("""
|
|
SELECT LEFT(TO_CHAR(timestamp_i, 'Dy'),1) AS day_short,
|
|
TO_CHAR(timestamp_i, 'Mon. DD, YYYY') AS day_long,
|
|
(
|
|
SELECT COUNT(*)
|
|
FROM events_common.issues INNER JOIN public.issues USING (issue_id)
|
|
WHERE project_id = %(project_id)s
|
|
AND timestamp >= (EXTRACT(EPOCH FROM timestamp_i) * 1000)::BIGINT
|
|
AND timestamp <= (EXTRACT(EPOCH FROM timestamp_i + INTERVAL '1 day') * 1000)::BIGINT
|
|
) AS issues_count
|
|
FROM generate_series(
|
|
DATE_TRUNC('day', now()) - INTERVAL '7 days',
|
|
DATE_TRUNC('day', now()) - INTERVAL '1 day',
|
|
'1 day'::INTERVAL
|
|
) AS timestamp_i
|
|
ORDER BY timestamp_i;""", params))
|
|
days_partition = cur.fetchall()
|
|
max_days_partition = max(x['issues_count'] for x in days_partition)
|
|
for d in days_partition:
|
|
if max_days_partition <= 0:
|
|
d["value"] = LOWEST_BAR_VALUE
|
|
else:
|
|
d["value"] = d["issues_count"] * 100 / max_days_partition
|
|
d["value"] = d["value"] if d["value"] > LOWEST_BAR_VALUE else LOWEST_BAR_VALUE
|
|
cur.execute(cur.mogrify("""\
|
|
SELECT type, COUNT(*) AS count
|
|
FROM events_common.issues INNER JOIN public.issues USING (issue_id)
|
|
WHERE project_id = %(project_id)s
|
|
AND timestamp >= (EXTRACT(EPOCH FROM DATE_TRUNC('day', now()) - INTERVAL '7 days') * 1000)::BIGINT
|
|
GROUP BY type
|
|
ORDER BY count DESC, type
|
|
LIMIT 4;""", params))
|
|
issues_by_type = cur.fetchall()
|
|
max_issues_by_type = sum(i["count"] for i in issues_by_type)
|
|
for i in issues_by_type:
|
|
i["type"] = get_issue_title(i["type"])
|
|
if max_issues_by_type <= 0:
|
|
i["value"] = LOWEST_BAR_VALUE
|
|
else:
|
|
i["value"] = i["count"] * 100 / max_issues_by_type
|
|
cur.execute(cur.mogrify("""\
|
|
SELECT TO_CHAR(timestamp_i, 'Dy') AS day_short,
|
|
TO_CHAR(timestamp_i, 'Mon. DD, YYYY') AS day_long,
|
|
COALESCE((SELECT JSONB_AGG(sub)
|
|
FROM (
|
|
SELECT type, COUNT(*) AS count
|
|
FROM events_common.issues
|
|
INNER JOIN public.issues USING (issue_id)
|
|
WHERE project_id = %(project_id)s
|
|
AND timestamp >= (EXTRACT(EPOCH FROM timestamp_i) * 1000)::BIGINT
|
|
AND timestamp <= (EXTRACT(EPOCH FROM timestamp_i + INTERVAL '1 day') * 1000)::BIGINT
|
|
GROUP BY type
|
|
ORDER BY count
|
|
) AS sub), '[]'::JSONB) AS partition
|
|
FROM generate_series(
|
|
DATE_TRUNC('day', now()) - INTERVAL '7 days',
|
|
DATE_TRUNC('day', now()) - INTERVAL '1 day',
|
|
'1 day'::INTERVAL
|
|
) AS timestamp_i
|
|
GROUP BY timestamp_i
|
|
ORDER BY timestamp_i;""", params))
|
|
issues_breakdown_by_day = cur.fetchall()
|
|
for i in issues_breakdown_by_day:
|
|
i["sum"] = sum(x["count"] for x in i["partition"])
|
|
for j in i["partition"]:
|
|
j["type"] = get_issue_title(j["type"])
|
|
max_days_partition = max(i["sum"] for i in issues_breakdown_by_day)
|
|
for i in issues_breakdown_by_day:
|
|
for j in i["partition"]:
|
|
if max_days_partition <= 0:
|
|
j["value"] = LOWEST_BAR_VALUE
|
|
else:
|
|
j["value"] = j["count"] * 100 / max_days_partition
|
|
j["value"] = j["value"] if j["value"] > LOWEST_BAR_VALUE else LOWEST_BAR_VALUE
|
|
cur.execute(cur.mogrify("""
|
|
SELECT type,
|
|
COUNT(*) AS issue_count,
|
|
COUNT(DISTINCT session_id) AS sessions_count,
|
|
(SELECT COUNT(DISTINCT sessions.session_id)
|
|
FROM public.sessions
|
|
INNER JOIN events_common.issues AS sci USING (session_id)
|
|
INNER JOIN public.issues AS si USING (issue_id)
|
|
WHERE si.project_id = %(project_id)s
|
|
AND sessions.project_id = %(project_id)s
|
|
AND sessions.start_ts <= (EXTRACT(EPOCH FROM DATE_TRUNC('day', now()) - INTERVAL '1 week') * 1000)::BIGINT
|
|
AND sessions.start_ts >= (EXTRACT(EPOCH FROM DATE_TRUNC('day', now()) - INTERVAL '2 weeks') * 1000)::BIGINT
|
|
AND si.type = mi.type
|
|
AND sessions.duration IS NOT NULL
|
|
) AS last_week_sessions_count,
|
|
(SELECT COUNT(DISTINCT sci.session_id)
|
|
FROM public.sessions
|
|
INNER JOIN events_common.issues AS sci USING (session_id)
|
|
INNER JOIN public.issues AS si USING (issue_id)
|
|
WHERE si.project_id = %(project_id)s
|
|
AND sessions.project_id = %(project_id)s
|
|
AND sessions.start_ts <= (EXTRACT(EPOCH FROM DATE_TRUNC('day', now()) - INTERVAL '1 week') * 1000)::BIGINT
|
|
AND sessions.start_ts >= (EXTRACT(EPOCH FROM DATE_TRUNC('day', now()) - INTERVAL '5 weeks') * 1000)::BIGINT
|
|
AND si.type = mi.type
|
|
AND sessions.duration IS NOT NULL
|
|
) AS last_month_sessions_count
|
|
FROM events_common.issues
|
|
INNER JOIN public.issues AS mi USING (issue_id)
|
|
INNER JOIN public.sessions USING (session_id)
|
|
WHERE mi.project_id = %(project_id)s AND sessions.project_id = %(project_id)s AND sessions.duration IS NOT NULL
|
|
AND sessions.start_ts >= (EXTRACT(EPOCH FROM DATE_TRUNC('day', now()) - INTERVAL '1 week') * 1000)::BIGINT
|
|
GROUP BY type
|
|
ORDER BY issue_count DESC;""", params))
|
|
issues_breakdown_list = cur.fetchall()
|
|
if len(issues_breakdown_list) > 4:
|
|
others = {"type": "Others",
|
|
"sessions_count": sum(i["sessions_count"] for i in issues_breakdown_list[4:]),
|
|
"issue_count": sum(i["issue_count"] for i in issues_breakdown_list[4:]),
|
|
"last_week_sessions_count": sum(
|
|
i["last_week_sessions_count"] for i in issues_breakdown_list[4:]),
|
|
"last_month_sessions_count": sum(
|
|
i["last_month_sessions_count"] for i in issues_breakdown_list[4:])}
|
|
issues_breakdown_list = issues_breakdown_list[:4]
|
|
issues_breakdown_list.append(others)
|
|
for i in issues_breakdown_list:
|
|
i["type"] = get_issue_title(i["type"])
|
|
i["last_week_sessions_evolution"] = helper.__decimal_limit(
|
|
helper.__progress(i["sessions_count"], i["last_week_sessions_count"]), 1)
|
|
i["last_month_sessions_evolution"] = helper.__decimal_limit(
|
|
helper.__progress(i["sessions_count"], i["last_month_sessions_count"]), 1)
|
|
i["sessions_count"] = f'{i["sessions_count"]:,}'
|
|
keep_types = [i["type"] for i in issues_breakdown_list]
|
|
for i in issues_breakdown_by_day:
|
|
keep = []
|
|
for j in i["partition"]:
|
|
if j["type"] in keep_types:
|
|
keep.append(j)
|
|
i["partition"] = keep
|
|
emails_to_send.append({"email": p.pop("emails"),
|
|
"data": {
|
|
**p,
|
|
"days_partition": days_partition,
|
|
"issues_by_type": issues_by_type,
|
|
"issues_breakdown_by_day": issues_breakdown_by_day,
|
|
"issues_breakdown_list": issues_breakdown_list
|
|
}})
|
|
print(f">>> Sending weekly report to {len(emails_to_send)} email-group")
|
|
for e in emails_to_send:
|
|
email_helper.weekly_report2(recipients=e["email"], data=e["data"])
|