Repository: wso2/msf4j
Branch: master
Commit: 76897238aaef
Files: 937
Total size: 3.4 MB
Directory structure:
gitextract_cwpary60/
├── .gitignore
├── LICENSE
├── README.md
├── analytics/
│ ├── README.md
│ ├── das-setup/
│ │ ├── capps/
│ │ │ ├── msf4j_http_monitoring_capp.car
│ │ │ └── org_wso2_carbon_metrics-1.0.0.car
│ │ └── setup.sh
│ ├── msf4j-analytics/
│ │ ├── pom.xml
│ │ └── src/
│ │ ├── main/
│ │ │ ├── java/
│ │ │ │ └── org/
│ │ │ │ └── wso2/
│ │ │ │ └── msf4j/
│ │ │ │ └── analytics/
│ │ │ │ ├── AnalyticUtils.java
│ │ │ │ ├── httpmonitoring/
│ │ │ │ │ ├── HTTPMonitored.java
│ │ │ │ │ ├── HTTPMonitoringDataPublisher.java
│ │ │ │ │ ├── HTTPMonitoringEvent.java
│ │ │ │ │ ├── HTTPMonitoringInterceptor.java
│ │ │ │ │ └── config/
│ │ │ │ │ ├── HTTPMonitoringConfigBuilder.java
│ │ │ │ │ └── model/
│ │ │ │ │ ├── DasConfig.java
│ │ │ │ │ └── HTTPMonitoringConfig.java
│ │ │ │ ├── internal/
│ │ │ │ │ ├── AnalyticsSC.java
│ │ │ │ │ ├── DataHolder.java
│ │ │ │ │ └── InterceptorCapabilityProvider.java
│ │ │ │ ├── metrics/
│ │ │ │ │ ├── Metrics.java
│ │ │ │ │ ├── MetricsComponent.java
│ │ │ │ │ └── MetricsInterceptor.java
│ │ │ │ └── tracing/
│ │ │ │ └── MSF4JTracingInterceptor.java
│ │ │ └── resources/
│ │ │ └── http-monitoring.yml
│ │ └── test/
│ │ ├── java/
│ │ │ └── org/
│ │ │ └── wso2/
│ │ │ └── msf4j/
│ │ │ └── analytics/
│ │ │ └── HTTPMonitoringConfigTest.java
│ │ └── resources/
│ │ └── deployment.yaml
│ ├── msf4j-analytics-common/
│ │ ├── pom.xml
│ │ └── src/
│ │ └── main/
│ │ └── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── analytics/
│ │ └── common/
│ │ └── tracing/
│ │ ├── MSF4JClientTracingFilter.java
│ │ ├── TraceEvent.java
│ │ ├── TracingConstants.java
│ │ ├── TracingEventTracker.java
│ │ └── TracingUtil.java
│ ├── msf4j_http_monitoring_capp_source/
│ │ ├── build.xml
│ │ └── msf4j_http_monitoring_capp/
│ │ ├── artifacts.xml
│ │ ├── http_event_receiver_1.0.0/
│ │ │ ├── artifact.xml
│ │ │ └── http_event_receiver.xml
│ │ ├── http_event_store_1.0.0/
│ │ │ ├── artifact.xml
│ │ │ └── org_wso2_msf4j_analytics_httpmonitoring.xml
│ │ ├── http_event_stream_1.0.0/
│ │ │ ├── artifact.xml
│ │ │ └── org.wso2.msf4j.analytics.httpmonitoring_1.0.0.json
│ │ └── spark_script_1.0.0/
│ │ ├── artifact.xml
│ │ └── http_event_script.xml
│ ├── wso2das-tracing-capp/
│ │ ├── capp-content/
│ │ │ ├── Dashboard_1.0.0/
│ │ │ │ ├── artifact.xml
│ │ │ │ └── msf4j-message-tracing.json
│ │ │ ├── Eventreceiver_1.0.0/
│ │ │ │ ├── artifact.xml
│ │ │ │ └── msf4jtracereceiver.xml
│ │ │ ├── Eventstore_1.0.0/
│ │ │ │ ├── artifact.xml
│ │ │ │ └── msf4j-tracing.xml
│ │ │ ├── Eventstream_1.0.0/
│ │ │ │ ├── artifact.xml
│ │ │ │ └── msf4j-tracing_1.0.0.json
│ │ │ ├── GadgetMSF4JTracing_1.0.0/
│ │ │ │ ├── artifact.xml
│ │ │ │ └── msf4j-tracing/
│ │ │ │ ├── css/
│ │ │ │ │ └── main.css
│ │ │ │ ├── gadget.json
│ │ │ │ ├── index.xml
│ │ │ │ └── js/
│ │ │ │ ├── libs/
│ │ │ │ │ └── jquery.base64.js
│ │ │ │ └── main.js
│ │ │ └── artifacts.xml
│ │ ├── pom.xml
│ │ └── zip.xml
│ └── zipkin-tracing/
│ ├── pom.xml
│ └── src/
│ ├── main/
│ │ └── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── analytics/
│ │ └── zipkintracing/
│ │ ├── MSF4JZipkinTracingInterceptor.java
│ │ ├── TraceableHttpClientRequest.java
│ │ ├── TraceableHttpClientResponse.java
│ │ ├── TraceableHttpServerRequest.java
│ │ └── TraceableHttpServerResponse.java
│ └── test/
│ ├── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── analytics/
│ │ └── zipkintracing/
│ │ ├── TraceableHttpClientRequestTest.java
│ │ ├── TraceableHttpClientResponseTest.java
│ │ ├── TraceableHttpServerRequestTest.java
│ │ └── TraceableHttpServerResponseTest.java
│ └── resources/
│ └── testng.xml
├── archetypes/
│ ├── README.md
│ └── msf4j-microservice/
│ ├── pom.xml
│ └── src/
│ └── main/
│ └── resources/
│ ├── META-INF/
│ │ └── maven/
│ │ └── archetype-metadata.xml
│ └── archetype-resources/
│ ├── pom.xml
│ └── src/
│ └── main/
│ └── java/
│ ├── Application.java
│ └── __serviceClass__.java
├── client/
│ ├── README.md
│ ├── pom.xml
│ ├── src/
│ │ └── main/
│ │ └── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── client/
│ │ ├── ApacheHttpClient.java
│ │ ├── FeginZipkinTracingClient.java
│ │ ├── FeignClientWrapper.java
│ │ ├── FeignTracingClient.java
│ │ ├── MSF4JClient.java
│ │ ├── ModelUtils.java
│ │ ├── codec/
│ │ │ ├── DefaultErrorDecoder.java
│ │ │ ├── DefaultRestErrorResponse.java
│ │ │ ├── MSF4JDecoder.java
│ │ │ ├── MSF4JJacksonDecoder.java
│ │ │ └── RestErrorResponseMapper.java
│ │ └── exception/
│ │ └── RestServiceException.java
│ └── test/
│ ├── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── client/
│ │ └── test/
│ │ ├── ClientTest.java
│ │ ├── ModelUtils.java
│ │ ├── client/
│ │ │ ├── api/
│ │ │ │ ├── CustomerServiceAPI.java
│ │ │ │ └── InvoiceServiceAPI.java
│ │ │ └── exception/
│ │ │ ├── CustomerNotFoundResponseMapper.java
│ │ │ ├── CustomerNotFoundRestServiceException.java
│ │ │ ├── InvoiceNotFoundResponseMapper.java
│ │ │ └── InvoiceNotFoundRestServiceException.java
│ │ ├── exception/
│ │ │ ├── CustomerNotFoundException.java
│ │ │ ├── CustomerNotFoundMapper.java
│ │ │ ├── EntityNotFoundException.java
│ │ │ ├── EntityNotFoundMapper.java
│ │ │ ├── GenericServerErrorException.java
│ │ │ ├── GenericServerErrorMapper.java
│ │ │ ├── InvoiceNotFoundException.java
│ │ │ └── InvoiceNotFoundMapper.java
│ │ ├── model/
│ │ │ ├── Customer.java
│ │ │ ├── Invoice.java
│ │ │ ├── InvoiceReport.java
│ │ │ └── ServiceErrorResponse.java
│ │ └── service/
│ │ ├── CustomerService.java
│ │ ├── InvoiceService.java
│ │ └── ReportService.java
│ └── resources/
│ └── testng.xml
├── core/
│ ├── deployment.yaml
│ ├── pom.xml
│ └── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── org/
│ │ │ └── wso2/
│ │ │ └── msf4j/
│ │ │ ├── AbstractSessionManager.java
│ │ │ ├── DefaultSessionManager.java
│ │ │ ├── HttpStreamHandler.java
│ │ │ ├── HttpStreamer.java
│ │ │ ├── Interceptor.java
│ │ │ ├── Microservice.java
│ │ │ ├── MicroservicesRegistry.java
│ │ │ ├── MicroservicesRunner.java
│ │ │ ├── MicroservicesServer.java
│ │ │ ├── PersistentSessionManager.java
│ │ │ ├── Request.java
│ │ │ ├── Response.java
│ │ │ ├── ServiceMethodInfo.java
│ │ │ ├── Session.java
│ │ │ ├── SessionManager.java
│ │ │ ├── SwaggerService.java
│ │ │ ├── beanconversion/
│ │ │ │ ├── BeanConversionException.java
│ │ │ │ └── MediaTypeConverter.java
│ │ │ ├── config/
│ │ │ │ └── MSF4JConfig.java
│ │ │ ├── exception/
│ │ │ │ ├── InterceptorException.java
│ │ │ │ └── OSGiDeclarativeServiceException.java
│ │ │ ├── formparam/
│ │ │ │ ├── FileInfo.java
│ │ │ │ ├── FormDataParam.java
│ │ │ │ ├── FormItem.java
│ │ │ │ ├── FormParamIterator.java
│ │ │ │ ├── MultipartStream.java
│ │ │ │ ├── ParameterParser.java
│ │ │ │ ├── RequestContext.java
│ │ │ │ ├── exception/
│ │ │ │ │ ├── FormUploadException.java
│ │ │ │ │ ├── InvalidContentTypeException.java
│ │ │ │ │ └── InvalidFileNameException.java
│ │ │ │ └── util/
│ │ │ │ ├── Closeable.java
│ │ │ │ ├── FormItemHeader.java
│ │ │ │ ├── StreamUtil.java
│ │ │ │ ├── mime/
│ │ │ │ │ ├── Base64Decoder.java
│ │ │ │ │ ├── MimeUtility.java
│ │ │ │ │ ├── ParseException.java
│ │ │ │ │ ├── QuotedPrintableDecoder.java
│ │ │ │ │ └── package-info.java
│ │ │ │ └── package-info.java
│ │ │ ├── interceptor/
│ │ │ │ ├── InterceptorExecutor.java
│ │ │ │ ├── OSGiInterceptorConfig.java
│ │ │ │ ├── RequestInterceptor.java
│ │ │ │ ├── ResponseInterceptor.java
│ │ │ │ └── annotation/
│ │ │ │ ├── RequestInterceptor.java
│ │ │ │ └── ResponseInterceptor.java
│ │ │ ├── internal/
│ │ │ │ ├── ClassComparator.java
│ │ │ │ ├── DataHolder.java
│ │ │ │ ├── HttpConnectorPortBindingListener.java
│ │ │ │ ├── HttpHeadersImpl.java
│ │ │ │ ├── MSF4JConstants.java
│ │ │ │ ├── MSF4JHttpConnectorListener.java
│ │ │ │ ├── MSF4JThreadFactory.java
│ │ │ │ ├── MSF4JWSConnectorListener.java
│ │ │ │ ├── MicroservicesLCException.java
│ │ │ │ ├── MicroservicesRegistryImpl.java
│ │ │ │ ├── MicroservicesServerActivator.java
│ │ │ │ ├── MicroservicesServerImpl.java
│ │ │ │ ├── MicroservicesServerSC.java
│ │ │ │ ├── beanconversion/
│ │ │ │ │ ├── BeanConverter.java
│ │ │ │ │ ├── JsonConverter.java
│ │ │ │ │ ├── TextPlainConverter.java
│ │ │ │ │ └── XmlConverter.java
│ │ │ │ ├── entitywriter/
│ │ │ │ │ ├── EntityWriter.java
│ │ │ │ │ ├── EntityWriterRegistry.java
│ │ │ │ │ ├── FileEntityWriter.java
│ │ │ │ │ ├── InputStreamEntityWriter.java
│ │ │ │ │ ├── ObjectEntityWriter.java
│ │ │ │ │ └── StreamingOutputEntityWriter.java
│ │ │ │ ├── mime/
│ │ │ │ │ ├── MimeMapper.java
│ │ │ │ │ └── MimeMappingException.java
│ │ │ │ ├── router/
│ │ │ │ │ ├── HandlerException.java
│ │ │ │ │ ├── HttpMethodInfo.java
│ │ │ │ │ ├── HttpMethodInfoBuilder.java
│ │ │ │ │ ├── HttpResourceModel.java
│ │ │ │ │ ├── HttpResourceModelProcessor.java
│ │ │ │ │ ├── ImmutablePair.java
│ │ │ │ │ ├── MicroserviceMetadata.java
│ │ │ │ │ ├── ParamConvertUtils.java
│ │ │ │ │ ├── PatternPathRouter.java
│ │ │ │ │ ├── SubresourceKey.java
│ │ │ │ │ ├── Util.java
│ │ │ │ │ └── package-info.java
│ │ │ │ ├── session/
│ │ │ │ │ └── SessionIdGenerator.java
│ │ │ │ └── websocket/
│ │ │ │ ├── CloseCodeImpl.java
│ │ │ │ ├── EndpointDispatcher.java
│ │ │ │ ├── EndpointValidator.java
│ │ │ │ ├── EndpointsRegistryImpl.java
│ │ │ │ ├── WebSocketPongMessage.java
│ │ │ │ └── WebSocketServerSC.java
│ │ │ ├── security/
│ │ │ │ ├── JWTSecurityInterceptor.java
│ │ │ │ ├── MSF4JSecurityException.java
│ │ │ │ ├── SecurityErrorCode.java
│ │ │ │ ├── basic/
│ │ │ │ │ └── AbstractBasicAuthSecurityInterceptor.java
│ │ │ │ └── oauth2/
│ │ │ │ ├── IntrospectionResponse.java
│ │ │ │ └── OAuth2SecurityInterceptor.java
│ │ │ ├── template/
│ │ │ │ ├── RuntimeTemplateException.java
│ │ │ │ └── TemplateEngine.java
│ │ │ ├── util/
│ │ │ │ ├── BufferUtil.java
│ │ │ │ ├── Defaults.java
│ │ │ │ ├── HttpUtil.java
│ │ │ │ ├── Primitives.java
│ │ │ │ ├── QueryStringDecoderUtil.java
│ │ │ │ ├── ReflectionUtils.java
│ │ │ │ ├── RuntimeAnnotations.java
│ │ │ │ ├── SystemVariableUtil.java
│ │ │ │ └── Utils.java
│ │ │ └── websocket/
│ │ │ ├── WebSocketEndpoint.java
│ │ │ ├── WebSocketEndpointsRegistry.java
│ │ │ └── exception/
│ │ │ ├── WebSocketEndpointAnnotationException.java
│ │ │ ├── WebSocketEndpointMethodReturnTypeException.java
│ │ │ └── WebSocketMethodParameterException.java
│ │ └── resources/
│ │ ├── deployment.yaml
│ │ ├── log4j.properties
│ │ └── mime-map.properties
│ └── test/
│ ├── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ ├── DeprecatedInterceptorTest.java
│ │ ├── ExtendedServiceTest.java
│ │ ├── HostBindingTest.java
│ │ ├── HttpResourceModelTest.java
│ │ ├── HttpServerTest.java
│ │ ├── HttpsServerTest.java
│ │ ├── InterceptorTest.java
│ │ ├── InterceptorTestBase.java
│ │ ├── MSF4JResponseTest.java
│ │ ├── MimeMapperTest.java
│ │ ├── MutualAuthServerTest.java
│ │ ├── PathRouterTest.java
│ │ ├── SSLKeyStoreTest.java
│ │ ├── TransportConfigurationTest.java
│ │ ├── TransportConfigurationTest2.java
│ │ ├── beanconversion/
│ │ │ └── BeanConverterTest.java
│ │ ├── conf/
│ │ │ ├── Constants.java
│ │ │ ├── SSLClientContext.java
│ │ │ ├── SSLConfig.java
│ │ │ ├── SSLHandlerFactory.java
│ │ │ └── TrustManagerFactory.java
│ │ ├── exception/
│ │ │ ├── MappedException.java
│ │ │ ├── MappedException2.java
│ │ │ ├── TestExceptionMapper.java
│ │ │ └── TestExceptionMapper2.java
│ │ ├── interceptor/
│ │ │ ├── HighPriorityClassRequestInterceptor.java
│ │ │ ├── HighPriorityClassResponseInterceptor.java
│ │ │ ├── HighPriorityGlobalRequestInterceptor.java
│ │ │ ├── HighPriorityGlobalResponseInterceptor.java
│ │ │ ├── HighPriorityMethodRequestInterceptor.java
│ │ │ ├── HighPriorityMethodResponseInterceptor.java
│ │ │ ├── LowPriorityClassRequestInterceptor.java
│ │ │ ├── LowPriorityClassResponseInterceptor.java
│ │ │ ├── LowPriorityGlobalRequestInterceptor.java
│ │ │ ├── LowPriorityGlobalResponseInterceptor.java
│ │ │ ├── LowPriorityMethodRequestInterceptor.java
│ │ │ ├── LowPriorityMethodResponseInterceptor.java
│ │ │ ├── MediumPriorityClassRequestInterceptor.java
│ │ │ ├── MediumPriorityClassResponseInterceptor.java
│ │ │ ├── MediumPriorityGlobalRequestInterceptor.java
│ │ │ ├── MediumPriorityGlobalResponseInterceptor.java
│ │ │ ├── MediumPriorityMethodRequestInterceptor.java
│ │ │ ├── MediumPriorityMethodResponseInterceptor.java
│ │ │ ├── PriorityDataHolder.java
│ │ │ ├── TestBreakRequestInterceptor.java
│ │ │ ├── TestBreakResponseInterceptor.java
│ │ │ ├── TestExceptionBreakRequestInterceptor.java
│ │ │ ├── TestInterceptor.java
│ │ │ ├── TestInterceptorDeprecated.java
│ │ │ ├── TestRequestInterceptor.java
│ │ │ └── TestResponseInterceptor.java
│ │ ├── internal/
│ │ │ ├── HttpHeadersImplTest.java
│ │ │ └── MicroservicesRegistryTest.java
│ │ ├── pojo/
│ │ │ ├── Category.java
│ │ │ ├── Company.java
│ │ │ ├── Person.java
│ │ │ ├── Pet.java
│ │ │ ├── TextBean.java
│ │ │ └── XmlBean.java
│ │ ├── service/
│ │ │ ├── ExtendedTestMicroservice.java
│ │ │ ├── InterceptorTestMicroService.java
│ │ │ ├── PriorityInterceptorTestMicroService.java
│ │ │ ├── SecondService.java
│ │ │ ├── TestMicroServiceWithDynamicPath.java
│ │ │ ├── TestMicroservice.java
│ │ │ └── sub/
│ │ │ ├── Player.java
│ │ │ └── Team.java
│ │ ├── session/
│ │ │ └── SessionIdGeneratorTest.java
│ │ ├── util/
│ │ │ ├── QueryStringDecoderUtilTest.java
│ │ │ └── client/
│ │ │ └── websocket/
│ │ │ ├── WebSocketClient.java
│ │ │ └── WebSocketClientHandler.java
│ │ └── websocket/
│ │ ├── DeploymentTest.java
│ │ ├── EndpointRegistryTest.java
│ │ ├── ValidatorTest.java
│ │ └── endpoint/
│ │ ├── ChatAppEndpoint.java
│ │ ├── EchoEndpoint.java
│ │ ├── TestEndpoint.java
│ │ ├── TestEndpointWithAllCorrect.java
│ │ ├── TestEndpointWithMandatoryParameters.java
│ │ └── error/
│ │ ├── TestEndpoinWithOnTextError.java
│ │ ├── TestEndpointWithMandatoryParametersMissing.java
│ │ ├── TestEndpointWithOnBinaryError.java
│ │ ├── TestEndpointWithOnCloseError.java
│ │ ├── TestEndpointWithOnError.java
│ │ ├── TestEndpointWithOnOpenError.java
│ │ ├── TestEndpointWithOnPongError.java
│ │ ├── TestEndpointWithReturnTypeError.java
│ │ └── TestEndpointWithServerEndpointError.java
│ └── resources/
│ ├── cert.jks
│ ├── client.jks
│ ├── deployment.yaml
│ ├── netty-transports-1.yaml
│ ├── netty-transports-2.yaml
│ ├── netty-transports-3.yaml
│ ├── netty-transports-4.yaml
│ ├── testTxtFile.txt
│ └── testng.xml
├── deployer/
│ ├── pom.xml
│ └── src/
│ ├── main/
│ │ └── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── deployer/
│ │ ├── MicroserviceDeploymentException.java
│ │ ├── MicroserviceDeploymentUtils.java
│ │ └── internal/
│ │ ├── DataHolder.java
│ │ ├── MSF4JDeployerSC.java
│ │ └── MicroservicesDeployer.java
│ └── test/
│ ├── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── deployer/
│ │ └── MSF4JDeployerTest.java
│ └── resources/
│ └── testng.xml
├── distribution/
│ ├── binary/
│ │ ├── LICENSE.txt
│ │ ├── README.md
│ │ ├── bin.xml
│ │ ├── conf/
│ │ │ ├── netty-transports.yml
│ │ │ └── wso2carbon.jks
│ │ └── pom.xml
│ └── msf4j-all/
│ ├── README.md
│ └── pom.xml
├── features/
│ ├── etc/
│ │ └── feature.properties
│ ├── feature-test/
│ │ ├── pom.xml
│ │ └── src/
│ │ └── test/
│ │ ├── java/
│ │ │ └── org/
│ │ │ └── wso2/
│ │ │ └── msf4j/
│ │ │ └── osgi/
│ │ │ └── test/
│ │ │ └── MSF4JStartupTest.java
│ │ └── resources/
│ │ ├── carbon-home/
│ │ │ └── conf/
│ │ │ ├── carbon.yml
│ │ │ └── log4j2.xml
│ │ └── testng.xml
│ ├── org.wso2.msf4j.deployer.feature/
│ │ ├── pom.xml
│ │ └── resources/
│ │ └── p2.inf
│ └── org.wso2.msf4j.feature/
│ ├── pom.xml
│ └── resources/
│ └── netty-transports.yml
├── issue_template.md
├── jaxrs-delegates/
│ ├── pom.xml
│ └── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── org/
│ │ │ └── wso2/
│ │ │ └── msf4j/
│ │ │ └── delegates/
│ │ │ ├── CookieHeaderProvider.java
│ │ │ ├── MSF4JResponse.java
│ │ │ ├── MSF4JRuntimeDelegate.java
│ │ │ └── MediaTypeHeaderProvider.java
│ │ └── resources/
│ │ └── META-INF/
│ │ └── services/
│ │ └── javax.ws.rs.ext.RuntimeDelegate
│ └── test/
│ ├── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ ├── delegates/
│ │ │ ├── CookieHeaderProviderTest.java
│ │ │ └── MediaTypeHeaderProviderTest.java
│ │ ├── models/
│ │ │ └── SampleEntity.java
│ │ └── service/
│ │ └── ClientTestMicroService.java
│ └── resources/
│ └── testng.xml
├── perf-benchmark/
│ ├── README.md
│ ├── Samples/
│ │ ├── dropwizard/
│ │ │ ├── README.md
│ │ │ ├── pom.xml
│ │ │ ├── run.sh
│ │ │ └── src/
│ │ │ └── main/
│ │ │ └── java/
│ │ │ └── org/
│ │ │ └── wso2/
│ │ │ └── msf4j/
│ │ │ └── perftest/
│ │ │ └── echo/
│ │ │ └── dropwizard/
│ │ │ ├── AppStart.java
│ │ │ └── EchoService.java
│ │ ├── ninja-echo-message/
│ │ │ ├── README.md
│ │ │ ├── pom.xml
│ │ │ ├── run.sh
│ │ │ └── src/
│ │ │ └── main/
│ │ │ └── java/
│ │ │ ├── conf/
│ │ │ │ ├── Module.java
│ │ │ │ ├── Routes.java
│ │ │ │ ├── application.conf
│ │ │ │ └── messages.properties
│ │ │ ├── controllers/
│ │ │ │ └── ApplicationController.java
│ │ │ ├── ehcache.xml
│ │ │ ├── logback.xml
│ │ │ └── util/
│ │ │ └── BodyParserEngineTextPlain.java
│ │ ├── spark/
│ │ │ ├── README.md
│ │ │ ├── pom.xml
│ │ │ ├── run.sh
│ │ │ └── src/
│ │ │ └── main/
│ │ │ └── java/
│ │ │ └── org/
│ │ │ └── wso2/
│ │ │ └── msf4j/
│ │ │ └── perftest/
│ │ │ └── echo/
│ │ │ └── spark/
│ │ │ └── Application.java
│ │ ├── springboot/
│ │ │ ├── README.md
│ │ │ ├── pom.xml
│ │ │ ├── run.sh
│ │ │ └── src/
│ │ │ └── main/
│ │ │ └── java/
│ │ │ └── org/
│ │ │ └── wso2/
│ │ │ └── msf4j/
│ │ │ └── perftest/
│ │ │ └── echo/
│ │ │ └── springboot/
│ │ │ ├── Application.java
│ │ │ └── EchoService.java
│ │ ├── wildfly/
│ │ │ ├── README.md
│ │ │ ├── pom.xml
│ │ │ ├── run.sh
│ │ │ └── src/
│ │ │ └── main/
│ │ │ ├── java/
│ │ │ │ └── org/
│ │ │ │ └── wso2/
│ │ │ │ └── msf4j/
│ │ │ │ └── perftest/
│ │ │ │ └── echo/
│ │ │ │ └── wildfly/
│ │ │ │ ├── EchoService.java
│ │ │ │ └── WFApplication.java
│ │ │ └── webapp/
│ │ │ └── WEB-INF/
│ │ │ └── beans.xml
│ │ └── wso2msf4j/
│ │ ├── README.md
│ │ ├── pom.xml
│ │ ├── run.sh
│ │ └── src/
│ │ └── main/
│ │ └── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── perftest/
│ │ └── echo/
│ │ └── wso2msf4j/
│ │ ├── Application.java
│ │ └── EchoService.java
│ ├── excecute-tests.sh
│ ├── run-latency.sh
│ └── run.sh
├── pom.xml
├── poms/
│ ├── msf4j-service/
│ │ ├── README.md
│ │ └── pom.xml
│ └── parent/
│ └── pom.xml
├── pull_request_template.md
├── samples/
│ ├── README.md
│ ├── basicauth-security/
│ │ ├── README.md
│ │ ├── pom.xml
│ │ └── src/
│ │ └── main/
│ │ └── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── example/
│ │ ├── Application.java
│ │ ├── Helloworld.java
│ │ └── UsernamePasswordSecurityInterceptor.java
│ ├── circuitbreaker/
│ │ ├── README.md
│ │ ├── pom.xml
│ │ └── src/
│ │ └── main/
│ │ └── java/
│ │ └── org/
│ │ └── example/
│ │ └── service/
│ │ ├── Application.java
│ │ ├── CircuitBreakerCommand.java
│ │ ├── Stock.java
│ │ ├── StockQuoteDatabase.java
│ │ └── StockQuoteService.java
│ ├── fileserver/
│ │ ├── README.md
│ │ ├── pom.xml
│ │ └── src/
│ │ └── main/
│ │ └── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── example/
│ │ ├── Application.java
│ │ └── FileServer.java
│ ├── formparam/
│ │ ├── README.md
│ │ ├── pom.xml
│ │ └── src/
│ │ └── main/
│ │ ├── java/
│ │ │ └── org/
│ │ │ └── wso2/
│ │ │ └── msf4j/
│ │ │ └── example/
│ │ │ ├── Application.java
│ │ │ ├── FormService.java
│ │ │ ├── SampleClient.java
│ │ │ └── bean/
│ │ │ ├── Company.java
│ │ │ └── Person.java
│ │ └── resources/
│ │ └── sample.txt
│ ├── helloworld/
│ │ ├── README.md
│ │ ├── pom.xml
│ │ └── src/
│ │ └── main/
│ │ └── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── example/
│ │ ├── Application.java
│ │ └── HelloService.java
│ ├── http-monitoring/
│ │ ├── README.md
│ │ ├── client-truststore.jks
│ │ ├── data-agent-config.xml
│ │ ├── pom.xml
│ │ └── src/
│ │ └── main/
│ │ ├── java/
│ │ │ └── org/
│ │ │ └── wso2/
│ │ │ └── msf4j/
│ │ │ └── sample/
│ │ │ └── httpmonitoring/
│ │ │ ├── Application.java
│ │ │ └── service/
│ │ │ ├── Student.java
│ │ │ └── StudentService.java
│ │ └── resources/
│ │ ├── deployment.yaml
│ │ ├── http-monitoring.yaml
│ │ └── metrics.yaml
│ ├── http-session/
│ │ ├── README.md
│ │ ├── pom.xml
│ │ └── src/
│ │ └── main/
│ │ └── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── example/
│ │ ├── Application.java
│ │ └── CounterService.java
│ ├── interceptor/
│ │ ├── README.md
│ │ ├── deployable-jar-interceptor-service/
│ │ │ ├── README.md
│ │ │ ├── pom.xml
│ │ │ └── src/
│ │ │ └── main/
│ │ │ └── java/
│ │ │ └── org/
│ │ │ └── wso2/
│ │ │ └── msf4j/
│ │ │ └── samples/
│ │ │ └── deployablejarinterceptorservice/
│ │ │ ├── InterceptorService.java
│ │ │ └── interceptors/
│ │ │ ├── HTTPRequestLogger.java
│ │ │ ├── HTTPResponseLogger.java
│ │ │ ├── LogTextRequestInterceptor.java
│ │ │ ├── LogTextResponseInterceptor.java
│ │ │ ├── PropertyAddRequestInterceptor.java
│ │ │ └── PropertyGetResponseInterceptor.java
│ │ ├── fatjar-interceptor-service/
│ │ │ ├── README.md
│ │ │ ├── pom.xml
│ │ │ └── src/
│ │ │ └── main/
│ │ │ └── java/
│ │ │ └── org/
│ │ │ └── wso2/
│ │ │ └── msf4j/
│ │ │ └── samples/
│ │ │ └── fatjarinterceptorservice/
│ │ │ ├── Application.java
│ │ │ └── InterceptorService.java
│ │ ├── interceptor-common/
│ │ │ ├── pom.xml
│ │ │ └── src/
│ │ │ └── main/
│ │ │ └── java/
│ │ │ └── org/
│ │ │ └── wso2/
│ │ │ └── msf4j/
│ │ │ └── samples/
│ │ │ └── interceptor/
│ │ │ └── common/
│ │ │ ├── HTTPRequestLogger.java
│ │ │ ├── HTTPResponseLogger.java
│ │ │ ├── LogTextRequestInterceptor.java
│ │ │ ├── LogTextResponseInterceptor.java
│ │ │ ├── PropertyAddRequestInterceptor.java
│ │ │ └── PropertyGetResponseInterceptor.java
│ │ ├── osgi-interceptor-service/
│ │ │ ├── README.md
│ │ │ ├── pom.xml
│ │ │ └── src/
│ │ │ └── main/
│ │ │ └── java/
│ │ │ └── org/
│ │ │ └── wso2/
│ │ │ └── msf4j/
│ │ │ └── samples/
│ │ │ └── osgiinterceptorservice/
│ │ │ ├── InterceptorService.java
│ │ │ └── config/
│ │ │ └── SampleInterceptorConfig.java
│ │ └── spring-fatjar-interceptor-service/
│ │ ├── README.md
│ │ ├── pom.xml
│ │ └── src/
│ │ └── main/
│ │ └── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── samples/
│ │ └── springfatjarinterceptorservice/
│ │ ├── Application.java
│ │ ├── CustomerService.java
│ │ └── ReceptionService.java
│ ├── jpa/
│ │ ├── README.md
│ │ ├── pom.xml
│ │ └── src/
│ │ └── main/
│ │ ├── java/
│ │ │ └── org/
│ │ │ └── wso2/
│ │ │ └── msf4j/
│ │ │ └── example/
│ │ │ ├── Application.java
│ │ │ ├── dao/
│ │ │ │ ├── AbstractRepository.java
│ │ │ │ └── UserRepository.java
│ │ │ ├── model/
│ │ │ │ └── User.java
│ │ │ └── resource/
│ │ │ └── UserResource.java
│ │ └── resources/
│ │ └── META-INF/
│ │ └── persistence.xml
│ ├── jwt-claims/
│ │ ├── JWTAccessTokenBuilder/
│ │ │ ├── pom.xml
│ │ │ └── src/
│ │ │ └── main/
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── wso2/
│ │ │ └── jwt/
│ │ │ └── token/
│ │ │ └── builder/
│ │ │ ├── Constants.java
│ │ │ ├── JWTAccessTokenBuilder.java
│ │ │ └── internal/
│ │ │ └── JWTAccessTokenBuilderDSComponent.java
│ │ ├── README.md
│ │ ├── jwt-sample/
│ │ │ ├── pom.xml
│ │ │ └── src/
│ │ │ └── main/
│ │ │ ├── java/
│ │ │ │ └── org/
│ │ │ │ └── wso2/
│ │ │ │ └── msf4j/
│ │ │ │ └── example/
│ │ │ │ ├── Application.java
│ │ │ │ ├── CustomJWTClaimsInterceptor.java
│ │ │ │ └── Helloworld.java
│ │ │ └── resources/
│ │ │ └── wso2carbon.jks
│ │ ├── pom.xml
│ │ ├── sso-agent-for-jwt-webapp/
│ │ │ ├── pom.xml
│ │ │ └── src/
│ │ │ └── main/
│ │ │ ├── java/
│ │ │ │ └── org/
│ │ │ │ └── wso2/
│ │ │ │ └── sample/
│ │ │ │ └── is/
│ │ │ │ └── sso/
│ │ │ │ └── agent/
│ │ │ │ ├── ForwardingServlet.java
│ │ │ │ ├── SSOAgentSampleFilter.java
│ │ │ │ ├── SampleAttributesRequestor.java
│ │ │ │ └── SampleContextEventListener.java
│ │ │ ├── resources/
│ │ │ │ ├── avis.properties
│ │ │ │ ├── travelocity.properties
│ │ │ │ └── wso2carbon.jks
│ │ │ └── webapp/
│ │ │ ├── WEB-INF/
│ │ │ │ └── web.xml
│ │ │ ├── css/
│ │ │ │ └── cart-styles.css
│ │ │ ├── errors.jsp
│ │ │ ├── home.jsp
│ │ │ └── index.jsp
│ │ └── sso-agent-sample/
│ │ └── pom.xml
│ ├── lifecycle/
│ │ ├── README.md
│ │ ├── pom.xml
│ │ └── src/
│ │ └── main/
│ │ └── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── example/
│ │ ├── Application.java
│ │ └── Helloworld.java
│ ├── log-interceptor-bundle/
│ │ └── pom.xml
│ ├── message-tracing/
│ │ ├── das/
│ │ │ ├── README.md
│ │ │ ├── pom.xml
│ │ │ └── src/
│ │ │ └── main/
│ │ │ └── java/
│ │ │ └── org/
│ │ │ └── wso2/
│ │ │ └── msf4j/
│ │ │ └── example/
│ │ │ ├── Application.java
│ │ │ ├── ModelUtils.java
│ │ │ ├── client/
│ │ │ │ ├── api/
│ │ │ │ │ ├── CustomerServiceAPI.java
│ │ │ │ │ └── InvoiceServiceAPI.java
│ │ │ │ └── exception/
│ │ │ │ ├── CustomerNotFoundResponseMapper.java
│ │ │ │ ├── CustomerNotFoundRestServiceException.java
│ │ │ │ ├── InvoiceNotFoundResponseMapper.java
│ │ │ │ └── InvoiceNotFoundRestServiceException.java
│ │ │ ├── exception/
│ │ │ │ ├── CustomerNotFoundException.java
│ │ │ │ ├── CustomerNotFoundMapper.java
│ │ │ │ ├── EntityNotFoundException.java
│ │ │ │ ├── EntityNotFoundMapper.java
│ │ │ │ ├── GenericServerErrorException.java
│ │ │ │ ├── GenericServerErrorMapper.java
│ │ │ │ ├── InvoiceNotFoundException.java
│ │ │ │ └── InvoiceNotFoundMapper.java
│ │ │ ├── model/
│ │ │ │ ├── Customer.java
│ │ │ │ ├── Invoice.java
│ │ │ │ ├── InvoiceReport.java
│ │ │ │ └── ServiceErrorResponse.java
│ │ │ └── service/
│ │ │ ├── CustomerService.java
│ │ │ ├── InvoiceService.java
│ │ │ └── ReportService.java
│ │ └── zipkin/
│ │ ├── pom.xml
│ │ └── src/
│ │ └── main/
│ │ └── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── example/
│ │ ├── Application.java
│ │ ├── TraceableService.java
│ │ └── TraceableServiceInterface.java
│ ├── metrics/
│ │ ├── README.md
│ │ ├── pom.xml
│ │ └── src/
│ │ └── main/
│ │ ├── java/
│ │ │ └── org/
│ │ │ └── wso2/
│ │ │ └── msf4j/
│ │ │ └── sample/
│ │ │ └── metrics/
│ │ │ ├── Application.java
│ │ │ └── service/
│ │ │ └── DemoService.java
│ │ └── resources/
│ │ ├── deployment.yaml
│ │ └── metrics.yaml
│ ├── oauth2-security/
│ │ ├── README.md
│ │ ├── pom.xml
│ │ └── src/
│ │ └── main/
│ │ └── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── example/
│ │ ├── Application.java
│ │ └── service/
│ │ └── Helloworld.java
│ ├── petstore/
│ │ ├── README.md
│ │ ├── deployment/
│ │ │ ├── docker-compose/
│ │ │ │ ├── README.md
│ │ │ │ ├── clean.sh
│ │ │ │ ├── das/
│ │ │ │ │ └── Dockerfile
│ │ │ │ ├── docker-compose.yaml
│ │ │ │ └── run.sh
│ │ │ └── kubernetes/
│ │ │ ├── README.md
│ │ │ ├── clean.sh
│ │ │ ├── external-endpoints/
│ │ │ │ ├── das-endpoint.yaml
│ │ │ │ ├── das-service.yaml
│ │ │ │ ├── is-endpoint.yaml
│ │ │ │ └── is-service.yaml
│ │ │ ├── packs/
│ │ │ │ └── README.md
│ │ │ ├── path.sh
│ │ │ ├── petstore.sh
│ │ │ └── scale.sh
│ │ ├── microservices/
│ │ │ ├── fileserver/
│ │ │ │ ├── README.md
│ │ │ │ ├── client-truststore.jks
│ │ │ │ ├── container/
│ │ │ │ │ ├── docker/
│ │ │ │ │ │ ├── Dockerfile
│ │ │ │ │ │ └── README.md
│ │ │ │ │ └── kubernetes/
│ │ │ │ │ ├── README.md
│ │ │ │ │ ├── fileserver-rc.yaml
│ │ │ │ │ └── fileserver-service.yaml
│ │ │ │ ├── data-agent-conf.xml
│ │ │ │ ├── pom.xml
│ │ │ │ └── src/
│ │ │ │ └── main/
│ │ │ │ ├── java/
│ │ │ │ │ └── org/
│ │ │ │ │ └── wso2/
│ │ │ │ │ └── msf4j/
│ │ │ │ │ └── examples/
│ │ │ │ │ └── petstore/
│ │ │ │ │ └── fileserver/
│ │ │ │ │ ├── FileServerService.java
│ │ │ │ │ └── Runner.java
│ │ │ │ └── resources/
│ │ │ │ ├── http-monitoring.yml
│ │ │ │ ├── metrics.yml
│ │ │ │ └── wso2carbon.jks
│ │ │ ├── frontend-admin/
│ │ │ │ └── container/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── docker/
│ │ │ │ │ ├── Dockerfile
│ │ │ │ │ ├── html/
│ │ │ │ │ │ ├── .htaccess
│ │ │ │ │ │ ├── add-pet-types.php
│ │ │ │ │ │ ├── add-pets.php
│ │ │ │ │ │ ├── config/
│ │ │ │ │ │ │ └── config.php
│ │ │ │ │ │ ├── controllers/
│ │ │ │ │ │ │ ├── API/
│ │ │ │ │ │ │ │ └── curl_api.php
│ │ │ │ │ │ │ ├── authentication/
│ │ │ │ │ │ │ │ └── auth.php
│ │ │ │ │ │ │ └── rest.php
│ │ │ │ │ │ ├── css/
│ │ │ │ │ │ │ └── custom.css
│ │ │ │ │ │ ├── includes/
│ │ │ │ │ │ │ ├── header.php
│ │ │ │ │ │ │ └── navbar.php
│ │ │ │ │ │ ├── index.php
│ │ │ │ │ │ ├── js/
│ │ │ │ │ │ │ ├── custom.js
│ │ │ │ │ │ │ └── login.js
│ │ │ │ │ │ ├── libs/
│ │ │ │ │ │ │ ├── font-awesome_4.3.0/
│ │ │ │ │ │ │ │ ├── css/
│ │ │ │ │ │ │ │ │ └── font-awesome.css
│ │ │ │ │ │ │ │ └── fonts/
│ │ │ │ │ │ │ │ └── FontAwesome.otf
│ │ │ │ │ │ │ ├── font-wso2_1.2/
│ │ │ │ │ │ │ │ └── css/
│ │ │ │ │ │ │ │ └── font-wso2.css
│ │ │ │ │ │ │ ├── jquery_1.11.3/
│ │ │ │ │ │ │ │ └── jquery-1.11.3.js
│ │ │ │ │ │ │ └── noty_2.3.5/
│ │ │ │ │ │ │ ├── jquery.noty.js
│ │ │ │ │ │ │ ├── layouts/
│ │ │ │ │ │ │ │ ├── bottom.js
│ │ │ │ │ │ │ │ ├── bottomCenter.js
│ │ │ │ │ │ │ │ ├── bottomLeft.js
│ │ │ │ │ │ │ │ ├── bottomRight.js
│ │ │ │ │ │ │ │ ├── center.js
│ │ │ │ │ │ │ │ ├── centerLeft.js
│ │ │ │ │ │ │ │ ├── centerRight.js
│ │ │ │ │ │ │ │ ├── inline.js
│ │ │ │ │ │ │ │ ├── top.js
│ │ │ │ │ │ │ │ ├── topCenter.js
│ │ │ │ │ │ │ │ ├── topLeft.js
│ │ │ │ │ │ │ │ └── topRight.js
│ │ │ │ │ │ │ ├── packaged/
│ │ │ │ │ │ │ │ └── jquery.noty.packaged.js
│ │ │ │ │ │ │ ├── promise.js
│ │ │ │ │ │ │ └── themes/
│ │ │ │ │ │ │ ├── bootstrap.js
│ │ │ │ │ │ │ ├── default.js
│ │ │ │ │ │ │ └── relax.js
│ │ │ │ │ │ ├── login.php
│ │ │ │ │ │ ├── logout.php
│ │ │ │ │ │ ├── pet-types.php
│ │ │ │ │ │ └── pets.php
│ │ │ │ │ └── init.sh
│ │ │ │ └── kubernetes/
│ │ │ │ ├── admin-fe-controller.yaml
│ │ │ │ ├── admin-fe-service.yaml
│ │ │ │ ├── redis-master-controller.yaml
│ │ │ │ └── redis-master-service.yaml
│ │ │ ├── frontend-user/
│ │ │ │ └── container/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── docker/
│ │ │ │ │ ├── Dockerfile
│ │ │ │ │ ├── html/
│ │ │ │ │ │ ├── cart.php
│ │ │ │ │ │ ├── checkout.php
│ │ │ │ │ │ ├── config/
│ │ │ │ │ │ │ └── config.php
│ │ │ │ │ │ ├── controllers/
│ │ │ │ │ │ │ ├── API/
│ │ │ │ │ │ │ │ └── curl_api.php
│ │ │ │ │ │ │ ├── authentication/
│ │ │ │ │ │ │ │ └── auth.php
│ │ │ │ │ │ │ └── cart/
│ │ │ │ │ │ │ └── cart.php
│ │ │ │ │ │ ├── css/
│ │ │ │ │ │ │ └── custom.css
│ │ │ │ │ │ ├── includes/
│ │ │ │ │ │ │ ├── header.php
│ │ │ │ │ │ │ └── navbar.php
│ │ │ │ │ │ ├── index.php
│ │ │ │ │ │ ├── js/
│ │ │ │ │ │ │ ├── custom.js
│ │ │ │ │ │ │ └── login.js
│ │ │ │ │ │ ├── libs/
│ │ │ │ │ │ │ ├── font-awesome_4.3.0/
│ │ │ │ │ │ │ │ ├── css/
│ │ │ │ │ │ │ │ │ └── font-awesome.css
│ │ │ │ │ │ │ │ └── fonts/
│ │ │ │ │ │ │ │ └── FontAwesome.otf
│ │ │ │ │ │ │ ├── font-wso2_1.2/
│ │ │ │ │ │ │ │ └── css/
│ │ │ │ │ │ │ │ └── font-wso2.css
│ │ │ │ │ │ │ ├── jquery_1.11.3/
│ │ │ │ │ │ │ │ └── jquery-1.11.3.js
│ │ │ │ │ │ │ └── noty_2.3.5/
│ │ │ │ │ │ │ ├── jquery.noty.js
│ │ │ │ │ │ │ ├── layouts/
│ │ │ │ │ │ │ │ ├── bottom.js
│ │ │ │ │ │ │ │ ├── bottomCenter.js
│ │ │ │ │ │ │ │ ├── bottomLeft.js
│ │ │ │ │ │ │ │ ├── bottomRight.js
│ │ │ │ │ │ │ │ ├── center.js
│ │ │ │ │ │ │ │ ├── centerLeft.js
│ │ │ │ │ │ │ │ ├── centerRight.js
│ │ │ │ │ │ │ │ ├── inline.js
│ │ │ │ │ │ │ │ ├── top.js
│ │ │ │ │ │ │ │ ├── topCenter.js
│ │ │ │ │ │ │ │ ├── topLeft.js
│ │ │ │ │ │ │ │ └── topRight.js
│ │ │ │ │ │ │ ├── packaged/
│ │ │ │ │ │ │ │ └── jquery.noty.packaged.js
│ │ │ │ │ │ │ ├── promise.js
│ │ │ │ │ │ │ └── themes/
│ │ │ │ │ │ │ ├── bootstrap.js
│ │ │ │ │ │ │ ├── default.js
│ │ │ │ │ │ │ └── relax.js
│ │ │ │ │ │ ├── login.php
│ │ │ │ │ │ └── logout.php
│ │ │ │ │ └── init.sh
│ │ │ │ └── kubernetes/
│ │ │ │ ├── user-fe-controller.yaml
│ │ │ │ └── user-fe-service.yaml
│ │ │ ├── pet/
│ │ │ │ ├── README.md
│ │ │ │ ├── client-truststore.jks
│ │ │ │ ├── container/
│ │ │ │ │ ├── docker/
│ │ │ │ │ │ ├── Dockerfile
│ │ │ │ │ │ ├── README.md
│ │ │ │ │ │ └── ssh/
│ │ │ │ │ │ └── Dockerfile
│ │ │ │ │ └── kubernetes/
│ │ │ │ │ ├── pet-controller.yaml
│ │ │ │ │ └── pet-service.yaml
│ │ │ │ ├── data-agent-conf.xml
│ │ │ │ ├── etc/
│ │ │ │ │ └── init.sh
│ │ │ │ ├── pom.xml
│ │ │ │ └── src/
│ │ │ │ └── main/
│ │ │ │ ├── java/
│ │ │ │ │ └── org/
│ │ │ │ │ └── wso2/
│ │ │ │ │ └── msf4j/
│ │ │ │ │ └── examples/
│ │ │ │ │ └── petstore/
│ │ │ │ │ └── pet/
│ │ │ │ │ ├── PetCategoryService.java
│ │ │ │ │ ├── PetConstants.java
│ │ │ │ │ ├── PetService.java
│ │ │ │ │ └── Runner.java
│ │ │ │ └── resources/
│ │ │ │ ├── http-monitoring.yml
│ │ │ │ ├── metrics.yml
│ │ │ │ └── wso2carbon.jks
│ │ │ ├── redis/
│ │ │ │ └── container/
│ │ │ │ └── kubernetes/
│ │ │ │ ├── README.md
│ │ │ │ ├── redis-controller.yaml
│ │ │ │ ├── redis-master.yaml
│ │ │ │ ├── redis-sentinel-controller.yaml
│ │ │ │ └── redis-sentinel-service.yaml
│ │ │ ├── security/
│ │ │ │ ├── client-truststore.jks
│ │ │ │ ├── container/
│ │ │ │ │ ├── docker/
│ │ │ │ │ │ └── Dockerfile
│ │ │ │ │ └── kubernetes/
│ │ │ │ │ ├── README.md
│ │ │ │ │ ├── security-controller.yaml
│ │ │ │ │ └── security-service.yaml
│ │ │ │ ├── data-agent-conf.xml
│ │ │ │ ├── pom.xml
│ │ │ │ └── src/
│ │ │ │ └── main/
│ │ │ │ ├── java/
│ │ │ │ │ ├── README.md
│ │ │ │ │ └── org/
│ │ │ │ │ └── wso2/
│ │ │ │ │ └── msf4j/
│ │ │ │ │ └── examples/
│ │ │ │ │ └── petstore/
│ │ │ │ │ └── security/
│ │ │ │ │ ├── JWTGenerator.java
│ │ │ │ │ ├── Runner.java
│ │ │ │ │ ├── UserAuthenticationService.java
│ │ │ │ │ └── ldap/
│ │ │ │ │ ├── LDAPUserStoreManager.java
│ │ │ │ │ └── server/
│ │ │ │ │ ├── ApacheDirectoryServerActivator.java
│ │ │ │ │ └── LDAPServerConfigurationBuilder.java
│ │ │ │ └── resources/
│ │ │ │ ├── http-monitoring.yml
│ │ │ │ ├── metrics.yml
│ │ │ │ ├── repository/
│ │ │ │ │ └── conf/
│ │ │ │ │ └── embedded-ldap.xml
│ │ │ │ └── wso2carbon.jks
│ │ │ └── transaction/
│ │ │ ├── README.md
│ │ │ ├── client-truststore.jks
│ │ │ ├── container/
│ │ │ │ ├── docker/
│ │ │ │ │ └── Dockerfile
│ │ │ │ └── kubernetes/
│ │ │ │ ├── txn-controller.yaml
│ │ │ │ └── txn-service.yaml
│ │ │ ├── data-agent-conf.xml
│ │ │ ├── pom.xml
│ │ │ └── src/
│ │ │ └── main/
│ │ │ ├── java/
│ │ │ │ └── org/
│ │ │ │ └── wso2/
│ │ │ │ └── msf4j/
│ │ │ │ └── examples/
│ │ │ │ └── petstore/
│ │ │ │ └── transaction/
│ │ │ │ ├── Runner.java
│ │ │ │ ├── TxnConstants.java
│ │ │ │ └── TxnService.java
│ │ │ └── resources/
│ │ │ ├── http-monitoring.yml
│ │ │ ├── metrics.yml
│ │ │ └── wso2carbon.jks
│ │ ├── pom.xml
│ │ └── util/
│ │ ├── pom.xml
│ │ └── src/
│ │ └── main/
│ │ └── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── examples/
│ │ └── petstore/
│ │ └── util/
│ │ ├── JedisUtil.java
│ │ └── model/
│ │ ├── Category.java
│ │ ├── CreditCard.java
│ │ ├── Order.java
│ │ ├── Pet.java
│ │ └── User.java
│ ├── regex-pathparam/
│ │ ├── pom.xml
│ │ └── src/
│ │ └── main/
│ │ └── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── example/
│ │ ├── Application.java
│ │ └── RegexPathParam.java
│ ├── spring-helloworld/
│ │ ├── README.md
│ │ ├── pom.xml
│ │ └── src/
│ │ └── main/
│ │ └── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── example/
│ │ ├── Application.java
│ │ ├── Hello.java
│ │ ├── HelloService.java
│ │ ├── InvalidNameException.java
│ │ ├── InvalidNameExceptionMapper.java
│ │ ├── LogHeadersInterceptor.java
│ │ └── TransportConfiguration.java
│ ├── spring-profile/
│ │ ├── README.md
│ │ ├── pom.xml
│ │ └── src/
│ │ └── main/
│ │ ├── java/
│ │ │ └── org/
│ │ │ └── wso2/
│ │ │ └── msf4j/
│ │ │ └── example/
│ │ │ ├── Application.java
│ │ │ ├── Hello.java
│ │ │ ├── HelloService.java
│ │ │ └── TransportConfig.java
│ │ └── resources/
│ │ └── application.yml
│ ├── stockquote/
│ │ ├── bundle/
│ │ │ ├── README.md
│ │ │ ├── pom.xml
│ │ │ └── src/
│ │ │ └── main/
│ │ │ └── java/
│ │ │ └── org/
│ │ │ └── wso2/
│ │ │ └── msf4j/
│ │ │ └── stockquote/
│ │ │ ├── Stock.java
│ │ │ ├── StockQuoteService.java
│ │ │ ├── Stocks.java
│ │ │ └── exception/
│ │ │ ├── DuplicateSymbolException.java
│ │ │ ├── DuplicateSymbolMapper.java
│ │ │ ├── EntityNotFoundException.java
│ │ │ ├── EntityNotFoundMapper.java
│ │ │ ├── SymbolNotFoundException.java
│ │ │ └── SymbolNotFoundMapper.java
│ │ ├── deployable-jar/
│ │ │ ├── README.md
│ │ │ ├── pom.xml
│ │ │ └── src/
│ │ │ └── main/
│ │ │ └── java/
│ │ │ └── org/
│ │ │ └── wso2/
│ │ │ └── msf4j/
│ │ │ └── stockquote/
│ │ │ └── example/
│ │ │ ├── Stock.java
│ │ │ ├── StockQuoteService.java
│ │ │ ├── Stocks.java
│ │ │ └── exception/
│ │ │ ├── DuplicateSymbolException.java
│ │ │ ├── DuplicateSymbolMapper.java
│ │ │ ├── EntityNotFoundException.java
│ │ │ ├── EntityNotFoundMapper.java
│ │ │ ├── SymbolNotFoundException.java
│ │ │ └── SymbolNotFoundMapper.java
│ │ └── fatjar/
│ │ ├── README.md
│ │ ├── conf/
│ │ │ ├── netty-transports.yml
│ │ │ └── wso2carbon.jks
│ │ ├── container/
│ │ │ ├── docker/
│ │ │ │ └── Dockerfile
│ │ │ └── kubernetes/
│ │ │ ├── stockquote-controller.yaml
│ │ │ └── stockquote-service.yaml
│ │ ├── pom.xml
│ │ └── src/
│ │ └── main/
│ │ └── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── example/
│ │ ├── Application.java
│ │ ├── Stock.java
│ │ ├── StockQuoteService.java
│ │ ├── Stocks.java
│ │ └── exception/
│ │ ├── DuplicateSymbolException.java
│ │ ├── DuplicateSymbolMapper.java
│ │ ├── EntityNotFoundException.java
│ │ ├── EntityNotFoundMapper.java
│ │ ├── SymbolNotFoundException.java
│ │ └── SymbolNotFoundMapper.java
│ ├── subresource/
│ │ ├── README.md
│ │ ├── pom.xml
│ │ └── src/
│ │ └── main/
│ │ └── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── example/
│ │ ├── Application.java
│ │ ├── Bowler.java
│ │ ├── Country.java
│ │ ├── Player.java
│ │ └── Team.java
│ ├── template/
│ │ ├── README.md
│ │ ├── pom.xml
│ │ └── src/
│ │ └── main/
│ │ ├── java/
│ │ │ └── org/
│ │ │ └── wso2/
│ │ │ └── msf4j/
│ │ │ └── example/
│ │ │ ├── Application.java
│ │ │ └── TemplateService.java
│ │ └── resources/
│ │ └── templates/
│ │ └── hello.mustache
│ └── websocket/
│ ├── README.md
│ └── chatApp/
│ ├── bundle/
│ │ ├── README.md
│ │ ├── pom.xml
│ │ └── src/
│ │ └── main/
│ │ └── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── sample/
│ │ └── websocket/
│ │ └── chatapp/
│ │ └── ChatAppEndpoint.java
│ ├── deployable-jar/
│ │ ├── pom.xml
│ │ └── src/
│ │ └── main/
│ │ └── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── sample/
│ │ └── websocket/
│ │ └── chatapp/
│ │ └── ChatAppEndpoint.java
│ ├── fatjar/
│ │ ├── pom.xml
│ │ └── src/
│ │ └── main/
│ │ └── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── sample/
│ │ └── websocket/
│ │ └── chatapp/
│ │ ├── Application.java
│ │ └── ChatAppEndpoint.java
│ └── js-client/
│ └── index.html
├── spring/
│ ├── deployment.yaml
│ ├── pom.xml
│ └── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── org/
│ │ │ └── wso2/
│ │ │ └── msf4j/
│ │ │ └── spring/
│ │ │ ├── MSF4JBeanDefinitionRegistryPostProcessor.java
│ │ │ ├── MSF4JSpringApplication.java
│ │ │ ├── MSF4JSpringConfiguration.java
│ │ │ ├── SpringConstants.java
│ │ │ ├── SpringMicroservicesRunner.java
│ │ │ ├── property/
│ │ │ │ └── YamlFileApplicationContextInitializer.java
│ │ │ └── transport/
│ │ │ ├── HTTPSTransportConfig.java
│ │ │ ├── HTTPTransportConfig.java
│ │ │ └── TransportConfig.java
│ │ └── resources/
│ │ └── log4j.xml
│ └── test/
│ ├── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── spring/
│ │ ├── ServerConfig.java
│ │ ├── SpringHttpServerTest.java
│ │ ├── SpringInterceptorTest.java
│ │ ├── exception/
│ │ │ ├── SpringTestExceptionMapper.java
│ │ │ └── SpringTestExceptionMapper2.java
│ │ └── service/
│ │ ├── SpringTestMicroservice.java
│ │ └── second/
│ │ ├── CustomService.java
│ │ ├── SecondService.java
│ │ └── TestMicroServiceWithDynamicPath.java
│ └── resources/
│ ├── cert.jks
│ ├── client.jks
│ ├── deployment.yaml
│ ├── netty-transports-1.yml
│ ├── netty-transports-2.yml
│ ├── testTxtFile.txt
│ └── testng.xml
├── swagger/
│ ├── deployment.yaml
│ ├── pom.xml
│ └── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── org/
│ │ │ └── wso2/
│ │ │ └── msf4j/
│ │ │ └── swagger/
│ │ │ ├── ExtendedSwaggerReader.java
│ │ │ ├── MSF4JBeanConfig.java
│ │ │ ├── SwaggerDefinitionService.java
│ │ │ └── internal/
│ │ │ ├── DataHolder.java
│ │ │ └── SwaggerDefinitionSC.java
│ │ └── resources/
│ │ └── META-INF/
│ │ └── services/
│ │ └── org.wso2.msf4j.SwaggerService
│ └── test/
│ ├── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── swagger/
│ │ └── SwaggerTest.java
│ └── resources/
│ ├── deployment.yaml
│ └── testng.xml
├── templating/
│ └── msf4j-mustache-template/
│ ├── pom.xml
│ └── src/
│ ├── main/
│ │ └── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── template/
│ │ └── MustacheTemplateEngine.java
│ └── test/
│ ├── java/
│ │ └── org/
│ │ └── wso2/
│ │ └── msf4j/
│ │ └── template/
│ │ └── MustacheTemplateEngineTest.java
│ └── resources/
│ └── templates/
│ ├── nomodel.mustache
│ └── withmodel.mustache
├── tests/
│ ├── osgi-tests/
│ │ ├── pom.xml
│ │ └── src/
│ │ └── test/
│ │ ├── java/
│ │ │ └── org/
│ │ │ └── wso2/
│ │ │ └── msf4j/
│ │ │ └── osgi/
│ │ │ └── test/
│ │ │ ├── MSF4JOSGiTest.java
│ │ │ └── service/
│ │ │ ├── SecondService.java
│ │ │ └── TestService.java
│ │ └── resources/
│ │ ├── carbon-home/
│ │ │ ├── conf/
│ │ │ │ ├── carbon.yml
│ │ │ │ ├── etc/
│ │ │ │ │ └── pax-logging.properties
│ │ │ │ ├── log4j2.xml
│ │ │ │ └── osgi/
│ │ │ │ └── launch.properties
│ │ │ └── deployment/
│ │ │ └── README.txt
│ │ └── testng.xml
│ ├── pom.xml
│ └── test-distribution/
│ ├── carbon-home/
│ │ └── conf/
│ │ └── deployment.yaml
│ ├── pom.xml
│ └── src/
│ └── assembly/
│ └── bin.xml
└── tooling/
├── LICENSE
├── README.md
├── features/
│ ├── org.wso2.developerstudio.msf4j.feature/
│ │ ├── build.properties
│ │ ├── feature.xml
│ │ └── pom.xml
│ └── pom.xml
├── plugins/
│ ├── org.wso2.developerstudio.msf4j.artifact/
│ │ ├── .gitignore
│ │ ├── META-INF/
│ │ │ └── MANIFEST.MF
│ │ ├── build.properties
│ │ ├── plugin.xml
│ │ ├── pom.xml
│ │ ├── project_wizard.xml
│ │ └── src/
│ │ └── org/
│ │ └── wso2/
│ │ └── developerstudio/
│ │ └── msf4j/
│ │ └── artifact/
│ │ ├── Activator.java
│ │ ├── generator/
│ │ │ └── SwaggerToJavaGenerator.java
│ │ ├── model/
│ │ │ └── MSF4JProjectModel.java
│ │ ├── project/
│ │ │ └── nature/
│ │ │ └── MSF4JArtifactProjectNature.java
│ │ ├── ui/
│ │ │ └── wizard/
│ │ │ ├── MSF4JPerspective.java
│ │ │ └── MSF4JProjectCreationWizard.java
│ │ ├── util/
│ │ │ ├── GeneratorUtils.java
│ │ │ ├── LibraryUtils.java
│ │ │ ├── MSF4JArtifactConstants.java
│ │ │ ├── MSF4JDependencyResolverJob.java
│ │ │ ├── MSF4JImageUtils.java
│ │ │ ├── MSF4JMavenDependencyResolverJob.java
│ │ │ └── MSF4JProjectImporter.java
│ │ └── validators/
│ │ └── MSF4JArtifactFieldController.java
│ └── pom.xml
├── pom.xml
├── repository/
│ ├── composite/
│ │ ├── category.xml
│ │ └── pom.xml
│ ├── main/
│ │ ├── category.xml
│ │ └── pom.xml
│ └── pom.xml
└── swagger-mustache/
├── 1.4/
│ ├── ApiException.mustache
│ ├── ApiOriginFilter.mustache
│ ├── ApiResponseMessage.mustache
│ ├── NotFoundException.mustache
│ ├── README.mustache
│ ├── api.mustache
│ ├── apiService.mustache
│ ├── apiServiceFactory.mustache
│ ├── apiServiceImpl.mustache
│ ├── bodyParams.mustache
│ ├── formParams.mustache
│ ├── generatedAnnotation.mustache
│ ├── headerParams.mustache
│ ├── model.mustache
│ ├── pathParams.mustache
│ ├── pom.mustache
│ ├── queryParams.mustache
│ ├── returnTypes.mustache
│ ├── serviceBodyParams.mustache
│ ├── serviceFormParams.mustache
│ ├── serviceHeaderParams.mustache
│ ├── servicePathParams.mustache
│ ├── serviceQueryParams.mustache
│ └── web.mustache
└── README.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
*.class
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
# Ignore everything in this directory
target
.classpath
.settings
.project
*.iml
*.iws
*.ipr
.idea
# Ignore dependency-reduced-pom.xml file created by Apache Maven Shade Plugin, see https://maven.apache.org/plugins/maven-shade-plugin/shade-mojo.html
dependency-reduced-pom.xml
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
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.
================================================
FILE: README.md
================================================
[Build status:](https://wso2.org/jenkins/job/products/job/msf4j/) 
# WSO2 Microservices Framework for Java (MSF4J)
WSO2 Microservices Framework for Java (MSF4J) is a lightweight high performance framework for developing
& running microservices.
WSO2 MSF4J is one of the highest performing lightweight Java microservices frameworks. The following graphs show the
throughput, memory consumption & latency characteristics of MSF4J against other microservices frameworks.

An echo service which accepts a 1KB request & echoes it back directly and using a temp file was developed for the respective
frameworks, and requests were sent for different concurrency values. The test was repeated for each concurrency value for each
framework and the average throughput was calculated.
Tests were run out of the box without any tuning on 32 core 64GB server in JVM v1.8.0_60 with default configuration.

Memory usage for each framework was observed after running the 1KB payload echo microservice on each framework &
sending a number of requests at different concurrency levels to each service.
The graph above shows the averaged out values after several runs for each framework.
Latency results was observed using the Apache bench provided percentile values. Results were plotted for
various concurrency levels the simple echo test.

Tests were run out of the box without any tuning on 32 core 64GB server in JVM v1.8.0_60 with default configuration.
More details about the performance test can found [here](perf-benchmark).
## Hello world with MSF4J
It is really easy to define & deploy a Java microservice using WSO2 MSF4J.
You simply need to annotate your service and deploy it using a single line of code.
Let's get started by writing a hello world MSF4J microservice.
You can use the [msf4j-microservice](archetypes) Maven [archetype](http://maven.apache.org/archetype/maven-archetype-plugin/generate-mojo.html)
to create your first MSF4J project.
Make sure you have JDK 1.8 and Maven 3.x installed, & run the following command.
```
mvn archetype:generate -DarchetypeGroupId=org.wso2.msf4j \
-DarchetypeArtifactId=msf4j-microservice -DarchetypeVersion=2.6.2 \
-DgroupId=org.example -DartifactId=Hello-Service -Dversion=0.1-SNAPSHOT \
-Dpackage=org.example.service -DserviceClass=HelloService
```
This will generate a project structure for you to quickly get started.
Next navigate to the Hello-Service directory. You will find a pom.xml file and also an src directory.
#### pom.xml
This pom file inherits from the msf4j-service/pom.xml. It provides a way of setting things up quickly with minimum
amount of
configuration. Click [here](poms/msf4j-service) for more information.
```xml
org.wso2.msf4jmsf4j-service2.6.24.0.0org.exampleHello-Service0.1-SNAPSHOTWSO2 MSF4J Microserviceorg.example.service.Application
```
You don't need to change anything in this pom.xml file.
#### HelloService.java
Change the org.example.service.HelloService class as follows to echo back the name input parameter.
You can remove the auto generated code and replace it with the following code segment:
```java
package org.example.service;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
@Path("/hello")
public class HelloService {
@GET
@Path("/{name}")
public String hello(@PathParam("name") String name) {
return "Hello " + name;
}
}
```
#### Application.java
This is the one-liner to deploy your service using WSO2 MSF4J.
```java
public class Application {
public static void main(String[] args) {
new MicroservicesRunner()
.deploy(new HelloService())
.start();
}
}
```
You can also pass in the port(s) as an argument to the MicroservicesRunner class constructor. When passing the port(s)
as an argument, by default it binds to 0.0.0.0 host. Use "msf4j.host" environment variable to override the host value.
### Build the Service
Run the following Maven command. This will create the fat jar **Hello-Service-0.1-SNAPSHOT.jar** in the **target** directory.
```
mvn package
```
This fat jar is a jar file that contains your microservice as well as all its dependencies.
### Run the Service
You just have to run the following command to get your service up and running.
```
java -jar target/Hello-Service-*.jar
```
### Test the Service with cURL
Run the following command or simply go to [http://localhost:8080/hello/wso2]
(http://localhost:8080/hello/wso2) from your browser.
```
curl http://localhost:8080/hello/wso2
```
You should see a response that prints "Hello wso2"
## Supported Annotations
In this section, we will look at the annotations used in MSF4J microservices. As you may have already noticed,
we support a subset of the JAXRS annotations.
### Class level annotations
##### @Path
Root path for resource methods. All the paths specified in the resource methods will be sub paths of this.
##### @Consumes
Default consume media type(s) for resource methods. The resource methods that do not specify @Consume annotation will
inherit this consume media type(s).
##### @Produces
Default produce media type(s) for resource methods. The resource methods that do not specify @Produce annotation will
inherit this produce media type(s).
### Method level annotations
##### @Path
Endpoint of the resource method relative to @Path of the container resource class.
##### @Consumes
Media type(s) that the method can consume. This overrides the class level @Consumes media types.
##### @Produces
Media type(s) that is produced by the method. This overrides the class level @Produces media types.
##### @GET
HTTP GET method. Specify that the resource method supports HTTP GET method.
##### @PUT
HTTP PUT method. Specify that the resource method supports HTTP PUT method.
##### @POST
HTTP POST method. Specify that the resource method supports HTTP POST method.
##### @DELETE
HTTP DELETE method. Specify that the resource method supports HTTP DELETE method.
##### @HEAD
HTTP HEAD method. Specify that the resource method supports HTTP HEAD method.
##### @OPTIONS
HTTP OPTIONS method. Specify that the resource method supports HTTP OPTIONS method.
### Parameter level annotations
##### @DefaultValue
Specify a default value for a resource method parameter. The value will be automatically converted to the
corresponding parameter's type.
##### @Context
Inject additional objects to a resource method. Currently supports injection of the following objects.
* org.wso2.msf4j.Request -
This object can be used to access properties of the HTTP request. The transport session (org.wso2.msf4j.Session)
can also be accessed via org.wso2.msf4j.Request#getSession().
See the [Session-aware service](samples/http-session) sample.
* org.wso2.msf4j.Response -
This object can be used to send HTTP responses. You can make responses more clean way by returning an instance of
javax.ws.rs.core.Response or a POJO. See the [StockQuote-Service]
(samples/stockquote/fatjar) sample.
* org.wso2.msf4j.HttpStreamer -
This object can be used to stream a chunked request body and process it while the request is streaming.
See the [FileServer](samples/fileserver) sample.
* org.wso2.msf4j.formparam.FormParamIterator -
This object can be used to stream a HTML form submission request body and process it while the request is streaming.
See the [FormParam](samples/formparam) sample.
##### @PathParam
/StockQuote/{symbol} to get value of symbol. The value will be automatically converted to the corresponding parameter
type and assigned to that parameter.
##### @QueryParam
/Students?age=18 to get value of age. The value will be automatically converted to the corresponding parameter type
and assigned to that parameter.
##### @HeaderParam
To read HTTP request header values. The value will be automatically converted to the corresponding parameter type and
assigned to that parameter.
##### @CookieParam
Extracts the value from the specified cookie, converts to the corresponding parameter type and assigns the value to
that parameter.
##### @FormParam
To support HTML form submission with application/x-www-form-urlencoded and multipart/form-data The value will be
automatically converted to the corresponding parameter type and assigned to that parameter
##### @FormDataParam
To support complex form submission with multipart/form-data content type. E.g file uploads and beans. The values will be
automatically converted to the corresponding parameter type and assigned to that parameter
### Lifecycle Callback Methods
Support following Java lifecycle callback method annotations.
##### @PostConstruct
Invoke by the container on newly constructed service instances after all dependency injection has completed and before transport starts.
##### @PreDestroy
Invoke by the container during server shutdown before the container removes the service instance.
For a detailed example, check out the lifecycle sample [here](https://github.com/wso2/msf4j/tree/master/samples/lifecycle).
## MSF4J Interceptors
Please do refer the following for complete instructions.
* [General instructions](/samples/interceptor/README.md)
* [MSF4J Interceptors - Stand alone mode instructions](/samples/interceptor/fatjar-interceptor-service/README.md)
* [MSF4J Interceptors - Deployable Jar mode instructions ](/samples/interceptor/deployable-jar-interceptor-service/README.md)
* [MSF4J Interceptors - OSGi mode instructions](/samples/interceptor/osgi-interceptor-service/README.md)
* [MSF4J Interceptors with MSF4J Spring - Fat Jar mode](/samples/interceptor/spring-fatjar-interceptor-service/README.md)
## Develop and configure MSF4J services using Spring framework
Spring is a popular Java application development framework which supports concepts like Dependency Injection(DI)
and Convention over Configuration. Spring support for MSF4J provides following features.
1. Develop MSF4J services as Spring beans
2. Develop and configure MSF4J components such as Interceptors and ExceptionMappers using Spring.
3. Use Annotation or XML based Spring configuration to configure internals of MSF4J framework such as ports, SSL etc.
Following example illustrates how to use Spring annotations together with MSF4J annotations to build a RESTful service. The main advantage here is service developers can consume Spring features such as dependency injection , Spring AOP etc. in the Spring way.
```java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
@Component
@Path("/greeting")
public class Hello {
@Autowired
private HelloService helloService;
@GET
public String message() {
return helloService.hello(" World");
}
}
```
For further details refer Spring [Helloworld sample](samples/spring-helloworld).
## Annotations for Analytics
In this section, we will look at the annotations available for analytics purposes MSF4J microservices. There are annotations
for Metrics and HTTP Monitoring.
You will need to configure [analytics](analytics) when you want to publish Metrics and HTTP Monitoring events to
WSO2 Data Analytics Server (DAS).
The Metrics data will be published to WSO2 DAS periodically. However the HTTP Monitoring events are published on each request.
For a detailed example, check out the [Metrics and HTTP Monitoring sample](samples/http-monitoring).
### Metrics Annotations
You can use the Metrics annnotations in your MSF4J microservices to understand how your microservices work in production.
There are three metrics annotations supported. Those are @Counted, @Metered and @Timed.
Each metric must have a unique name and the MSF4J will use the fully qualified method name as the metric name by default.
You can give a custom name by using the "name" parameter. This custom name will be appended to the fully qualified method name
with a dot character. You can set the "absolute" parameter to "true" if you want use only the given name as the metric name.
For example, see following table to understand how the final metric name is built by the Metrics runtime. Let's asssume that the
annotation is added to the "hello" method of "HelloService" shown above.
| Metrics Annotation | Metric Name |
| ------------------------------------------------ | --------------------------------------------------- |
| @Counted | org.example.service.HelloService.hello |
| @Counted(name = "helloCounter") | org.example.service.HelloService.hello.helloCounter |
| @Counted(name = "helloCounter", absolute = true) | helloCounter |
The Metrics annotations can be used at the Method level and Class level.
You can also configure a level in Metrics Annotations. For more information about Metric Levels,
see [WSO2 Carbon Metrics](https://github.com/wso2/carbon-metrics). In MSF4J, you can load the metrics level configuration
via the System Property named `metrics.level.conf`.
##### @Counted
Count the method invocations. There is a parameter named "monotonic" and it is set to false by default. This means that the
counter is decremented when the method returns. This is useful to count the current invocations of the annotated method.
Use `@Counted(monotonic = true)` when you want the counter to increase monotonically. This is useful to count the total invocations
of the annotated method
##### @Metered
Measure the rate of method invocations. This also keeps a count of the total invocations of the annotated method.
##### @Timed
Maintain a histogram of durations of each method invocation. This also measures the rate of method invocations and keeps a count of the
total invocations of the annotated method.
### HTTP Monitoring Annotation
You can use the annotation provided for HTTP Monitoring when you want to monitor each HTTP request and see the summary
in "HTTP Monitoring Dashboard".
##### @HTTPMonitored
Monitor each HTTP request. This annotation can be used at the Class level and the Method level.
### HTTP Message Tracing
MSF4J supports visual message tracing through user friendly dashboards in WSO2 DAS or Zipkin. MSF4J message tracing provides
a detailed insight to the complex microservices interactions in a system making monitoring, trouble shooting and optimization of
microservices very easy. Please check [WSO2 DAS Tracing](samples/message-tracing/das) and [Zipkin Tracing](samples/message-tracing/zipkin) samples for more details.
### Swagger Annotations
[Swagger](http://swagger.io/getting-started/) is a standard, language-agnostic interface to REST APIs which allows both
humans and computers to discover and understand the capabilities of the service without access to source code, documentation,
or through network traffic inspection.
MSF4J supports all [Swagger annotations](https://github.com/swagger-api/swagger-core/wiki/Annotations-1.5.X) out of the box.
To enable swagger support you need to add the following dependency to your project
```xml
org.wso2.msf4jmsf4j-swagger2.6.2
```
In order to retrieve Swagger definitions of your microservice, go to http://<host>:<port>/swagger?path=<service_base_path>.
e.g. [http://localhost:8080/swagger?path=/hello](http://localhost:8080/swagger?path=/hello)
To retrieve Swagger definitions of all microservices in your runtime, go to http://<host>:<port>/swagger.
e.g. [http://localhost:8080/swagger](http://localhost:8080/swagger)
NOTE: Even without any Swagger annotation, default Swagger definitions will be generated using the JAXRS annotation
in your MSF4J microservice.
The [StockQuote sample](samples/stockquote/fatjar) demonstrates Swagger annotations in action.
### ExceptionMapper
MSF4J supports [JAXRS ExceptionMapper](https://docs.oracle.com/javaee/7/api/javax/ws/rs/ext/ExceptionMapper.html)
which allows creation of custom responses when exceptions are thrown from MSF4J services.
The [StockQuote sample](samples/stockquote/fatjar) demonstrates ExceptionMapper in action.
The following code segment shows how ExceptionMappers are registered with the MSF4J runtime.
```java
new MicroservicesRunner().addExceptionMapper(new SymbolNotFoundMapper(), new DuplicateSymbolMapper());
```
### Circuit Breaker
Nygard's circuit breaker pattern is supported in MSF4J using the Netflix Hystrix library. For more details see the
[circuit breaker sample](samples/circuitbreaker)
### Complete Feature List
* Annotation based definition of microservices
* High performance Netty based transport
* WSO2 Developer Studio based tooling for microservices development starting from a Swagger API definition
* Generate Swagger definition using [Swagger annotations](https://github.com/swagger-api/swagger-core/wiki/Annotations-1.5.X)
* Ability to develop and Configure MSF4J services using Spring framework
* HTTP request & response streaming including support for javax.ws.rs.core.StreamingOutput.
* [ExceptionMapper]((https://docs.oracle.com/javaee/7/api/javax/ws/rs/ext/ExceptionMapper.html))
* Support for metrics & visualization of metrics using WSO2 Data Analytics Server (DAS) dashboards
* Message tracing with WSO2 DAS or Zipkin to get a detailed visual insight to the microservices interactions
* Supports circuit breaker using Netflix Hystrix.
* Support for securing microservices
* Integration with rendering engines such as Mustache
* Comprehensive samples demonstrating how to develop microservices based solutions
================================================
FILE: analytics/README.md
================================================
# WSO2 MSF4J - Analytics with WSO2 Data Analytics Server (DAS)
This directory contains the files related to publishing metrics to WSO2 Data Analytics Server (DAS)
Download WSO2 DAS
------------------------------------------
[Download](http://wso2.com/products/data-analytics-server/) WSO2 DAS and unpack it to some directory.
This will be the DAS_HOME directory.
Configure DAS
------------------------------------------
Run "das-setup/setup.sh" to setup DAS. Note that the DAS Home directory in the above step has to
be provided as an input to that script.
The setup script will also copy the already built MSF4J HTTP Monitoring Carbon App (CAPP) to DAS.
Start DAS
------------------------------------------
From DAS_HOME, run, bin/wso2server.sh to start DAS and make sure that it starts properly.
Run a sample that publishes data to DAS
------------------------------------------
Run the [HTTP Monitoring Sample](../samples/http-monitoring)
included in the distribution. This sample will publish data to DAS.
Accessing the dashboard
------------------------------------------
Go to [http://127.0.0.1:9763/monitoring/](http://127.0.0.1:9763/monitoring/). If everything works fine, you should
see the metrics & information related to your microservices on this dashboard. Please allow a few minutes for the
dashboard to be updated because the dashboard update batch task runs every few minutes.
For Advanced Users
------------------------------------------
If you are an advanced WSO2 DAS user, you can go to the DAS Management Console at
[https://localhost:9443/](https://localhost:9443/) and login with username/password admin/admin.
Once you login, you can view and manually execute the *http_event_script* in the console to immediately see
the results in the dashboard.
The sources for MSF4J HTTP Monitoring Carbon Application (CAPP) can be found inside "msf4j_http_monitoring_capp_source"
directory. This CAPP is already built and copied to WSO2 DAS when you Configure DAS as mentioned above.
================================================
FILE: analytics/das-setup/setup.sh
================================================
#!/bin/bash
# Copyright 2015 WSO2 Inc. (http://wso2.org)
#
# 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.
#
# ----------------------------------------------------------------------------
# A script for setting up DAS
# ----------------------------------------------------------------------------
set -e
config_dir=$(dirname "$0")
das_dir=""
function help {
echo ""
echo "Usage: "
echo "setup.sh -d "
echo ""
echo "-d: WSO2 Data Analytics Server (DAS) home directory"
echo ""
}
checkcommand () {
command -v $1 >/dev/null 2>&1 || { echo >&2 "Command $1 not found."; exit 1; }
}
while getopts "d:" opts
do
case $opts in
d)
das_dir=${OPTARG}
;;
\?)
help
exit 1
;;
esac
done
if [[ ! -d $das_dir ]]; then
echo "Please specify the WSO2 DAS Home."
help
exit 1
fi
checkcommand unzip
echo "Copying Carbon Apps to DAS."
mkdir -p $das_dir/repository/deployment/server/carbonapps
cp $config_dir/capps/*.car $das_dir/repository/deployment/server/carbonapps
echo "Setting up HTTP Monitoring Dashboard."
if [[ ! -d $das_dir/repository/deployment/server/jaggeryapps/monitoring ]]; then
mkdir -p $das_dir/repository/deployment/server/jaggeryapps/monitoring
unzip -q $config_dir/httpmon-dashboard/monitoring.zip -d $das_dir/repository/deployment/server/jaggeryapps/monitoring
fi
unzip -q -o $config_dir/httpmon-dashboard/modules.zip -d $das_dir/modules/
echo "Completed..."
================================================
FILE: analytics/msf4j-analytics/pom.xml
================================================
4.0.0org.wso2.msf4jmsf4j-parent2.8.14-SNAPSHOT../../poms/parent/pom.xmlmsf4j-analyticsbundleWSO2 MSF4J AnalyticsWSO2 MSF4J Analyticshttps://github.com/wso2/msf4jorg.wso2.msf4jmsf4j-coreorg.wso2.carbon.metricsorg.wso2.carbon.metrics.coreorg.wso2.carbon.metricsorg.wso2.carbon.metrics.jdbc.coreorg.wso2.carbon.metricsorg.wso2.carbon.metrics.das.coreorg.wso2.msf4jmsf4j-analytics-commonorg.wso2.carbon.configorg.wso2.carbon.config${carbon.config.version}org.testngtestngtestorg.apache.maven.pluginsmaven-compiler-pluginorg.apache.ratapache-rat-pluginorg.apache.maven.pluginsmaven-checkstyle-pluginorg.apache.maven.pluginsmaven-surefire-pluginorg.apache.maven.pluginsmaven-deploy-pluginorg.apache.felixmaven-bundle-pluginorg.wso2.carbon.configorg.wso2.carbon.config.maven.plugincoverageorg.apache.maven.pluginsmaven-surefire-plugin${argLine} -Xmx512morg.jacocojacoco-maven-pluginprepare-agentprepare-agentreportprepare-packagereportorg.jacocojacoco-maven-pluginreleaseorg.apache.maven.pluginsmaven-source-plugintrueattach-sourcespackagejar-no-forkorg.apache.maven.pluginsmaven-javadoc-plugintrue
http://docs.oracle.com/javaee/6/api/
*.internal.*
Licensed under the Apache License, Version 2.0]]>
attach-javadocpackagejarorg.apache.maven.pluginsmaven-gpg-plugin${gpg.passphrase}${gpg.useagent}signorg.apache.maven.pluginsmaven-source-pluginorg.apache.maven.pluginsmaven-javadoc-pluginorg.apache.maven.pluginsmaven-gpg-plugin
org.wso2.msf4j.analytics.*;version="${msf4j.version}"
javax.annotation.*,
org.slf4j.*;version="${slf4j.version.range}",
org.apache.commons.beanutils.*;version="${beanutils.version.range}",
org.osgi.framework.*;version="${osgi.framework.import.version.range}",
org.osgi.util.tracker; version="${osgi.service.tracker.import.version.range}",
org.wso2.carbon.utils.*;version="${carbon.utils.package.import.version.range}",
org.wso2.carbon.config.*;version="${carbon.config.package.import.version.range}",
org.wso2.carbon.metrics.core.*;version="${carbon.metrics.version.range}",
org.wso2.carbon.kernel.startupresolver.*;version="${carbon.kernel.version.range}",
org.wso2.msf4j.*,
org.wso2.msf4j.util.*,
javax.ws.rs.*,
osgi.service;objectClass="org.wso2.carbon.kernel.startupresolver.CapabilityProvider";capabilityName="org.wso2.msf4j.Interceptor"
================================================
FILE: analytics/msf4j-analytics/src/main/java/org/wso2/msf4j/analytics/AnalyticUtils.java
================================================
/*
* Copyright (c) 2017, WSO2 Inc. (http://wso2.com) All Rights Reserved.
*
* 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 org.wso2.msf4j.analytics;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wso2.carbon.config.ConfigProviderFactory;
import org.wso2.carbon.config.ConfigurationException;
import org.wso2.carbon.config.provider.ConfigProvider;
import org.wso2.msf4j.analytics.internal.DataHolder;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
/**
* Utils contains utility methods to use analytic purposes
*/
public class AnalyticUtils {
private static final Logger logger = LoggerFactory.getLogger(AnalyticUtils.class);
private static final String DEPLOYMENT_YAML_SYS_PROPERTY = "msf4j.conf";
private static final String DEPLOYMENT_YAML_FILE = "deployment.yaml";
/**
* Retrieve Configuration Provider Object to read analytic configurations
* @return configProvider object
*/
public static ConfigProvider getConfigurationProvider() {
ConfigProvider configProvider = DataHolder.getInstance().getConfigProvider();
if (configProvider == null) {
if (DataHolder.getInstance().getBundleContext() != null) {
throw new RuntimeException(
"Failed to populate HTTPMonitoringConfig Configuration. Config Provider is Null.");
}
//Standalone mode
String deploymentYamlPath = System.getProperty(DEPLOYMENT_YAML_SYS_PROPERTY);
if (deploymentYamlPath == null || deploymentYamlPath.isEmpty()) {
logger.info("System property '" + DEPLOYMENT_YAML_SYS_PROPERTY +
"' is not set. Default deployment.yaml file will be used.");
deploymentYamlPath = DEPLOYMENT_YAML_FILE;
try (InputStream configInputStream = AnalyticUtils.class.getClassLoader()
.getResourceAsStream(DEPLOYMENT_YAML_FILE)) {
if (configInputStream == null) {
throw new RuntimeException("Couldn't find " + deploymentYamlPath);
}
if (Files.notExists(Paths.get(deploymentYamlPath))) {
Files.copy(configInputStream, Paths.get(deploymentYamlPath));
}
} catch (IOException e) {
throw new RuntimeException("Couldn't read configuration from file " + deploymentYamlPath, e);
}
} else if (!Files.exists(Paths.get(deploymentYamlPath))) {
throw new RuntimeException("Couldn't find " + deploymentYamlPath);
}
try {
configProvider = ConfigProviderFactory.getConfigProvider(Paths.get(deploymentYamlPath), null);
DataHolder.getInstance().setConfigProvider(configProvider);
} catch (ConfigurationException e) {
throw new RuntimeException("Error loading deployment.yaml Configuration", e);
}
}
return configProvider;
}
}
================================================
FILE: analytics/msf4j-analytics/src/main/java/org/wso2/msf4j/analytics/httpmonitoring/HTTPMonitored.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://wso2.com) All Rights Reserved.
*
* 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 org.wso2.msf4j.analytics.httpmonitoring;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Monitor HTTP Requests.
*/
@Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
public @interface HTTPMonitored {
boolean tracing() default false;
}
================================================
FILE: analytics/msf4j-analytics/src/main/java/org/wso2/msf4j/analytics/httpmonitoring/HTTPMonitoringDataPublisher.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://wso2.com) All Rights Reserved.
*
* 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 org.wso2.msf4j.analytics.httpmonitoring;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wso2.carbon.databridge.agent.AgentHolder;
import org.wso2.carbon.databridge.agent.DataPublisher;
import org.wso2.carbon.databridge.agent.exception.DataEndpointAgentConfigurationException;
import org.wso2.carbon.databridge.agent.exception.DataEndpointAuthenticationException;
import org.wso2.carbon.databridge.agent.exception.DataEndpointConfigurationException;
import org.wso2.carbon.databridge.agent.exception.DataEndpointException;
import org.wso2.carbon.databridge.commons.Event;
import org.wso2.carbon.databridge.commons.exception.TransportException;
import org.wso2.carbon.databridge.commons.utils.DataBridgeCommonsUtils;
import org.wso2.msf4j.analytics.httpmonitoring.config.model.DasConfig;
import org.wso2.msf4j.util.SystemVariableUtil;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.Map;
/**
* A utility class to initialize/destroy HTTP Monitoring Data Publisher for DAS.
*/
public final class HTTPMonitoringDataPublisher {
private static final Logger logger = LoggerFactory.getLogger(HTTPMonitoringDataPublisher.class);
private static final String HTTP_MONITORING_STREAM = "org.wso2.msf4j.analytics.httpmonitoring";
private static final String VERSION = "1.0.0";
private static final String HTTP_MONITORING_STREAM_ID;
private static final String SERVER_HOST_ADDRESS;
private static final String SERVER_HOSTNAME;
private static final String MICROSERVICE = "Microservice";
private DataPublisher dataPublisher;
private Map arbitraryAttributes;
static {
HTTP_MONITORING_STREAM_ID = DataBridgeCommonsUtils.generateStreamId(HTTP_MONITORING_STREAM, VERSION);
try {
InetAddress localAddress = getLocalAddress();
SERVER_HOST_ADDRESS = localAddress.getHostAddress();
SERVER_HOSTNAME = localAddress.getHostName();
} catch (SocketException | UnknownHostException e) {
throw new IllegalStateException("Cannot determine server host address", e);
}
}
public HTTPMonitoringDataPublisher(DasConfig dasConfig) {
init(dasConfig);
// Destroy data publisher at shutdown
Thread thread = new Thread(this::destroy);
Runtime.getRuntime().addShutdownHook(thread);
}
private static InetAddress getLocalAddress() throws SocketException, UnknownHostException {
Enumeration interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface iface = interfaces.nextElement();
Enumeration addresses = iface.getInetAddresses();
if (iface.isUp()) {
while (addresses.hasMoreElements()) {
InetAddress addr = addresses.nextElement();
if (addr instanceof Inet4Address && !addr.isLoopbackAddress()) {
return addr;
}
}
}
}
return InetAddress.getLocalHost();
}
private void init(DasConfig dasConfig) {
if (logger.isInfoEnabled()) {
logger.info("Initializing HTTP Monitoring Data Publisher");
}
String type = dasConfig.getType();
String receiverURL = dasConfig.getReceiverURL();
String authURL = dasConfig.getAuthURL();
String username = dasConfig.getUsername();
String password = dasConfig.getPassword();
String dataAgentConfigPath = dasConfig.getDataAgentConfigPath();
if (type == null) {
throw new IllegalArgumentException("Type cannot be null");
}
if (receiverURL == null) {
throw new IllegalArgumentException("Data Receiver URL cannot be null");
}
if (username == null) {
throw new IllegalArgumentException("Username cannot be null");
}
if (password == null) {
throw new IllegalArgumentException("Password cannot be null");
}
if (dataAgentConfigPath == null) {
throw new IllegalArgumentException("Data Agent Configuration Path cannot be null");
}
AgentHolder.setConfigPath(dataAgentConfigPath);
arbitraryAttributes = SystemVariableUtil.getArbitraryAttributes();
try {
dataPublisher = new DataPublisher(type, receiverURL, authURL, username, password);
} catch (DataEndpointAgentConfigurationException | DataEndpointException | DataEndpointConfigurationException
| DataEndpointAuthenticationException | TransportException e) {
throw new IllegalStateException("Error when initializing the Data Publisher", e);
}
}
private void destroy() {
if (dataPublisher != null) {
try {
dataPublisher.shutdownWithAgent();
} catch (DataEndpointException e) {
logger.error("Error shutting down the data publisher with agent", e);
} finally {
dataPublisher = null;
}
}
}
public void publishEvent(HTTPMonitoringEvent httpMonitoringEvent) {
Object[] meta = new Object[4];
meta[0] = httpMonitoringEvent.getTimestamp();
meta[1] = SERVER_HOST_ADDRESS;
meta[2] = SERVER_HOSTNAME;
meta[3] = MICROSERVICE;
Object[] correlation = new Object[2];
correlation[0] = httpMonitoringEvent.getActivityId();
correlation[1] = httpMonitoringEvent.getParentRequest();
Object[] payload = new Object[11];
payload[0] = httpMonitoringEvent.getServiceClass();
payload[1] = httpMonitoringEvent.getServiceName();
payload[2] = httpMonitoringEvent.getServiceMethod();
payload[3] = httpMonitoringEvent.getRequestUri();
payload[4] = httpMonitoringEvent.getServiceContext();
payload[5] = httpMonitoringEvent.getHttpMethod();
payload[6] = httpMonitoringEvent.getContentType();
payload[7] = httpMonitoringEvent.getRequestSizeBytes();
payload[8] = httpMonitoringEvent.getReferrer();
payload[9] = httpMonitoringEvent.getResponseHttpStatusCode();
payload[10] = httpMonitoringEvent.getResponseTime();
Event event = new Event(HTTP_MONITORING_STREAM_ID, httpMonitoringEvent.getTimestamp(), meta, correlation,
payload, arbitraryAttributes);
dataPublisher.publish(event);
}
}
================================================
FILE: analytics/msf4j-analytics/src/main/java/org/wso2/msf4j/analytics/httpmonitoring/HTTPMonitoringEvent.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://wso2.com) All Rights Reserved.
*
* 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 org.wso2.msf4j.analytics.httpmonitoring;
/**
* Monitoring Event.
*/
public class HTTPMonitoringEvent {
private long timestamp;
private String serverName;
private String serverAddress;
private long startNanoTime;
private String serviceClass;
private String serviceName;
private String serviceContext;
private String serviceMethod;
private String requestUri;
private String httpMethod;
private String contentType;
private Integer responseHttpStatusCode;
private String referrer;
private long responseTime;
private long requestSizeBytes;
private String activityId;
private String parentRequest;
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public String getServerName() {
return serverName;
}
public void setServerName(String serverName) {
this.serverName = serverName;
}
public String getServerAddress() {
return serverAddress;
}
public void setServerAddress(String serverAddress) {
this.serverAddress = serverAddress;
}
public long getStartNanoTime() {
return startNanoTime;
}
public void setStartNanoTime(long startNanoTime) {
this.startNanoTime = startNanoTime;
}
public String getServiceClass() {
return serviceClass;
}
public void setServiceClass(String serviceClass) {
this.serviceClass = serviceClass;
}
public String getServiceName() {
return serviceName;
}
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
public String getServiceContext() {
return serviceContext;
}
public void setServiceContext(String serviceContext) {
this.serviceContext = serviceContext;
}
public String getServiceMethod() {
return serviceMethod;
}
public void setServiceMethod(String serviceMethod) {
this.serviceMethod = serviceMethod;
}
public String getRequestUri() {
return requestUri;
}
public void setRequestUri(String requestUri) {
this.requestUri = requestUri;
}
public String getHttpMethod() {
return httpMethod;
}
public void setHttpMethod(String httpMethod) {
this.httpMethod = httpMethod;
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public Integer getResponseHttpStatusCode() {
return responseHttpStatusCode;
}
public void setResponseHttpStatusCode(Integer responseHttpStatusCode) {
this.responseHttpStatusCode = responseHttpStatusCode;
}
public String getReferrer() {
return referrer;
}
public void setReferrer(String referrer) {
this.referrer = referrer;
}
public long getResponseTime() {
return responseTime;
}
public void setResponseTime(long responseTime) {
this.responseTime = responseTime;
}
public long getRequestSizeBytes() {
return requestSizeBytes;
}
public void setRequestSizeBytes(long requestSizeBytes) {
this.requestSizeBytes = requestSizeBytes;
}
public String getActivityId() {
return activityId;
}
public void setActivityId(String activityId) {
this.activityId = activityId;
}
public String getParentRequest() {
return parentRequest;
}
public void setParentRequest(String parentRequest) {
this.parentRequest = parentRequest;
}
}
================================================
FILE: analytics/msf4j-analytics/src/main/java/org/wso2/msf4j/analytics/httpmonitoring/HTTPMonitoringInterceptor.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://wso2.com) All Rights Reserved.
*
* 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 org.wso2.msf4j.analytics.httpmonitoring;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wso2.msf4j.Interceptor;
import org.wso2.msf4j.Request;
import org.wso2.msf4j.Response;
import org.wso2.msf4j.ServiceMethodInfo;
import org.wso2.msf4j.analytics.httpmonitoring.config.HTTPMonitoringConfigBuilder;
import org.wso2.msf4j.analytics.httpmonitoring.config.model.HTTPMonitoringConfig;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import javax.ws.rs.Path;
import javax.ws.rs.core.HttpHeaders;
/**
* Monitor HTTP Requests for methods with {@link HTTPMonitored} annotations.
*/
public class HTTPMonitoringInterceptor implements Interceptor {
private static final Logger logger = LoggerFactory.getLogger(HTTPMonitoringInterceptor.class);
public static final String REFERER = "Referer";
private Map map = new ConcurrentHashMap<>();
private final boolean enabled;
private final HTTPMonitoringDataPublisher httpMonitoringDataPublisher;
public HTTPMonitoringInterceptor() {
if (logger.isDebugEnabled()) {
logger.debug("Creating HTTP Monitoring Interceptor");
}
HTTPMonitoringConfig httpMonitoringConfig = HTTPMonitoringConfigBuilder.build();
enabled = httpMonitoringConfig.isEnabled();
httpMonitoringDataPublisher = enabled ? new HTTPMonitoringDataPublisher(httpMonitoringConfig.getDas()) :
null;
}
/**
* Returns the final annotation that is application to the given method. For example,
* the {@link HTTPMonitored} annotation can be mentioned in class level, and also in
* the target method, but the method only have tracing enabled. Then we should get the
* setting as tracing is disabled for that specific method.
*/
private HTTPMonitored extractFinalAnnotation(Method method) {
HTTPMonitored httpMon = method.getAnnotation(HTTPMonitored.class);
if (httpMon == null) {
httpMon = method.getDeclaringClass().getAnnotation(HTTPMonitored.class);
}
return httpMon;
}
@Override
public boolean preCall(Request request, Response responder, ServiceMethodInfo serviceMethodInfo) throws Exception {
if (!enabled) {
return true;
}
Method method = serviceMethodInfo.getMethod();
MethodInterceptor methodInterceptor = map.get(method);
if (methodInterceptor == null || !methodInterceptor.annotationScanned) {
HTTPMonitored httpMon = extractFinalAnnotation(method);
Interceptor interceptor = null;
if (httpMon != null) {
interceptor = new HTTPInterceptor(httpMon.tracing());
}
methodInterceptor = new MethodInterceptor(true, interceptor);
map.put(method, methodInterceptor);
}
return methodInterceptor.preCall(request, responder, serviceMethodInfo);
}
@Override
public void postCall(Request request, int status, ServiceMethodInfo serviceMethodInfo) throws Exception {
if (!enabled) {
return;
}
Method method = serviceMethodInfo.getMethod();
MethodInterceptor methodInterceptor = map.get(method);
if (methodInterceptor != null) {
methodInterceptor.postCall(request, status, serviceMethodInfo);
}
}
private static class MethodInterceptor implements Interceptor {
private final boolean annotationScanned;
private final Interceptor interceptor;
MethodInterceptor(boolean annotationScanned, Interceptor interceptor) {
this.annotationScanned = annotationScanned;
this.interceptor = interceptor;
}
@Override
public boolean preCall(Request request, Response responder, ServiceMethodInfo serviceMethodInfo)
throws Exception {
if (interceptor != null) {
return interceptor.preCall(request, responder, serviceMethodInfo);
}
return true;
}
@Override
public void postCall(Request request, int status, ServiceMethodInfo serviceMethodInfo) throws Exception {
if (interceptor != null) {
interceptor.postCall(request, status, serviceMethodInfo);
}
}
}
private class HTTPInterceptor implements Interceptor {
private static final String DEFAULT_TRACE_ID = "DEFAULT";
private static final String DEFAULT_PARENT_REQUEST = "DEFAULT";
private static final String MONITORING_EVENT = "MONITORING_EVENT";
private static final String ACTIVITY_ID = "activity-id";
private static final String PARENT_REQUEST = "parent-request";
private String serviceClass;
private String serviceName;
private String serviceMethod;
private String servicePath;
private boolean tracing;
private HTTPInterceptor(boolean tracing) {
this.tracing = tracing;
}
boolean isTracing() {
return tracing;
}
private String generateTraceId() {
return UUID.randomUUID().toString();
}
private void handleTracing(Request request, HTTPMonitoringEvent httpMonitoringEvent) {
String traceId, parentRequest;
if (this.isTracing()) {
traceId = request.getHeader(ACTIVITY_ID);
if (traceId == null) {
traceId = this.generateTraceId();
}
parentRequest = request.getHeader(PARENT_REQUEST);
} else {
traceId = DEFAULT_TRACE_ID;
parentRequest = DEFAULT_PARENT_REQUEST;
}
httpMonitoringEvent.setActivityId(traceId);
httpMonitoringEvent.setParentRequest(parentRequest);
}
@Override
public boolean preCall(Request request, Response responder, ServiceMethodInfo serviceMethodInfo) {
HTTPMonitoringEvent httpMonitoringEvent = new HTTPMonitoringEvent();
httpMonitoringEvent.setTimestamp(System.currentTimeMillis());
httpMonitoringEvent.setStartNanoTime(System.nanoTime());
if (serviceClass == null) {
Method method = serviceMethodInfo.getMethod();
Class> serviceClass = method.getDeclaringClass();
this.serviceClass = serviceClass.getName();
serviceName = serviceClass.getSimpleName();
serviceMethod = method.getName();
if (serviceClass.isAnnotationPresent(Path.class)) {
Path path = serviceClass.getAnnotation(Path.class);
servicePath = path.value();
}
}
httpMonitoringEvent.setServiceClass(serviceClass);
httpMonitoringEvent.setServiceName(serviceName);
httpMonitoringEvent.setServiceMethod(serviceMethod);
httpMonitoringEvent.setRequestUri(request.getUri());
httpMonitoringEvent.setServiceContext(servicePath);
HttpHeaders httpHeaders = request.getHeaders();
httpMonitoringEvent.setHttpMethod(request.getHttpMethod());
httpMonitoringEvent.setContentType(httpHeaders.getHeaderString(HttpHeaders.CONTENT_TYPE));
String contentLength = httpHeaders.getHeaderString(HttpHeaders.CONTENT_LENGTH);
if (contentLength != null) {
httpMonitoringEvent.setRequestSizeBytes(Long.parseLong(contentLength));
}
httpMonitoringEvent.setReferrer(httpHeaders.getHeaderString(REFERER));
this.handleTracing(request, httpMonitoringEvent);
serviceMethodInfo.setAttribute(MONITORING_EVENT, httpMonitoringEvent);
return true;
}
@Override
public void postCall(Request request, int status, ServiceMethodInfo serviceMethodInfo) {
HTTPMonitoringEvent httpMonitoringEvent =
(HTTPMonitoringEvent) serviceMethodInfo.getAttribute(MONITORING_EVENT);
httpMonitoringEvent.setResponseTime(
TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - httpMonitoringEvent.getStartNanoTime()));
httpMonitoringEvent.setResponseHttpStatusCode(status);
httpMonitoringDataPublisher.publishEvent(httpMonitoringEvent);
}
}
}
================================================
FILE: analytics/msf4j-analytics/src/main/java/org/wso2/msf4j/analytics/httpmonitoring/config/HTTPMonitoringConfigBuilder.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://wso2.com) All Rights Reserved.
*
* 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 org.wso2.msf4j.analytics.httpmonitoring.config;
import org.wso2.carbon.config.ConfigurationException;
import org.wso2.carbon.config.provider.ConfigProvider;
import org.wso2.msf4j.analytics.AnalyticUtils;
import org.wso2.msf4j.analytics.httpmonitoring.config.model.HTTPMonitoringConfig;
/**
* Build {@link HTTPMonitoringConfig} from the YAML file
*/
public final class HTTPMonitoringConfigBuilder {
public static HTTPMonitoringConfig build() {
HTTPMonitoringConfig configurationObject;
ConfigProvider configProvider = AnalyticUtils.getConfigurationProvider();
try {
configurationObject =
configProvider.getConfigurationObject(HTTPMonitoringConfig.class);
} catch (ConfigurationException e) {
throw new RuntimeException(
"Error while loading " + HTTPMonitoringConfig.class.getName() + " from config provider", e);
}
return configurationObject;
}
}
================================================
FILE: analytics/msf4j-analytics/src/main/java/org/wso2/msf4j/analytics/httpmonitoring/config/model/DasConfig.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://wso2.com) All Rights Reserved.
*
* 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 org.wso2.msf4j.analytics.httpmonitoring.config.model;
import org.wso2.carbon.config.annotation.Configuration;
import org.wso2.carbon.config.annotation.Element;
import org.wso2.carbon.config.annotation.Ignore;
/**
* Configuration for connecting with Data Analytics Server (DAS)
*/
@Configuration(description = "DAS configuration")
public class DasConfig {
@Element(description = "The type used with Data Publisher")
private String type = "thrift";
@Element(description = "Data Receiver URL used by the Data Publisher")
private String receiverURL = "tcp://localhost:7611";
@Ignore
private String authURL;
private String username = "admin";
private String password = "admin";
@Element(description = "The path for Data Bridge Agent configuration")
private String dataAgentConfigPath = "data-agent-config.xml";
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getReceiverURL() {
return receiverURL;
}
public void setReceiverURL(String receiverURL) {
this.receiverURL = receiverURL;
}
public String getAuthURL() {
return authURL;
}
public void setAuthURL(String authURL) {
this.authURL = authURL;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getDataAgentConfigPath() {
return dataAgentConfigPath;
}
public void setDataAgentConfigPath(String dataAgentConfigPath) {
this.dataAgentConfigPath = dataAgentConfigPath;
}
}
================================================
FILE: analytics/msf4j-analytics/src/main/java/org/wso2/msf4j/analytics/httpmonitoring/config/model/HTTPMonitoringConfig.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://wso2.com) All Rights Reserved.
*
* 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 org.wso2.msf4j.analytics.httpmonitoring.config.model;
import org.wso2.carbon.config.annotation.Configuration;
import org.wso2.carbon.config.annotation.Element;
/**
* Configuration for HTTP Monitoring
*/
@Configuration(namespace = "wso2.msf4j.analytics.configuration", description = "MSF4J Analytics configuration")
public class HTTPMonitoringConfig {
@Element(description = "Whether HTTP Monitoring is enables or not")
private boolean enabled = false;
@Element(description = "Configuration for DAS")
private DasConfig das = new DasConfig();
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public DasConfig getDas() {
return das;
}
public void setDas(DasConfig das) {
this.das = das;
}
}
================================================
FILE: analytics/msf4j-analytics/src/main/java/org/wso2/msf4j/analytics/internal/AnalyticsSC.java
================================================
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* 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 org.wso2.msf4j.analytics.internal;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.wso2.carbon.config.provider.ConfigProvider;
import org.wso2.msf4j.Interceptor;
import org.wso2.msf4j.analytics.httpmonitoring.HTTPMonitoringInterceptor;
/**
*
* Bundle Activator for msf4j-analytics bundle.
*/
@Component(
name = "org.wso2.msf4j.analytics.httpmonitoringsc",
immediate = true,
property = {
"componentName=msf4j-analytics-sc"
}
)
public class AnalyticsSC {
@Reference(
name = "carbon-config",
service = ConfigProvider.class,
cardinality = ReferenceCardinality.MANDATORY,
policy = ReferencePolicy.DYNAMIC,
unbind = "unregisterConfigProvider"
)
protected void registerConfigProvider(ConfigProvider configProvider) {
DataHolder.getInstance().setConfigProvider(configProvider);
}
protected void unregisterConfigProvider(ConfigProvider configProvider) {
DataHolder.getInstance().setConfigProvider(null);
}
@Activate
protected void activate(BundleContext bundleContext) {
DataHolder.getInstance().setBundleContext(bundleContext);
bundleContext.registerService(Interceptor.class, new HTTPMonitoringInterceptor(), null);
}
@Deactivate
public void stop(BundleContext bundleContext) throws Exception {
DataHolder.getInstance().setBundleContext(null);
}
}
================================================
FILE: analytics/msf4j-analytics/src/main/java/org/wso2/msf4j/analytics/internal/DataHolder.java
================================================
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* 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 org.wso2.msf4j.analytics.internal;
import org.osgi.framework.BundleContext;
import org.wso2.carbon.config.provider.ConfigProvider;
/**
* Data holder for analytics bundle.
*/
public class DataHolder {
private static final DataHolder instance = new DataHolder();
private ConfigProvider configProvider;
public ConfigProvider getConfigProvider() {
return configProvider;
}
public void setConfigProvider(ConfigProvider configProvider) {
this.configProvider = configProvider;
}
public BundleContext getBundleContext() {
return bundleContext;
}
public void setBundleContext(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
private BundleContext bundleContext;
public static DataHolder getInstance() {
return instance;
}
}
================================================
FILE: analytics/msf4j-analytics/src/main/java/org/wso2/msf4j/analytics/internal/InterceptorCapabilityProvider.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you 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 org.wso2.msf4j.analytics.internal;
import org.osgi.service.component.annotations.Component;
import org.wso2.carbon.kernel.startupresolver.CapabilityProvider;
/**
* This class signals Startup Order Resolver module in kernel that this bundle provides
* two services of type {@code Interceptor}
*/
@Component(
name = "org.wso2.msf4j.analytics.internal.InterceptorCapabilityProvider",
immediate = true,
property = "capabilityName=org.wso2.msf4j.Interceptor"
)
public class InterceptorCapabilityProvider implements CapabilityProvider {
/**
* Returns the count of {@code Interceptor} OSGi services registered by this bundle.
*
* This bundle registers two Interceptors
* 1. {@code HTTPMonitoringInterceptor}
* 2. {@code MetricsInterceptor}
*
* But here we return count as one, due to a bug in the startup launcher in Kernel.
*
* @return count of {@code Interceptor} services registered by this bundle.
*/
@Override
public int getCount() {
return 2;
}
}
================================================
FILE: analytics/msf4j-analytics/src/main/java/org/wso2/msf4j/analytics/metrics/Metrics.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://wso2.com) All Rights Reserved.
*
* 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 org.wso2.msf4j.analytics.metrics;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wso2.carbon.metrics.core.MetricManagementService;
import org.wso2.carbon.metrics.core.MetricService;
import org.wso2.msf4j.analytics.AnalyticUtils;
/**
* A utility class to keep Metric Services.
*/
public final class Metrics {
private static final Logger logger = LoggerFactory.getLogger(Metrics.class);
private volatile MetricService metricService;
private volatile MetricManagementService metricManagementService;
private Metrics() {
}
/**
* Initializes the Metrics instance
*/
private static class MetricsHolder {
private static final Metrics INSTANCE = new Metrics();
}
/**
* This returns the Metrics singleton instance.
*
* @return The Metrics instance
*/
public static Metrics getInstance() {
return MetricsHolder.INSTANCE;
}
/**
* Initialize metric services
*/
private void initializeServices() {
if (logger.isInfoEnabled()) {
logger.info("Initializing Metrics Services");
}
org.wso2.carbon.metrics.core.Metrics metrics =
new org.wso2.carbon.metrics.core.Metrics(AnalyticUtils.getConfigurationProvider());
// Activate metrics
metrics.activate();
metricService = metrics.getMetricService();
metricManagementService = metrics.getMetricManagementService();
// Deactivate Metrics at shutdown
Thread thread = new Thread(() -> metrics.deactivate());
Runtime.getRuntime().addShutdownHook(thread);
}
/**
* Returns the {@link MetricService}
*
* @return The {@link MetricService} instance
*/
public MetricService getMetricService() {
if (metricService == null) {
synchronized (this) {
if (metricService == null) {
initializeServices();
}
}
}
return metricService;
}
/**
* Set the {@link MetricService} service
*
* @param metricService The {@link MetricService} reference
*/
void setMetricService(MetricService metricService) {
this.metricService = metricService;
}
/**
* Returns the {@link MetricManagementService}
*
* @return The {@link MetricManagementService} instance
*/
public MetricManagementService getMetricManagementService() {
if (metricManagementService == null) {
synchronized (this) {
if (metricManagementService == null) {
initializeServices();
}
}
}
return metricManagementService;
}
/**
* Set the {@link MetricManagementService} service
*
* @param metricManagementService The {@link MetricManagementService} reference
*/
void setMetricManagementService(MetricManagementService metricManagementService) {
this.metricManagementService = metricManagementService;
}
}
================================================
FILE: analytics/msf4j-analytics/src/main/java/org/wso2/msf4j/analytics/metrics/MetricsComponent.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://wso2.com) All Rights Reserved.
*
* 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 org.wso2.msf4j.analytics.metrics;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wso2.carbon.metrics.core.MetricManagementService;
import org.wso2.carbon.metrics.core.MetricService;
/**
* Metrics OSGi Component to Initialize/Destroy Metrics.
*/
@Component(name = "org.wso2.msf4j.analytics.metrics.MetricsComponent")
public class MetricsComponent {
private static final Logger logger = LoggerFactory.getLogger(MetricsComponent.class);
/**
* This is the activation method of MetricsComponent. This will be called when its references are
* satisfied.
*/
@Activate
protected void activate() {
if (logger.isInfoEnabled()) {
logger.info("Metrics Component is activated");
}
}
/**
* This is the deactivation method of MetricsComponent.
*/
@Deactivate
protected void deactivate() {
if (logger.isInfoEnabled()) {
logger.info("Metrics Component is deactivated");
}
}
/**
* This bind method will be called when {@link MetricService} is registered.
*
* @param metricService The {@link MetricService} instance registered as an OSGi service
*/
@Reference(
name = "carbon.metrics.service",
service = MetricService.class,
cardinality = ReferenceCardinality.MANDATORY,
policy = ReferencePolicy.DYNAMIC,
unbind = "unsetMetricService"
)
protected void setMetricService(MetricService metricService) {
if (logger.isDebugEnabled()) {
logger.debug("Setting MetricService reference");
}
Metrics.getInstance().setMetricService(metricService);
}
/**
* This is the unbind method which gets called at the un-registration of {@link MetricService}
*
* @param metricService The {@link MetricService} instance registered as an OSGi service
*/
protected void unsetMetricService(MetricService metricService) {
Metrics.getInstance().setMetricService(null);
}
/**
* This bind method will be called when {@link MetricManagementService} is registered.
*
* @param metricManagementService The {@link MetricManagementService} instance registered as an OSGi service
*/
@Reference(
name = "carbon.metrics.management.service",
service = MetricManagementService.class,
cardinality = ReferenceCardinality.MANDATORY,
policy = ReferencePolicy.DYNAMIC,
unbind = "unsetMetricManagementService"
)
protected void setMetricManagementService(MetricManagementService metricManagementService) {
if (logger.isDebugEnabled()) {
logger.debug("Setting MetricManagementService reference");
}
Metrics.getInstance().setMetricManagementService(metricManagementService);
}
/**
* This is the unbind method which gets called at the un-registration of {@link MetricManagementService}
*
* @param metricManagementService The {@link MetricManagementService} instance registered as an OSGi service
*/
protected void unsetMetricManagementService(MetricManagementService metricManagementService) {
Metrics.getInstance().setMetricManagementService(null);
}
}
================================================
FILE: analytics/msf4j-analytics/src/main/java/org/wso2/msf4j/analytics/metrics/MetricsInterceptor.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://wso2.com) All Rights Reserved.
*
* 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 org.wso2.msf4j.analytics.metrics;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wso2.carbon.metrics.core.Counter;
import org.wso2.carbon.metrics.core.Meter;
import org.wso2.carbon.metrics.core.MetricAnnotation;
import org.wso2.carbon.metrics.core.Timer;
import org.wso2.carbon.metrics.core.annotation.Counted;
import org.wso2.carbon.metrics.core.annotation.Metered;
import org.wso2.carbon.metrics.core.annotation.Timed;
import org.wso2.msf4j.Interceptor;
import org.wso2.msf4j.Request;
import org.wso2.msf4j.Response;
import org.wso2.msf4j.ServiceMethodInfo;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Collecting Metrics via annotations.
*/
@Component(
name = "org.wso2.msf4j.analytics.metrics.MetricsInterceptor",
service = Interceptor.class
)
public class MetricsInterceptor implements Interceptor {
private static final Logger logger = LoggerFactory.getLogger(MetricsInterceptor.class);
private Map map = new ConcurrentHashMap<>();
public MetricsInterceptor() {
if (logger.isDebugEnabled()) {
logger.debug("Creating Metrics Interceptor");
}
}
private Timed getTimedAnnotation(Method method) {
Timed annotation = method.getAnnotation(Timed.class);
if (annotation == null) {
annotation = method.getDeclaringClass().getAnnotation(Timed.class);
}
return annotation;
}
private Metered getMeteredAnnotation(Method method) {
Metered annotation = method.getAnnotation(Metered.class);
if (annotation == null) {
annotation = method.getDeclaringClass().getAnnotation(Metered.class);
}
return annotation;
}
private Counted getCountedAnnotation(Method method) {
Counted annotation = method.getAnnotation(Counted.class);
if (annotation == null) {
annotation = method.getDeclaringClass().getAnnotation(Counted.class);
}
return annotation;
}
@Override
public boolean preCall(Request request, Response responder, ServiceMethodInfo serviceMethodInfo) throws Exception {
Method method = serviceMethodInfo.getMethod();
MethodInterceptors methodInterceptors = map.get(method);
if (methodInterceptors == null || !methodInterceptors.annotationScanned) {
List interceptors = new CopyOnWriteArrayList<>();
Timed timed = getTimedAnnotation(method);
if (timed != null) {
Timer timer = MetricAnnotation.timer(Metrics.getInstance().getMetricService(), timed, method);
Interceptor interceptor = new TimerInterceptor(timer);
interceptors.add(interceptor);
}
Metered metered = getMeteredAnnotation(method);
if (metered != null) {
Meter meter = MetricAnnotation.meter(Metrics.getInstance().getMetricService(), metered, method);
Interceptor interceptor = new MeterInterceptor(meter);
interceptors.add(interceptor);
}
Counted counted = getCountedAnnotation(method);
if (counted != null) {
Counter counter = MetricAnnotation.counter(Metrics.getInstance().getMetricService(), counted, method);
Interceptor interceptor = new CounterInterceptor(counter, counted.monotonic());
interceptors.add(interceptor);
}
methodInterceptors = new MethodInterceptors(true, interceptors);
map.put(method, methodInterceptors);
}
return methodInterceptors.preCall(request, responder, serviceMethodInfo);
}
@Override
public void postCall(Request request, int status, ServiceMethodInfo serviceMethodInfo) throws Exception {
Method method = serviceMethodInfo.getMethod();
MethodInterceptors methodInterceptors = map.get(method);
if (methodInterceptors != null) {
methodInterceptors.postCall(request, status, serviceMethodInfo);
}
}
private static class MethodInterceptors implements Interceptor {
private final boolean annotationScanned;
private Interceptor[] interceptors;
MethodInterceptors(boolean annotationScanned, List interceptors) {
this.annotationScanned = annotationScanned;
if (!interceptors.isEmpty()) {
this.interceptors = interceptors.toArray(new Interceptor[interceptors.size()]);
}
}
@Override
public boolean preCall(Request request, Response responder, ServiceMethodInfo serviceMethodInfo)
throws Exception {
if (interceptors != null) {
for (Interceptor interceptor : interceptors) {
interceptor.preCall(request, responder, serviceMethodInfo);
}
}
return true;
}
@Override
public void postCall(Request request, int status, ServiceMethodInfo serviceMethodInfo) throws Exception {
if (interceptors != null) {
for (Interceptor interceptor : interceptors) {
interceptor.postCall(request, status, serviceMethodInfo);
}
}
}
}
private static class TimerInterceptor implements Interceptor {
private final Timer timer;
private static final String TIMER_CONTEXT = "TIMER_CONTEXT";
private TimerInterceptor(Timer timer) {
this.timer = timer;
}
@Override
public boolean preCall(Request request, Response responder, ServiceMethodInfo serviceMethodInfo) {
Timer.Context context = timer.start();
serviceMethodInfo.setAttribute(TIMER_CONTEXT, context);
return true;
}
@Override
public void postCall(Request request, int status, ServiceMethodInfo serviceMethodInfo) {
Timer.Context context = (Timer.Context) serviceMethodInfo.getAttribute(TIMER_CONTEXT);
context.stop();
}
}
private static class MeterInterceptor implements Interceptor {
private final Meter meter;
private MeterInterceptor(Meter meter) {
this.meter = meter;
}
@Override
public boolean preCall(Request request, Response responder, ServiceMethodInfo serviceMethodInfo) {
meter.mark();
return true;
}
@Override
public void postCall(Request request, int status, ServiceMethodInfo serviceMethodInfo) {
}
}
private static class CounterInterceptor implements Interceptor {
private final Counter counter;
private final boolean monotonic;
private CounterInterceptor(Counter counter, boolean monotonic) {
this.counter = counter;
this.monotonic = monotonic;
}
@Override
public boolean preCall(Request request, Response responder, ServiceMethodInfo serviceMethodInfo) {
counter.inc();
return true;
}
@Override
public void postCall(Request request, int status, ServiceMethodInfo serviceMethodInfo) {
if (!monotonic) {
counter.dec();
}
}
}
}
================================================
FILE: analytics/msf4j-analytics/src/main/java/org/wso2/msf4j/analytics/tracing/MSF4JTracingInterceptor.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://wso2.com) All Rights Reserved.
*
* 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 org.wso2.msf4j.analytics.tracing;
import org.wso2.msf4j.Interceptor;
import org.wso2.msf4j.Request;
import org.wso2.msf4j.Response;
import org.wso2.msf4j.ServiceMethodInfo;
import org.wso2.msf4j.analytics.common.tracing.TraceEvent;
import org.wso2.msf4j.analytics.common.tracing.TracingConstants;
import org.wso2.msf4j.analytics.common.tracing.TracingEventTracker;
import org.wso2.msf4j.analytics.common.tracing.TracingUtil;
import java.util.Date;
/**
* Interceptor for tracing server side request/response flows.
*/
// TODO: Write tests and add the OSGi mode support
public class MSF4JTracingInterceptor implements Interceptor {
private static final String RESPONDER_ATTRIBUTE = "responder-attribute";
private static final String TRACE_EVENT_ATTRIBUTE = "trace-event-attribute";
private String instanceId;
private String instanceName;
private String dasUrl;
/**
* Constructor of the MSF4JTracingInterceptor.
*
* @param microServiceName Name of the Microservice
*/
public MSF4JTracingInterceptor(String microServiceName) {
this(microServiceName, TracingConstants.DAS_RECEIVER_URL);
}
/**
* Constructor of the MSF4JTracingInterceptor.
*
* @param microServiceName Name of the Microservice
* @param dasUrl URL of the receiver of DAS server
*/
public MSF4JTracingInterceptor(String microServiceName, String dasUrl) {
this.instanceId = TracingUtil.generateUniqueId();
this.instanceName = microServiceName;
this.dasUrl = dasUrl;
}
/**
* Intercepts the server request flow and extract request information
* to be published to the DAS for tracing.
*/
@Override
public boolean preCall(Request request, Response responder, ServiceMethodInfo serviceMethodInfo) throws Exception {
long time = new Date().getTime();
serviceMethodInfo.setAttribute(RESPONDER_ATTRIBUTE, responder);
String traceOriginId = request.getHeader(TracingConstants.TRACE_ORIGIN_ID_HEADER);
String serverTraceId;
if (traceOriginId == null) {
traceOriginId = TracingUtil.generateUniqueId();
serverTraceId = traceOriginId;
} else {
serverTraceId = TracingUtil.generateUniqueId();
}
String traceParentId = request.getHeader(TracingConstants.TRACE_ID_HEADER);
TraceEvent serverTraceEvent = new TraceEvent(
TracingConstants.SERVER_TRACE_START,
serverTraceId,
traceOriginId,
time
);
serverTraceEvent.setInstanceId(instanceId);
serverTraceEvent.setInstanceName(instanceName);
serverTraceEvent.setParentId(traceParentId);
serverTraceEvent.setHttpMethod(request.getHttpMethod());
serverTraceEvent.setUrl(request.getUri());
TracingEventTracker.setTraceEvent(serverTraceEvent);
serviceMethodInfo.setAttribute(TRACE_EVENT_ATTRIBUTE, serverTraceEvent);
TracingUtil.pushToDAS(serverTraceEvent, dasUrl);
return true;
}
/**
* Intercepts the server response flow and extract response information
* to be published to the DAS for tracing.
*/
@Override
public void postCall(Request request, int status, ServiceMethodInfo serviceMethodInfo) throws Exception {
long time = new Date().getTime();
TraceEvent traceEvent = (TraceEvent) serviceMethodInfo.getAttribute(TRACE_EVENT_ATTRIBUTE);
if (traceEvent != null) {
TraceEvent endTraceEvent = new TraceEvent(
TracingConstants.SERVER_TRACE_END,
traceEvent.getTraceId(),
traceEvent.getOriginId(),
time
);
Response responder = (Response) serviceMethodInfo.getAttribute(RESPONDER_ATTRIBUTE);
endTraceEvent.setStatusCode(responder.getStatusCode());
TracingUtil.pushToDAS(endTraceEvent, dasUrl);
}
}
}
================================================
FILE: analytics/msf4j-analytics/src/main/resources/http-monitoring.yml
================================================
# Copyright 2016 WSO2 Inc. (http://wso2.org)
#
# 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.
# This is the main configuration file for HTTP Monitoring
# Enable HTTP Monitoring
enabled: true
# Data Analytics Server (DAS) configuration
das:
# Data Receiver URL used by the Data Publisher
receiverURL: tcp://localhost:7611
# Authentication URL for the Data Publisher
# authURL: ssl://localhost:7711
# The type used with Data Publisher
type: thrift
username: admin
password: admin
# The path for Data Bridge Agent configuration
dataAgentConfigPath: data-agent-config.xml
================================================
FILE: analytics/msf4j-analytics/src/test/java/org/wso2/msf4j/analytics/HTTPMonitoringConfigTest.java
================================================
/*
* Copyright 2016 WSO2 Inc. (http://wso2.org)
*
* 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 org.wso2.msf4j.analytics;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.wso2.msf4j.analytics.httpmonitoring.config.HTTPMonitoringConfigBuilder;
import org.wso2.msf4j.analytics.httpmonitoring.config.model.DasConfig;
import org.wso2.msf4j.analytics.httpmonitoring.config.model.HTTPMonitoringConfig;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* Test Cases for {@link HTTPMonitoringConfig}
*/
public class HTTPMonitoringConfigTest {
private static final String DEFAULT_CONFIG_PATH = "deployment.yaml";
private static HTTPMonitoringConfig httpMonitoringConfig;
@BeforeClass
private void load() {
httpMonitoringConfig = HTTPMonitoringConfigBuilder.build();
}
@AfterClass
private void clear() throws IOException {
Path configPath = Paths.get(DEFAULT_CONFIG_PATH);
if (Files.exists(configPath)) {
Files.delete(configPath);
}
}
@Test
public void testEnabled() {
Assert.assertFalse(httpMonitoringConfig.isEnabled());
}
@Test
public void testDasConfigLoad() {
DasConfig config = httpMonitoringConfig.getDas();
Assert.assertEquals(config.getReceiverURL(), "tcp://localhost:7611");
Assert.assertNull(config.getAuthURL());
Assert.assertEquals(config.getType(), "thrift");
Assert.assertEquals(config.getUsername(), "admin");
Assert.assertEquals(config.getPassword(), "admin");
Assert.assertEquals(config.getDataAgentConfigPath(), "data-agent-config.xml");
}
}
================================================
FILE: analytics/msf4j-analytics/src/test/resources/deployment.yaml
================================================
# Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved
#
# 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.
# MSF4J configuration
wso2.msf4j.configuration:
# No of worker pool threads to handle MSF4J requests
threadCount: 100
threadPoolName: msf4j.executor.workerpool
# MSF4J Analytics configuration
wso2.msf4j.analytics.configuration:
# Whether HTTP Monitoring is enables or not
enabled: false
# DAS configuration
das:
# The type used with Data Publisher
type: thrift
# Data Receiver URL used by the Data Publisher
receiverURL: tcp://localhost:7611
username: admin
password: admin
# The path for Data Bridge Agent configuration
dataAgentConfigPath: data-agent-config.xml
================================================
FILE: analytics/msf4j-analytics-common/pom.xml
================================================
4.0.0org.wso2.msf4jmsf4j-parent2.8.14-SNAPSHOT../../poms/parent/pom.xmlmsf4j-analytics-commonbundleWSO2 MSF4J Analytics CommonWSO2 MSF4J Analytics Commonhttps://github.com/wso2/msf4jorg.wso2.msf4jmsf4j-coreorg.testngtestngtestorg.apache.maven.pluginsmaven-compiler-pluginorg.apache.ratapache-rat-pluginorg.apache.maven.pluginsmaven-checkstyle-pluginorg.apache.maven.pluginsmaven-surefire-pluginorg.apache.maven.pluginsmaven-deploy-pluginorg.apache.felixmaven-bundle-plugincoverageorg.apache.maven.pluginsmaven-surefire-plugin${argLine} -Xmx512morg.jacocojacoco-maven-pluginprepare-agentprepare-agentreportprepare-packagereportorg.jacocojacoco-maven-pluginreleaseorg.apache.maven.pluginsmaven-source-plugintrueattach-sourcespackagejar-no-forkorg.apache.maven.pluginsmaven-javadoc-plugintrue
http://docs.oracle.com/javaee/6/api/
*.internal.*
Licensed under the Apache License, Version 2.0]]>
attach-javadocpackagejarorg.apache.maven.pluginsmaven-gpg-plugin${gpg.passphrase}${gpg.useagent}signorg.apache.maven.pluginsmaven-source-pluginorg.apache.maven.pluginsmaven-javadoc-pluginorg.apache.maven.pluginsmaven-gpg-plugin
org.wso2.msf4j.analytics.*;version="${msf4j.version}"
org.slf4j.*;version="${slf4j.version.range}",
org.osgi.framework.*;version="${osgi.framework.import.version.range}",
org.osgi.util.tracker; version="${osgi.service.tracker.import.version.range}",
javax.ws.rs.*,
osgi.service;objectClass="org.wso2.carbon.kernel.startupresolver.CapabilityProvider";capabilityName="org.wso2.msf4j.Interceptor"
================================================
FILE: analytics/msf4j-analytics-common/src/main/java/org/wso2/msf4j/analytics/common/tracing/MSF4JClientTracingFilter.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://wso2.com) All Rights Reserved.
*
* 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 org.wso2.msf4j.analytics.common.tracing;
import java.io.IOException;
import java.util.Date;
import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientRequestFilter;
import javax.ws.rs.client.ClientResponseContext;
import javax.ws.rs.client.ClientResponseFilter;
/**
* Filter for tracing client side request/response flow.
*/
// TODO: Write tests and add the OSGi mode support
public class MSF4JClientTracingFilter implements ClientRequestFilter, ClientResponseFilter {
private static final String TRACE_EVENT_ATTRIBUTE = "trace-event-attribute";
private TraceEvent parentEvent;
private String instanceId;
private String instanceName;
private String dasUrl;
/**
* Constructor of the MSF4JClientTracingFilter.
*
* @param clientName Name of the client
*/
public MSF4JClientTracingFilter(String clientName) {
this(clientName, TracingConstants.DAS_RECEIVER_URL);
}
/**
* Constructor of the MSF4JClientTracingFilter.
*
* @param clientName Name of the client
* @param dasUrl URL of the receiver of DAS server
*/
public MSF4JClientTracingFilter(String clientName, String dasUrl) {
this(clientName, null, dasUrl);
}
/**
* Constructor of the MSF4JClientTracingFilter.
*
* @param clientName Name of the client
* @param parentEvent TraceEvent of the caller
* @param dasUrl URL of the receiver of DAS server
*/
public MSF4JClientTracingFilter(String clientName, TraceEvent parentEvent, String dasUrl) {
this.instanceName = clientName;
this.instanceId = TracingUtil.generateUniqueId();
this.dasUrl = dasUrl;
if (parentEvent != null) {
this.parentEvent = parentEvent;
} else {
this.parentEvent = TracingEventTracker.getTraceEvent();
}
}
/**
* Intercepts the client request flow and extract request information
* to be published to the DAS for tracing.
*/
@Override
public void filter(ClientRequestContext requestContext) throws IOException {
long time = new Date().getTime();
String clientTraceId;
String traceOriginId;
String traceParentId = null;
if (this.parentEvent == null) {
traceOriginId = TracingUtil.generateUniqueId();
clientTraceId = traceOriginId;
} else {
traceOriginId = parentEvent.getOriginId();
clientTraceId = TracingUtil.generateUniqueId();
traceParentId = parentEvent.getTraceId();
}
TraceEvent clientTraceEvent = new TraceEvent(
TracingConstants.CLIENT_TRACE_START,
clientTraceId,
traceOriginId,
time
);
clientTraceEvent.setInstanceId(instanceId);
clientTraceEvent.setInstanceName(instanceName);
clientTraceEvent.setParentId(traceParentId);
clientTraceEvent.setHttpMethod(requestContext.getMethod());
clientTraceEvent.setUrl(requestContext.getUri().toString());
requestContext.setProperty(TRACE_EVENT_ATTRIBUTE, clientTraceEvent);
requestContext.getHeaders().putSingle(TracingConstants.TRACE_ID_HEADER, clientTraceId);
requestContext.getHeaders().putSingle(TracingConstants.TRACE_ORIGIN_ID_HEADER, traceOriginId);
TracingUtil.pushToDAS(clientTraceEvent, dasUrl);
}
/**
* Intercepts the client response flow and extract response information
* to be published to the DAS server for tracing.
*/
@Override
public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
long time = new Date().getTime();
TraceEvent traceEvent = (TraceEvent) requestContext.getProperty(TRACE_EVENT_ATTRIBUTE);
if (traceEvent != null) {
TraceEvent endTraceEvent = new TraceEvent(
TracingConstants.CLIENT_TRACE_END,
traceEvent.getTraceId(),
traceEvent.getOriginId(),
time
);
endTraceEvent.setStatusCode(responseContext.getStatus());
TracingUtil.pushToDAS(endTraceEvent, dasUrl);
}
}
}
================================================
FILE: analytics/msf4j-analytics-common/src/main/java/org/wso2/msf4j/analytics/common/tracing/TraceEvent.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you 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 org.wso2.msf4j.analytics.common.tracing;
/**
* Class to hold tracing start event data.
*/
public class TraceEvent {
private final String type;
private final String traceId;
private final String originId;
private final long time;
private int statusCode;
private String httpMethod;
private String instanceId;
private String instanceName;
private String parentId;
private String url;
public TraceEvent(String type, String traceId, String originId, long time) {
this.type = type;
this.traceId = traceId;
this.originId = originId;
this.time = time;
}
public String getType() {
return type;
}
public String getTraceId() {
return traceId;
}
public String getOriginId() {
return originId;
}
public long getTime() {
return time;
}
public String getInstanceId() {
return instanceId;
}
public void setInstanceId(String instanceId) {
this.instanceId = instanceId;
}
public String getInstanceName() {
return instanceName;
}
public void setInstanceName(String instanceName) {
this.instanceName = instanceName;
}
public String getParentId() {
return parentId;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
public int getStatusCode() {
return statusCode;
}
public void setStatusCode(int statusCode) {
this.statusCode = statusCode;
}
public String getHttpMethod() {
return httpMethod;
}
public void setHttpMethod(String httpMethod) {
this.httpMethod = httpMethod;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public String toString() {
return "TraceEvent{" +
"type='" + type + '\'' +
", traceId='" + traceId + '\'' +
", originId='" + originId + '\'' +
", time=" + time +
", statusCode=" + statusCode +
", httpMethod='" + httpMethod + '\'' +
", instanceId='" + instanceId + '\'' +
", instanceName='" + instanceName + '\'' +
", parentId='" + parentId + '\'' +
", url='" + url + '\'' +
'}';
}
}
================================================
FILE: analytics/msf4j-analytics-common/src/main/java/org/wso2/msf4j/analytics/common/tracing/TracingConstants.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you 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 org.wso2.msf4j.analytics.common.tracing;
/**
* Class to hold constants used in tracing.
*/
public class TracingConstants {
public static final String CLIENT_TRACE_START = "CTS";
public static final String CLIENT_TRACE_END = "CTE";
public static final String SERVER_TRACE_START = "STS";
public static final String SERVER_TRACE_END = "STE";
public static final String TRACE_ID_HEADER = "X-msf4j-trace-id";
public static final String TRACE_ORIGIN_ID_HEADER = "X-msf4j-trace-origin-id";
public static final String DAS_RECEIVER_URL = "http://localhost:9763/endpoints/msf4jtracereceiver";
public static final String DEFAULT_ZIPKIN_URL = "http://0.0.0.0:9411";
/**
* Tracing Types.
*/
public enum TracingType {
DAS, ZIPKIN
}
}
================================================
FILE: analytics/msf4j-analytics-common/src/main/java/org/wso2/msf4j/analytics/common/tracing/TracingEventTracker.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you 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 org.wso2.msf4j.analytics.common.tracing;
/**
* Class for holding the thread local of tracing events.
* This class help the Client interceptors to access the
* request trace event of the containing service to keep
* the correlation.
*/
public class TracingEventTracker {
private static final ThreadLocal traceEventThreadLocal = new ThreadLocal<>();
public static void setTraceEvent(TraceEvent traceEvent) {
traceEventThreadLocal.set(traceEvent);
}
public static TraceEvent getTraceEvent() {
return traceEventThreadLocal.get();
}
}
================================================
FILE: analytics/msf4j-analytics-common/src/main/java/org/wso2/msf4j/analytics/common/tracing/TracingUtil.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you 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 org.wso2.msf4j.analytics.common.tracing;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
/**
* Utility methods of for MSF4J tracing.
*/
public class TracingUtil {
private static final Logger log = LoggerFactory.getLogger(TracingUtil.class);
private static final ExecutorService executorService = Executors.newSingleThreadExecutor();
private static final Random random = new Random();
/**
* Generate a random string unique identifier.
*/
public static String generateUniqueId() {
// UUID.randomUUID().toString() is too slow
// TODO: Test whether the ID is unique enough
return System.currentTimeMillis() + "" + String.format("%08d", random.nextInt(100000000));
}
/**
* Publish trace event to DAS in the background.
*/
public static void pushToDAS(TraceEvent traceEvent, String dasUrl) {
Future> future = executorService.submit(() -> {
log.debug("Publishing trace event " + traceEvent);
if (ClientBuilder.newClient().target(dasUrl)
.request().post(Entity.json(traceEvent)).getStatus() != Response.Status.OK.getStatusCode()) {
log.error("Error while publishing trace event " + traceEvent);
}
});
future.isDone(); // Added to avoid findbugs warning
}
}
================================================
FILE: analytics/msf4j_http_monitoring_capp_source/build.xml
================================================
================================================
FILE: analytics/msf4j_http_monitoring_capp_source/msf4j_http_monitoring_capp/artifacts.xml
================================================
================================================
FILE: analytics/msf4j_http_monitoring_capp_source/msf4j_http_monitoring_capp/http_event_receiver_1.0.0/artifact.xml
================================================
http_event_receiver.xml
================================================
FILE: analytics/msf4j_http_monitoring_capp_source/msf4j_http_monitoring_capp/http_event_receiver_1.0.0/http_event_receiver.xml
================================================
================================================
FILE: analytics/msf4j_http_monitoring_capp_source/msf4j_http_monitoring_capp/http_event_store_1.0.0/artifact.xml
================================================
org_wso2_msf4j_analytics_httpmonitoring.xml
================================================
FILE: analytics/msf4j_http_monitoring_capp_source/msf4j_http_monitoring_capp/http_event_store_1.0.0/org_wso2_msf4j_analytics_httpmonitoring.xml
================================================
meta_timestamptruefalsefalseLONGmeta_server_addresstruefalsefalseSTRINGmeta_server_nametruefalsefalseSTRINGmeta_application_typetruefalsefalseSTRINGcorrelation_activity_idtruefalsefalseFACETcorrelation_parent_requesttruefalsefalseSTRINGservice_classtruefalsefalseSTRINGservice_nametruefalsefalseSTRINGservice_methodtruefalsefalseSTRINGrequest_urifalsefalsefalseSTRINGservice_contexttruefalsefalseSTRINGhttp_methodfalsefalsefalseSTRINGcontent_typefalsefalsefalseSTRINGrequest_content_lengthfalsefalsefalseLONGreferrerfalsefalsefalseSTRINGhttp_status_codetruefalsefalseINTEGERresponse_timetruefalsefalseLONGgroup_bytruefalsefalseFACETorg.wso2.msf4j.analytics.httpmonitoring:1.0.0EVENT_STORE
================================================
FILE: analytics/msf4j_http_monitoring_capp_source/msf4j_http_monitoring_capp/http_event_stream_1.0.0/artifact.xml
================================================
org.wso2.msf4j.analytics.httpmonitoring_1.0.0.json
================================================
FILE: analytics/msf4j_http_monitoring_capp_source/msf4j_http_monitoring_capp/http_event_stream_1.0.0/org.wso2.msf4j.analytics.httpmonitoring_1.0.0.json
================================================
{
"name": "org.wso2.msf4j.analytics.httpmonitoring",
"version": "1.0.0",
"nickName": "msf4j_http_monitoring",
"description": "MSF4J HTTP Monitoring",
"metaData": [
{
"name": "timestamp",
"type": "LONG"
},
{
"name": "server_address",
"type": "STRING"
},
{
"name": "server_name",
"type": "STRING"
},
{
"name": "application_type",
"type": "STRING"
}
],
"correlationData": [
{
"name": "activity_id",
"type": "STRING"
},
{
"name": "parent_request",
"type": "STRING"
}
],
"payloadData": [
{
"name": "service_class",
"type": "STRING"
},
{
"name": "service_name",
"type": "STRING"
},
{
"name": "service_method",
"type": "STRING"
},
{
"name": "request_uri",
"type": "STRING"
},
{
"name": "service_context",
"type": "STRING"
},
{
"name": "http_method",
"type": "STRING"
},
{
"name": "content_type",
"type": "STRING"
},
{
"name": "request_content_length",
"type": "LONG"
},
{
"name": "referrer",
"type": "STRING"
},
{
"name": "http_status_code",
"type": "INT"
},
{
"name": "response_time",
"type": "LONG"
}
]
}
================================================
FILE: analytics/msf4j_http_monitoring_capp_source/msf4j_http_monitoring_capp/spark_script_1.0.0/artifact.xml
================================================
http_event_script.xml
================================================
FILE: analytics/msf4j_http_monitoring_capp_source/msf4j_http_monitoring_capp/spark_script_1.0.0/http_event_script.xml
================================================
http_event_script0 0/15 * 1/1 * ? *
================================================
FILE: analytics/wso2das-tracing-capp/capp-content/Dashboard_1.0.0/artifact.xml
================================================
msf4j-message-tracing.json
================================================
FILE: analytics/wso2das-tracing-capp/capp-content/Dashboard_1.0.0/msf4j-message-tracing.json
================================================
{
"id": "msf4j-message-tracing",
"title": "MSF4J Message Tracing",
"description": "",
"permissions": {
"viewers": [
"Internal/everyone"
],
"editors": [
"Internal/everyone"
]
},
"pages": [
{
"id": "landing",
"title": "Welcome",
"layout": {
"content": {
"loggedIn": {
"blocks": [
{
"id": "a",
"col": 1,
"row": 1,
"size_x": 12,
"size_y": 3,
"banner": false
}
]
}
},
"fluidLayout": false
},
"isanon": false,
"content": {
"default": {
"a": [
{
"id": "n6ql6vcjn4hs1mikmu5trzfr",
"content": {
"id": "msf4j-message-tracing",
"title": "MSF4J Message Tracing",
"type": "gadget",
"thumbnail": "store://gadget/msf4j-tracing/icon.png",
"data": {
"url": "store://gadget/msf4j-tracing/index.xml"
},
"styles": {
"title": "MSF4J Message Tracing",
"borders": true
},
"options": {
"timeBack": {
"type": "STRING",
"title": "Trace Last Minutes",
"value": "1440",
"options": [],
"required": false
},
"dasHost": {
"type": "STRING",
"title": "DAS Host",
"value": "https://localhost:9443",
"options": [],
"required": false
},
"username": {
"type": "STRING",
"title": "Username",
"value": "admin",
"options": [],
"required": false
},
"password": {
"type": "STRING",
"title": "Password",
"value": "admin",
"options": [],
"required": false
}
},
"locale_titles": {}
}
}
]
},
"anon": {}
}
}
],
"identityServerUrl": "",
"accessTokenUrl": "",
"apiKey": "",
"apiSecret": "",
"banner": {
"globalBannerExists": null,
"customBannerExists": null
},
"landing": "landing",
"isanon": false,
"isUserCustom": false
}
================================================
FILE: analytics/wso2das-tracing-capp/capp-content/Eventreceiver_1.0.0/artifact.xml
================================================
msf4jtracereceiver.xml
================================================
FILE: analytics/wso2das-tracing-capp/capp-content/Eventreceiver_1.0.0/msf4jtracereceiver.xml
================================================
http
================================================
FILE: analytics/wso2das-tracing-capp/capp-content/Eventstore_1.0.0/artifact.xml
================================================
msf4j-tracing.xml
================================================
FILE: analytics/wso2das-tracing-capp/capp-content/Eventstore_1.0.0/msf4j-tracing.xml
================================================
typefalsetruefalseSTRINGtimefalsefalsefalseLONGstatusCodefalsefalsefalseINTEGERhttpMethodfalsefalsefalseSTRINGinstanceIdfalsefalsefalseSTRINGinstanceNamefalsefalsefalseSTRINGparentIdfalsefalsefalseSTRINGtraceIdfalsetruefalseSTRINGoriginIdtruefalsefalseSTRINGurlfalsefalsefalseSTRINGmeta_traceIdfalsefalsefalseSTRINGcorrelation_originIdfalsefalsefalseINTEGERmsf4j-tracing:1.0.0falseEVENT_STORE
================================================
FILE: analytics/wso2das-tracing-capp/capp-content/Eventstream_1.0.0/artifact.xml
================================================
msf4j-tracing_1.0.0.json
================================================
FILE: analytics/wso2das-tracing-capp/capp-content/Eventstream_1.0.0/msf4j-tracing_1.0.0.json
================================================
{
"name": "msf4j-tracing",
"version": "1.0.0",
"nickName": "",
"description": "",
"payloadData": [
{
"name": "type",
"type": "STRING"
},
{
"name": "time",
"type": "LONG"
},
{
"name": "statusCode",
"type": "INT"
},
{
"name": "httpMethod",
"type": "STRING"
},
{
"name": "instanceId",
"type": "STRING"
},
{
"name": "instanceName",
"type": "STRING"
},
{
"name": "parentId",
"type": "STRING"
},
{
"name": "traceId",
"type": "STRING"
},
{
"name": "originId",
"type": "STRING"
},
{
"name": "url",
"type": "STRING"
}
]
}
================================================
FILE: analytics/wso2das-tracing-capp/capp-content/GadgetMSF4JTracing_1.0.0/artifact.xml
================================================
msf4j-tracing
================================================
FILE: analytics/wso2das-tracing-capp/capp-content/GadgetMSF4JTracing_1.0.0/msf4j-tracing/css/main.css
================================================
body {
display: block;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
overflow: hidden;
}
#refresh-traces {
padding: 5px 10px;
background-color: #005FB0;
color: #ffffff;
display: inline-block;
margin: 12px 32px;
cursor: pointer;
}
#refresh-traces .pressed {
background-color: #ffffff;
}
#trace-groups {
position: relative;
display: block;
width: 100%;
height: 100%;
overflow-y: auto;
}
.trace-group {
padding: 12px;
cursor: default;
border-bottom: 1px solid #dddddd;
}
.trace-group .inst-name {
display: inline-block;
margin-left: 20px;
max-width: 120px;
}
.trace-group .endpoint {
display: inline-block;
margin-left: 20px;
}
.trace-group .method {
font-weight: bold;
display: inline-block;
margin-left: 20px;
}
.trace-group .url {
margin-left: 20px;
display: inline-block;
}
.trace-group .time {
display: inline-block;
margin-left: 20px;
min-width: 145px;
}
.trace-bar, .trace-bar * {
position: relative;
}
.trace-bar .bar-row {
border-bottom: 1px solid #dddddd;
}
.trace-bar .left-pane {
position: absolute;
float: left;
left: 0;
top: 0;
width: 200px;
line-height: 20px;
padding: 10px 0;
cursor: pointer;
}
.trace-bar .arrow {
display: inline-block;
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 5px solid #000;
}
.trace-bar .arrow-down {
display: inline-block;
width: 0;
height: 0;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-left: 5px solid #000;
}
.trace-bar .arrow-hide {
margin-left: 5px;
display: inline-block;
}
.trace-bar .right-pane {
margin-left: 200px;
border-left: 1px solid #dddddd;
padding: 14px 0;
}
.trace-bar .bar-wrapper {
padding: 0 5px;
}
.trace-bar .bar {
position: relative;
background-color: #005FB0;
top: 0;
height: 12px;
cursor: pointer;
border-radius: 2px;
}
.trace-bar .child-container {
}
#trace-tree-view {
position: absolute;
display: block;
height: 100%;
width: 100%;
left: 0;
top: 0;
z-index: 100;
background-color: #ffffff;
padding-top: 40px;
overflow-y: auto;
}
.bar-info {
z-index: 100;
margin: 5px auto;
width: 600px;
position: relative;
}
.bar-info .row {
display: block;
position: relative;
}
.bar-info .row.emp {
font-weight: bold;
}
.bar-info .row.gap {
margin-top: 15px;
}
.bar-info .left-ipane {
position: relative;
display: block;
left: 0;
width: 50%;
text-align: right;
}
.bar-info .left-ipane .wrapper.emp, .bar-info .right-ipane .wrapper.emp {
padding: 8px;
}
.bar-info .left-ipane .wrapper, .bar-info .right-ipane .wrapper {
padding: 8px;
}
.bar-info .right-ipane {
position: absolute;
display: block;
left: 50%;
width: 50%;
top: 0;
text-align: left;
}
.bar-info .close {
z-index: 100;
}
#trace-tree-view .container {
border-top: 1px solid #dddddd;
}
.bar-info .cell {
display: inline-block;
}
#trace-tree-view .close, .bar-info .close {
cursor: pointer;
position: absolute;
display: block;
left: 0;
top: 0;
margin-left: 10px;
font-size: 18px;
}
#trace-tree-view .close .arrow {
display: inline-block;
width: 0;
height: 0;
border-right: 10px solid #666;
border-top: 8px solid transparent;
border-bottom: 8px solid transparent;
margin-right: 5px;
margin-bottom: -2px;
}
#trace-tree-view .time-line-pane {
margin-left: 200px;
}
#trace-tree-view .time-line-wrapper {
position: relative;
display: block;
}
#time-line {
width: 100%;
height: 20px;
}
#time-line .unit {
border-left: 1px solid #dddddd;
color: #666666;
min-height: 4px;
font-size: 10px;
padding-top: 3px;
padding-left: 3px;
display: inline-block;
position: absolute;
}
================================================
FILE: analytics/wso2das-tracing-capp/capp-content/GadgetMSF4JTracing_1.0.0/msf4j-tracing/gadget.json
================================================
{
"id": "msf4j-message-tracing",
"title": "MSF4J Message Tracing",
"type": "gadget",
"thumbnail": "store://gadget/msf4j-tracing/icon.png",
"data": {
"url": "store://gadget/msf4j-tracing/index.xml"
}
}
================================================
FILE: analytics/wso2das-tracing-capp/capp-content/GadgetMSF4JTracing_1.0.0/msf4j-tracing/index.xml
================================================
Refresh Traces
Back
]]>
================================================
FILE: analytics/wso2das-tracing-capp/capp-content/GadgetMSF4JTracing_1.0.0/msf4j-tracing/js/libs/jquery.base64.js
================================================
/*!
* jquery.base64.js 0.1 - https://github.com/yckart/jquery.base64.js
* Makes Base64 en & -decoding simpler as it is.
*
* Based upon: https://gist.github.com/Yaffle/1284012
*
* Copyright (c) 2012 Yannick Albert (http://yckart.com)
* Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php).
* 2013/02/10
**/
;(function($) {
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
a256 = '',
r64 = [256],
r256 = [256],
i = 0;
var UTF8 = {
/**
* Encode multi-byte Unicode string into utf-8 multiple single-byte characters
* (BMP / basic multilingual plane only)
*
* Chars in range U+0080 - U+07FF are encoded in 2 chars, U+0800 - U+FFFF in 3 chars
*
* @param {String} strUni Unicode string to be encoded as UTF-8
* @returns {String} encoded string
*/
encode: function(strUni) {
// use regular expressions & String.replace callback function for better efficiency
// than procedural approaches
var strUtf = strUni.replace(/[\u0080-\u07ff]/g, // U+0080 - U+07FF => 2 bytes 110yyyyy, 10zzzzzz
function(c) {
var cc = c.charCodeAt(0);
return String.fromCharCode(0xc0 | cc >> 6, 0x80 | cc & 0x3f);
})
.replace(/[\u0800-\uffff]/g, // U+0800 - U+FFFF => 3 bytes 1110xxxx, 10yyyyyy, 10zzzzzz
function(c) {
var cc = c.charCodeAt(0);
return String.fromCharCode(0xe0 | cc >> 12, 0x80 | cc >> 6 & 0x3F, 0x80 | cc & 0x3f);
});
return strUtf;
},
/**
* Decode utf-8 encoded string back into multi-byte Unicode characters
*
* @param {String} strUtf UTF-8 string to be decoded back to Unicode
* @returns {String} decoded string
*/
decode: function(strUtf) {
// note: decode 3-byte chars first as decoded 2-byte strings could appear to be 3-byte char!
var strUni = strUtf.replace(/[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g, // 3-byte chars
function(c) { // (note parentheses for precence)
var cc = ((c.charCodeAt(0) & 0x0f) << 12) | ((c.charCodeAt(1) & 0x3f) << 6) | (c.charCodeAt(2) & 0x3f);
return String.fromCharCode(cc);
})
.replace(/[\u00c0-\u00df][\u0080-\u00bf]/g, // 2-byte chars
function(c) { // (note parentheses for precence)
var cc = (c.charCodeAt(0) & 0x1f) << 6 | c.charCodeAt(1) & 0x3f;
return String.fromCharCode(cc);
});
return strUni;
}
};
while(i < 256) {
var c = String.fromCharCode(i);
a256 += c;
r256[i] = i;
r64[i] = b64.indexOf(c);
++i;
}
function code(s, discard, alpha, beta, w1, w2) {
s = String(s);
var buffer = 0,
i = 0,
length = s.length,
result = '',
bitsInBuffer = 0;
while(i < length) {
var c = s.charCodeAt(i);
c = c < 256 ? alpha[c] : -1;
buffer = (buffer << w1) + c;
bitsInBuffer += w1;
while(bitsInBuffer >= w2) {
bitsInBuffer -= w2;
var tmp = buffer >> bitsInBuffer;
result += beta.charAt(tmp);
buffer ^= tmp << bitsInBuffer;
}
++i;
}
if(!discard && bitsInBuffer > 0) result += beta.charAt(buffer << (w2 - bitsInBuffer));
return result;
}
var Plugin = $.base64 = function(dir, input, encode) {
return input ? Plugin[dir](input, encode) : dir ? null : this;
};
Plugin.btoa = Plugin.encode = function(plain, utf8encode) {
plain = Plugin.raw === false || Plugin.utf8encode || utf8encode ? UTF8.encode(plain) : plain;
plain = code(plain, false, r256, b64, 8, 6);
return plain + '===='.slice((plain.length % 4) || 4);
};
Plugin.atob = Plugin.decode = function(coded, utf8decode) {
coded = String(coded).split('=');
var i = coded.length;
do {--i;
coded[i] = code(coded[i], true, r64, a256, 6, 8);
} while (i > 0);
coded = coded.join('');
return Plugin.raw === false || Plugin.utf8decode || utf8decode ? UTF8.decode(coded) : coded;
};
}(jQuery));
================================================
FILE: analytics/wso2das-tracing-capp/capp-content/GadgetMSF4JTracing_1.0.0/msf4j-tracing/js/main.js
================================================
gadgets.util.registerOnLoadHandler(function () {
gadgets.window.adjustHeight();
});
$(document).ready(function () {
var prefs = new _IG_Prefs();
var traceGroupsElm = $('#trace-groups');
var traceTreeVwElm = $("#trace-tree-view");
var traceTreeVw = initTraceTreeView(
traceTreeVwElm,
traceTreeVwElm.find(".container").first(),
traceTreeVwElm.find(".close").first()
);
(function () {
var refreshTracesElm = $("#refresh-traces");
var isLoading = false;
load();
function load() {
if (isLoading == false) {
isLoading = true;
loadAndRenderTraceGroups(prefs, traceGroupsElm, traceTreeVw, function () {
isLoading = false;
});
}
}
refreshTracesElm.click(function () {
load();
});
})();
});
function loadAndRenderTraceGroups(prefs, traceGroupsElm, traceTreeVw, callback) {
var analyticsPath = "/analytics/tables/MSF4J-TRACING";
var timeBack = prefs.getInt("timeBack");
var dasHost = prefs.getString("dasHost");
var username = prefs.getString("username");
var password = prefs.getString("password");
loadTraces((function (dasHost, analyticsPath, timeBack) {
return dasHost + analyticsPath +
((dasHost.substr(dasHost.length - 1) == "/") ? "" : "/") +
((new Date()).getTime() - timeBack * 60 * 1000);
})(dasHost, analyticsPath, timeBack), timeBack, username, password, function (data) {
var traceGroups = groupTraceEvents(data);
renderTraceGroups(traceGroups, traceGroupsElm, traceTreeVw);
callback();
}, function (jqXHR) {
callback();
var errorData = $.parseJSON(jqXHR.responseText);
if (errorData) {
alert(errorData.message);
} else {
alert("Failed to load traces");
}
});
}
function initBarInfoView(rootElm, traceData, closeCallBack) {
var close = null;
function buildBarInfoVwModel(traceData) {
var vwModel = {
chttpMethod: "-",
shttpMethod: "-",
clientPath: "-",
serverPath: "-",
cStatusCode: "-",
sStatusCode: "-",
clientStartTime: "-",
serverStartTime: "-",
serverEndTime: "-",
clientEndTime: "-",
serverInstName: "-",
clientInstName: "-",
serverInstId: "-",
clientInstId: "-"
};
if (traceData.type == "CTS") {
vwModel.chttpMethod = traceData.httpMethod || "-";
vwModel.clientPath = traceData.url || "-";
vwModel.clientStartTime = traceData.timeStr || "-";
vwModel.clientEndTime = (traceData.end) ? traceData.end.timeStr || "-" : "-";
vwModel.clientInstName = traceData.clientName || "-";
vwModel.clientInstId = traceData.instanceId || "-";
vwModel.cStatusCode = (traceData.end) ? traceData.end.statusCode : "-";
if (traceData.service) {
vwModel.shttpMethod = traceData.service.httpMethod || "-";
vwModel.serverPath = traceData.service.url || "-";
vwModel.serverStartTime = traceData.service.timeStr || "-";
vwModel.serverEndTime = (traceData.service.end) ? traceData.service.end.timeStr || "-" : "-";
vwModel.serverInstName = traceData.instanceName || "-";
vwModel.serverInstId = traceData.service.instanceId || "-";
vwModel.sStatusCode = (traceData.service.end) ? traceData.service.end.statusCode : "-";
}
} else if (traceData.type == "STS") {
vwModel.shttpMethod = traceData.httpMethod || "-";
vwModel.serverPath = traceData.url || "-";
vwModel.serverStartTime = traceData.timeStr || "-";
vwModel.serverEndTime = (traceData.end) ? traceData.end.timeStr || "-" : "-";
vwModel.serverInstName = traceData.instanceName || "-";
vwModel.serverInstId = traceData.instanceId || "-";
vwModel.sStatusCode = (traceData.end) ? traceData.end.statusCode : "-";
}
return vwModel;
}
function show(traceData) {
var barInfoElm = $(
Mustache.render(
$('#bar-info').html(),
buildBarInfoVwModel(traceData)
)
);
close = function () {
barInfoElm.remove();
if (closeCallBack) {
closeCallBack();
}
};
// var closeBtnElm = barInfoElm.find(".close").first();
// closeBtnElm.click(close);
rootElm.append(barInfoElm);
}
return {
show: show,
close: function () {
if (close) {
close();
}
}
};
}
function initTraceTreeView(viewElm, containerElm, closeBtnElm) {
hide();
closeBtnElm.click(function () {
hide();
});
function clean() {
containerElm.empty();
}
function hide() {
clean();
viewElm.hide();
}
function renderTimeLine(start, end) {
var timeLineElm = $("#time-line");
var timeGaps = [
{
gap: 1,
unit: "ms",
unitMs: 1
},
{
gap: 5,
unit: "ms",
unitMs: 1
},
{
gap: 10,
unit: "ms",
unitMs: 1
},
{
gap: 100,
unit: "s",
unitMs: 1000
},
{
gap: 200,
unit: "s",
unitMs: 1000
},
{
gap: 500,
unit: "s",
unitMs: 1000
},
{
gap: 1000,
unit: "s",
unitMs: 1000
},
{
gap: 1000 * 5,
unit: "s",
unitMs: 1000
},
{
gap: 1000 * 10,
unit: "s",
unitMs: 1000
},
{
gap: 1000 * 60,
unit: "s",
unitMs: 1000 * 60
},
{
gap: 1000 * 60 * 5,
unit: "m",
unitMs: 1000 * 60
},
{
gap: 1000 * 60 * 10,
unit: "m",
unitMs: 1000 * 60
},
{
gap: 1000 * 60 * 60,
unit: "h",
unitMs: 1000 * 60 * 60
}
];
var timeDiff = end - start;
function render() {
var spaceDiff = timeLineElm.width();
var minGapWidth = 40;
var timeGap = (function () {
var timeGapsLen = timeGaps.length;
for (var i = 0; i < timeGapsLen; i++) {
var timeGap = timeGaps[i];
var gapCount = (timeDiff / timeGap.gap);
var gapWidth = spaceDiff / gapCount;
if (gapWidth >= minGapWidth) {
return timeGap;
}
}
return timeGaps[timeGapsLen - 1];
})();
var gapCount = (timeDiff / timeGap.gap);
var unitGap = timeGap.gap / timeGap.unitMs;
for (var i = 0; i < gapCount; i++) {
var left = (i * timeGap.gap) * 100 / timeDiff;
var unitElm = $(document.createElement("div"));
unitElm.attr("class", "unit");
unitElm.css("left", left + "%");
unitElm.html((i * unitGap).toFixed(3) + timeGap.unit);
timeLineElm.append(unitElm);
}
}
timeLineElm.empty();
render();
timeLineElm.resize(function () {
timeLineElm.empty();
render();
});
}
function show(traceTree) {
viewElm.show();
renderTraceTree(traceTree, buildOriginTraceBarVw(traceTree, traceTree.timeRange, 0));
renderTimeLine(traceTree.timeRange.start, traceTree.timeRange.end);
}
function buildOriginTraceBarVw(traceTree, timeRange, callDepth) {
var originTraceBarVw = buildTraceBarView(traceTree, timeRange, callDepth);
containerElm.append(originTraceBarVw.traceBarElm);
return originTraceBarVw;
}
function renderTraceTree(traceTree, parentTraceBarVw) {
var children = traceTree.children;
var childrenLen = children.length;
for (var i = 0; i < childrenLen; i++) {
var child = children[i];
var childTraceBarVw = buildTraceBarView(
child,
parentTraceBarVw.timeRange,
// Do not indent the service call of a client
(child.type == "STS") ? parentTraceBarVw.callDepth : parentTraceBarVw.callDepth + 1
);
parentTraceBarVw.addChildTraceBar(childTraceBarVw);
renderTraceTree(child, childTraceBarVw);
}
}
return {
show: function (traceTree) {
show(traceTree);
}
};
}
function buildTraceBarView(traceData, timeRange, callDepth) {
var traceBarElm = $(
Mustache.render(
$('#trace-bar').html()
)
);
var childContainerElm = traceBarElm.find(".child-container").first();
var leftPaneElm = traceBarElm.find(".left-pane").first();
var arrowElm = traceBarElm.find(".arrow").first();
var labelElm = traceBarElm.find(".label").first();
var barElm = traceBarElm.find(".bar").first();
var barInfoContElm = traceBarElm.find(".bar-info-container").first();
var childTraceBarVws = [];
var collapseChildren = null;
setName(traceData.instanceName);
setTimeRange(
traceData.time,
// If end time is not available, draw the bar to touch right end
(traceData.end) ? traceData.end.time : timeRange.end,
timeRange.start,
timeRange.end
);
setCallDepth(callDepth);
(function () {
var inforBarVw = null;
barElm.click(function () {
if (!inforBarVw) {
inforBarVw = initBarInfoView(barInfoContElm, traceData);
inforBarVw.show(traceData);
} else {
inforBarVw.close();
inforBarVw = null;
}
});
})();
(function (childTraceBarVws) {
var isHidden = false;
collapseChildren = function () {
if (traceData.children.length > 0) {
childContainerElm.hide();
labelElm.css("font-weight", "bold");
arrowElm.attr("class", "arrow-down");
var childTraceBarVwsLen = childTraceBarVws.length;
for (var i = 0; i < childTraceBarVwsLen; i++) {
childTraceBarVw = childTraceBarVws[i];
childTraceBarVw.collapseChildren();
}
isHidden = true;
}
};
if (traceData.children.length > 0) {
leftPaneElm.click(function () {
if (isHidden) {
childContainerElm.show();
labelElm.css("font-weight", "normal");
arrowElm.attr("class", "arrow");
isHidden = false;
} else {
collapseChildren();
}
});
} else {
arrowElm.attr("class", "arrow-hide");
}
})(childTraceBarVws);
function setTimeRange(startTime, endTime, rootStart, rootEnd) {
var left = 100 * (startTime - rootStart) / (rootEnd - rootStart);
var width = 100 * (endTime - startTime) / (rootEnd - rootStart);
barElm.css({
left: left + "%",
width: width + "%",
"background-color": (function shadeBlend(p, c0, c1) {
var n = p < 0 ? p * -1 : p, u = Math.round, w = parseInt;
if (c0.length > 7) {
var f = c0.split(","), t = (c1 ? c1 : p < 0 ? "rgb(0,0,0)" : "rgb(255,255,255)").split(","), R = w(f[0].slice(4)), G = w(f[1]), B = w(f[2]);
return "rgb(" + (u((w(t[0].slice(4)) - R) * n) + R) + "," + (u((w(t[1]) - G) * n) + G) + "," + (u((w(t[2]) - B) * n) + B) + ")"
} else {
var f = w(c0.slice(1), 16), t = w((c1 ? c1 : p < 0 ? "#000000" : "#FFFFFF").slice(1), 16), R1 = f >> 16, G1 = f >> 8 & 0x00FF, B1 = f & 0x0000FF;
return "#" + (0x1000000 + (u(((t >> 16) - R1) * n) + R1) * 0x10000 + (u(((t >> 8 & 0x00FF) - G1) * n) + G1) * 0x100 + (u(((t & 0x0000FF) - B1) * n) + B1)).toString(16).slice(1)
}
})((function () {
var p = callDepth * 0.1;
return (p > 0.4) ? 0.4 : p;
})(callDepth), "#005FB0")
});
}
function setName(name) {
labelElm.html(name);
}
function addChildTraceBar(traceBarVw) {
childTraceBarVws.push(traceBarVw);
childContainerElm.append(traceBarVw.traceBarElm);
}
function setCallDepth(callDepth) {
leftPaneElm.css("margin-left", callDepth * 15);
}
return {
traceBarElm: traceBarElm,
collapseChildren: collapseChildren,
timeRange: timeRange,
callDepth: callDepth,
addChildTraceBar: function (traceBarVw) {
addChildTraceBar(traceBarVw);
}
};
}
function loadTraces(url, timeBack, username, password, callback, errorCallback) {
$.ajax({
type: "GET",
beforeSend: function (request) {
if (!window.btoa) {
window.btoa = $.base64.btoa;
}
request.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
},
url: url,
data: "json",
processData: false,
success: callback,
error: errorCallback
});
}
function renderTraceGroups(traceGroups, rootElm, traceTreeVw) {
rootElm.empty();
itrValidTraceGroups(traceGroups, function (traceGroup) {
var traceGroupElm = $(
Mustache.render(
$('#trace-group').html(),
traceGroup
)
);
traceGroupElm.click(function () {
traceTreeVw.show(traceGroup.getTraceTree());
});
rootElm.prepend(traceGroupElm);
});
}
function groupTraceEvents(data) {
var traceGroups = {};
var dataLen = data.length;
for (var i = 0; i < dataLen; i++) {
var event = data[i].values;
if (!event || !event.originId) {
// Ignore the event if it is null or does not contain the original event ID
// Or the original event Id is invalid
continue;
}
var eventDate = new Date(event.time);
event.timeStr = eventDate.toTimeString()
.replace(" GMT", ":" + ("00" + eventDate.getMilliseconds()).slice(-3) + " GMT");
var traceGroup = traceGroups[event.originId];
if (!traceGroup) {
traceGroups[event.originId] = traceGroup = {
isBuilt: false,
timeRange: {
// The time range that the trace spans
// Required for drawing gantt bars to scale
start: Number.MAX_VALUE,
end: 0,
addStart: function (startTime) {
if (this.start > startTime) {
this.start = startTime;
}
},
addEnd: function (endTime) {
if (this.end < endTime) {
this.end = endTime;
}
}
},
origin: null,
events: {
start: {},
end: {}
},
addEvent: function (event) {
if (event.type == "STS" || event.type == "CTS") {
if (event.traceId == event.originId) {
// If this condition is met this is the first event of the trace
if (validateOriginEvent(event)) {
this.origin = event;
this.timeRange.addStart(event.time);
}
} else {
var children = this.events.start[event.parentId];
if (!children) {
this.events.start[event.parentId] = children = [];
}
children.push(event);
this.timeRange.addStart(event.time);
}
} else {
this.events.end[event.traceId] = event;
this.timeRange.addEnd(event.time);
}
},
getTraceTree: function () {
if (this.isBuilt) {
return this.origin;
} else {
var startEvents = this.events.start;
var endEvents = this.events.end;
var origin = this.origin;
origin.timeRange = this.timeRange;
var parents = [];
parents.push(origin);
while (Object.keys(startEvents).length > 0 || parents.length > 0) {
var parent = parents.shift();
parent.end = endEvents[parent.traceId];
parent.children = startEvents[parent.traceId] || [];
delete startEvents[parent.traceId];
var childrenLen = parent.children.length;
if (parent.type == "CTS") {
// Parent STS can have many children that are initiated multiple client calls
// Parent CTS will have only one child which is the service call (Merge it to CTS itself)
// In all iterations except the initial* iteration Parent will be CTS
if (childrenLen == 1) {
// The only child of CTS is a STS
// Add children of STS to CTS
var childSTS = parent.children[0];
childSTS.end = endEvents[childSTS.traceId];
parent.service = childSTS;
parent.clientName = parent.instanceName;
parent.instanceName = childSTS.instanceName;
parent.children = startEvents[childSTS.traceId] || [];
delete startEvents[childSTS.traceId];
}
}
parent.children.sort(function (a, b) {
return a.time - b.time;
});
childrenLen = parent.children.length;
for (var i = 0; i < childrenLen; i++) {
var childCTS = parent.children[i];
childCTS.end = endEvents[childCTS.traceId];
parents.push(childCTS);
}
}
this.isBuilt = true;
this.events = null;
console.log("TraceTree:");
console.log(origin);
if (origin.timeRange.end == 0) {
// This condition will satisfy if no end events are available
origin.timeRange.end = (new Date()).getTime();
}
return origin;
}
}
};
}
traceGroup.addEvent(event);
}
console.log("Trace groups:");
console.log(traceGroups);
return traceGroups;
}
function itrValidTraceGroups(traceGroups, callback) {
for (var key in traceGroups) {
if (!traceGroups.hasOwnProperty(key)) {
continue;
}
var traceGroup = traceGroups[key];
if (traceGroup.origin && validateOriginEvent(traceGroup.origin)) {
callback(traceGroup);
}
}
}
function validateOriginEvent(event) {
return event.instanceName && event.time && event.traceId && event.url && event.httpMethod && !event.parentId;
}
================================================
FILE: analytics/wso2das-tracing-capp/capp-content/artifacts.xml
================================================
================================================
FILE: analytics/wso2das-tracing-capp/pom.xml
================================================
org.wso2.msf4jmsf4j-parent2.8.14-SNAPSHOT../../poms/parent/pom.xml4.0.0wso2das-msf4j-tracingWSO2 DAS MSF4J message tracing C-Apporg.wso2.msf4jmsf4j-analyticsorg.apache.maven.pluginsmaven-assembly-pluginzip.xmlfalse${project.artifactId}-${project.version}make-assemblypackagesingleorg.apache.maven.pluginsmaven-antrun-pluginpackagerunorg.apache.maven.pluginsmaven-jar-plugindefault-jarnoneorg.wso2.msf4j.example.Application
================================================
FILE: analytics/wso2das-tracing-capp/zip.xml
================================================
bin/zipfalsecapp-content//
================================================
FILE: analytics/zipkin-tracing/pom.xml
================================================
4.0.0org.wso2.msf4jmsf4j-parent2.8.14-SNAPSHOT../../poms/parent/pom.xmlzipkin-tracingjarZipkin Tracing ModuleThis module provides Zipkin tracing support for MSF4J server-less mode.https://github.com/wso2/msf4jorg.wso2.msf4jmsf4j-coreio.zipkin.bravebrave-spancollector-httpio.zipkin.bravebrave-httporg.wso2.msf4jmsf4j-analytics-commonio.github.openfeignfeign-coreorg.testngtestngtestorg.apache.maven.pluginsmaven-compiler-pluginorg.apache.ratapache-rat-pluginorg.apache.maven.pluginsmaven-checkstyle-pluginorg.apache.maven.pluginsmaven-surefire-plugin-Dmsf4jTestRunningsrc/test/resources/testng.xmlorg.apache.maven.pluginsmaven-deploy-plugincoverageorg.apache.maven.pluginsmaven-surefire-plugin${argLine} -Xmx512morg.jacocojacoco-maven-pluginprepare-agentprepare-agentreportprepare-packagereportorg.jacocojacoco-maven-pluginreleaseorg.apache.maven.pluginsmaven-source-plugintrueattach-sourcespackagejar-no-forkorg.apache.maven.pluginsmaven-javadoc-plugintrue
http://docs.oracle.com/javaee/6/api/
*.internal.*
Licensed under the Apache License, Version 2.0]]>
attach-javadocpackagejarorg.apache.maven.pluginsmaven-gpg-plugin${gpg.passphrase}${gpg.useagent}signorg.apache.maven.pluginsmaven-source-pluginorg.apache.maven.pluginsmaven-javadoc-pluginorg.apache.maven.pluginsmaven-gpg-plugin
================================================
FILE: analytics/zipkin-tracing/src/main/java/org/wso2/msf4j/analytics/zipkintracing/MSF4JZipkinTracingInterceptor.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://wso2.com) All Rights Reserved.
*
* 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 org.wso2.msf4j.analytics.zipkintracing;
import com.github.kristofa.brave.Brave;
import com.github.kristofa.brave.EmptySpanCollectorMetricsHandler;
import com.github.kristofa.brave.ServerRequestInterceptor;
import com.github.kristofa.brave.ServerResponseInterceptor;
import com.github.kristofa.brave.http.DefaultSpanNameProvider;
import com.github.kristofa.brave.http.HttpResponse;
import com.github.kristofa.brave.http.HttpServerRequest;
import com.github.kristofa.brave.http.HttpServerRequestAdapter;
import com.github.kristofa.brave.http.HttpServerResponseAdapter;
import com.github.kristofa.brave.http.HttpSpanCollector;
import org.wso2.msf4j.Interceptor;
import org.wso2.msf4j.Request;
import org.wso2.msf4j.Response;
import org.wso2.msf4j.ServiceMethodInfo;
import org.wso2.msf4j.analytics.common.tracing.TracingConstants;
/**
* Interceptor for tracing server side request/response flows to Zipkin.
*/
public class MSF4JZipkinTracingInterceptor implements Interceptor {
private final ServerRequestInterceptor reqInterceptor;
private final ServerResponseInterceptor respInterceptor;
private static final String RESPONDER_ATTRIBUTE = "responder-attribute";
/**
* Constructor of the MSF4JTracingInterceptor.
*
* @param microServiceName Name of the Microservice
*/
public MSF4JZipkinTracingInterceptor(String microServiceName) {
this(microServiceName, TracingConstants.DEFAULT_ZIPKIN_URL);
}
/**
* Constructor of the MSF4JTracingInterceptor.
*
* @param microServiceName Name of the Microservice
* @param zipkinUrl Base URL of the Zipkin server
*/
public MSF4JZipkinTracingInterceptor(String microServiceName, String zipkinUrl) {
Brave.Builder builder = new Brave.Builder(microServiceName);
builder.spanCollector(HttpSpanCollector.create(zipkinUrl, new EmptySpanCollectorMetricsHandler()));
Brave brave = builder.build();
reqInterceptor = brave.serverRequestInterceptor();
respInterceptor = brave.serverResponseInterceptor();
}
/**
* Intercepts the server request flow and extract request information
* to be published to the Zipkin server for tracing.
*/
@Override
public boolean preCall(Request request, Response responder, ServiceMethodInfo serviceMethodInfo) throws Exception {
serviceMethodInfo.setAttribute(RESPONDER_ATTRIBUTE, responder);
HttpServerRequest req = new TraceableHttpServerRequest(request);
HttpServerRequestAdapter reqAdapter = new HttpServerRequestAdapter(req, new DefaultSpanNameProvider());
reqInterceptor.handle(reqAdapter);
return true;
}
/**
* Intercepts the server response flow and extract response information
* to be published to the Zipkin server for tracing.
*/
@Override
public void postCall(Request request, int status, ServiceMethodInfo serviceMethodInfo) throws Exception {
HttpResponse httpResponse = new TraceableHttpServerResponse((Response) serviceMethodInfo
.getAttribute(RESPONDER_ATTRIBUTE));
HttpServerResponseAdapter adapter = new HttpServerResponseAdapter(httpResponse);
respInterceptor.handle(adapter);
}
}
================================================
FILE: analytics/zipkin-tracing/src/main/java/org/wso2/msf4j/analytics/zipkintracing/TraceableHttpClientRequest.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you 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 org.wso2.msf4j.analytics.zipkintracing;
import com.github.kristofa.brave.http.HttpClientRequest;
import feign.Request;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
/**
* Adaptor class for client side request object tracing
*/
public class TraceableHttpClientRequest implements HttpClientRequest {
private final Request request;
public TraceableHttpClientRequest(Request request) {
this.request = request;
}
@Override
public void addHeader(String header, String value) {
Collection existingValues = request.headers().get(header);
if (existingValues == null) {
existingValues = new ArrayList<>();
}
existingValues.add(value);
request.headers().put(header, existingValues);
}
@Override
public URI getUri() {
return URI.create(request.url());
}
@Override
public String getHttpMethod() {
return request.method();
}
}
================================================
FILE: analytics/zipkin-tracing/src/main/java/org/wso2/msf4j/analytics/zipkintracing/TraceableHttpClientResponse.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you 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 org.wso2.msf4j.analytics.zipkintracing;
import com.github.kristofa.brave.http.HttpResponse;
import feign.Response;
/**
* Adaptor class for client side response object tracing
*/
public class TraceableHttpClientResponse implements HttpResponse {
private final Response response;
public TraceableHttpClientResponse(Response response) {
this.response = response;
}
@Override
public int getHttpStatusCode() {
return response.status();
}
}
================================================
FILE: analytics/zipkin-tracing/src/main/java/org/wso2/msf4j/analytics/zipkintracing/TraceableHttpServerRequest.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you 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 org.wso2.msf4j.analytics.zipkintracing;
import com.github.kristofa.brave.http.HttpServerRequest;
import org.wso2.msf4j.Request;
import java.net.URI;
/**
* Adaptor class for server side request object tracing
*/
public class TraceableHttpServerRequest implements HttpServerRequest {
private final Request req;
TraceableHttpServerRequest(Request req) {
this.req = req;
}
@Override
public String getHttpHeaderValue(String headerName) {
return req.getHeader(headerName);
}
@Override
public URI getUri() {
return URI.create(req.getUri());
}
@Override
public String getHttpMethod() {
return req.getHttpMethod();
}
}
================================================
FILE: analytics/zipkin-tracing/src/main/java/org/wso2/msf4j/analytics/zipkintracing/TraceableHttpServerResponse.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you 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 org.wso2.msf4j.analytics.zipkintracing;
import com.github.kristofa.brave.http.HttpResponse;
import org.wso2.msf4j.Response;
/**
* Adaptor class for server side response object tracing
*/
public class TraceableHttpServerResponse implements HttpResponse {
private Response response;
TraceableHttpServerResponse(Response response) {
this.response = response;
}
@Override
public int getHttpStatusCode() {
return response.getStatusCode();
}
}
================================================
FILE: analytics/zipkin-tracing/src/test/java/org/wso2/msf4j/analytics/zipkintracing/TraceableHttpClientRequestTest.java
================================================
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* 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 org.wso2.msf4j.analytics.zipkintracing;
import com.github.kristofa.brave.http.HttpClientRequest;
import feign.Request;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.net.MalformedURLException;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.HashMap;
import javax.ws.rs.HttpMethod;
/**
* Class for testing TraceableHttpClient.
*/
public class TraceableHttpClientRequestTest extends Assert {
private Request request;
private HttpClientRequest httpRequest;
@BeforeClass
public void setUp() throws MalformedURLException {
request = Request.create(HttpMethod.GET, URI.create("msf4j").toString(), new HashMap<>(), null,
Charset.defaultCharset());
httpRequest = new TraceableHttpClientRequest(request);
}
@Test
public void testAddHeader() {
httpRequest.addHeader("testK", "testV");
assertTrue(request.headers().get("testK").contains("testV"));
}
@Test
public void testGetUri() {
assertEquals(httpRequest.getUri(), URI.create("msf4j"));
}
@Test
public void testGetHttpMethod() {
assertEquals(httpRequest.getHttpMethod(), HttpMethod.GET);
}
}
================================================
FILE: analytics/zipkin-tracing/src/test/java/org/wso2/msf4j/analytics/zipkintracing/TraceableHttpClientResponseTest.java
================================================
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* 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 org.wso2.msf4j.analytics.zipkintracing;
import com.github.kristofa.brave.http.HttpResponse;
import feign.Response;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.io.IOException;
import java.util.HashMap;
/**
* Class for testing TraceableHttpClientResponse.
*/
public class TraceableHttpClientResponseTest extends Assert {
private Response response;
private HttpResponse httpResponse;
@BeforeClass
public void setUp() throws IOException {
response = Response.builder().status(200).headers(new HashMap<>()).build();
httpResponse = new TraceableHttpClientResponse(response);
}
@Test
public void testGetStatusCode() {
assertEquals(httpResponse.getHttpStatusCode(), response.status());
}
}
================================================
FILE: analytics/zipkin-tracing/src/test/java/org/wso2/msf4j/analytics/zipkintracing/TraceableHttpServerRequestTest.java
================================================
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* 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 org.wso2.msf4j.analytics.zipkintracing;
import com.github.kristofa.brave.http.HttpServerRequest;
import io.netty.handler.codec.http.DefaultHttpRequest;
import io.netty.handler.codec.http.HttpVersion;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.wso2.msf4j.Request;
import org.wso2.transport.http.netty.message.HttpCarbonMessage;
import java.io.IOException;
import java.net.URI;
import javax.ws.rs.HttpMethod;
/**
* Class for testing TraceableHttpServerRequest.
*/
public class TraceableHttpServerRequestTest extends Assert {
private Request request;
private HttpServerRequest httpServerRequest;
@BeforeClass
public void setUp() throws IOException {
HttpCarbonMessage httpCarbonMessage = new HttpCarbonMessage(
new DefaultHttpRequest(HttpVersion.HTTP_1_1, io.netty.handler.codec.http.HttpMethod.GET, "msf4j"));
httpCarbonMessage.setHeader("testK", "testV");
httpCarbonMessage.setHttpMethod(HttpMethod.GET);
request = new Request(httpCarbonMessage);
request.setProperty("TO", "msf4j");
httpServerRequest = new TraceableHttpServerRequest(request);
}
@Test
public void testGetHeader() {
assertEquals(httpServerRequest.getHttpHeaderValue("testK"), "testV");
}
@Test
public void testGetUrl() {
assertEquals(httpServerRequest.getUri(), URI.create("msf4j"));
}
@Test
public void testGetHttpMethod() {
assertEquals(httpServerRequest.getHttpMethod(), HttpMethod.GET);
}
}
================================================
FILE: analytics/zipkin-tracing/src/test/java/org/wso2/msf4j/analytics/zipkintracing/TraceableHttpServerResponseTest.java
================================================
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* 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 org.wso2.msf4j.analytics.zipkintracing;
import com.github.kristofa.brave.http.HttpResponse;
import io.netty.handler.codec.http.DefaultHttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.wso2.msf4j.Response;
import org.wso2.transport.http.netty.message.HttpCarbonMessage;
import java.io.IOException;
/**
* Class for testing TraceableHttpServerResponse.
*/
public class TraceableHttpServerResponseTest extends Assert {
private Response response;
private HttpResponse httpResponse;
@BeforeClass
public void setUp() throws IOException {
HttpCarbonMessage httpCarbonMessage =
new HttpCarbonMessage(new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK));
response = new Response(httpCarbonMessage);
response.setStatus(200);
httpResponse = new TraceableHttpServerResponse(response);
}
@Test
public void testGetStatusCode() {
assertEquals(httpResponse.getHttpStatusCode(), response.getStatusCode());
}
}
================================================
FILE: analytics/zipkin-tracing/src/test/resources/testng.xml
================================================
================================================
FILE: archetypes/README.md
================================================
#Creating a Microservice using the msf4j-microservice Maven archetype
A Microservice based on WSO2 Microservices Framework for Java (MSF4J) can be created with single command
using this Maven archetype.
Here is an example;
```
mvn archetype:generate -DarchetypeGroupId=org.wso2.msf4j -DarchetypeArtifactId=msf4j-microservice
-DarchetypeVersion=2.6.2 -DgroupId=org.example -DartifactId=myservice -Dversion=1.0.0-SNAPSHOT
-Dpackage=org.example.service
```
The above command will create an MSF4J microservice project structure for you similar to the one shown below;
```
myservice
├── pom.xml
└── src
└── main
└── java
└── org
└── example
└── service
├── Application.java
└── MyService.java
```
##Properties
The following table lists down the properties specific to the msf4j-microservice Maven archetype;
| Property | Description | Mandatory/Optional |
| ------------------- | ------------------------------- | ------------------ |
| archetypeGroupId | The groupId of the archetype | Mandatory |
| archetypeArtifactId | The artifactId of the archetype | Mandatory |
| archetypeVersion | The version of the archetype | Optional |
The table below lists down the properties which are specific to the project you create.
| Property | Description | Default value |
| --------------- | ------------------------------------ | --------------------------- |
| groupId | The groupId of the project | org.example |
| artifactId | The artifactId of the project | msf4j-service |
| version | The version of the project | 1.0.0-SNAPSHOT |
| package | The package hierarchy of the project | org.example.service |
| serviceClass | The names of the microservice class | org.example.service |
For more information about Maven archetypes, see [http://maven.apache.org/archetype/maven-archetype-plugin/generate-mojo.html](http://maven.apache.org/archetype/maven-archetype-plugin/generate-mojo.html)
================================================
FILE: archetypes/msf4j-microservice/pom.xml
================================================
org.wso2.msf4jmsf4j-parent2.8.14-SNAPSHOT../../poms/parent/pom.xml4.0.0msf4j-microservicemaven-archetypeWSO2 MSF4J - Microservice ArchetypeThis an archetype for WSO2 MSF4J microservice${project.basedir}/src/main/resourcestrue**/*org.apache.maven.pluginsmaven-resources-plugin^*^false
================================================
FILE: archetypes/msf4j-microservice/src/main/resources/META-INF/maven/archetype-metadata.xml
================================================
src/main/java**/*.javaorg.examplemsf4j-service1.0.0-SNAPSHOTorg.example.serviceMyService
================================================
FILE: archetypes/msf4j-microservice/src/main/resources/archetype-resources/pom.xml
================================================
org.wso2.msf4jmsf4j-service^project.version^4.0.0${groupId}${artifactId}${version}WSO2 MSF4J Microservice${package}.Application
================================================
FILE: archetypes/msf4j-microservice/src/main/resources/archetype-resources/src/main/java/Application.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://wso2.com) All Rights Reserved.
*
* 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 ${package};
import org.wso2.msf4j.MicroservicesRunner;
/**
* Application entry point.
*
* @since ${version}
*/
public class Application {
public static void main(String[] args) {
new MicroservicesRunner()
.deploy(new ${serviceClass}())
.start();
}
}
================================================
FILE: archetypes/msf4j-microservice/src/main/resources/archetype-resources/src/main/java/__serviceClass__.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://wso2.com) All Rights Reserved.
*
* 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 ${package};
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
/**
* This is the Microservice resource class.
* See https://github.com/wso2/msf4j#getting-started
* for the usage of annotations.
*
* @since ${version}
*/
@Path("/service")
public class ${serviceClass} {
@GET
@Path("/")
public String get() {
// TODO: Implementation for HTTP GET request
System.out.println("GET invoked");
return "Hello from WSO2 MSF4J";
}
@POST
@Path("/")
public void post() {
// TODO: Implementation for HTTP POST request
System.out.println("POST invoked");
}
@PUT
@Path("/")
public void put() {
// TODO: Implementation for HTTP PUT request
System.out.println("PUT invoked");
}
@DELETE
@Path("/")
public void delete() {
// TODO: Implementation for HTTP DELETE request
System.out.println("DELETE invoked");
}
}
================================================
FILE: client/README.md
================================================
# MSF4J Client
MSF4J client which allow making HTTP calls to other microservices as well as external APIs.
================================================
FILE: client/pom.xml
================================================
4.0.0org.wso2.msf4jmsf4j-parent2.8.14-SNAPSHOT../poms/parent/pom.xmlmsf4j-clientbundleWSO2 MSF4J clientWSO2 MSF4J clienthttps://github.com/wso2/msf4jorg.wso2.msf4jmsf4j-analyticsorg.wso2.msf4jmsf4j-coreorg.wso2.orbit.org.apache.httpcomponentshttpclientio.github.openfeignfeign-coreio.github.openfeignfeign-jacksoncom.fasterxml.jackson.corejackson-databindio.github.openfeignfeign-gsonio.github.openfeignfeign-hystrixorg.apache.httpcomponentshttpclient-osgiorg.apache.httpcomponentshttpcore-osgicom.fasterxml.jackson.corejackson-corecom.fasterxml.jackson.corejackson-databindcom.fasterxml.jackson.corejackson-annotationsio.zipkin.bravebrave-spancollector-httpio.zipkin.bravebrave-httporg.wso2.msf4jzipkin-tracingorg.wso2.carbon.utilsorg.wso2.carbon.utilsorg.wso2.msf4jmsf4j-coreorg.testngtestngorg.wso2.msf4j.internal.*
!org.wso2.msf4j.client.internal.*,
org.wso2.msf4j.client.*;version="${msf4j.version}"
feign.*;version="${feign.version}",
feign.gson.*;version="${feign.version}",
com.google.gson.*;version="${gson.version.range}",
com.google.common.*;version="${guava.version.range}",
javax.annotation.*,
javax.ws.rs.*,
javax.xml.bind;resolution:=optional,
javax.xml.bind.annotation;resolution:=optional,
org.osgi.framework.*;version="${osgi.framework.import.version.range}",
org.osgi.util.tracker; version="${osgi.service.tracker.import.version.range}",
com.github.kristofa.brave.*;resolution:=optional,
org.wso2.msf4j.analytics.*;version="${msf4j.version}";resolution:=optional,
org.slf4j.*;version="${slf4j.version.range}";resolution:=optional,
================================================
FILE: client/src/main/java/org/wso2/msf4j/client/ApacheHttpClient.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you 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 org.wso2.msf4j.client;
import feign.Client;
import feign.Request;
import feign.Response;
import feign.Util;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static feign.Util.UTF_8;
/**
* This module directs Feign's http requests to Apache's
* HttpClient. Ex.
*
* GitHub github = Feign.builder().client(new ApacheHttpClient()).target(GitHub.class,
* "https://api.github.com");
*
* Based on Square, Inc's Retrofit ApacheClient implementation
*/
public final class ApacheHttpClient implements Client {
private static final String ACCEPT_HEADER_NAME = "Accept";
private final ThreadLocal httpContextThreadLocal = new ThreadLocal<>();
private final HttpClient client;
public ApacheHttpClient() {
this(HttpClientBuilder.create().build());
}
public ApacheHttpClient(HttpClient client) {
this.client = client;
}
@Override
public Response execute(Request request, Request.Options options) throws IOException {
HttpUriRequest httpUriRequest;
HttpContext httpContext = httpContextThreadLocal.get();
if (httpContext == null) {
CookieStore cookieStore = new BasicCookieStore();
httpContext = new BasicHttpContext();
httpContext.setAttribute(HttpClientContext.COOKIE_STORE, cookieStore);
httpContextThreadLocal.set(httpContext);
}
try {
httpUriRequest = toHttpUriRequest(request, options);
} catch (URISyntaxException e) {
throw new IOException("URL '" + request.url() + "' couldn't be parsed into a URI", e);
}
HttpResponse httpResponse = client.execute(httpUriRequest, httpContext);
return toFeignResponse(httpResponse).toBuilder().request(request).build();
}
HttpUriRequest toHttpUriRequest(Request request, Request.Options options) throws
UnsupportedEncodingException, MalformedURLException, URISyntaxException {
RequestBuilder requestBuilder = RequestBuilder.create(request.method());
//per request timeouts
RequestConfig requestConfig = RequestConfig
.custom()
.setConnectTimeout(options.connectTimeoutMillis())
.setSocketTimeout(options.readTimeoutMillis())
.build();
requestBuilder.setConfig(requestConfig);
URI uri = new URIBuilder(request.url()).build();
requestBuilder.setUri(uri.getScheme() + "://" + uri.getAuthority() + uri.getRawPath());
//request query params
List queryParams = URLEncodedUtils.parse(uri, requestBuilder.getCharset().name
());
for (NameValuePair queryParam : queryParams) {
requestBuilder.addParameter(queryParam);
}
//request headers
boolean hasAcceptHeader = false;
for (Map.Entry> headerEntry : request.headers().entrySet()) {
String headerName = headerEntry.getKey();
if (headerName.equalsIgnoreCase(ACCEPT_HEADER_NAME)) {
hasAcceptHeader = true;
}
if (headerName.equalsIgnoreCase(Util.CONTENT_LENGTH)) {
// The 'Content-Length' header is always set by the Apache client and it
// doesn't like us to set it as well.
continue;
}
for (String headerValue : headerEntry.getValue()) {
requestBuilder.addHeader(headerName, headerValue);
}
}
//some servers choke on the default accept string, so we'll set it to anything
if (!hasAcceptHeader) {
requestBuilder.addHeader(ACCEPT_HEADER_NAME, "*/*");
}
//request body
if (request.body() != null) {
HttpEntity entity = null;
if (request.charset() != null) {
ContentType contentType = getContentType(request);
String content = new String(request.body(), request.charset());
entity = new StringEntity(content, contentType);
} else {
entity = new ByteArrayEntity(request.body());
}
requestBuilder.setEntity(entity);
}
return requestBuilder.build();
}
private ContentType getContentType(Request request) {
ContentType contentType = ContentType.DEFAULT_TEXT;
for (Map.Entry> entry : request.headers().entrySet()) {
if (entry.getKey().equalsIgnoreCase("Content-Type")) {
Collection values = entry.getValue();
if (values != null && !values.isEmpty()) {
contentType = ContentType.create(entry.getValue().iterator().next(), request.charset());
break;
}
}
}
return contentType;
}
Response toFeignResponse(HttpResponse httpResponse) throws IOException {
StatusLine statusLine = httpResponse.getStatusLine();
int statusCode = statusLine.getStatusCode();
String reason = statusLine.getReasonPhrase();
Map> headers = new HashMap>();
for (Header header : httpResponse.getAllHeaders()) {
String name = header.getName();
String value = header.getValue();
Collection headerValues = headers.get(name);
if (headerValues == null) {
headerValues = new ArrayList();
headers.put(name, headerValues);
}
headerValues.add(value);
}
return Response.builder()
.status(statusCode)
.reason(reason)
.headers(headers)
.body(toFeignBody(httpResponse))
.build();
}
Response.Body toFeignBody(HttpResponse httpResponse) throws IOException {
final HttpEntity entity = httpResponse.getEntity();
if (entity == null) {
return null;
}
return new HttpEntityResponseBody(entity);
}
/**
* Implements {@link feign.Response.Body} which represents HTTP response body
*/
private static class HttpEntityResponseBody implements Response.Body {
final HttpEntity entity;
HttpEntityResponseBody(HttpEntity entity) {
this.entity = entity;
}
@Override
public Integer length() {
return entity.getContentLength() >= 0 && entity.getContentLength() <= Integer.MAX_VALUE ?
(int) entity.getContentLength() : null;
}
@Override
public boolean isRepeatable() {
return entity.isRepeatable();
}
@Override
public InputStream asInputStream() throws IOException {
return entity.getContent();
}
@Override
public Reader asReader() throws IOException {
return new InputStreamReader(asInputStream(), UTF_8);
}
@Override
public void close() throws IOException {
EntityUtils.consume(entity);
}
}
}
================================================
FILE: client/src/main/java/org/wso2/msf4j/client/FeginZipkinTracingClient.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* 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 org.wso2.msf4j.client;
import com.github.kristofa.brave.Brave;
import com.github.kristofa.brave.ClientRequestAdapter;
import com.github.kristofa.brave.ClientRequestInterceptor;
import com.github.kristofa.brave.ClientResponseAdapter;
import com.github.kristofa.brave.ClientResponseInterceptor;
import com.github.kristofa.brave.EmptySpanCollectorMetricsHandler;
import com.github.kristofa.brave.http.DefaultSpanNameProvider;
import com.github.kristofa.brave.http.HttpClientRequest;
import com.github.kristofa.brave.http.HttpClientRequestAdapter;
import com.github.kristofa.brave.http.HttpClientResponseAdapter;
import com.github.kristofa.brave.http.HttpResponse;
import com.github.kristofa.brave.http.HttpSpanCollector;
import feign.Client;
import feign.Request;
import feign.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wso2.msf4j.analytics.common.tracing.TracingConstants;
import org.wso2.msf4j.analytics.zipkintracing.TraceableHttpClientRequest;
import org.wso2.msf4j.analytics.zipkintracing.TraceableHttpClientResponse;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* Client for Zipkin Tracing.
*/
public class FeginZipkinTracingClient implements Client {
private static final Logger log = LoggerFactory.getLogger(FeignTracingClient.class);
private final Client clientDelegate;
private final ClientRequestInterceptor requestInterceptor;
private final ClientResponseInterceptor responseInterceptor;
/**
* Constructor of FeignTracingClient.
*/
public FeginZipkinTracingClient(Client client, String instanceName) {
this(client, instanceName, TracingConstants.DEFAULT_ZIPKIN_URL);
}
/**
* Constructor of FeginZipkinTracingClient.
*
* @param client
* @param instanceName
* @param zipkinUrl URL of the receiver of DAS server.
*/
public FeginZipkinTracingClient(Client client, String instanceName, String zipkinUrl) {
this.clientDelegate = client;
Brave.Builder builder = new Brave.Builder(instanceName);
builder.spanCollector(HttpSpanCollector.create(zipkinUrl, new EmptySpanCollectorMetricsHandler()));
Brave brave = builder.build();
requestInterceptor = brave.clientRequestInterceptor();
responseInterceptor = brave.clientResponseInterceptor();
}
@Override
public Response execute(Request request, Request.Options options) throws IOException {
Map> traceHeaders = new HashMap<>();
traceHeaders.putAll(request.headers());
Request wrappedRequest =
Request.create(request.method(), request.url(), traceHeaders, request.body(), request.charset());
HttpClientRequest httpClientRequest = new TraceableHttpClientRequest(wrappedRequest);
ClientRequestAdapter adapter = new HttpClientRequestAdapter(httpClientRequest, new DefaultSpanNameProvider());
requestInterceptor.handle(adapter);
Response response = clientDelegate.execute(wrappedRequest, options);
HttpResponse httpResponse = new TraceableHttpClientResponse(response);
ClientResponseAdapter responseAdapter = new HttpClientResponseAdapter(httpResponse);
responseInterceptor.handle(responseAdapter);
return response;
}
}
================================================
FILE: client/src/main/java/org/wso2/msf4j/client/FeignClientWrapper.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* 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 org.wso2.msf4j.client;
import feign.Client;
import feign.Request;
import feign.Response;
import java.io.IOException;
/**
* Wrapper for #Feign.Client
*/
public class FeignClientWrapper implements Client {
private final Client clientDelegate;
public FeignClientWrapper(Client client) {
this.clientDelegate = client;
}
@Override
public Response execute(Request request, Request.Options options) throws IOException {
return clientDelegate.execute(request, options);
}
}
================================================
FILE: client/src/main/java/org/wso2/msf4j/client/FeignTracingClient.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* 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 org.wso2.msf4j.client;
import feign.Client;
import feign.Request;
import feign.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wso2.msf4j.analytics.common.tracing.TraceEvent;
import org.wso2.msf4j.analytics.common.tracing.TracingConstants;
import org.wso2.msf4j.analytics.common.tracing.TracingEventTracker;
import org.wso2.msf4j.analytics.common.tracing.TracingUtil;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* Supports tracing capabilities with WSO2DAS
*/
class FeignTracingClient implements Client {
private static final Logger log = LoggerFactory.getLogger(FeignTracingClient.class);
private final String instanceId;
private final String instanceName;
private final String dasUrl;
private final Client clientDelegate;
/**
* Constructor of FeignTracingClient.
*/
public FeignTracingClient(Client client, String instanceName) {
this(client, instanceName, TracingConstants.DAS_RECEIVER_URL);
}
/**
* Constructor of FeignTracingClient with custom SSL configuration
*
* @param dasReceiverUrl URL of the receiver of DAS server
*/
public FeignTracingClient(Client client, String instanceName, String dasReceiverUrl) {
this.instanceName = instanceName;
this.dasUrl = dasReceiverUrl;
this.instanceId = TracingUtil.generateUniqueId();
this.clientDelegate = client;
}
@Override
public Response execute(Request request, Request.Options options) throws IOException {
TraceEvent clientStartTraceEvent = generateClientStartTraceEvent(request);
Request traceableRequest = tracePreRequest(request, clientStartTraceEvent);
Response response = clientDelegate.execute(traceableRequest, options);
tracePostRequest(response, clientStartTraceEvent);
return response;
}
private TraceEvent generateClientStartTraceEvent(Request request) {
long time = new Date().getTime();
String clientTraceId;
String traceOriginId;
String traceParentId = null;
TraceEvent parentEvent = TracingEventTracker.getTraceEvent();
if (parentEvent == null) {
traceOriginId = TracingUtil.generateUniqueId();
clientTraceId = traceOriginId;
} else {
traceOriginId = parentEvent.getOriginId();
clientTraceId = TracingUtil.generateUniqueId();
traceParentId = parentEvent.getTraceId();
}
TraceEvent clientStartTraceEvent = new TraceEvent(
TracingConstants.CLIENT_TRACE_START,
clientTraceId,
traceOriginId,
time
);
clientStartTraceEvent.setInstanceId(instanceId);
clientStartTraceEvent.setInstanceName(instanceName);
clientStartTraceEvent.setParentId(traceParentId);
clientStartTraceEvent.setHttpMethod(request.method());
clientStartTraceEvent.setUrl(request.url());
if (log.isDebugEnabled()) {
log.debug("clientStartTraceEvent: " + ModelUtils.toString(clientStartTraceEvent));
}
return clientStartTraceEvent;
}
private Request tracePreRequest(Request request, TraceEvent traceEvent) {
// set tracing headers to HTTP request
Map> traceHeaders = new HashMap<>();
traceHeaders.putAll(request.headers());
traceHeaders.put(TracingConstants.TRACE_ID_HEADER, Collections.singletonList(traceEvent.getTraceId()));
traceHeaders.put(TracingConstants.TRACE_ORIGIN_ID_HEADER, Collections.singletonList(traceEvent.getOriginId()));
// publish event to DAS
TracingUtil.pushToDAS(traceEvent, dasUrl);
return Request.create(request.method(), request.url(), traceHeaders, request.body(), request.charset());
}
/**
* Publish client request information to DAS after response is received
*/
private void tracePostRequest(Response response, TraceEvent traceEvent) {
long time = new Date().getTime();
if (traceEvent != null) {
TraceEvent clientEndTraceEvent = new TraceEvent(
TracingConstants.CLIENT_TRACE_END,
traceEvent.getTraceId(),
traceEvent.getOriginId(),
time
);
clientEndTraceEvent.setStatusCode(response.status());
if (log.isDebugEnabled()) {
log.debug("ClientEndTraceEvent: " + ModelUtils.toString(clientEndTraceEvent));
}
TracingUtil.pushToDAS(clientEndTraceEvent, dasUrl);
}
}
}
================================================
FILE: client/src/main/java/org/wso2/msf4j/client/MSF4JClient.java
================================================
/*
* Copyright (c) 2016 WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you 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 org.wso2.msf4j.client;
import feign.Client;
import feign.Feign;
import feign.RequestInterceptor;
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.codec.ErrorDecoder;
import feign.gson.GsonDecoder;
import feign.gson.GsonEncoder;
import feign.hystrix.FallbackFactory;
import feign.hystrix.HystrixFeign;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wso2.carbon.utils.StringUtils;
import org.wso2.msf4j.analytics.common.tracing.TracingConstants;
import org.wso2.msf4j.client.codec.DefaultErrorDecoder;
import org.wso2.msf4j.client.codec.RestErrorResponseMapper;
import org.wso2.msf4j.client.exception.RestServiceException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
/**
* MSF4J client.
*
* @param REST service API interface
*/
public class MSF4JClient {
private static final Logger log = LoggerFactory.getLogger(MSF4JClient.class);
private final T api;
public MSF4JClient(T api) {
this.api = api;
}
public T api() {
return api;
}
/**
* MSF4J client builder
*
* @param API interface
*/
public static class Builder {
private final List requestInterceptors = new ArrayList();
private final Map> errorCodeExceptionMap = new HashMap<>();
private FallbackFactory extends T> fallbackFactory;
private boolean enableCircuitBreaker;
private boolean enableTracing;
private String instanceName;
private String analyticsEndpoint;
private String serviceEndpoint;
private SSLContext sslContext;
private HostnameVerifier hostnameVerifier;
private boolean decode404;
private Class apiClass;
private ErrorDecoder errorDecoder = new DefaultErrorDecoder(errorCodeExceptionMap);
private Encoder encoder = new GsonEncoder(ModelUtils.GSON);
private Decoder decoder = new GsonDecoder(ModelUtils.GSON);
private TracingConstants.TracingType tracingType = TracingConstants.TracingType.DAS;
public Feign.Builder newFeignClientBuilder() {
return Feign.builder()
.encoder(encoder)
.decoder(decoder);
}
public HystrixFeign.Builder newHystrixFeignClientBuilder() {
return HystrixFeign.builder()
.encoder(encoder)
.decoder(decoder);
}
/**
* Adds a single request interceptor to the builder.
*/
public MSF4JClient.Builder requestInterceptor(RequestInterceptor requestInterceptor) {
this.requestInterceptors.add(requestInterceptor);
return this;
}
/**
* Sets the full set of request interceptors for the builder, overwriting any previous
* interceptors.
*/
public MSF4JClient.Builder requestInterceptors(Iterable requestInterceptors) {
this.requestInterceptors.clear();
for (RequestInterceptor requestInterceptor : requestInterceptors) {
this.requestInterceptors.add(requestInterceptor);
}
return this;
}
/**
* Sets the fallback factory for HystrixFeign client which supports circuit breaker
*/
public MSF4JClient.Builder fallbackFactory(FallbackFactory extends T> fallbackFactory) {
this.fallbackFactory = fallbackFactory;
return this;
}
public MSF4JClient.Builder enableCircuitBreaker() {
this.enableCircuitBreaker = true;
return this;
}
public MSF4JClient.Builder enableTracing() {
this.enableTracing = true;
return this;
}
public MSF4JClient.Builder instanceName(String instanceName) {
this.instanceName = instanceName;
return this;
}
public MSF4JClient.Builder analyticsEndpoint(String analyticsEndpoint) {
this.analyticsEndpoint = analyticsEndpoint;
return this;
}
public MSF4JClient.Builder serviceEndpoint(String serviceEndpoint) {
this.serviceEndpoint = serviceEndpoint;
return this;
}
public MSF4JClient.Builder apiClass(Class apiClass) {
this.apiClass = apiClass;
return this;
}
public MSF4JClient.Builder decode404(boolean decode404) {
this.decode404 = decode404;
return this;
}
public MSF4JClient.Builder encoder(Encoder encoder) {
this.encoder = encoder;
return this;
}
public MSF4JClient.Builder decoder(Decoder decoder) {
this.decoder = decoder;
return this;
}
public MSF4JClient.Builder tracingType(TracingConstants.TracingType tracingType) {
this.tracingType = tracingType;
return this;
}
public MSF4JClient.Builder addErrorResponseMapper(RestErrorResponseMapper... responseMappers) {
Arrays.stream(responseMappers).forEach(rm -> {
Arrays.stream(rm.getClass().getMethods()).
filter(method -> !StringUtils.isNullOrEmptyAfterTrim(rm.getExceptionKey())).
findAny().
ifPresent(method -> {
if (errorCodeExceptionMap.containsKey(rm.getExceptionKey())) {
log.warn("RestErrorResponseMapper has already been added for the given exception key " +
"'{}'", rm.getExceptionKey());
}
errorCodeExceptionMap.put(rm.getExceptionKey(), rm.getExceptionClass());
});
});
return this;
}
public MSF4JClient.Builder errorDecoder(ErrorDecoder errorDecoder) {
this.errorDecoder = errorDecoder;
return this;
}
public HostnameVerifier getHostnameVerifier() {
return hostnameVerifier;
}
public void setHostnameVerifier(HostnameVerifier hostnameVerifier) {
this.hostnameVerifier = hostnameVerifier;
}
public SSLContext getSslContext() {
return sslContext;
}
public void setSslContext(SSLContext sslContext) {
this.sslContext = sslContext;
}
public MSF4JClient build() {
MSF4JClient msf4JClient;
Client client;
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(200);
cm.setDefaultMaxPerRoute(20);
CloseableHttpClient apacheHttpClient = HttpClients.custom()
.setSSLContext(sslContext)
.setSSLHostnameVerifier(hostnameVerifier)
.setConnectionManager(cm)
.build();
if (enableTracing) {
if (tracingType == TracingConstants.TracingType.ZIPKIN) {
client = new FeignClientWrapper(
new FeginZipkinTracingClient(new ApacheHttpClient(apacheHttpClient), instanceName,
analyticsEndpoint));
} else {
client = new FeignClientWrapper(
new FeignTracingClient(new ApacheHttpClient(apacheHttpClient), instanceName,
analyticsEndpoint));
}
} else {
client = new FeignClientWrapper(new ApacheHttpClient(apacheHttpClient));
}
if (enableCircuitBreaker) {
HystrixFeign.Builder builder = newHystrixFeignClientBuilder();
builder.client(client);
builder.requestInterceptors(requestInterceptors);
builder.errorDecoder(errorDecoder);
if (decode404) {
builder.decode404();
}
msf4JClient = new MSF4JClient(builder.target(apiClass, serviceEndpoint, fallbackFactory));
} else {
Feign.Builder builder = newFeignClientBuilder();
builder.client(client);
builder.requestInterceptors(requestInterceptors);
builder.errorDecoder(errorDecoder);
if (decode404) {
builder.decode404();
}
msf4JClient = new MSF4JClient(builder.target(apiClass, serviceEndpoint));
}
return msf4JClient;
}
}
}
================================================
FILE: client/src/main/java/org/wso2/msf4j/client/ModelUtils.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* 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 org.wso2.msf4j.client;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
/**
* Converts Object to gson
*/
public class ModelUtils {
public static final Gson GSON = new GsonBuilder().setPrettyPrinting()
.disableHtmlEscaping().create();
public static String toString(Object o) {
return GSON.toJson(o);
}
}
================================================
FILE: client/src/main/java/org/wso2/msf4j/client/codec/DefaultErrorDecoder.java
================================================
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* 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 org.wso2.msf4j.client.codec;
import feign.Response;
import feign.codec.Decoder;
import feign.codec.ErrorDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wso2.msf4j.client.exception.RestServiceException;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* Feign error decoder which translates REST service error response to Java exception class
* which inherits {@link RestServiceException}
*/
public class DefaultErrorDecoder implements ErrorDecoder {
private static final Logger log = LoggerFactory.getLogger(DefaultErrorDecoder.class);
private final Map> errorResponseMappers;
private Decoder decoder = new MSF4JJacksonDecoder();
private ErrorDecoder fallbackErrorDecoder = new ErrorDecoder.Default();
public DefaultErrorDecoder(Map> errorResponseMappers) {
this.errorResponseMappers = errorResponseMappers;
}
@Override
public Exception decode(String methodKey, Response response) {
try {
DefaultRestErrorResponse apiErrorResponse = (DefaultRestErrorResponse) decoder.decode(response,
DefaultRestErrorResponse.class);
if (apiErrorResponse != null && errorResponseMappers.containsKey(apiErrorResponse.getErrorCode())) {
return getExceptionSupplierFromExceptionClass(
errorResponseMappers.get(apiErrorResponse.getErrorCode()), apiErrorResponse.getMessage());
}
} catch (IOException e) {
log.error("Error decoding error response", e);
} catch (Exception e) {
log.error("Error instantiating the exception mapped for the REST service error response '{}'",
response, e);
}
return fallbackErrorDecoder.decode(methodKey, response);
}
private RestServiceException getExceptionSupplierFromExceptionClass(Class extends RestServiceException> clazz,
String message)
throws IllegalAccessException, InvocationTargetException, InstantiationException {
List