├── doc └── intro.md ├── .gitignore ├── src └── opentracing_clj │ ├── impl │ ├── noop.clj │ └── mock.clj │ ├── core.clj │ └── propagation.clj ├── .travis.yml ├── test └── opentracing_clj │ ├── impl │ ├── noop_test.clj │ └── mock_test.clj │ ├── propagation_test.clj │ └── core_test.clj ├── project.clj ├── README.md ├── CHANGELOG.md └── LICENSE /doc/intro.md: -------------------------------------------------------------------------------- 1 | # Introduction to opentracing-clj 2 | 3 | TODO: write [great documentation](http://jacobian.org/writing/what-to-write/) 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /classes 3 | /checkouts 4 | pom.xml 5 | pom.xml.asc 6 | *.jar 7 | *.class 8 | /.lein-* 9 | /.nrepl-port 10 | .hgignore 11 | .hg/ 12 | -------------------------------------------------------------------------------- /src/opentracing_clj/impl/noop.clj: -------------------------------------------------------------------------------- 1 | (ns opentracing-clj.impl.noop 2 | (:import [io.opentracing.noop NoopTracerFactory])) 3 | 4 | (defn make-tracer 5 | "generate a noop tracer" 6 | [] 7 | (NoopTracerFactory/create)) 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: clojure 2 | jdk: 3 | - oraclejdk8 4 | script: 5 | - lein cloverage --codecov 6 | after_success: 7 | - bash <(curl -s https://codecov.io/bash) -f target/coverage/codecov.json 8 | - lein deploy clojars 9 | -------------------------------------------------------------------------------- /test/opentracing_clj/impl/noop_test.clj: -------------------------------------------------------------------------------- 1 | (ns opentracing-clj.impl.noop-test 2 | (:require [clojure.test :refer :all] 3 | [opentracing-clj.impl.noop :refer :all])) 4 | 5 | (deftest constructor 6 | (is (instance? io.opentracing.noop.NoopTracer 7 | (make-tracer)))) 8 | -------------------------------------------------------------------------------- /test/opentracing_clj/impl/mock_test.clj: -------------------------------------------------------------------------------- 1 | (ns opentracing-clj.impl.mock-test 2 | (:require [clojure.test :refer :all] 3 | [opentracing-clj.impl.mock :refer :all]) 4 | (:import [io.opentracing.mock MockTracer MockTracer$Propagator])) 5 | 6 | 7 | (deftest constructor 8 | (is (instance? io.opentracing.mock.MockTracer 9 | (make-tracer))) 10 | (is (instance? io.opentracing.mock.MockTracer 11 | (make-tracer :printer))) 12 | (is (instance? io.opentracing.mock.MockTracer 13 | (make-tracer :text-map))) 14 | (is (thrown-with-msg? Exception #"unknown or unsupported propagator" 15 | (make-tracer :unknown)))) 16 | -------------------------------------------------------------------------------- /src/opentracing_clj/impl/mock.clj: -------------------------------------------------------------------------------- 1 | (ns opentracing-clj.impl.mock 2 | (:import (io.opentracing.mock MockTracer 3 | MockTracer$Propagator) 4 | (io.opentracing.util ThreadLocalScopeManager))) 5 | 6 | (def props {:printer MockTracer$Propagator/PRINTER 7 | :text-map MockTracer$Propagator/TEXT_MAP}) 8 | 9 | (defn make-tracer 10 | "generate a mock tracer with optional propagator, currently limited to 11 | :printer (MockTracer$Propagator/PRINTER) 12 | and :text-map (MockTracer$Propagator/TEXT_MAP)" 13 | ([] 14 | (MockTracer.)) 15 | ([propagator] 16 | (if-let [p (get props propagator)] 17 | (MockTracer. (ThreadLocalScopeManager.) p) 18 | (throw (Exception. "unknown or unsupported propagator"))))) 19 | -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defproject gonewest818/opentracing-clj "0.3.0-SNAPSHOT" 2 | :description "OpenTracing bindings for Clojure" 3 | :url "http://github.com/gonewest818/opentracing-clj" 4 | :license {:name "Eclipse Public License" 5 | :url "http://www.eclipse.org/legal/epl-v10.html"} 6 | :dependencies [[org.clojure/clojure "1.8.0"] 7 | [io.opentracing/opentracing-api "0.31.0"] 8 | [io.opentracing/opentracing-mock "0.31.0"] 9 | [io.opentracing/opentracing-noop "0.31.0"] 10 | [io.opentracing/opentracing-util "0.31.0"]] 11 | :deploy-repositories [["clojars" {:url "https://clojars.org/repo" 12 | :username :env/clojars_username 13 | :password :env/clojars_password}]] 14 | :profiles {:dev {:plugins [[lein-cloverage "1.0.10"]]}}) 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # opentracing-clj 2 | 3 | Convenience wrapper around the OpenTracing Java bindings for 4 | instrumentation of Clojure applications. 5 | 6 | Inspired in part by [guilespi/clj-zipkin](https://github.com/guilespi/clj-zipkin) 7 | 8 | [![Build Status](https://travis-ci.org/gonewest818/opentracing-clj.svg?branch=master)](https://travis-ci.org/gonewest818/opentracing-clj) 9 | [![codecov](https://codecov.io/gh/gonewest818/opentracing-clj/branch/master/graph/badge.svg)](https://codecov.io/gh/gonewest818/opentracing-clj) 10 | [![Dependencies Status](https://jarkeeper.com/gonewest818/opentracing-clj/status.svg)](https://jarkeeper.com/gonewest818/opentracing-clj) 11 | 12 | 13 | ## Usage 14 | 15 | FIXME 16 | 17 | ## License 18 | 19 | Copyright © 2017 Neil Okamoto 20 | 21 | Distributed under the Eclipse Public License either version 1.0 or (at 22 | your option) any later version. 23 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. This change log follows the conventions of [keepachangelog.com](http://keepachangelog.com/). 3 | 4 | ## [Unreleased] 5 | ### Changed 6 | - Add a new arity to `make-widget-async` to provide a different widget shape. 7 | 8 | ## [0.1.1] - 2017-02-14 9 | ### Changed 10 | - Documentation on how to make the widgets. 11 | 12 | ### Removed 13 | - `make-widget-sync` - we're all async, all the time. 14 | 15 | ### Fixed 16 | - Fixed widget maker to keep working when daylight savings switches over. 17 | 18 | ## 0.1.0 - 2017-02-14 19 | ### Added 20 | - Files from the new template. 21 | - Widget maker public API - `make-widget-sync`. 22 | 23 | [Unreleased]: https://github.com/your-name/opentracing-clj/compare/0.1.1...HEAD 24 | [0.1.1]: https://github.com/your-name/opentracing-clj/compare/0.1.0...0.1.1 25 | -------------------------------------------------------------------------------- /src/opentracing_clj/core.clj: -------------------------------------------------------------------------------- 1 | (ns opentracing-clj.core) 2 | 3 | 4 | (defn add-tags 5 | "Add contents of map 'm' as tags to a span context" 6 | [span-builder m] 7 | (if (map? m) 8 | (doseq [[k v] (seq m)] 9 | (.withTag span-builder k v))) 10 | span-builder) 11 | 12 | (defn scope 13 | "Convenience wrapper to create a span with optional tags and return the scope" 14 | ([tracer op-name] 15 | (scope tracer op-name nil true)) 16 | ([tracer op-name tags] 17 | (scope tracer op-name tags true)) 18 | ([tracer op-name tags finish-span] 19 | (-> tracer 20 | (.buildSpan op-name) 21 | (add-tags tags) 22 | (.startActive finish-span)))) 23 | 24 | (defn log-kv 25 | "Convenience wrapper to log a hashmap of structured data on the scope's span" 26 | ([s h] 27 | (-> s .span (.log (java.util.HashMap. h)))) 28 | ([s h ts] 29 | (-> s .span (.log ts (java.util.HashMap. h))))) 30 | 31 | (defn log-string 32 | "Convenience wrapper to log a event (string) on the scope's span" 33 | ([s e] 34 | (-> s .span (.log e))) 35 | ([s e ts] 36 | (-> s .span (.log ts e)))) 37 | 38 | (defn add-baggage-item 39 | "Convenience wrapper to add baggage to a scope's span, where baggage is 40 | a key and a value both strings." 41 | [s k v] 42 | (-> s .span (.setBaggageItem k v))) 43 | -------------------------------------------------------------------------------- /test/opentracing_clj/propagation_test.clj: -------------------------------------------------------------------------------- 1 | (ns opentracing-clj.propagation-test 2 | (:require [clojure.test :refer :all] 3 | [opentracing-clj.propagation :refer :all] 4 | [opentracing-clj.core :refer [scope]] 5 | [opentracing-clj.impl.mock :refer [make-tracer]])) 6 | 7 | (def tracer (atom (make-tracer :text-map))) 8 | 9 | (use-fixtures :each 10 | (fn [t] 11 | (.reset @tracer) 12 | (t))) 13 | 14 | (deftest inject-http 15 | (let [s (scope @tracer "foo" {"a" "1"}) 16 | c (-> s .span .context)] 17 | (is (= #{"traceid" "spanid"} 18 | (set (keys (inject @tracer c :http))))))) 19 | 20 | (deftest inject-text-map 21 | (let [s (scope @tracer "foo" {"a" "1"}) 22 | c (-> s .span .context)] 23 | (is (= #{"traceid" "spanid"} 24 | (set (keys (inject @tracer c :text))))))) 25 | 26 | (deftest extract-http 27 | (let [c (extract @tracer {"traceid" "1" "spanid" "2"} :http)] 28 | (is (= 1 (.traceId c))) 29 | (is (= 2 (.spanId c))))) 30 | 31 | (deftest extract-text-map 32 | (let [c (extract @tracer {"traceid" "1" "spanid" "2"} :text)] 33 | (is (= 1 (.traceId c))) 34 | (is (= 2 (.spanId c))))) 35 | 36 | (deftest ring 37 | (let [wrap (ring-wrapper (fn [h] {:status 200}) @tracer "foo") 38 | req {:headers {} 39 | :server-port 80 40 | :server-name "localhost" 41 | :uri "/foo" 42 | :scheme "http" 43 | :request-method :get}] 44 | (is (= (wrap req) {:status 200})))) 45 | -------------------------------------------------------------------------------- /src/opentracing_clj/propagation.clj: -------------------------------------------------------------------------------- 1 | (ns opentracing-clj.propagation 2 | (:require [opentracing-clj.core :as ot]) 3 | (:import (io.opentracing.propagation Format$Builtin 4 | TextMapExtractAdapter 5 | TextMapInjectAdapter))) 6 | 7 | 8 | (def formats {:http Format$Builtin/HTTP_HEADERS 9 | :text Format$Builtin/TEXT_MAP 10 | ; :binary Format$Builtin/BINARY ; unsupported for now 11 | }) 12 | 13 | (defn inject 14 | "Serialize a tracing context and inject into a hashmap for 15 | inter-process calls, where 'fmt' is one of :http or :text, 16 | corresponding to the HTTP_HEADERS and TEXT_MAP builtins in the 17 | opentracing-java implementation. Does not support a BINARY 18 | carrier. Returns a Clojure hash-map containing the injected data." 19 | [tracer ctx fmt] 20 | (let [hm (java.util.HashMap.) 21 | tm (TextMapInjectAdapter. hm)] 22 | (.inject tracer ctx (get formats fmt) tm) 23 | (into {} hm))) 24 | 25 | (defn extract 26 | "De-serialize a hashmap obtained from the header of an inter-process 27 | call, where the header format 'fmt' is one of :http or :text, corresponding 28 | to the HTTP_HEADERS and TEXT_MAP builtins in the opentracing-java 29 | implementation. Does not support the BINARY carrier. 30 | Returns the span context." 31 | [tracer header fmt] 32 | (let [hm (java.util.HashMap. header) 33 | tm (TextMapExtractAdapter. hm)] 34 | (.extract tracer (get formats fmt) tm))) 35 | 36 | (defn ring-wrapper 37 | "This ring middleware creates a span from the inbound request with 38 | the given name and optional tags. If the tracer is able to extract a 39 | valid context from the inbound request header, that context then 40 | becomes the parent of the newly created span, else there is no 41 | parent. The enclosing scope is assoc'ed into the request hash-map 42 | with key :opentracing-scope for downstream handlers to 43 | retrieve. This is in addition to the behavior of the ScopeManager 44 | associated with this tracer." 45 | ([handler tracer op-name] 46 | (ring-wrapper handler tracer op-name nil)) 47 | ([handler tracer op-name tags] 48 | (fn [request] 49 | ;;(log/debug (:headers request)) 50 | (if-let [ctx (extract tracer (:headers request) :http)] 51 | (with-open [s (-> tracer 52 | (.buildSpan op-name) 53 | (.asChildOf ctx) 54 | (ot/add-tags tags) 55 | (.startActive))] 56 | (handler (assoc request :opentracing-scope s))) 57 | (with-open [s (ot/scope tracer op-name tags)] 58 | (handler (assoc request :opentracing-scope s))))))) 59 | -------------------------------------------------------------------------------- /test/opentracing_clj/core_test.clj: -------------------------------------------------------------------------------- 1 | (ns opentracing-clj.core-test 2 | (:require [clojure.test :refer :all] 3 | [opentracing-clj.core :refer :all] 4 | [opentracing-clj.impl.mock :refer [make-tracer]])) 5 | 6 | 7 | (def tracer (atom (make-tracer :text-map))) 8 | 9 | (use-fixtures :each 10 | (fn [t] 11 | (.reset @tracer) 12 | (t))) 13 | 14 | (defn mock->hash-map 15 | "convert mock span into a hashmap for simpler comparisons" 16 | [mock] 17 | {:name (.operationName mock) 18 | :parent-id (.parentId mock) 19 | :start (.startMicros mock) 20 | :finish (.finishMicros mock) 21 | :tags (into {} (.tags mock)) 22 | :log-entries (map #(.fields %) (.logEntries mock)) 23 | :baggage (into {} (-> mock .context .baggageItems))}) 24 | 25 | (deftest interop-create-with-no-tags 26 | (let [_ (with-open [s (-> @tracer 27 | (.buildSpan "foo") 28 | (add-tags nil) 29 | (.startActive true))]) 30 | spans (map mock->hash-map (.finishedSpans @tracer))] 31 | (is (= 1 (count spans))) 32 | (is (= {} (:tags (first spans)))))) 33 | 34 | (deftest interop-create-with-one-tag 35 | (let [_ (with-open [s (-> @tracer 36 | (.buildSpan "foo") 37 | (add-tags {"a" "1"}) 38 | (.startActive true))]) 39 | spans (map mock->hash-map (.finishedSpans @tracer))] 40 | (is (= 1 (count spans))) 41 | (is (= {"a" "1"} (:tags (first spans)))))) 42 | 43 | (deftest interop-create-with-three-tags 44 | (let [_ (with-open [s (-> @tracer 45 | (.buildSpan "foo") 46 | (add-tags {"a" "1" "b" "2" "c" "3"}) 47 | (.startActive true))]) 48 | spans (map mock->hash-map (.finishedSpans @tracer))] 49 | (is (= 1 (count spans))) 50 | (is (= 3 (count (:tags (first spans))))))) 51 | 52 | (deftest scope-create 53 | (let [sc (scope @tracer "foo" nil) 54 | sp (.span sc)] 55 | (is (= io.opentracing.mock.MockSpan (type sp))) 56 | (is (= "foo" (.operationName sp))))) 57 | 58 | (deftest scope-create-with-one-tag 59 | (let [sc (scope @tracer "foo" {"a" "1"}) 60 | sp (.span sc)] 61 | (is (= io.opentracing.mock.MockSpan (type sp))) 62 | (is (= {"a" "1"} (.tags sp))) 63 | (is (= "foo" (.operationName sp))))) 64 | 65 | (deftest scope-create-finishspan 66 | (let [sc (scope @tracer "foo" nil false) 67 | sp (.span sc)] 68 | (is (= io.opentracing.mock.MockSpan (type sp))) 69 | (is (= "foo" (.operationName sp))))) 70 | 71 | (deftest scope-create-finishspan-with-one-tag 72 | (let [sc (scope @tracer "foo" {"a" "1"} false) 73 | sp (.span sc)] 74 | (is (= io.opentracing.mock.MockSpan (type sp))) 75 | (is (= {"a" "1"} (.tags sp))) 76 | (is (= "foo" (.operationName sp))))) 77 | 78 | (deftest log-event-to-scope 79 | (let [_ (with-open [s (scope @tracer "foo")] 80 | (log-string s "and then this happened")) 81 | spans (map mock->hash-map (.finishedSpans @tracer))] 82 | (is (= 1 (count spans))) 83 | (is (= 1 (count (:log-entries (first spans))))) 84 | (is (= {"event" "and then this happened"} 85 | (-> spans first :log-entries first))))) 86 | 87 | (deftest log-event-with-ts-to-scope 88 | (let [_ (with-open [s (scope @tracer "foo")] 89 | (log-string s "and then this happened" 100)) 90 | spans (map mock->hash-map (.finishedSpans @tracer))] 91 | (is (= 1 (count spans))) 92 | (is (= 1 (count (:log-entries (first spans))))) 93 | (is (= {"event" "and then this happened"} 94 | (-> spans first :log-entries first))))) 95 | 96 | (deftest log-kv-to-scope 97 | (let [_ (with-open [s (scope @tracer "bar")] 98 | (log-kv s {"foo" 1 "bar" 2 "baz" false})) 99 | spans (map mock->hash-map (.finishedSpans @tracer))] 100 | (is (= 1 (count spans))) 101 | (is (= 1 (count (:log-entries (first spans))))) 102 | (is (= {"foo" 1 "bar" 2 "baz" false} 103 | (-> spans first :log-entries first))))) 104 | 105 | (deftest log-kvs-to-scope 106 | (let [_ (with-open [s (scope @tracer "bar")] 107 | (log-kv s {"foo" 1 "bar" 2}) 108 | (log-kv s {"baz" false})) 109 | spans (map mock->hash-map (.finishedSpans @tracer))] 110 | (is (= 1 (count spans))) 111 | (is (= 2 (count (:log-entries (first spans))))) 112 | (is (= {"foo" 1 "bar" 2} 113 | (-> spans first :log-entries first))) 114 | (is (= {"baz" false} 115 | (-> spans first :log-entries second))))) 116 | 117 | (deftest log-kvs-with-ts-to-scope 118 | (let [_ (with-open [s (scope @tracer "bar")] 119 | (log-kv s {"foo" 1 "bar" 2} 200) 120 | (log-kv s {"baz" false} 300)) 121 | spans (map mock->hash-map (.finishedSpans @tracer))] 122 | (is (= 1 (count spans))) 123 | (is (= 2 (count (:log-entries (first spans))))) 124 | (is (= {"foo" 1 "bar" 2} 125 | (-> spans first :log-entries first))) 126 | (is (= {"baz" false} 127 | (-> spans first :log-entries second))))) 128 | 129 | (deftest baggage-item 130 | (let [_ (with-open [s (scope @tracer "bar")] 131 | (add-baggage-item s "bag" "value")) 132 | spans (map mock->hash-map (.finishedSpans @tracer))] 133 | (is (= 1 (count spans))) 134 | (is (= {"bag" "value"} (-> spans first :baggage))))) 135 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC 2 | LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM 3 | CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 4 | 5 | 1. DEFINITIONS 6 | 7 | "Contribution" means: 8 | 9 | a) in the case of the initial Contributor, the initial code and 10 | documentation distributed under this Agreement, and 11 | 12 | b) in the case of each subsequent Contributor: 13 | 14 | i) changes to the Program, and 15 | 16 | ii) additions to the Program; 17 | 18 | where such changes and/or additions to the Program originate from and are 19 | distributed by that particular Contributor. A Contribution 'originates' from 20 | a Contributor if it was added to the Program by such Contributor itself or 21 | anyone acting on such Contributor's behalf. Contributions do not include 22 | additions to the Program which: (i) are separate modules of software 23 | distributed in conjunction with the Program under their own license 24 | agreement, and (ii) are not derivative works of the Program. 25 | 26 | "Contributor" means any person or entity that distributes the Program. 27 | 28 | "Licensed Patents" mean patent claims licensable by a Contributor which are 29 | necessarily infringed by the use or sale of its Contribution alone or when 30 | combined with the Program. 31 | 32 | "Program" means the Contributions distributed in accordance with this 33 | Agreement. 34 | 35 | "Recipient" means anyone who receives the Program under this Agreement, 36 | including all Contributors. 37 | 38 | 2. GRANT OF RIGHTS 39 | 40 | a) Subject to the terms of this Agreement, each Contributor hereby grants 41 | Recipient a non-exclusive, worldwide, royalty-free copyright license to 42 | reproduce, prepare derivative works of, publicly display, publicly perform, 43 | distribute and sublicense the Contribution of such Contributor, if any, and 44 | such derivative works, in source code and object code form. 45 | 46 | b) Subject to the terms of this Agreement, each Contributor hereby grants 47 | Recipient a non-exclusive, worldwide, royalty-free patent license under 48 | Licensed Patents to make, use, sell, offer to sell, import and otherwise 49 | transfer the Contribution of such Contributor, if any, in source code and 50 | object code form. This patent license shall apply to the combination of the 51 | Contribution and the Program if, at the time the Contribution is added by the 52 | Contributor, such addition of the Contribution causes such combination to be 53 | covered by the Licensed Patents. The patent license shall not apply to any 54 | other combinations which include the Contribution. No hardware per se is 55 | licensed hereunder. 56 | 57 | c) Recipient understands that although each Contributor grants the licenses 58 | to its Contributions set forth herein, no assurances are provided by any 59 | Contributor that the Program does not infringe the patent or other 60 | intellectual property rights of any other entity. Each Contributor disclaims 61 | any liability to Recipient for claims brought by any other entity based on 62 | infringement of intellectual property rights or otherwise. As a condition to 63 | exercising the rights and licenses granted hereunder, each Recipient hereby 64 | assumes sole responsibility to secure any other intellectual property rights 65 | needed, if any. For example, if a third party patent license is required to 66 | allow Recipient to distribute the Program, it is Recipient's responsibility 67 | to acquire that license before distributing the Program. 68 | 69 | d) Each Contributor represents that to its knowledge it has sufficient 70 | copyright rights in its Contribution, if any, to grant the copyright license 71 | set forth in this Agreement. 72 | 73 | 3. REQUIREMENTS 74 | 75 | A Contributor may choose to distribute the Program in object code form under 76 | its own license agreement, provided that: 77 | 78 | a) it complies with the terms and conditions of this Agreement; and 79 | 80 | b) its license agreement: 81 | 82 | i) effectively disclaims on behalf of all Contributors all warranties and 83 | conditions, express and implied, including warranties or conditions of title 84 | and non-infringement, and implied warranties or conditions of merchantability 85 | and fitness for a particular purpose; 86 | 87 | ii) effectively excludes on behalf of all Contributors all liability for 88 | damages, including direct, indirect, special, incidental and consequential 89 | damages, such as lost profits; 90 | 91 | iii) states that any provisions which differ from this Agreement are offered 92 | by that Contributor alone and not by any other party; and 93 | 94 | iv) states that source code for the Program is available from such 95 | Contributor, and informs licensees how to obtain it in a reasonable manner on 96 | or through a medium customarily used for software exchange. 97 | 98 | When the Program is made available in source code form: 99 | 100 | a) it must be made available under this Agreement; and 101 | 102 | b) a copy of this Agreement must be included with each copy of the Program. 103 | 104 | Contributors may not remove or alter any copyright notices contained within 105 | the Program. 106 | 107 | Each Contributor must identify itself as the originator of its Contribution, 108 | if any, in a manner that reasonably allows subsequent Recipients to identify 109 | the originator of the Contribution. 110 | 111 | 4. COMMERCIAL DISTRIBUTION 112 | 113 | Commercial distributors of software may accept certain responsibilities with 114 | respect to end users, business partners and the like. While this license is 115 | intended to facilitate the commercial use of the Program, the Contributor who 116 | includes the Program in a commercial product offering should do so in a 117 | manner which does not create potential liability for other Contributors. 118 | Therefore, if a Contributor includes the Program in a commercial product 119 | offering, such Contributor ("Commercial Contributor") hereby agrees to defend 120 | and indemnify every other Contributor ("Indemnified Contributor") against any 121 | losses, damages and costs (collectively "Losses") arising from claims, 122 | lawsuits and other legal actions brought by a third party against the 123 | Indemnified Contributor to the extent caused by the acts or omissions of such 124 | Commercial Contributor in connection with its distribution of the Program in 125 | a commercial product offering. The obligations in this section do not apply 126 | to any claims or Losses relating to any actual or alleged intellectual 127 | property infringement. In order to qualify, an Indemnified Contributor must: 128 | a) promptly notify the Commercial Contributor in writing of such claim, and 129 | b) allow the Commercial Contributor to control, and cooperate with the 130 | Commercial Contributor in, the defense and any related settlement 131 | negotiations. The Indemnified Contributor may participate in any such claim 132 | at its own expense. 133 | 134 | For example, a Contributor might include the Program in a commercial product 135 | offering, Product X. That Contributor is then a Commercial Contributor. If 136 | that Commercial Contributor then makes performance claims, or offers 137 | warranties related to Product X, those performance claims and warranties are 138 | such Commercial Contributor's responsibility alone. Under this section, the 139 | Commercial Contributor would have to defend claims against the other 140 | Contributors related to those performance claims and warranties, and if a 141 | court requires any other Contributor to pay any damages as a result, the 142 | Commercial Contributor must pay those damages. 143 | 144 | 5. NO WARRANTY 145 | 146 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON 147 | AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER 148 | EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR 149 | CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A 150 | PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the 151 | appropriateness of using and distributing the Program and assumes all risks 152 | associated with its exercise of rights under this Agreement , including but 153 | not limited to the risks and costs of program errors, compliance with 154 | applicable laws, damage to or loss of data, programs or equipment, and 155 | unavailability or interruption of operations. 156 | 157 | 6. DISCLAIMER OF LIABILITY 158 | 159 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY 160 | CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, 161 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION 162 | LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 163 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 164 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE 165 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY 166 | OF SUCH DAMAGES. 167 | 168 | 7. GENERAL 169 | 170 | If any provision of this Agreement is invalid or unenforceable under 171 | applicable law, it shall not affect the validity or enforceability of the 172 | remainder of the terms of this Agreement, and without further action by the 173 | parties hereto, such provision shall be reformed to the minimum extent 174 | necessary to make such provision valid and enforceable. 175 | 176 | If Recipient institutes patent litigation against any entity (including a 177 | cross-claim or counterclaim in a lawsuit) alleging that the Program itself 178 | (excluding combinations of the Program with other software or hardware) 179 | infringes such Recipient's patent(s), then such Recipient's rights granted 180 | under Section 2(b) shall terminate as of the date such litigation is filed. 181 | 182 | All Recipient's rights under this Agreement shall terminate if it fails to 183 | comply with any of the material terms or conditions of this Agreement and 184 | does not cure such failure in a reasonable period of time after becoming 185 | aware of such noncompliance. If all Recipient's rights under this Agreement 186 | terminate, Recipient agrees to cease use and distribution of the Program as 187 | soon as reasonably practicable. However, Recipient's obligations under this 188 | Agreement and any licenses granted by Recipient relating to the Program shall 189 | continue and survive. 190 | 191 | Everyone is permitted to copy and distribute copies of this Agreement, but in 192 | order to avoid inconsistency the Agreement is copyrighted and may only be 193 | modified in the following manner. The Agreement Steward reserves the right to 194 | publish new versions (including revisions) of this Agreement from time to 195 | time. No one other than the Agreement Steward has the right to modify this 196 | Agreement. The Eclipse Foundation is the initial Agreement Steward. The 197 | Eclipse Foundation may assign the responsibility to serve as the Agreement 198 | Steward to a suitable separate entity. Each new version of the Agreement will 199 | be given a distinguishing version number. The Program (including 200 | Contributions) may always be distributed subject to the version of the 201 | Agreement under which it was received. In addition, after a new version of 202 | the Agreement is published, Contributor may elect to distribute the Program 203 | (including its Contributions) under the new version. Except as expressly 204 | stated in Sections 2(a) and 2(b) above, Recipient receives no rights or 205 | licenses to the intellectual property of any Contributor under this 206 | Agreement, whether expressly, by implication, estoppel or otherwise. All 207 | rights in the Program not expressly granted under this Agreement are 208 | reserved. 209 | 210 | This Agreement is governed by the laws of the State of New York and the 211 | intellectual property laws of the United States of America. No party to this 212 | Agreement will bring a legal action under this Agreement more than one year 213 | after the cause of action arose. Each party waives its rights to a jury trial 214 | in any resulting litigation. 215 | --------------------------------------------------------------------------------