{"action":"created","issue":{"url":"https://api.github.com/repos/Graylog2/graylog2-server/issues/1604","labels_url":"https://api.github.com/repos/Graylog2/graylog2-server/issues/1604/labels{/name}","comments_url":"https://api.github.com/repos/Graylog2/graylog2-server/issues/1604/comments","events_url":"https://api.github.com/repos/Graylog2/graylog2-server/issues/1604/events","html_url":"https://github.com/Graylog2/graylog2-server/pull/1604","id":120356016,"number":1604,"title":"Make index rotation strategies pluggable","user":{"login":"bernd","id":461,"avatar_url":"https://avatars.githubusercontent.com/u/461?v=3","gravatar_id":"","url":"https://api.github.com/users/bernd","html_url":"https://github.com/bernd","followers_url":"https://api.github.com/users/bernd/followers","following_url":"https://api.github.com/users/bernd/following{/other_user}","gists_url":"https://api.github.com/users/bernd/gists{/gist_id}","starred_url":"https://api.github.com/users/bernd/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bernd/subscriptions","organizations_url":"https://api.github.com/users/bernd/orgs","repos_url":"https://api.github.com/users/bernd/repos","events_url":"https://api.github.com/users/bernd/events{/privacy}","received_events_url":"https://api.github.com/users/bernd/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/Graylog2/graylog2-server/labels/ready-for-review","name":"ready-for-review","color":"e11d21"}],"state":"open","locked":false,"assignee":{"login":"joschi","id":43951,"avatar_url":"https://avatars.githubusercontent.com/u/43951?v=3","gravatar_id":"","url":"https://api.github.com/users/joschi","html_url":"https://github.com/joschi","followers_url":"https://api.github.com/users/joschi/followers","following_url":"https://api.github.com/users/joschi/following{/other_user}","gists_url":"https://api.github.com/users/joschi/gists{/gist_id}","starred_url":"https://api.github.com/users/joschi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/joschi/subscriptions","organizations_url":"https://api.github.com/users/joschi/orgs","repos_url":"https://api.github.com/users/joschi/repos","events_url":"https://api.github.com/users/joschi/events{/privacy}","received_events_url":"https://api.github.com/users/joschi/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/Graylog2/graylog2-server/milestones/40","html_url":"https://github.com/Graylog2/graylog2-server/milestones/2.x","labels_url":"https://api.github.com/repos/Graylog2/graylog2-server/milestones/40/labels","id":1170288,"number":40,"title":"2.x","description":"Future release in the 2.x scope.","creator":{"login":"zexxon","id":1154318,"avatar_url":"https://avatars.githubusercontent.com/u/1154318?v=3","gravatar_id":"","url":"https://api.github.com/users/zexxon","html_url":"https://github.com/zexxon","followers_url":"https://api.github.com/users/zexxon/followers","following_url":"https://api.github.com/users/zexxon/following{/other_user}","gists_url":"https://api.github.com/users/zexxon/gists{/gist_id}","starred_url":"https://api.github.com/users/zexxon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zexxon/subscriptions","organizations_url":"https://api.github.com/users/zexxon/orgs","repos_url":"https://api.github.com/users/zexxon/repos","events_url":"https://api.github.com/users/zexxon/events{/privacy}","received_events_url":"https://api.github.com/users/zexxon/received_events","type":"User","site_admin":false},"open_issues":12,"closed_issues":21,"state":"open","created_at":"2015-06-18T09:17:11Z","updated_at":"2015-12-09T13:41:13Z","due_on":null,"closed_at":null},"comments":4,"created_at":"2015-12-04T08:33:18Z","updated_at":"2015-12-09T15:06:37Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/Graylog2/graylog2-server/pulls/1604","html_url":"https://github.com/Graylog2/graylog2-server/pull/1604","diff_url":"https://github.com/Graylog2/graylog2-server/pull/1604.diff","patch_url":"https://github.com/Graylog2/graylog2-server/pull/1604.patch"},"body":"A first version of making the rotation strategies pluggable. Once we decide that this is the way to go, I will also do the same for the retention strategies.\r\n\r\n### Changes\r\n\r\n- Change RotationStrategy interface to only require a rotate() method\r\n- Add addRotationStrategy() helper to PluginModule\r\n- Move rotation strategy configuration into the cluster configuration\r\n- Add a ConfigManagementPeriodical which migrates settings from the server configuration file to the database\r\n\r\nThe TimeBasedRotationStrategy still needs to be a `@Singleton` because it keeps state. This will be moved to the database in a later step.\r\n\r\n### Discussion\r\n\r\nTo add a new rotation strategy, the `addRotationStrategy(MyStrategy.class)` needs to be called in the guice bindings. The strategies take care of getting their configuration on their own. This makes it more flexible than passing in the configuration and also simplifies the bindings and implementation.\r\n\r\nAs said in the commit message, the `TimeBasedRotationStrategy` still needs to be a `@Singleton` because it keeps state. That state should be moved into the database so the strategy does not need to be a singleton.\r\n\r\n### TODO\r\n\r\n* The rotation strategies need to be configurable via REST API. This will be added once we decided to go ahead with this.\r\n* The implementation of the rotation strategies can be simplified. I didn't do that yet to keep the changes small and reviewable."},"comment":{"url":"https://api.github.com/repos/Graylog2/graylog2-server/issues/comments/163283676","html_url":"https://github.com/Graylog2/graylog2-server/pull/1604#issuecomment-163283676","issue_url":"https://api.github.com/repos/Graylog2/graylog2-server/issues/1604","id":163283676,"user":{"login":"joschi","id":43951,"avatar_url":"https://avatars.githubusercontent.com/u/43951?v=3","gravatar_id":"","url":"https://api.github.com/users/joschi","html_url":"https://github.com/joschi","followers_url":"https://api.github.com/users/joschi/followers","following_url":"https://api.github.com/users/joschi/following{/other_user}","gists_url":"https://api.github.com/users/joschi/gists{/gist_id}","starred_url":"https://api.github.com/users/joschi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/joschi/subscriptions","organizations_url":"https://api.github.com/users/joschi/orgs","repos_url":"https://api.github.com/users/joschi/repos","events_url":"https://api.github.com/users/joschi/events{/privacy}","received_events_url":"https://api.github.com/users/joschi/received_events","type":"User","site_admin":false},"created_at":"2015-12-09T15:06:37Z","updated_at":"2015-12-09T15:06:37Z","body":"Accessing the deflector resource currently generates an internal server error.\r\n\r\nRequest URL: `http://127.0.0.1:12900/system/deflector/config`\r\nResponse Body:\r\n```\r\n{\r\n  \"type\": \"ApiError\",\r\n  \"message\": \"A MultiException has 1 exceptions.  They are:\\n1. java.lang.reflect.UndeclaredThrowableException\\n\"\r\n}\r\n```\r\n\r\nException:\r\n```\r\n015-12-09 16:03:09,179 ERROR: org.graylog2.shared.rest.exceptionmappers.AnyExceptionClassMapper - Unhandled exception in REST resource\r\norg.glassfish.hk2.api.MultiException: A MultiException has 1 exceptions.  They are:\r\n1. java.lang.reflect.UndeclaredThrowableException\r\n\r\n\tat org.jvnet.hk2.internal.Collector.throwIfErrors(Collector.java:89) ~[hk2-locator-2.4.0-b31.jar:?]\r\n\tat org.jvnet.hk2.internal.ServiceLocatorImpl.secondChanceResolve(ServiceLocatorImpl.java:522) ~[hk2-locator-2.4.0-b31.jar:?]\r\n\tat org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetInjecteeDescriptor(ServiceLocatorImpl.java:582) ~[hk2-locator-2.4.0-b31.jar:?]\r\n\tat org.jvnet.hk2.internal.ServiceLocatorImpl.getInjecteeDescriptor(ServiceLocatorImpl.java:594) ~[hk2-locator-2.4.0-b31.jar:?]\r\n\tat org.jvnet.hk2.internal.IterableProviderImpl.justInTime(IterableProviderImpl.java:99) ~[hk2-locator-2.4.0-b31.jar:?]\r\n\tat org.jvnet.hk2.internal.IterableProviderImpl.get(IterableProviderImpl.java:108) ~[hk2-locator-2.4.0-b31.jar:?]\r\n\tat org.graylog2.rest.resources.system.DeflectorResource.config(DeflectorResource.java:92) ~[classes/:?]\r\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_66]\r\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_66]\r\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_66]\r\n\tat java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_66]\r\n\tat org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81) ~[jersey-server-2.22.1.jar:?]\r\n\tat org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:144) ~[jersey-server-2.22.1.jar:?]\r\n\tat org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:161) ~[jersey-server-2.22.1.jar:?]\r\n\tat org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:205) ~[jersey-server-2.22.1.jar:?]\r\n\tat org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99) ~[jersey-server-2.22.1.jar:?]\r\n\tat org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389) ~[jersey-server-2.22.1.jar:?]\r\n\tat org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347) ~[jersey-server-2.22.1.jar:?]\r\n\tat org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102) ~[jersey-server-2.22.1.jar:?]\r\n\tat org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:326) [jersey-server-2.22.1.jar:?]\r\n\tat org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) [jersey-common-2.22.1.jar:?]\r\n\tat org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) [jersey-common-2.22.1.jar:?]\r\n\tat org.glassfish.jersey.internal.Errors.process(Errors.java:315) [jersey-common-2.22.1.jar:?]\r\n\tat org.glassfish.jersey.internal.Errors.process(Errors.java:297) [jersey-common-2.22.1.jar:?]\r\n\tat org.glassfish.jersey.internal.Errors.process(Errors.java:267) [jersey-common-2.22.1.jar:?]\r\n\tat org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317) [jersey-common-2.22.1.jar:?]\r\n\tat org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305) [jersey-server-2.22.1.jar:?]\r\n\tat org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154) [jersey-server-2.22.1.jar:?]\r\n\tat org.graylog2.jersey.container.netty.NettyContainer.messageReceived(NettyContainer.java:356) [jersey-netty-1.5.2.jar:?]\r\n\tat org.jboss.netty.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.java:70) [netty-3.10.5.Final.jar:?]\r\n\tat org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:564) [netty-3.10.5.Final.jar:?]\r\n\tat org.jboss.netty.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendUpstream(DefaultChannelPipeline.java:791) [netty-3.10.5.Final.jar:?]\r\n\tat org.jboss.netty.handler.execution.ChannelUpstreamEventRunnable.doRun(ChannelUpstreamEventRunnable.java:43) [netty-3.10.5.Final.jar:?]\r\n\tat org.jboss.netty.handler.execution.ChannelEventRunnable.run(ChannelEventRunnable.java:67) [netty-3.10.5.Final.jar:?]\r\n\tat com.codahale.metrics.InstrumentedExecutorService$InstrumentedRunnable.run(InstrumentedExecutorService.java:176) [metrics-core-3.1.2.jar:3.1.2]\r\n\tat org.jboss.netty.handler.execution.MemoryAwareThreadPoolExecutor$MemoryAwareRunnable.run(MemoryAwareThreadPoolExecutor.java:606) [netty-3.10.5.Final.jar:?]\r\n\tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0_66]\r\n\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0_66]\r\n\tat java.lang.Thread.run(Thread.java:745) [?:1.8.0_66]\r\nCaused by: java.lang.reflect.UndeclaredThrowableException\r\n\tat com.sun.proxy.$Proxy152.getBinding(Unknown Source) ~[?:?]\r\n\tat org.jvnet.hk2.guice.bridge.internal.GuiceToHk2JITResolver.findBinding(GuiceToHk2JITResolver.java:86) ~[guice-bridge-2.4.0-b31.jar:?]\r\n\tat org.jvnet.hk2.guice.bridge.internal.GuiceToHk2JITResolver.justInTimeResolution(GuiceToHk2JITResolver.java:140) ~[guice-bridge-2.4.0-b31.jar:?]\r\n\tat org.jvnet.hk2.internal.ServiceLocatorImpl.secondChanceResolve(ServiceLocatorImpl.java:511) ~[hk2-locator-2.4.0-b31.jar:?]\r\n\t... 37 more\r\nCaused by: java.lang.reflect.InvocationTargetException\r\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_66]\r\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_66]\r\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_66]\r\n\tat java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_66]\r\n\tat org.graylog2.shared.bindings.Hk2GuiceBridgeJitInjector.invoke(Hk2GuiceBridgeJitInjector.java:90) ~[classes/:?]\r\n\tat com.sun.proxy.$Proxy152.getBinding(Unknown Source) ~[?:?]\r\n\tat org.jvnet.hk2.guice.bridge.internal.GuiceToHk2JITResolver.findBinding(GuiceToHk2JITResolver.java:86) ~[guice-bridge-2.4.0-b31.jar:?]\r\n\tat org.jvnet.hk2.guice.bridge.internal.GuiceToHk2JITResolver.justInTimeResolution(GuiceToHk2JITResolver.java:140) ~[guice-bridge-2.4.0-b31.jar:?]\r\n\tat org.jvnet.hk2.internal.ServiceLocatorImpl.secondChanceResolve(ServiceLocatorImpl.java:511) ~[hk2-locator-2.4.0-b31.jar:?]\r\n\t... 37 more\r\nCaused by: com.google.inject.ConfigurationException: Guice configuration errors:\r\n\r\n1) No implementation for org.graylog2.plugin.indexer.rotation.RotationStrategy was bound.\r\n  while locating org.graylog2.plugin.indexer.rotation.RotationStrategy\r\n\r\n1 error\r\n\tat com.google.inject.internal.InjectorImpl.getBinding(InjectorImpl.java:159) ~[guice-4.0.jar:?]\r\n\tat com.google.inject.internal.InjectorImpl.getBinding(InjectorImpl.java:67) ~[guice-4.0.jar:?]\r\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_66]\r\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_66]\r\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_66]\r\n\tat java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_66]\r\n\tat org.graylog2.shared.bindings.Hk2GuiceBridgeJitInjector.invoke(Hk2GuiceBridgeJitInjector.java:90) ~[classes/:?]\r\n\tat com.sun.proxy.$Proxy152.getBinding(Unknown Source) ~[?:?]\r\n\tat org.jvnet.hk2.guice.bridge.internal.GuiceToHk2JITResolver.findBinding(GuiceToHk2JITResolver.java:86) ~[guice-bridge-2.4.0-b31.jar:?]\r\n\tat org.jvnet.hk2.guice.bridge.internal.GuiceToHk2JITResolver.justInTimeResolution(GuiceToHk2JITResolver.java:140) ~[guice-bridge-2.4.0-b31.jar:?]\r\n\tat org.jvnet.hk2.internal.ServiceLocatorImpl.secondChanceResolve(ServiceLocatorImpl.java:511) ~[hk2-locator-2.4.0-b31.jar:?]\r\n\t... 37 more\r\n```"}}