Tracery
Setup
brew install node thrift
node install -g npm
Run the Demo
-
Populate the database (this command will auto-build the service):
./tracery-service.sh insert --diskio example_trace ./tracery.db
-
Start the data layer:
./tracery-service.sh server ./tracery.db
-
Build the client:
npm run build
-
Open http://localhost:9090 in your browser
Quick UI Guide
Right now we've just got a heatmap with fake data for performance testing. A few keyboard commands have been hacked in:
-
: Zoom out by 1 dip/cell=
/+
: Zoom in by 1 dip/cellz
: Zoom all the way outx
: Zoom all the way in
Hitting z
and x
alternately is a fun perf test.
Develop the UI
NOTE: This functionality is currently disabled while we figure out how to allow the UI to come from
webpack-dev-server
but the data to come from tracery-service.sh
. For now, follow the demo instructions above and refresh the browser manually whenever the code changes
-
If you've just rebased, pick up any dependencies and rebuild the Thrift layer:
npm install npm run thrift
-
Start the Webpack Dev Server
npm start
-
Open http://localhost:8080 in Chrome
-
Start coding! Many types of edits will automatically be applied thanks to React Hot Loader. Refresh the browser for those that don't (there'll be messages in the Console).
-
Use Chrome DevTools for debugging. (React and Redux browser extensions are helpful.)5.
Other Commands
Command | Purpose |
---|---|
npm run jest |
Runs Jest tests on the JavaScript code |
npm run coverage |
Runs Jest tests on the JavaScript code, while recording coverage. Find the report at coverage/lcov-report/index.html . |
npm run lint-all |
Runs ESLint |
npm run fix-all |
Runs ESLint in fixing mode |
npm run flow |
Runs Flow |
npm run thrift |
Builds the Thrift stubs for accessing the data layer |
npm test |
Runs the JavaScript tests that Travis would run |
Develop the Data Layer
Gradle commands
Command | Purpose |
---|---|
./gradlew fatJar |
Builds a .jar with the data layer and all of its dependencies |
./gradlew run <params> |
Runs the data layer (equivalent to ./tracery-service.sh ) |
./gradlew check |
Runs the Java tests that Travis would run. Reports are in build/reports/{checkstyle, findbugs}/ . |
./gradlew build |
Build and test everything |
tracery-service.sh
commands
Command | Purpose |
---|---|
./tracery-service.sh insert --diskio <trace file> <db path> |
Insert disk IO trace data from the given trace into the given db |
./tracery-service.sh server <db path> |
Start the data layer and open the given db file |
./tracery-service.sh client |
Start the data layer test client, which will make a few test queries |
Working With Thrift
We use Thrift as the interface between the UI and Data Layer. Thrift interface definitions are found
in src/main/thrift
. The Thrift compiler generates Java bindings in
build/generated-sources/thrift/gen-java
, and JavaScript bindings with TypeScript type declarations
in build/generated-sources/thrift/gen-js
.
Whenever we make a change to our Thrift interface definitions, there are also some manual steps to be taken:
- Update imports and exports: The generated JavaScript code is not in any kind of a module,
so we have settings in
webpack.config.js
that insert appropriate export and import statements during packaging. Any new types we add must be exported from their corresponding JS files, and any new types we use in the service declarations must be imported to their corresponding JS files. - Update Flow declarations: Thrift generates TypeScript, but we use Flow. Fortunately the
two have very similar syntax. We have manually ported the TypeScript files generated by the Thrift
compiler to Flow syntax in
src/main/flow
. Whenever we change our Thrift definitions, we need to re-port the parts of the TypeScript that correspond to the added/changed types, methods, etc. If we do this often enough, we can invest in a script to do the translation for us.
Examples
Insert trace data into database
$ ./tracery-service.sh insert --diskio example_trace ./tracery.db
$ sqlite3 ./tracery.db
sqlite> .tables
com_facebook_tracery_database_trace_DiskPhysOpTable
com_facebook_tracery_database_trace_FileInfoTable
trace_master
sqlite> .headers on
sqlite> .mode column
sqlite> SELECT * FROM trace_master;
...
sqlite> SELECT * FROM com_facebook_tracery_database_trace_FileInfoTable;
...
sqlite> SELECT * FROM com_facebook_tracery_database_trace_DiskPhysOpTable;
...
sqlite> .exit