/*
* #%L
* Service Locator Monitor
* %%
* Copyright (C) 2011 - 2014 Talend Inc.
* %%
* 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.
* #L%
*/
package org.talend.esb.servicelocator.monitor;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.xml.namespace.QName;
import org.apache.log4j.MDC;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;
import org.talend.esb.servicelocator.client.SLEndpoint;
import org.talend.esb.servicelocator.client.SLProperties;
import org.talend.esb.servicelocator.client.ServiceLocator;
import org.talend.esb.servicelocator.client.ServiceLocatorException;
public class LocatorMonitor {
public static final String MONITORING = "Monitoring";
public static final String EVENT_CATEGORY = "eventCategory";
public static final String ADDRESS = "address";
public static final String ACTIVE = "active";
public static final String LAST_TIME_STARTED = "lastTimeStarted";
public static final String LAST_TIME_STOPPED = "lastTimeStopped";
public static final String MDC_PROPERTY_PREFIX = "sl.property.";
public static final String COUNT = "count";
public static final String PROTOCOL = "protocol";
public static final String SERVICE_QNAME = "service.qname";
public static final String TRANSPORT = "transport.type";
private static final Logger LOG = LoggerFactory.getLogger(LocatorMonitor.class);
private static final Marker SERVICES = MarkerFactory.getMarker("SERVICES");
private static final Marker SERVICE_INFO = MarkerFactory.getMarker("SERVICE_INFO");
private static final Marker ENDPOINTS = MarkerFactory.getMarker("ENDPOINTS");
private static final Marker ENDPOINT_INFO = MarkerFactory.getMarker("ENDPOINT_INFO");
/**
* Number in seconds to request SL for active/inactive services. Default is 10 seconds.
*/
private int scanIntervall = 60;
private ServiceLocator sl;
private int startDelay = 1;
public LocatorMonitor(ServiceLocator sl, int scanIntervall) {
this.sl = sl;
this.scanIntervall = scanIntervall;
startScanning();
}
private String[] addPropertiesToMDC(SLProperties properties) {
Set<String> mdcKeys = new HashSet<String>();
Collection<String> names = properties.getPropertyNames();
if (!names.isEmpty()) {
} else {
for (String name : names) {
String mdcKey = MDC_PROPERTY_PREFIX + name;
MDC.put(mdcKey, properties.getValues(name).toString());
mdcKeys.add(mdcKey);
}
}
return mdcKeys.toArray(new String[] {});
}
private void cleanMDC(String... mdcKeys) {
for (String key : mdcKeys) {
MDC.remove(key);
}
}
private String formatTimeStamp(long timestamp) {
String timeStampStr;
if (timestamp >= 0) {
Calendar timeStarted = Calendar.getInstance();
DateFormat df = DateFormat.getDateTimeInstance();
timeStarted.setTimeInMillis(timestamp);
timeStampStr = df.format(timeStarted.getTime());
} else {
timeStampStr = "";
}
return timeStampStr;
}
private void startScanning() {
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
MDC.put(EVENT_CATEGORY, MONITORING);
try {
if (sl != null) {
List<QName> services = sl.getServices();
int activeService = 0;
int totalActiveEndpoints = 0;
int totalOfflineEndpoints = 0;
for (QName service : services) {
List<SLEndpoint> endpoints = sl.getEndpoints(service);
int activeEndpoints = 0;
MDC.put(SERVICE_QNAME, service);
for (SLEndpoint endpoint : endpoints) {
boolean alive = endpoint.isLive();
MDC.put(ACTIVE, alive);
String address = endpoint.getAddress();
MDC.put(ADDRESS, address);
String protocol = endpoint.getBinding().getValue();
MDC.put(PROTOCOL, protocol);
String transport = endpoint.getTransport().getValue();
MDC.put(TRANSPORT, transport);
long lastTimeStarted = endpoint.getLastTimeStarted();
MDC.put(LAST_TIME_STARTED, formatTimeStamp(lastTimeStarted));
long lastTimeStopped = endpoint.getLastTimeStopped();
MDC.put(LAST_TIME_STOPPED, formatTimeStamp(lastTimeStopped));
String[] mdcPropertyKeys = addPropertiesToMDC(endpoint.getProperties());
if (alive) {
activeEndpoints++;
totalActiveEndpoints++;
LOG.info(ENDPOINT_INFO, "Endpoint for Service {} with Address {} is alive since {}", service, address,
formatTimeStamp(lastTimeStarted));
} else {
LOG.warn(ENDPOINT_INFO, "Endpoint for Service {} with Address {} is down since {}", service, address,
formatTimeStamp(lastTimeStopped));
totalOfflineEndpoints++;
}
cleanMDC(mdcPropertyKeys);
cleanMDC(ACTIVE, ADDRESS, PROTOCOL, TRANSPORT, LAST_TIME_STARTED, LAST_TIME_STOPPED);
}
MDC.remove(ACTIVE);
MDC.put(COUNT, endpoints.size());
LOG.info(SERVICE_INFO, "{} endpoints are registered for service {}", endpoints.size(), service);
MDC.put(ACTIVE, true);
MDC.put(COUNT, activeEndpoints);
LOG.info(SERVICE_INFO, "{} endpoints are active for service {}", activeEndpoints, service);
MDC.put(ACTIVE, false);
int offlineEndpoints = endpoints.size() - activeEndpoints;
MDC.put(COUNT, offlineEndpoints);
if (offlineEndpoints > 0) {
LOG.warn(SERVICE_INFO, "{} endpoints are offline for service {}", offlineEndpoints, service);
} else {
LOG.info(SERVICE_INFO, "{} endpoints are offline for service {}", offlineEndpoints, service);
}
if (activeEndpoints > 0) {
activeService++;
}
cleanMDC(COUNT, ACTIVE, SERVICE_QNAME);
}
// Absolute Numbers for Services
MDC.put(COUNT, services.size());
MDC.remove(ACTIVE);
LOG.info(SERVICES, "{} services are registered at the ServiceLocator", services.size());
MDC.put(COUNT, activeService);
MDC.put(ACTIVE, true);
LOG.info(SERVICES, "{} services are available and currently registered at the ServiceLocator", activeService);
MDC.put(COUNT, services.size() - activeService);
MDC.put(ACTIVE, false);
LOG.info(SERVICES, "{} services are currently registered at the ServiceLocator but are not available", services.size()
- activeService);
// Absolute Numbers for Endpoints
MDC.put(COUNT, totalActiveEndpoints + totalOfflineEndpoints);
MDC.remove(ACTIVE);
LOG.info(ENDPOINTS, "{} endpoints are registered at the ServiceLocator", totalActiveEndpoints + totalOfflineEndpoints);
MDC.put(COUNT, totalActiveEndpoints);
MDC.put(ACTIVE, true);
LOG.info(ENDPOINTS, "{} endpoints are available and currently registered at the ServiceLocator", totalActiveEndpoints);
MDC.put(COUNT, totalOfflineEndpoints);
MDC.put(ACTIVE, false);
LOG.info(ENDPOINTS, "{} endpoints are currently registered at the ServiceLocator but are not available",
totalOfflineEndpoints);
cleanMDC(COUNT, ACTIVE);
}
} catch (ServiceLocatorException e) {
LOG.warn("Error during SL monitoring", e);
} catch (InterruptedException e) {
}
MDC.remove(EVENT_CATEGORY);
}
}, startDelay, scanIntervall, TimeUnit.SECONDS);
}
}