🚧 This instance is under construction; expect occasional downtime. Runners available in /repos. Questions? Ask in #wikimedia-gitlab on libera.chat, or under GitLab on Phabricator.

Commit dc2cf095 authored by 20after4's avatar 20after4
Browse files

Move charts to separate yaml files and queries to separate sql files

parent 3ac87d43
This diff is collapsed.
......@@ -194,10 +194,13 @@ def map(
else:
res = db.conn.execute('select after_id from conduit_cursor where name=:name', {"name": cursor_id})
row = res.fetchone()
after = row[0]
if row and len(row):
after = row[0]
else:
after = 0
if after:
arg['after'] = after
console.log('resuming after task id '+str(after))
console.log(f'Resuming after task id [bold blue]T{after}[/bold blue]')
r = phab.request("maniphest.search", arg)
while len(r.data):
task = r.data.popleft()
......@@ -205,15 +208,17 @@ def map(
task.save()
if pages and pages > 1 and len(r.data) < 1:
pages -= 1
console.log("Fetching next page", r.cursor)
# console.log("Fetching next page")
cursor_after = r.cursor.get("after", None)
if cursor_after:
status.update(f'Fetching tasks after [bold blue]T{cursor_after}[/bold blue]. [bold blue]{pages}[/bold blue] pages remaining.')
r.next_page()
if cursor_id:
cursor_after = r.cursor.get("after", None)
db.conn.execute(f'REPLACE INTO conduit_cursor values (?,?)', (cursor_id, cursor_after))
# status.update(f"Saved cursor position at [bold blue]{cursor_after}[/bold blue]")
else:
console.log("No more pages to fetch")
status.update("Done")
if project_phid:
console.log(
......@@ -228,6 +233,7 @@ def map(
)
transactions = r.result
elif task_ids:
status.update('Fetching Transactions')
console.log(
f"Fetching transactions for [bold blue]{len(task_ids)}[/bold blue] tasks."
)
......@@ -322,10 +328,10 @@ def load_data_with_progress(
cursor = conn.executemany(sql, chunk)
count += cursor.rowcount
sts.update(
f"Updating [bold green]({count}/{total})[/bold green] {table_name}"
f"Updating {table_name} [bold green]({count}/{total})[/bold green]"
)
console.log(
f"Inserted [bold green]{count}/[/bold green] into {table_name} rows."
f"Inserted [bold green]{count}[/bold green] rows into {table_name}."
)
......
......@@ -9,9 +9,8 @@ plugins:
title: Project Metrics
description: ""
tabs:
projects: Phabricator Projects
columns: Columns & Milestones
cycle: "Lead & Cycle Time"
charts: Charts
cycle: Report
placeholder_text:
To get started, please enter a project name or task ID at the top of the page.
filters:
......@@ -35,7 +34,7 @@ plugins:
task-details:
title: Task details
db: metrics
tab: task
tab: charts
requires: task_id
query: task_details
library: jinja
......@@ -43,7 +42,7 @@ plugins:
task-projects:
title: Task projects
db: metrics
tab: task
tab: charts
requires: task_id
query: task_projects
library: jinja
......@@ -51,7 +50,7 @@ plugins:
task-users:
title: Task users
db: metrics
tab: task
tab: charts
requires: task_id
query: task_users
library: jinja
......@@ -63,11 +62,11 @@ plugins:
library: jinja
template: task_days_in_project.html
requires: [ task_id, project ]
tab: task
tab: charts
task-days-in-columns:
title: Days in project columns
db: metrics
tab: task
tab: charts
requires: [ task_id, project ]
query: select *, next_ts - ts as duration, printf('%.0f', ((next_ts - ts) / 86400.0)) AS duration_days from (select events.*, columns.column_name, columns.project_name, columns.is_default, ifnull(LEAD(ts) OVER(ORDER BY ts), strftime('%s','now', 'localtime')) next_ts from events join columns on new = column_phid where new like '%PHID-PCOL-%' and task = :task_id and event = 'columns' and project_phid = :project order by ts);
library: vega
......@@ -78,24 +77,59 @@ plugins:
y: { field: column_name, type: nominal, title: 'Column' }
databases:
metrics:
tables:
conduit_cursor:
description_html: |-
Each row in the cursors table is used to keep track of the last ID encountered when paging through conduit API responses.
When fetching the next page of results, we pass this ID as the 'after' argument to tell phabricator where the next page will begin.
Pagination enables us to transfer large amounts of data without overloading the server or exceeding request time limits.
phobjects:
label_column: "name"
description_html: |-
The name, url and basic metadata of every known phabricator object. Used mostly to look up the names of users, projects and columns efficiently. Especially convenient because you can join on the phid field even when you have multiple different PHID types to resolve.
Project:
label_column: "name"
description_html: |-
Bulk phabricator project data.
ProjectColumn:
label_column: "name"
Task:
label_column: "name"
description_html: |-
The bulk phabricator task metadata as extracted from th maniphest.search api
Columns:
description_html: |-
Every column from every workboard, including archived projects and hidden columns.
column_metrics:
description_html: |-
This table organizes phabricator task data by the projects and workboard columns.
This is sometimes more useful when building a project-centric or milestone-centric
view of phabricator activity.
columns:
ts: unix epoch timestamp when the activity occurred.
project: This is either a project PHID, or one of 'global', empty for the events which do not belong to a project context.
column: either a column PHID or empty when the event is unrelated to a column or workboard.
task: the task id
type: the type of activity, for example, 'assign', 'mention-this', 'status'
value: eitehr +1 or -1, representing whether the given status was added or removed from the task
task_metrics:
description_html: |-
This table represents every state change that was
recorded on each phabricator task in the index. The data is organized by
"metric" and "state" where metric is the category and state is the value.
There are begining and ending timestamps, as well as a duration for each state.
units:
duration: day
columns:
task: Phabricator task that this metric applies to.
metric: The type or category of the state transition represented.
state: The specific value of the metric during this time period.
ts: The unix epoch timestamp when this state begins.
ts2: The unix epoch timestamp when this state ends.
duration: The number of days elapsed between ts and ts2.
queries:
column_events:
title: Column movement events.
......
......@@ -64,6 +64,12 @@ async def ddd_view(datasette:Datasette, request, scope, send, receive):
_models = {}
page:str = request.url_vars["page"]
response_format = 'html'
if page.endswith('.json'):
page = page[:-5]
response_format = 'json'
views_path = Path(__file__).parent.parent / "templates" / "views"
if page not in _models:
model_page = page + '.py'
......@@ -86,6 +92,7 @@ async def ddd_view(datasette:Datasette, request, scope, send, receive):
db = datasette.get_database('metrics')
context = {
"response_format": response_format,
"base_url": datasette.urls.path('/'),
"views_path": views_path,
"console": console,
......@@ -101,7 +108,7 @@ async def ddd_view(datasette:Datasette, request, scope, send, receive):
if ('template_name' in context):
template_name = context['template_name']
else:
template_name = f"views/{page}.html"
template_name = f"views/{page}.{response_format}"
console.log('template name: ',template_name)
try:
output = await datasette.render_template(template_name, context, request, page)
......@@ -121,7 +128,7 @@ def register_routes():
return prefix + "/".join(parts) + "/?$"
def v(name):
"""Compose regex fragment that captures one path level as a named variable"""
return f"(?P<{name}>[a-zA-Z0-9\\-]+)"
return f"(?P<{name}>[a-zA-Z0-9\\-_]+(\\.json)?)"
def optional(part):
"""Mark a path segment as optional by wrapping it with ()?"""
return f"?({part})?"
......
......@@ -110,6 +110,8 @@ def extra_template_vars(datasette):
def render_cell(
value, column: str, table: Union[str, None], database: str, datasette: Datasette
) -> Union[str, None]:
if column == 'duration':
return str(int(int(value) / (60*60*24)))
if isinstance(value, int):
value = str(value)
if isinstance(value, bytes):
......@@ -122,6 +124,7 @@ def render_cell(
value = value.strip()
if ( column in ['tid', 'task'] ):
if value[0] == 'T' and value[1:].isdigit():
value = value[1:]
......
......@@ -4,7 +4,8 @@ SELECT
ph.phid AS state_phid,
w.date AS week,
max(date(m.ts, 'unixepoch')) AS ts,
max(date(m.ts2, 'unixepoch')) AS ts2
max(date(m.ts2, 'unixepoch')) AS ts2,
group_concat(task) as task
FROM
task_metrics m
JOIN enabled_columns_and_milestones ph ON (m.state = ph.phid)
......
SELECT
MONTH,
month,
column_name,
sum(value) AS total_tasks
column_phid,
sum(value) AS total_tasks,
CASE WHEN value > 0 THEN 'added' ELSE 'removed' END as action
FROM
(
SELECT
printf('T%u', c.task) AS task,
datetime(c.ts, 'unixepoch') AS ts,
date(c.ts, 'unixepoch', 'start of month') AS MONTH,
date(c.ts, 'unixepoch', 'start of month') AS month,
date(
c.ts,
'unixepoch',
......@@ -17,13 +19,11 @@ FROM
p.column_name AS column_name,
p.project_phid AS project_phid,
p.project_name AS project_name,
p.project_name || ':' || p.column_name AS qualified_name,
p.status AS column_hidden,
c.value AS value
FROM
column_metrics c
JOIN COLUMNS p ON c.column = p.column_phid
AND column_phid = :column
WHERE
project_phid = :project
ORDER BY
......@@ -35,5 +35,6 @@ WHERE
AND ts >= date(:date_start)
AND ts <= date(:date_end)
GROUP BY
MONTH,
column_phid
\ No newline at end of file
month,
column_phid,
action
\ No newline at end of file
SELECT
date(ts, 'unixepoch') AS DAY,
date(ts, 'unixepoch', 'start of month') AS month,
task,
project,
user,
event,
......
......@@ -3,6 +3,7 @@ SELECT
date(ts, 'unixepoch') AS day,
date(ts, 'unixepoch', 'start of month') AS month,
count(task) AS count,
group_concat(task) as task,
c.name AS old,
n.name AS new,
c.phid || ':' || n.phid as phids,
......
......@@ -6,7 +6,7 @@ import { InputFilter, DaterangeFilter, NavTabs, TabItem, AutocompleteFilter } fr
import { VegaChart } from './vega-tonic.js'
import {DependableComponent, Query} from "./dom.js"
import { DateTime } from "luxon";
import { ModalDialog} from "./ui.js"
import { TaskDialog} from "./ui.js"
function initApp() {
if (window['BASE_URL'])
......@@ -22,7 +22,7 @@ function initApp() {
Tonic.add(DashboardApp);
initDataSets();
const app = <DashboardApp> <unknown>document.getElementsByTagName('dashboard-app')[0];
console.log(TaskDialog);
console.log('---------------- init ----------------')
}
......
This diff is collapsed.
......@@ -486,6 +486,14 @@ class DaterangeFilter extends InputFilter {
render() {
const id = this.id;
const dt = DateTime.now();
var fs, fe;
if (dt.month < 6) {
fe = dt.set({month: 6}).endOf('month');
fs = fe.minus({years: 1}).set({month:7, day:1});
} else {
fs = dt.set({month: 7, day: 1, hour: 0});
fe = fs.plus({years: 1}).minus({days: 1});
}
const yr = dt.startOf('year');
const qt = dt.startOf('quarter');
const pq = qt.minus({months: 3});
......@@ -500,6 +508,7 @@ class DaterangeFilter extends InputFilter {
<li><a class="dropdown-item" href="#date_start=${qt.toISODate()}&date_end=${qt.endOf('quarter').toISODate()}">This Quarter ${qt.toISODate()}</a></li>
<li><a class="dropdown-item" href="#date_start=${pq.toISODate()}&date_end=${pq.endOf('quarter').toISODate()}">Last Quarter ${pq.toISODate()}</a></li>
<li><a class="dropdown-item" href="#date_start=${yr.toISODate()}&date_end=${dt.endOf('year').toISODate()}">This Year ${yr.toISODate()}</a></li>
<li><a class="dropdown-item" href="#date_start=${fs.toISODate()}&date_end=${fe.toISODate()}">Fiscal Year ${fs.year.toString()}:${fe.year.toString()}</a></li>
</ul>
</div>
<!--<span class="input-group-text">From:</span>-->
......
......@@ -6,6 +6,7 @@ import { InputFilter, DaterangeFilter, AutocompleteFilter } from './filter-input
import { VegaChart } from './vega-tonic.js';
import { DependableComponent, Query } from "./dom.js";
import { DateTime } from "luxon";
import { TaskDialog } from "./ui.js";
function initApp() {
if (window['BASE_URL'])
DependableComponent._base_url = window['BASE_URL'];
......@@ -19,6 +20,7 @@ function initApp() {
Tonic.add(DashboardApp);
initDataSets();
const app = document.getElementsByTagName('dashboard-app')[0];
console.log(TaskDialog);
console.log('---------------- init ----------------');
}
class DashboardApp extends DependableComponent {
......
{"version":3,"file":"DashboardApp.js","sourceRoot":"","sources":["../DashboardApp.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
{"version":3,"file":"DashboardApp.js","sourceRoot":"","sources":["../DashboardApp.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
......@@ -447,6 +447,15 @@ class DaterangeFilter extends InputFilter {
render() {
const id = this.id;
const dt = DateTime.now();
var fs, fe;
if (dt.month < 6) {
fe = dt.set({ month: 6 }).endOf('month');
fs = fe.minus({ years: 1 }).set({ month: 7, day: 1 });
}
else {
fs = dt.set({ month: 7, day: 1, hour: 0 });
fe = fs.plus({ years: 1 }).minus({ days: 1 });
}
const yr = dt.startOf('year');
const qt = dt.startOf('quarter');
const pq = qt.minus({ months: 3 });
......@@ -461,6 +470,7 @@ class DaterangeFilter extends InputFilter {
<li><a class="dropdown-item" href="#date_start=${qt.toISODate()}&date_end=${qt.endOf('quarter').toISODate()}">This Quarter ${qt.toISODate()}</a></li>
<li><a class="dropdown-item" href="#date_start=${pq.toISODate()}&date_end=${pq.endOf('quarter').toISODate()}">Last Quarter ${pq.toISODate()}</a></li>
<li><a class="dropdown-item" href="#date_start=${yr.toISODate()}&date_end=${dt.endOf('year').toISODate()}">This Year ${yr.toISODate()}</a></li>
<li><a class="dropdown-item" href="#date_start=${fs.toISODate()}&date_end=${fe.toISODate()}">Fiscal Year ${fs.year.toString()}:${fe.year.toString()}</a></li>
</ul>
</div>
<!--<span class="input-group-text">From:</span>-->
......
This diff is collapsed.
......@@ -11,6 +11,7 @@ class ModalDialog extends DependableComponent {
<h5 id="modal-${this.id}-title">${this.props.title}</h5>
</div>
<div class="modal-body">
${this.renderBody()}
${this.elements}
</div>
</div>
......@@ -18,10 +19,48 @@ class ModalDialog extends DependableComponent {
</div>
`;
}
renderBody() {
return [];
}
connected() {
this.state.modal = new Modal(this);
this.state.modal = new Modal(this.querySelector('.modal'));
}
show() {
this.state.modal.show();
}
hide() {
this.state.modal.hide();
}
}
Tonic.add(ModalDialog);
export { ModalDialog };
class TaskDialog extends ModalDialog {
constructor() {
super();
this.props.title = 'Counted Tasks';
this.state.tasks = [];
console.log('loaded taskdialog', this);
}
renderBody() {
const output = [];
for (const task of this.state.tasks) {
output.push(this.html `
<phab-task id='${task}'>${task}</phab-task>
`);
}
return output;
}
showTasks(tasks) {
this.state.tasks = tasks;
this.querySelector('.modal-body').innerHTML = this.renderBody().join('');
this.show();
}
}
class PhabTask extends Tonic {
render() {
return this.html `<a href='https://phabricator.wikimedia.org/T${this.id}'>T${this.id}</a>`;
}
}
Tonic.add(PhabTask);
Tonic.add(TaskDialog);
export { ModalDialog, TaskDialog };
//# sourceMappingURL=ui.js.map
\ No newline at end of file
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../ui.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,mBAAmB,EAAC,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,MAAM,mBAAmB,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAElC,MAAM,WAAY,SAAQ,mBAAmB;IAC3C,MAAM;QACJ,OAAO,IAAI,CAAC,IAAI,CAAA;qBACC,IAAI,CAAC,EAAE,kEAAkE,IAAI,CAAC,EAAE;;;;4BAIzE,IAAI,CAAC,EAAE,WAAW,IAAI,CAAC,KAAK,CAAC,KAAK;;;cAGhD,IAAI,CAAC,QAAQ;;;;;KAKtB,CAAC;IACJ,CAAC;IAED,SAAS;QACP,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC;CACF;AACD,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AACvB,OAAO,EAAC,WAAW,EAAC,CAAA"}
\ No newline at end of file
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../ui.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,mBAAmB,EAAC,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,MAAM,mBAAmB,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAElC,MAAM,WAAY,SAAQ,mBAAmB;IAC3C,MAAM;QACJ,OAAO,IAAI,CAAC,IAAI,CAAA;qBACC,IAAI,CAAC,EAAE,kEAAkE,IAAI,CAAC,EAAE;;;;4BAIzE,IAAI,CAAC,EAAE,WAAW,IAAI,CAAC,KAAK,CAAC,KAAK;;;cAGhD,IAAI,CAAC,UAAU,EAAE;cACjB,IAAI,CAAC,QAAQ;;;;;KAKtB,CAAC;IACJ,CAAC;IAED,UAAU;QACR,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,SAAS;QACP,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC7D,CAAC;IAED,IAAI;QACF,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAC1B,CAAC;IAED,IAAI;QACF,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAC1B,CAAC;CACF;AAED,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AAEvB,MAAM,UAAW,SAAQ,WAAW;IAClC;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,eAAe,CAAC;QACnC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAC;IACzC,CAAC;IAED,UAAU;QACR,MAAM,MAAM,GAAG,EAAE,CAAC;QAClB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;YACnC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAA;yBACF,IAAI,KAAK,IAAI;OAC/B,CAAC,CAAC;SACJ;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,SAAS,CAAC,KAAK;QACb,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;QACzB,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACzE,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;CACF;AAED,MAAM,QAAS,SAAQ,KAAK;IAC1B,MAAM;QACJ,OAAO,IAAI,CAAC,IAAI,CAAA,+CAA+C,IAAI,CAAC,EAAE,MAAM,IAAI,CAAC,EAAE,MAAM,CAAA;IAC3F,CAAC;CACF;AAED,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAEpB,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;AACtB,OAAO,EAAC,WAAW,EAAE,UAAU,EAAC,CAAA"}
\ No newline at end of file
......@@ -17,20 +17,25 @@ class VegaChart extends Chart {
$schema: 'https://vega.github.io/schema/vega-lite/v5.json',
width: 'container',
height: 'container',
padding: 50,
padding: 15,
autosize: {
type: "fit",
type: "pad",
contains: "padding",
resize: true
},
view: { stroke: null },
config: {
continuousHeight: 400,
discreteHeight: 400,
background: '#00000000',
arc: {
innerRadius: 50
},
line: {
point: true
},
scale: {
scheme: "category20"
}
}
};
......@@ -158,21 +163,21 @@ class VegaChart extends Chart {
return;
const classes = label.classList;
if (classes.contains('view-stack')) {
this.className = 'view-stack';
this.className = 'chart view-stack';
}
else if (classes.contains('view-grid')) {
this.className = 'view-grid';
this.className = 'chart view-grid';
}
else if (classes.contains('view-table')) {
this.renderTable();
this.className = 'view-table';
this.className = 'chart view-table';
}
else if (classes.contains('view-source')) {
this.renderSource();
this.className = 'view-source';
this.className = 'chart view-source';
}
else {
this.className = 'view-normal';
this.className = 'chart view-normal';
}
window.dispatchEvent(new Event('resize'));
}
......@@ -219,6 +224,14 @@ class VegaChart extends Chart {
const updatedJson = jsoneditor.get();
}
}
chartClicked(e, arg) {
console.log(e, e.item);
const datum = arg['datum'];
const dialog = document.getElementById('task-modal');
console.log(datum);
const tasks = datum.task.split(',');
dialog.showTasks(tasks);
}
datasetChanged(ds) {
if (this.state.view) {
const view = this.state.view;
......@@ -239,6 +252,9 @@ class VegaChart extends Chart {
disconnected() {
}
connected() {
if (this.props['order']) {
this.style = 'order:' + this.props['order'];
}
//this.loadcharts();
}
updated(props) {
......@@ -274,9 +290,12 @@ class VegaChart extends Chart {
},
...this.state.display
};
var self = this;
const chartClicked = (e, arg) => this.chartClicked(e, arg);
vegaEmbed(this.ele('.vega-embed'), spec, { renderer: "svg", actions: false, ...this.props.options }).then((result) => {
this.state.vega = result;
this.state.view = result.view;
result.view.addEventListener('click', chartClicked);
if (result.view) {
this.classList.remove('hidden');
if (DependableComponent.debug_logging) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment