contentTypeHeader = headersMap.get(HttpHeaders.CONTENT_TYPE);
48 |
49 | Assert.assertNotNull(response);
50 | Assert.assertEquals(responseBodyJson.get("status").getAsString(), "Error");
51 | Assert.assertEquals(responseBodyJson.get("message").getAsString(),
52 | "Invalid parameter " + paramName + " provided. Expected " + expectedParamValue
53 | + ", received " + receivedParamValue);
54 | Assert.assertEquals(response.getStatus(), Response.Status.PRECONDITION_FAILED.getStatusCode());
55 | Assert.assertEquals(contentTypeHeader.size(), 1);
56 | Assert.assertEquals(contentTypeHeader.get(0), MediaType.APPLICATION_JSON);
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/components/global/core/io.cellery.observability.api/src/main/java/io/cellery/observability/api/interceptor/CORSInterceptor.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 |
19 | package io.cellery.observability.api.interceptor;
20 |
21 | import io.cellery.observability.api.Constants;
22 | import org.apache.commons.lang3.StringUtils;
23 | import org.apache.log4j.Logger;
24 | import org.wso2.msf4j.Request;
25 | import org.wso2.msf4j.Response;
26 | import org.wso2.msf4j.interceptor.RequestInterceptor;
27 |
28 | import javax.ws.rs.HttpMethod;
29 | import javax.ws.rs.core.HttpHeaders;
30 |
31 | /**
32 | * Used for applying header for allowing cross origin requests.
33 | *
34 | * This alone is not enough since the browsers send an OPTIONS HTTP call to the endpoint first to check
35 | * which methods are allowed. Therefore an endpoint with HTTP Method OPTIONS should be added to all services.
36 | */
37 | public class CORSInterceptor implements RequestInterceptor {
38 | private static final Logger logger = Logger.getLogger(CORSInterceptor.class);
39 |
40 | @Override
41 | public boolean interceptRequest(Request request, Response response) {
42 | response.setHeader(Constants.HEADER_ACCESS_CONTROL_ALLOW_METHODS, HttpMethod.GET + "," + HttpMethod.POST +
43 | "," + HttpMethod.PUT + "," + HttpMethod.DELETE);
44 | response.setHeader(Constants.HEADER_ACCESS_CONTROL_MAX_AGE, Constants.MAX_AGE);
45 | response.setHeader(Constants.HEADER_ACCESS_CONTROL_ALLOW_HEADERS,
46 | HttpHeaders.CONTENT_TYPE + "," + HttpHeaders.AUTHORIZATION);
47 | response.setHeader(Constants.HEADER_ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
48 | if (StringUtils.isNotBlank(request.getHeader(Constants.HEADER_ORIGIN))) {
49 | response.setHeader(Constants.HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
50 | request.getHeader(Constants.HEADER_ORIGIN));
51 | } else {
52 | response.setHeader(Constants.HEADER_ACCESS_CONTROL_ALLOW_ORIGIN, Constants.ALL_ORIGINS);
53 | }
54 | if (logger.isDebugEnabled()) {
55 | logger.debug("Attached CORS Headers to API Call " + request.getHttpMethod() + " " + request.getUri());
56 | }
57 | return true;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/components/global/portal/io.cellery.observability.ui/src/components/common/error/ErrorBoundary.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | import Logger from "js-logger";
18 | import React from "react";
19 | import UnknownError from "./UnknownError";
20 | import * as PropTypes from "prop-types";
21 |
22 | /**
23 | * Error Boundary to catch error in React Components.
24 | * This Component can be used to wrap areas of the React App and catch any errors that occur inside them.
25 | *
26 | * Example:- A graph can be wrapped and the title can be set to "Invalid Data" to make sure that the users sees
27 | * this message instead of a blank screen if an error occurs.
28 | *
29 | * This will not affect the dev servers and the errors will still be shown.
30 | *
31 | * @returns {React.Component} Error Boundary React Component
32 | */
33 | class ErrorBoundary extends React.Component {
34 |
35 | static logger = Logger.get("components/common/error/ErrorBoundary");
36 |
37 | constructor(props) {
38 | super(props);
39 |
40 | this.state = {
41 | hasError: false
42 | };
43 | }
44 |
45 | /**
46 | * Derive a suitable state from the error if any error occurs.
47 | *
48 | * @param {Error} error The error that occurred
49 | * @returns {Object} New state
50 | */
51 | static getDerivedStateFromError = (error) => {
52 | ErrorBoundary.logger.error("Failed to render Observability Portal", error);
53 | return {
54 | hasError: true
55 | };
56 | };
57 |
58 | render = () => {
59 | const {children, title, description, showNavigationButtons} = this.props;
60 | const {hasError} = this.state;
61 |
62 | let content;
63 | if (hasError) {
64 | content = (
65 |
66 | );
67 | } else {
68 | content = children;
69 | }
70 | return content;
71 | };
72 |
73 | }
74 |
75 | ErrorBoundary.propTypes = {
76 | children: PropTypes.any.isRequired,
77 | title: PropTypes.string,
78 | description: PropTypes.string,
79 | showNavigationButtons: PropTypes.bool
80 | };
81 |
82 | export default ErrorBoundary;
83 |
--------------------------------------------------------------------------------
/docker/portal/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 | io.cellery.observability
21 | io.cellery.observability.docker
22 | 0.6.2-SNAPSHOT
23 | ../pom.xml
24 |
25 |
26 | 4.0.0
27 | io.cellery.observability.docker.portal
28 | Cellery Observability Docker - Portal
29 | Dockerfiles for Cellery Observability Portal
30 | pom
31 |
32 |
33 |
34 |
35 |
36 | org.apache.maven.plugins
37 | maven-dependency-plugin
38 | false
39 |
40 |
41 | copy-observability-portal-app
42 | initialize
43 |
44 | unpack
45 |
46 |
47 |
48 |
49 |
50 |
51 | io.cellery.observability
52 | io.cellery.observability.ui
53 | ${project.version}
54 | zip
55 | true
56 | ${project.build.directory}/files/
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/components/global/portal/io.cellery.observability.ui/src/utils/constants.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | const Constants = {
18 | Pattern: {
19 | DATE_TIME: "DD MMM YYYY, hh:mm A",
20 | PRECISE_DATE_TIME: "DD MMM YYYY, hh:mm:ss A",
21 | Query: {
22 | SECONDS: "second(?:s)?",
23 | MINUTES: "minute(?:s)?",
24 | HOURS: "hour(?:s)?",
25 | DAYS: "day(?:s)?",
26 | MONTHS: "month(?:s)?",
27 | YEARS: "year(?:s)?"
28 | }
29 | },
30 | Span: {
31 | Kind: {
32 | CLIENT: "CLIENT",
33 | SERVER: "SERVER",
34 | PRODUCER: "PRODUCER",
35 | CONSUMER: "CONSUMER"
36 | }
37 | },
38 | InstanceKind: {
39 | CELL: "Cell",
40 | COMPOSITE: "Composite"
41 | },
42 | Instance: {
43 | GATEWAY_NAME_PATTERN: /^gateway$/,
44 | COMPONENT_NAME_PATTERN: /^(.+)--(.+)$/
45 | },
46 | System: {
47 | ISTIO_MIXER_NAME_PATTERN: /^istio-mixer$/,
48 | GLOBAL_GATEWAY_NAME_PATTERN: /^global-gateway$/,
49 | SIDECAR_AUTH_FILTER_OPERATION_NAME_PATTERN: /^async\sext_authz\segress$/
50 | },
51 | CelleryType: {
52 | SYSTEM: "System",
53 | COMPONENT: "Component"
54 | },
55 | Status: {
56 | Success: "Success",
57 | Error: "Error",
58 | Warning: "Warning",
59 | Unknown: "Unknown"
60 | },
61 | Dashboard: {
62 | ALL_VALUE: "All",
63 | INBOUND: "Inbound",
64 | OUTBOUND: "Outbound",
65 | SIDE_NAV_BAR_WIDTH: 240,
66 | AUTHORIZATION_EP: "/oauth2/authorize?response_type=code"
67 | }
68 | };
69 |
70 | /*
71 | * Constants that are made up of other constants starts here.
72 | * These cannot be defined in a single object. Hence these are defined separately.
73 | */
74 | Constants.Pattern.Query.TIME_UNIT = `${Constants.Pattern.Query.YEARS}|${Constants.Pattern.Query.MONTHS}|`
75 | + `${Constants.Pattern.Query.DAYS}|${Constants.Pattern.Query.HOURS}|${Constants.Pattern.Query.MINUTES}|`
76 | + `${Constants.Pattern.Query.SECONDS}`;
77 | Constants.Pattern.Query.TIME = `([0-9]+)\\s*(${Constants.Pattern.Query.TIME_UNIT})`;
78 | Constants.Pattern.Query.RELATIVE_TIME = `^\\s*now\\s*(?:-\\s*(?:${Constants.Pattern.Query.TIME}\\s*)+)?$`;
79 |
80 | export default Constants;
81 |
--------------------------------------------------------------------------------
/components/global/core/io.cellery.observability.model.generator/src/main/java/io/cellery/observability/model/generator/internal/ModelServiceComponent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 | package io.cellery.observability.model.generator.internal;
19 |
20 | import io.cellery.observability.model.generator.model.ModelManager;
21 | import org.apache.log4j.Logger;
22 | import org.osgi.framework.BundleContext;
23 | import org.osgi.service.component.annotations.Activate;
24 | import org.osgi.service.component.annotations.Component;
25 | import org.osgi.service.component.annotations.Reference;
26 | import org.osgi.service.component.annotations.ReferenceCardinality;
27 | import org.osgi.service.component.annotations.ReferencePolicy;
28 | import org.wso2.carbon.datasource.core.api.DataSourceService;
29 |
30 | /**
31 | * This class acts as a Service Component which specifies the services that is required by the component.
32 | */
33 | @Component(
34 | service = ModelServiceComponent.class,
35 | immediate = true
36 | )
37 | public class ModelServiceComponent {
38 | private static final Logger log = Logger.getLogger(ModelServiceComponent.class);
39 |
40 | @Activate
41 | protected void start(BundleContext bundleContext) throws Exception {
42 | try {
43 | ServiceHolder.setModelStoreManager(new ModelStoreManager());
44 | ServiceHolder.setModelManager(new ModelManager());
45 | bundleContext.registerService(ModelManager.class.getName(), ServiceHolder.getModelManager(), null);
46 | } catch (Throwable throwable) {
47 | log.error("Error occurred while activating the model generation bundle", throwable);
48 | throw throwable;
49 | }
50 | }
51 |
52 | @Reference(
53 | name = "org.wso2.carbon.datasource.DataSourceService",
54 | service = DataSourceService.class,
55 | cardinality = ReferenceCardinality.AT_LEAST_ONE,
56 | policy = ReferencePolicy.DYNAMIC,
57 | unbind = "unregisterDataSourceService"
58 | )
59 | protected void registerDataSourceService(DataSourceService service) {
60 | ServiceHolder.setDataSourceService(service);
61 | }
62 |
63 | protected void unregisterDataSourceService(DataSourceService service) {
64 | ServiceHolder.setDataSourceService(null);
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/components/global/core/io.cellery.observability.siddhi.apps/src/main/siddhi/istio-telemetry-app.siddhi:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 |
19 | @App:name("istio-telemetry-app")
20 | @App:description("This receives the attributes generally received by the Istio Mixer")
21 |
22 | @source(type="runtime-agent", port="9091", agent.type="Telemetry",
23 | @map(type="keyvalue", fail.on.missing.attribute="false"))
24 | define stream TelemetryStream(runtime string, requestId string, traceId string, spanId string, parentSpanId string,
25 | sourceNamespace string, sourceInstance string, sourceInstanceKind string,
26 | sourceComponent string, sourcePod string, destinationNamespace string,
27 | destinationInstance string, destinationInstanceKind string, destinationComponent string,
28 | destinationPod string, requestPath string, requestMethod string, requestSizeBytes long,
29 | responseCode long, responseDurationNanoSec long, responseSizeBytes long,
30 | reporterUID string, reporterKind string);
31 |
32 | @sink(type="inMemory", topic="istio-mixer-report", @map(type="passThrough"))
33 | define stream TelemetryInMemorySink(runtime string, requestId string, traceId string, spanId string,
34 | parentSpanId string, sourceNamespace string, sourceInstance string,
35 | sourceInstanceKind string, sourceComponent string, sourcePod string,
36 | destinationNamespace string, destinationInstance string,
37 | destinationInstanceKind string, destinationComponent string, destinationPod string,
38 | requestPath string, requestMethod string, requestSizeBytes long, responseCode long,
39 | responseDurationNanoSec long, responseSizeBytes long, reporterUID string,
40 | reporterKind string);
41 |
42 | -- Storing the required attributes in a in memory sink (To be accessed from other siddhi apps)
43 | -- When updating the used attributes from the received attributes the stream definitions needs to be updated in all
44 | -- the places where the in memory source is used
45 |
46 | from TelemetryStream[(not sourcePod is null) and (not destinationPod is null)]
47 | insert into TelemetryInMemorySink;
48 |
--------------------------------------------------------------------------------
/components/global/portal/io.cellery.observability.ui/src/utils/common/notificationUtils.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing,
11 | * software distributed under the License is distributed on an
12 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
13 | * KIND, either express or implied. See the License for the
14 | * specific language governing permissions and limitations
15 | * under the License.
16 | */
17 |
18 | import {StateHolder} from "../../components/common/state";
19 |
20 | class NotificationUtils {
21 |
22 | static Levels = {
23 | INFO: "INFO",
24 | WARNING: "WARNING",
25 | ERROR: "ERROR"
26 | };
27 |
28 | /**
29 | * Show the loading overlay.
30 | *
31 | * @param {string} message The message to be shown in the loading overlay
32 | * @param {StateHolder} globalState The global state provided to the current component
33 | */
34 | static showLoadingOverlay = (message, globalState) => {
35 | const prevState = globalState.get(StateHolder.LOADING_STATE);
36 | globalState.set(StateHolder.LOADING_STATE, {
37 | loadingOverlayCount: prevState.loadingOverlayCount + 1,
38 | message: message
39 | });
40 | };
41 |
42 | /**
43 | * Hide the loading overlay.
44 | *
45 | * @param {StateHolder} globalState The global state provided to the current component
46 | */
47 | static hideLoadingOverlay = (globalState) => {
48 | const prevState = globalState.get(StateHolder.LOADING_STATE);
49 | globalState.set(StateHolder.LOADING_STATE, {
50 | loadingOverlayCount: prevState.loadingOverlayCount === 0 ? 0 : prevState.loadingOverlayCount - 1,
51 | message: null
52 | });
53 | };
54 |
55 | /**
56 | * Show a notification to the user.
57 | *
58 | * @param {string} message The message to be shown in the notification
59 | * @param {string} level The notification level
60 | * @param {StateHolder} globalState The global state provided to the current component
61 | */
62 | static showNotification = (message, level, globalState) => {
63 | globalState.set(StateHolder.NOTIFICATION_STATE, {
64 | isOpen: true,
65 | message: message,
66 | notificationLevel: level
67 | });
68 | };
69 |
70 | /**
71 | * Close the notification shown to the user.
72 | *
73 | * @param {StateHolder} globalState The global state provided to the current component
74 | */
75 | static closeNotification = (globalState) => {
76 | globalState.set(StateHolder.NOTIFICATION_STATE, {
77 | ...globalState.get(StateHolder.NOTIFICATION_STATE),
78 | isOpen: false
79 | });
80 | };
81 |
82 | }
83 |
84 | export default NotificationUtils;
85 |
--------------------------------------------------------------------------------
/components/global/observability-agent/pkg/kubeagent/kubeagent.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 |
19 | package kubeagent
20 |
21 | import (
22 | "encoding/json"
23 | "fmt"
24 |
25 | meshv1alpha2 "cellery.io/cellery-controller/pkg/generated/informers/externalversions/mesh/v1alpha2"
26 | meshv1alpha2listers "cellery.io/cellery-controller/pkg/generated/listers/mesh/v1alpha2"
27 | "go.uber.org/zap"
28 | corev1 "k8s.io/client-go/informers/core/v1"
29 | "k8s.io/client-go/tools/cache"
30 | )
31 |
32 | type ResourceWatcher struct {
33 | podInformer corev1.PodInformer
34 | componentInformer meshv1alpha2.ComponentInformer
35 | cellLister meshv1alpha2listers.CellLister
36 | compositeLister meshv1alpha2listers.CompositeLister
37 | buffer chan string
38 | logger *zap.SugaredLogger
39 | }
40 |
41 | func New(
42 | podInformer corev1.PodInformer,
43 | componentInformer meshv1alpha2.ComponentInformer,
44 | cellInformer meshv1alpha2.CellInformer,
45 | compositeInformer meshv1alpha2.CompositeInformer,
46 | buffer chan string,
47 | logger *zap.SugaredLogger,
48 | ) *ResourceWatcher {
49 | rw := &ResourceWatcher{
50 | podInformer: podInformer,
51 | componentInformer: componentInformer,
52 | cellLister: cellInformer.Lister(),
53 | compositeLister: compositeInformer.Lister(),
54 | buffer: buffer,
55 | logger: logger.Named("kubeagent"),
56 | }
57 | rw.podInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{
58 | FilterFunc: FilterWithInstanceLabel(),
59 | Handler: HandleAll(PodMapper, rw.write, rw.logger.Named("pod").With().Warnf),
60 | })
61 | rw.componentInformer.Informer().AddEventHandler(HandleAll(ComponentMapper(rw.cellLister, rw.compositeLister), rw.write, rw.logger.Named("cell").Warnf))
62 | return rw
63 | }
64 |
65 | func (rw *ResourceWatcher) Run(stopCh <-chan struct{}) error {
66 | if ok := cache.WaitForCacheSync(stopCh,
67 | //rw.podInformer.Informer().HasSynced,
68 | rw.componentInformer.Informer().HasSynced,
69 | ); !ok {
70 | return fmt.Errorf("failed to wait for caches to sync")
71 | }
72 | rw.logger.Info("Resource watcher stared successfully")
73 | return nil
74 | }
75 |
76 | func (rw *ResourceWatcher) write(attr Attributes) {
77 | jsonBytes, err := json.Marshal(attr)
78 | if err != nil {
79 | rw.logger.Errorf("cannot marshal attributes to json: %v", err)
80 | return
81 | }
82 | dataStr := string(jsonBytes)
83 | rw.logger.Debugf("Writing event to buffer: %s", dataStr)
84 | rw.buffer <- dataStr
85 | }
86 |
--------------------------------------------------------------------------------
/components/global/observability-agent/pkg/writer/writer.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 |
19 | package writer
20 |
21 | import (
22 | "fmt"
23 | "strings"
24 | "time"
25 |
26 | "go.uber.org/zap"
27 |
28 | "cellery.io/cellery-observability/components/global/observability-agent/pkg/store"
29 | )
30 |
31 | type (
32 | Writer struct {
33 | WaitingTimeSec int
34 | WaitingSize int
35 | Logger *zap.SugaredLogger
36 | Buffer chan string
37 | LastWrittenTime time.Time
38 | Persister store.Persister
39 | }
40 | )
41 |
42 | func (writer *Writer) Run(stopCh <-chan struct{}) {
43 | writer.Logger.Info("Writer started")
44 | for {
45 | select {
46 | case <-stopCh:
47 | writer.flushBuffer()
48 | return
49 | default:
50 | if writer.shouldWrite() {
51 | err := writer.write()
52 | if err != nil {
53 | writer.Logger.Errorf("Received an error while writing : %v", err)
54 | }
55 | } else {
56 | time.Sleep(5 * time.Second)
57 | }
58 | }
59 | }
60 | }
61 |
62 | func (writer *Writer) write() error {
63 | elements := writer.getElements()
64 | str := fmt.Sprintf("[%s]", strings.Join(elements, ","))
65 | err := writer.Persister.Write(str)
66 | if err != nil {
67 | writer.restore(elements)
68 | return err
69 | }
70 | return nil
71 | }
72 |
73 | func (writer *Writer) flushBuffer() {
74 | for {
75 | if len(writer.Buffer) == 0 {
76 | return
77 | }
78 | err := writer.write()
79 | if err != nil {
80 | writer.Logger.Errorf("Received an error while writing : %v", err)
81 | }
82 | }
83 | }
84 |
85 | func (writer *Writer) shouldWrite() bool {
86 | if (len(writer.Buffer) > 0) && (len(writer.Buffer) >= writer.WaitingSize || time.Since(writer.LastWrittenTime) >
87 | time.Duration(writer.WaitingTimeSec)*time.Second) {
88 | writer.Logger.Debugf("Time since the previous write : %s", time.Since(writer.LastWrittenTime))
89 | writer.LastWrittenTime = time.Now()
90 | return true
91 | } else {
92 | return false
93 | }
94 | }
95 |
96 | func (writer *Writer) getElements() []string {
97 | var elements []string
98 | for i := 0; i < writer.WaitingSize; i++ {
99 | element := <-writer.Buffer
100 | if element == "" {
101 | if len(writer.Buffer) == 0 {
102 | break
103 | }
104 | continue
105 | }
106 | elements = append(elements, element)
107 | if len(writer.Buffer) == 0 {
108 | break
109 | }
110 | }
111 | return elements
112 | }
113 |
114 | func (writer *Writer) restore(elements []string) {
115 | for _, element := range elements {
116 | writer.Buffer <- element
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/components/global/portal/io.cellery.observability.ui/src/icons/NodeIcon.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | import React from "react";
18 | import SvgIcon from "@material-ui/core/SvgIcon";
19 |
20 | const NodeIcon = (props) => (
21 |
22 |
44 |
45 | );
46 |
47 | export default NodeIcon;
48 |
--------------------------------------------------------------------------------
/components/global/core/io.cellery.observability.tracing.synapse.handler/src/main/java/io/cellery/observability/tracing/synapse/handler/Constants.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 |
19 | package io.cellery.observability.tracing.synapse.handler;
20 |
21 | /**
22 | * Synapse handler related Constants.
23 | */
24 | public class Constants {
25 | public static final String ZIPKIN_HOST_ENV_VAR = "ZIPKIN_HOST";
26 | public static final String ZIPKIN_PORT_ENV_VAR = "ZIPKIN_PORT";
27 | public static final String ZIPKIN_API_CONTEXT_ENV_VAR = "ZIPKIN_API_CONTEXT";
28 | public static final String CELLERY_TRACING_SERVICE_NAME_ENV_VAR = "CELLERY_TRACING_SERVICE_NAME";
29 | public static final String CELLERY_TRACING_NAMESPACE_ENV_VAR = "CELLERY_TRACING_NAMESPACE";
30 | public static final String ZIPKIN_HOST_DEFAULT_VALUE = "wso2sp-worker.cellery-system";
31 | public static final int ZIPKIN_PORT_DEFAULT_VALUE = 9411;
32 | public static final String ZIPKIN_API_CONTEXT_DEFAULT_VALUE = "/api/v1/spans";
33 | public static final String CELLERY_TRACING_SERVICE_NAME_DEFAULT_VALUE = "global-gateway";
34 |
35 | public static final String TRACING_CORRELATION_ID = "TRACING_CORRELATION_ID";
36 | public static final boolean TRACING_SENDER_COMPRESSION_ENABLED = false;
37 | public static final String B3_GLOBAL_GATEWAY_CORRELATION_ID_HEADER = "X-B3-GlobalGatewayCorrelationId";
38 |
39 | // Tag keys
40 | public static final String TAG_KEY_HTTP_METHOD = "http.method";
41 | public static final String TAG_KEY_HTTP_URL = "http.url";
42 | public static final String TAG_KEY_PROTOCOL = "protocol";
43 | public static final String TAG_KEY_PEER_ADDRESS = "peer.address";
44 | public static final String TAG_KEY_SPAN_KIND = "span.kind";
45 | public static final String TAG_KEY_HTTP_STATUS_CODE = "http.status_code";
46 | public static final String TAG_KEY_ERROR = "error";
47 |
48 | // Tag values
49 | public static final String SPAN_KIND_CLIENT = "client";
50 | public static final String SPAN_KIND_SERVER = "server";
51 |
52 | // Synapse message context properties
53 | public static final String SYNAPSE_MESSAGE_CONTEXT_PROPERTY_HTTP_METHOD = "REST_METHOD";
54 | public static final String SYNAPSE_MESSAGE_CONTEXT_PROPERTY_ENDPOINT = "ENDPOINT_ADDRESS";
55 | public static final String SYNAPSE_MESSAGE_CONTEXT_PROPERTY_PEER_ADDRESS = "api.ut.hostName";
56 | public static final String SYNAPSE_MESSAGE_CONTEXT_PROPERTY_TRANSPORT = "TRANSPORT_IN_NAME";
57 |
58 | // Axis2 message context properties
59 | public static final String AXIS2_MESSAGE_CONTEXT_PROPERTY_HTTP_STATUS_CODE = "HTTP_SC";
60 | public static final String AXIS2_MESSAGE_CONTEXT_PROPERTY_HTTP_METHOD = "HTTP_METHOD";
61 | public static final String AXIS2_MESSAGE_CONTEXT_PROPERTY_REMOTE_HOST = "REMOTE_HOST";
62 | }
63 |
--------------------------------------------------------------------------------
/components/global/core/io.cellery.observability.telemetry.deduplicator/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
22 | io.cellery.observability.core
23 | io.cellery.observability
24 | 0.6.2-SNAPSHOT
25 |
26 |
27 | 4.0.0
28 | io.cellery.observability.telemetry.deduplicator
29 | 0.6.2-SNAPSHOT
30 | Cellery Observability Components - Global Plane - Core - Deduplicator
31 | bundle
32 |
33 |
34 |
35 | org.wso2.siddhi
36 | siddhi-core
37 |
38 |
39 | org.wso2.siddhi
40 | siddhi-query-api
41 |
42 |
43 | org.wso2.siddhi
44 | siddhi-annotations
45 |
46 |
47 |
48 |
49 | org.testng
50 | testng
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | org.apache.felix
59 | maven-bundle-plugin
60 | true
61 |
62 |
63 | ${project.artifactId}
64 | ${project.artifactId}
65 |
66 | io.cellery.observability.telemetry.deduplicator.*,
67 |
68 |
69 | *;resolution:=optional
70 |
71 |
72 | META-INF=target/classes/META-INF
73 |
74 | *
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/components/global/portal/io.cellery.observability.ui/src/utils/api/authUtils.test.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 |
19 | import AuthUtils from "./authUtils";
20 | import {StateHolder} from "../../components/common/state";
21 |
22 | describe("AuthUtils", () => {
23 | const username = "User1";
24 | const loggedInUser = {
25 | username: username,
26 | accessToken: "12345",
27 | idToken: "54321"
28 | };
29 | afterEach(() => {
30 | localStorage.removeItem(StateHolder.USER);
31 | });
32 |
33 | describe("signIn()", () => {
34 | it("should set the username provided", () => {
35 | const stateHolder = new StateHolder();
36 | const spy = jest.spyOn(stateHolder, "set");
37 | AuthUtils.signIn(loggedInUser, stateHolder);
38 |
39 | expect(spy).toHaveBeenCalledTimes(1);
40 | expect(spy).toHaveBeenCalledWith(StateHolder.USER, loggedInUser);
41 | expect(localStorage.getItem(StateHolder.USER)).toBe(JSON.stringify(loggedInUser));
42 | });
43 |
44 | it("should not set a username and should throw and error", () => {
45 | const stateHolder = new StateHolder();
46 | const spy = jest.spyOn(stateHolder, "set");
47 |
48 | expect(() => AuthUtils.signIn(null, stateHolder)).toThrow();
49 | expect(() => AuthUtils.signIn(undefined, stateHolder)).toThrow();
50 | expect(() => AuthUtils.signIn("", stateHolder)).toThrow();
51 | expect(spy).toHaveBeenCalledTimes(0);
52 | expect(spy).not.toHaveBeenCalled();
53 | expect(localStorage.getItem(StateHolder.USER)).toBeNull();
54 | });
55 | });
56 |
57 | describe("signOut()", () => {
58 | it("should unset the user in the state", () => {
59 | const stateHolder = new StateHolder();
60 | localStorage.setItem(StateHolder.USER, JSON.stringify(loggedInUser));
61 | stateHolder.state[StateHolder.USER] = {
62 | value: {...loggedInUser},
63 | listeners: []
64 | };
65 | stateHolder.state[StateHolder.CONFIG] = {
66 | value: {
67 | idp: {
68 | idpURL: "http://test-url",
69 | callBackURL: "http://test-callbak-url"
70 | }
71 | },
72 | listener: []
73 | };
74 | AuthUtils.signOut(stateHolder);
75 | expect(localStorage.getItem(StateHolder.USER)).toBeNull();
76 | });
77 | });
78 |
79 | describe("getAuthenticatedUser()", () => {
80 | localStorage.setItem(StateHolder.USER, JSON.stringify(loggedInUser));
81 | const user = AuthUtils.getAuthenticatedUser();
82 |
83 | expect(user).toEqual({...user});
84 | });
85 | });
86 |
--------------------------------------------------------------------------------
/components/global/core/io.cellery.observability.model.generator/src/test/java/io/cellery/observability/model/generator/model/NodeTestCase.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 |
19 | package io.cellery.observability.model.generator.model;
20 |
21 | import org.testng.Assert;
22 | import org.testng.annotations.Test;
23 |
24 | /**
25 | * Node related test cases.
26 | */
27 | public class NodeTestCase {
28 |
29 | @Test
30 | public void testNodeEquality() {
31 | Node nodeA = new Node("test-namespace", "test-instance", "test-component");
32 | nodeA.setInstanceKind("Cell");
33 | Node nodeB = new Node("test-namespace", "test-instance", "test-component");
34 | nodeB.setInstanceKind("Cell");
35 | Assert.assertEquals(nodeA, nodeB);
36 | }
37 |
38 | @Test
39 | public void testNodeEqualityWithMismatchedInstanceKind() {
40 | Node nodeA = new Node("test-namespace", "test-instance", "test-component");
41 | nodeA.setInstanceKind("Cell");
42 | Node nodeB = new Node("test-namespace", "test-instance", "test-component");
43 | nodeB.setInstanceKind("Composite");
44 | Assert.assertEquals(nodeA, nodeB);
45 | }
46 |
47 | @Test
48 | public void testNodeInEqualityWithMismatchedNamespace() {
49 | Node nodeA = new Node("test-namespace", "test-instance", "test-component");
50 | nodeA.setInstanceKind("Cell");
51 | Node nodeB = new Node("different-namespace", "test-instance", "test-component");
52 | nodeB.setInstanceKind("Cell");
53 | Assert.assertNotEquals(nodeA, nodeB);
54 | }
55 |
56 | @Test
57 | public void testNodeInEqualityWithMismatchedInstance() {
58 | Node nodeA = new Node("test-namespace", "test-instance", "test-component");
59 | nodeA.setInstanceKind("Cell");
60 | Node nodeB = new Node("test-namespace", "different-instance", "test-component");
61 | nodeB.setInstanceKind("Cell");
62 | Assert.assertNotEquals(nodeA, nodeB);
63 | }
64 |
65 | @Test
66 | public void testNodeInEqualityWithMismatchedComponent() {
67 | Node nodeA = new Node("test-namespace", "test-instance", "test-component");
68 | nodeA.setInstanceKind("Cell");
69 | Node nodeB = new Node("test-namespace", "test-instance", "different-component");
70 | nodeB.setInstanceKind("Cell");
71 | Assert.assertNotEquals(nodeA, nodeB);
72 | }
73 |
74 | @Test
75 | public void testNodeFQN() {
76 | Node nodeA = new Node("test-namespace", "test-instance", "test-component");
77 | nodeA.setInstanceKind("Cell");
78 | Assert.assertEquals(Model.getNodeFQN(nodeA), nodeA.getFQN());
79 |
80 | Node nodeB = new Node("test-namespace", "test-instance", "test-component");
81 | nodeB.setInstanceKind("Composite");
82 | Assert.assertEquals(Model.getNodeFQN(nodeB), nodeB.getFQN());
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/components/global/core/io.cellery.observability.api/src/test/java/io/cellery/observability/api/siddhi/SiddhiStoreQueryManagerTestCase.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 |
19 | package io.cellery.observability.api.siddhi;
20 |
21 | import io.cellery.observability.api.internal.ServiceHolder;
22 | import org.mockito.Mockito;
23 | import org.powermock.core.classloader.annotations.PowerMockIgnore;
24 | import org.powermock.core.classloader.annotations.PrepareForTest;
25 | import org.powermock.modules.testng.PowerMockObjectFactory;
26 | import org.powermock.reflect.Whitebox;
27 | import org.testng.IObjectFactory;
28 | import org.testng.annotations.AfterMethod;
29 | import org.testng.annotations.BeforeMethod;
30 | import org.testng.annotations.ObjectFactory;
31 | import org.testng.annotations.Test;
32 | import org.wso2.siddhi.core.SiddhiAppRuntime;
33 | import org.wso2.siddhi.core.SiddhiManager;
34 |
35 | /**
36 | * Test Cases for Siddhi Store Query Manager.
37 | */
38 | @PrepareForTest(SiddhiStoreQueryManager.class)
39 | @PowerMockIgnore("org.apache.log4j.*")
40 | public class SiddhiStoreQueryManagerTestCase {
41 |
42 | private SiddhiStoreQueryManager siddhiStoreQueryManager;
43 | private SiddhiManager siddhiManager;
44 | private SiddhiAppRuntime internalSiddhiAppRuntime;
45 |
46 | @ObjectFactory
47 | public IObjectFactory getObjectFactory() {
48 | return new PowerMockObjectFactory();
49 | }
50 |
51 | @BeforeMethod
52 | public void init() {
53 | String siddhiAppString = Whitebox.getInternalState(SiddhiStoreQueryManager.class, "SIDDHI_APP");
54 | internalSiddhiAppRuntime = Mockito.mock(SiddhiAppRuntime.class);
55 |
56 | siddhiManager = Mockito.mock(SiddhiManager.class);
57 | Mockito.when(siddhiManager.createSiddhiAppRuntime(siddhiAppString))
58 | .thenReturn(internalSiddhiAppRuntime);
59 | ServiceHolder.setSiddhiManager(siddhiManager);
60 |
61 | siddhiStoreQueryManager = new SiddhiStoreQueryManager();
62 | }
63 |
64 | @AfterMethod
65 | public void cleanUp() {
66 | ServiceHolder.setSiddhiManager(null);
67 | }
68 |
69 | @Test
70 | public void testInitialization() throws Exception {
71 | String siddhiAppString = Whitebox.getInternalState(SiddhiStoreQueryManager.class, "SIDDHI_APP");
72 | Mockito.verify(siddhiManager, Mockito.times(1))
73 | .createSiddhiAppRuntime(siddhiAppString);
74 | Mockito.verify(internalSiddhiAppRuntime, Mockito.times(1)).start();
75 | }
76 |
77 | @Test
78 | public void testQuery() {
79 | siddhiStoreQueryManager.query("test");
80 | Mockito.verify(internalSiddhiAppRuntime, Mockito.times(1)).query("test");
81 | }
82 |
83 | @Test
84 | public void testShutdown() {
85 | siddhiStoreQueryManager.stop();
86 | Mockito.verify(internalSiddhiAppRuntime, Mockito.times(1)).shutdown();
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/components/global/core/io.cellery.observability.api/src/main/java/io/cellery/observability/api/AuthAPI.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 |
19 | package io.cellery.observability.api;
20 |
21 | import com.google.gson.JsonObject;
22 | import com.google.gson.JsonParser;
23 | import io.cellery.observability.api.exception.APIInvocationException;
24 | import io.cellery.observability.api.internal.ServiceHolder;
25 | import io.cellery.observability.auth.AuthUtils;
26 | import org.apache.oltu.oauth2.client.response.OAuthAccessTokenResponse;
27 |
28 | import java.util.HashMap;
29 | import java.util.Map;
30 | import javax.ws.rs.GET;
31 | import javax.ws.rs.OPTIONS;
32 | import javax.ws.rs.Path;
33 | import javax.ws.rs.PathParam;
34 | import javax.ws.rs.Produces;
35 | import javax.ws.rs.core.NewCookie;
36 | import javax.ws.rs.core.Response;
37 |
38 | /**
39 | * MSF4J service for Authentication services.
40 | *
41 | * All endpoints in this API are unauthenticated
42 | */
43 | @Path("/api/auth")
44 | public class AuthAPI {
45 | private static final JsonParser jsonParser = new JsonParser();
46 |
47 | @GET
48 | @Path("/tokens/{authCode}")
49 | @Produces("application/json")
50 | public Response getTokens(@PathParam("authCode") String authCode) throws APIInvocationException {
51 | try {
52 | OAuthAccessTokenResponse oAuthResponse = AuthUtils.exchangeAuthCode(authCode);
53 | JsonObject jsonObj = jsonParser.parse(oAuthResponse.getBody()).getAsJsonObject();
54 | String accessToken = oAuthResponse.getAccessToken();
55 | String idToken = jsonObj.get(Constants.ID_TOKEN).getAsString();
56 |
57 | final int mid = accessToken.length() / 2;
58 |
59 | Map