devops-pipelines/run.ipynb

251 строка
7.0 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# The Plan\n",
"Everything we know about the plan.\n",
"\n",
"### Instructions\n",
"1. Run all cells! (click on Menu > Cell > Run All Cells)\n",
"1. View report at the bottom."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"inputHidden": false,
"outputHidden": false,
"tags": [
"parameters"
]
},
"outputs": [],
"source": [
"#planId = \"98db70e2-cee5-4e2d-ae15-dca389fa8f41\"\n",
"planId = \"f38f1a4b-49d7-4f08-a9b9-c81b2c39aff6\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"inputHidden": false,
"outputHidden": false
},
"outputs": [],
"source": [
"%%capture \n",
"# install packages, setup workspace root\n",
"!pip install --upgrade azure-kusto-notebooks plotly\n",
"import os\n",
"from azure.kusto.notebooks import utils as akn\n",
"import pandas as pd\n",
"pd.options.display.html.table_schema = True\n",
"\n",
"# cwd should be workspace root\n",
"if os.path.basename(os.getcwd()) == 'devops-pipelines':\n",
" os.chdir(os.pardir)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"inputHidden": false,
"outputHidden": false
},
"outputs": [],
"source": [
"# authenticate kusto client\n",
"# you will need to copy the token into a browser window for AAD auth. \n",
"client = akn.get_client('https://vso.kusto.windows.net')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"inputHidden": false,
"outputHidden": false
},
"outputs": [],
"source": [
"# collect basic plan info\n",
"plan_info = akn.Query(\n",
" client, 'VSO', \n",
" path=os.path.join('devops-pipelines', 'queries', 'run', 'PlanInfo.csl'), \n",
" params={'OrchestrationId': akn.quote(planId)})\n",
"\n",
"# collect full plan history\n",
"what_happened = akn.Query(client, 'VSO',\n",
" path=os.path.join('devops-pipelines', 'queries', 'run', 'WhatHappened.csl'),\n",
" params={'OrchestrationId': akn.quote(planId)})\n",
"\n",
"# fetch data in parallel\n",
"akn.run((plan_info, what_happened))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"inputHidden": false,
"outputHidden": false
},
"outputs": [],
"source": [
"# draw basic info\n",
"\n",
"# compute relative time stamps\n",
"history = what_happened.dataframe\n",
"t0 = history['PreciseTimeStamp'].iloc[0]\n",
"history['Time'] = history.apply(lambda row: row['PreciseTimeStamp'] - t0, axis=1)\n",
"history.OrchestrationId = history.apply(lambda row: row.OrchestrationId[37:], axis=1)\n",
"\n",
"# record critical times\n",
"def find_time(message):\n",
" r = history[history.Message.str.startswith(message)]\n",
" if len(r.index) > 0:\n",
" return r['PreciseTimeStamp'].iloc[0]\n",
"\n",
"create_time = find_time('Created plan')\n",
"start_time = find_time('Started plan')\n",
"end_time = find_time('Completed orchestration with result')\n",
"total_duration = end_time - start_time if end_time and start_time else None\n",
"\n",
"import importlib\n",
"importlib.reload(akn)\n",
"# info will only exist if the plan has started at least one job :(\n",
"d = akn.pandas_row_to_dictionary(plan_info.dataframe)\n",
"d['create time'] = create_time\n",
"d['start time'] = start_time\n",
"d['end time'] = end_time\n",
"d['total duration'] = total_duration\n",
"r = akn.Report()\n",
"r.write(akn.to_md_table(d))\n",
"\n",
"from IPython.display import Markdown\n",
"Markdown(r.content)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"inputHidden": false,
"outputHidden": false
},
"outputs": [],
"source": [
"# SLA analysis\n",
"su = akn.quote(d.get('ScaleUnit', ''))\n",
"oids = [akn.quote(joid) for joid in d.get('JobOrchestrationIds', [])]\n",
"slas = [akn.Query(client, 'VSO', \n",
" os.path.join('devops-pipelines', 'queries', 'sla', 'SLAVisualization.csl'),\n",
" params=dict(ScaleUnit=su, OrchestrationId=oid)) \n",
" for oid in oids]\n",
"akn.run(slas)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"inputHidden": false,
"outputHidden": false
},
"outputs": [],
"source": [
"# draw all slas\n",
"from _plotly_future_ import v4_subplots\n",
"from plotly.subplots import make_subplots\n",
"import plotly.graph_objects as go\n",
"import math\n",
"if not slas:\n",
" print(\"There are no jobs associated with this plan.\")\n",
"else:\n",
" number_of_graphs = min(25, len(slas))\n",
" names = [n[37:] for n in d.get('JobOrchestrationIds',[])]\n",
" fig = make_subplots(cols=2, rows=int(math.ceil(number_of_graphs / 2)), \n",
" subplot_titles=names,\n",
" shared_xaxes=True, \n",
" vertical_spacing=0.1)\n",
"\n",
" for i in range(len(slas)):\n",
" df = slas[i].dataframe\n",
" row = int(i / 2) + 1\n",
" col = int(i % 2) + 1\n",
" name = names[i]\n",
" \n",
" df = slas[0].dataframe\n",
" fig.add_trace(go.Bar(x=df.PhaseName, y=df.PercentDifference, name=name), \n",
" row=row, col=col)\n",
" fig.update_xaxes(showgrid=False, tickangle=-60, automargin=True)\n",
" fig.update_xaxes(showgrid=True, zeroline=True, automargin=True)\n",
" fig.update_layout(height=150 * number_of_graphs, \n",
" width=1000, showlegend=False,\n",
" title_text=\"Analysis!\")\n",
"\n",
" fig.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"inputHidden": false,
"outputHidden": false
},
"outputs": [],
"source": [
"# draw full history\n",
"columns_to_ignore = ('source_', 'PreciseTimeStamp')\n",
"columns = ['Time'] + [c for c in history.columns if c not in columns_to_ignore and c != 'Time']\n",
"\n",
"from IPython.display import HTML\n",
"HTML(history[columns].to_html(index=False))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"inputHidden": false,
"outputHidden": false
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernel_info": {
"name": "python3"
},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.4"
},
"nteract": {
"version": "0.15.0"
}
},
"nbformat": 4,
"nbformat_minor": 2
}