{"action":"created","issue":{"url":"https://api.github.com/repos/ReactiveX/RxJava/issues/4007","repository_url":"https://api.github.com/repos/ReactiveX/RxJava","labels_url":"https://api.github.com/repos/ReactiveX/RxJava/issues/4007/labels{/name}","comments_url":"https://api.github.com/repos/ReactiveX/RxJava/issues/4007/comments","events_url":"https://api.github.com/repos/ReactiveX/RxJava/issues/4007/events","html_url":"https://github.com/ReactiveX/RxJava/pull/4007","id":160194213,"number":4007,"title":"1.x: new hook management proposal","user":{"login":"akarnokd","id":1269832,"avatar_url":"https://avatars.githubusercontent.com/u/1269832?v=3","gravatar_id":"","url":"https://api.github.com/users/akarnokd","html_url":"https://github.com/akarnokd","followers_url":"https://api.github.com/users/akarnokd/followers","following_url":"https://api.github.com/users/akarnokd/following{/other_user}","gists_url":"https://api.github.com/users/akarnokd/gists{/gist_id}","starred_url":"https://api.github.com/users/akarnokd/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akarnokd/subscriptions","organizations_url":"https://api.github.com/users/akarnokd/orgs","repos_url":"https://api.github.com/users/akarnokd/repos","events_url":"https://api.github.com/users/akarnokd/events{/privacy}","received_events_url":"https://api.github.com/users/akarnokd/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/ReactiveX/RxJava/labels/Discussion","name":"Discussion","color":"5319e7"},{"url":"https://api.github.com/repos/ReactiveX/RxJava/labels/Enhancement","name":"Enhancement","color":"84b6eb"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":3,"created_at":"2016-06-14T14:22:17Z","updated_at":"2016-06-15T07:32:20Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/ReactiveX/RxJava/pulls/4007","html_url":"https://github.com/ReactiveX/RxJava/pull/4007","diff_url":"https://github.com/ReactiveX/RxJava/pull/4007.diff","patch_url":"https://github.com/ReactiveX/RxJava/pull/4007.patch"},"body":"This PR adds a new, in-between, hook manager class, `RxJavaHooks` that allows runtime hooking of `Observable`, `Single`, `Completable` and `Schedulers` components and is aimed to be more versatile than the `RxJavaPlugins`.\r\n\r\nSince `RxJavaPlugins` is public API, it can't be just removed, therefore, `RxJavaHooks` by default delegates to it but that delegation can be completely disabled via `clear()`.\r\n\r\n#### Usage\r\n\r\nCall the `setOn` methods with an appropriate function to manipulate the object being hooked:\r\n\r\n```java\r\nRxJavaHooks.setOnComputationScheduler(s -> Schedulers.immediate());\r\n\r\nRxJavaHooks.setObservableCreate(o -> { System.out.println(\"Creating: \" + o); return o; });\r\n```\r\n\r\nYou can also get the current hooks via the `getOn` methods, allowing chaining multiple hooks if necessary. Changing and retrieving the hooks are thread safe, although it is recommended you change them in quiet times.\r\n\r\nOperator writers should usually not call the `onXXX` methods on `RxJavaHooks` except `RxJavaHooks.onError()`; It is useful when they have to signal a `Throwable` that can't be delivered to a `Subscriber`.\r\n\r\nCalling `reset()` will restore the original delegation hooks.\r\n\r\nThis PR also features a way of tracking the assembly locations, that is where `Observable.create()` was invoked internally or externally, via `enableAssemblyTracking`. It changes the creation hooks of all 3 base types by adding an `OnSubscribeOnAssemblyX` wrapper. This operator will replace the Throwable flowing through `onError` and wraps it via the new `AssemblyStackTraceException`. \r\n\r\nBoth the wrapper and the exception contain a string representation of the captured stacktrace, this helps \"printing\" out that information in a debugging session by simply viewing the field contents.\r\n\r\nThis tracking can be enabled at any time and affects sequences created afterwards. To stop the tracking, use `resetAssemblyTracking` to restore the default delegate callbacks to `RxJavaPlugins` or `clearAssemblyTracking` to restore the empty hooks (only affecting the `onCreate` hooks).\r\n\r\nFor frameworks, the `RxJavaHooks` can be locked down, preventing changing the hooks.\r\n\r\nIf you are using `RxJavaPlugins` existing features, you don't have to do anything; tests will work as before.\r\n\r\n#### Performance impact\r\n\r\nA default `RxJavaHooks` incurs a 2-4 level indirection in method calls. `onNext` calls are not affected.\r\n\r\nA clear `RxJavaHooks` incurs a volatile read (very cheap) followed by a branch (predictable). `onNext` calls are not affected.\r\n\r\nA tracking-enabled RxJavaHooks incurs an estimated 1000-3000 cycles overhead for each source creation and operator application. The `AssemblyStackTraceException` itself doesn't fill in its own stacktrace but takes only the captured stacktrace string and has mostly the cost of an object allocation. Due to the in-between nature of tracking, `onXXX` calls get through another indirection at each operator. For example, `range(1, 5).map(v -> v).filter(v -> true).subscribe()` will have 3 extra layers (one for each `.`). I believe these are acceptable overheads because the tracking feature is for tracking down crashes and not performance problems.\r\n\r\n#### Discussion\r\n\r\nNot all hook methods have been replicated completely on `RxJavaHooks`. For one, I wanted a minimal working prototype that passes existing tests. Second, those that are left out are not even tested (`onSubscribeError`, `onLift`). If the **concept** of this PR is accepted, those can be added along with their unit tests. Also further Javadoc will be added in the same case.\r\n\r\nNames and structure are not set in stone."},"comment":{"url":"https://api.github.com/repos/ReactiveX/RxJava/issues/comments/226110273","html_url":"https://github.com/ReactiveX/RxJava/pull/4007#issuecomment-226110273","issue_url":"https://api.github.com/repos/ReactiveX/RxJava/issues/4007","id":226110273,"user":{"login":"artem-zinnatullin","id":967132,"avatar_url":"https://avatars.githubusercontent.com/u/967132?v=3","gravatar_id":"","url":"https://api.github.com/users/artem-zinnatullin","html_url":"https://github.com/artem-zinnatullin","followers_url":"https://api.github.com/users/artem-zinnatullin/followers","following_url":"https://api.github.com/users/artem-zinnatullin/following{/other_user}","gists_url":"https://api.github.com/users/artem-zinnatullin/gists{/gist_id}","starred_url":"https://api.github.com/users/artem-zinnatullin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/artem-zinnatullin/subscriptions","organizations_url":"https://api.github.com/users/artem-zinnatullin/orgs","repos_url":"https://api.github.com/users/artem-zinnatullin/repos","events_url":"https://api.github.com/users/artem-zinnatullin/events{/privacy}","received_events_url":"https://api.github.com/users/artem-zinnatullin/received_events","type":"User","site_admin":false},"created_at":"2016-06-15T07:32:20Z","updated_at":"2016-06-15T07:32:20Z","body":"Accept `StackTraceElement[]` in the function and pass fake `StackTraceElement[]` in tests?"}}
{"actor":{"display_login":"artem-zinnatullin"}}