├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── build.gradle
├── codequality
├── HEADER
└── checkstyle.xml
├── gradle.properties
├── gradle
├── buildscript.gradle
├── check.gradle
├── convention.gradle
├── license.gradle
├── maven.gradle
├── netflix-oss.gradle
├── release.gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
├── turbine-core
├── build.gradle
├── src
│ ├── main
│ │ └── java
│ │ │ └── com
│ │ │ └── netflix
│ │ │ └── turbine
│ │ │ ├── StartTurbine.java
│ │ │ ├── Turbine.java
│ │ │ ├── aggregator
│ │ │ ├── AggregateString.java
│ │ │ ├── GroupKey.java
│ │ │ ├── InstanceKey.java
│ │ │ ├── NumberList.java
│ │ │ ├── StreamAggregator.java
│ │ │ └── TypeAndNameKey.java
│ │ │ ├── discovery
│ │ │ ├── StreamAction.java
│ │ │ └── StreamDiscovery.java
│ │ │ └── internal
│ │ │ ├── AggregateStringSerializer.java
│ │ │ ├── JsonUtility.java
│ │ │ ├── NumberListSerializer.java
│ │ │ └── RequestCreator.java
│ └── test
│ │ ├── java
│ │ └── com
│ │ │ └── netflix
│ │ │ └── turbine
│ │ │ ├── Demo.java
│ │ │ ├── HttpServerDemo.java
│ │ │ ├── HystrixStreamSource.java
│ │ │ ├── aggregator
│ │ │ ├── AggregateStringTest.java
│ │ │ ├── NumberListTest.java
│ │ │ └── StreamAggregatorTest.java
│ │ │ └── internal
│ │ │ └── RequestCreatorTest.java
│ │ └── resources
│ │ └── com
│ │ └── netflix
│ │ └── turbine
│ │ ├── hystrix-cinematch.stream
│ │ ├── hystrix-subscriber.stream
│ │ ├── hystrix-subscriber_cinematch_1.stream
│ │ ├── hystrix-subscriber_cinematch_2.stream
│ │ ├── hystrix.stream
│ │ └── unsort
└── testfiles
│ └── StatsSingleServerMonitorUnitTest.txt
└── turbine-ext
├── turbine-discovery-eureka1
├── build.gradle
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── netflix
│ │ │ └── turbine
│ │ │ └── discovery
│ │ │ └── eureka
│ │ │ ├── EurekaInstance.java
│ │ │ ├── EurekaInstanceDiscovery.java
│ │ │ ├── EurekaStreamDiscovery.java
│ │ │ └── StartEurekaTurbine.java
│ └── resources
│ │ ├── eureka-client.properties
│ │ └── log4j.properties
│ └── test
│ └── java
│ └── com
│ └── netflix
│ └── turbine
│ └── discovery
│ └── eureka
│ └── EurekaInstanceDiscoveryTest.java
└── turbine-discovery-eureka2
├── build.gradle
└── src
├── main
├── java
│ └── com
│ │ └── netflix
│ │ └── turbine
│ │ └── discovery
│ │ └── eureka
│ │ ├── EurekaInstance.java
│ │ ├── EurekaInstanceDiscovery.java
│ │ ├── EurekaStreamDiscovery.java
│ │ └── StartEurekaTurbine.java
└── resources
│ └── log4j.properties
└── test
└── java
└── com
└── netflix
└── turbine
└── discovery
└── eureka
└── EurekaInstanceDiscoveryTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled source #
2 | ###################
3 | *.com
4 | *.class
5 | *.dll
6 | *.exe
7 | *.o
8 | *.so
9 |
10 | # Packages #
11 | ############
12 | # it's better to unpack these files and commit the raw source
13 | # git has its own built in compression methods
14 | *.7z
15 | *.dmg
16 | *.gz
17 | *.iso
18 | *.jar
19 | *.rar
20 | *.tar
21 | *.zip
22 |
23 | # Logs and databases #
24 | ######################
25 | *.log
26 |
27 | # OS generated files #
28 | ######################
29 | .DS_Store*
30 | ehthumbs.db
31 | Icon?
32 | Thumbs.db
33 |
34 | # Editor Files #
35 | ################
36 | *~
37 | *.swp
38 |
39 | # Gradle Files #
40 | ################
41 | .gradle
42 |
43 | # Build output directies
44 | /target
45 | */target
46 | /build
47 | */build
48 | build/
49 |
50 | # IntelliJ specific files/directories
51 | out
52 | .idea
53 | *.ipr
54 | *.iws
55 | *.iml
56 | atlassian-ide-plugin.xml
57 |
58 | # Eclipse specific files/directories
59 | .classpath
60 | .project
61 | .settings
62 | .metadata
63 | bin/
64 |
65 | # NetBeans specific files/directories
66 | .nbattrs
67 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 |
3 | jdk:
4 | - oraclejdk8
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright 2012 Netflix, Inc.
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Documentation
2 |
3 | See the [Wiki](https://github.com/Netflix/Turbine/wiki) for full documentation, examples, operational details and other information.
4 |
5 | ## Build Status
6 |
7 |
8 |
9 | ## Bugs and Feedback
10 |
11 | For bugs, questions and discussions please use the [Github Issues](https://github.com/Netflix/Turbine/issues).
12 |
13 | ## Binaries
14 |
15 | Binaries and dependency information for Maven, Ivy, Gradle and others can be found at [http://search.maven.org](http://search.maven.org/#search%7Cga%7C1%7Cnetflix%20turbine).
16 |
17 | ### Library
18 |
19 | Dependencies on the library for embedded use are found on Maven Central.
20 |
21 | Example for Maven:
22 |
23 | ```xml
24 |
25 | com.netflix.turbine
26 | turbine
27 | 2.minor.patch
28 |
29 | ```
30 | and for Ivy:
31 |
32 | ```xml
33 |
34 | ```
35 |
36 | ### Executable
37 |
38 | The standalone executable can also be found on Maven Central or in the Github Releases section.
39 |
40 |
41 | ## Build
42 |
43 | * You need Java 8 or later.
44 |
45 | To build:
46 |
47 | ```
48 | $ git clone git@github.com:Netflix/Turbine.git
49 | $ cd Turbine/
50 | $ ./gradlew build
51 | ```
52 |
53 |
54 | ## LICENSE
55 |
56 | Copyright 2014 Netflix, Inc.
57 |
58 | Licensed under the Apache License, Version 2.0 (the "License");
59 | you may not use this file except in compliance with the License.
60 | You may obtain a copy of the License at
61 |
62 |
63 |
64 | Unless required by applicable law or agreed to in writing, software
65 | distributed under the License is distributed on an "AS IS" BASIS,
66 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
67 | See the License for the specific language governing permissions and
68 | limitations under the License.
69 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Establish version and status
2 | ext.githubProjectName = rootProject.name // Change if github project name is not the same as the root project's name
3 |
4 | buildscript {
5 | repositories {
6 | mavenLocal()
7 | mavenCentral() // maven { url 'http://jcenter.bintray.com' }
8 | jcenter()
9 | }
10 | dependencies {
11 | classpath 'com.github.jengelman.gradle.plugins:shadow:1.1.1'
12 | }
13 | apply from: file('gradle/buildscript.gradle'), to: buildscript
14 | }
15 |
16 |
17 | allprojects {
18 | repositories {
19 | mavenLocal()
20 | mavenCentral() // maven { url 'http://jcenter.bintray.com' }
21 | jcenter()
22 | }
23 | }
24 |
25 | apply from: file('gradle/convention.gradle')
26 | apply from: file('gradle/maven.gradle')
27 | //apply from: file('gradle/check.gradle')
28 | apply from: file('gradle/license.gradle')
29 | apply from: file('gradle/release.gradle')
30 |
31 | tasks.withType(Javadoc).each { task ->
32 | task.enabled = false
33 | }
34 |
35 | subprojects {
36 |
37 | group = "com.netflix.${githubProjectName}"
38 |
39 | tasks.withType(Javadoc).each { task ->
40 | task.enabled = false
41 | }
42 |
43 | sourceSets {
44 | test {
45 | java {
46 | srcDir 'src/main/java'
47 | }
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/codequality/HEADER:
--------------------------------------------------------------------------------
1 | Copyright ${year} Netflix, Inc.
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
--------------------------------------------------------------------------------
/codequality/checkstyle.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | version=2.0.0-DP.3-SNAPSHOT
2 |
--------------------------------------------------------------------------------
/gradle/buildscript.gradle:
--------------------------------------------------------------------------------
1 | // Executed in context of buildscript
2 | repositories {
3 | // Repo in addition to maven central
4 | repositories { maven { url 'http://dl.bintray.com/content/netflixoss/external-gradle-plugins/' } } // For gradle-release
5 | }
6 | dependencies {
7 | classpath 'nl.javadude.gradle.plugins:license-gradle-plugin:0.6.1'
8 | classpath 'com.mapvine:gradle-cobertura-plugin:0.1'
9 | classpath 'gradle-release:gradle-release:1.1.5'
10 | classpath 'org.ajoberstar:gradle-git:0.5.0'
11 | }
12 |
--------------------------------------------------------------------------------
/gradle/check.gradle:
--------------------------------------------------------------------------------
1 | subprojects {
2 | // Checkstyle
3 | apply plugin: 'checkstyle'
4 | checkstyle {
5 | ignoreFailures = true
6 | configFile = rootProject.file('codequality/checkstyle.xml')
7 | }
8 |
9 | // FindBugs
10 | apply plugin: 'findbugs'
11 | findbugs {
12 | ignoreFailures = true
13 | }
14 |
15 | // PMD
16 | apply plugin: 'pmd'
17 | //tasks.withType(Pmd) { reports.html.enabled true }
18 |
19 | apply plugin: 'cobertura'
20 | cobertura {
21 | sourceDirs = sourceSets.main.java.srcDirs
22 | format = 'html'
23 | includes = ['**/*.java', '**/*.groovy']
24 | excludes = []
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/gradle/convention.gradle:
--------------------------------------------------------------------------------
1 | // GRADLE-2087 workaround, perform after java plugin
2 | status = project.hasProperty('preferredStatus')?project.preferredStatus:(version.contains('SNAPSHOT')?'snapshot':'release')
3 |
4 | subprojects { project ->
5 | apply plugin: 'java' // Plugin as major conventions
6 |
7 | sourceCompatibility = 1.6
8 |
9 | // Restore status after Java plugin
10 | status = rootProject.status
11 |
12 | task sourcesJar(type: Jar, dependsOn:classes) {
13 | from sourceSets.main.allSource
14 | classifier 'sources'
15 | extension 'jar'
16 | }
17 |
18 | task javadocJar(type: Jar, dependsOn:javadoc) {
19 | from javadoc.destinationDir
20 | classifier 'javadoc'
21 | extension 'jar'
22 | }
23 |
24 | configurations.add('sources')
25 | configurations.add('javadoc')
26 | configurations.archives {
27 | extendsFrom configurations.sources
28 | extendsFrom configurations.javadoc
29 | }
30 |
31 | // When outputing to an Ivy repo, we want to use the proper type field
32 | gradle.taskGraph.whenReady {
33 | def isNotMaven = !it.hasTask(project.uploadMavenCentral)
34 | if (isNotMaven) {
35 | def artifacts = project.configurations.sources.artifacts
36 | def sourceArtifact = artifacts.iterator().next()
37 | sourceArtifact.type = 'sources'
38 | }
39 | }
40 |
41 | artifacts {
42 | sources(sourcesJar) {
43 | // Weird Gradle quirk where type will be used for the extension, but only for sources
44 | type 'jar'
45 | }
46 | javadoc(javadocJar) {
47 | type 'javadoc'
48 | }
49 | }
50 |
51 | configurations {
52 | provided {
53 | description = 'much like compile, but indicates you expect the JDK or a container to provide it. It is only available on the compilation classpath, and is not transitive.'
54 | transitive = true
55 | visible = true
56 | }
57 | }
58 |
59 | project.sourceSets {
60 | main.compileClasspath += project.configurations.provided
61 | main.runtimeClasspath -= project.configurations.provided
62 | test.compileClasspath += project.configurations.provided
63 | test.runtimeClasspath += project.configurations.provided
64 | }
65 | }
66 |
67 | apply plugin: 'github-pages' // Used to create publishGhPages task
68 |
69 | def docTasks = [:]
70 | [Javadoc,ScalaDoc,Groovydoc].each{ Class docClass ->
71 | def allSources = allprojects.tasks*.withType(docClass).flatten()*.source
72 | if (allSources) {
73 | def shortName = docClass.simpleName.toLowerCase()
74 | def docTask = task "aggregate${shortName.capitalize()}"(type: docClass, description: "Aggregate subproject ${shortName}s") {
75 | source = allSources
76 | destinationDir = file("${project.buildDir}/docs/${shortName}")
77 | doFirst {
78 | def classpaths = allprojects.findAll { it.plugins.hasPlugin(JavaPlugin) }.collect { it.sourceSets.main.compileClasspath }
79 | classpath = files(classpaths)
80 | }
81 | }
82 | docTasks[shortName] = docTask
83 | processGhPages.dependsOn(docTask)
84 | }
85 | }
86 |
87 | githubPages {
88 | repoUri = "git@github.com:Netflix/${rootProject.githubProjectName}.git"
89 | pages {
90 | docTasks.each { shortName, docTask ->
91 | from(docTask.outputs.files) {
92 | into "docs/${shortName}"
93 | }
94 | }
95 | }
96 | }
97 |
98 | // Generate wrapper, which is distributed as part of source to alleviate the need of installing gradle
99 | task createWrapper(type: Wrapper) {
100 | gradleVersion = '1.5'
101 | }
102 |
--------------------------------------------------------------------------------
/gradle/license.gradle:
--------------------------------------------------------------------------------
1 | // Dependency for plugin was set in buildscript.gradle
2 |
3 | subprojects {
4 | apply plugin: 'license' //nl.javadude.gradle.plugins.license.LicensePlugin
5 | license {
6 | header rootProject.file('codequality/HEADER')
7 | ext.year = Calendar.getInstance().get(Calendar.YEAR)
8 | skipExistingHeaders true
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/gradle/maven.gradle:
--------------------------------------------------------------------------------
1 | // Maven side of things
2 | subprojects {
3 | apply plugin: 'maven' // Java plugin has to have been already applied for the conf2scope mappings to work
4 | apply plugin: 'signing'
5 |
6 | signing {
7 | required { gradle.taskGraph.hasTask(uploadMavenCentral) }
8 | sign configurations.archives
9 | }
10 |
11 | /**
12 | * Publishing to Maven Central example provided from http://jedicoder.blogspot.com/2011/11/automated-gradle-project-deployment-to.html
13 | * artifactory will execute uploadArchives to force generation of ivy.xml, and we don't want that to trigger an upload to maven
14 | * central, so using custom upload task.
15 | */
16 | task uploadMavenCentral(type:Upload, dependsOn: signArchives) {
17 | configuration = configurations.archives
18 | onlyIf { ['release', 'snapshot'].contains(project.status) }
19 | repositories.mavenDeployer {
20 | beforeDeployment { signing.signPom(it) }
21 |
22 | // To test deployment locally, use the following instead of oss.sonatype.org
23 | //repository(url: "file://localhost/${rootProject.rootDir}/repo")
24 |
25 | def sonatypeUsername = rootProject.hasProperty('sonatypeUsername')?rootProject.sonatypeUsername:''
26 | def sonatypePassword = rootProject.hasProperty('sonatypePassword')?rootProject.sonatypePassword:''
27 |
28 | repository(url: 'https://oss.sonatype.org/service/local/staging/deploy/maven2') {
29 | authentication(userName: sonatypeUsername, password: sonatypePassword)
30 | }
31 |
32 | snapshotRepository(url: 'https://oss.sonatype.org/content/repositories/snapshots/') {
33 | authentication(userName: sonatypeUsername, password: sonatypePassword)
34 | }
35 |
36 | // Prevent datastamp from being appending to artifacts during deployment
37 | uniqueVersion = false
38 |
39 | // Closure to configure all the POM with extra info, common to all projects
40 | pom.project {
41 | name "${project.name}"
42 | description "${project.name} developed by Netflix"
43 | developers {
44 | developer {
45 | id 'netflixgithub'
46 | name 'Netflix Open Source Development'
47 | email 'talent@netflix.com'
48 | }
49 | }
50 | licenses {
51 | license {
52 | name 'The Apache Software License, Version 2.0'
53 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
54 | distribution 'repo'
55 | }
56 | }
57 | url "https://github.com/Netflix/${rootProject.githubProjectName}"
58 | scm {
59 | connection "scm:git:git@github.com:Netflix/${rootProject.githubProjectName}.git"
60 | url "scm:git:git@github.com:Netflix/${rootProject.githubProjectName}.git"
61 | developerConnection "scm:git:git@github.com:Netflix/${rootProject.githubProjectName}.git"
62 | }
63 | issueManagement {
64 | system 'github'
65 | url "https://github.com/Netflix/${rootProject.githubProjectName}/issues"
66 | }
67 | }
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/gradle/netflix-oss.gradle:
--------------------------------------------------------------------------------
1 | apply from: 'http://artifacts.netflix.com/gradle-netflix-local/artifactory.gradle'
2 |
--------------------------------------------------------------------------------
/gradle/release.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'release'
2 |
3 | [ uploadIvyLocal: 'uploadLocal', uploadArtifactory: 'artifactoryPublish', buildWithArtifactory: 'build' ].each { key, value ->
4 | // Call out to compile against internal repository
5 | task "${key}"(type: GradleBuild) {
6 | startParameter = project.gradle.startParameter.newInstance()
7 | doFirst {
8 | startParameter.projectProperties = [status: project.status, preferredStatus: project.status]
9 | }
10 | startParameter.addInitScript( file('gradle/netflix-oss.gradle') )
11 | startParameter.getExcludedTaskNames().add('check')
12 | tasks = [ 'build', value ]
13 | }
14 | }
15 |
16 | // Marker task for following code to key in on
17 | task releaseCandidate(dependsOn: release)
18 | task forceCandidate {
19 | onlyIf { gradle.taskGraph.hasTask(releaseCandidate) }
20 | doFirst { project.status = 'candidate' }
21 | }
22 | task forceRelease {
23 | onlyIf { !gradle.taskGraph.hasTask(releaseCandidate) }
24 | doFirst { project.status = 'release' }
25 | }
26 | release.dependsOn([forceCandidate, forceRelease])
27 |
28 | task uploadMavenCentral(dependsOn: subprojects.tasks.uploadMavenCentral)
29 | task releaseSnapshot(dependsOn: [uploadArtifactory, uploadMavenCentral])
30 |
31 | // Ensure our versions look like the project status before publishing
32 | task verifyStatus << {
33 | def hasSnapshot = version.contains('-SNAPSHOT')
34 | if (project.status == 'snapshot' && !hasSnapshot) {
35 | throw new GradleException("Version (${version}) needs -SNAPSHOT if publishing snapshot")
36 | }
37 | }
38 | uploadArtifactory.dependsOn(verifyStatus)
39 | uploadMavenCentral.dependsOn(verifyStatus)
40 |
41 | // Ensure upload happens before taggging, hence upload failures will leave repo in a revertable state
42 | preTagCommit.dependsOn([uploadArtifactory, uploadMavenCentral])
43 |
44 |
45 | gradle.taskGraph.whenReady { taskGraph ->
46 | def hasRelease = taskGraph.hasTask('commitNewVersion')
47 | def indexOf = { return taskGraph.allTasks.indexOf(it) }
48 |
49 | if (hasRelease) {
50 | assert indexOf(build) < indexOf(unSnapshotVersion), 'build target has to be after unSnapshotVersion'
51 | assert indexOf(uploadMavenCentral) < indexOf(preTagCommit), 'preTagCommit has to be after uploadMavenCentral'
52 | assert indexOf(uploadArtifactory) < indexOf(preTagCommit), 'preTagCommit has to be after uploadArtifactory'
53 | }
54 | }
55 |
56 | // Prevent plugin from asking for a version number interactively
57 | ext.'gradle.release.useAutomaticVersion' = "true"
58 |
59 | release {
60 | git.requireBranch = null
61 | }
62 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Netflix/Turbine/0e924058aa4d1d526310206a51dcf82f65274d58/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Aug 14 16:28:54 PDT 2012
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=http\://services.gradle.org/distributions/gradle-1.10-bin.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name='turbine'
2 | include 'turbine-core', 'turbine-ext:turbine-discovery-eureka1', 'turbine-ext:turbine-discovery-eureka2'
3 |
--------------------------------------------------------------------------------
/turbine-core/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java'
2 | apply plugin: 'eclipse'
3 | apply plugin:'application'
4 | apply plugin: 'com.github.johnrengelman.shadow'
5 | apply plugin: 'maven-publish'
6 |
7 | sourceCompatibility = JavaVersion.VERSION_1_8
8 | targetCompatibility = JavaVersion.VERSION_1_8
9 |
10 | dependencies {
11 | compile 'io.reactivex:rxjava:1.0.8'
12 | compile 'com.netflix.rxnetty:rx-netty:0.3.18'
13 | compile 'org.codehaus.jackson:jackson-core-asl:1.9.2'
14 | compile 'org.codehaus.jackson:jackson-mapper-asl:1.9.2'
15 | compile 'net.sf.jopt-simple:jopt-simple:4.8'
16 | compile 'org.slf4j:slf4j-simple:1.7.7'
17 | testCompile 'junit:junit-dep:4.10'
18 | testCompile 'org.json:json:20140107'
19 | }
20 |
21 | mainClassName = "com.netflix.turbine.StartTurbine"
22 |
23 | shadowJar {
24 | baseName = 'turbine-executable'
25 | classifier = ''
26 | }
27 |
28 | publishing {
29 | publications {
30 | shadow(MavenPublication) {
31 | from components.shadow
32 | artifactId = 'turbine-executable'
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/turbine-core/src/main/java/com/netflix/turbine/StartTurbine.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2014 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.netflix.turbine;
17 |
18 | import java.net.URI;
19 | import java.net.URISyntaxException;
20 |
21 | import joptsimple.OptionParser;
22 | import joptsimple.OptionSet;
23 |
24 | public class StartTurbine {
25 |
26 | public static void main(String[] args) {
27 | OptionParser optionParser = new OptionParser();
28 | optionParser.accepts("port").withRequiredArg();
29 | optionParser.accepts("streams").withRequiredArg();
30 |
31 | OptionSet options = optionParser.parse(args);
32 | int port = -1;
33 | if (!options.has("port")) {
34 | System.err.println("Argument -port required for SSE HTTP server to start on.");
35 | System.exit(-1);
36 | } else {
37 | try {
38 | port = Integer.parseInt(String.valueOf(options.valueOf("port")));
39 | } catch (NumberFormatException e) {
40 | System.err.println("Value of port must be an integer but was: " + options.valueOf("port"));
41 | }
42 | }
43 |
44 | URI[] streams = null;
45 | if (!options.hasArgument("streams")) {
46 | System.err.println("Argument -streams required with URIs to connect to. Eg. -streams \"http://host1/metrics.stream http://host2/metrics.stream\"");
47 | System.exit(-1);
48 | } else {
49 | String streamsArg = String.valueOf(options.valueOf("streams"));
50 | String[] ss = streamsArg.split(" ");
51 | streams = new URI[ss.length];
52 | for (int i = 0; i < ss.length; i++) {
53 | try {
54 | streams[i] = new URI(ss[i]);
55 | } catch (URISyntaxException e) {
56 | System.err.println("ERROR: Could not parse stream into URI: " + ss[i]);
57 | System.exit(-1);
58 | }
59 | }
60 | }
61 |
62 | if (streams == null || streams.length == 0) {
63 | System.err.println("There must be at least 1 valid stream URI.");
64 | System.exit(-1);
65 | }
66 |
67 | try {
68 | Turbine.startServerSentEventServer(port, Turbine.aggregateHttpSSE(streams));
69 | } catch (Throwable e) {
70 | e.printStackTrace();
71 | }
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/turbine-core/src/main/java/com/netflix/turbine/Turbine.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2014 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *