├── .babelrc
├── .coveralls.yml
├── .dockerignore
├── .eslintignore
├── .eslintrc
├── .gitignore
├── .gitmodules
├── .npmrc
├── .prettierignore
├── .prettierrc
├── .travis.yml
├── .vscode
└── settings.json
├── CONTRIBUTING.md
├── LICENSE
├── Makefile
├── README.md
├── Release.md
├── build
├── docker
│ ├── Dockerfile
│ └── publish-to-docker-hub.sh
└── zipkin
│ ├── README.md
│ ├── base.json
│ └── zipkin-quickstart.sh
├── deployment
└── terraform
│ ├── main.tf
│ ├── outputs.tf
│ ├── templates
│ ├── deployment_yaml.tpl
│ └── haystack-ui_json.tpl
│ └── variables.tf
├── package-lock.json
├── package.json
├── public
├── assets.json
├── favicon.ico
├── fonts
│ ├── LICENSE_THEMIFY
│ ├── LICENSE_TITILLIUM_WEB
│ ├── themify.ttf
│ ├── themify.woff
│ ├── titillium-web-v5-latin-200.ttf
│ ├── titillium-web-v5-latin-200.woff
│ ├── titillium-web-v5-latin-200.woff2
│ ├── titillium-web-v5-latin-300.ttf
│ ├── titillium-web-v5-latin-300.woff
│ ├── titillium-web-v5-latin-300.woff2
│ ├── titillium-web-v5-latin-600.ttf
│ ├── titillium-web-v5-latin-600.woff
│ ├── titillium-web-v5-latin-600.woff2
│ ├── titillium-web-v5-latin-700.ttf
│ ├── titillium-web-v5-latin-700.woff
│ ├── titillium-web-v5-latin-700.woff2
│ ├── titillium-web-v5-latin-regular.ttf
│ ├── titillium-web-v5-latin-regular.woff
│ └── titillium-web-v5-latin-regular.woff2
├── images
│ ├── assets
│ │ ├── alerts.png
│ │ ├── demo.gif
│ │ ├── logo_lighter.png
│ │ ├── logo_with_title.png
│ │ ├── logo_with_title_dark.png
│ │ ├── logo_with_title_transparent.png
│ │ ├── service_graph.png
│ │ ├── trace_timeline.png
│ │ ├── trends.png
│ │ └── universal_search.png
│ ├── error.svg
│ ├── loading.gif
│ ├── logo-white.png
│ ├── logo.png
│ ├── slack.png
│ ├── success.svg
│ └── zipkin-logo.jpg
└── scripts
│ ├── particles.json
│ └── particles.min.js
├── server
├── app.js
├── config
│ ├── base.js
│ ├── config.js
│ └── override.js
├── connectors
│ ├── alerts
│ │ ├── haystack
│ │ │ ├── alertsConnector.js
│ │ │ ├── expressionTreeBuilder.js
│ │ │ └── subscriptionsConnector.js
│ │ └── stub
│ │ │ ├── alertsConnector.js
│ │ │ └── subscriptionsConnector.js
│ ├── operations
│ │ ├── grpcDeleter.js
│ │ ├── grpcFetcher.js
│ │ ├── grpcPoster.js
│ │ ├── grpcPutter.js
│ │ └── restFetcher.js
│ ├── serviceGraph
│ │ ├── haystack
│ │ │ ├── graphDataExtractor.js
│ │ │ └── serviceGraphConnector.js
│ │ ├── stub
│ │ │ └── serviceGraphConnector.js
│ │ └── zipkin
│ │ │ ├── converter.js
│ │ │ └── serviceGraphConnector.js
│ ├── serviceInsights
│ │ ├── detectCycles.js
│ │ ├── fetcher.js
│ │ ├── graphDataExtractor.js
│ │ └── serviceInsightsConnector.js
│ ├── services
│ │ └── servicesConnector.js
│ ├── traces
│ │ ├── haystack
│ │ │ ├── expressionTreeBuilder.js
│ │ │ ├── protobufConverters
│ │ │ │ ├── callGraphConverter.js
│ │ │ │ ├── traceConverter.js
│ │ │ │ └── traceCountsConverter.js
│ │ │ ├── search
│ │ │ │ ├── searchRequestBuilder.js
│ │ │ │ └── searchResultsTransformer.js
│ │ │ ├── timeline
│ │ │ │ └── traceCountsRequestBuilder.js
│ │ │ └── tracesConnector.js
│ │ ├── mock
│ │ │ ├── mock-web-ui.js
│ │ │ ├── spanTypes.js
│ │ │ ├── tracesConnector.js
│ │ │ └── tracesGenerator.js
│ │ ├── stub
│ │ │ └── tracesConnector.js
│ │ └── zipkin
│ │ │ ├── converter.js
│ │ │ └── tracesConnector.js
│ ├── trends
│ │ ├── haystack
│ │ │ └── trendsConnector.js
│ │ └── stub
│ │ │ └── trendsConnector.js
│ └── utils
│ │ ├── LoaderBackedCache.js
│ │ ├── encoders
│ │ ├── Base64Encoder.js
│ │ ├── MetricpointNameEncoder.js
│ │ ├── NoopEncoder.js
│ │ └── PeriodReplacementEncoder.js
│ │ ├── errorConverter.js
│ │ └── objectUtils.js
├── routes
│ ├── alertsApi.js
│ ├── auth.js
│ ├── index.js
│ ├── login.js
│ ├── serviceGraphApi.js
│ ├── serviceInsightsApi.js
│ ├── servicesApi.js
│ ├── servicesPerfApi.js
│ ├── sso.js
│ ├── tracesApi.js
│ ├── trendsApi.js
│ ├── user.js
│ └── utils
│ │ └── apiResponseHandler.js
├── sso
│ ├── authChecker.js
│ └── samlSsoAuthenticator.js
├── start.js
├── utils
│ ├── logger.js
│ ├── metrics.js
│ ├── metricsMiddleware.js
│ ├── metricsReporter.js
│ └── server.js
└── views
│ └── index.pug
├── src
├── app.jsx
├── app.less
├── bootstrap
│ ├── LICENSE_BOOTSTRAP
│ ├── LICENSE_BOOTSWATCH
│ ├── alerts.less
│ ├── badges.less
│ ├── bootstrap.less
│ ├── bootswatch.less
│ ├── breadcrumbs.less
│ ├── button-groups.less
│ ├── buttons.less
│ ├── carousel.less
│ ├── close.less
│ ├── code.less
│ ├── component-animations.less
│ ├── dropdowns.less
│ ├── forms.less
│ ├── grid.less
│ ├── input-groups.less
│ ├── jumbotron.less
│ ├── labels.less
│ ├── list-group.less
│ ├── media.less
│ ├── mixins.less
│ ├── mixins
│ │ ├── alerts.less
│ │ ├── background-variant.less
│ │ ├── border-radius.less
│ │ ├── buttons.less
│ │ ├── center-block.less
│ │ ├── clearfix.less
│ │ ├── forms.less
│ │ ├── gradients.less
│ │ ├── grid-framework.less
│ │ ├── grid.less
│ │ ├── hide-text.less
│ │ ├── image.less
│ │ ├── labels.less
│ │ ├── list-group.less
│ │ ├── nav-divider.less
│ │ ├── nav-vertical-align.less
│ │ ├── opacity.less
│ │ ├── pagination.less
│ │ ├── panels.less
│ │ ├── progress-bar.less
│ │ ├── reset-filter.less
│ │ ├── reset-text.less
│ │ ├── resize.less
│ │ ├── responsive-visibility.less
│ │ ├── size.less
│ │ ├── tab-focus.less
│ │ ├── table-row.less
│ │ ├── text-emphasis.less
│ │ ├── text-overflow.less
│ │ └── vendor-prefixes.less
│ ├── modals.less
│ ├── navbar.less
│ ├── navs.less
│ ├── normalize.less
│ ├── pager.less
│ ├── pagination.less
│ ├── panels.less
│ ├── popovers.less
│ ├── print.less
│ ├── progress-bars.less
│ ├── responsive-embed.less
│ ├── responsive-utilities.less
│ ├── scaffolding.less
│ ├── svc-colors.less
│ ├── tables.less
│ ├── theme.less
│ ├── themify-icons.less
│ ├── thumbnails.less
│ ├── titillium-web.less
│ ├── tooltip.less
│ ├── type.less
│ ├── utilities.less
│ ├── variables.less
│ └── wells.less
├── components
│ ├── alerts
│ │ ├── alertCounter.jsx
│ │ ├── alertTabs.jsx
│ │ ├── alerts.jsx
│ │ ├── alerts.less
│ │ ├── alertsTable.jsx
│ │ ├── alertsTableSparkline.jsx
│ │ ├── alertsToolbar.jsx
│ │ ├── details
│ │ │ ├── alertDetails.jsx
│ │ │ ├── alertDetailsToolbar.jsx
│ │ │ ├── alertHistory.jsx
│ │ │ ├── alertSubscriptions.jsx
│ │ │ └── subscriptionRow.jsx
│ │ ├── stores
│ │ │ ├── alertDetailsStore.js
│ │ │ ├── alertTrendFetcher.js
│ │ │ └── serviceAlertsStore.js
│ │ └── utils
│ │ │ └── subscriptionConstructor.js
│ ├── common
│ │ ├── error.jsx
│ │ ├── error.less
│ │ ├── loading.jsx
│ │ ├── loading.less
│ │ ├── login.jsx
│ │ ├── login.less
│ │ ├── modal.jsx
│ │ ├── modal.less
│ │ ├── noMatch.jsx
│ │ ├── resultsTable.less
│ │ ├── timeRangePicker.jsx
│ │ ├── timeRangePicker.less
│ │ ├── withTracker.jsx
│ │ └── workInProgress.jsx
│ ├── docs
│ │ └── help.jsx
│ ├── layout
│ │ ├── authenticationTimeoutModal.jsx
│ │ ├── footer.jsx
│ │ ├── footer.less
│ │ └── slimHeader.jsx
│ ├── serviceGraph
│ │ ├── connectionDetails.jsx
│ │ ├── graphSearch.jsx
│ │ ├── nodeDetails.jsx
│ │ ├── serviceGraph.jsx
│ │ ├── serviceGraph.less
│ │ ├── serviceGraphContainer.jsx
│ │ ├── serviceGraphResults.jsx
│ │ ├── stores
│ │ │ └── serviceGraphStore.js
│ │ ├── trafficTable.jsx
│ │ ├── util
│ │ │ └── graph.js
│ │ ├── vizceralConfig.js
│ │ └── vizceralExt.jsx
│ ├── serviceInsights
│ │ ├── serviceInsights.jsx
│ │ ├── serviceInsights.less
│ │ ├── serviceInsightsGraph
│ │ │ ├── dataLayout.js
│ │ │ ├── dragGroup.jsx
│ │ │ ├── icons
│ │ │ │ ├── db.svg
│ │ │ │ ├── gateway.svg
│ │ │ │ ├── outbound.svg
│ │ │ │ └── uninstrumented.svg
│ │ │ ├── label.jsx
│ │ │ ├── labels.jsx
│ │ │ ├── lines.jsx
│ │ │ ├── nodes.jsx
│ │ │ ├── serviceInsightsGraph.jsx
│ │ │ ├── serviceInsightsGraph.less
│ │ │ ├── tooltip.jsx
│ │ │ └── tooltip.less
│ │ ├── stores
│ │ │ └── serviceInsightsStore.js
│ │ └── summary.jsx
│ ├── servicePerf
│ │ ├── servicePerformance.jsx
│ │ ├── servicePerformance.less
│ │ └── stores
│ │ │ └── servicePerfStore.js
│ ├── traces
│ │ ├── details
│ │ │ ├── latency
│ │ │ │ ├── latencyCostTab.jsx
│ │ │ │ └── latencyCostTabContainer.jsx
│ │ │ ├── rawTraceModal.jsx
│ │ │ ├── relatedTraces
│ │ │ │ ├── relatedTracesRow.jsx
│ │ │ │ ├── relatedTracesTab.jsx
│ │ │ │ └── relatedTracesTabContainer.jsx
│ │ │ ├── timeline
│ │ │ │ ├── logsTable.jsx
│ │ │ │ ├── rawSpan.jsx
│ │ │ │ ├── span.jsx
│ │ │ │ ├── spanDetailsModal.jsx
│ │ │ │ ├── tagsTable.jsx
│ │ │ │ ├── timelineTab.jsx
│ │ │ │ └── timelineTabContainer.jsx
│ │ │ ├── traceDetails.jsx
│ │ │ ├── traceDetails.less
│ │ │ └── trends
│ │ │ │ ├── serviceOperationTrendRow.jsx
│ │ │ │ ├── trendsTab.jsx
│ │ │ │ └── trendsTabContainer.jsx
│ │ ├── results
│ │ │ ├── noSearch.jsx
│ │ │ ├── noSearch.less
│ │ │ ├── spanResultsTable.jsx
│ │ │ ├── spansView.jsx
│ │ │ ├── tagsFilter.jsx
│ │ │ ├── traceResults.jsx
│ │ │ ├── traceResultsTable.jsx
│ │ │ ├── traceTimeline.jsx
│ │ │ ├── traceTimeline.less
│ │ │ └── tracesContainer.jsx
│ │ ├── stores
│ │ │ ├── latencyCostStore.js
│ │ │ ├── rawSpanStore.js
│ │ │ ├── rawTraceStore.js
│ │ │ ├── searchableKeysStore.js
│ │ │ ├── spansSearchStore.js
│ │ │ ├── traceDetailsStore.js
│ │ │ ├── traceTrendFetcher.js
│ │ │ └── tracesSearchStore.js
│ │ ├── traces.less
│ │ ├── upload
│ │ │ ├── uploadContainer.jsx
│ │ │ └── uploadHeader.jsx
│ │ └── utils
│ │ │ ├── auxiliaryTags.js
│ │ │ ├── presets.js
│ │ │ └── traceQueryParser.js
│ ├── trends
│ │ ├── details
│ │ │ ├── graphs
│ │ │ │ ├── countGraph.jsx
│ │ │ │ ├── durationGraph.jsx
│ │ │ │ ├── graphContainer.jsx
│ │ │ │ ├── graphContainer.less
│ │ │ │ ├── missingTrend.jsx
│ │ │ │ ├── missingTrend.less
│ │ │ │ ├── options.js
│ │ │ │ └── successGraph.jsx
│ │ │ ├── trendDetails.jsx
│ │ │ ├── trendDetails.less
│ │ │ ├── trendDetailsToolbar.jsx
│ │ │ └── trendDetailsToolbar.less
│ │ ├── operation
│ │ │ ├── operationResults.jsx
│ │ │ ├── operationResults.less
│ │ │ ├── operationResultsHeatmap.jsx
│ │ │ ├── operationResultsHeatmap.less
│ │ │ ├── operationResultsTable.jsx
│ │ │ └── operationResultsTable.less
│ │ ├── stores
│ │ │ └── operationStore.js
│ │ └── utils
│ │ │ ├── metricGranularity.js
│ │ │ ├── trendSparklines.jsx
│ │ │ └── trendsTableFormatters.jsx
│ └── universalSearch
│ │ ├── searchBar
│ │ ├── autosuggest.jsx
│ │ ├── autosuggest.less
│ │ ├── chips.jsx
│ │ ├── guide.jsx
│ │ ├── queryBank.jsx
│ │ ├── searchBar.jsx
│ │ ├── searchSubmit.jsx
│ │ ├── stores
│ │ │ ├── searchBarUiStateStore.js
│ │ │ └── searchableKeysStore.js
│ │ ├── suggestions.jsx
│ │ ├── timeRangePicker.jsx
│ │ ├── timeRangePicker.less
│ │ └── timeWindowPicker.jsx
│ │ ├── tabs
│ │ ├── emptyTabPlaceholder.jsx
│ │ ├── externalLinksList.jsx
│ │ ├── serviceGraph.jsx
│ │ ├── serviceInsights.jsx
│ │ ├── servicePerformance.jsx
│ │ ├── tabStores
│ │ │ ├── alertsTabStateStore.js
│ │ │ ├── serviceGraphStateStore.js
│ │ │ ├── serviceInsightsTabStateStore.js
│ │ │ ├── servicePerformanceStateStore.js
│ │ │ ├── tracesTabStateStore.js
│ │ │ └── trendsTabStateStore.js
│ │ └── tabs.jsx
│ │ ├── universalSearch.jsx
│ │ ├── universalSearch.less
│ │ └── utils
│ │ └── urlUtils.js
├── main.jsx
├── stores
│ ├── authenticationStore.js
│ ├── errorHandlingStore.js
│ ├── operationStore.js
│ ├── serviceStore.js
│ └── storesInitializer.js
└── utils
│ ├── blobUtil.js
│ ├── externalLinkFormatter.jsx
│ ├── formatters.js
│ ├── hashUtil.js
│ ├── linkBuilder.js
│ ├── loginRenewer.js
│ ├── queryParser.js
│ ├── serviceColorMapper.js
│ ├── timeWindow.js
│ └── validUrl.js
├── test
├── server
│ ├── config
│ │ └── override.spec.js
│ ├── connectors
│ │ ├── serviceGraph
│ │ │ ├── haystack
│ │ │ │ └── serviceGraphConnector.spec.js
│ │ │ └── zipkin
│ │ │ │ └── converter.spec.js
│ │ ├── serviceInsights
│ │ │ ├── detectCycles.spec.js
│ │ │ ├── fetcher.spec.js
│ │ │ ├── graphDataExtractor.spec.js
│ │ │ └── serviceInsightsConnector.spec.js
│ │ ├── traces
│ │ │ ├── haystack
│ │ │ │ ├── search
│ │ │ │ │ └── searchResultsTransformer.spec.js
│ │ │ │ └── tracesConnector.spec.js
│ │ │ └── zipkin
│ │ │ │ ├── converter.spec.js
│ │ │ │ └── tracesConnector.spec.js
│ │ ├── trends
│ │ │ └── haystack
│ │ │ │ └── trendsConnector.spec.js
│ │ └── utils
│ │ │ └── encoders
│ │ │ ├── Base64Encoder.spec.js
│ │ │ ├── MetricpointNameEncoder.spec.js
│ │ │ ├── NoopEncoder.spec.js
│ │ │ └── PeriodReplacementEncoder.spec.js
│ └── routes
│ │ ├── alertsApi.spec.js
│ │ ├── index.spec.js
│ │ ├── serviceInsightsApi.spec.js
│ │ ├── servicesApi.spec.js
│ │ ├── servicesPerfApi.spec.js
│ │ ├── tracesApi.spec.js
│ │ └── trendsApi.spec.js
└── src
│ ├── components
│ ├── alerts.spec.jsx
│ ├── common
│ │ ├── help.spec.jsx
│ │ ├── noMatch.spec.jsx
│ │ └── timeRangePicker.spec.jsx
│ ├── layout.spec.jsx
│ ├── serviceGraph
│ │ ├── graph.spec.js
│ │ ├── serviceGraph.spec.jsx
│ │ └── util
│ │ │ └── edges.js
│ ├── serviceInsights
│ │ ├── serviceInsights.spec.jsx
│ │ ├── serviceInsightsGraph
│ │ │ ├── dataLayout.spec.js
│ │ │ ├── dragGroup.spec.jsx
│ │ │ ├── label.spec.jsx
│ │ │ ├── labels.spec.jsx
│ │ │ ├── lines.spec.jsx
│ │ │ ├── nodes.spec.jsx
│ │ │ ├── serviceInsightsGraph.spec.jsx
│ │ │ └── tooltip.spec.jsx
│ │ ├── stores
│ │ │ └── serviceInsightsStore.spec.js
│ │ └── summary.spec.jsx
│ ├── servicePerf.spec.jsx
│ ├── traces
│ │ ├── latencyCost.spec.jsx
│ │ ├── rawSpan.spec.jsx
│ │ ├── rawTrace.spec.jsx
│ │ ├── spansView.spec.jsx
│ │ └── traces.spec.jsx
│ ├── trends
│ │ ├── details
│ │ │ └── graphs
│ │ │ │ └── durationGraph.spec.jsx
│ │ └── trends.spec.jsx
│ └── universalSearch
│ │ ├── searchBar
│ │ ├── stores
│ │ │ └── searchBarUiStateStore.spec.js
│ │ └── timeRangePicker.spec.jsx
│ │ ├── tabs
│ │ ├── serviceInsights.spec.jsx
│ │ └── tabStores
│ │ │ ├── serviceInsightsTabStateStore.spec.js
│ │ │ └── tracesTabStateStore.spec.js
│ │ └── universalSearch.spec.jsx
│ ├── main.spec.jsx
│ ├── stores
│ ├── alertStore.spec.js
│ ├── operationStore.spec.js
│ ├── serviceGraphStore.spec.js
│ ├── serviceStore.spec.js
│ ├── tracesStore.spec.js
│ └── trendsStore.spec.js
│ ├── test_helper.js
│ └── utils
│ └── timeWindow.spec.js
├── universal
└── enums.js
└── webpack.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": [
3 | "lodash",
4 | [
5 | "@babel/plugin-proposal-decorators",
6 | {
7 | "legacy": true
8 | }
9 | ],
10 | [
11 | "@babel/plugin-proposal-class-properties",
12 | {
13 | "loose": true
14 | }
15 | ],
16 | "dynamic-import-node"
17 | ],
18 | "presets": [
19 | ["@babel/preset-env", {
20 | "targets": {
21 | "node": "current"
22 | }
23 | }],
24 | "@babel/preset-react"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/.coveralls.yml:
--------------------------------------------------------------------------------
1 | service_name: travis-ci
2 | repo_token: rmv39G8JKUPr9W8whITKKlHLl3x4CEi50
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | public/*
2 | haystack-idl/*
3 | static_codegen/*
4 | coverage/*'
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | sample
4 | *.log
5 |
6 | # Mac Trash directories
7 | *.DS_Store
8 |
9 | # Dependency directory
10 | node_modules
11 |
12 | #intellij
13 | .idea/
14 | *.iml
15 | *.ipr
16 | *.iws
17 |
18 | # generated scripts/css in public should not be commited
19 | public/bundles
20 | static_codegen
21 |
22 | # Code coverage reports
23 | .nyc_output/
24 | coverage
25 |
26 | # HTTPS Certs
27 | server.cert
28 | server.key
29 |
30 | # Zipkin runner
31 | zipkin-workspace
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "haystack-idl"]
2 | path = haystack-idl
3 | url = https://github.com/ExpediaDotCom/haystack-idl
4 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | registry=https://registry.npmjs.org/
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | package.json
2 | package-lock.json
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "tabWidth": 4,
3 | "printWidth": 150,
4 | "singleQuote": true,
5 | "bracketSpacing": false,
6 | "arrowParens": "always"
7 | }
8 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 |
3 | node_js:
4 | - "12"
5 |
6 | services:
7 | - docker
8 |
9 | dist: xenial
10 |
11 | env:
12 | global:
13 | - BRANCH=${TRAVIS_BRANCH}
14 | - TAG=${TRAVIS_TAG}
15 | - SHA=${TRAVIS_COMMIT}
16 |
17 | before_install:
18 | - sudo apt-get update
19 | - sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
20 | - sudo apt-get install libcairo2-dev libjpeg8-dev libpango1.0-dev libgif-dev build-essential g++
21 |
22 | script:
23 | # build, create docker image
24 | # upload to dockerhub only for master(non PR) and tag scenario
25 | - if ([ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]) || [ -n "$TRAVIS_TAG" ]; then make release; else make all; fi
26 |
27 | notifications:
28 | email:
29 | - haystack-notifications@expedia.com
30 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | // Place your settings in this file to overwrite default and user settings.
2 | {
3 | // Prettier
4 | "editor.formatOnSave": true,
5 | "[less]": {
6 | "editor.formatOnSave": true
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ##Bugs
2 | We use Github Issues for our bug reporting. Please make sure the bug isn't already listed before opening a new issue.
3 |
4 | ##Development
5 | All work on Haystack happens directly on Github. Core Haystack team members will review opened pull requests.
6 |
7 | ##Requests
8 | If you see a feature that you would like to be added, please open an issue in the respective repository or in the general Haystack repo.
9 |
10 | ##Contributing to Documentation
11 | To contribute to documentation, you can directly modify the corresponding .md files in the docs directory under the base haystack repository, and submit a pull request. Once your PR is merged, the documentation is automatically built and deployed to https://expediadotcom.github.io/haystack.
12 |
13 | ##License
14 | By contributing to Haystack, you agree that your contributions will be licensed under its Apache License.
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: clean build docker_build all release
2 |
3 | # docker namespace
4 | export DOCKER_ORG := expediadotcom
5 | export DOCKER_IMAGE_NAME := haystack-ui
6 |
7 | clean:
8 | npm run clean
9 |
10 | install:
11 | npm install
12 |
13 | build: clean install
14 | npm run build
15 |
16 | docker_build:
17 | docker build -t $(DOCKER_IMAGE_NAME) -f build/docker/Dockerfile .
18 |
19 | all: build docker_build
20 |
21 | # build all and release
22 | release: all
23 | ./build/docker/publish-to-docker-hub.sh
24 |
--------------------------------------------------------------------------------
/Release.md:
--------------------------------------------------------------------------------
1 | #Releasing
2 | Currently we publish the repo to only docker hub. We don't publish it to nexus central repository since its a npm module.
3 |
4 | #How to release and publish
5 |
6 | * Git tagging:
7 |
8 | ```git tag -a 1.x.x -m "Release description..."```
9 |
10 | Or you can also tag using UI: https://github.com/ExpediaDotCom/haystack-ui/releases
--------------------------------------------------------------------------------
/build/docker/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:12 AS base
2 |
3 | ENV APP_HOME /app
4 | ENV PUBLIC_PATH /${APP_HOME}/public
5 | ENV SERVER_PATH /${APP_HOME}/server
6 | ENV UNIVERSAL_PATH /${APP_HOME}/universal
7 | ENV NODE_MODULES_PATH /${APP_HOME}/node_modules
8 | ENV STATIC_CODEGEN_PATH /${APP_HOME}/static_codegen
9 | ENV PACKAGE_JSON_PATH /${APP_HOME}/package.json
10 | WORKDIR ${APP_HOME}
11 |
12 | # generating proto code, building bundles and running tests
13 | FROM base AS builder
14 | COPY . .
15 | RUN npm -q install
16 | RUN npm -q run build
17 |
18 | # creating release image
19 | FROM base AS release
20 | COPY --from=builder ${PUBLIC_PATH} ${PUBLIC_PATH}
21 | COPY --from=builder ${SERVER_PATH} ${SERVER_PATH}
22 | COPY --from=builder ${UNIVERSAL_PATH} ${UNIVERSAL_PATH}
23 | COPY --from=builder ${STATIC_CODEGEN_PATH} ${STATIC_CODEGEN_PATH}
24 | COPY --from=builder ${PACKAGE_JSON_PATH} ${PACKAGE_JSON_PATH}
25 | RUN npm -q install --only=prod
26 |
27 | EXPOSE 8080
28 | CMD node server/start.js
29 |
--------------------------------------------------------------------------------
/build/docker/publish-to-docker-hub.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | QUALIFIED_DOCKER_IMAGE_NAME=$DOCKER_ORG/$DOCKER_IMAGE_NAME
6 | echo "DOCKER_ORG=$DOCKER_ORG, DOCKER_IMAGE_NAME=$DOCKER_IMAGE_NAME, QUALIFIED_DOCKER_IMAGE_NAME=$QUALIFIED_DOCKER_IMAGE_NAME"
7 | echo "BRANCH=$BRANCH, TAG=$TAG, SHA=$SHA"
8 |
9 | # login
10 | docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD
11 |
12 | # Add tags
13 | if [[ $TAG =~ ([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then
14 | echo "releasing semantic versions"
15 |
16 | unset MAJOR MINOR PATCH
17 | MAJOR="${BASH_REMATCH[1]}"
18 | MINOR="${BASH_REMATCH[2]}"
19 | PATCH="${BASH_REMATCH[3]}"
20 |
21 | # for tag, add MAJOR, MAJOR.MINOR, MAJOR.MINOR.PATCH and latest as tag
22 | docker tag $DOCKER_IMAGE_NAME $QUALIFIED_DOCKER_IMAGE_NAME:$MAJOR
23 | docker tag $DOCKER_IMAGE_NAME $QUALIFIED_DOCKER_IMAGE_NAME:$MAJOR.$MINOR
24 | docker tag $DOCKER_IMAGE_NAME $QUALIFIED_DOCKER_IMAGE_NAME:$MAJOR.$MINOR.$PATCH
25 | docker tag $DOCKER_IMAGE_NAME $QUALIFIED_DOCKER_IMAGE_NAME:latest
26 |
27 | # publish image with tags
28 | docker push $QUALIFIED_DOCKER_IMAGE_NAME
29 |
30 | elif [[ "$BRANCH" == "master" ]]; then
31 | echo "releasing master branch"
32 |
33 | # for 'master' branch, add SHA as tags
34 | docker tag $DOCKER_IMAGE_NAME $QUALIFIED_DOCKER_IMAGE_NAME:$SHA
35 |
36 | # publish image with tags
37 | docker push $QUALIFIED_DOCKER_IMAGE_NAME
38 | fi
39 |
--------------------------------------------------------------------------------
/build/zipkin/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Zipkin haystack-ui Quickstart Utility
3 |
4 | Utility script to run haystack-ui with a zipkin instance as backend for traces. It spins sleuth-webmvc-example services for feeding traces in Zipkin cluster and generates some examples. It configures haystack-ui point to Zipkin V2 api and has only traces subsystem.
5 |
6 |
7 | ### PREREQUISITES
8 |
9 | - Assumes that you have mvn and git available on your machine.
10 | - haystack-ui must be already installed (npm install) and built (npm build), if not please install and build before running this script
11 |
12 |
13 | ### USAGE
14 |
15 | ```> ./zipkin-quickstart```
16 |
17 | Wait for couple of minutes till you see `Express server listening : 8080` message. Then you can hit [http://localhost:8080/search?serviceName=backend](http://localhost:8080/search?serviceName=backend) to use haystack-ui. Search for `serviceName=backend` to see pre-feeded traces coming from Zipkin backend.
18 |
19 |
20 | ### OPTIONS
21 |
22 | ```
23 | -h help
24 | -d debug mode, will emit out all logs from zipkin and sleuth-webmvc-example
25 | ```
26 |
27 |
--------------------------------------------------------------------------------
/build/zipkin/base.json:
--------------------------------------------------------------------------------
1 | {
2 | "port": 8080,
3 | "cluster": false,
4 | "upstreamTimeout": 30000,
5 | "connectors": {
6 | "traces": {
7 | "connectorName": "zipkin",
8 | "zipkinUrl": "http://localhost:9411/api/v2"
9 | },
10 | "serviceGraph": {
11 | "connectorName": "zipkin",
12 | "zipkinUrl": "http://localhost:9411/api/v2"
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/deployment/terraform/outputs.tf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/deployment/terraform/outputs.tf
--------------------------------------------------------------------------------
/deployment/terraform/templates/deployment_yaml.tpl:
--------------------------------------------------------------------------------
1 | # ------------------- Deployment ------------------- #
2 |
3 | kind: Deployment
4 | apiVersion: apps/v1beta2
5 | metadata:
6 | labels:
7 | k8s-app: ${app_name}
8 | name: ${app_name}
9 | namespace: ${namespace}
10 | spec:
11 | replicas: ${replicas}
12 | revisionHistoryLimit: 10
13 | selector:
14 | matchLabels:
15 | k8s-app: ${app_name}
16 | template:
17 | metadata:
18 | labels:
19 | k8s-app: ${app_name}
20 | spec:
21 | containers:
22 | - name: ${app_name}
23 | image: ${image}
24 | volumeMounts:
25 | # Create on-disk volume to store exec logs
26 | - mountPath: /config
27 | name: config-volume
28 | resources:
29 | limits:
30 | cpu: ${cpu_limit}
31 | memory: ${memory_limit}Mi
32 | requests:
33 | cpu: ${cpu_request}
34 | memory: ${memory_limit}Mi
35 | env:
36 | - name: "HAYSTACK_OVERRIDES_CONFIG_PATH"
37 | value: "/config/haystack-ui.json"
38 | nodeSelector:
39 | ${node_selecter_label}
40 | volumes:
41 | - name: config-volume
42 | configMap:
43 | name: ${configmap_name}
44 |
45 | # ------------------- Service ------------------- #
46 | ---
47 | apiVersion: v1
48 | kind: Service
49 | metadata:
50 | labels:
51 | k8s-app: ${app_name}
52 | name: ${app_name}
53 | namespace: ${namespace}
54 | spec:
55 | ports:
56 | - port: ${service_port}
57 | targetPort: ${container_port}
58 | selector:
59 | k8s-app: ${app_name}
60 |
--------------------------------------------------------------------------------
/deployment/terraform/templates/haystack-ui_json.tpl:
--------------------------------------------------------------------------------
1 | {
2 | "port": 8080,
3 | "cluster": true,
4 | "upstreamTimeout": 30000,
5 | "encoder": "${encoder_type}",
6 | "enableServicePerformance": false,
7 | "enableServiceLevelTrends": false,
8 | "enableLatencyCostViewer": true,
9 | "graphite": {
10 | "host": "${graphite_hostname}",
11 | "port": ${graphite_port}
12 | },
13 | "grpcOptions": {
14 | "grpc.max_receive_message_length": 52428800
15 | },
16 | "connectors": {
17 | "traces": {
18 | "connectorName": "haystack",
19 | "haystackHost": "${trace_reader_hostname}",
20 | "haystackPort": ${trace_reader_service_port},
21 | "serviceRefreshIntervalInSecs": 60,
22 | "fieldKeys": [${whitelisted_fields}]
23 | },
24 | "trends": {
25 | "connectorName": "haystack",
26 | "metricTankUrl": "http://${metrictank_hostname}:${metrictank_port}"
27 | },
28 | "alerts": {
29 | "connectorName": "haystack",
30 | "metricTankUrl": "http://${metrictank_hostname}:${metrictank_port}",
31 | "alertFreqInSec": 300,
32 | "alertMergeBufferTimeInSec": 60,
33 | "subscriptions": {
34 | "connectorName": "stub",
35 | "enabled": false
36 | }
37 | }
38 | },
39 | "enableSSO": ${ui_enable_sso},
40 | "saml": {
41 | "callbackUrl": "${ui_saml_callback_url}",
42 | "entry_point": "${ui_saml_entry_point}",
43 | "issuer": "${ui_saml_issuer}"
44 | },
45 | "sessionTimeout": 3600000,
46 | "sessionSecret": "${ui_session_secret}"
47 | }
48 |
--------------------------------------------------------------------------------
/deployment/terraform/variables.tf:
--------------------------------------------------------------------------------
1 | variable "enabled" {
2 | default = true
3 | }
4 |
5 | variable "image" {}
6 | variable "replicas" {}
7 | variable "namespace" {}
8 | variable "kubectl_executable_name" {}
9 | variable "kubectl_context_name" {}
10 | variable "node_selecter_label"{}
11 | variable "memory_request"{}
12 | variable "memory_limit"{}
13 | variable "cpu_request"{}
14 | variable "cpu_limit"{}
15 | variable "graphite_hostname" {}
16 | variable "graphite_port" {}
17 | variable "encoder_type" {}
18 |
19 | variable "termination_grace_period" {
20 | default = 30
21 | }
22 | variable "service_port" {
23 | default = 80
24 | }
25 | variable "container_port" {
26 | default = 8080
27 | }
28 |
29 | variable "k8s_cluster_name" {}
30 |
31 | variable "trace_reader_hostname" {}
32 |
33 | variable "trace_reader_service_port" {}
34 |
35 | variable "metrictank_hostname" {}
36 |
37 | variable "metrictank_port" {}
38 |
39 | variable "whitelisted_fields" {}
40 |
41 | variable "ui_enable_sso" {
42 | default = false
43 | }
44 |
45 | variable "ui_saml_callback_url" {}
46 |
47 | variable "ui_saml_entry_point" {}
48 |
49 | variable "ui_saml_issuer" {}
50 |
51 | variable "ui_session_secret" {}
52 |
--------------------------------------------------------------------------------
/public/assets.json:
--------------------------------------------------------------------------------
1 | {"ServiceInsights":{"css":"/bundles/style/ServiceInsights.css","js":"/bundles/js/ServiceInsights.js"},"app":{"css":"/bundles/style/app.css","js":"/bundles/js/app.js"},"commons":{"js":"/bundles/js/commons.js"},"serviceGraphContainer":{"js":"/bundles/js/serviceGraphContainer.js"},"servicePerformance":{"css":"/bundles/style/servicePerformance.css","js":"/bundles/js/servicePerformance.js"},"vendors~ServiceInsights":{"js":"/bundles/js/vendors~ServiceInsights.js"},"vendors~ServiceInsights~serviceGraphContainer":{"js":"/bundles/js/vendors~ServiceInsights~serviceGraphContainer.js"},"vendors~serviceGraphContainer":{"js":"/bundles/js/vendors~serviceGraphContainer.js"},"vendors~servicePerformance":{"js":"/bundles/js/vendors~servicePerformance.js"},"vendors~vis":{"js":"/bundles/js/vendors~vis.js"}}
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/favicon.ico
--------------------------------------------------------------------------------
/public/fonts/LICENSE_THEMIFY:
--------------------------------------------------------------------------------
1 | LICENSE
2 |
3 | - Themify Icons font licensed under: http://scripts.sil.org/OFL
4 | - Code licensed under: http://opensource.org/licenses/mit-license.html
5 | - All brand icons are copyright/trademarks of their respective owners.
6 |
--------------------------------------------------------------------------------
/public/fonts/themify.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/fonts/themify.ttf
--------------------------------------------------------------------------------
/public/fonts/themify.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/fonts/themify.woff
--------------------------------------------------------------------------------
/public/fonts/titillium-web-v5-latin-200.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/fonts/titillium-web-v5-latin-200.ttf
--------------------------------------------------------------------------------
/public/fonts/titillium-web-v5-latin-200.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/fonts/titillium-web-v5-latin-200.woff
--------------------------------------------------------------------------------
/public/fonts/titillium-web-v5-latin-200.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/fonts/titillium-web-v5-latin-200.woff2
--------------------------------------------------------------------------------
/public/fonts/titillium-web-v5-latin-300.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/fonts/titillium-web-v5-latin-300.ttf
--------------------------------------------------------------------------------
/public/fonts/titillium-web-v5-latin-300.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/fonts/titillium-web-v5-latin-300.woff
--------------------------------------------------------------------------------
/public/fonts/titillium-web-v5-latin-300.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/fonts/titillium-web-v5-latin-300.woff2
--------------------------------------------------------------------------------
/public/fonts/titillium-web-v5-latin-600.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/fonts/titillium-web-v5-latin-600.ttf
--------------------------------------------------------------------------------
/public/fonts/titillium-web-v5-latin-600.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/fonts/titillium-web-v5-latin-600.woff
--------------------------------------------------------------------------------
/public/fonts/titillium-web-v5-latin-600.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/fonts/titillium-web-v5-latin-600.woff2
--------------------------------------------------------------------------------
/public/fonts/titillium-web-v5-latin-700.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/fonts/titillium-web-v5-latin-700.ttf
--------------------------------------------------------------------------------
/public/fonts/titillium-web-v5-latin-700.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/fonts/titillium-web-v5-latin-700.woff
--------------------------------------------------------------------------------
/public/fonts/titillium-web-v5-latin-700.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/fonts/titillium-web-v5-latin-700.woff2
--------------------------------------------------------------------------------
/public/fonts/titillium-web-v5-latin-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/fonts/titillium-web-v5-latin-regular.ttf
--------------------------------------------------------------------------------
/public/fonts/titillium-web-v5-latin-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/fonts/titillium-web-v5-latin-regular.woff
--------------------------------------------------------------------------------
/public/fonts/titillium-web-v5-latin-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/fonts/titillium-web-v5-latin-regular.woff2
--------------------------------------------------------------------------------
/public/images/assets/alerts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/images/assets/alerts.png
--------------------------------------------------------------------------------
/public/images/assets/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/images/assets/demo.gif
--------------------------------------------------------------------------------
/public/images/assets/logo_lighter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/images/assets/logo_lighter.png
--------------------------------------------------------------------------------
/public/images/assets/logo_with_title.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/images/assets/logo_with_title.png
--------------------------------------------------------------------------------
/public/images/assets/logo_with_title_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/images/assets/logo_with_title_dark.png
--------------------------------------------------------------------------------
/public/images/assets/logo_with_title_transparent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/images/assets/logo_with_title_transparent.png
--------------------------------------------------------------------------------
/public/images/assets/service_graph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/images/assets/service_graph.png
--------------------------------------------------------------------------------
/public/images/assets/trace_timeline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/images/assets/trace_timeline.png
--------------------------------------------------------------------------------
/public/images/assets/trends.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/images/assets/trends.png
--------------------------------------------------------------------------------
/public/images/assets/universal_search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/images/assets/universal_search.png
--------------------------------------------------------------------------------
/public/images/error.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/public/images/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/images/loading.gif
--------------------------------------------------------------------------------
/public/images/logo-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/images/logo-white.png
--------------------------------------------------------------------------------
/public/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/images/logo.png
--------------------------------------------------------------------------------
/public/images/slack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/images/slack.png
--------------------------------------------------------------------------------
/public/images/success.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/public/images/zipkin-logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ExpediaDotCom/haystack-ui/08370d17a5316378519322ee7e9b15a720f5b33d/public/images/zipkin-logo.jpg
--------------------------------------------------------------------------------
/server/config/config.js:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | * Copyright 2018 Expedia Group
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except 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, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | *
17 |
18 | */
19 |
20 | const _ = require('lodash');
21 | const baseConfiguration = require('../config/base');
22 | const override = require('./override');
23 |
24 | let finalConfiguration = _.merge({}, baseConfiguration);
25 |
26 | // if an override configuration file is provided, extend the base config with
27 | // the provided one. This is not a recursive merge, just a top level extend with
28 | // the overriden config
29 | if (process.env.HAYSTACK_OVERRIDES_CONFIG_PATH) {
30 | let overridesConfigration = process.env.HAYSTACK_OVERRIDES_CONFIG_PATH;
31 | if (!overridesConfigration.startsWith('/')) {
32 | overridesConfigration = `${process.cwd()}/${overridesConfigration}`;
33 | }
34 | // eslint-disable-next-line global-require, import/no-dynamic-require
35 | const environmentSpecificConfiguration = require(overridesConfigration);
36 | finalConfiguration = _.extend({}, finalConfiguration, environmentSpecificConfiguration);
37 | }
38 |
39 | // if there are environment variables, read them as objects and merge them
40 | // into the current configuration
41 | const overrideObject = override.readOverrides(process.env);
42 | module.exports = _.merge({}, finalConfiguration, overrideObject);
43 |
--------------------------------------------------------------------------------
/server/connectors/alerts/haystack/expressionTreeBuilder.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 requestBuilder = {};
18 | const messages = require('../../../../static_codegen/subscription/subscriptionManagement_pb');
19 |
20 |
21 | requestBuilder.createSubscriptionExpressionTree = (subscription) => {
22 | const expressionTree = new messages.ExpressionTree();
23 | expressionTree.setOperator(messages.ExpressionTree.Operator.AND);
24 | const uiExpressionTree = subscription.expressionTree;
25 |
26 | const operands = Object.keys(uiExpressionTree).map((key) => {
27 | const op = new messages.Operand();
28 |
29 | const field = new messages.Field();
30 | field.setName(key);
31 | field.setValue(uiExpressionTree[key]);
32 |
33 | op.setField(field);
34 |
35 | return op;
36 | });
37 |
38 | expressionTree.setOperandsList(operands);
39 | return expressionTree;
40 | };
41 |
42 | module.exports = requestBuilder;
43 |
--------------------------------------------------------------------------------
/server/connectors/operations/restFetcher.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 axios = require('axios');
18 | const Q = require('q');
19 | const errorConverter = require('../utils/errorConverter');
20 | const logger = require('../../utils/logger').withIdentifier('fetcher.rest');
21 | const metrics = require('../../utils/metrics');
22 |
23 | const fetcher = (fetcherName) => ({
24 | fetch: (url, headers = {}) => {
25 | const deferred = Q.defer();
26 | const timer = metrics.timer(`fetcher_rest_${fetcherName}`).start();
27 |
28 | axios.get(url, {headers}).then(
29 | (response) => {
30 | timer.end();
31 | logger.info(`fetch successful: ${url}`);
32 |
33 | deferred.resolve(response.data);
34 | },
35 | (error) => {
36 | timer.end();
37 | metrics.meter(`fetcher_rest_failure_${fetcherName}`).mark();
38 | logger.error(`fetch failed: ${url}`);
39 |
40 | deferred.reject(errorConverter.fromAxiosError(error));
41 | }
42 | );
43 |
44 | return deferred.promise;
45 | }
46 | });
47 |
48 | module.exports = fetcher;
49 |
--------------------------------------------------------------------------------
/server/connectors/serviceGraph/haystack/serviceGraphConnector.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 Q = require('q');
18 |
19 | const fetcher = require('../../operations/restFetcher');
20 | const config = require('../../../config/config');
21 | const extractor = require('./graphDataExtractor');
22 |
23 | const trendsFetcher = fetcher('serviceGraph');
24 |
25 | const connector = {};
26 | const serviceGraphUrl = config.connectors.serviceGraph && config.connectors.serviceGraph.serviceGraphUrl;
27 |
28 | function fetchServiceGraph(from, to) {
29 | return trendsFetcher
30 | .fetch(`${serviceGraphUrl}?from=${from}&to=${to}`)
31 | .then(data => extractor.extractGraphs(data));
32 | }
33 |
34 | connector.getServiceGraphForTimeLine = (from, to) => Q.fcall(() => fetchServiceGraph(from, to));
35 |
36 | module.exports = connector;
37 |
--------------------------------------------------------------------------------
/server/connectors/serviceGraph/zipkin/serviceGraphConnector.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 Q = require('q');
18 |
19 | const fetcher = require('../../operations/restFetcher');
20 | const config = require('../../../config/config');
21 | const converter = require('./converter');
22 | const extractor = require('../haystack/graphDataExtractor');
23 |
24 | const dependenciesFetcher = fetcher('getDependencies');
25 |
26 | const connector = {};
27 | const baseZipkinUrl = config.connectors.serviceGraph.zipkinUrl;
28 |
29 | function fetchServiceGraph(from, to) {
30 | const endTs = parseInt(to, 10);
31 | const lookback = endTs - parseInt(from, 10);
32 |
33 | return dependenciesFetcher
34 | .fetch(`${baseZipkinUrl}/dependencies?endTs=${endTs}&lookback=${lookback}`)
35 | .then(data => extractor.extractGraphFromEdges(converter.toHaystackServiceEdges(data)));
36 | }
37 |
38 | connector.getServiceGraphForTimeLine = (from, to) => Q.fcall(() => fetchServiceGraph(from, to));
39 |
40 | module.exports = connector;
41 |
--------------------------------------------------------------------------------
/server/connectors/services/servicesConnector.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 | const config = require('../../config/config');
17 | const LoaderBackedCache = require('../utils/LoaderBackedCache');
18 |
19 | const tracesConnector = config.connectors.traces && require(`../traces/${config.connectors.traces.connectorName}/tracesConnector`); // eslint-disable-line import/no-dynamic-require, global-require
20 | const refreshIntervalInSecs = config.connectors.traces.serviceRefreshIntervalInSecs;
21 | const connector = {};
22 |
23 | const serviceCache = new LoaderBackedCache(() => tracesConnector.getServices(), refreshIntervalInSecs * 1000);
24 | connector.getServices = () => serviceCache.get();
25 |
26 | const operationsCache = new LoaderBackedCache((serviceName) => tracesConnector.getOperations(serviceName), refreshIntervalInSecs * 1000);
27 | connector.getOperations = (serviceName) => operationsCache.get(serviceName);
28 |
29 | module.exports = connector;
30 |
--------------------------------------------------------------------------------
/server/connectors/traces/haystack/protobufConverters/traceCountsConverter.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 converter = {};
18 |
19 | converter.toTraceCountsJson = pbTraceCounts => pbTraceCounts.tracecountList.map(
20 | pbTraceCount => ({
21 | x: pbTraceCount.timestamp,
22 | y: pbTraceCount.count
23 | }
24 | ));
25 |
26 | module.exports = converter;
27 |
--------------------------------------------------------------------------------
/server/connectors/traces/haystack/search/searchRequestBuilder.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 expressionTreeBuilder = require('../expressionTreeBuilder');
18 |
19 | const requestBuilder = {};
20 | const messages = require('../../../../../static_codegen/traceReader_pb');
21 |
22 | const DEFAULT_RESULTS_LIMIT = 25;
23 |
24 | requestBuilder.buildRequest = (query) => {
25 | const request = new messages.TracesSearchRequest();
26 |
27 | request.setFilterexpression(expressionTreeBuilder.createFilterExpression(query));
28 | request.setStarttime(parseInt(query.startTime, 10));
29 | request.setEndtime(parseInt(query.endTime, 10));
30 | request.setLimit(parseInt(query.limit, 10) || DEFAULT_RESULTS_LIMIT);
31 |
32 | return request;
33 | };
34 |
35 | module.exports = requestBuilder;
36 |
--------------------------------------------------------------------------------
/server/connectors/utils/encoders/Base64Encoder.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 | class Base64Encoder {
18 | static encode(name) {
19 | return Buffer.from(name).toString('base64').replace(new RegExp('=', 'g'), '_');
20 | }
21 |
22 | static decode(name) {
23 | return Buffer.from(name.replace(new RegExp('_', 'g'), '='), 'base64').toString('utf8');
24 | }
25 | }
26 |
27 | module.exports = Base64Encoder;
28 |
--------------------------------------------------------------------------------
/server/connectors/utils/encoders/MetricpointNameEncoder.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 PeriodReplacementEncoder = require('../encoders/PeriodReplacementEncoder');
18 | const Base64Encoder = require('../encoders/Base64Encoder');
19 | const NoopEncoder = require('../encoders/NoopEncoder');
20 |
21 | class MetricpointNameEncoder {
22 | constructor(encoderType) {
23 | if (encoderType === 'periodreplacement') {
24 | this.encoder = PeriodReplacementEncoder;
25 | } else if (encoderType === 'base64') {
26 | this.encoder = Base64Encoder;
27 | } else {
28 | this.encoder = NoopEncoder;
29 | }
30 | }
31 |
32 | encodeMetricpointName(operationName) {
33 | return this.encoder.encode(decodeURIComponent(operationName));
34 | }
35 |
36 | decodeMetricpointName(operationName) {
37 | return this.encoder.decode(operationName);
38 | }
39 | }
40 |
41 | module.exports = MetricpointNameEncoder;
42 |
--------------------------------------------------------------------------------
/server/connectors/utils/encoders/NoopEncoder.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 | class NoopEncoder {
18 | static encode(name) {
19 | return name;
20 | }
21 |
22 | static decode(name) {
23 | return name;
24 | }
25 | }
26 |
27 | module.exports = NoopEncoder;
28 |
--------------------------------------------------------------------------------
/server/connectors/utils/encoders/PeriodReplacementEncoder.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 | class PeriodReplacementEncoder {
18 | static encode(name) {
19 | return name.replace(/\./gi, '___');
20 | }
21 |
22 | static decode(name) {
23 | return name.replace(/___/gi, '.');
24 | }
25 | }
26 |
27 | module.exports = PeriodReplacementEncoder;
28 |
--------------------------------------------------------------------------------
/server/connectors/utils/errorConverter.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 converter = {};
18 |
19 | converter.fromAxiosError = (error) => new Error(`${error} ${JSON.stringify(error.config)}`);
20 |
21 | converter.fromGrpcError = (error) => new Error(`${JSON.stringify(error)}`);
22 |
23 | module.exports = converter;
24 |
--------------------------------------------------------------------------------
/server/connectors/utils/objectUtils.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 | const _ = require('lodash');
17 |
18 | const utils = {};
19 |
20 | utils.getPropIgnoringCase = (array, name) => {
21 | const prop = _.compact(array.map(query => JSON.parse(query.toLowerCase())[name.toLowerCase()]));
22 | return prop && prop.length > 0 && prop[0];
23 | };
24 |
25 | module.exports = utils;
26 |
27 |
--------------------------------------------------------------------------------
/server/routes/auth.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 express = require('express');
18 | const authenticatorWithRedirect = require('../sso/samlSsoAuthenticator').authenticatorWithRedirect;
19 | const authChecker = require('../sso/authChecker');
20 |
21 | const router = express.Router();
22 |
23 | const loggedOutHome = '/login';
24 |
25 | const authenticate = req => authenticatorWithRedirect(req);
26 |
27 | const extractFullRedirectUrl = req => req.originalUrl.split('/auth/login?redirectUrl=').pop();
28 |
29 | router.get('/login', (req, res, next) => {
30 | const redirectUrl = extractFullRedirectUrl(req);
31 | return authenticate(redirectUrl)(redirectUrl, res, next);
32 | });
33 |
34 | // check for active login session and then renew user
35 | router.get('/renewlogin', authChecker.forApi, (req, res, next) => {
36 | req.login({...req.user, timestamp: Date.now()}, (err) => {
37 | if (err) {
38 | next(err);
39 | } else {
40 | res.send(200);
41 | }
42 | });
43 | });
44 |
45 | router.get('/logout', (req, res) => {
46 | req.logout();
47 | req.session = null;
48 | res.redirect(loggedOutHome);
49 | });
50 |
51 | module.exports = router;
52 |
--------------------------------------------------------------------------------
/server/routes/login.js:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * Copyright 2018 Expedia Group
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except 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, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | const express = require('express');
19 | const config = require('../config/config');
20 | const assets = require('../../public/assets.json');
21 |
22 | const router = express.Router();
23 |
24 | router.get('/', (req, res) => {
25 | res.render('index', {
26 | bundleAppJsPath: assets.app.js,
27 | bundleAppCssPath: assets.app.css,
28 | bundleCommonsJsPath: assets.commons.js,
29 | ssoAdfsDomain: config.saml && config.saml.adfsDomain
30 | });
31 | });
32 |
33 | module.exports = router;
34 |
--------------------------------------------------------------------------------
/server/routes/serviceGraphApi.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 express = require('express');
18 | const config = require('../config/config');
19 | const handleResponsePromise = require('./utils/apiResponseHandler').handleResponsePromise;
20 |
21 | const serviceGraphConnector = require(`../connectors/serviceGraph/${config.connectors.serviceGraph.connectorName}/serviceGraphConnector`); // eslint-disable-line import/no-dynamic-require
22 |
23 | const router = express.Router();
24 |
25 | router.get('/serviceGraph', (req, res, next) => {
26 | handleResponsePromise(res, next, 'svc_graph_SVC')(
27 | () => serviceGraphConnector.getServiceGraphForTimeLine(req.query.from, req.query.to)
28 |
29 | );
30 | });
31 |
32 | module.exports = router;
33 |
--------------------------------------------------------------------------------
/server/routes/serviceInsightsApi.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Expedia Group
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 express = require('express');
18 | const {handleResponsePromise} = require('./utils/apiResponseHandler');
19 |
20 | const serviceInsightsConnector = require('../connectors/serviceInsights/serviceInsightsConnector');
21 |
22 | const router = express.Router();
23 |
24 | router.get('/serviceInsights', (req, res, next) => {
25 | handleResponsePromise(res, next, 'svc_insights_SVC')(() => {
26 | const {serviceName, operationName, traceId, startTime, endTime, limit, relationship} = req.query;
27 | return serviceInsightsConnector.getServiceInsightsForService({
28 | serviceName,
29 | operationName,
30 | traceId,
31 | startTime,
32 | endTime,
33 | limit,
34 | relationship
35 | });
36 | });
37 | });
38 |
39 | module.exports = router;
40 |
--------------------------------------------------------------------------------
/server/routes/servicesApi.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 express = require('express');
18 |
19 | const handleResponsePromise = require('./utils/apiResponseHandler').handleResponsePromise;
20 | const servicesConnector = require('../connectors/services/servicesConnector');
21 |
22 | const router = express.Router();
23 |
24 | router.get('/services', (req, res, next) => {
25 | handleResponsePromise(res, next, 'services')(
26 | () => servicesConnector.getServices()
27 | );
28 | });
29 |
30 | router.get('/operations', (req, res, next) => {
31 | handleResponsePromise(res, next, 'operations')(
32 | () => servicesConnector.getOperations(req.query.serviceName)
33 | );
34 | });
35 |
36 | module.exports = router;
37 |
--------------------------------------------------------------------------------
/server/routes/servicesPerfApi.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 express = require('express');
18 |
19 | const config = require('../config/config');
20 | const handleResponsePromise = require('./utils/apiResponseHandler').handleResponsePromise;
21 |
22 | const trendsConnector = require(`../connectors/trends/${config.connectors.trends.connectorName}/trendsConnector`); // eslint-disable-line import/no-dynamic-require
23 |
24 | const router = express.Router();
25 |
26 | router.get('/servicePerf', (req, res, next) => {
27 | const {
28 | granularity,
29 | from,
30 | until
31 | } = req.query;
32 | handleResponsePromise(res, next, 'servicePerf')(
33 | () => trendsConnector.getServicePerfStats(granularity, from, until)
34 | );
35 | });
36 |
37 | module.exports = router;
38 |
--------------------------------------------------------------------------------
/server/routes/sso.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 express = require('express');
18 | const authenticator = require('../sso/samlSsoAuthenticator').authenticator;
19 | const logger = require('../utils/logger').withIdentifier('sso');
20 |
21 | const router = express.Router();
22 |
23 | const extractFullRedirectUrl = req => req.originalUrl.split('/sso/saml/consume?redirectUrl=').pop();
24 |
25 | router.use('/saml/consume', authenticator.authenticate('saml'),
26 | (req, res) => {
27 | const redirectUrl = extractFullRedirectUrl(req);
28 | logger.info(`action=authentication, status=success, redirectUrl=${redirectUrl}`);
29 | res.redirect(redirectUrl);
30 | });
31 |
32 | module.exports = router;
33 |
--------------------------------------------------------------------------------
/server/routes/user.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 express = require('express');
18 |
19 | const router = express.Router();
20 |
21 | router.get('/details', (req, res) => {
22 | res.type('application/json').send(req.user);
23 | });
24 |
25 | module.exports = router;
26 |
--------------------------------------------------------------------------------
/server/routes/utils/apiResponseHandler.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 metrics = require('../../utils/metrics');
18 |
19 | const responseHandler = {};
20 |
21 | responseHandler.handleResponsePromise = (response, next, pathName) => (operation) => {
22 | const timer = metrics.timer(`http_rq_${pathName}`).start();
23 |
24 | operation()
25 | .then(
26 | (result) => response.json(result),
27 | (err) => {
28 | metrics.meter(`http_rq_${pathName}_failed`).mark();
29 | next(err);
30 | }
31 | )
32 | .fin(() => timer.end())
33 | .done();
34 | };
35 |
36 | module.exports = responseHandler;
37 |
--------------------------------------------------------------------------------
/server/sso/authChecker.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 | function authChecker(errorHandler) {
18 | return (req, res, next) => {
19 | if (req.user) {
20 | next();
21 | } else {
22 | errorHandler(res, req.originalUrl);
23 | }
24 | };
25 | }
26 |
27 | module.exports = {
28 | forPage: authChecker((res, redirectUrl) => { res.redirect(`/login?redirectUrl=${redirectUrl}`); }),
29 | forApi: authChecker((res) => { res.status(401).send('UNAUTHORIZED'); })
30 | };
31 |
--------------------------------------------------------------------------------
/server/start.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | const app = require('./app');
19 | const config = require('./config/config');
20 | const Server = require('./utils/server');
21 |
22 | const server = new Server(app);
23 |
24 | if (config.cluster) {
25 | server.startInClusterMode();
26 | } else {
27 | server.startInStandaloneMode();
28 | }
29 |
--------------------------------------------------------------------------------
/server/utils/metrics.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 measured = require('measured');
18 |
19 | module.exports = measured.createCollection();
20 |
--------------------------------------------------------------------------------
/server/utils/metricsMiddleware.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 onFinished = require('finished');
18 | const metrics = require('./metrics');
19 |
20 | const middleware = {};
21 |
22 | middleware.httpMetrics = (req, res, next) => {
23 | onFinished(res, () => {
24 | metrics.meter(`http_${res.statusCode}`).mark();
25 | });
26 |
27 | next();
28 | };
29 |
30 | module.exports = middleware;
31 |
--------------------------------------------------------------------------------
/server/utils/metricsReporter.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 flatten = require('flat');
18 | const metrics = require('./metrics');
19 | const logger = require('./logger').withIdentifier('metrics');
20 |
21 | const reporter = {};
22 |
23 | reporter.start = (host, port, prefix, interval) => {
24 | setInterval(() => {
25 | const flattenedMetrics = flatten(metrics.toJSON());
26 |
27 | // report to logs
28 | logger.info(prefix);
29 | logger.info(JSON.stringify(flattenedMetrics));
30 | }, interval);
31 | };
32 |
33 | module.exports = reporter;
34 |
--------------------------------------------------------------------------------
/src/app.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | import React from 'react';
19 | import ReactDOM from 'react-dom';
20 | import {Route, BrowserRouter as Router} from 'react-router-dom';
21 | import Main from './main';
22 | import storesInitializer from './stores/storesInitializer';
23 | import withTracker from './components/common/withTracker';
24 |
25 | // app initializers
26 | storesInitializer.init();
27 |
28 | // mount react components
29 | ReactDOM.render(
30 |
31 |
32 |
33 | , document.getElementById('root')
34 | );
35 |
--------------------------------------------------------------------------------
/src/bootstrap/LICENSE_BOOTSTRAP:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2011-2016 Twitter, Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/bootstrap/LICENSE_BOOTSWATCH:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 Thomas Park
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/bootstrap/alerts.less:
--------------------------------------------------------------------------------
1 | //
2 | // Alerts
3 | // --------------------------------------------------
4 |
5 |
6 | // Base styles
7 | // -------------------------
8 |
9 | .alert {
10 | padding: @alert-padding;
11 | margin-bottom: @line-height-computed;
12 | border: 1px solid transparent;
13 | border-radius: @alert-border-radius;
14 |
15 | // Headings for larger alerts
16 | h4 {
17 | margin-top: 0;
18 | // Specified for the h4 to prevent conflicts of changing @headings-color
19 | color: inherit;
20 | }
21 |
22 | // Provide class for links that match alerts
23 | .alert-link {
24 | font-weight: @alert-link-font-weight;
25 | }
26 |
27 | // Improve alignment and spacing of inner content
28 | > p,
29 | > ul {
30 | margin-bottom: 0;
31 | }
32 |
33 | > p + p {
34 | margin-top: 5px;
35 | }
36 | }
37 |
38 | // Dismissible alerts
39 | //
40 | // Expand the right padding and account for the close button's positioning.
41 |
42 | .alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0.
43 | .alert-dismissible {
44 | padding-right: (@alert-padding + 20);
45 |
46 | // Adjust close link position
47 | .close {
48 | position: relative;
49 | top: -2px;
50 | right: -21px;
51 | color: inherit;
52 | }
53 | }
54 |
55 | // Alternate styles
56 | //
57 | // Generate contextual modifier classes for colorizing the alert.
58 |
59 | .alert-success {
60 | .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);
61 | }
62 |
63 | .alert-info {
64 | .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);
65 | }
66 |
67 | .alert-warning {
68 | .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);
69 | }
70 |
71 | .alert-danger {
72 | .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);
73 | }
74 |
--------------------------------------------------------------------------------
/src/bootstrap/badges.less:
--------------------------------------------------------------------------------
1 | //
2 | // Badges
3 | // --------------------------------------------------
4 |
5 |
6 | // Base class
7 | .badge {
8 | display: inline-block;
9 | min-width: 10px;
10 | padding: 3px 7px;
11 | font-size: @font-size-small;
12 | font-weight: @badge-font-weight;
13 | color: @badge-color;
14 | line-height: @badge-line-height;
15 | vertical-align: middle;
16 | white-space: nowrap;
17 | text-align: center;
18 | background-color: @badge-bg;
19 | border-radius: @badge-border-radius;
20 |
21 | // Empty badges collapse automatically (not available in IE8)
22 | &:empty {
23 | display: none;
24 | }
25 |
26 | // Quick fix for badges in buttons
27 | .btn & {
28 | position: relative;
29 | top: -1px;
30 | }
31 |
32 | .btn-xs &,
33 | .btn-group-xs > .btn & {
34 | top: 0;
35 | padding: 1px 5px;
36 | }
37 |
38 | // Hover state, but only for links
39 | a& {
40 | &:hover,
41 | &:focus {
42 | color: @badge-link-hover-color;
43 | text-decoration: none;
44 | cursor: pointer;
45 | }
46 | }
47 |
48 | // Account for badges in navs
49 | .list-group-item.active > &,
50 | .nav-pills > .active > a > & {
51 | color: @badge-active-color;
52 | background-color: @badge-active-bg;
53 | }
54 |
55 | .list-group-item > & {
56 | float: right;
57 | }
58 |
59 | .list-group-item > & + & {
60 | margin-right: 5px;
61 | }
62 |
63 | .nav-pills > li > a > & {
64 | margin-left: 3px;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/bootstrap/bootstrap.less:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap v3.3.7 (http://getbootstrap.com)
3 | * Copyright 2011-2016 Twitter, Inc.
4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5 | */
6 |
7 | // Core variables and mixins
8 | @import 'variables.less';
9 | @import 'mixins.less';
10 |
11 | // Reset and dependencies
12 | @import 'normalize.less';
13 | @import 'print.less';
14 | @import 'themify-icons.less';
15 | @import 'titillium-web.less';
16 |
17 | // Core CSS
18 | @import 'scaffolding.less';
19 | @import 'type.less';
20 | @import 'code.less';
21 | @import 'grid.less';
22 | @import 'tables.less';
23 | @import 'forms.less';
24 | @import 'buttons.less';
25 |
26 | // Components
27 | @import 'component-animations.less';
28 | @import 'dropdowns.less';
29 | @import 'button-groups.less';
30 | @import 'input-groups.less';
31 | @import 'navs.less';
32 | @import 'navbar.less';
33 | //@import "breadcrumbs.less";
34 | @import 'pagination.less';
35 | @import 'pager.less';
36 | @import 'labels.less';
37 | @import 'badges.less';
38 | @import 'jumbotron.less';
39 | //@import "thumbnails.less";
40 | //@import "alerts.less";
41 | //@import "progress-bars.less";
42 | //@import "media.less";
43 | @import 'list-group.less';
44 | //@import "panels.less";
45 | //@import "responsive-embed.less";
46 | @import 'wells.less';
47 | @import 'close.less';
48 |
49 | // Components w/ JavaScript
50 | @import 'modals.less';
51 | @import 'tooltip.less';
52 | //@import "popovers.less";
53 | //@import "carousel.less";
54 |
55 | // Utility classes
56 | @import 'utilities.less';
57 | @import 'responsive-utilities.less';
58 |
59 | // custom colors
60 | @import 'svc-colors.less';
61 |
62 | // Theme override
63 | @import 'bootswatch.less';
64 |
--------------------------------------------------------------------------------
/src/bootstrap/breadcrumbs.less:
--------------------------------------------------------------------------------
1 | //
2 | // Breadcrumbs
3 | // --------------------------------------------------
4 |
5 |
6 | .breadcrumb {
7 | padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;
8 | margin-bottom: @line-height-computed;
9 | list-style: none;
10 | background-color: @breadcrumb-bg;
11 | border-radius: @border-radius-base;
12 |
13 | > li {
14 | display: inline-block;
15 |
16 | + li:before {
17 | content: "@{breadcrumb-separator}\00a0"; // Unicode space added since inline-block means non-collapsing white-space
18 | padding: 0 5px;
19 | color: @breadcrumb-color;
20 | }
21 | }
22 |
23 | > .active {
24 | color: @breadcrumb-active-color;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/bootstrap/close.less:
--------------------------------------------------------------------------------
1 | //
2 | // Close icons
3 | // --------------------------------------------------
4 |
5 |
6 | .close {
7 | float: right;
8 | font-size: (@font-size-base * 1.5);
9 | font-weight: @close-font-weight;
10 | line-height: 1;
11 | color: @close-color;
12 | text-shadow: @close-text-shadow;
13 | .opacity(.2);
14 |
15 | &:hover,
16 | &:focus {
17 | color: @close-color;
18 | text-decoration: none;
19 | cursor: pointer;
20 | .opacity(.5);
21 | }
22 |
23 | // Additional properties for button version
24 | // iOS requires the button element instead of an anchor tag.
25 | // If you want the anchor version, it requires `href="#"`.
26 | // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile
27 | button& {
28 | padding: 0;
29 | cursor: pointer;
30 | background: transparent;
31 | border: 0;
32 | -webkit-appearance: none;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/bootstrap/code.less:
--------------------------------------------------------------------------------
1 | //
2 | // Code (inline and block)
3 | // --------------------------------------------------
4 |
5 |
6 | // Inline and block code styles
7 | code,
8 | kbd,
9 | pre,
10 | samp {
11 | font-family: @font-family-monospace;
12 | }
13 |
14 | // Inline code
15 | code {
16 | padding: 2px 4px;
17 | font-size: 90%;
18 | color: @code-color;
19 | background-color: @code-bg;
20 | border-radius: @border-radius-base;
21 | }
22 |
23 | // User input typically entered via keyboard
24 | kbd {
25 | padding: 2px 4px;
26 | font-size: 90%;
27 | color: @kbd-color;
28 | background-color: @kbd-bg;
29 | border-radius: @border-radius-small;
30 | box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);
31 |
32 | kbd {
33 | padding: 0;
34 | font-size: 100%;
35 | font-weight: bold;
36 | box-shadow: none;
37 | }
38 | }
39 |
40 | // Blocks of code
41 | pre {
42 | display: block;
43 | padding: ((@line-height-computed - 1) / 2);
44 | margin: 0 0 (@line-height-computed / 2);
45 | font-size: (@font-size-base - 1); // 14px to 13px
46 | line-height: @line-height-base;
47 | word-break: break-all;
48 | word-wrap: break-word;
49 | color: @pre-color;
50 | background-color: @pre-bg;
51 | border: 1px solid @pre-border-color;
52 | border-radius: @border-radius-base;
53 |
54 | // Account for some code outputs that place code tags in pre tags
55 | code {
56 | padding: 0;
57 | font-size: inherit;
58 | color: inherit;
59 | white-space: pre-wrap;
60 | background-color: transparent;
61 | border-radius: 0;
62 | }
63 | }
64 |
65 | // Enable scrollable blocks of code
66 | .pre-scrollable {
67 | max-height: @pre-scrollable-max-height;
68 | overflow-y: scroll;
69 | }
70 |
--------------------------------------------------------------------------------
/src/bootstrap/component-animations.less:
--------------------------------------------------------------------------------
1 | //
2 | // Component animations
3 | // --------------------------------------------------
4 |
5 | // Heads up!
6 | //
7 | // We don't use the `.opacity()` mixin here since it causes a bug with text
8 | // fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552.
9 |
10 | .fade {
11 | opacity: 0;
12 | .transition(opacity .15s linear);
13 | &.in {
14 | opacity: 1;
15 | }
16 | }
17 |
18 | .collapse {
19 | display: none;
20 |
21 | &.in { display: block; }
22 | tr&.in { display: table-row; }
23 | tbody&.in { display: table-row-group; }
24 | }
25 |
26 | .collapsing {
27 | position: relative;
28 | height: 0;
29 | overflow: hidden;
30 | .transition-property(~"height, visibility");
31 | .transition-duration(.35s);
32 | .transition-timing-function(ease);
33 | }
34 |
--------------------------------------------------------------------------------
/src/bootstrap/grid.less:
--------------------------------------------------------------------------------
1 | //
2 | // Grid system
3 | // --------------------------------------------------
4 |
5 |
6 | // Container widths
7 | //
8 | // Set the container width, and override it for fixed navbars in media queries.
9 |
10 | .container {
11 | .container-fixed();
12 |
13 | @media (min-width: @screen-sm-min) {
14 | width: @container-sm;
15 | }
16 | @media (min-width: @screen-md-min) {
17 | width: @container-md;
18 | }
19 | @media (min-width: @screen-lg-min) {
20 | width: @container-lg;
21 | }
22 | }
23 |
24 |
25 | // Fluid container
26 | //
27 | // Utilizes the mixin meant for fixed width containers, but without any defined
28 | // width for fluid, full width layouts.
29 |
30 | .container-fluid {
31 | .container-fixed();
32 | }
33 |
34 |
35 | // Row
36 | //
37 | // Rows contain and clear the floats of your columns.
38 |
39 | .row {
40 | .make-row();
41 | }
42 |
43 |
44 | // Columns
45 | //
46 | // Common styles for small and large grid columns
47 |
48 | .make-grid-columns();
49 |
50 |
51 | // Extra small grid
52 | //
53 | // Columns, offsets, pushes, and pulls for extra small devices like
54 | // smartphones.
55 |
56 | .make-grid(xs);
57 |
58 |
59 | // Small grid
60 | //
61 | // Columns, offsets, pushes, and pulls for the small device range, from phones
62 | // to tablets.
63 |
64 | @media (min-width: @screen-sm-min) {
65 | .make-grid(sm);
66 | }
67 |
68 |
69 | // Medium grid
70 | //
71 | // Columns, offsets, pushes, and pulls for the desktop device range.
72 |
73 | @media (min-width: @screen-md-min) {
74 | .make-grid(md);
75 | }
76 |
77 |
78 | // Large grid
79 | //
80 | // Columns, offsets, pushes, and pulls for the large desktop device range.
81 |
82 | @media (min-width: @screen-lg-min) {
83 | .make-grid(lg);
84 | }
85 |
--------------------------------------------------------------------------------
/src/bootstrap/jumbotron.less:
--------------------------------------------------------------------------------
1 | //
2 | // Jumbotron
3 | // --------------------------------------------------
4 |
5 |
6 | .jumbotron {
7 | padding-top: @jumbotron-padding;
8 | padding-bottom: @jumbotron-padding;
9 | margin-bottom: @jumbotron-padding;
10 | color: @jumbotron-color;
11 | background-color: @jumbotron-bg;
12 |
13 | h1,
14 | .h1 {
15 | color: @jumbotron-heading-color;
16 | }
17 |
18 | p {
19 | margin-bottom: (@jumbotron-padding / 2);
20 | font-size: @jumbotron-font-size;
21 | color: #fff;
22 | }
23 |
24 | > hr {
25 | border-top-color: darken(@jumbotron-bg, 10%);
26 | }
27 |
28 | .container &,
29 | .container-fluid & {
30 | border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container
31 | padding-left: (@grid-gutter-width / 2);
32 | padding-right: (@grid-gutter-width / 2);
33 | }
34 |
35 | .container {
36 | max-width: 100%;
37 | }
38 |
39 | @media screen and (min-width: @screen-sm-min) {
40 | padding-top: (@jumbotron-padding * 1.6);
41 | padding-bottom: (@jumbotron-padding * 1.6);
42 |
43 | .container &,
44 | .container-fluid & {
45 | padding-left: (@jumbotron-padding * 2);
46 | padding-right: (@jumbotron-padding * 2);
47 | }
48 |
49 | h1,
50 | .h1 {
51 | font-size: @jumbotron-heading-font-size;
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/bootstrap/labels.less:
--------------------------------------------------------------------------------
1 | //
2 | // Labels
3 | // --------------------------------------------------
4 |
5 | .label {
6 | display: inline;
7 | padding: .2em .6em .3em;
8 | font-size: 75%;
9 | font-weight: bold;
10 | line-height: 1;
11 | color: @label-color;
12 | text-align: center;
13 | white-space: nowrap;
14 | vertical-align: baseline;
15 | border-radius: .25em;
16 |
17 | // Add hover effects, but only for links
18 | a& {
19 | &:hover,
20 | &:focus {
21 | color: @label-link-hover-color;
22 | text-decoration: none;
23 | cursor: pointer;
24 | }
25 | }
26 |
27 | // Empty labels collapse automatically (not available in IE8)
28 | &:empty {
29 | display: none;
30 | }
31 |
32 | // Quick fix for labels in buttons
33 | .btn & {
34 | position: relative;
35 | top: -1px;
36 | }
37 | }
38 |
39 | // Colors
40 | // Contextual variations (linked labels get darker on :hover)
41 |
42 | .label-default {
43 | .label-variant(@label-default-bg);
44 | }
45 |
46 | .label-primary {
47 | .label-variant(@label-primary-bg);
48 | }
49 |
50 | .label-success {
51 | .label-variant(@label-success-bg);
52 | }
53 |
54 | .label-info {
55 | .label-variant(@label-info-bg);
56 | }
57 |
58 | .label-warning {
59 | .label-variant(@label-warning-bg);
60 | }
61 |
62 | .label-danger {
63 | .label-variant(@label-danger-bg);
64 | }
65 |
--------------------------------------------------------------------------------
/src/bootstrap/media.less:
--------------------------------------------------------------------------------
1 | .media {
2 | // Proper spacing between instances of .media
3 | margin-top: 15px;
4 |
5 | &:first-child {
6 | margin-top: 0;
7 | }
8 | }
9 |
10 | .media,
11 | .media-body {
12 | zoom: 1;
13 | overflow: hidden;
14 | }
15 |
16 | .media-body {
17 | width: 10000px;
18 | }
19 |
20 | .media-object {
21 | display: block;
22 |
23 | // Fix collapse in webkit from max-width: 100% and display: table-cell.
24 | &.img-thumbnail {
25 | max-width: none;
26 | }
27 | }
28 |
29 | .media-right,
30 | .media > .pull-right {
31 | padding-left: 10px;
32 | }
33 |
34 | .media-left,
35 | .media > .pull-left {
36 | padding-right: 10px;
37 | }
38 |
39 | .media-left,
40 | .media-right,
41 | .media-body {
42 | display: table-cell;
43 | vertical-align: top;
44 | }
45 |
46 | .media-middle {
47 | vertical-align: middle;
48 | }
49 |
50 | .media-bottom {
51 | vertical-align: bottom;
52 | }
53 |
54 | // Reset margins on headings for tighter default spacing
55 | .media-heading {
56 | margin-top: 0;
57 | margin-bottom: 5px;
58 | }
59 |
60 | // Media list variation
61 | //
62 | // Undo default ul/ol styles
63 | .media-list {
64 | padding-left: 0;
65 | list-style: none;
66 | }
67 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins.less:
--------------------------------------------------------------------------------
1 | // Mixins
2 | // --------------------------------------------------
3 |
4 | // Utilities
5 | @import "mixins/hide-text.less";
6 | @import "mixins/opacity.less";
7 | @import "mixins/image.less";
8 | @import "mixins/labels.less";
9 | @import "mixins/reset-filter.less";
10 | @import "mixins/resize.less";
11 | @import "mixins/responsive-visibility.less";
12 | @import "mixins/size.less";
13 | @import "mixins/tab-focus.less";
14 | @import "mixins/reset-text.less";
15 | @import "mixins/text-emphasis.less";
16 | @import "mixins/text-overflow.less";
17 | @import "mixins/vendor-prefixes.less";
18 |
19 | // Components
20 | @import "mixins/alerts.less";
21 | @import "mixins/buttons.less";
22 | @import "mixins/panels.less";
23 | @import "mixins/pagination.less";
24 | @import "mixins/list-group.less";
25 | @import "mixins/nav-divider.less";
26 | @import "mixins/forms.less";
27 | @import "mixins/progress-bar.less";
28 | @import "mixins/table-row.less";
29 |
30 | // Skins
31 | @import "mixins/background-variant.less";
32 | @import "mixins/border-radius.less";
33 | @import "mixins/gradients.less";
34 |
35 | // PageLayout
36 | @import "mixins/clearfix.less";
37 | @import "mixins/center-block.less";
38 | @import "mixins/nav-vertical-align.less";
39 | @import "mixins/grid-framework.less";
40 | @import "mixins/grid.less";
41 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins/alerts.less:
--------------------------------------------------------------------------------
1 | // Alerts
2 |
3 | .alert-variant(@background; @border; @text-color) {
4 | background-color: @background;
5 | border-color: @border;
6 | color: @text-color;
7 |
8 | hr {
9 | border-top-color: darken(@border, 5%);
10 | }
11 | .alert-link {
12 | color: darken(@text-color, 10%);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins/background-variant.less:
--------------------------------------------------------------------------------
1 | // Contextual backgrounds
2 |
3 | .bg-variant(@color) {
4 | background-color: @color;
5 | a&:hover,
6 | a&:focus {
7 | background-color: darken(@color, 10%);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins/border-radius.less:
--------------------------------------------------------------------------------
1 | // Single side border-radius
2 |
3 | .border-top-radius(@radius) {
4 | border-top-right-radius: @radius;
5 | border-top-left-radius: @radius;
6 | }
7 | .border-right-radius(@radius) {
8 | border-bottom-right-radius: @radius;
9 | border-top-right-radius: @radius;
10 | }
11 | .border-bottom-radius(@radius) {
12 | border-bottom-right-radius: @radius;
13 | border-bottom-left-radius: @radius;
14 | }
15 | .border-left-radius(@radius) {
16 | border-bottom-left-radius: @radius;
17 | border-top-left-radius: @radius;
18 | }
19 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins/buttons.less:
--------------------------------------------------------------------------------
1 | // Button variants
2 | //
3 | // Easily pump out default styles, as well as :hover, :focus, :active,
4 | // and disabled options for all buttons
5 |
6 | .button-variant(@color; @background; @border) {
7 | color: @color;
8 | background-color: @background;
9 | border-color: @border;
10 |
11 | &:focus,
12 | &.focus {
13 | color: @color;
14 | background-color: darken(@background, 10%);
15 | border-color: darken(@border, 25%);
16 | }
17 | &:hover {
18 | color: @color;
19 | background-color: darken(@background, 10%);
20 | border-color: darken(@border, 12%);
21 | }
22 | &:active,
23 | &.active,
24 | .open > .dropdown-toggle& {
25 | color: @color;
26 | background-color: darken(@background, 10%);
27 | border-color: darken(@border, 12%);
28 |
29 | &:hover,
30 | &:focus,
31 | &.focus {
32 | color: @color;
33 | background-color: darken(@background, 17%);
34 | border-color: darken(@border, 25%);
35 | }
36 | }
37 | &:active,
38 | &.active,
39 | .open > .dropdown-toggle& {
40 | background-image: none;
41 | }
42 | &.disabled,
43 | &[disabled],
44 | fieldset[disabled] & {
45 | &:hover,
46 | &:focus,
47 | &.focus {
48 | background-color: @background;
49 | border-color: @border;
50 | }
51 | }
52 |
53 | .badge {
54 | color: @background;
55 | background-color: @color;
56 | }
57 | }
58 |
59 | // Button sizes
60 | .button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {
61 | padding: @padding-vertical @padding-horizontal;
62 | font-size: @font-size;
63 | line-height: @line-height;
64 | border-radius: @border-radius;
65 | }
66 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins/center-block.less:
--------------------------------------------------------------------------------
1 | // Center-align a block level element
2 |
3 | .center-block() {
4 | display: block;
5 | margin-left: auto;
6 | margin-right: auto;
7 | }
8 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins/clearfix.less:
--------------------------------------------------------------------------------
1 | // Clearfix
2 | //
3 | // For modern browsers
4 | // 1. The space content is one way to avoid an Opera bug when the
5 | // contenteditable attribute is included anywhere else in the document.
6 | // Otherwise it causes space to appear at the top and bottom of elements
7 | // that are clearfixed.
8 | // 2. The use of `table` rather than `block` is only necessary if using
9 | // `:before` to contain the top-margins of child elements.
10 | //
11 | // Source: http://nicolasgallagher.com/micro-clearfix-hack/
12 |
13 | .clearfix() {
14 | &:before,
15 | &:after {
16 | content: ' '; // 1
17 | display: table; // 2
18 | }
19 | &:after {
20 | clear: both;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins/hide-text.less:
--------------------------------------------------------------------------------
1 | // CSS image replacement
2 | //
3 | // Heads up! v3 launched with only `.hide-text()`, but per our pattern for
4 | // mixins being reused as classes with the same name, this doesn't hold up. As
5 | // of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`.
6 | //
7 | // Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757
8 |
9 | // Deprecated as of v3.0.1 (has been removed in v4)
10 | .hide-text() {
11 | font: ~'0/0' a;
12 | color: transparent;
13 | text-shadow: none;
14 | background-color: transparent;
15 | border: 0;
16 | }
17 |
18 | // New mixin to use as of v3.0.1
19 | .text-hide() {
20 | .hide-text();
21 | }
22 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins/image.less:
--------------------------------------------------------------------------------
1 | // Image Mixins
2 | // - Responsive image
3 | // - Retina image
4 |
5 | // Responsive image
6 | //
7 | // Keep images from scaling beyond the width of their parents.
8 | .img-responsive(@display: block) {
9 | display: @display;
10 | max-width: 100%; // Part 1: Set a maximum relative to the parent
11 | height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching
12 | }
13 |
14 | // Retina image
15 | //
16 | // Short retina mixin for setting background-image and -size. Note that the
17 | // spelling of `min--moz-device-pixel-ratio` is intentional.
18 | .img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {
19 | background-image: url('@{file-1x}');
20 |
21 | @media only screen and (-webkit-min-device-pixel-ratio: 2),
22 | only screen and (min--moz-device-pixel-ratio: 2),
23 | only screen and (-o-min-device-pixel-ratio: 2/1),
24 | only screen and (min-device-pixel-ratio: 2),
25 | only screen and (min-resolution: 192dpi),
26 | only screen and (min-resolution: 2dppx) {
27 | background-image: url('@{file-2x}');
28 | background-size: @width-1x @height-1x;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins/labels.less:
--------------------------------------------------------------------------------
1 | // Labels
2 |
3 | .label-variant(@color) {
4 | background-color: @color;
5 |
6 | &[href] {
7 | &:hover,
8 | &:focus {
9 | background-color: darken(@color, 10%);
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins/list-group.less:
--------------------------------------------------------------------------------
1 | // List Groups
2 |
3 | .list-group-item-variant(@state; @background; @color) {
4 | .list-group-item-@{state} {
5 | color: @color;
6 | background-color: @background;
7 |
8 | a&,
9 | button& {
10 | color: @color;
11 |
12 | .list-group-item-heading {
13 | color: inherit;
14 | }
15 |
16 | &:hover,
17 | &:focus {
18 | color: @color;
19 | background-color: darken(@background, 5%);
20 | }
21 | &.active,
22 | &.active:hover,
23 | &.active:focus {
24 | color: #fff;
25 | background-color: @color;
26 | border-color: @color;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins/nav-divider.less:
--------------------------------------------------------------------------------
1 | // Horizontal dividers
2 | //
3 | // Dividers (basically an hr) within dropdowns and nav lists
4 |
5 | .nav-divider(@color: #e5e5e5) {
6 | height: 1px;
7 | margin: ((@line-height-computed / 2) - 1) 0;
8 | overflow: hidden;
9 | background-color: @color;
10 | }
11 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins/nav-vertical-align.less:
--------------------------------------------------------------------------------
1 | // Navbar vertical align
2 | //
3 | // Vertically center elements in the navbar.
4 | // Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.
5 |
6 | .navbar-vertical-align(@element-height) {
7 | margin-top: ((@navbar-height - @element-height) / 2);
8 | margin-bottom: ((@navbar-height - @element-height) / 2);
9 | }
10 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins/opacity.less:
--------------------------------------------------------------------------------
1 | // Opacity
2 |
3 | .opacity(@opacity) {
4 | opacity: @opacity;
5 | // IE8 filter
6 | @opacity-ie: (@opacity * 100);
7 | filter: ~'alpha(opacity=@{opacity-ie})';
8 | }
9 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins/pagination.less:
--------------------------------------------------------------------------------
1 | // Pagination
2 |
3 | .pagination-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {
4 | > li {
5 | > a,
6 | > span {
7 | padding: @padding-vertical @padding-horizontal;
8 | font-size: @font-size;
9 | line-height: @line-height;
10 | }
11 | &:first-child {
12 | > a,
13 | > span {
14 | .border-left-radius(@border-radius);
15 | }
16 | }
17 | &:last-child {
18 | > a,
19 | > span {
20 | .border-right-radius(@border-radius);
21 | }
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins/panels.less:
--------------------------------------------------------------------------------
1 | // Panels
2 |
3 | .panel-variant(@border; @heading-text-color; @heading-bg-color; @heading-border) {
4 | border-color: @border;
5 |
6 | & > .panel-heading {
7 | color: @heading-text-color;
8 | background-color: @heading-bg-color;
9 | border-color: @heading-border;
10 |
11 | + .panel-collapse > .panel-body {
12 | border-top-color: @border;
13 | }
14 | .badge {
15 | color: @heading-bg-color;
16 | background-color: @heading-text-color;
17 | }
18 | }
19 | & > .panel-footer {
20 | + .panel-collapse > .panel-body {
21 | border-bottom-color: @border;
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins/progress-bar.less:
--------------------------------------------------------------------------------
1 | // Progress bars
2 |
3 | .progress-bar-variant(@color) {
4 | background-color: @color;
5 |
6 | // Deprecated parent class requirement as of v3.2.0
7 | .progress-striped & {
8 | #gradient > .striped();
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins/reset-filter.less:
--------------------------------------------------------------------------------
1 | // Reset filters for IE
2 | //
3 | // When you need to remove a gradient background, do not forget to use this to reset
4 | // the IE filter for IE9 and below.
5 |
6 | .reset-filter() {
7 | filter: e(%('progid:DXImageTransform.Microsoft.gradient(enabled = false)'));
8 | }
9 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins/reset-text.less:
--------------------------------------------------------------------------------
1 | .reset-text() {
2 | font-family: @font-family-base;
3 | // We deliberately do NOT reset font-size.
4 | font-style: normal;
5 | font-weight: normal;
6 | letter-spacing: normal;
7 | line-break: auto;
8 | line-height: @line-height-base;
9 | text-align: left; // Fallback for where `start` is not supported
10 | text-align: start;
11 | text-decoration: none;
12 | text-shadow: none;
13 | text-transform: none;
14 | white-space: normal;
15 | word-break: normal;
16 | word-spacing: normal;
17 | word-wrap: normal;
18 | }
19 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins/resize.less:
--------------------------------------------------------------------------------
1 | // Resize anything
2 |
3 | .resizable(@direction) {
4 | resize: @direction; // Options: horizontal, vertical, both
5 | overflow: auto; // Per CSS3 UI, `resize` only applies when `overflow` isn't `visible`
6 | }
7 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins/responsive-visibility.less:
--------------------------------------------------------------------------------
1 | // Responsive utilities
2 |
3 | //
4 | // More easily include all the states for responsive-utilities.less.
5 | .responsive-visibility() {
6 | display: block !important;
7 | table& {
8 | display: table !important;
9 | }
10 | tr& {
11 | display: table-row !important;
12 | }
13 | th&,
14 | td& {
15 | display: table-cell !important;
16 | }
17 | }
18 |
19 | .responsive-invisibility() {
20 | display: none !important;
21 | }
22 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins/size.less:
--------------------------------------------------------------------------------
1 | // Sizing shortcuts
2 |
3 | .size(@width; @height) {
4 | width: @width;
5 | height: @height;
6 | }
7 |
8 | .square(@size) {
9 | .size(@size; @size);
10 | }
11 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins/tab-focus.less:
--------------------------------------------------------------------------------
1 | // WebKit-style focus
2 |
3 | .tab-focus() {
4 | // WebKit-specific. Other browsers will keep their default outline style.
5 | // (Initially tried to also force default via `outline: initial`,
6 | // but that seems to erroneously remove the outline in Firefox altogether.)
7 | outline: 5px auto -webkit-focus-ring-color;
8 | outline-offset: -2px;
9 | }
10 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins/table-row.less:
--------------------------------------------------------------------------------
1 | // Tables
2 |
3 | .table-row-variant(@state; @background) {
4 | // Exact selectors below required to override `.table-striped` and prevent
5 | // inheritance to nested tables.
6 | .table > thead > tr,
7 | .table > tbody > tr,
8 | .table > tfoot > tr {
9 | > td.@{state},
10 | > th.@{state},
11 | &.@{state} > td,
12 | &.@{state} > th {
13 | background-color: @background;
14 | }
15 | }
16 |
17 | // Hover states for `.table-hover`
18 | // Note: this is not available for cells or rows within `thead` or `tfoot`.
19 | .table-hover > tbody > tr {
20 | > td.@{state}:hover,
21 | > th.@{state}:hover,
22 | &.@{state}:hover > td,
23 | &:hover > .@{state},
24 | &.@{state}:hover > th {
25 | background-color: darken(@background, 5%);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins/text-emphasis.less:
--------------------------------------------------------------------------------
1 | // Typography
2 |
3 | .text-emphasis-variant(@color) {
4 | color: @color;
5 | a&:hover,
6 | a&:focus {
7 | color: darken(@color, 10%);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/bootstrap/mixins/text-overflow.less:
--------------------------------------------------------------------------------
1 | // Text overflow
2 | // Requires inline-block or block for proper styling
3 |
4 | .text-overflow() {
5 | overflow: hidden;
6 | text-overflow: ellipsis;
7 | white-space: nowrap;
8 | }
9 |
--------------------------------------------------------------------------------
/src/bootstrap/pager.less:
--------------------------------------------------------------------------------
1 | //
2 | // Pager pagination
3 | // --------------------------------------------------
4 |
5 |
6 | .pager {
7 | padding-left: 0;
8 | margin: @line-height-computed 0;
9 | list-style: none;
10 | text-align: center;
11 | &:extend(.clearfix all);
12 | li {
13 | display: inline;
14 | > a,
15 | > span {
16 | display: inline-block;
17 | padding: 5px 14px;
18 | background-color: @pager-bg;
19 | border: 1px solid @pager-border;
20 | border-radius: @pager-border-radius;
21 | }
22 |
23 | > a:hover,
24 | > a:focus {
25 | text-decoration: none;
26 | background-color: @pager-hover-bg;
27 | }
28 | }
29 |
30 | .next {
31 | > a,
32 | > span {
33 | float: right;
34 | }
35 | }
36 |
37 | .previous {
38 | > a,
39 | > span {
40 | float: left;
41 | }
42 | }
43 |
44 | .disabled {
45 | > a,
46 | > a:hover,
47 | > a:focus,
48 | > span {
49 | color: @pager-disabled-color;
50 | background-color: @pager-bg;
51 | cursor: @cursor-disabled;
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/bootstrap/responsive-embed.less:
--------------------------------------------------------------------------------
1 | // Embeds responsive
2 | //
3 | // Credit: Nicolas Gallagher and SUIT CSS.
4 |
5 | .embed-responsive {
6 | position: relative;
7 | display: block;
8 | height: 0;
9 | padding: 0;
10 | overflow: hidden;
11 |
12 | .embed-responsive-item,
13 | iframe,
14 | embed,
15 | object,
16 | video {
17 | position: absolute;
18 | top: 0;
19 | left: 0;
20 | bottom: 0;
21 | height: 100%;
22 | width: 100%;
23 | border: 0;
24 | }
25 | }
26 |
27 | // Modifier class for 16:9 aspect ratio
28 | .embed-responsive-16by9 {
29 | padding-bottom: 56.25%;
30 | }
31 |
32 | // Modifier class for 4:3 aspect ratio
33 | .embed-responsive-4by3 {
34 | padding-bottom: 75%;
35 | }
36 |
--------------------------------------------------------------------------------
/src/bootstrap/thumbnails.less:
--------------------------------------------------------------------------------
1 | //
2 | // Thumbnails
3 | // --------------------------------------------------
4 |
5 |
6 | // Mixin and adjust the regular image class
7 | .thumbnail {
8 | display: block;
9 | padding: @thumbnail-padding;
10 | margin-bottom: @line-height-computed;
11 | line-height: @line-height-base;
12 | background-color: @thumbnail-bg;
13 | border: 1px solid @thumbnail-border;
14 | border-radius: @thumbnail-border-radius;
15 | .transition(border .2s ease-in-out);
16 |
17 | > img,
18 | a > img {
19 | &:extend(.img-responsive);
20 | margin-left: auto;
21 | margin-right: auto;
22 | }
23 |
24 | // Add a hover state for linked versions only
25 | a&:hover,
26 | a&:focus,
27 | a&.active {
28 | border-color: @link-color;
29 | }
30 |
31 | // Image captions
32 | .caption {
33 | padding: @thumbnail-caption-padding;
34 | color: @thumbnail-caption-color;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/bootstrap/utilities.less:
--------------------------------------------------------------------------------
1 | //
2 | // Utility classes
3 | // --------------------------------------------------
4 |
5 |
6 | // Floats
7 | // -------------------------
8 |
9 | .clearfix {
10 | .clearfix();
11 | }
12 | .center-block {
13 | .center-block();
14 | }
15 | .pull-right {
16 | float: right !important;
17 | }
18 | .pull-left {
19 | float: left !important;
20 | }
21 |
22 |
23 | // Toggling content
24 | // -------------------------
25 |
26 | // Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1
27 | .hide {
28 | display: none !important;
29 | }
30 | .show {
31 | display: block !important;
32 | }
33 | .invisible {
34 | visibility: hidden;
35 | }
36 | .text-hide {
37 | .text-hide();
38 | }
39 |
40 |
41 | // Hide from screenreaders and browsers
42 | //
43 | // Credit: HTML5 Boilerplate
44 |
45 | .hidden {
46 | display: none !important;
47 | }
48 |
49 |
50 | // For Affix plugin
51 | // -------------------------
52 |
53 | .affix {
54 | position: fixed;
55 | }
56 |
--------------------------------------------------------------------------------
/src/bootstrap/wells.less:
--------------------------------------------------------------------------------
1 | //
2 | // Wells
3 | // --------------------------------------------------
4 |
5 |
6 | // Base class
7 | .well {
8 | min-height: 20px;
9 | padding: 19px;
10 | margin-bottom: 20px;
11 | background-color: @well-bg;
12 | border: 1px solid @well-border;
13 | border-radius: @border-radius-base;
14 | .box-shadow(inset 0 1px 1px rgba(0,0,0,.05));
15 | blockquote {
16 | border-color: #ddd;
17 | border-color: rgba(0,0,0,.15);
18 | }
19 | }
20 |
21 | // Sizes
22 | .well-lg {
23 | padding: 24px;
24 | border-radius: @border-radius-large;
25 | }
26 | .well-sm {
27 | padding: 9px;
28 | border-radius: @border-radius-small;
29 | }
30 |
--------------------------------------------------------------------------------
/src/components/alerts/stores/alertTrendFetcher.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 | import Q from 'q';
17 | import axios from 'axios';
18 | import ErrorHandlingStore from '../../../stores/errorHandlingStore';
19 |
20 | const fetcher = {};
21 |
22 | fetcher.fetchOperationTrends = (serviceName, operationName, granularity, from, until) => {
23 | const deferred = Q.defer();
24 |
25 | axios
26 | .get(`/api/trends/operation/${encodeURIComponent(serviceName)}/${encodeURIComponent(operationName)}?granularity=${granularity}&from=${from}&until=${until}`)
27 | .then((result) => {
28 | deferred.resolve(result.data);
29 | })
30 | .catch((result) => {
31 | ErrorHandlingStore.handleError(result);
32 | });
33 |
34 | return deferred.promise;
35 | };
36 |
37 | export default fetcher;
38 |
--------------------------------------------------------------------------------
/src/components/alerts/utils/subscriptionConstructor.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | export default function newSubscriptionConstructor(serviceName, operationName, type, interval, dispatchers) {
19 | return {
20 | dispatchers,
21 | expressionTree: {
22 | serviceName,
23 | operationName,
24 | metric_key: type,
25 | stat: type === 'failure-span' ? 'count' : '*_99',
26 | interval,
27 | mtype: 'gauge',
28 | product: 'haystack'
29 | }
30 | };
31 | }
32 |
--------------------------------------------------------------------------------
/src/components/common/error.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | import React from 'react';
19 | import PropTypes from 'prop-types';
20 |
21 | import './error.less';
22 |
23 | const Error = ({errorMessage}) => (
24 |
25 |
26 |
{"Oops! Couldn't find the needle"}
27 |
{errorMessage}
28 |
29 |
30 | );
31 |
32 | Error.defaultProps = {
33 | errorMessage: 'Please try again later'
34 | };
35 |
36 | Error.propTypes = {
37 | errorMessage: PropTypes.string
38 | };
39 |
40 | export default Error;
41 |
--------------------------------------------------------------------------------
/src/components/common/error.less:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * * Copyright 2018 Expedia Group
4 | * *
5 | * * Licensed under the Apache License, Version 2.0 (the "License");
6 | * * you may not use this file except 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, software
12 | * * distributed under the License is distributed on an "AS IS" BASIS,
13 | * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * * See the License for the specific language governing permissions and
15 | * * limitations under the License.
16 | * *
17 | *
18 | */
19 |
20 | @import (reference) '../../app';
21 |
22 | .error-message_text {
23 | display: inline-block;
24 | margin: @spacing-xl;
25 | padding: @spacing-s @spacing-l @spacing-s @spacing-l;
26 | border: 1px solid @gray-mid-lighter;
27 | background-color: white;
28 | }
29 |
--------------------------------------------------------------------------------
/src/components/common/loading.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | import React from 'react';
19 | import './loading.less';
20 |
21 | export default () => (
22 |
23 |
24 |
25 |
Loading...
26 |
27 |
28 | );
29 |
--------------------------------------------------------------------------------
/src/components/common/loading.less:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | @import (reference) '../../app';
19 |
20 | .loading_text {
21 | display: inline-block;
22 | margin: @spacing-xl;
23 | padding: @spacing-s @spacing-xl @spacing-s @spacing-xl;
24 | border: 2px solid @brand-primary;
25 | background-color: white;
26 | }
27 |
--------------------------------------------------------------------------------
/src/components/common/login.less:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 (reference) '../../app';
18 |
19 | .login-cover {
20 | position: relative;
21 | height: 100%;
22 | background-color: @gray-darker;
23 | }
24 |
25 | .login-box {
26 | position: absolute;
27 | top: 150px;
28 | width: 100%;
29 | }
30 |
31 | .login-box_jumbotron {
32 | .jumbotron;
33 | display: inline-block;
34 | width: 600px;
35 | margin-right: 0;
36 | margin-left: 0;
37 | border-radius: 6px;
38 | background-color: @gray-lighter;
39 | }
40 |
41 | .login-box_title.h1 {
42 | color: @gray-dark;
43 | }
44 |
45 | .login-box_logo {
46 | width: 70px;
47 | margin-right: @spacing-s;
48 | padding-bottom: @spacing-l;
49 | }
50 |
51 | .login-box_btn {
52 | padding-left: @spacing-xl !important;
53 | padding-right: @spacing-xl !important;
54 | }
55 |
--------------------------------------------------------------------------------
/src/components/common/modal.less:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 (reference) '../../app';
18 |
19 | .ReactModalPortal > * {
20 | // When the modal is closed, overlay div has no css class
21 | // This selector should be overridden by the `&--after-open` class below
22 | opacity: 0;
23 | }
24 |
25 | .ReactModal__Overlay {
26 | transition: opacity 200ms ease-in-out;
27 | background: rgba(0, 0, 0, 0.15);
28 | &--after-open {
29 | opacity: 1;
30 | }
31 | &--before-close {
32 | opacity: 0;
33 | }
34 | }
35 |
36 | /* Remove scroll on the body when react-modal is open */
37 | .ReactModal__Body--open {
38 | overflow: hidden;
39 | }
40 |
--------------------------------------------------------------------------------
/src/components/common/noMatch.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | import React from 'react';
19 | import {Link} from 'react-router-dom';
20 |
21 | export default () => (
22 |
23 |
24 |
Sorry!
25 |
Page not found
26 |
27 | Return to home
28 |
29 |
30 |
31 | );
32 |
--------------------------------------------------------------------------------
/src/components/common/timeRangePicker.less:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 (reference) '../../app';
18 |
19 | .custom-timerange-picker__datetime-from {
20 | margin-bottom: @spacing-s;
21 | }
22 |
--------------------------------------------------------------------------------
/src/components/docs/help.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | import React from 'react';
19 |
20 | export default () => (
21 |
22 |
23 |
Help
24 |
Coming Soon!
25 |
26 |
27 | );
28 |
--------------------------------------------------------------------------------
/src/components/layout/authenticationTimeoutModal.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | import React from 'react';
19 | import Modal from 'react-modal';
20 |
21 | const modalStyles = {
22 | overlay: {
23 | zIndex: 10,
24 | backgroundColor: 'rgba(0, 0, 0, 0.5)'
25 | },
26 | content: {
27 | width: '45%',
28 | maxWidth: '1240px',
29 | top: '30%',
30 | bottom: 'auto',
31 | left: '0',
32 | right: '0',
33 | marginLeft: 'auto',
34 | marginRight: 'auto'
35 | }
36 | };
37 |
38 | export default () => (
39 |
40 |
41 |
Session Expired
42 |
43 | Please login to continue where you left
44 | off.
45 |
46 |
47 |
48 | );
49 |
--------------------------------------------------------------------------------
/src/components/layout/footer.less:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | @import (reference) '../../app';
19 |
20 | .primary-footer {
21 | padding-top: @spacing-m;
22 | padding-bottom: @spacing-m;
23 | border-top: 1px solid @gray-mid-lighter;
24 | }
25 |
26 | .footer-links {
27 | display: block;
28 | padding: 0;
29 | }
30 |
31 | .footer-links__item {
32 | display: inline-block;
33 | margin-right: @spacing-l;
34 | }
35 |
36 | .footer-links__link {
37 | color: @text-color;
38 | }
39 |
--------------------------------------------------------------------------------
/src/components/serviceGraph/graphSearch.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia, Inc.
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 |
18 | import React from 'react';
19 | import PropTypes from 'prop-types';
20 |
21 | const ServiceGraphSearch = ({searchString, searchStringChanged}) => (
22 |
23 | {
27 | searchStringChanged(event.currentTarget.value);
28 | }}
29 | value={searchString}
30 | placeholder="Filter services..."
31 | />
32 |
33 |
34 | );
35 |
36 | ServiceGraphSearch.propTypes = {
37 | searchStringChanged: PropTypes.func.isRequired,
38 | searchString: PropTypes.string.isRequired
39 | };
40 |
41 | export default ServiceGraphSearch;
42 |
--------------------------------------------------------------------------------
/src/components/serviceGraph/serviceGraph.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | import React from 'react';
19 | import PropTypes from 'prop-types';
20 | import ServiceGraphContainer from './serviceGraphContainer';
21 | import './serviceGraph.less';
22 | import serviceGraphStore from './stores/serviceGraphStore';
23 |
24 | const ServiceGraph = ({history}) => {
25 | const search = {
26 | serviceName: undefined,
27 | time: {
28 | preset: '1h'
29 | }
30 | };
31 | return (
32 |
33 |
34 |
35 | );
36 | };
37 |
38 | ServiceGraph.propTypes = {
39 | history: PropTypes.object.isRequired
40 | };
41 | export default ServiceGraph;
42 |
--------------------------------------------------------------------------------
/src/components/serviceGraph/stores/serviceGraphStore.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 axios from 'axios';
18 | import {action, observable} from 'mobx';
19 | import {fromPromise} from 'mobx-utils';
20 | import {ErrorHandlingStore} from '../../../stores/errorHandlingStore';
21 |
22 | export class ServiceGraphStore extends ErrorHandlingStore {
23 | @observable graphs = [];
24 | @observable promiseState = null;
25 | @observable filterQuery = null;
26 |
27 | @action fetchServiceGraph(filterQuery) {
28 | this.promiseState = fromPromise(
29 | axios
30 | .get(`/api/serviceGraph?from=${filterQuery.from}&to=${filterQuery.to}`)
31 | .then((result) => {
32 | this.filterQuery = filterQuery;
33 | this.graphs = result.data;
34 | })
35 | .catch((result) => {
36 | ServiceGraphStore.handleError(result);
37 | })
38 | );
39 | }
40 | }
41 | export default new ServiceGraphStore();
42 |
--------------------------------------------------------------------------------
/src/components/serviceGraph/vizceralConfig.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | renderer: 'region',
3 | layout: 'ltrTree',
4 | name: 'haystack',
5 | maxVolume: 100000,
6 | metadata: {
7 | streaming: 1
8 | },
9 | updated: new Date().getTime(),
10 | nodes: [],
11 | connections: []
12 | };
13 |
--------------------------------------------------------------------------------
/src/components/serviceGraph/vizceralExt.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 Vizceral from 'vizceral-react';
18 |
19 | class VizceralExt extends Vizceral {
20 | componentWillUnmount() {
21 | this.vizceral.animate = () => {};
22 | delete this.vizceral;
23 | }
24 | }
25 |
26 | export default VizceralExt;
27 |
--------------------------------------------------------------------------------
/src/components/serviceInsights/serviceInsights.less:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Expedia Group
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 |
18 | .service-insights {
19 | margin-top: -18px;
20 | margin-bottom: -19px;
21 | }
22 |
23 | .service-insights__header {
24 | label {
25 | padding-right: 20px;
26 | }
27 | }
28 |
29 | .service-insights__filter {
30 | position: absolute;
31 | right: 50px;
32 | z-index: 1;
33 | span {
34 | display: inline-block;
35 | margin-right: 5px;
36 | }
37 | select {
38 | padding-right: 20px;
39 | }
40 | }
41 |
42 | .header-summary {
43 | position: absolute;
44 | max-width: 500px;
45 | margin-top: 20px;
46 | padding: 8px 16px;
47 | z-index: 1;
48 | background: #f2f4fbde;
49 | border: solid 1px #cacaca;
50 | pointer-events: none;
51 |
52 | .violation-grid {
53 | display: grid;
54 | grid-template-columns: auto auto;
55 | align-items: baseline;
56 | line-height: 14px;
57 | color: red;
58 | }
59 |
60 | .violation-title {
61 | padding-right: 5px;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/components/serviceInsights/serviceInsightsGraph/icons/db.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
--------------------------------------------------------------------------------
/src/components/serviceInsights/serviceInsightsGraph/icons/gateway.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
--------------------------------------------------------------------------------
/src/components/serviceInsights/serviceInsightsGraph/icons/outbound.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
--------------------------------------------------------------------------------
/src/components/serviceInsights/serviceInsightsGraph/icons/uninstrumented.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
--------------------------------------------------------------------------------
/src/components/serviceInsights/serviceInsightsGraph/labels.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Expedia Group
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 |
18 | import React from 'react';
19 | import PropTypes from 'prop-types';
20 |
21 | import Label from './label';
22 |
23 | function Labels({nodes}) {
24 | return (
25 |
26 | {nodes.map((node) => {
27 | if (node.data.type === 'mesh') {
28 | return null;
29 | }
30 | return ;
31 | })}
32 |
33 | );
34 | }
35 |
36 | Labels.propTypes = {
37 | nodes: PropTypes.array.isRequired
38 | };
39 |
40 | export default Labels;
41 |
--------------------------------------------------------------------------------
/src/components/serviceInsights/summary.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Expedia Group
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 |
18 | import React from 'react';
19 | import PropTypes from 'prop-types';
20 |
21 | function Summary({data}) {
22 | return (
23 |
38 | );
39 | }
40 |
41 | Summary.propTypes = {
42 | data: PropTypes.object.isRequired
43 | };
44 |
45 | export default Summary;
46 |
--------------------------------------------------------------------------------
/src/components/servicePerf/stores/servicePerfStore.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 axios from 'axios';
18 | import {action, observable} from 'mobx';
19 | import {fromPromise} from 'mobx-utils';
20 |
21 | import { ErrorHandlingStore } from '../../../stores/errorHandlingStore';
22 |
23 | export class ServicePerfStore extends ErrorHandlingStore {
24 | @observable servicePerfStats = [];
25 | @observable promiseState = { case: ({empty}) => empty() };
26 |
27 | @action fetchServicePerf(timeWindow, from, until) {
28 | this.promiseState = fromPromise(
29 | axios({
30 | method: 'get',
31 | url: `/api/servicePerf?timeWindow=${timeWindow}&from=${from}&until=${until}`
32 | })
33 | .then((response) => {
34 | this.servicePerfStats = response.data;
35 | })
36 | .catch((result) => {
37 | ServicePerfStore.handleError(result);
38 | })
39 | );
40 | }
41 | }
42 |
43 | export default new ServicePerfStore();
44 |
--------------------------------------------------------------------------------
/src/components/traces/results/noSearch.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | import React from 'react';
19 | import './noSearch.less';
20 |
21 | export default () => (
22 |
23 |
24 |
{'Please select a service and search'}
25 |
26 |
27 | );
28 |
--------------------------------------------------------------------------------
/src/components/traces/results/noSearch.less:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 (reference) '../../../app';
18 |
19 | .no-search_text {
20 | display: inline-block;
21 | margin: @spacing-xl;
22 | padding: @spacing-s @spacing-l @spacing-s @spacing-l;
23 | border: 1px solid @gray-mid-lighter;
24 | background-color: white;
25 | }
26 |
--------------------------------------------------------------------------------
/src/components/traces/stores/latencyCostStore.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 axios from 'axios';
18 | import {observable, action} from 'mobx';
19 | import { fromPromise } from 'mobx-utils';
20 | import { ErrorHandlingStore } from '../../../stores/errorHandlingStore';
21 |
22 | export class LatencyCostStore extends ErrorHandlingStore {
23 | @observable latencyCost = {};
24 | @observable promiseState = null;
25 | traceId = null;
26 |
27 | @action fetchLatencyCost(traceId) {
28 | if (this.traceId === traceId) return;
29 | this.traceId = traceId;
30 |
31 | this.promiseState = fromPromise(
32 | axios
33 | .get(`/api/trace/${traceId}/latencyCost`)
34 | .then((result) => {
35 | this.latencyCost = result.data;
36 | })
37 | .catch((result) => {
38 | LatencyCostStore.handleError(result);
39 | })
40 | );
41 | }
42 | }
43 |
44 | export default new LatencyCostStore();
45 |
--------------------------------------------------------------------------------
/src/components/traces/stores/rawSpanStore.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 | import axios from 'axios';
17 | import {observable, action} from 'mobx';
18 | import { fromPromise } from 'mobx-utils';
19 | import { ErrorHandlingStore } from '../../../stores/errorHandlingStore';
20 |
21 | export class RawSpanStore extends ErrorHandlingStore {
22 | @observable rawSpan = [];
23 |
24 | @observable promiseState = null;
25 |
26 | @action fetchRawSpan(traceId, spanId, serviceName) {
27 | this.promiseState = fromPromise(
28 | axios
29 | .get(`/api/trace/raw/${traceId}/${spanId}?serviceName=${serviceName}`)
30 | .then((result) => {
31 | this.rawSpan = result.data;
32 | })
33 | .catch((result) => {
34 | RawSpanStore.handleError(result);
35 | })
36 | );
37 | }
38 | }
39 |
40 | export default new RawSpanStore();
41 |
--------------------------------------------------------------------------------
/src/components/traces/stores/rawTraceStore.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 | import axios from 'axios';
17 | import {observable, action} from 'mobx';
18 | import { fromPromise } from 'mobx-utils';
19 | import { ErrorHandlingStore } from '../../../stores/errorHandlingStore';
20 |
21 |
22 | export class RawTraceStore extends ErrorHandlingStore {
23 | @observable rawTrace = [];
24 |
25 | @observable promiseState = null;
26 |
27 | @action fetchRawTrace(traceId) {
28 | this.promiseState = fromPromise(
29 | axios
30 | .get(`/api/trace/raw/${traceId}`)
31 | .then((result) => {
32 | this.rawTrace = result.data;
33 | })
34 | .catch((result) => {
35 | RawTraceStore.handleError(result);
36 | })
37 | );
38 | }
39 | }
40 |
41 | export default new RawTraceStore();
42 |
--------------------------------------------------------------------------------
/src/components/traces/stores/searchableKeysStore.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 axios from 'axios';
18 | import {observable, action} from 'mobx';
19 |
20 | export class SearchableKeysStore {
21 | @observable keys = [];
22 |
23 | @action fetchKeys() {
24 | if (this.keys.length) {
25 | return; // services already available, don't retrigger
26 | }
27 | axios({
28 | method: 'get',
29 | url: '/api/traces/searchableKeys'
30 | })
31 | .then((response) => {
32 | this.keys = response.data.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
33 | });
34 | }
35 | }
36 |
37 | export default new SearchableKeysStore();
38 |
--------------------------------------------------------------------------------
/src/components/traces/stores/spansSearchStore.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 axios from 'axios';
18 | import {observable, action} from 'mobx';
19 | import { fromPromise } from 'mobx-utils';
20 | import { ErrorHandlingStore } from '../../../stores/errorHandlingStore';
21 |
22 | export class SpansSearchStore extends ErrorHandlingStore {
23 | @observable results = [];
24 | @observable promiseState = null;
25 |
26 | @action fetchSpans(traceIds) {
27 | this.promiseState = fromPromise(
28 | axios
29 | .get(`/api/traces/raw?traceIds=${encodeURIComponent(JSON.stringify(traceIds))}`)
30 | .then((result) => {
31 | this.results = result.data;
32 | })
33 | .catch((result) => {
34 | SpansSearchStore.handleError(result);
35 | })
36 | );
37 | }
38 | }
39 |
40 | export default new SpansSearchStore();
41 |
--------------------------------------------------------------------------------
/src/components/traces/stores/traceTrendFetcher.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 | import Q from 'q';
17 | import axios from 'axios';
18 | import ErrorHandlingStore from '../../../stores/errorHandlingStore';
19 |
20 | const fetcher = {};
21 |
22 | fetcher.fetchOperationTrends = (serviceName, operationName, granularity, from, until) => {
23 | const deferred = Q.defer();
24 |
25 | axios
26 | .get(`/api/trends/operation/${encodeURIComponent(serviceName)}/${encodeURIComponent(operationName)}?granularity=${granularity}&from=${from}&until=${until}`)
27 | .then((result) => {
28 | deferred.resolve(result.data);
29 | })
30 | .catch((result) => {
31 | ErrorHandlingStore.handleError(result);
32 | });
33 |
34 | return deferred.promise;
35 | };
36 |
37 | export default fetcher;
38 |
--------------------------------------------------------------------------------
/src/components/traces/utils/auxiliaryTags.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 | export default {
18 | IS_MERGED_SPAN: 'X-HAYSTACK-IS-MERGED-SPAN',
19 | CLIENT_SERVICE_NAME: 'X-HAYSTACK-CLIENT-SERVICE-NAME',
20 | CLIENT_OPERATION_NAME: 'X-HAYSTACK-CLIENT-OPERATION-NAME',
21 | CLIENT_START_TIME: 'X-HAYSTACK-CLIENT-START-TIME',
22 | CLIENT_DURATION: 'X-HAYSTACK-CLIENT-DURATION',
23 | CLIENT_SPAN_ID: 'X-HAYSTACK-CLIENT-SPAN-ID',
24 | IS_AUTOGENERATED_SPAN: 'X-HAYSTACK-AUTOGEN'
25 | };
26 |
--------------------------------------------------------------------------------
/src/components/traces/utils/presets.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | function getUnitText(unit) {
19 | if (unit === 'd') return 'day';
20 | if (unit === 'h') return 'hour';
21 | return 'minute';
22 | }
23 |
24 | export function toPresetDisplayText(preset) {
25 | const count = preset.substr(0, preset.length - 1);
26 | const unit = getUnitText(preset[preset.length - 1]);
27 |
28 | return `last ${count} ${unit}${count > 1 ? 's' : ''}`;
29 | }
30 |
31 | export function toDurationMicroseconds(preset) {
32 | if (preset) {
33 | const count = preset.substr(0, preset.length - 1);
34 | const unit = preset[preset.length - 1];
35 | let multiplier;
36 |
37 | switch (unit) {
38 | case 's':
39 | multiplier = 60;
40 | break;
41 | case 'h':
42 | multiplier = 60 * 60;
43 | break;
44 | case 'd':
45 | multiplier = 60 * 60 * 24;
46 | break;
47 | default:
48 | multiplier = 60;
49 | }
50 |
51 | return parseInt(count, 10) * multiplier * 1000 * 1000;
52 | }
53 |
54 | return null;
55 | }
56 |
--------------------------------------------------------------------------------
/src/components/trends/details/graphs/graphContainer.less:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 (reference) '../../../../app';
18 |
19 | .reset-button {
20 | position: relative;
21 | margin-right: 15px;
22 | margin-bottom: -55px;
23 | z-index: 100;
24 | }
25 |
--------------------------------------------------------------------------------
/src/components/trends/details/graphs/missingTrend.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 PropTypes from 'prop-types';
19 |
20 | import './missingTrend.less';
21 |
22 | const MissingTrend = ({title}) =>
23 | (
24 |
25 |
{title}
26 |
27 |
28 | No data points found
29 |
30 |
31 |
32 | );
33 |
34 | MissingTrend.propTypes = {
35 | title: PropTypes.string.isRequired
36 | };
37 |
38 | export default MissingTrend;
39 |
--------------------------------------------------------------------------------
/src/components/trends/details/graphs/missingTrend.less:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 (reference) '../../../../app';
18 |
19 | .missing-data-point-warn {
20 | display: inline-block;
21 | padding: @spacing-s;
22 | border: 1px solid @gray-mid-light;
23 | margin-bottom: @spacing-l;
24 | }
--------------------------------------------------------------------------------
/src/components/trends/details/graphs/options.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 {Chart} from 'react-chartjs-2';
18 |
19 | Chart.defaults.global.defaultFontFamily = 'monospace';
20 |
21 | export default {
22 | maintainAspectRatio: false,
23 | legend: {
24 | position: 'right'
25 | },
26 | scales: {
27 | xAxes: [
28 | {
29 | type: 'time'
30 | }
31 | ],
32 | yAxes: [
33 | {
34 | ticks: {
35 | beginAtZero: true
36 | }
37 | }
38 | ]
39 | },
40 | pan: {
41 | enabled: false,
42 | mode: 'x'
43 | },
44 | zoom: {
45 | enabled: true,
46 | mode: 'x',
47 | speed: 0.05,
48 | drag: {
49 | borderColor: 'rgba(63,77,113,0.4)',
50 | borderWidth: 0.3,
51 | backgroundColor: 'rgba(63,77,113,0.2)'
52 | }
53 | }
54 | };
55 |
--------------------------------------------------------------------------------
/src/components/trends/details/trendDetails.less:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 (reference) '../../../app';
18 |
19 | .chart-container {
20 | height: 200px;
21 | margin-bottom: @spacing-s;
22 | }
23 |
24 | canvas {
25 | user-select: none;
26 | }
--------------------------------------------------------------------------------
/src/components/trends/operation/operationResults.less:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 | @import (reference) '../../../app';
17 |
18 | .operation-results .react-bs-table-container {
19 | margin-top: 0;
20 | }
21 | .results-table-heading {
22 | font-size: xx-large;
23 | }
24 | .operation-results-view-selector {
25 | margin-bottom: @spacing-m;
26 | }
27 |
--------------------------------------------------------------------------------
/src/components/trends/utils/metricGranularity.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | const granularity = {};
19 |
20 | granularity.options = [
21 | {
22 | shortName: '1m',
23 | longName: 'OneMinute',
24 | value: 60 * 1000
25 | },
26 | {
27 | shortName: '5m',
28 | longName: 'FiveMinute',
29 | value: 5 * 60 * 1000
30 | },
31 | {
32 | shortName: '15m',
33 | longName: 'FifteenMinute',
34 | value: 15 * 60 * 1000
35 | },
36 | {
37 | shortName: '1h',
38 | longName: 'OneHour',
39 | value: 60 * 60 * 1000
40 | }
41 | ];
42 |
43 | granularity.getMinGranularity = timeInMs => granularity.options.find(option => option.value >= timeInMs) || granularity.options[granularity.options.length - 1];
44 |
45 | const granularityRanges = [60 * 1000, 5 * 60 * 1000, 15 * 60 * 1000, 30 * 60 * 1000, 60 * 60 * 1000, 3 * 60 * 60 * 1000, 6 * 60 * 60 * 1000, 12 * 60 * 60 * 1000, 24 * 60 * 60 * 1000];
46 |
47 | granularity.getMaxGranularity = timeInMs => granularityRanges.find(option => option >= timeInMs);
48 |
49 | export default granularity;
50 |
--------------------------------------------------------------------------------
/src/components/universalSearch/searchBar/searchSubmit.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 PropTypes from 'prop-types';
19 |
20 | const Submit = ({handleSearch}) => (
21 |
22 |
25 |
26 | );
27 |
28 | Submit.propTypes = {
29 | handleSearch: PropTypes.func.isRequired
30 | };
31 |
32 | export default Submit;
33 |
--------------------------------------------------------------------------------
/src/components/universalSearch/searchBar/stores/searchableKeysStore.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 axios from 'axios';
18 | import {observable, action} from 'mobx';
19 | import {ErrorHandlingStore} from '../../../../stores/errorHandlingStore';
20 |
21 | export class SearchableKeysStore extends ErrorHandlingStore {
22 | @observable keys = {};
23 |
24 | @action fetchKeys() {
25 | if (Object.keys(this.keys).length > 3) { // traceId, serviceName and operationName are default
26 | return; // don't re-trigger if other keys are available
27 | }
28 | axios
29 | .get('/api/traces/searchableKeys')
30 | .then((response) => {
31 | this.keys = response.data;
32 | if (this.keys.error) {
33 | this.keys.error.values = ['true', 'false'];
34 | }
35 | })
36 | .catch((result) => {
37 | SearchableKeysStore.handleError(result);
38 | }
39 | );
40 | }
41 | }
42 |
43 | export default new SearchableKeysStore();
44 |
--------------------------------------------------------------------------------
/src/components/universalSearch/tabs/emptyTabPlaceholder.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
19 | export default () => (
20 |
21 |
22 |
23 |
24 |
25 | Start with a query for serviceName, traceId, or any other
26 | searchable key
27 |
28 |
29 | e.g. serviceName=test-service
30 |
31 |
32 |
33 |
34 |
35 | );
36 |
--------------------------------------------------------------------------------
/src/components/universalSearch/tabs/serviceInsights.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Expedia Group
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 {observer} from 'mobx-react';
19 | import PropTypes from 'prop-types';
20 |
21 | @observer
22 | export default class ServiceInsights extends React.Component {
23 | static propTypes = {
24 | history: PropTypes.object.isRequired,
25 | search: PropTypes.object.isRequired,
26 | store: PropTypes.object.isRequired
27 | };
28 |
29 | state = {};
30 |
31 | componentDidMount() {
32 | import(/* webpackChunkName: "ServiceInsights", webpackPreload: true */ '../../serviceInsights/serviceInsights').then((mod) => {
33 | this.setState({ServiceInsightsView: mod.default});
34 | });
35 | }
36 |
37 | render() {
38 | const ServiceInsightsView = this.state.ServiceInsightsView;
39 |
40 | return (
41 |
42 | {ServiceInsightsView && }
43 |
44 | );
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/components/universalSearch/tabs/tabStores/serviceGraphStateStore.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable class-methods-use-this */
2 | /*
3 | * Copyright 2018 Expedia Group
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except 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, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | import store from '../../../serviceGraph/stores/serviceGraphStore';
19 |
20 | const subsystems = (window.haystackUiConfig && window.haystackUiConfig.subsystems) || [];
21 | const enabled = subsystems.includes('serviceGraph');
22 |
23 | export class ServiceGraphStateStore {
24 | search = null;
25 | isAvailable = false;
26 |
27 | init(search, tabProperties) {
28 | // initialize observables using search object
29 | // check if for the given search context tab should be available
30 | this.search = search;
31 |
32 | this.isAvailable = enabled && (tabProperties.onlyService || !tabProperties.queries.length);
33 | }
34 |
35 | fetch() {
36 | return store;
37 | }
38 | }
39 |
40 | export default new ServiceGraphStateStore();
41 |
--------------------------------------------------------------------------------
/src/components/universalSearch/tabs/tabStores/servicePerformanceStateStore.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 | /* eslint-disable class-methods-use-this */
18 |
19 | const enabled = window.haystackUiConfig && window.haystackUiConfig.subsystems.includes('trends') && window.haystackUiConfig.enableServicePerformance;
20 |
21 | export class ServicePerformanceStateStore {
22 | isAvailable = false;
23 |
24 | init(search, tabProperties) {
25 | this.isAvailable = enabled && !tabProperties.queries.length;
26 | }
27 |
28 | fetch() {}
29 | }
30 |
31 | export default new ServicePerformanceStateStore();
32 |
--------------------------------------------------------------------------------
/src/main.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | import React from 'react';
19 | import {Route, Switch} from 'react-router-dom';
20 |
21 | import Login from './components/common/login';
22 | import UploadContainer from './components/traces/upload/uploadContainer';
23 | import UniversalSearch from './components/universalSearch/universalSearch';
24 | import './app.less';
25 |
26 | export default () => (
27 |
28 |
29 | }/>
30 |
31 |
32 |
33 |
34 | );
35 |
--------------------------------------------------------------------------------
/src/stores/authenticationStore.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 {observable} from 'mobx';
18 |
19 | export class AuthenticationStore {
20 | @observable timedOut = false;
21 | }
22 |
23 | export default new AuthenticationStore();
24 |
--------------------------------------------------------------------------------
/src/stores/errorHandlingStore.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 authenticationStore from './authenticationStore';
18 |
19 | function HaystackApiException(data) {
20 | this.message = 'Unable to resolve promise';
21 | this.data = data;
22 | }
23 |
24 | export class ErrorHandlingStore {
25 | static handleError(result) {
26 | if (result.response.status === 401) {
27 | authenticationStore.timedOut = true;
28 | }
29 | throw new HaystackApiException(result);
30 | }
31 | }
32 |
33 | export default new ErrorHandlingStore();
34 |
--------------------------------------------------------------------------------
/src/stores/operationStore.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 axios from 'axios';
18 | import {observable, action} from 'mobx';
19 |
20 | import { ErrorHandlingStore } from './errorHandlingStore';
21 |
22 | export class OperationStore extends ErrorHandlingStore {
23 | @observable operations = [];
24 |
25 | @action fetchOperations(serviceName, callback) {
26 | this.operations = [];
27 | axios({
28 | method: 'get',
29 | url: `/api/operations?serviceName=${serviceName}`
30 | })
31 | .then((response) => {
32 | this.operations = ['all', ...response.data.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()))];
33 | callback();
34 | })
35 | .catch((result) => {
36 | OperationStore.handleError(result);
37 | });
38 | }
39 | }
40 |
41 | export default new OperationStore();
42 |
--------------------------------------------------------------------------------
/src/stores/serviceStore.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 axios from 'axios';
18 | import {observable, action} from 'mobx';
19 |
20 | import { ErrorHandlingStore } from './errorHandlingStore';
21 |
22 | export class ServiceStore extends ErrorHandlingStore {
23 | @observable services = [];
24 |
25 | @action fetchServices() {
26 | if (this.services.length) {
27 | return; // services already available, don't retrigger
28 | }
29 | if (window.haystackUiConfig.services) {
30 | this.services = window.haystackUiConfig.services;
31 | return; // services found in the html, don't retrigger
32 | }
33 | axios({
34 | method: 'get',
35 | url: '/api/services'
36 | })
37 | .then((response) => {
38 | this.services = response.data.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
39 | })
40 | .catch((result) => {
41 | ServiceStore.handleError(result);
42 | });
43 | }
44 | }
45 |
46 | export default new ServiceStore();
47 |
--------------------------------------------------------------------------------
/src/stores/storesInitializer.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | import axios from 'axios';
19 |
20 | export default {
21 | init: () => {
22 | // axios init
23 | axios.defaults.timeout = 60000;
24 | }
25 | };
26 |
--------------------------------------------------------------------------------
/src/utils/blobUtil.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Expedia, Inc.
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 blobUtil = {};
18 |
19 | blobUtil.isBlobUrlTag = (key) => {
20 | const lowercaseKey = key.toLowerCase();
21 | return lowercaseKey.endsWith('-blob') || lowercaseKey === 'request' || lowercaseKey === 'response';
22 | };
23 |
24 | blobUtil.formatBlobTagValue = (tagValue, blobsUrl) => {
25 | if (tagValue.startsWith('/getBlob/')) {
26 | return blobsUrl ? `${blobsUrl}${tagValue}` : `${window.location.protocol}//${window.location.host}${tagValue}`;
27 | }
28 | return blobsUrl ? `${blobsUrl}/getBlob/${tagValue}` : `${window.location.protocol}//${window.location.host}/getBlob/${tagValue}`;
29 | };
30 |
31 | export default blobUtil;
32 |
--------------------------------------------------------------------------------
/src/utils/hashUtil.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-bitwise */
2 | /*
3 | * Copyright 2018 Expedia Group
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except 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, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | const hashUtil = {};
19 |
20 | hashUtil.calculateHash = svc =>
21 | svc.split('').reduce((a, b) => {
22 | let running = a;
23 | running = ((running << 5) - running) + b.charCodeAt(0);
24 | return running & running;
25 | }, 0);
26 |
27 | export default hashUtil;
28 |
--------------------------------------------------------------------------------
/src/utils/linkBuilder.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 { convertSearchToUrlQuery } from '../components/universalSearch/utils/urlUtils';
18 |
19 | const linkBuilder = {};
20 |
21 | linkBuilder.withAbsoluteUrl = relativeUrl => `${window.location.protocol}//${window.location.host}${relativeUrl}`;
22 |
23 | linkBuilder.universalSearchLink = search => `/search?${convertSearchToUrlQuery(search)}`;
24 |
25 | linkBuilder.universalSearchTracesLink = search => `/search?${convertSearchToUrlQuery(search)}&tabId=traces`;
26 |
27 | linkBuilder.universalSearchTrendsLink = search => `/search?${convertSearchToUrlQuery(search)}&tabId=trends`;
28 |
29 | linkBuilder.universalSearchAlertsLink = search => `/search?${convertSearchToUrlQuery(search)}&tabId=alerts`;
30 |
31 | export default linkBuilder;
32 |
--------------------------------------------------------------------------------
/src/utils/loginRenewer.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 axios from 'axios';
18 |
19 | const renewer = {};
20 |
21 | renewer.init = () => setInterval(() => axios.get('/auth/renewlogin'), 5 * 60 * 1000);
22 |
23 | export default renewer;
24 |
--------------------------------------------------------------------------------
/src/utils/queryParser.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | export const toQueryUrlString = query => Object
19 | .keys(query)
20 | .filter(key => query[key])
21 | .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(query[key])}`)
22 | .join('&');
23 |
24 | export const toQuery = (query) => {
25 | const queryDict = {};
26 |
27 | if (!query || query.length <= 1) return {};
28 |
29 | query.substr(1)
30 | .split('&')
31 | .forEach((item) => {
32 | queryDict[decodeURIComponent(item.split('=')[0])] = decodeURIComponent(item.split('=')[1]);
33 | });
34 | return queryDict;
35 | };
36 |
--------------------------------------------------------------------------------
/src/utils/serviceColorMapper.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 | /* eslint-disable no-bitwise */
17 |
18 | import hashUtil from './hashUtil';
19 |
20 | const colorMapper = {};
21 |
22 | function mapToColorIndex(svc) {
23 | return (Math.abs(hashUtil.calculateHash(svc)) % 25) + 1;
24 | }
25 |
26 | colorMapper.toFillClass = serviceName => `svc-color-${mapToColorIndex(serviceName)}-fill`;
27 |
28 | colorMapper.toBackgroundClass = serviceName => `svc-color-${mapToColorIndex(serviceName)}-bg`;
29 |
30 | export default colorMapper;
31 |
--------------------------------------------------------------------------------
/src/utils/validUrl.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 validUrl = {};
18 |
19 | const urlRegex = new RegExp(/(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/); // eslint-disable-line no-useless-escape
20 |
21 | validUrl.isUrl = str => urlRegex.test(str);
22 |
23 | export default validUrl;
24 |
--------------------------------------------------------------------------------
/test/server/connectors/utils/encoders/Base64Encoder.spec.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 |
19 | import {expect} from 'chai';
20 |
21 | const Base64Encoder = require('../../../../../server/connectors/utils/encoders/Base64Encoder');
22 |
23 | describe('Base64Encoder', () => {
24 | it('encodes and decodes correctly', () => {
25 | const value = 'some Value. /';
26 |
27 | const encodedValue = Base64Encoder.encode(value);
28 | expect(encodedValue).equals('c29tZSBWYWx1ZS4gLw__');
29 | expect(Base64Encoder.decode(encodedValue)).equals(value);
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/test/server/connectors/utils/encoders/NoopEncoder.spec.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 |
19 | import {expect} from 'chai';
20 |
21 | const NoopEncoder = require('../../../../../server/connectors/utils/encoders/NoopEncoder');
22 |
23 | describe('NoopEncoder', () => {
24 | it('encodes and decodes correctly', () => {
25 | const value = 'some Value. /';
26 |
27 | const encodedValue = NoopEncoder.encode(value);
28 | expect(encodedValue).equals(value);
29 | expect(NoopEncoder.decode(encodedValue)).equals(value);
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/test/server/connectors/utils/encoders/PeriodReplacementEncoder.spec.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 |
19 | import {expect} from 'chai';
20 |
21 | const PeriodReplacementEncoder = require('../../../../../server/connectors/utils/encoders/PeriodReplacementEncoder');
22 |
23 | describe('PeriodReplacementEncoder', () => {
24 | it('encodes and decodes correctly', () => {
25 | const value = 'some Value. /';
26 |
27 | const encodedValue = PeriodReplacementEncoder.encode(value);
28 | expect(encodedValue).equals('some Value___ /');
29 | expect(PeriodReplacementEncoder.decode(encodedValue)).equals(value);
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/test/server/routes/index.spec.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 server = require('../../../server/app.js');
18 | const request = require('supertest');
19 |
20 | describe('routes.index', () => {
21 | it('returns http 200', (done) => {
22 | request(server)
23 | .get('/')
24 | .expect(200)
25 | .end((err) => {
26 | if (err) {
27 | return done(err);
28 | }
29 | return done();
30 | });
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/test/server/routes/serviceInsightsApi.spec.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 server = require('../../../server/app.js');
18 | const request = require('supertest');
19 |
20 | describe('routes.servicesApi', () => {
21 | it('returns http 200 for /api/serviceInsights', (done) => {
22 | request(server)
23 | .get('/api/serviceInsights?serviceName=stark-service&from=1000&to=2000')
24 | .expect(200)
25 | .end((err) => {
26 | if (err) {
27 | return done(err);
28 | }
29 | return done();
30 | });
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/test/server/routes/servicesApi.spec.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 server = require('../../../server/app.js');
18 | const request = require('supertest');
19 |
20 | describe('routes.servicesApi', () => {
21 | it('returns http 200 for /api/services', (done) => {
22 | request(server)
23 | .get('/api/services')
24 | .expect(200)
25 | .end((err) => {
26 | if (err) {
27 | return done(err);
28 | }
29 | return done();
30 | });
31 | });
32 |
33 | it('returns http 200 for /api/operations', (done) => {
34 | request(server)
35 | .get('/api/operations?serviceName=service')
36 | .expect(200)
37 | .end((err) => {
38 | if (err) {
39 | return done(err);
40 | }
41 | return done();
42 | });
43 | });
44 | });
45 |
--------------------------------------------------------------------------------
/test/server/routes/servicesPerfApi.spec.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 server = require('../../../server/app.js');
18 | const request = require('supertest');
19 |
20 | describe('routes.servicePerfApi', () => {
21 | it('returns http 200 for /api/servicePerf', (done) => {
22 | request(server)
23 | .get('/api/servicePerf')
24 | .expect(200)
25 | .end((err) => {
26 | if (err) {
27 | return done(err);
28 | }
29 | return done();
30 | });
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/test/src/components/common/help.spec.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | import React from 'react';
19 | import { mount } from 'enzyme';
20 | import { expect } from 'chai';
21 | import Help from '../../../../src/components/docs/help';
22 |
23 | describe('', () => {
24 | it('should render the help panel`', () => {
25 | const wrapper = mount();
26 | expect(wrapper.find('.help-panel')).to.have.length(1);
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/test/src/components/common/noMatch.spec.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | import React from 'react';
19 | import { shallow } from 'enzyme';
20 | import { expect } from 'chai';
21 | import NoMatch from '../../../../src/components/common/noMatch';
22 |
23 | describe('', () => {
24 | it('should render the NoMatch panel`', () => {
25 | const wrapper = shallow();
26 | expect(wrapper.find('.nomatch-panel')).to.have.length(1);
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/test/src/components/common/timeRangePicker.spec.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | import {expect} from 'chai';
19 | import DateTime from 'react-datetime';
20 | import TimeRangePicker from '../../../../src/components/common/timeRangePicker';
21 |
22 | describe('TimeRangePicker.isFromValid', () => {
23 | window.haystackUiConfig.trendsTTL = 3 * 24 * 60 * 60 * 1000;
24 |
25 | it('should be true when current is before today and after the ttl', () => {
26 | expect(TimeRangePicker.isFromValid(DateTime.moment().subtract(1, 'day'))).to.equal(true);
27 | });
28 |
29 | it('should be false when current is after today and after the ttl', () => {
30 | expect(TimeRangePicker.isFromValid(DateTime.moment().add(1, 'day'))).to.equal(false);
31 | });
32 |
33 | it('should be false when current is before today and before the ttl', () => {
34 | expect(TimeRangePicker.isFromValid(DateTime.moment().subtract(11, 'day'))).to.equal(false);
35 | });
36 | });
37 |
--------------------------------------------------------------------------------
/test/src/components/layout.spec.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | import React from 'react';
19 | import {mount} from 'enzyme';
20 | import {expect} from 'chai';
21 | import {MemoryRouter} from 'react-router-dom';
22 |
23 | import Footer from '../../../src/components/layout/footer';
24 |
25 | describe('', () => {
26 | it('should render the footer`', () => {
27 | const wrapper = mount();
28 | expect(wrapper.find('.primary-footer')).to.have.length(1);
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/test/src/components/serviceInsights/serviceInsightsGraph/labels.spec.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Expedia Group
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 |
18 | import React from 'react';
19 | import {expect} from 'chai';
20 | import {shallow} from 'enzyme';
21 |
22 | import Labels from '../../../../../src/components/serviceInsights/serviceInsightsGraph/labels';
23 |
24 | describe('', () => {
25 | it('should render the expected elements', () => {
26 | const wrapper = shallow();
27 |
28 | expect(wrapper.find('.labels')).to.have.lengthOf(1);
29 | expect(wrapper.find('Label')).to.have.lengthOf(1);
30 | expect(wrapper.find('Label').prop('text')).to.equal('foo');
31 | expect(wrapper.find('Label').prop('x')).to.equal(10);
32 | expect(wrapper.find('Label').prop('y')).to.equal(20);
33 | });
34 |
35 | it('should not render a label for mesh nodes', () => {
36 | const wrapper = shallow();
37 |
38 | expect(wrapper.find('.labels')).to.have.lengthOf(1);
39 | expect(wrapper.find('Label')).to.have.lengthOf(0);
40 | });
41 | });
42 |
--------------------------------------------------------------------------------
/test/src/components/trends/details/graphs/durationGraph.spec.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | import React from 'react';
19 | import {shallow} from 'enzyme';
20 | import {expect} from 'chai';
21 | import {Line} from 'react-chartjs-2';
22 | import {observable} from 'mobx';
23 | import DurationGraph from '../../../../../../src/components/trends/details/graphs/durationGraph';
24 |
25 | describe('', () => {
26 | it('should not transform value as it is already in ms', () => {
27 | const from = 1000;
28 | const until = 2000;
29 |
30 | const xAxesTicks = {
31 | min: from,
32 | max: until
33 | };
34 |
35 | const meanPoints = observable.array([{timestamp: 1530844500000, value: 902}]);
36 | const tp95Points = observable.array([]);
37 | const tp99Points = observable.array([]);
38 | const wrapper = shallow();
39 |
40 | expect(wrapper.find(Line).props().data.datasets[2].data[0].y).to.equal(902);
41 | });
42 | });
43 |
--------------------------------------------------------------------------------
/test/src/components/universalSearch/searchBar/timeRangePicker.spec.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | import {expect} from 'chai';
19 | import DateTime from 'react-datetime';
20 | import TimeRangePicker from '../../../../../src/components/universalSearch/searchBar/timeRangePicker';
21 |
22 | describe('TimeRangePicker.fromValid', () => {
23 | window.haystackUiConfig.tracesTTL = 3 * 24 * 60 * 60 * 1000;
24 |
25 | it('should be true when current is before today and after the ttl', () => {
26 | expect(TimeRangePicker.fromValid(DateTime.moment().subtract(1, 'day'))).to.equal(true);
27 | });
28 |
29 | it('should be false when current is after today and after the ttl', () => {
30 | expect(TimeRangePicker.fromValid(DateTime.moment().add(1, 'day'))).to.equal(false);
31 | });
32 |
33 | it('should be false when current is before today and before the ttl', () => {
34 | expect(TimeRangePicker.fromValid(DateTime.moment().subtract(11, 'day'))).to.equal(false);
35 | });
36 | });
37 |
--------------------------------------------------------------------------------
/test/src/components/universalSearch/tabs/serviceInsights.spec.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Expedia Group
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 |
18 | import React from 'react';
19 | import {shallow} from 'enzyme';
20 | import {expect} from 'chai';
21 |
22 | import SearchInsights from '../../../../../src/components/universalSearch/tabs/serviceInsights';
23 |
24 | const stubLocation = {
25 | search: ''
26 | };
27 |
28 | const stubHistory = {
29 | location: {
30 | search: ''
31 | },
32 | push: (location) => {
33 | stubLocation.search = location.search;
34 | }
35 | };
36 |
37 | const stubStore = {};
38 |
39 | describe('', () => {
40 | it('should render the serviceInsights panel', (done) => {
41 | const wrapper = shallow();
42 | setTimeout(() => {
43 | expect(wrapper.find('section')).to.have.length(1);
44 | expect(!!wrapper.state('ServiceInsightsView')).to.equal(true);
45 | done();
46 | }, 50);
47 | });
48 | });
49 |
--------------------------------------------------------------------------------
/test/src/main.spec.jsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | import React from 'react';
19 | import {shallow} from 'enzyme';
20 | import {expect} from 'chai';
21 | import Main from '../../src/main';
22 |
23 | it('renders correct routes', () => {
24 | const wrapper = shallow();
25 | expect(wrapper.find('.layout')).to.have.length(0);
26 | });
27 |
--------------------------------------------------------------------------------
/test/src/stores/operationStore.spec.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | import { expect } from 'chai';
19 | import axios from 'axios';
20 | import { when } from 'mobx';
21 | import MockAdapter from 'axios-mock-adapter';
22 |
23 |
24 | import {OperationStore} from '../../../src/stores/operationStore';
25 |
26 | describe('OperationStore', () => {
27 | let server = null;
28 | const store = new OperationStore();
29 |
30 | beforeEach(() => {
31 | server = new MockAdapter(axios);
32 | });
33 |
34 | afterEach(() => {
35 | server = null;
36 | });
37 |
38 | it('fetches operations off the api', (done) => {
39 | server.onGet('/api/operations?serviceName=test-service').reply(200, '["test-service"]');
40 |
41 | store.fetchOperations('test-service');
42 |
43 | when(
44 | () => store.operations.length > 0,
45 | () => {
46 | expect(store.operations).to.have.length(2);
47 | done();
48 | });
49 | });
50 | });
51 |
--------------------------------------------------------------------------------
/test/src/stores/serviceStore.spec.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | import { expect } from 'chai';
19 | import axios from 'axios';
20 | import { when } from 'mobx';
21 | import MockAdapter from 'axios-mock-adapter';
22 |
23 |
24 | import {ServiceStore} from '../../../src/stores/serviceStore';
25 |
26 | describe('ServiceStore', () => {
27 | let server = null;
28 | const store = new ServiceStore();
29 |
30 | beforeEach(() => {
31 | server = new MockAdapter(axios);
32 | });
33 |
34 | afterEach(() => {
35 | server = null;
36 | });
37 |
38 | it('fetches services off the api', (done) => {
39 | server.onGet('/api/services').reply(200, '["test-service"]');
40 |
41 | store.fetchServices();
42 |
43 | when(
44 | () => store.services.length > 0,
45 | () => {
46 | expect(store.services).to.have.length(1);
47 | done();
48 | });
49 |
50 | store.fetchServices();
51 | expect(store.services).to.have.length(0);
52 | });
53 | });
54 |
--------------------------------------------------------------------------------
/test/src/utils/timeWindow.spec.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Expedia Group
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 |
18 | import {expect} from 'chai';
19 | import DateTime from 'react-datetime';
20 | import timeWindow from '../../../src/utils/timeWindow';
21 |
22 | describe('timeWindow.isAfterTTL', () => {
23 | const threeDayTTL = 3 * 24 * 60 * 60 * 1000;
24 |
25 | it('should be true when no ttl is defined', () => {
26 | expect(timeWindow.isAfterTTL(DateTime.moment(), 'unknownTTL')).to.equal(true);
27 | });
28 |
29 | it('should be true when the ttl is <= 0', () => {
30 | window.haystackUiConfig.someTTL = 0;
31 | expect(timeWindow.isAfterTTL(DateTime.moment(), 'someTTL')).to.equal(true);
32 | });
33 |
34 | it('should be true when the ttl exists and the date is after it', () => {
35 | window.haystackUiConfig.someTTL = threeDayTTL;
36 | expect(timeWindow.isAfterTTL(DateTime.moment().subtract(2, 'day'), 'someTTL')).to.equal(true);
37 | });
38 |
39 | it('should be false when the ttl exists and the date is before it', () => {
40 | window.haystackUiConfig.someTTL = threeDayTTL;
41 | expect(timeWindow.isAfterTTL(DateTime.moment().subtract(4, 'day'), 'someTTL')).to.equal(false);
42 | });
43 | });
44 |
--------------------------------------------------------------------------------