Skip to content

Commit 81f3827

Browse files
committed
Initial commit
0 parents  commit 81f3827

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+4651
-0
lines changed

.gitignore

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
__pycache__/
2+
*.py[cod]
3+
venv/
4+
.idea/
5+
config/stored_tasks
6+
config/local_config.py
7+
todo*
8+
/watch/config/local_config.py
9+
/watch/logs/
10+
/watch/ext/*
11+
!/watch/ext/__init__.py
12+
/run.py

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2018 alx-sdv
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

MANIFEST.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
recursive-include watch *
2+
recursive-include bin *

README.md

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
# Watch
2+
![Python 3.6](https://img.shields.io/badge/python-3.6-brightgreen.svg)
3+
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/8d35de9129b4497385b6aa7446893038)](https://www.codacy.com/app/dtbx/watch?utm_source=github.com&utm_medium=referral&utm_content=alx-sdv/watch&utm_campaign=Badge_Grade)
4+
5+
Is another try to make a monitoring of the Oracle Database more handy.
6+
7+
This app created for people who have to deal with long-term sql queries. In other words, if you are data warehouse developer or admin, it could be helpful.
8+
9+
Oracle DB has an infinity number of system views which may give answers for questions like:
10+
* Why does my query run slow?
11+
* Which user consumes too much resources?
12+
* What is going on my database right now?
13+
* How many rows were inserted in my table?
14+
* and many many others.
15+
16+
The problem is you have no GUI to work with these views. So, you retype the same query every time you need some DB statistics.
17+
This app provides easy way to wrap a query to a web report and share it with your team.
18+
Of course, it is actual if your company don't want to buy Oracle Enterprise Manager.
19+
20+
### Features
21+
* Flask-based. Minimum dependencies. Easy to customize.
22+
* Permanent links to all reports and objects can be sent to other people or can be saved to favourites in your browser.
23+
* Defining permitted targets to each user.
24+
* A bunch of predefined reports & utilities for creation your's.
25+
* Background monitoring tasks.
26+
* Interacting through [Telegram](https://telegram.org/) chat (notifications & commands).
27+
28+
![Report example](/docs/top_activity.png) ![Report example](/docs/longops.png)
29+
30+
### Requirements
31+
* Python 3.6+
32+
* Flask
33+
* cx_Oracle
34+
* Pygal
35+
36+
### Installation
37+
First thing you should know: cx_Oracle needs Oracle Instant Client. Installing it could be a bit painful, please read [cx_Oracle guide](https://cx-oracle.readthedocs.io/en/latest/installation.html) and [Oracle Client Guide](https://oracle.github.io/odpi/doc/installation.html). On Windows Oracle Client requires [redistributable libraries](https://www.oracle.com/database/technologies/instant-client/winx64-64-downloads.html).
38+
39+
Then create a new virtual environment if you don't want to mess your python instance.
40+
41+
Install Watch:
42+
`pip install git+https://github.com/alx-sdv/watch.git`
43+
44+
If you deploy the app on Linux, please, add sqlnet.ora file to /usr/lib/oracle/XX.X/client64/lib with parameter "DISABLE_OOB=ON". Otherwise you will not be able to cancel heavy queries. For other platforms this problem also can be actual, it depends on Oracle Client version.
45+
46+
### Settings
47+
Open `/config/config.py` and follow instructions inside.
48+
49+
Please check your database account privileges. By default Watch is not going to modify any data, but for heaven's sake make all accounts read-only.
50+
51+
Also restrict an access to critical business data if you find it necessary. All you need is to read system statistic views.
52+
53+
### Launch
54+
Use `run.py` to run the application on internal web-server provided by Flask.
55+
56+
It is not recommended for production, so you can attach app object from `run.py` to your favourite wsgi server.
57+
58+
See the official [Flask docs](http://flask.pocoo.org/docs/1.0/deploying/#deployment), it contains a lot of scenarios to deploy flask-based application.
59+
60+
### Usage
61+
Some popular system views already included as reports:
62+
63+
Report | View
64+
------ | ----
65+
Top activity | Inspired by OEM chart view, will be improved in further versions.
66+
Top SQL | v$sqlarea
67+
SQL monitor | v$sql_monitor
68+
Session monitor | v$session
69+
Plans cache | v$sql_plan
70+
Top object waits | v$active_session_history
71+
Long operations | v$session_longops
72+
Temp usage | v$sort_usage
73+
Undo usage | v$session
74+
Rman status | v$rman_status
75+
DML locks | dba_dml_locks
76+
Workload | Oracle DB reports, generated by dbms_workload_repository functions.
77+
Objects | all_objects
78+
Table stats | all_tab_statistics
79+
Index stats | all_ind_statistics
80+
Segments | dba_segments
81+
Segment usage | v$segment_statistics
82+
Tabspace usage | dba_free_space
83+
Tabspace fragmentation | dba_segments
84+
Users | dba_users
85+
Synonyms | dba_synonyms
86+
Privileges | dba_tab_privs
87+
Tab partition count | Helps to find extremely partitioned tables.
88+
Ind partition count | Helps to find extremely partitioned indexes.
89+
Modifications | all_tab_modifications
90+
Query text | v$sql
91+
Query plan | dbms_xplan.display_cursor
92+
Query waits | v$active_session_history
93+
Query long ops | v$session_longops
94+
Query plan stats | v$sql_plan_monitor
95+
Monitor report | dbms_sqltune.report_sql_monitor
96+
Table and View columns | all_tab_columns
97+
Table indexes | all_indexes
98+
Table partitions | all_tab_partitions
99+
Table DDL and View script | dbms_metadata.get_ddl, view text
100+
Row count | To count rows grouped by specified date.
101+
Test scan speed | Performs full scan query over chosen table.
102+
103+
And some tasks:
104+
105+
Task | Description
106+
---- | -----------
107+
SQL execution | Notify when specified query will be finished.
108+
Queued SQL | Notify if some query has been queued too long.
109+
SQL concurrency | To monitor average concurrency time.
110+
Heavy SQL | Notify if some query executes too long or consumes too much temp space.
111+
Frequent SQL | Notify if some SQL statement executes too often.
112+
SQL error | Notify if some query has failed. It is based on sql monitor, but a trigger on servererror is much better.
113+
Session activity | Notify when specified session will be inactive (for example, when the client has got first portion of rows).
114+
Session stats | To monitor session stat params.
115+
Uncommitted transactions | Notify when somebody has an inactive session containing locks.
116+
Zombie sessions | Notify if some sessions do nothing but still are active.
117+
Temp usage | Notify when free temp space ends up.
118+
Tabspace usage | Notify when some tablespace becomes full.
119+
Recycled space | Notify to take out the trash.
120+
Segment size | Notify when segment (table, index, ...) size has reached specified threshold.
121+
Watch status | Notify when specified table will contain specified row.
122+
Resource usage | Notify when some of server resource usage reached specified threshold.
123+
Redo switches | Notify if redo logs switch too often.
124+
Logs moving | Notify if too many archived redo logs wait for deletion.
125+
Job health | Notify if Oracle Job became broken.
126+
Expired users | Notify if some user account expires.
127+
Compare structure | Notify if some source column has been changed.
128+
Ping target | Notify if ping to the target has failed.
129+
130+
All views and tasks were tested on Oracle 11.2 & 12.1 (single instance mode).
131+
132+
### Making your own view
133+
There is two ways to add your code to the app:
134+
* Create a regular flask-view, and do everything you want inside it.
135+
* Use some provided conveniences.
136+
137+
Let's open `/views/target.py` and go to a function named `get_target_objects`.
138+
```python
139+
@app.route('/<target>/objects')
140+
@title('Objects')
141+
@template('list')
142+
@snail()
143+
@select("all_objects")
144+
@columns({"owner": 'str'
145+
, "object_name": 'str'
146+
, "subobject_name": 'str'
147+
, "object_type": 'str'
148+
, "created": 'datetime'
149+
, "last_ddl_time": 'datetime'
150+
, "status": 'str'})
151+
@default_filters("object_type = 'TABLE' and object_name like '%%'")
152+
@default_sort("object_name, subobject_name")
153+
def get_target_objects(target):
154+
return render_page()
155+
```
156+
As you can see this view does not contain any specific python code.
157+
158+
How it works:
159+
* You click "OBJECTS" item in the main menu.
160+
* Your request maps to get_target_objects: `@app.route('/<target>/objects')`
161+
* The server returns the view page. The page is generated on "standard" template: `@template('list')`.
162+
* The page contains these controls:
163+
* "Filter" field with default value: `@default_filters("object_type = 'TABLE' and object_name like '%%'", ..., ...)`
164+
* "Sort" field with default value: `@default_sort("object_name, subobject_name")`
165+
* Draggable labels for columns names: `@columns({"owner": 'str' ... '})`. Use in for sorting and filtering. Note that both values will be parsed before sending to database. See the main page of the app for more information.
166+
* Draggable labels of all preset filters.
167+
* "Run" button.
168+
* You press "Run" button.
169+
* The app receives your request with "do" parameter, and executes `get_target_objects`.
170+
* get_target_objects call render_page function.
171+
* render_page parses params, builds a sql query to specified table: `@select("all_objects")`.
172+
* render_page sends the query do DB, then renders "standard" template with fetched data.
173+
* get_target_objects returns rendered template to your browser.
174+
175+
You can make your own view in the same way.
176+
* If any additional steps needed, use `execute` function from `/utils/oracle.py` inside your view to send custom query to DB.
177+
* To render "non-standard" template use `render_template` function from Flask.
178+
* Put your view in a new python file into `/ext` folder.
179+
* Add the view name in the menu structure by importing it from `config.menu` and setting a new key. `@title('<Choose a name>')` will be displayed.
180+
181+
### How to register a bot
182+
* Add the BotFather to contacts and follow its instructions to create a bot.
183+
* Send `/id` command to your new bot, it will show your account id.
184+
* Set the bot name and token in local_config.py.
185+
* Put your id into account properties (see `USERS` dict).
186+
* Now you are able to get notifications an send some commands to the application.
187+
188+
### Making you own task
189+
Watch task looks like a view, the difference is: it's code will never be executed in http request context.
190+
191+
Open `/views/task.py` and find `wait_for_execution` function:
192+
* `@template('task')` lets the app know that `wait_for_execution` is not a report-view.
193+
* `@period('1m')` defines default execution frequency.
194+
* `@command('/wait')` is a command name that can be sent from a chat to register a new instance of the task.
195+
* The task always must return two params:
196+
* The first one is a flag of completion (if true, the task will be deleted from the task queue).
197+
* The second is a message that should be sent to a subscriber.
198+
199+
### Contributing
200+
Feel free to submit a pull request to improve or extend an existing functionality or just open an issue.
201+
202+
### Road map
203+
* `usage` New data types 'bytes' and 'msecs' for pretty formatting and filtering (1.1Gb, 00:00:21.000, 1.1h).
204+
* `usage` Ability to download report result or send it by e-mail.
205+
* `usage` Easy copying to clipboard.
206+
* `usage` User-specific report settings, recent views history.
207+
* `usage` More detailed error messages returning from parser.
208+
* `usage` Braces and IN operator support for parser.
209+
* `usage` New value directive t(trunc). -t10d for date fields.
210+
* `usage` Ability to cancel heavy view directly from it's form. Not only from administration page.
211+
* `usage` Sign up via Telegram.
212+
* `usage` Improve chat commands, use buttons.
213+
* `report` Monitor for specified part of active sql text.
214+
* `report` Which queries has been executed too often.
215+
* `usage` Generate script for all necessary grants.
216+
* `usage` Add an optional numeric argument to @auto() which will refresh a report each N minutes automatically.
217+
* `report` Go deeper to [ASH](https://www.slideshare.net/jberesni/ash-architecture-and-advanced-usage-rmoug2014-36611678).
218+
* `security` Encrypt app data.
219+
* `usage` Ability to set hyperlinks via decorators. Add useful links to existing views.
220+
* `report` Make a forecast for disk space usage.
221+
* `report` Find unused indexes, partitions, tables.
222+
* `general` Improve styles, IE support.
223+
* `general` Fix spelling inaccuracies.

bin/run_watch.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from watch import app
2+
3+
# not recommended for production
4+
if __name__ == '__main__':
5+
app.run(host=app.config['HOST'], port=app.config['PORT'], threaded=True)

docs/longops.png

51.2 KB
Loading

docs/top_activity.png

154 KB
Loading

requirements.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
cx-Oracle==6.0.3
2+
Flask==0.12.2
3+
pygal==2.4.0

setup.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from setuptools import setup
2+
setup(name='watch'
3+
, version='0.0.1'
4+
, description='Oracle Database monitoring'
5+
, author='alx-sdv'
6+
, url='https://github.com/alx-sdv/watch'
7+
, license='MIT'
8+
, python_requires='>=3.6.0'
9+
, include_package_data=True
10+
, packages=['watch']
11+
, install_requires=['cx-Oracle>=6.0.3', 'Flask>=0.12.2', 'pygal>=2.4.0']
12+
, scripts=['bin/run_watch.py'])

0 commit comments

Comments
 (0)