Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add collector support activemq #2466

Closed
wants to merge 16 commits into from
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,12 @@
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>io.zipkin.zipkin2</groupId>
<artifactId>zipkin-collector-activemq</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>io.zipkin.zipkin2</groupId>
<artifactId>zipkin-collector-scribe</artifactId>
Expand Down
43 changes: 43 additions & 0 deletions zipkin-autoconfigure/collector-activemq/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--

Copyright 2015-2019 The OpenZipkin Authors

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License
is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
or implied. See the License for the specific language governing permissions and limitations under
the License.

-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>zipkin-autoconfigure</artifactId>
<groupId>io.zipkin.java</groupId>
<version>2.12.7-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>zipkin-autoconfigure-collector-activemq</artifactId>

<name>Auto Configuration: ActiveMQ Collector</name>

<properties>
<main.basedir>${project.basedir}/../..</main.basedir>
</properties>

<dependencies>
<dependency>
<groupId>io.zipkin.zipkin2</groupId>
<artifactId>zipkin-collector-activemq</artifactId>
</dependency>
</dependencies>


</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright 2015-2019 The OpenZipkin Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package zipkin2.autoconfigure.collector.activemq;

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.*;
import org.springframework.core.type.AnnotatedTypeMetadata;
import zipkin2.collector.CollectorMetrics;
import zipkin2.collector.CollectorSampler;
import zipkin2.collector.activemq.ActiveMQCollector;
import zipkin2.storage.StorageComponent;

import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;

/** Auto-configuration for {@link ActiveMQCollector}. */
@Configuration
@Conditional(ZipkinActiveMQCollectorAutoConfiguration.ActiveMQAddressesOrUriSet.class)
@EnableConfigurationProperties(ZipkinActiveMQCollectorProperties.class)
class ZipkinActiveMQCollectorAutoConfiguration {

@Bean(initMethod = "start")
ActiveMQCollector activemq(
ZipkinActiveMQCollectorProperties properties,
CollectorSampler sampler,
CollectorMetrics metrics,
StorageComponent storage)
throws NoSuchAlgorithmException, KeyManagementException, URISyntaxException {
return properties.toBuilder().sampler(sampler).metrics(metrics).storage(storage).build();
}

/**
* This condition passes when {@link ZipkinActiveMQCollectorProperties#getAddresses()} is set to a non-empty value.
*
* <p>This is here because the yaml defaults this property to empty like this, and Spring Boot
* doesn't have an option to treat empty properties as unset.
*
* <pre>{@code
* addresses: ${RABBIT_ADDRESSES:}
* uri: ${RABBIT_URI:}
* }</pre>
*/
static final class ActiveMQAddressesOrUriSet implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata a) {
return !isEmpty(context.getEnvironment().getProperty("zipkin.collector.activemq.addresses"));
}

private static boolean isEmpty(String s) {
return s == null || s.isEmpty();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Copyright 2015-2019 The OpenZipkin Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package zipkin2.autoconfigure.collector.activemq;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import zipkin2.collector.activemq.ActiveMQCollector;

import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;

/** Properties for configuring and building a {@link zipkin2.collector.activemq.ActiveMQCollector}. */
@ConfigurationProperties("zipkin.collector.activemq")
class ZipkinActiveMQCollectorProperties {

/** RabbitMQ server addresses in the form of a (comma-separated) list of host:port pairs */
private String addresses;

/** TCP connection timeout in milliseconds */
private Integer connectionTimeout;
/** RabbitMQ user password */
private String password;
/** RabbitMQ queue from which to collect the Zipkin spans */
private String queue;
/** RabbitMQ username */
private String username;


public String getAddresses() {
return addresses;
}

public void setAddresses(String addresses) {
this.addresses = addresses;
}


public Integer getConnectionTimeout() {
return connectionTimeout;
}

public void setConnectionTimeout(Integer connectionTimeout) {
this.connectionTimeout = connectionTimeout;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public String getQueue() {
return queue;
}

public void setQueue(String queue) {
this.queue = queue;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}


public ActiveMQCollector.Builder toBuilder()
throws KeyManagementException, NoSuchAlgorithmException, URISyntaxException {
final ActiveMQCollector.Builder result = ActiveMQCollector.builder();
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
if (connectionTimeout != null) {
connectionFactory.setConnectResponseTimeout(connectionTimeout);
}
if (queue != null) {
result.queue(queue);
}
if (addresses != null) {
result.addresses(addresses);
}
if (password != null) {
connectionFactory.setPassword(password);
}
if (username != null) {
connectionFactory.setUserName(username);
}

result.connectionFactory(connectionFactory);
return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
zipkin2.autoconfigure.collector.activemq.ZipkinActiveMQCollectorAutoConfiguration
1 change: 1 addition & 0 deletions zipkin-autoconfigure/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
<module>storage-mysql</module>
<module>storage-cassandra</module>
<module>metrics-prometheus</module>
<module>collector-activemq</module>
</modules>

<dependencies>
Expand Down
56 changes: 56 additions & 0 deletions zipkin-collector/activemq/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# collector-activemq

## ActiveMQCollector
This collector consumes a ActiveMQ queue for messages that contain a list of spans.
Its only dependencies besides Zipkin core are the `slf4j-api` and the [ActiveMQ Java Client](https://github.com/apache/activemq).

### Configuration

The following configuration can be set for the ActiveMQ Collector.

Property | Environment Variable | Description
--- | --- | ---
`zipkin.collector.activemq.connection-timeout` | `ACTIVEMQ_CONNECTION_TIMEOUT` | Milliseconds to wait establishing a connection. Defaults to `60000` (1 minute)
`zipkin.collector.activemq.queue` | `ACTIVEMQ_QUEUE` | Queue from which to collect span messages. Defaults to `zipkin`

If the URI is set, the following properties will be ignored.

Property | Environment Variable | Description
--- | --- | ---
`zipkin.collector.activemq.addresses` | `ACTIVEMQ_ADDRESSES` | Comma-separated list of ActiveMQ addresses, ex. `tcp://localhost:61616,tcp://localhost2:61616`
`zipkin.collector.activemq.password` | `ACTIVEMQ_PASSWORD`| Password to use when connecting to ActiveMQ. Defaults to `system`
`zipkin.collector.activemq.username` | `ACTIVEMQ_USER` | Username to use when connecting to ActiveMQ. Defaults to `manager`

### Caveats

The configured queue will be idempotently declared as a durable queue.


Consumption is done with `autoAck` on, so messages that fail to process successfully are not retried.

## Encoding spans into ActiveMQ messages
The message's body should be the bytes of an encoded list of spans.

### JSON
A list of Spans in JSON. The first character must be '[' (decimal 91).

`SpanBytesEncoder.JSON_V2.encodeList(spans)` performs the correct JSON encoding.

## Local testing

The following assumes you are running an instance of ActiveMQ locally on the default port (61616).
You can download and install ActiveMQ following [instructions available here](http://activemq.apache.org/download.html).
With the [ActiveMQ Management Admin](http://localhost:8161/admin/) you can easily publish
one-off spans to ActiveMQ to be collected by this collector.

1. Start ActiveMQ server
2. Start Zipkin server
```bash
$ ACTIVEMQ_ADDRESSES=tcp://localhost:61616 java -jar zipkin.jar
```
3. Save an array of spans to a file like `sample-spans.json`
```json
[{"traceId":"9032b04972e475c5","id":"9032b04972e475c5","kind":"SERVER","name":"get","timestamp":1505990621526000,"duration":612898,"localEndpoint":{"serviceName":"brave-webmvc-example","ipv4":"192.168.1.113"},"remoteEndpoint":{"serviceName":"","ipv4":"127.0.0.1","port":60149},"tags":{"error":"500 Internal Server Error","http.path":"/a"}}]
```
4. Publish them using the admin

71 changes: 71 additions & 0 deletions zipkin-collector/activemq/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--

Copyright 2015-2019 The OpenZipkin Authors

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License
is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
or implied. See the License for the specific language governing permissions and limitations under
the License.

-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>zipkin-collector-parent</artifactId>
<groupId>io.zipkin.zipkin2</groupId>
<version>2.12.7-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>zipkin-collector-activemq</artifactId>

<name>Collector: ActiveMQ</name>
<description>Zipkin span collector for ActiveMQ transport</description>

<properties>
<main.basedir>${project.basedir}/../..</main.basedir>

<activemq-client.version>5.15.0</activemq-client.version>
</properties>

<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>zipkin-collector</artifactId>
</dependency>

<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-client</artifactId>
<version>${activemq-client.version}</version>
</dependency>

<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>zipkin</artifactId>
<type>test-jar</type>
<scope>test</scope>
</dependency>
</dependencies>

</project>
Loading