mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-13 22:25:52 +08:00
Signoz cloud onboarding v1 (#3525)
* Signoz Cloud - Onboarding Flow - Getting Started page * Signoz Cloud - Onboarding Flow - Java lang setup flow * Signoz Cloud - Onboarding Flow - Wireup other lang docs for APM and create empty base component for other modules * Signoz Cloud - Onboarding Flow - remove try signoz cloud button, Update code background * Signoz Cloud - Onboarding Flow - Wire up all docs and modules * Signoz Cloud - Onboarding Flow - Integrate Intercom and other minor fixes * Signoz Cloud - Onboarding Flow - Logs Management - Update Connection Status component * Signoz Cloud - Onboarding Flow - Logs Management - Update light mode styles * Signoz Cloud - Onboarding Flow - Logs Management - Update Logs * Signoz Cloud - Update yarn.lock * Signoz Cloud - Delete Progress Steps component * Signoz Cloud - Poll for connection status, created common Header component * Signoz Cloud - Add polling to check connection status, update components to use common Header component * Signoz Cloud - Render onboarding only if feature flag is enabled * Signoz Cloud - Configure Logs Management Steps * Signoz Cloud - Update intercom snippet and set max width for onboarding flow container to 1440px * Signoz Cloud - Use andD card component for displaying modules * chore: first clean up * Signoz Cloud - Use ONBOARDING and CHAT_SUPPORT FF * Signoz Cloud - Update version check logic and fix minor css issues * fix: feature flag is updated * chore: docusaurus is removed * chore: docusaurus is removed * feat: signoz cloud - fix typecheck errors * feat: signoz cloud - enable chat support based on FF * feat: signoz cloud - fix type errors * feat: signoz cloud - fix type errors * feat: signoz cloud - update webpack config rules --------- Co-authored-by: Palash Gupta <palashgdev@gmail.com>
This commit is contained in:
parent
7209ac0007
commit
c15240abab
@ -30,7 +30,10 @@
|
||||
"@ant-design/colors": "6.0.0",
|
||||
"@ant-design/icons": "4.8.0",
|
||||
"@grafana/data": "^9.5.2",
|
||||
"@mdx-js/loader": "2.3.0",
|
||||
"@mdx-js/react": "2.3.0",
|
||||
"@monaco-editor/react": "^4.3.1",
|
||||
"@uiw/react-md-editor": "3.23.5",
|
||||
"@xstate/react": "^3.0.0",
|
||||
"ansi-to-html": "0.7.2",
|
||||
"antd": "5.0.5",
|
||||
@ -45,6 +48,7 @@
|
||||
"chart.js": "3.9.1",
|
||||
"chartjs-adapter-date-fns": "^2.0.0",
|
||||
"chartjs-plugin-annotation": "^1.4.0",
|
||||
"classnames": "2.3.2",
|
||||
"color": "^4.2.1",
|
||||
"color-alpha": "1.1.3",
|
||||
"cross-env": "^7.0.3",
|
||||
|
1
frontend/public/Logos/cmd-terminal.svg
Normal file
1
frontend/public/Logos/cmd-terminal.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 122.88 103.53" style="enable-background:new 0 0 122.88 103.53" xml:space="preserve"><style type="text/css">.st0{fill-rule:evenodd;clip-rule:evenodd;} .st0{fill:#1668dc;} .st1{fill:#FFFFFF;}</style><g><path class="st0" d="M5.47,0h111.93c3.01,0,5.47,2.46,5.47,5.47v92.58c0,3.01-2.46,5.47-5.47,5.47H5.47 c-3.01,0-5.47-2.46-5.47-5.47V5.47C0,2.46,2.46,0,5.47,0L5.47,0z M31.84,38.55l17.79,18.42l2.14,2.13l-2.12,2.16L31.68,80.31 l-5.07-5l15.85-16.15L26.81,43.6L31.84,38.55L31.84,38.55z M94.1,79.41H54.69v-6.84H94.1V79.41L94.1,79.41z M38.19,9.83 c3.19,0,5.78,2.59,5.78,5.78s-2.59,5.78-5.78,5.78c-3.19,0-5.78-2.59-5.78-5.78S35,9.83,38.19,9.83L38.19,9.83z M18.95,9.83 c3.19,0,5.78,2.59,5.78,5.78s-2.59,5.78-5.78,5.78c-3.19,0-5.78-2.59-5.78-5.78S15.75,9.83,18.95,9.83L18.95,9.83z M7.49,5.41 h107.91c1.15,0,2.09,0.94,2.09,2.09v18.32H5.4V7.5C5.4,6.35,6.34,5.41,7.49,5.41L7.49,5.41z"/></g></svg>
|
After Width: | Height: | Size: 1.0 KiB |
1
frontend/public/Logos/docker.svg
Normal file
1
frontend/public/Logos/docker.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 122.88 88.17" style="enable-background:new 0 0 122.88 88.17" xml:space="preserve"><style type="text/css">.st0{fill:#0091E2;}</style><g><path class="st0" d="M121.68,33.34c-0.34-0.28-3.42-2.62-10.03-2.62c-1.71,0-3.48,0.17-5.19,0.46c-1.25-8.72-8.49-12.94-8.78-13.16 l-1.77-1.03l-1.14,1.65c-1.42,2.22-2.51,4.73-3.13,7.29c-1.2,4.96-0.46,9.63,2.05,13.62c-3.02,1.71-7.92,2.11-8.95,2.17l-80.93,0 c-2.11,0-3.82,1.71-3.82,3.82c-0.11,7.07,1.08,14.13,3.53,20.8c2.79,7.29,6.95,12.71,12.31,16.01c6.04,3.7,15.9,5.81,27.01,5.81 c5.01,0,10.03-0.46,14.99-1.37c6.9-1.25,13.51-3.65,19.6-7.12c5.02-2.91,9.52-6.61,13.34-10.94c6.44-7.24,10.26-15.33,13.05-22.51 c0.4,0,0.74,0,1.14,0c7.01,0,11.34-2.79,13.73-5.19c1.6-1.48,2.79-3.31,3.65-5.36l0.51-1.48L121.68,33.34L121.68,33.34z M71.59,39.38h10.83c0.51,0,0.97-0.4,0.97-0.97v-9.69c0-0.51-0.4-0.97-0.97-0.97l0,0l-10.83,0c-0.51,0-0.97,0.4-0.97,0.97l0,0v9.69 C70.68,38.98,71.08,39.38,71.59,39.38L71.59,39.38z M56.49,11.63h10.83c0.51,0,0.97-0.4,0.97-0.97V0.97c0-0.51-0.46-0.97-0.97-0.97 L56.49,0c-0.51,0-0.97,0.4-0.97,0.97l0,0v9.69C55.52,11.17,55.97,11.63,56.49,11.63L56.49,11.63z M56.49,25.53h10.83 c0.51,0,0.97-0.46,0.97-0.97v-9.69c0-0.51-0.46-0.97-0.97-0.97H56.49c-0.51,0-0.97,0.4-0.97,0.97l0,0v9.69 C55.52,25.08,55.97,25.53,56.49,25.53L56.49,25.53z M41.5,25.53h10.83c0.51,0,0.97-0.46,0.97-0.97v-9.69c0-0.51-0.4-0.97-0.97-0.97 l0,0H41.5c-0.51,0-0.97,0.4-0.97,0.97l0,0v9.69C40.53,25.08,40.93,25.53,41.5,25.53L41.5,25.53z M26.28,25.53h10.83 c0.51,0,0.97-0.46,0.97-0.97v-9.69c0-0.51-0.4-0.97-0.97-0.97l0,0H26.28c-0.51,0-0.97,0.4-0.97,0.97v9.69 C25.37,25.08,25.77,25.53,26.28,25.53L26.28,25.53z M56.49,39.38h10.83c0.51,0,0.97-0.4,0.97-0.97v-9.69c0-0.51-0.4-0.97-0.97-0.97 l0,0l-10.83,0c-0.51,0-0.97,0.4-0.97,0.97l0,0v9.69C55.52,38.98,55.97,39.38,56.49,39.38L56.49,39.38L56.49,39.38z M41.5,39.38 h10.83c0.51,0,0.97-0.4,0.97-0.97l0,0v-9.69c0-0.51-0.4-0.97-0.97-0.97l0,0l-10.83,0c-0.51,0-0.97,0.4-0.97,0.97l0,0v9.69 C40.53,38.98,40.93,39.38,41.5,39.38L41.5,39.38L41.5,39.38z M26.28,39.38h10.83c0.51,0,0.97-0.4,0.97-0.97l0,0v-9.69 c0-0.51-0.4-0.97-0.97-0.97l0,0l-10.83,0c-0.51,0-0.97,0.4-0.97,0.97v9.69C25.37,38.98,25.77,39.38,26.28,39.38L26.28,39.38z M11.35,39.38h10.83c0.51,0,0.97-0.4,0.97-0.97l0,0v-9.69c0-0.51-0.4-0.97-0.97-0.97l0,0l-10.83,0c-0.51,0-0.97,0.4-0.97,0.97l0,0 v9.69C10.44,38.98,10.84,39.38,11.35,39.38L11.35,39.38L11.35,39.38z"/></g></svg>
|
After Width: | Height: | Size: 2.5 KiB |
1
frontend/public/Logos/kubernetes.svg
Normal file
1
frontend/public/Logos/kubernetes.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 5.9 KiB |
1
frontend/public/Logos/node-js.svg
Normal file
1
frontend/public/Logos/node-js.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 109 122.88" style="enable-background:new 0 0 109 122.88" xml:space="preserve"><style type="text/css">.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#689F63;}</style><g><path class="st0" d="M68.43,87.08c-19.7,0-23.83-9.04-23.83-16.63c0-0.72,0.58-1.3,1.3-1.3h5.82c0.64,0,1.18,0.47,1.28,1.1 c0.88,5.93,3.49,8.92,15.41,8.92c9.49,0,13.52-2.14,13.52-7.18c0-2.9-1.15-5.05-15.89-6.49c-12.33-1.22-19.95-3.93-19.95-13.8 c0-9.08,7.66-14.49,20.5-14.49c14.42,0,21.56,5,22.46,15.76c0.03,0.37-0.1,0.73-0.35,1c-0.25,0.26-0.6,0.42-0.96,0.42H81.9 c-0.61,0-1.14-0.43-1.26-1.01c-1.41-6.23-4.81-8.23-14.07-8.23c-10.36,0-11.56,3.61-11.56,6.31c0,3.28,1.42,4.24,15.4,6.09 c13.84,1.84,20.41,4.43,20.41,14.16c0,9.81-8.18,15.43-22.45,15.43L68.43,87.08L68.43,87.08z M54.52,122.88 c-1.65,0-3.28-0.43-4.72-1.26l-15.03-8.9c-2.25-1.26-1.15-1.7-0.41-1.96c2.99-1.05,3.6-1.28,6.8-3.1c0.34-0.19,0.78-0.12,1.12,0.08 l11.55,6.85c0.42,0.23,1.01,0.23,1.4,0l45.03-25.99c0.42-0.24,0.69-0.72,0.69-1.22V35.43c0-0.52-0.27-0.98-0.7-1.24L55.23,8.22 c-0.42-0.25-0.97-0.25-1.39,0l-45,25.97c-0.44,0.25-0.71,0.73-0.71,1.23v51.96c0,0.5,0.27,0.97,0.7,1.21l12.33,7.12 c6.69,3.35,10.79-0.6,10.79-4.56V39.86c0-0.73,0.57-1.3,1.31-1.3l5.7,0c0.71,0,1.3,0.56,1.3,1.3v51.31 c0,8.93-4.87,14.05-13.33,14.05c-2.6,0-4.66,0-10.38-2.82L4.72,95.59C1.8,93.9,0,90.75,0,87.38V35.42c0-3.38,1.8-6.54,4.72-8.21 l45.07-26c2.85-1.61,6.64-1.61,9.47,0l45.02,26.01c2.91,1.68,4.72,4.82,4.72,8.21v51.96c0,3.37-1.81,6.51-4.72,8.21l-45.02,26 c-1.44,0.83-3.08,1.26-4.74,1.26L54.52,122.88L54.52,122.88z M54.52,122.88L54.52,122.88L54.52,122.88L54.52,122.88z"/></g></svg>
|
After Width: | Height: | Size: 1.7 KiB |
1
frontend/public/Logos/software-window.svg
Normal file
1
frontend/public/Logos/software-window.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 122.88 98.18" style="enable-background:new 0 0 122.88 98.18" xml:space="preserve"><style type="text/css">.st0{fill-rule:evenodd;clip-rule:evenodd;} .st0{fill:#1668dc;} .st1{fill:#FFFFFF;}</style><g><path class="st0" d="M3.42,0h116.05c1.88,0,3.41,1.54,3.41,3.41v91.36c0,1.88-1.54,3.41-3.41,3.41l-116.05,0 C1.54,98.18,0,96.65,0,94.77L0,3.41C0,1.53,1.54,0,3.42,0L3.42,0L3.42,0z M25.89,8.19c2.05,0,3.72,1.67,3.72,3.72 c0,2.05-1.67,3.72-3.72,3.72c-2.05,0-3.72-1.67-3.72-3.72C22.17,9.85,23.83,8.19,25.89,8.19L25.89,8.19z M103.07,7.69l2.52,2.77 l2.52-2.77l1.97,1.79l-2.69,2.96l2.69,2.96l-1.97,1.79l-2.52-2.77l-2.52,2.77l-1.97-1.79l2.69-2.96l-2.69-2.96L103.07,7.69 L103.07,7.69z M14.52,8.19c2.05,0,3.72,1.67,3.72,3.72c0,2.05-1.67,3.72-3.72,3.72c-2.05,0-3.72-1.67-3.72-3.72 C10.79,9.85,12.46,8.19,14.52,8.19L14.52,8.19z M37.26,8.19c2.05,0,3.72,1.67,3.72,3.72c0,2.05-1.67,3.72-3.72,3.72 c-2.05,0-3.72-1.67-3.72-3.72C33.54,9.85,35.21,8.19,37.26,8.19L37.26,8.19z M14.05,22.75h93.33c1.77,0,3.22,1.49,3.22,3.22v59.2 c0,1.73-1.49,3.22-3.22,3.22l-93.33,0c-1.73,0-3.22-1.45-3.22-3.22v-59.2C10.84,24.2,12.29,22.75,14.05,22.75L14.05,22.75 L14.05,22.75z"/></g></svg>
|
After Width: | Height: | Size: 1.3 KiB |
9
frontend/public/Logos/syslogs.svg
Normal file
9
frontend/public/Logos/syslogs.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 6.2 KiB |
@ -1,13 +1,13 @@
|
||||
{
|
||||
"SIGN_UP": "SigNoz | Sign Up",
|
||||
"LOGIN": "SigNoz | Login",
|
||||
"GET_STARTED": "SigNoz | Get Started",
|
||||
"SERVICE_METRICS": "SigNoz | Service Metrics",
|
||||
"SERVICE_MAP": "SigNoz | Service Map",
|
||||
"TRACE": "SigNoz | Trace",
|
||||
"TRACE_DETAIL": "SigNoz | Trace Detail",
|
||||
"TRACES_EXPLORER": "SigNoz | Traces Explorer",
|
||||
"SETTINGS": "SigNoz | Settings",
|
||||
"INSTRUMENTATION": "SigNoz | Get Started",
|
||||
"USAGE_EXPLORER": "SigNoz | Usage Explorer",
|
||||
"APPLICATION": "SigNoz | Home",
|
||||
"ALL_DASHBOARD": "SigNoz | All Dashboards",
|
||||
|
@ -3,11 +3,11 @@
|
||||
"LOGIN": "SigNoz | Login",
|
||||
"SERVICE_METRICS": "SigNoz | Service Metrics",
|
||||
"SERVICE_MAP": "SigNoz | Service Map",
|
||||
"GET_STARTED": "SigNoz | Get Started",
|
||||
"TRACE": "SigNoz | Trace",
|
||||
"TRACE_DETAIL": "SigNoz | Trace Detail",
|
||||
"TRACES_EXPLORER": "SigNoz | Traces Explorer",
|
||||
"SETTINGS": "SigNoz | Settings",
|
||||
"INSTRUMENTATION": "SigNoz | Get Started",
|
||||
"USAGE_EXPLORER": "SigNoz | Usage Explorer",
|
||||
"APPLICATION": "SigNoz | Home",
|
||||
"ALL_DASHBOARD": "SigNoz | All Dashboards",
|
||||
|
@ -1,20 +1,72 @@
|
||||
import { ConfigProvider } from 'antd';
|
||||
import NotFound from 'components/NotFound';
|
||||
import Spinner from 'components/Spinner';
|
||||
import { FeatureKeys } from 'constants/features';
|
||||
import ROUTES from 'constants/routes';
|
||||
import AppLayout from 'container/AppLayout';
|
||||
import { useThemeConfig } from 'hooks/useDarkMode';
|
||||
import useGetFeatureFlag from 'hooks/useGetFeatureFlag';
|
||||
import { NotificationProvider } from 'hooks/useNotifications';
|
||||
import { ResourceProvider } from 'hooks/useResourceAttribute';
|
||||
import history from 'lib/history';
|
||||
import { QueryBuilderProvider } from 'providers/QueryBuilder';
|
||||
import { Suspense } from 'react';
|
||||
import { Suspense, useState } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { Route, Router, Switch } from 'react-router-dom';
|
||||
import { Dispatch } from 'redux';
|
||||
import { AppState } from 'store/reducers';
|
||||
import AppActions from 'types/actions';
|
||||
import { UPDATE_FEATURE_FLAG_RESPONSE } from 'types/actions/app';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
|
||||
import PrivateRoute from './Private';
|
||||
import routes from './routes';
|
||||
import defaultRoutes from './routes';
|
||||
|
||||
function App(): JSX.Element {
|
||||
const themeConfig = useThemeConfig();
|
||||
const [routes, setRoutes] = useState(defaultRoutes);
|
||||
const { isLoggedIn: isLoggedInState, user } = useSelector<
|
||||
AppState,
|
||||
AppReducer
|
||||
>((state) => state.app);
|
||||
|
||||
const dispatch = useDispatch<Dispatch<AppActions>>();
|
||||
|
||||
const featureResponse = useGetFeatureFlag((allFlags) => {
|
||||
const isOnboardingEnabled =
|
||||
allFlags.find((flag) => flag.name === FeatureKeys.ONBOARDING)?.active ||
|
||||
false;
|
||||
|
||||
const isChatSupportEnabled =
|
||||
allFlags.find((flag) => flag.name === FeatureKeys.CHAT_SUPPORT)?.active ||
|
||||
false;
|
||||
|
||||
dispatch({
|
||||
type: UPDATE_FEATURE_FLAG_RESPONSE,
|
||||
payload: {
|
||||
featureFlag: allFlags,
|
||||
refetch: featureResponse.refetch,
|
||||
},
|
||||
});
|
||||
|
||||
if (isOnboardingEnabled) {
|
||||
const newRoutes = routes.filter(
|
||||
(route) => route?.key !== ROUTES.GET_STARTED,
|
||||
);
|
||||
|
||||
setRoutes(newRoutes);
|
||||
}
|
||||
|
||||
if (isLoggedInState && isChatSupportEnabled) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
window.Intercom('boot', {
|
||||
app_id: process.env.INTERCOM_APP_ID,
|
||||
email: user?.email || '',
|
||||
name: user?.name || '',
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<ConfigProvider theme={themeConfig}>
|
||||
|
@ -44,6 +44,10 @@ export const GettingStarted = Loadable(
|
||||
() => import(/* webpackChunkName: "GettingStarted" */ 'pages/GettingStarted'),
|
||||
);
|
||||
|
||||
export const Onboarding = Loadable(
|
||||
() => import(/* webpackChunkName: "Onboarding" */ 'pages/OnboardingPage'),
|
||||
);
|
||||
|
||||
export const DashboardPage = Loadable(
|
||||
() => import(/* webpackChunkName: "DashboardPage" */ 'pages/Dashboard'),
|
||||
);
|
||||
|
@ -11,7 +11,6 @@ import {
|
||||
EditAlertChannelsAlerts,
|
||||
EditRulesPage,
|
||||
ErrorDetails,
|
||||
GettingStarted,
|
||||
LicensePage,
|
||||
ListAllALertsPage,
|
||||
LiveLogs,
|
||||
@ -21,6 +20,7 @@ import {
|
||||
LogsIndexToFields,
|
||||
MySettings,
|
||||
NewDashboardPage,
|
||||
Onboarding,
|
||||
OrganizationSettings,
|
||||
PasswordReset,
|
||||
PipelinePage,
|
||||
@ -46,6 +46,13 @@ const routes: AppRoutes[] = [
|
||||
isPrivate: false,
|
||||
key: 'SIGN_UP',
|
||||
},
|
||||
{
|
||||
path: ROUTES.GET_STARTED,
|
||||
exact: true,
|
||||
component: Onboarding,
|
||||
isPrivate: true,
|
||||
key: 'GET_STARTED',
|
||||
},
|
||||
{
|
||||
component: LogsIndexToFields,
|
||||
path: ROUTES.LOGS_INDEX_FIELDS,
|
||||
@ -95,13 +102,6 @@ const routes: AppRoutes[] = [
|
||||
isPrivate: true,
|
||||
key: 'USAGE_EXPLORER',
|
||||
},
|
||||
{
|
||||
path: ROUTES.INSTRUMENTATION,
|
||||
exact: true,
|
||||
component: GettingStarted,
|
||||
isPrivate: true,
|
||||
key: 'INSTRUMENTATION',
|
||||
},
|
||||
{
|
||||
path: ROUTES.ALL_DASHBOARD,
|
||||
exact: true,
|
||||
|
@ -1,24 +1,10 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { PayloadProps } from 'types/api/features/getFeaturesFlags';
|
||||
import { ApiResponse } from 'types/api';
|
||||
import { FeatureFlagProps } from 'types/api/features/getFeaturesFlags';
|
||||
|
||||
const getFeaturesFlags = async (): Promise<
|
||||
SuccessResponse<PayloadProps> | ErrorResponse
|
||||
> => {
|
||||
try {
|
||||
const response = await axios.get(`/featureFlags`);
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: response.data.status,
|
||||
payload: response.data.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
}
|
||||
};
|
||||
const getFeaturesFlags = (): Promise<FeatureFlagProps[]> =>
|
||||
axios
|
||||
.get<ApiResponse<FeatureFlagProps[]>>(`/featureFlags`)
|
||||
.then((response) => response.data.data);
|
||||
|
||||
export default getFeaturesFlags;
|
||||
|
@ -79,7 +79,6 @@ const interceptorRejected = async (
|
||||
|
||||
// when refresh token is expired
|
||||
if (response.status === 401 && response.config.url === '/login') {
|
||||
console.log('logging out ');
|
||||
Logout();
|
||||
}
|
||||
}
|
||||
|
@ -60,5 +60,9 @@ export const Logout = (): void => {
|
||||
},
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
window.Intercom('shutdown');
|
||||
|
||||
history.push(ROUTES.LOGIN);
|
||||
};
|
||||
|
@ -17,4 +17,6 @@ export enum FeatureKeys {
|
||||
DISABLE_UPSELL = 'DISABLE_UPSELL',
|
||||
USE_SPAN_METRICS = 'USE_SPAN_METRICS',
|
||||
OSS = 'OSS',
|
||||
ONBOARDING = 'ONBOARDING',
|
||||
CHAT_SUPPORT = 'CHAT_SUPPORT',
|
||||
}
|
||||
|
@ -11,4 +11,7 @@ export enum LOCALSTORAGE {
|
||||
GRAPH_VISIBILITY_STATES = 'GRAPH_VISIBILITY_STATES',
|
||||
TRACES_LIST_COLUMNS = 'TRACES_LIST_COLUMNS',
|
||||
LOGS_LIST_COLUMNS = 'LOGS_LIST_COLUMNS',
|
||||
LOGGED_IN_USER_NAME = 'LOGGED_IN_USER_NAME',
|
||||
LOGGED_IN_USER_EMAIL = 'LOGGED_IN_USER_EMAIL',
|
||||
CHAT_SUPPORT = 'CHAT_SUPPORT',
|
||||
}
|
||||
|
@ -3,4 +3,5 @@ export const REACT_QUERY_KEY = {
|
||||
GET_QUERY_RANGE: 'GET_QUERY_RANGE',
|
||||
GET_ALL_DASHBOARDS: 'GET_ALL_DASHBOARDS',
|
||||
GET_TRIGGERED_ALERTS: 'GET_TRIGGERED_ALERTS',
|
||||
GET_FEATURES_FLAGS: 'GET_FEATURES_FLAGS',
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ const ROUTES = {
|
||||
TRACE_DETAIL: '/trace/:id',
|
||||
TRACES_EXPLORER: '/traces-explorer',
|
||||
SETTINGS: '/settings',
|
||||
INSTRUMENTATION: '/get-started',
|
||||
GET_STARTED: '/get-started',
|
||||
USAGE_EXPLORER: '/usage-explorer',
|
||||
APPLICATION: '/services',
|
||||
ALL_DASHBOARD: '/dashboard',
|
||||
|
@ -1,7 +1,7 @@
|
||||
import getDynamicConfigs from 'api/dynamicConfigs/getDynamicConfigs';
|
||||
import getFeaturesFlags from 'api/features/getFeatureFlags';
|
||||
import getUserLatestVersion from 'api/user/getLatestVersion';
|
||||
import getUserVersion from 'api/user/getVersion';
|
||||
import ROUTES from 'constants/routes';
|
||||
import Header from 'container/Header';
|
||||
import SideNav from 'container/SideNav';
|
||||
import TopNav from 'container/TopNav';
|
||||
@ -19,7 +19,6 @@ import {
|
||||
UPDATE_CONFIGS,
|
||||
UPDATE_CURRENT_ERROR,
|
||||
UPDATE_CURRENT_VERSION,
|
||||
UPDATE_FEATURE_FLAG_RESPONSE,
|
||||
UPDATE_LATEST_VERSION,
|
||||
UPDATE_LATEST_VERSION_ERROR,
|
||||
} from 'types/actions/app';
|
||||
@ -32,13 +31,13 @@ function AppLayout(props: AppLayoutProps): JSX.Element {
|
||||
const { isLoggedIn, user } = useSelector<AppState, AppReducer>(
|
||||
(state) => state.app,
|
||||
);
|
||||
|
||||
const { pathname } = useLocation();
|
||||
const { t } = useTranslation(['titles']);
|
||||
|
||||
const [
|
||||
getUserVersionResponse,
|
||||
getUserLatestVersionResponse,
|
||||
getFeaturesResponse,
|
||||
getDynamicConfigsResponse,
|
||||
] = useQueries([
|
||||
{
|
||||
@ -51,10 +50,6 @@ function AppLayout(props: AppLayoutProps): JSX.Element {
|
||||
queryKey: ['getUserLatestVersion', user?.accessJwt],
|
||||
enabled: isLoggedIn,
|
||||
},
|
||||
{
|
||||
queryFn: getFeaturesFlags,
|
||||
queryKey: ['getFeatureFlags', user?.accessJwt],
|
||||
},
|
||||
{
|
||||
queryFn: getDynamicConfigs,
|
||||
queryKey: ['getDynamicConfigs', user?.accessJwt],
|
||||
@ -62,10 +57,6 @@ function AppLayout(props: AppLayoutProps): JSX.Element {
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (getFeaturesResponse.status === 'idle') {
|
||||
getFeaturesResponse.refetch();
|
||||
}
|
||||
|
||||
if (getUserLatestVersionResponse.status === 'idle' && isLoggedIn) {
|
||||
getUserLatestVersionResponse.refetch();
|
||||
}
|
||||
@ -73,14 +64,10 @@ function AppLayout(props: AppLayoutProps): JSX.Element {
|
||||
if (getUserVersionResponse.status === 'idle' && isLoggedIn) {
|
||||
getUserVersionResponse.refetch();
|
||||
}
|
||||
if (getFeaturesResponse.status === 'idle') {
|
||||
getFeaturesResponse.refetch();
|
||||
}
|
||||
if (getDynamicConfigsResponse.status === 'idle') {
|
||||
getDynamicConfigsResponse.refetch();
|
||||
}
|
||||
}, [
|
||||
getFeaturesResponse,
|
||||
getUserLatestVersionResponse,
|
||||
getUserVersionResponse,
|
||||
isLoggedIn,
|
||||
@ -194,42 +181,17 @@ function AppLayout(props: AppLayoutProps): JSX.Element {
|
||||
getUserLatestVersionResponse.isFetched,
|
||||
getUserVersionResponse.isFetched,
|
||||
getUserLatestVersionResponse.isSuccess,
|
||||
getFeaturesResponse.isFetched,
|
||||
getFeaturesResponse.isSuccess,
|
||||
getFeaturesResponse.data,
|
||||
getDynamicConfigsResponse.data,
|
||||
getDynamicConfigsResponse.isFetched,
|
||||
getDynamicConfigsResponse.isSuccess,
|
||||
notifications,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
getFeaturesResponse.isFetched &&
|
||||
getFeaturesResponse.isSuccess &&
|
||||
getFeaturesResponse.data &&
|
||||
getFeaturesResponse.data.payload
|
||||
) {
|
||||
dispatch({
|
||||
type: UPDATE_FEATURE_FLAG_RESPONSE,
|
||||
payload: {
|
||||
featureFlag: getFeaturesResponse.data.payload,
|
||||
refetch: getFeaturesResponse.refetch,
|
||||
},
|
||||
});
|
||||
}
|
||||
}, [
|
||||
dispatch,
|
||||
getFeaturesResponse.data,
|
||||
getFeaturesResponse.isFetched,
|
||||
getFeaturesResponse.isSuccess,
|
||||
getFeaturesResponse.refetch,
|
||||
]);
|
||||
|
||||
const isToDisplayLayout = isLoggedIn;
|
||||
|
||||
const routeKey = useMemo(() => getRouteKey(pathname), [pathname]);
|
||||
const pageTitle = t(routeKey);
|
||||
const renderFullScreen = pathname === ROUTES.GET_STARTED;
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
@ -239,10 +201,10 @@ function AppLayout(props: AppLayoutProps): JSX.Element {
|
||||
|
||||
{isToDisplayLayout && <Header />}
|
||||
<Layout>
|
||||
{isToDisplayLayout && <SideNav />}
|
||||
{isToDisplayLayout && !renderFullScreen && <SideNav />}
|
||||
<LayoutContent>
|
||||
<ChildrenContainer>
|
||||
{isToDisplayLayout && <TopNav />}
|
||||
{isToDisplayLayout && !renderFullScreen && <TopNav />}
|
||||
{children}
|
||||
</ChildrenContainer>
|
||||
</LayoutContent>
|
||||
|
@ -123,7 +123,6 @@ function HeaderContainer(): JSX.Element {
|
||||
Try Signoz Cloud
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<Config frontendId="tooltip" />
|
||||
|
||||
<ToggleButton
|
||||
|
@ -136,6 +136,8 @@ export function OptionsValueResolution(
|
||||
options: uniqWith(
|
||||
map(
|
||||
flattenDeep(
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
map(searchData, (searchItem) => searchItem.data.tags).filter(Boolean),
|
||||
),
|
||||
(tag) => ({ name: tag }),
|
||||
|
@ -1,9 +1,13 @@
|
||||
import { Button, Form, Input, Space, Tooltip, Typography } from 'antd';
|
||||
import setLocalStorageApi from 'api/browser/localstorage/set';
|
||||
import getUserVersion from 'api/user/getVersion';
|
||||
import loginApi from 'api/user/login';
|
||||
import loginPrecheckApi from 'api/user/loginPrecheck';
|
||||
import afterLogin from 'AppRoutes/utils';
|
||||
import { FeatureKeys } from 'constants/features';
|
||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import ROUTES from 'constants/routes';
|
||||
import useFeatureFlag from 'hooks/useFeatureFlag';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
import history from 'lib/history';
|
||||
import { useEffect, useState } from 'react';
|
||||
@ -38,6 +42,9 @@ function Login({
|
||||
const { t } = useTranslation(['login']);
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const { user } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
const isChatSupportEnabled: boolean | undefined = useFeatureFlag(
|
||||
FeatureKeys.CHAT_SUPPORT,
|
||||
)?.active;
|
||||
|
||||
const [precheckResult, setPrecheckResult] = useState<PrecheckResultType>({
|
||||
sso: false,
|
||||
@ -158,11 +165,21 @@ function Login({
|
||||
password,
|
||||
});
|
||||
if (response.statusCode === 200) {
|
||||
await afterLogin(
|
||||
const user = await afterLogin(
|
||||
response.payload.userId,
|
||||
response.payload.accessJwt,
|
||||
response.payload.refreshJwt,
|
||||
);
|
||||
|
||||
if (user) {
|
||||
setLocalStorageApi(LOCALSTORAGE.LOGGED_IN_USER_NAME, user.payload?.name);
|
||||
setLocalStorageApi(LOCALSTORAGE.LOGGED_IN_USER_EMAIL, user.payload?.email);
|
||||
setLocalStorageApi(
|
||||
LOCALSTORAGE.CHAT_SUPPORT,
|
||||
(isChatSupportEnabled || '').toString(),
|
||||
);
|
||||
}
|
||||
|
||||
history.push(ROUTES.APPLICATION);
|
||||
} else {
|
||||
notifications.error({
|
||||
|
144
frontend/src/container/OnboardingContainer/APM/APM.styles.scss
Normal file
144
frontend/src/container/OnboardingContainer/APM/APM.styles.scss
Normal file
@ -0,0 +1,144 @@
|
||||
.apm-module-container {
|
||||
padding: 48px 0;
|
||||
|
||||
.header {
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 14px;
|
||||
font-weight: 300;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.supported-languages-container {
|
||||
display: flex;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.supported-language {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 300px;
|
||||
height: 120px;
|
||||
background: #1d1d1d;
|
||||
border: 1px solid #424242;
|
||||
border-radius: 3px;
|
||||
color: #424242;
|
||||
cursor: pointer;
|
||||
|
||||
&.selected {
|
||||
background-color: #111a2c;
|
||||
border: 0.5px solid #3c89e8;
|
||||
}
|
||||
}
|
||||
|
||||
.supported-langauge-img {
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.selected-langauage-setup-instructions {
|
||||
padding: 24px 0;
|
||||
}
|
||||
|
||||
div[class*='-setup-instructions-container'] {
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
margin: 16px 0;
|
||||
|
||||
img {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 18px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #e5e7eb;
|
||||
gap: 16px;
|
||||
margin: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 14px;
|
||||
margin-bottom: 8px;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: #292d3e;
|
||||
padding: 8px;
|
||||
overflow: auto;
|
||||
border-radius: 3px;
|
||||
|
||||
code {
|
||||
overflow: auto;
|
||||
text-wrap: wrap;
|
||||
}
|
||||
}
|
||||
|
||||
.content-container {
|
||||
padding: 24px;
|
||||
margin: 16px 0;
|
||||
background: rgba(29, 29, 29, 1);
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.detailed-docs-link {
|
||||
display: flex;
|
||||
margin: 12px;
|
||||
font-size: 12px;
|
||||
|
||||
a {
|
||||
padding-left: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.form-container {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
width: 100%;
|
||||
gap: 16px;
|
||||
|
||||
& .ant-form-item {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
$lightModeFontColor: rgb(29, 29, 29);
|
||||
|
||||
.lightMode {
|
||||
.apm-module-container {
|
||||
.header {
|
||||
color: $lightModeFontColor;
|
||||
}
|
||||
|
||||
div[class*='-setup-instructions-container'] {
|
||||
.header {
|
||||
h1 {
|
||||
color: $lightModeFontColor;
|
||||
}
|
||||
}
|
||||
|
||||
.framework-selector {
|
||||
.label {
|
||||
color: $lightModeFontColor;
|
||||
}
|
||||
}
|
||||
|
||||
.service-name-container {
|
||||
.label {
|
||||
color: $lightModeFontColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
95
frontend/src/container/OnboardingContainer/APM/APM.tsx
Normal file
95
frontend/src/container/OnboardingContainer/APM/APM.tsx
Normal file
@ -0,0 +1,95 @@
|
||||
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
||||
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
||||
import './APM.styles.scss';
|
||||
|
||||
import cx from 'classnames';
|
||||
import { useState } from 'react';
|
||||
|
||||
import GoLang from './GoLang/GoLang';
|
||||
import Java from './Java/Java';
|
||||
import Javascript from './Javascript/Javascript';
|
||||
import Python from './Python/Python';
|
||||
|
||||
const supportedLanguages = [
|
||||
{
|
||||
name: 'java',
|
||||
imgURL: `Logos/java.png`,
|
||||
},
|
||||
{
|
||||
name: 'python',
|
||||
imgURL: `Logos/java.png`,
|
||||
},
|
||||
{
|
||||
name: 'javascript',
|
||||
imgURL: `Logos/java.png`,
|
||||
},
|
||||
{
|
||||
name: 'go',
|
||||
imgURL: `Logos/java.png`,
|
||||
},
|
||||
];
|
||||
|
||||
export default function APM({
|
||||
activeStep,
|
||||
}: {
|
||||
activeStep: number;
|
||||
}): JSX.Element {
|
||||
const [selectedLanguage, setSelectedLanguage] = useState('java');
|
||||
|
||||
const renderSelectedLanguageSetupInstructions = (): JSX.Element => {
|
||||
switch (selectedLanguage) {
|
||||
case 'java':
|
||||
return <Java activeStep={activeStep} />;
|
||||
case 'python':
|
||||
return <Python activeStep={activeStep} />;
|
||||
case 'javascript':
|
||||
return <Javascript activeStep={activeStep} />;
|
||||
case 'go':
|
||||
return <GoLang activeStep={activeStep} />;
|
||||
default:
|
||||
return <> </>;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="apm-module-container">
|
||||
{activeStep === 2 && (
|
||||
<>
|
||||
<div className="header">
|
||||
<h1>
|
||||
Get Started to instrument your applications and sending data to SigNoz
|
||||
</h1>
|
||||
<h4> Select the data source </h4>
|
||||
</div>
|
||||
|
||||
<div className="supported-languages-container">
|
||||
{supportedLanguages.map((supportedLanguage) => (
|
||||
<div
|
||||
className={cx(
|
||||
'supported-language',
|
||||
selectedLanguage === supportedLanguage.name ? 'selected' : '',
|
||||
)}
|
||||
key={supportedLanguage.name}
|
||||
onClick={(): void => setSelectedLanguage(supportedLanguage.name)}
|
||||
>
|
||||
<img
|
||||
className={cx('supported-langauge-img')}
|
||||
src={`/Logos/${supportedLanguage.name}.png`}
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
{selectedLanguage && (
|
||||
<div
|
||||
className={cx('selected-langauage-setup-instructions', selectedLanguage)}
|
||||
>
|
||||
{renderSelectedLanguageSetupInstructions()}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
import './GoLang.styles.scss';
|
||||
|
||||
import { MDXProvider } from '@mdx-js/react';
|
||||
import { Form, Input } from 'antd';
|
||||
import Header from 'container/OnboardingContainer/common/Header/Header';
|
||||
|
||||
import ConnectionStatus from '../common/ConnectionStatus/ConnectionStatus';
|
||||
import GoLangDocs from './goLang.md';
|
||||
|
||||
export default function GoLang({
|
||||
activeStep,
|
||||
}: {
|
||||
activeStep: number;
|
||||
}): JSX.Element {
|
||||
const [form] = Form.useForm();
|
||||
|
||||
return (
|
||||
<>
|
||||
{activeStep === 2 && (
|
||||
<div className="golang-setup-instructions-container">
|
||||
<Header
|
||||
entity="go"
|
||||
heading="Go OpenTelemetry Instrumentation"
|
||||
imgURL="/Logos/go.png"
|
||||
docsURL="https://signoz.io/docs/instrumentation/golang/"
|
||||
imgClassName="supported-language-img"
|
||||
/>
|
||||
|
||||
<div className="form-container">
|
||||
<div className="service-name-container">
|
||||
<div className="label"> Service Name </div>
|
||||
|
||||
<Form form={form} name="service-name" style={{ minWidth: '300px' }}>
|
||||
<Form.Item
|
||||
hasFeedback
|
||||
name="Service Name"
|
||||
rules={[{ required: true }]}
|
||||
validateTrigger="onBlur"
|
||||
>
|
||||
<Input autoFocus />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="content-container">
|
||||
<MDXProvider>
|
||||
<GoLangDocs />
|
||||
</MDXProvider>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{activeStep === 3 && (
|
||||
<ConnectionStatus
|
||||
serviceName={form.getFieldValue('Service Name')}
|
||||
framework="go"
|
||||
language="go"
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
412
frontend/src/container/OnboardingContainer/APM/GoLang/goLang.md
Normal file
412
frontend/src/container/OnboardingContainer/APM/GoLang/goLang.md
Normal file
@ -0,0 +1,412 @@
|
||||
## Send Traces to SigNoz Cloud
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="vm" label="VM" default>
|
||||
|
||||
From VMs, there are two ways to send data to SigNoz Cloud.
|
||||
|
||||
- [Send traces directly to SigNoz Cloud](#send-traces-directly-to-signoz-cloud)
|
||||
- [Send traces via OTel Collector binary](#send-traces-via-otel-collector-binary) (recommended)
|
||||
|
||||
#### **Send traces directly to SigNoz Cloud**
|
||||
|
||||
1. **Install Dependencies**<br></br>
|
||||
Dependencies related to OpenTelemetry exporter and SDK have to be installed first. Note that we are assuming you are using `gin` request router. If you are using other request routers, check out the [corresponding package](#request-routers).
|
||||
|
||||
Run the below commands after navigating to the application source folder:
|
||||
|
||||
```bash
|
||||
go get go.opentelemetry.io/otel \
|
||||
go.opentelemetry.io/otel/trace \
|
||||
go.opentelemetry.io/otel/sdk \
|
||||
go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin \
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace \
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc
|
||||
```
|
||||
|
||||
2. **Declare environment variables for configuring OpenTelemetry**<br></br>
|
||||
Declare the following global variables in `main.go` which we will use to configure OpenTelemetry:
|
||||
|
||||
```bash
|
||||
var (
|
||||
serviceName = os.Getenv("SERVICE_NAME")
|
||||
collectorURL = os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT")
|
||||
insecure = os.Getenv("INSECURE_MODE")
|
||||
)
|
||||
```
|
||||
|
||||
3. **Instrument your Go application with OpenTelemetry**<br></br>
|
||||
To configure your application to send data we will need a function to initialize OpenTelemetry. Add the following snippet of code in your `main.go` file.
|
||||
|
||||
```go
|
||||
|
||||
import (
|
||||
.....
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
|
||||
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
||||
)
|
||||
|
||||
func initTracer() func(context.Context) error {
|
||||
|
||||
var secureOption otlptracegrpc.Option
|
||||
|
||||
if strings.ToLower(insecure) == "false" || insecure == "0" || strings.ToLower(insecure) == "f" {
|
||||
secureOption = otlptracegrpc.WithTLSCredentials(credentials.NewClientTLSFromCert(nil, ""))
|
||||
} else {
|
||||
secureOption = otlptracegrpc.WithInsecure()
|
||||
}
|
||||
|
||||
exporter, err := otlptrace.New(
|
||||
context.Background(),
|
||||
otlptracegrpc.NewClient(
|
||||
secureOption,
|
||||
otlptracegrpc.WithEndpoint(collectorURL),
|
||||
),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create exporter: %v", err)
|
||||
}
|
||||
resources, err := resource.New(
|
||||
context.Background(),
|
||||
resource.WithAttributes(
|
||||
attribute.String("service.name", serviceName),
|
||||
attribute.String("library.language", "go"),
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not set resources: %v", err)
|
||||
}
|
||||
|
||||
otel.SetTracerProvider(
|
||||
sdktrace.NewTracerProvider(
|
||||
sdktrace.WithSampler(sdktrace.AlwaysSample()),
|
||||
sdktrace.WithBatcher(exporter),
|
||||
sdktrace.WithResource(resources),
|
||||
),
|
||||
)
|
||||
return exporter.Shutdown
|
||||
}
|
||||
```
|
||||
|
||||
4. **Initialize the tracer in main.go**<br></br>
|
||||
Modify the main function to initialise the tracer in `main.go`. Initiate the tracer at the very beginning of our main function.
|
||||
```go
|
||||
func main() {
|
||||
cleanup := initTracer()
|
||||
defer cleanup(context.Background())
|
||||
|
||||
......
|
||||
}
|
||||
```
|
||||
5. **Add the OpenTelemetry Gin middleware**<br></br>
|
||||
Configure Gin to use the middleware by adding the following lines in `main.go`.
|
||||
|
||||
```go
|
||||
import (
|
||||
....
|
||||
"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
|
||||
)
|
||||
|
||||
func main() {
|
||||
......
|
||||
r := gin.Default()
|
||||
r.Use(otelgin.Middleware(serviceName))
|
||||
......
|
||||
}
|
||||
```
|
||||
|
||||
6. **Set environment variables and run your Go Gin application**<br></br>
|
||||
The run command must have some environment variables to send data to SigNoz cloud. The run command:
|
||||
|
||||
```bash
|
||||
SERVICE_NAME=goApp INSECURE_MODE=false OTEL_EXPORTER_OTLP_HEADERS=signoz-access-token=<SIGNOZ-INGESTION-TOKEN> OTEL_EXPORTER_OTLP_ENDPOINT=ingest.{region}.signoz.cloud:443 go run main.go
|
||||
```
|
||||
|
||||
We can replace the placeholders based on our environment.
|
||||
|
||||
`SERVICE_NAME`: goGinApp (you can name it whatever you want)
|
||||
|
||||
`OTEL_EXPORTER_OTLP_HEADERS`: `signoz-access-token=<SIGNOZ-INGESTION-TOKEN>`. Update `<SIGNOZ-INGESTION-TOKEN>` with the ingestion token provided by SigNoz
|
||||
|
||||
`OTEL_EXPORTER_OTLP_ENDPOINT`: ingest.{region}.signoz.cloud:443. Depending on the choice of your region for SigNoz cloud, the ingest endpoint will vary according to this table.
|
||||
|
||||
| Region | Endpoint |
|
||||
| ------ | -------------------------- |
|
||||
| US | ingest.us.signoz.cloud:443 |
|
||||
| IN | ingest.in.signoz.cloud:443 |
|
||||
| EU | ingest.eu.signoz.cloud:443 |
|
||||
|
||||
---
|
||||
|
||||
#### **Send traces via OTel Collector binary**
|
||||
|
||||
OTel Collector binary helps to collect logs, hostmetrics, resource and infra attributes. It is recommended to install Otel Collector binary to collect and send traces to SigNoz cloud. You can correlate signals and have rich contextual data through this way.
|
||||
|
||||
You can find instructions to install OTel Collector binary [here](https://signoz.io/docs/tutorial/opentelemetry-binary-usage-in-virtual-machine/) in your VM. Once you are done setting up your OTel Collector binary, you can follow the below steps for instrumenting your Golang application.
|
||||
|
||||
1. **Install Dependencies**<br></br>
|
||||
Dependencies related to OpenTelemetry exporter and SDK have to be installed first. Note that we are assuming you are using `gin` request router. If you are using other request routers, check out the [corresponding package](#request-routers).
|
||||
|
||||
Run the below commands after navigating to the application source folder:
|
||||
|
||||
```bash
|
||||
go get go.opentelemetry.io/otel \
|
||||
go.opentelemetry.io/otel/trace \
|
||||
go.opentelemetry.io/otel/sdk \
|
||||
go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin \
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace \
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc
|
||||
```
|
||||
|
||||
2. **Declare environment variables for configuring OpenTelemetry**<br></br>
|
||||
Declare the following global variables in `main.go` which we will use to configure OpenTelemetry:
|
||||
|
||||
```go
|
||||
var (
|
||||
serviceName = os.Getenv("SERVICE_NAME")
|
||||
collectorURL = os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT")
|
||||
insecure = os.Getenv("INSECURE_MODE")
|
||||
)
|
||||
```
|
||||
|
||||
3. **Instrument your Go application with OpenTelemetry**<br></br>
|
||||
To configure your application to send data we will need a function to initialize OpenTelemetry. Add the following snippet of code in your `main.go` file.
|
||||
|
||||
```go
|
||||
|
||||
import (
|
||||
.....
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
|
||||
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
||||
)
|
||||
|
||||
func initTracer() func(context.Context) error {
|
||||
|
||||
var secureOption otlptracegrpc.Option
|
||||
|
||||
if strings.ToLower(insecure) == "false" || insecure == "0" || strings.ToLower(insecure) == "f" {
|
||||
secureOption = otlptracegrpc.WithTLSCredentials(credentials.NewClientTLSFromCert(nil, ""))
|
||||
} else {
|
||||
secureOption = otlptracegrpc.WithInsecure()
|
||||
}
|
||||
|
||||
exporter, err := otlptrace.New(
|
||||
context.Background(),
|
||||
otlptracegrpc.NewClient(
|
||||
secureOption,
|
||||
otlptracegrpc.WithEndpoint(collectorURL),
|
||||
),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create exporter: %v", err)
|
||||
}
|
||||
resources, err := resource.New(
|
||||
context.Background(),
|
||||
resource.WithAttributes(
|
||||
attribute.String("service.name", serviceName),
|
||||
attribute.String("library.language", "go"),
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not set resources: %v", err)
|
||||
}
|
||||
|
||||
otel.SetTracerProvider(
|
||||
sdktrace.NewTracerProvider(
|
||||
sdktrace.WithSampler(sdktrace.AlwaysSample()),
|
||||
sdktrace.WithBatcher(exporter),
|
||||
sdktrace.WithResource(resources),
|
||||
),
|
||||
)
|
||||
return exporter.Shutdown
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
4. **Initialize the tracer in main.go**<br></br>
|
||||
Modify the main function to initialise the tracer in `main.go`. Initiate the tracer at the very beginning of our main function.
|
||||
```go
|
||||
func main() {
|
||||
cleanup := initTracer()
|
||||
defer cleanup(context.Background())
|
||||
|
||||
......
|
||||
}
|
||||
```
|
||||
5. **Add the OpenTelemetry Gin middleware**<br></br>
|
||||
Configure Gin to use the middleware by adding the following lines in `main.go`.
|
||||
```go
|
||||
import (
|
||||
....
|
||||
"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
|
||||
)
|
||||
|
||||
func main() {
|
||||
......
|
||||
r := gin.Default()
|
||||
r.Use(otelgin.Middleware(serviceName))
|
||||
......
|
||||
}
|
||||
```
|
||||
6. **Set environment variables and run your Go Gin application**<br></br>
|
||||
The run command must have some environment variables to send data to SigNoz. The run command:
|
||||
|
||||
```bash
|
||||
SERVICE_NAME=goGinApp INSECURE_MODE=true OTEL_EXPORTER_OTLP_ENDPOINT=localhost:4317 go run main.go
|
||||
```
|
||||
|
||||
If you want to update your `service_name`, you can modify the `SERVICE_NAME` variable.<br></br>
|
||||
`SERVICE_NAME`: goGinApp (you can name it whatever you want)
|
||||
|
||||
7. You can validate if your application is sending traces to SigNoz cloud by following the instructions [here](#validating-instrumentation-by-checking-for-traces).
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem value="k8s" label="Kubernetes">
|
||||
|
||||
For Golang application deployed on Kubernetes, you need to install OTel Collector agent in your k8s infra to collect and send traces to SigNoz Cloud. You can find the instructions to install OTel Collector agent [here](/docs/tutorial/kubernetes-infra-metrics/).
|
||||
|
||||
Once you have set up OTel Collector agent, you can proceed with OpenTelemetry Golang instrumentation by following the below steps:
|
||||
|
||||
1. **Install Dependencies**<br></br>
|
||||
Dependencies related to OpenTelemetry exporter and SDK have to be installed first. Note that we are assuming you are using `gin` request router. If you are using other request routers, check out the [corresponding package](#request-routers).
|
||||
|
||||
Run the below commands after navigating to the application source folder:
|
||||
|
||||
```bash
|
||||
go get go.opentelemetry.io/otel \
|
||||
go.opentelemetry.io/otel/trace \
|
||||
go.opentelemetry.io/otel/sdk \
|
||||
go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin \
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace \
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc
|
||||
```
|
||||
|
||||
2. **Declare environment variables for configuring OpenTelemetry**<br></br>
|
||||
Declare the following global variables in `main.go` which we will use to configure OpenTelemetry:
|
||||
|
||||
```go
|
||||
var (
|
||||
serviceName = os.Getenv("SERVICE_NAME")
|
||||
collectorURL = os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT")
|
||||
insecure = os.Getenv("INSECURE_MODE")
|
||||
)
|
||||
```
|
||||
|
||||
3. **Instrument your Go application with OpenTelemetry**<br></br>
|
||||
To configure your application to send data we will need a function to initialize OpenTelemetry. Add the following snippet of code in your `main.go` file.
|
||||
|
||||
```go
|
||||
|
||||
import (
|
||||
.....
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
|
||||
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
||||
)
|
||||
|
||||
func initTracer() func(context.Context) error {
|
||||
|
||||
var secureOption otlptracegrpc.Option
|
||||
|
||||
if strings.ToLower(insecure) == "false" || insecure == "0" || strings.ToLower(insecure) == "f" {
|
||||
secureOption = otlptracegrpc.WithTLSCredentials(credentials.NewClientTLSFromCert(nil, ""))
|
||||
} else {
|
||||
secureOption = otlptracegrpc.WithInsecure()
|
||||
}
|
||||
|
||||
exporter, err := otlptrace.New(
|
||||
context.Background(),
|
||||
otlptracegrpc.NewClient(
|
||||
secureOption,
|
||||
otlptracegrpc.WithEndpoint(collectorURL),
|
||||
),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create exporter: %v", err)
|
||||
}
|
||||
resources, err := resource.New(
|
||||
context.Background(),
|
||||
resource.WithAttributes(
|
||||
attribute.String("service.name", serviceName),
|
||||
attribute.String("library.language", "go"),
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not set resources: %v", err)
|
||||
}
|
||||
|
||||
otel.SetTracerProvider(
|
||||
sdktrace.NewTracerProvider(
|
||||
sdktrace.WithSampler(sdktrace.AlwaysSample()),
|
||||
sdktrace.WithBatcher(exporter),
|
||||
sdktrace.WithResource(resources),
|
||||
),
|
||||
)
|
||||
return exporter.Shutdown
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
4. **Initialize the tracer in main.go**<br></br>
|
||||
Modify the main function to initialise the tracer in `main.go`. Initiate the tracer at the very beginning of our main function.
|
||||
```go
|
||||
func main() {
|
||||
cleanup := initTracer()
|
||||
defer cleanup(context.Background())
|
||||
|
||||
......
|
||||
}
|
||||
```
|
||||
5. **Add the OpenTelemetry Gin middleware**<br></br>
|
||||
Configure Gin to use the middleware by adding the following lines in `main.go`.
|
||||
```go
|
||||
import (
|
||||
....
|
||||
"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
|
||||
)
|
||||
|
||||
func main() {
|
||||
......
|
||||
r := gin.Default()
|
||||
r.Use(otelgin.Middleware(serviceName))
|
||||
......
|
||||
}
|
||||
```
|
||||
6. **Set environment variables and run your Go Gin application**<br></br>
|
||||
The run command must have some environment variables to send data to SigNoz. The run command:
|
||||
|
||||
```bash
|
||||
SERVICE_NAME=goGinApp INSECURE_MODE=true OTEL_EXPORTER_OTLP_ENDPOINT=localhost:4317 go run main.go
|
||||
```
|
||||
|
||||
If you want to update your `service_name`, you can modify the `SERVICE_NAME` variable.<br></br>
|
||||
`SERVICE_NAME`: goGinApp (you can name it whatever you want)
|
||||
|
||||
7. You can validate if your application is sending traces to SigNoz cloud by following the instructions [here](#validating-instrumentation-by-checking-for-traces).
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
@ -0,0 +1,10 @@
|
||||
.form-container {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
width: 100%;
|
||||
gap: 16px;
|
||||
|
||||
& .ant-form-item {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
}
|
115
frontend/src/container/OnboardingContainer/APM/Java/Java.tsx
Normal file
115
frontend/src/container/OnboardingContainer/APM/Java/Java.tsx
Normal file
@ -0,0 +1,115 @@
|
||||
import './Java.styles.scss';
|
||||
|
||||
import { MDXProvider } from '@mdx-js/react';
|
||||
import { Form, Input, Select } from 'antd';
|
||||
import Header from 'container/OnboardingContainer/common/Header/Header';
|
||||
import { useState } from 'react';
|
||||
|
||||
import ConnectionStatus from '../common/ConnectionStatus/ConnectionStatus';
|
||||
import JavaDocs from './md-docs/java.md';
|
||||
import JbossDocs from './md-docs/jboss.md';
|
||||
import SprintBootDocs from './md-docs/spring_boot.md';
|
||||
import TomcatDocs from './md-docs/tomcat.md';
|
||||
|
||||
enum FrameworksMap {
|
||||
tomcat = 'Tomcat',
|
||||
spring_boot = 'Spring Boot',
|
||||
jboss = 'JBoss',
|
||||
other = 'Others',
|
||||
}
|
||||
|
||||
export default function Java({
|
||||
activeStep,
|
||||
}: {
|
||||
activeStep: number;
|
||||
}): JSX.Element {
|
||||
const [selectedFrameWork, setSelectedFrameWork] = useState('spring_boot');
|
||||
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const renderDocs = (): JSX.Element => {
|
||||
switch (selectedFrameWork) {
|
||||
case 'tomcat':
|
||||
return <TomcatDocs />;
|
||||
case 'spring_boot':
|
||||
return <SprintBootDocs />;
|
||||
case 'jboss':
|
||||
return <JbossDocs />;
|
||||
default:
|
||||
return <JavaDocs />;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{activeStep === 2 && (
|
||||
<div className="java-setup-instructions-container">
|
||||
<Header
|
||||
entity="java"
|
||||
heading="Java OpenTelemetry Instrumentation"
|
||||
imgURL="/Logos/java.png"
|
||||
docsURL="https://signoz.io/docs/instrumentation/java/"
|
||||
imgClassName="supported-language-img"
|
||||
/>
|
||||
|
||||
<div className="form-container">
|
||||
<div className="framework-selector">
|
||||
<div className="label"> Select Framework </div>
|
||||
|
||||
<Select
|
||||
defaultValue="spring_boot"
|
||||
style={{ minWidth: 120 }}
|
||||
placeholder="Select Framework"
|
||||
onChange={(value): void => setSelectedFrameWork(value)}
|
||||
options={[
|
||||
{
|
||||
value: 'spring_boot',
|
||||
label: FrameworksMap.spring_boot,
|
||||
},
|
||||
{
|
||||
value: 'tomcat',
|
||||
label: FrameworksMap.tomcat,
|
||||
},
|
||||
{
|
||||
value: 'jboss',
|
||||
label: FrameworksMap.jboss,
|
||||
},
|
||||
{
|
||||
value: 'other',
|
||||
label: FrameworksMap.other,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="service-name-container">
|
||||
<div className="label"> Service Name </div>
|
||||
|
||||
<Form form={form} name="service-name" style={{ minWidth: '300px' }}>
|
||||
<Form.Item
|
||||
hasFeedback
|
||||
name="Service Name"
|
||||
rules={[{ required: true }]}
|
||||
validateTrigger="onBlur"
|
||||
>
|
||||
<Input autoFocus />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="content-container">
|
||||
<MDXProvider>{renderDocs()}</MDXProvider>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{activeStep === 3 && (
|
||||
<ConnectionStatus
|
||||
serviceName={form.getFieldValue('Service Name')}
|
||||
language="java"
|
||||
framework={(FrameworksMap as any)[selectedFrameWork]}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
## Send Traces to SigNoz Cloud
|
||||
|
||||
OpenTelemetry provides a handy Java JAR agent that can be attached to any Java 8+ application and dynamically injects bytecode to capture telemetry from a number of popular libraries and frameworks.
|
||||
|
||||
Based on your application environment, you can choose the setup below to send traces to SigNoz Cloud.
|
||||
|
||||
From VMs, there are two ways to send data to SigNoz Cloud.
|
||||
|
||||
- [Send traces directly to SigNoz Cloud](#send-traces-directly-to-signoz-cloud)
|
||||
- [Send traces via OTel Collector binary](#send-traces-via-otel-collector-binary) (recommended)
|
||||
|
||||
#### **Send traces directly to SigNoz Cloud**
|
||||
|
||||
OpenTelemetry Java agent can send traces directly to SigNoz Cloud.
|
||||
|
||||
Step 1. Download otel java binary agent
|
||||
|
||||
```bash
|
||||
wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
|
||||
```
|
||||
|
||||
Step 2. Run your application
|
||||
|
||||
```bash
|
||||
OTEL_RESOURCE_ATTRIBUTES=service.name=<app_name> \
|
||||
OTEL_EXPORTER_OTLP_HEADERS="signoz-access-token=SIGNOZ_INGESTION_KEY" \
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT=https://ingest.{region}.signoz.cloud:443 \
|
||||
java -javaagent:$PWD/opentelemetry-javaagent.jar -jar <my-app>.jar
|
||||
```
|
||||
|
||||
- `<app_name>` is the name for your application
|
||||
- `SIGNOZ_INGESTION_KEY` is the API token provided by SigNoz. You can find your ingestion key from SigNoz cloud account details sent on your email.
|
||||
|
||||
Depending on the choice of your region for SigNoz cloud, the ingest endpoint will vary according to this table.
|
||||
|
||||
| Region | Endpoint |
|
||||
| ------ | -------------------------- |
|
||||
| US | ingest.us.signoz.cloud:443 |
|
||||
| IN | ingest.in.signoz.cloud:443 |
|
||||
| EU | ingest.eu.signoz.cloud:443 |
|
||||
|
||||
---
|
||||
|
||||
#### **Send traces via OTel Collector binary**
|
||||
|
||||
OTel Collector binary helps to collect logs, hostmetrics, resource and infra attributes. It is recommended to install Otel Collector binary to collect and send traces to SigNoz cloud. You can correlate signals and have rich contextual data through this way.
|
||||
|
||||
You can find instructions to install OTel Collector binary [here](https://signoz.io/docs/tutorial/opentelemetry-binary-usage-in-virtual-machine/) in your VM. Once you are done setting up your OTel Collector binary, you can follow the below steps for instrumenting your Java application.
|
||||
|
||||
Step 1. Download OTel java binary agent<br></br>
|
||||
|
||||
```bash
|
||||
wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
|
||||
```
|
||||
|
||||
Step 2. Run your application<br></br>
|
||||
|
||||
```bash
|
||||
java -javaagent:$PWD/opentelemetry-javaagent.jar -jar <myapp>.jar
|
||||
```
|
||||
|
||||
- `<myapp>` is the name of your application jar file
|
||||
- In case you download `opentelemetry-javaagent.jar` file in different directory than that of the project, replace `$PWD` with the path of the otel jar file.
|
||||
|
||||
For Java application deployed on Kubernetes, you need to install OTel Collector agent in your k8s infra to collect and send traces to SigNoz Cloud. You can find the instructions to install OTel Collector agent [here](/docs/tutorial/kubernetes-infra-metrics/).
|
||||
|
||||
Once you have set up OTel Collector agent, you can proceed with OpenTelemetry java instrumentation by following the below steps:
|
||||
|
||||
1. Download otel java binary<br></br>
|
||||
|
||||
```bash
|
||||
wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
|
||||
```
|
||||
|
||||
2. Run your application<br></br>
|
||||
|
||||
```bash
|
||||
java -javaagent:$PWD/opentelemetry-javaagent.jar -jar <myapp>.jar
|
||||
```
|
||||
|
||||
- `<myapp>` is the name of your application jar file
|
||||
- In case you download `opentelemetry-javaagent.jar` file in different directory than that of the project, replace `$PWD` with the path of the otel jar file.
|
||||
|
||||
3. Make sure to dockerise your application along with OpenTelemetry instrumentation.
|
||||
|
||||
You can validate if your application is sending traces to SigNoz cloud by following the instructions [here](#validating-instrumentation-by-checking-for-traces).
|
@ -0,0 +1,110 @@
|
||||
## Send traces directly to SigNoz Cloud
|
||||
|
||||
OpenTelemetry Java agent can send traces directly to SigNoz Cloud.
|
||||
|
||||
Step 1. Download otel java binary agent
|
||||
|
||||
```bash
|
||||
wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
|
||||
```
|
||||
|
||||
Step 2. Open the configuration file
|
||||
|
||||
```bash
|
||||
vim /opt/jboss-eap-7.1/bin/standalone.conf
|
||||
```
|
||||
|
||||
Step 3. Update `JAVA_OPTS` environment variable
|
||||
|
||||
Update `JAVA_OPTS` environment variable with configurations required to send data to SigNoz cloud in your configuration file.
|
||||
|
||||
```bash
|
||||
JAVA_OPTS="-javaagent:/path/opentelemetry-javaagent.jar
|
||||
-Dotel.exporter.otlp.endpoint=https://ingest.{region}.signoz.cloud:443
|
||||
-Dotel.exporter.otlp.headers="signoz-access-token=SIGNOZ_INGESTION_KEY"
|
||||
-Dotel.resource.attributes="service.name=<app_name>""
|
||||
```
|
||||
|
||||
You need to replace the following things based on your environment:<br></br>
|
||||
|
||||
- `path` - Update it to the path of your downloaded Java JAR agent.<br></br>
|
||||
- `<app_name>` is the name for your application
|
||||
- `SIGNOZ_INGESTION_KEY` is the API token provided by SigNoz. You can find your ingestion key from SigNoz cloud account details sent on your email.
|
||||
|
||||
Depending on the choice of your region for SigNoz cloud, the ingest endpoint will vary according to this table.
|
||||
|
||||
| Region | Endpoint |
|
||||
| ------ | -------------------------- |
|
||||
| US | ingest.us.signoz.cloud:443 |
|
||||
| IN | ingest.in.signoz.cloud:443 |
|
||||
| EU | ingest.eu.signoz.cloud:443 |
|
||||
|
||||
Step 4. [Optional] Write the output/logs of standalone.sh script to a file nohup.out as a background thread
|
||||
|
||||
```bash
|
||||
/opt/jboss-eap-7.1/bin/standalone.sh > /opt/jboss-eap-7.1/bin/nohup.out &
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### **Send traces via OTel Collector binary**
|
||||
|
||||
OTel Collector binary helps to collect logs, hostmetrics, resource and infra attributes. It is recommended to install Otel Collector binary to collect and send traces to SigNoz cloud. You can correlate signals and have rich contextual data through this way.
|
||||
|
||||
You can find instructions to install OTel Collector binary [here](https://signoz.io/docs/tutorial/opentelemetry-binary-usage-in-virtual-machine/) in your VM. Once you are done setting up your OTel Collector binary, you can follow the below steps for instrumenting your Java application.
|
||||
|
||||
Step 1. Download OTel java binary agent<br></br>
|
||||
|
||||
```bash
|
||||
wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
|
||||
```
|
||||
|
||||
Step 2. Open the configuration file
|
||||
|
||||
```bash
|
||||
vim /opt/jboss-eap-7.1/bin/standalone.conf
|
||||
```
|
||||
|
||||
Step 3. Update `JAVA_OPTS` environment variable
|
||||
|
||||
Update `JAVA_OPTS` environment variable with configurations required to send data to SigNoz cloud in your configuration file.
|
||||
|
||||
```bash
|
||||
JAVA_OPTS="-javaagent:/path/opentelemetry-javaagent.jar"
|
||||
```
|
||||
|
||||
where,
|
||||
|
||||
- `path` - Update it to the path of your downloaded Java JAR agent.<br></br>
|
||||
|
||||
For Java application deployed on Kubernetes, you need to install OTel Collector agent in your k8s infra to collect and send traces to SigNoz Cloud. You can find the instructions to install OTel Collector agent [here](/docs/tutorial/kubernetes-infra-metrics/).
|
||||
|
||||
Once you have set up OTel Collector agent, you can proceed with OpenTelemetry java instrumentation by following the below steps:
|
||||
|
||||
Step 1. Download otel java binary<br></br>
|
||||
|
||||
```bash
|
||||
wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
|
||||
```
|
||||
|
||||
Step 2. Open the configuration file
|
||||
|
||||
```bash
|
||||
vim /opt/jboss-eap-7.1/bin/standalone.conf
|
||||
```
|
||||
|
||||
Step 3. Update `JAVA_OPTS` environment variable
|
||||
|
||||
Update `JAVA_OPTS` environment variable with configurations required to send data to SigNoz cloud in your configuration file.
|
||||
|
||||
```bash
|
||||
JAVA_OPTS="-javaagent:/path/opentelemetry-javaagent.jar"
|
||||
```
|
||||
|
||||
where,
|
||||
|
||||
- `path` - Update it to the path of your downloaded Java JAR agent.<br></br>
|
||||
|
||||
Step 4. Make sure to dockerise your application along with OpenTelemetry instrumentation.
|
||||
|
||||
You can validate if your application is sending traces to SigNoz cloud by following the instructions [here](#validating-instrumentation-by-checking-for-traces).
|
@ -0,0 +1,81 @@
|
||||
## Send traces directly to SigNoz Cloud
|
||||
|
||||
OpenTelemetry Java agent can send traces directly to SigNoz Cloud.
|
||||
|
||||
Step 1. Download otel java binary agent
|
||||
|
||||
```bash
|
||||
wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
|
||||
```
|
||||
|
||||
Step 2. Run your application
|
||||
|
||||
```bash
|
||||
OTEL_RESOURCE_ATTRIBUTES=service.name=<app_name> \
|
||||
OTEL_EXPORTER_OTLP_HEADERS="signoz-access-token=SIGNOZ_INGESTION_KEY" \
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT=https://ingest.{region}.signoz.cloud:443 \
|
||||
java -javaagent:$PWD/opentelemetry-javaagent.jar -jar <my-app>.jar
|
||||
```
|
||||
|
||||
- `<app_name>` is the name for your application
|
||||
- `SIGNOZ_INGESTION_KEY` is the API token provided by SigNoz. You can find your ingestion key from SigNoz cloud account details sent on your email.
|
||||
|
||||
Depending on the choice of your region for SigNoz cloud, the ingest endpoint will vary according to this table.
|
||||
|
||||
| Region | Endpoint |
|
||||
| ------ | -------------------------- |
|
||||
| US | ingest.us.signoz.cloud:443 |
|
||||
| IN | ingest.in.signoz.cloud:443 |
|
||||
| EU | ingest.eu.signoz.cloud:443 |
|
||||
|
||||
---
|
||||
|
||||
#### **Send traces via OTel Collector binary**
|
||||
|
||||
OTel Collector binary helps to collect logs, hostmetrics, resource and infra attributes. It is recommended to install Otel Collector binary to collect and send traces to SigNoz cloud. You can correlate signals and have rich contextual data through this way.
|
||||
|
||||
You can find instructions to install OTel Collector binary [here](https://signoz.io/docs/tutorial/opentelemetry-binary-usage-in-virtual-machine/) in your VM. Once you are done setting up your OTel Collector binary, you can follow the below steps for instrumenting your Java application.
|
||||
|
||||
Step 1. Download OTel java binary agent<br></br>
|
||||
|
||||
```bash
|
||||
wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
|
||||
```
|
||||
|
||||
Step 2. Run your application<br></br>
|
||||
|
||||
```bash
|
||||
java -javaagent:$PWD/opentelemetry-javaagent.jar -jar <myapp>.jar
|
||||
```
|
||||
|
||||
- `<myapp>` is the name of your application jar file
|
||||
- In case you download `opentelemetry-javaagent.jar` file in different directory than that of the project, replace `$PWD` with the path of the otel jar file.
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="k8s" label="Kubernetes">
|
||||
|
||||
For Java application deployed on Kubernetes, you need to install OTel Collector agent in your k8s infra to collect and send traces to SigNoz Cloud. You can find the instructions to install OTel Collector agent [here](/docs/tutorial/kubernetes-infra-metrics/).
|
||||
|
||||
Once you have set up OTel Collector agent, you can proceed with OpenTelemetry java instrumentation by following the below steps:
|
||||
|
||||
1. Download otel java binary<br></br>
|
||||
|
||||
```bash
|
||||
wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
|
||||
```
|
||||
|
||||
2. Run your application<br></br>
|
||||
|
||||
```bash
|
||||
java -javaagent:$PWD/opentelemetry-javaagent.jar -jar <myapp>.jar
|
||||
```
|
||||
|
||||
- `<myapp>` is the name of your application jar file
|
||||
- In case you download `opentelemetry-javaagent.jar` file in different directory than that of the project, replace `$PWD` with the path of the otel jar file.
|
||||
|
||||
3. Make sure to dockerise your application along with OpenTelemetry instrumentation.
|
||||
|
||||
You can validate if your application is sending traces to SigNoz cloud by following the instructions [here](#validating-instrumentation-by-checking-for-traces).
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
@ -0,0 +1,96 @@
|
||||
## Send Traces to SigNoz Cloud
|
||||
|
||||
OpenTelemetry provides a handy Java JAR agent that can be attached to any Java 8+ application and dynamically injects bytecode to capture telemetry from a number of popular libraries and frameworks.
|
||||
|
||||
Based on your application environment, you can choose the setup below to send traces to SigNoz Cloud.
|
||||
|
||||
From VMs, there are two ways to send data to SigNoz Cloud.
|
||||
|
||||
- [Send traces directly to SigNoz Cloud](#send-traces-directly-to-signoz-cloud)
|
||||
- [Send traces via OTel Collector binary](#send-traces-via-otel-collector-binary) (recommended)
|
||||
|
||||
#### **Send traces directly to SigNoz Cloud**
|
||||
|
||||
OpenTelemetry Java agent can send traces directly to SigNoz Cloud.
|
||||
|
||||
Step 1. Download otel java binary agent
|
||||
|
||||
```bash
|
||||
wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
|
||||
```
|
||||
|
||||
Step 2. Enable the instrumentation agent and run your application
|
||||
|
||||
If you run your `.war` package by putting in `webapps` folder, just add `setenv.sh` in your Tomcat `bin` folder.
|
||||
|
||||
This should set these environment variables and start sending telemetry data to SigNoz Cloud.
|
||||
|
||||
```bash
|
||||
export CATALINA_OPTS="$CATALINA_OPTS -javaagent:/path/to/opentelemetry-javaagent.jar"
|
||||
export OTEL_EXPORTER_OTLP_HEADERS="signoz-access-token=SIGNOZ_INGESTION_KEY"
|
||||
export OTEL_EXPORTER_OTLP_ENDPOINT=https://ingest.{region}.signoz.cloud:443
|
||||
export OTEL_RESOURCE_ATTRIBUTES=service.name=<app_name>
|
||||
```
|
||||
|
||||
- `<app_name>` is the name for your application
|
||||
- `SIGNOZ_INGESTION_KEY` is the API token provided by SigNoz. You can find your ingestion key from SigNoz cloud account details sent on your email.
|
||||
|
||||
Depending on the choice of your region for SigNoz cloud, the ingest endpoint will vary according to this table.
|
||||
|
||||
| Region | Endpoint |
|
||||
| ------ | -------------------------- |
|
||||
| US | ingest.us.signoz.cloud:443 |
|
||||
| IN | ingest.in.signoz.cloud:443 |
|
||||
| EU | ingest.eu.signoz.cloud:443 |
|
||||
|
||||
---
|
||||
|
||||
#### **Send traces via OTel Collector binary**
|
||||
|
||||
OTel Collector binary helps to collect logs, hostmetrics, resource and infra attributes. It is recommended to install Otel Collector binary to collect and send traces to SigNoz cloud. You can correlate signals and have rich contextual data through this way.
|
||||
|
||||
You can find instructions to install OTel Collector binary [here](https://signoz.io/docs/tutorial/opentelemetry-binary-usage-in-virtual-machine/) in your VM. Once you are done setting up your OTel Collector binary, you can follow the below steps for instrumenting your Java application.
|
||||
|
||||
Step 1. Download OTel java binary agent<br></br>
|
||||
|
||||
```bash
|
||||
wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
|
||||
```
|
||||
|
||||
Step 2. Enable the instrumentation agent and run your application<br></br>
|
||||
|
||||
If you run your `.war` package by putting in `webapps` folder, just add `setenv.sh` in your Tomcat `bin` folder.
|
||||
|
||||
This should set these environment variables and start sending telemetry data to SigNoz Cloud.
|
||||
|
||||
```bash
|
||||
export CATALINA_OPTS="$CATALINA_OPTS -javaagent:/path/to/opentelemetry-javaagent.jar"
|
||||
```
|
||||
|
||||
- path/to - Update it to the path of your downloaded Java JAR agent.
|
||||
|
||||
For Java application deployed on Kubernetes, you need to install OTel Collector agent in your k8s infra to collect and send traces to SigNoz Cloud. You can find the instructions to install OTel Collector agent [here](/docs/tutorial/kubernetes-infra-metrics/).
|
||||
|
||||
Once you have set up OTel Collector agent, you can proceed with OpenTelemetry java instrumentation by following the below steps:
|
||||
|
||||
1. Download otel java binary<br></br>
|
||||
|
||||
```bash
|
||||
wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
|
||||
```
|
||||
|
||||
2. Enable the instrumentation agent and run your application<br></br>
|
||||
|
||||
If you run your `.war` package by putting in `webapps` folder, just add `setenv.sh` in your Tomcat `bin` folder.
|
||||
|
||||
This should set the environment variable and start sending telemetry data to SigNoz Cloud.
|
||||
|
||||
```bash
|
||||
export CATALINA_OPTS="$CATALINA_OPTS -javaagent:/path/to/opentelemetry-javaagent.jar"
|
||||
```
|
||||
|
||||
- path/to - Update it to the path of your downloaded Java JAR agent.
|
||||
|
||||
3. Make sure to dockerise your application along with OpenTelemetry instrumentation.
|
||||
|
||||
You can validate if your application is sending traces to SigNoz cloud by following the instructions [here](#validating-instrumentation-by-checking-for-traces).
|
@ -0,0 +1,121 @@
|
||||
import './Javascript.styles.scss';
|
||||
|
||||
import { MDXProvider } from '@mdx-js/react';
|
||||
import { Form, Input, Select } from 'antd';
|
||||
import Header from 'container/OnboardingContainer/common/Header/Header';
|
||||
import { useState } from 'react';
|
||||
|
||||
import ConnectionStatus from '../common/ConnectionStatus/ConnectionStatus';
|
||||
import AngularDocs from './md-docs/angular.md';
|
||||
import ExpressDocs from './md-docs/express.md';
|
||||
import JavascriptDocs from './md-docs/javascript.md';
|
||||
import NestJsDocs from './md-docs/nestjs.md';
|
||||
|
||||
const frameworksMap = {
|
||||
express: 'Express',
|
||||
nestjs: 'Nest JS',
|
||||
angular: 'Angular',
|
||||
other: 'Others',
|
||||
};
|
||||
|
||||
export default function Javascript({
|
||||
activeStep,
|
||||
}: {
|
||||
activeStep: number;
|
||||
}): JSX.Element {
|
||||
const [selectedFrameWork, setSelectedFrameWork] = useState('express');
|
||||
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const renderDocs = (): JSX.Element => {
|
||||
switch (selectedFrameWork) {
|
||||
case 'express':
|
||||
return <ExpressDocs />;
|
||||
case 'nestjs':
|
||||
return <NestJsDocs />;
|
||||
case 'angular':
|
||||
return <AngularDocs />;
|
||||
default:
|
||||
return <JavascriptDocs />;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{activeStep === 2 && (
|
||||
<div className="javascript-setup-instructions-container">
|
||||
<Header
|
||||
entity="javascript"
|
||||
heading="Javascript OpenTelemetry Instrumentation"
|
||||
imgURL="/Logos/javascript.png"
|
||||
docsURL="https://signoz.io/docs/instrumentation/javascript/"
|
||||
imgClassName="supported-language-img"
|
||||
/>
|
||||
|
||||
<div className="form-container">
|
||||
<div className="framework-selector">
|
||||
<div className="label"> Select Framework </div>
|
||||
|
||||
<Select
|
||||
defaultValue="express"
|
||||
style={{ minWidth: 120 }}
|
||||
placeholder="Select Framework"
|
||||
onChange={(value): void => setSelectedFrameWork(value)}
|
||||
options={[
|
||||
{
|
||||
value: 'express',
|
||||
label: frameworksMap.express,
|
||||
},
|
||||
{
|
||||
value: 'nestjs',
|
||||
label: frameworksMap.nestjs,
|
||||
},
|
||||
{
|
||||
value: 'angular',
|
||||
label: frameworksMap.angular,
|
||||
},
|
||||
{
|
||||
value: 'other',
|
||||
label: frameworksMap.other,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="service-name-container">
|
||||
<div className="label"> Service Name </div>
|
||||
|
||||
<Form
|
||||
form={form}
|
||||
name="service-name"
|
||||
style={{ minWidth: '300px' }}
|
||||
scrollToFirstError
|
||||
>
|
||||
<Form.Item
|
||||
hasFeedback
|
||||
name="Service Name"
|
||||
rules={[{ required: true }]}
|
||||
validateTrigger="onBlur"
|
||||
requiredMark
|
||||
>
|
||||
<Input autoFocus />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="content-container">
|
||||
<MDXProvider>{renderDocs()}</MDXProvider>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{activeStep === 3 && (
|
||||
<ConnectionStatus
|
||||
serviceName={form.getFieldValue('Service Name')}
|
||||
language="javascript"
|
||||
framework={selectedFrameWork}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
## Instrumenting your Angular App with OpenTelemetry 🛠
|
||||
|
||||
#### Pre-requisites
|
||||
|
||||
Enable CORS in the OTel Receiver. Inside `docker/clickhouse-setup/otel-collector-config.yaml` add the following CORS config. You can view the file at [SigNoz GitHub repo](https://github.com/SigNoz/signoz/blob/develop/deploy/docker/clickhouse-setup/otel-collector-config.yaml).
|
||||
|
||||
```yml
|
||||
http:
|
||||
+ cors:
|
||||
+ allowed_origins:
|
||||
+ - https://netflix.com # URL of your Frontend application
|
||||
```
|
||||
|
||||
> Make sure to restart the container after making the config changes
|
||||
|
||||
Now let's get back to instrumenting our Angular Application. Let's start by installing a couple of dependencies.
|
||||
|
||||
```sh
|
||||
npm i @jufab/opentelemetry-angular-interceptor && npm i @opentelemetry/api @opentelemetry/sdk-trace-web @opentelemetry/sdk-trace-base @opentelemetry/core @opentelemetry/semantic-conventions @opentelemetry/resources @opentelemetry/exporter-trace-otlp-http @opentelemetry/exporter-zipkin @opentelemetry/propagator-b3 @opentelemetry/propagator-jaeger @opentelemetry/context-zone-peer-dep @opentelemetry/instrumentation @opentelemetry/instrumentation-document-load @opentelemetry/instrumentation-fetch @opentelemetry/instrumentation-xml-http-request @opentelemetry/propagator-aws-xray --save-dev
|
||||
```
|
||||
|
||||
Not let's import OTel module in `app.module.ts`
|
||||
|
||||
```ts
|
||||
import {
|
||||
OpenTelemetryInterceptorModule,
|
||||
OtelColExporterModule,
|
||||
CompositePropagatorModule,
|
||||
} from '@jufab/opentelemetry-angular-interceptor';
|
||||
|
||||
@NgModule({
|
||||
...
|
||||
imports: [
|
||||
...
|
||||
OpenTelemetryInterceptorModule.forRoot({
|
||||
commonConfig: {
|
||||
console: true, // Display trace on console (only in DEV env)
|
||||
production: false, // Send Trace with BatchSpanProcessor (true) or SimpleSpanProcessor (false)
|
||||
serviceName: 'Angular Sample App', // Service name send in trace
|
||||
probabilitySampler: '1',
|
||||
},
|
||||
otelcolConfig: {
|
||||
url: 'http://127.0.0.1:4318/v1/traces', // URL of opentelemetry collector
|
||||
},
|
||||
}),
|
||||
//Insert OtelCol exporter module
|
||||
OtelColExporterModule,
|
||||
//Insert propagator module
|
||||
CompositePropagatorModule,
|
||||
],
|
||||
...
|
||||
})
|
||||
```
|
||||
|
||||
This config would be enough to get you up and running. For more tweaks refer to [this](https://github.com/jufab/opentelemetry-angular-interceptor#readme) detailed documentation of the instrumentation library.
|
||||
|
||||
Facing difficulties with instrumenting your application? Check out this video tutorial 👇
|
@ -0,0 +1,132 @@
|
||||
## Send Traces Directly to SigNoz
|
||||
|
||||
### Using the all-in-one auto-instrumentation library
|
||||
|
||||
The recommended way to instrument your Express application is to use the all-in-one auto-instrumentation library - `@opentelemetry/auto-instrumentations-node`. It provides a simple way to initialize multiple Nodejs instrumentations.
|
||||
|
||||
Internally, it calls the specific auto-instrumentation library for components used in the application. You can see the complete list [here](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/metapackages/auto-instrumentations-node#supported-instrumentations).
|
||||
|
||||
#### Steps to auto-instrument Express application
|
||||
|
||||
1. Install the dependencies<br></br>
|
||||
We start by installing the relevant dependencies.
|
||||
|
||||
```bash
|
||||
npm install --save @opentelemetry/sdk-node
|
||||
npm install --save @opentelemetry/auto-instrumentations-node
|
||||
npm install --save @opentelemetry/exporter-trace-otlp-http
|
||||
```
|
||||
|
||||
The dependencies included are briefly explained below:<br></br>
|
||||
|
||||
`@opentelemetry/sdk-node` - This package provides the full OpenTelemetry SDK for Node.js including tracing and metrics.<br></br>
|
||||
|
||||
`@opentelemetry/auto-instrumentations-node` - This module provides a simple way to initialize multiple Node instrumentations.<br></br>
|
||||
|
||||
`@opentelemetry/exporter-trace-otlp-http` - This module provides the exporter to be used with OTLP (`http/json`) compatible receivers.<br></br>
|
||||
|
||||
<VersionPin />
|
||||
|
||||
2. **Create a `tracing.js` file**<br></br>
|
||||
The `tracing.js` file will contain the tracing setup code. Notice, that we have set some environment variables in the code(highlighted). You can update these variables based on your environment.
|
||||
|
||||
````jsx
|
||||
// tracing.js
|
||||
'use strict'
|
||||
const process = require('process');
|
||||
const opentelemetry = require('@opentelemetry/sdk-node');
|
||||
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
|
||||
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');
|
||||
const { Resource } = require('@opentelemetry/resources');
|
||||
const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
|
||||
|
||||
const exporterOptions = {
|
||||
// highlight-next-line
|
||||
url: 'http://localhost:4318/v1/traces'
|
||||
}
|
||||
|
||||
const traceExporter = new OTLPTraceExporter(exporterOptions);
|
||||
const sdk = new opentelemetry.NodeSDK({
|
||||
traceExporter,
|
||||
instrumentations: [getNodeAutoInstrumentations()],
|
||||
// highlight-start
|
||||
resource: new Resource({
|
||||
[SemanticResourceAttributes.SERVICE_NAME]: 'node_app'
|
||||
})
|
||||
// highlight-end
|
||||
});
|
||||
|
||||
// initialize the SDK and register with the OpenTelemetry API
|
||||
// this enables the API to record telemetry
|
||||
sdk.start()
|
||||
|
||||
// gracefully shut down the SDK on process exit
|
||||
process.on('SIGTERM', () => {
|
||||
sdk.shutdown()
|
||||
.then(() => console.log('Tracing terminated'))
|
||||
.catch((error) => console.log('Error terminating tracing', error))
|
||||
.finally(() => process.exit(0));
|
||||
});
|
||||
```
|
||||
|
||||
OpenTelemetry Node SDK currently does not detect the `OTEL_RESOURCE_ATTRIBUTES` from `.env` files as of today. That’s why we need to include the variables in the `tracing.js` file itself.
|
||||
|
||||
About environment variables:
|
||||
|
||||
`service_name` : node_app (you can give whatever name that suits you)
|
||||
|
||||
`http://localhost:4318/v1/traces` is the default url for sending your tracing data. We are assuming you have installed SigNoz on your `localhost`. Based on your environment, you can update it accordingly. It should be in the following format:
|
||||
|
||||
`http://<IP of SigNoz backend>:4318/v1/traces`
|
||||
|
||||
Here’s a handy [grid](https://signoz.io/docs/instrumentation/troubleshoot-instrumentation/) to figure out which address to use to send data to SigNoz.
|
||||
|
||||
:::note
|
||||
Remember to allow incoming requests to port 4318 of machine where SigNoz backend is hosted.
|
||||
|
||||
|
||||
|
||||
3. **Run the application**<br></br>
|
||||
The tracing configuration should be run before your application code. We will use the [`-r, —require module`](https://nodejs.org/api/cli.html#cli_r_require_module) flag for that.<br></br>
|
||||
|
||||
```jsx
|
||||
node -r ./tracing.js app.js
|
||||
```
|
||||
|
||||
:::note
|
||||
If you're running your nodejs application in PM2 cluster mode, it doesn't support node args: [Unitech/pm2#3227](https://github.com/Unitech/pm2/issues/3227). As above sample app instrumentation requires to load `tracing.js` before app load by passing node arg, so nodejs instrumentation doesn't work in PM2 cluster mode. So you need to import `tracing.js` in your main application. The `import ./tracing.js` should be the first line of your application code and initialize it before any other function. Here's the [sample github repo](https://github.com/SigNoz/sample-nodejs-app/tree/init-tracer-main) which shows the implementation.
|
||||
:::
|
||||
|
||||
### Validating instrumentation by checking for traces
|
||||
|
||||
With your application running, you can verify that you’ve instrumented your application with OpenTelemetry correctly by confirming that tracing data is being reported to SigNoz.
|
||||
|
||||
To do this, you need to ensure that your application generates some data. Applications will not produce traces unless they are being interacted with, and OpenTelemetry will often buffer data before sending. So you need to interact with your application and wait for some time to see your tracing data in SigNoz.
|
||||
|
||||
Validate your traces in SigNoz:
|
||||
|
||||
1. Trigger an action in your app that generates a web request. Hit the endpoint a number of times to generate some data. Then, wait for some time.
|
||||
2. In SigNoz, open the `Services` tab. Hit the `Refresh` button on the top right corner, and your application should appear in the list of `Applications`.
|
||||
3. Go to the `Traces` tab, and apply relevant filters to see your application’s traces.
|
||||
|
||||
You might see other dummy applications if you’re using SigNoz for the first time. You can remove it by following the docs [here](https://signoz.io/docs/operate/docker-standalone/#remove-the-sample-application).
|
||||
|
||||
<figure data-zoomable align='center'>
|
||||
<img src="/img/docs/express_application_services_list.webp" alt="Nestjs Application in the list of services being monitored in SigNoz"/>
|
||||
<figcaption><i>Express Application in the list of services being monitored in SigNoz</i></figcaption>
|
||||
</figure>
|
||||
|
||||
<br></br>
|
||||
|
||||
If you don't see your application reported in the list of services, try our [troubleshooting](https://signoz.io/docs/install/troubleshooting/) guide.
|
||||
|
||||
|
||||
### Using a specific auto-instrumentation library
|
||||
|
||||
If you want to instrument only your Express framework, then you need to use the following package:
|
||||
|
||||
```jsx
|
||||
npm install --save @opentelemetry/instrumentation-express
|
||||
````
|
||||
|
||||
Note that in the above case, you will have to install packages for all the components that you want to instrument with OpenTelemetry individually. You can find detailed instructions [here](https://signoz.io/docs/instrumentation/javascript/#using-a-specific-auto-instrumentation-library).
|
@ -0,0 +1,231 @@
|
||||
## Send traces to SigNoz Cloud
|
||||
|
||||
Based on your application environment, you can choose the setup below to send traces to SigNoz Cloud.
|
||||
|
||||
From VMs, there are two ways to send data to SigNoz Cloud.
|
||||
|
||||
- [Send traces directly to SigNoz Cloud](#send-traces-directly-to-signoz-cloud)
|
||||
- [Send traces via OTel Collector binary](#send-traces-via-otel-collector-binary) (recommended)
|
||||
|
||||
#### **Send traces directly to SigNoz Cloud**
|
||||
|
||||
Step 1. Install OpenTelemetry packages
|
||||
|
||||
```js
|
||||
npm install --save @opentelemetry/api@^1.4.1
|
||||
npm install --save @opentelemetry/sdk-node@^0.39.1
|
||||
npm install --save @opentelemetry/auto-instrumentations-node@^0.37.0
|
||||
npm install --save @opentelemetry/exporter-trace-otlp-grpc@^0.39.1
|
||||
```
|
||||
|
||||
Step 2. Create tracing.js file<br></br>
|
||||
You need to configure the endpoint for SigNoz cloud in this file. You can find your ingestion key from SigNoz cloud account details sent on your email.
|
||||
|
||||
```js
|
||||
// tracing.js
|
||||
'use strict';
|
||||
const process = require('process');
|
||||
const opentelemetry = require('@opentelemetry/sdk-node');
|
||||
const {
|
||||
getNodeAutoInstrumentations,
|
||||
} = require('@opentelemetry/auto-instrumentations-node');
|
||||
const {
|
||||
OTLPTraceExporter,
|
||||
} = require('@opentelemetry/exporter-trace-otlp-grpc');
|
||||
const { Resource } = require('@opentelemetry/resources');
|
||||
const {
|
||||
SemanticResourceAttributes,
|
||||
} = require('@opentelemetry/semantic-conventions');
|
||||
|
||||
// do not set headers in exporterOptions, the OTel spec recommends setting headers through ENV variables
|
||||
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#specifying-headers-via-environment-variables
|
||||
|
||||
// highlight-start
|
||||
const exporterOptions = {
|
||||
url: 'https://ingest.{region}.signoz.cloud:443',
|
||||
};
|
||||
// highlight-end
|
||||
|
||||
const traceExporter = new OTLPTraceExporter(exporterOptions);
|
||||
const sdk = new opentelemetry.NodeSDK({
|
||||
traceExporter,
|
||||
instrumentations: [getNodeAutoInstrumentations()],
|
||||
resource: new Resource({
|
||||
// highlight-next-line
|
||||
[SemanticResourceAttributes.SERVICE_NAME]: 'node_app',
|
||||
}),
|
||||
});
|
||||
|
||||
// initialize the SDK and register with the OpenTelemetry API
|
||||
// this enables the API to record telemetry
|
||||
sdk.start();
|
||||
|
||||
// gracefully shut down the SDK on process exit
|
||||
process.on('SIGTERM', () => {
|
||||
sdk
|
||||
.shutdown()
|
||||
.then(() => console.log('Tracing terminated'))
|
||||
.catch((error) => console.log('Error terminating tracing', error))
|
||||
.finally(() => process.exit(0));
|
||||
});
|
||||
```
|
||||
|
||||
Depending on the choice of your region for SigNoz cloud, the ingest endpoint will vary according to this table.
|
||||
|
||||
| Region | Endpoint |
|
||||
| ------ | -------------------------- |
|
||||
| US | ingest.us.signoz.cloud:443 |
|
||||
| IN | ingest.in.signoz.cloud:443 |
|
||||
| EU | ingest.eu.signoz.cloud:443 |
|
||||
|
||||
Step 3. Run the application<br></br>
|
||||
Make sure you set the `OTEL_EXPORTER_OTLP_HEADERS` env as follows
|
||||
|
||||
```bash
|
||||
OTEL_EXPORTER_OTLP_HEADERS="signoz-access-token=<SIGNOZ_INGESTION_KEY>" node -r ./tracing.js app.js
|
||||
```
|
||||
|
||||
`SIGNOZ_INGESTION_KEY` is the API token provided by SigNoz. You can find your ingestion key from SigNoz cloud account details sent on your email.
|
||||
|
||||
Step 4. You can validate if your application is sending traces to SigNoz cloud [here](#validating-instrumentation-by-checking-for-traces).
|
||||
|
||||
#### **Send traces via OTel Collector binary**
|
||||
|
||||
OTel Collector binary helps to collect logs, hostmetrics, resource and infra attributes. It is recommended to install Otel Collector binary to collect and send traces to SigNoz cloud. You can correlate signals and have rich contextual data through this way.
|
||||
|
||||
:::note
|
||||
You can find instructions to install OTel Collector binary [here](https://signoz.io/docs/tutorial/opentelemetry-binary-usage-in-virtual-machine/) in your VM. Once you are done setting up your OTel Collector binary, you can follow the below steps for instrumenting your Javascript application.
|
||||
:::
|
||||
|
||||
Step 1. Install OpenTelemetry packages
|
||||
|
||||
```js
|
||||
npm install --save @opentelemetry/api@^1.4.1
|
||||
npm install --save @opentelemetry/sdk-node@^0.39.1
|
||||
npm install --save @opentelemetry/auto-instrumentations-node@^0.37.0
|
||||
npm install --save @opentelemetry/exporter-trace-otlp-grpc@^0.39.1
|
||||
```
|
||||
|
||||
Step 2. Create tracing.js file<br></br>
|
||||
|
||||
```js
|
||||
// tracing.js
|
||||
'use strict';
|
||||
const process = require('process');
|
||||
const opentelemetry = require('@opentelemetry/sdk-node');
|
||||
const {
|
||||
getNodeAutoInstrumentations,
|
||||
} = require('@opentelemetry/auto-instrumentations-node');
|
||||
const {
|
||||
OTLPTraceExporter,
|
||||
} = require('@opentelemetry/exporter-trace-otlp-grpc');
|
||||
const { Resource } = require('@opentelemetry/resources');
|
||||
const {
|
||||
SemanticResourceAttributes,
|
||||
} = require('@opentelemetry/semantic-conventions');
|
||||
|
||||
const exporterOptions = {
|
||||
url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT || 'http://localhost:4317',
|
||||
};
|
||||
|
||||
const traceExporter = new OTLPTraceExporter(exporterOptions);
|
||||
const sdk = new opentelemetry.NodeSDK({
|
||||
traceExporter,
|
||||
instrumentations: [getNodeAutoInstrumentations()],
|
||||
resource: new Resource({
|
||||
// highlight-next-line
|
||||
[SemanticResourceAttributes.SERVICE_NAME]: 'node_app',
|
||||
}),
|
||||
});
|
||||
|
||||
// initialize the SDK and register with the OpenTelemetry API
|
||||
// this enables the API to record telemetry
|
||||
sdk.start();
|
||||
|
||||
// gracefully shut down the SDK on process exit
|
||||
process.on('SIGTERM', () => {
|
||||
sdk
|
||||
.shutdown()
|
||||
.then(() => console.log('Tracing terminated'))
|
||||
.catch((error) => console.log('Error terminating tracing', error))
|
||||
.finally(() => process.exit(0));
|
||||
});
|
||||
```
|
||||
|
||||
Step 3. Run the application<br></br>
|
||||
|
||||
```bash
|
||||
node -r ./tracing.js app.js
|
||||
```
|
||||
|
||||
Step 4. You can validate if your application is sending traces to SigNoz cloud [here](#validating-instrumentation-by-checking-for-traces).
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="k8s" label="Kubernetes">
|
||||
|
||||
For Javascript application deployed on Kubernetes, you need to install OTel Collector agent in your k8s infra to collect and send traces to SigNoz Cloud. You can find the instructions to install OTel Collector agent [here](/docs/tutorial/kubernetes-infra-metrics/).
|
||||
|
||||
Once you have set up OTel Collector agent, you can proceed with OpenTelemetry Javascript instrumentation by following the below steps:
|
||||
|
||||
Step 1. Install OpenTelemetry packages
|
||||
|
||||
```js
|
||||
npm install --save @opentelemetry/api@^1.4.1
|
||||
npm install --save @opentelemetry/sdk-node@^0.39.1
|
||||
npm install --save @opentelemetry/auto-instrumentations-node@^0.37.0
|
||||
npm install --save @opentelemetry/exporter-trace-otlp-grpc@^0.39.1
|
||||
```
|
||||
|
||||
Step 2. Create tracing.js file<br></br>
|
||||
|
||||
```js
|
||||
// tracing.js
|
||||
'use strict';
|
||||
const process = require('process');
|
||||
const opentelemetry = require('@opentelemetry/sdk-node');
|
||||
const {
|
||||
getNodeAutoInstrumentations,
|
||||
} = require('@opentelemetry/auto-instrumentations-node');
|
||||
const {
|
||||
OTLPTraceExporter,
|
||||
} = require('@opentelemetry/exporter-trace-otlp-grpc');
|
||||
const { Resource } = require('@opentelemetry/resources');
|
||||
const {
|
||||
SemanticResourceAttributes,
|
||||
} = require('@opentelemetry/semantic-conventions');
|
||||
|
||||
const exporterOptions = {
|
||||
url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT || 'http://localhost:4317',
|
||||
};
|
||||
|
||||
const traceExporter = new OTLPTraceExporter(exporterOptions);
|
||||
const sdk = new opentelemetry.NodeSDK({
|
||||
traceExporter,
|
||||
instrumentations: [getNodeAutoInstrumentations()],
|
||||
resource: new Resource({
|
||||
// highlight-next-line
|
||||
[SemanticResourceAttributes.SERVICE_NAME]: 'node_app',
|
||||
}),
|
||||
});
|
||||
|
||||
// initialize the SDK and register with the OpenTelemetry API
|
||||
// this enables the API to record telemetry
|
||||
sdk.start();
|
||||
|
||||
// gracefully shut down the SDK on process exit
|
||||
process.on('SIGTERM', () => {
|
||||
sdk
|
||||
.shutdown()
|
||||
.then(() => console.log('Tracing terminated'))
|
||||
.catch((error) => console.log('Error terminating tracing', error))
|
||||
.finally(() => process.exit(0));
|
||||
});
|
||||
```
|
||||
|
||||
Step 3. Run the application<br></br>
|
||||
|
||||
```bash
|
||||
node -r ./tracing.js app.js
|
||||
```
|
||||
|
||||
Step 4. You can validate if your application is sending traces to SigNoz cloud [here](#validating-instrumentation-by-checking-for-traces).
|
@ -0,0 +1,129 @@
|
||||
## Send Traces Directly to SigNoz
|
||||
|
||||
### Using the all-in-one auto-instrumentation library
|
||||
|
||||
The recommended way to instrument your Nestjs application is to use the all-in-one auto-instrumentation library - `@opentelemetry/auto-instrumentations-node`. It provides a simple way to initialize multiple Nodejs instrumentations.
|
||||
|
||||
Internally, it calls the specific auto-instrumentation library for components used in the application. You can see the complete list [here](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/metapackages/auto-instrumentations-node#supported-instrumentations).
|
||||
|
||||
#### Steps to auto-instrument Nestjs application
|
||||
|
||||
1. Install the dependencies<br></br>
|
||||
We start by installing the relevant dependencies.
|
||||
|
||||
```bash
|
||||
npm install --save @opentelemetry/sdk-node
|
||||
npm install --save @opentelemetry/auto-instrumentations-node
|
||||
npm install --save @opentelemetry/exporter-trace-otlp-http
|
||||
```
|
||||
|
||||
<NestjsPinnedVersions />
|
||||
|
||||
2. Create a `tracer.ts` file
|
||||
|
||||
```jsx
|
||||
'use strict';
|
||||
const process = require('process');
|
||||
//OpenTelemetry
|
||||
const opentelemetry = require('@opentelemetry/sdk-node');
|
||||
const {
|
||||
getNodeAutoInstrumentations,
|
||||
} = require('@opentelemetry/auto-instrumentations-node');
|
||||
const {
|
||||
OTLPTraceExporter,
|
||||
} = require('@opentelemetry/exporter-trace-otlp-http');
|
||||
const { Resource } = require('@opentelemetry/resources');
|
||||
const {
|
||||
SemanticResourceAttributes,
|
||||
} = require('@opentelemetry/semantic-conventions');
|
||||
|
||||
const exporterOptions = {
|
||||
url: 'http://localhost:4318/v1/traces',
|
||||
};
|
||||
|
||||
const traceExporter = new OTLPTraceExporter(exporterOptions);
|
||||
const sdk = new opentelemetry.NodeSDK({
|
||||
traceExporter,
|
||||
instrumentations: [getNodeAutoInstrumentations()],
|
||||
resource: new Resource({
|
||||
[SemanticResourceAttributes.SERVICE_NAME]: 'sampleNestjsApplication',
|
||||
}),
|
||||
});
|
||||
|
||||
// initialize the SDK and register with the OpenTelemetry API
|
||||
// this enables the API to record telemetry
|
||||
sdk.start();
|
||||
|
||||
// gracefully shut down the SDK on process exit
|
||||
process.on('SIGTERM', () => {
|
||||
sdk
|
||||
.shutdown()
|
||||
.then(() => console.log('Tracing terminated'))
|
||||
.catch((error) => console.log('Error terminating tracing', error))
|
||||
.finally(() => process.exit(0));
|
||||
});
|
||||
|
||||
module.exports = sdk;
|
||||
```
|
||||
|
||||
3. Import the tracer module where your app starts
|
||||
|
||||
```jsx
|
||||
const tracer = require('./tracer');
|
||||
```
|
||||
|
||||
4. Start the tracer<br></br>
|
||||
In the `async function boostrap` section of the application code, initialize the tracer as follows:
|
||||
|
||||
```jsx
|
||||
const tracer = require('./tracer');
|
||||
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { AppModule } from './app.module';
|
||||
// All of your application code and any imports that should leverage
|
||||
// OpenTelemetry automatic instrumentation must go here.
|
||||
|
||||
async function bootstrap() {
|
||||
// highlight-start
|
||||
await tracer.start();
|
||||
//highlight-end
|
||||
const app = await NestFactory.create(AppModule);
|
||||
await app.listen(3001);
|
||||
}
|
||||
bootstrap();
|
||||
```
|
||||
|
||||
You can now run your Nestjs application. The data captured with OpenTelemetry from your application should start showing on the SigNoz dashboard.
|
||||
|
||||
### Validating instrumentation by checking for traces
|
||||
|
||||
With your application running, you can verify that you’ve instrumented your application with OpenTelemetry correctly by confirming that tracing data is being reported to SigNoz.
|
||||
|
||||
To do this, you need to ensure that your application generates some data. Applications will not produce traces unless they are being interacted with, and OpenTelemetry will often buffer data before sending. So you need to interact with your application and wait for some time to see your tracing data in SigNoz.
|
||||
|
||||
Validate your traces in SigNoz:
|
||||
|
||||
1. Trigger an action in your app that generates a web request. Hit the endpoint a number of times to generate some data. Then, wait for some time.
|
||||
2. In SigNoz, open the `Services` tab. Hit the `Refresh` button on the top right corner, and your application should appear in the list of `Applications`.
|
||||
3. Go to the `Traces` tab, and apply relevant filters to see your application’s traces.
|
||||
|
||||
You might see other dummy applications if you’re using SigNoz for the first time. You can remove it by following the docs [here](https://signoz.io/docs/operate/docker-standalone/#remove-the-sample-application).
|
||||
|
||||
<figure data-zoomable align='center'>
|
||||
<img src="/img/docs/nestjs_application_instrumented.webp" alt="Nestjs Application in the list of services being monitored in SigNoz"/>
|
||||
<figcaption><i>Nestjs Application in the list of services being monitored in SigNoz</i></figcaption>
|
||||
</figure>
|
||||
|
||||
<br></br>
|
||||
|
||||
If you don't see your application reported in the list of services, try our [troubleshooting](https://signoz.io/docs/install/troubleshooting/) guide.
|
||||
|
||||
### Using a specific auto-instrumentation library
|
||||
|
||||
If you want to instrument only your Nestjs framework, then you need to use the following package:
|
||||
|
||||
```jsx
|
||||
npm install --save @opentelemetry/instrumentation-nestjs-core
|
||||
```
|
||||
|
||||
Note that in the above case, you will have to install packages for all the components that you want to instrument with OpenTelemetry individually. You can find detailed instructions [here](https://signoz.io/docs/instrumentation/javascript/#using-a-specific-auto-instrumentation-library).
|
123
frontend/src/container/OnboardingContainer/APM/Python/Python.tsx
Normal file
123
frontend/src/container/OnboardingContainer/APM/Python/Python.tsx
Normal file
@ -0,0 +1,123 @@
|
||||
import './Python.styles.scss';
|
||||
|
||||
import { MDXProvider } from '@mdx-js/react';
|
||||
import { Form, Input, Select } from 'antd';
|
||||
import Header from 'container/OnboardingContainer/common/Header/Header';
|
||||
import { useState } from 'react';
|
||||
|
||||
import ConnectionStatus from '../common/ConnectionStatus/ConnectionStatus';
|
||||
import DjangoDocs from './md-docs/django.md';
|
||||
import FalconDocs from './md-docs/falcon.md';
|
||||
import FastAPIDocs from './md-docs/fastAPI.md';
|
||||
import FlaskDocs from './md-docs/flask.md';
|
||||
import PythonDocs from './md-docs/python.md';
|
||||
|
||||
const frameworksMap = {
|
||||
django: 'Django',
|
||||
fastAPI: 'Fast API',
|
||||
flask: 'Flask',
|
||||
falcon: 'Falcon',
|
||||
other: 'Others',
|
||||
};
|
||||
|
||||
export default function Python({
|
||||
activeStep,
|
||||
}: {
|
||||
activeStep: number;
|
||||
}): JSX.Element {
|
||||
const [selectedFrameWork, setSelectedFrameWork] = useState('django');
|
||||
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const renderDocs = (): JSX.Element => {
|
||||
switch (selectedFrameWork) {
|
||||
case 'django':
|
||||
return <DjangoDocs />;
|
||||
case 'fastAPI':
|
||||
return <FastAPIDocs />;
|
||||
case 'flask':
|
||||
return <FlaskDocs />;
|
||||
case 'falcon':
|
||||
return <FalconDocs />;
|
||||
default:
|
||||
return <PythonDocs />;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{activeStep === 2 && (
|
||||
<div className="python-setup-instructions-container">
|
||||
<Header
|
||||
entity="python"
|
||||
heading="Python OpenTelemetry Instrumentation"
|
||||
imgURL="/Logos/python.png"
|
||||
docsURL="https://signoz.io/docs/instrumentation/python/"
|
||||
imgClassName="supported-language-img"
|
||||
/>
|
||||
|
||||
<div className="form-container">
|
||||
<div className="framework-selector">
|
||||
<div className="label"> Select Framework </div>
|
||||
|
||||
<Select
|
||||
defaultValue="Django"
|
||||
style={{ minWidth: 120 }}
|
||||
placeholder="Select Framework"
|
||||
onChange={(value): void => setSelectedFrameWork(value)}
|
||||
options={[
|
||||
{
|
||||
value: 'django',
|
||||
label: frameworksMap.django,
|
||||
},
|
||||
{
|
||||
value: 'fastAPI',
|
||||
label: frameworksMap.fastAPI,
|
||||
},
|
||||
{
|
||||
value: 'flask',
|
||||
label: frameworksMap.flask,
|
||||
},
|
||||
{
|
||||
value: 'falcon',
|
||||
label: frameworksMap.falcon,
|
||||
},
|
||||
{
|
||||
value: 'other',
|
||||
label: frameworksMap.other,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="service-name-container">
|
||||
<div className="label"> Service Name </div>
|
||||
|
||||
<Form form={form} name="service-name" style={{ minWidth: '300px' }}>
|
||||
<Form.Item
|
||||
hasFeedback
|
||||
name="Service Name"
|
||||
rules={[{ required: true }]}
|
||||
validateTrigger="onBlur"
|
||||
>
|
||||
<Input autoFocus />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="content-container">
|
||||
<MDXProvider>{renderDocs()}</MDXProvider>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{activeStep === 3 && (
|
||||
<ConnectionStatus
|
||||
serviceName={form.getFieldValue('Service Name')}
|
||||
language="python"
|
||||
framework={selectedFrameWork}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
## Send Traces Directly to SigNoz
|
||||
|
||||
You can use OpenTelemetry to send your traces directly to SigNoz. OpenTelemetry provides a handy distro in Python that can help you get started with automatic instrumentation. We recommend using it to get started quickly.
|
||||
|
||||
### Steps to auto-instrument Django app for traces
|
||||
|
||||
1. **Create a virtual environment**<br></br>
|
||||
|
||||
```bash
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
```
|
||||
|
||||
2. **Install the OpenTelemetry dependencies**<br></br>
|
||||
|
||||
```bash
|
||||
pip install opentelemetry-distro
|
||||
pip install opentelemetry-exporter-otlp
|
||||
```
|
||||
|
||||
The dependencies included are briefly explained below:
|
||||
|
||||
`opentelemetry-distro` - The distro provides a mechanism to automatically configure some of the more common options for users. It helps to get started with OpenTelemetry auto-instrumentation quickly.
|
||||
|
||||
`opentelemetry-exporter-otlp` - This library provides a way to install all OTLP exporters. You will need an exporter to send the data to SigNoz.
|
||||
|
||||
:::note
|
||||
💡 The `opentelemetry-exporter-otlp` is a convenient wrapper package to install all OTLP exporters. Currently, it installs:
|
||||
|
||||
- opentelemetry-exporter-otlp-proto-http
|
||||
- opentelemetry-exporter-otlp-proto-grpc
|
||||
|
||||
- (soon) opentelemetry-exporter-otlp-json-http
|
||||
|
||||
The `opentelemetry-exporter-otlp-proto-grpc` package installs the gRPC exporter which depends on the `grpcio` package. The installation of `grpcio` may fail on some platforms for various reasons. If you run into such issues, or you don't want to use gRPC, you can install the HTTP exporter instead by installing the `opentelemetry-exporter-otlp-proto-http` package. You need to set the `OTEL_EXPORTER_OTLP_PROTOCOL` environment variable to `http/protobuf` to use the HTTP exporter.
|
||||
:::
|
||||
|
||||
3. **Add automatic instrumentation**<br></br>
|
||||
The below command inspects the dependencies of your application and installs the instrumentation packages relevant for your Django application.
|
||||
|
||||
```bash
|
||||
opentelemetry-bootstrap --action=install
|
||||
```
|
||||
|
||||
:::note
|
||||
Please make sure that you have installed all the dependencies of your application before running the above command. The command will not install instrumentation for the dependencies which are not installed.
|
||||
:::
|
||||
|
||||
4. **Run your application**<br></br>
|
||||
In the final run command, you can configure environment variables and flags. Flags for exporters:<br></br>
|
||||
|
||||
For running your application, there are a few things that you need to keep in mind. Below are the notes:
|
||||
:::note
|
||||
Don’t run app in reloader/hot-reload mode as it breaks instrumentation. For example, you can disable the auto reload with `--noreload`.
|
||||
:::
|
||||
|
||||
For running applications with application servers which are based on [pre fork model](#running-applications-with-gunicorn-uwsgi), like Gunicorn, uWSGI you have to add a post_fork hook or a @postfork decorator in your configuration.
|
||||
|
||||
To start sending data to SigNoz, use the following run command:
|
||||
|
||||
```bash
|
||||
OTEL_RESOURCE_ATTRIBUTES=service.name=<service_name> OTEL_EXPORTER_OTLP_ENDPOINT="http://<IP of SigNoz Backend>:4317" OTEL_EXPORTER_OTLP_PROTOCOL=grpc opentelemetry-instrument <your run command>
|
||||
```
|
||||
|
||||
*<service_name>* is the name of service you want
|
||||
|
||||
*<your_run_command>* can be `python3 app.py` or `python manage.py runserver --noreload`
|
||||
|
||||
`IP of SigNoz backend` is the IP of the machine where you installed SigNoz. If you have installed SigNoz on `localhost`, the endpoint will be `http://localhost:4317` for gRPC exporter and `http://localhost:4318` for HTTP exporter.
|
||||
|
||||
:::note
|
||||
The port numbers are 4317 and 4318 for the gRPC and HTTP exporters respectively. Remember to allow incoming requests to port **4317**/**4318** of machine where SigNoz backend is hosted.
|
||||
:::
|
||||
|
||||
### Validating instrumentation by checking for traces
|
||||
|
||||
With your application running, you can verify that you’ve instrumented your application with OpenTelemetry correctly by confirming that tracing data is being reported to SigNoz.
|
||||
|
||||
To do this, you need to ensure that your application generates some data. Applications will not produce traces unless they are being interacted with, and OpenTelemetry will often buffer data before sending. So you need to interact with your application and wait for some time to see your tracing data in SigNoz.
|
||||
|
||||
Validate your traces in SigNoz:
|
||||
|
||||
1. Trigger an action in your app that generates a web request. Hit the endpoint a number of times to generate some data. Then, wait for some time.
|
||||
2. In SigNoz, open the `Services` tab. Hit the `Refresh` button on the top right corner, and your application should appear in the list of `Applications`.
|
||||
3. Go to the `Traces` tab, and apply relevant filters to see your application’s traces.
|
||||
|
||||
You might see other dummy applications if you’re using SigNoz for the first time. You can remove it by following the docs [here](https://signoz.io/docs/operate/docker-standalone/#remove-the-sample-application).
|
||||
|
||||
<figure data-zoomable align='center'>
|
||||
<img src="/img/docs/opentelemetry_python_app_instrumented.webp" alt="Python Application in the list of services being monitored in SigNoz"/>
|
||||
<figcaption><i>Python Application in the list of services being monitored in SigNoz</i></figcaption></figure>
|
||||
<br></br>
|
@ -0,0 +1,92 @@
|
||||
## Send Traces Directly to SigNoz
|
||||
|
||||
You can use OpenTelemetry to send your traces directly to SigNoz. OpenTelemetry provides a handy distro in Python that can help you get started with automatic instrumentation. We recommend using it to get started quickly.
|
||||
|
||||
### Steps to auto-instrument Falcon app for traces
|
||||
|
||||
1. **Create a virtual environment**<br></br>
|
||||
|
||||
```bash
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
```
|
||||
|
||||
2. **Install the OpenTelemetry dependencies**<br></br>
|
||||
|
||||
```bash
|
||||
pip install opentelemetry-distro
|
||||
pip install opentelemetry-exporter-otlp
|
||||
```
|
||||
|
||||
The dependencies included are briefly explained below:
|
||||
|
||||
`opentelemetry-distro` - The distro provides a mechanism to automatically configure some of the more common options for users. It helps to get started with OpenTelemetry auto-instrumentation quickly.
|
||||
|
||||
`opentelemetry-exporter-otlp` - This library provides a way to install all OTLP exporters. You will need an exporter to send the data to SigNoz.
|
||||
|
||||
:::note
|
||||
💡 The `opentelemetry-exporter-otlp` is a convenience wrapper package to install all OTLP exporters. Currently, it installs:
|
||||
|
||||
- opentelemetry-exporter-otlp-proto-http
|
||||
- opentelemetry-exporter-otlp-proto-grpc
|
||||
|
||||
- (soon) opentelemetry-exporter-otlp-json-http
|
||||
|
||||
The `opentelemetry-exporter-otlp-proto-grpc` package installs the gRPC exporter which depends on the `grpcio` package. The installation of `grpcio` may fail on some platforms for various reasons. If you run into such issues, or you don't want to use gRPC, you can install the HTTP exporter instead by installing the `opentelemetry-exporter-otlp-proto-http` package. You need to set the `OTEL_EXPORTER_OTLP_PROTOCOL` environment variable to `http/protobuf` to use the HTTP exporter.
|
||||
:::
|
||||
|
||||
3. **Add automatic instrumentation**<br></br>
|
||||
The below command inspects the dependencies of your application and installs the instrumentation packages relevant for your Falcon application.
|
||||
|
||||
```bash
|
||||
opentelemetry-bootstrap --action=install
|
||||
```
|
||||
|
||||
:::note
|
||||
Please make sure that you have installed all the dependencies of your application before running the above command. The command will not install instrumentation for the dependencies which are not installed.
|
||||
:::
|
||||
|
||||
4. **Run your application**<br></br>
|
||||
In the final run command, you can configure environment variables and flags. Flags for exporters:<br></br>
|
||||
|
||||
For running your application, there are a few things that you need to keep in mind. Below are the notes:
|
||||
:::note
|
||||
Don’t run app in reloader/hot-reload mode as it breaks instrumentation.
|
||||
:::
|
||||
|
||||
For running applications with application servers which are based on [pre fork model](#running-applications-with-gunicorn-uwsgi), like Gunicorn, uWSGI you have to add a post_fork hook or a @postfork decorator in your configuration.
|
||||
|
||||
To start sending data to SigNoz, use the following run command:
|
||||
|
||||
```bash
|
||||
OTEL_RESOURCE_ATTRIBUTES=service.name=<service_name> OTEL_EXPORTER_OTLP_ENDPOINT="http://<IP of SigNoz Backend>:4317" OTEL_EXPORTER_OTLP_PROTOCOL=grpc opentelemetry-instrument <your run command>
|
||||
```
|
||||
|
||||
*<service_name>* is the name of service you want
|
||||
|
||||
*<your_run_command>* can be `python3 app.py` or `flask run`
|
||||
|
||||
`IP of SigNoz backend` is the IP of the machine where you installed SigNoz. If you have installed SigNoz on `localhost`, the endpoint will be `http://localhost:4317` for gRPC exporter and `http://localhost:4318` for HTTP exporter.
|
||||
|
||||
:::note
|
||||
The port numbers are 4317 and 4318 for the gRPC and HTTP exporters respectively. Remember to allow incoming requests to port **4317**/**4318** of machine where SigNoz backend is hosted.
|
||||
:::
|
||||
|
||||
### Validating instrumentation by checking for traces
|
||||
|
||||
With your application running, you can verify that you’ve instrumented your application with OpenTelemetry correctly by confirming that tracing data is being reported to SigNoz.
|
||||
|
||||
To do this, you need to ensure that your application generates some data. Applications will not produce traces unless they are being interacted with, and OpenTelemetry will often buffer data before sending. So you need to interact with your application and wait for some time to see your tracing data in SigNoz.
|
||||
|
||||
Validate your traces in SigNoz:
|
||||
|
||||
1. Trigger an action in your app that generates a web request. Hit the endpoint a number of times to generate some data. Then, wait for some time.
|
||||
2. In SigNoz, open the `Services` tab. Hit the `Refresh` button on the top right corner, and your application should appear in the list of `Applications`.
|
||||
3. Go to the `Traces` tab, and apply relevant filters to see your application’s traces.
|
||||
|
||||
You might see other dummy applications if you’re using SigNoz for the first time. You can remove it by following the docs [here](https://signoz.io/docs/operate/docker-standalone/#remove-the-sample-application).
|
||||
|
||||
<figure data-zoomable align='center'>
|
||||
<img src="/img/docs/opentelemetry_python_app_instrumented.webp" alt="Python Application in the list of services being monitored in SigNoz"/>
|
||||
<figcaption><i>Python Application in the list of services being monitored in SigNoz</i></figcaption></figure>
|
||||
<br></br>
|
@ -0,0 +1,92 @@
|
||||
## Send Traces Directly to SigNoz
|
||||
|
||||
You can use OpenTelemetry to send your traces directly to SigNoz. OpenTelemetry provides a handy distro in Python that can help you get started with automatic instrumentation. We recommend using it to get started quickly.
|
||||
|
||||
### Steps to auto-instrument FastAPI app for traces
|
||||
|
||||
1. **Create a virtual environment**<br></br>
|
||||
|
||||
```bash
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
```
|
||||
|
||||
2. **Install the OpenTelemetry dependencies**<br></br>
|
||||
|
||||
```bash
|
||||
pip install opentelemetry-distro
|
||||
pip install opentelemetry-exporter-otlp
|
||||
```
|
||||
|
||||
The dependencies included are briefly explained below:
|
||||
|
||||
`opentelemetry-distro` - The distro provides a mechanism to automatically configure some of the more common options for users. It helps to get started with OpenTelemetry auto-instrumentation quickly.
|
||||
|
||||
`opentelemetry-exporter-otlp` - This library provides a way to install all OTLP exporters. You will need an exporter to send the data to SigNoz.
|
||||
|
||||
:::note
|
||||
💡 The `opentelemetry-exporter-otlp` is a convenience wrapper package to install all OTLP exporters. Currently, it installs:
|
||||
|
||||
- opentelemetry-exporter-otlp-proto-http
|
||||
- opentelemetry-exporter-otlp-proto-grpc
|
||||
|
||||
- (soon) opentelemetry-exporter-otlp-json-http
|
||||
|
||||
The `opentelemetry-exporter-otlp-proto-grpc` package installs the gRPC exporter which depends on the `grpcio` package. The installation of `grpcio` may fail on some platforms for various reasons. If you run into such issues, or you don't want to use gRPC, you can install the HTTP exporter instead by installing the `opentelemetry-exporter-otlp-proto-http` package. You need to set the `OTEL_EXPORTER_OTLP_PROTOCOL` environment variable to `http/protobuf` to use the HTTP exporter.
|
||||
:::
|
||||
|
||||
3. **Add automatic instrumentation**<br></br>
|
||||
The below command inspects the dependencies of your application and installs the instrumentation packages relevant for your FastAPI application.
|
||||
|
||||
```bash
|
||||
opentelemetry-bootstrap --action=install
|
||||
```
|
||||
|
||||
:::note
|
||||
Please make sure that you have installed all the dependencies of your application before running the above command. The command will not install instrumentation for the dependencies which are not installed.
|
||||
:::
|
||||
|
||||
4. **Run your application**<br></br>
|
||||
In the final run command, you can configure environment variables and flags. Flags for exporters:<br></br>
|
||||
|
||||
For running your application, there are a few things that you need to keep in mind. Below are the notes:
|
||||
:::note
|
||||
Don’t run app in reloader/hot-reload mode as it breaks instrumentation. For example, if you use `--reload` or `reload=True`, it enables the reloader mode which breaks OpenTelemetry isntrumentation.
|
||||
:::
|
||||
|
||||
For running applications with application servers which are based on [pre fork model](#running-applications-with-gunicorn-uwsgi), like Gunicorn, uWSGI you have to add a post_fork hook or a @postfork decorator in your configuration.
|
||||
|
||||
To start sending data to SigNoz, use the following run command:
|
||||
|
||||
```bash
|
||||
OTEL_RESOURCE_ATTRIBUTES=service.name=<service_name> OTEL_EXPORTER_OTLP_ENDPOINT="http://<IP of SigNoz Backend>:4317" OTEL_EXPORTER_OTLP_PROTOCOL=grpc opentelemetry-instrument <your run command>
|
||||
```
|
||||
|
||||
*<service_name>* is the name of service you want
|
||||
|
||||
*<your_run_command>* can be `python3 app.py` or `python manage.py runserver --noreload`
|
||||
|
||||
`IP of SigNoz backend` is the IP of the machine where you installed SigNoz. If you have installed SigNoz on `localhost`, the endpoint will be `http://localhost:4317` for gRPC exporter and `http://localhost:4318` for HTTP exporter.
|
||||
|
||||
:::note
|
||||
The port numbers are 4317 and 4318 for the gRPC and HTTP exporters respectively. Remember to allow incoming requests to port **4317**/**4318** of machine where SigNoz backend is hosted.
|
||||
:::
|
||||
|
||||
### Validating instrumentation by checking for traces
|
||||
|
||||
With your application running, you can verify that you’ve instrumented your application with OpenTelemetry correctly by confirming that tracing data is being reported to SigNoz.
|
||||
|
||||
To do this, you need to ensure that your application generates some data. Applications will not produce traces unless they are being interacted with, and OpenTelemetry will often buffer data before sending. So you need to interact with your application and wait for some time to see your tracing data in SigNoz.
|
||||
|
||||
Validate your traces in SigNoz:
|
||||
|
||||
1. Trigger an action in your app that generates a web request. Hit the endpoint a number of times to generate some data. Then, wait for some time.
|
||||
2. In SigNoz, open the `Services` tab. Hit the `Refresh` button on the top right corner, and your application should appear in the list of `Applications`.
|
||||
3. Go to the `Traces` tab, and apply relevant filters to see your application’s traces.
|
||||
|
||||
You might see other dummy applications if you’re using SigNoz for the first time. You can remove it by following the docs [here](https://signoz.io/docs/operate/docker-standalone/#remove-the-sample-application).
|
||||
|
||||
<figure data-zoomable align='center'>
|
||||
<img src="/img/docs/opentelemetry_python_app_instrumented.webp" alt="Python Application in the list of services being monitored in SigNoz"/>
|
||||
<figcaption><i>Python Application in the list of services being monitored in SigNoz</i></figcaption></figure>
|
||||
<br></br>
|
@ -0,0 +1,92 @@
|
||||
## Send Traces Directly to SigNoz
|
||||
|
||||
You can use OpenTelemetry to send your traces directly to SigNoz. OpenTelemetry provides a handy distro in Python that can help you get started with automatic instrumentation. We recommend using it to get started quickly.
|
||||
|
||||
### Steps to auto-instrument Flask app for traces
|
||||
|
||||
1. **Create a virtual environment**<br></br>
|
||||
|
||||
```bash
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
```
|
||||
|
||||
2. **Install the OpenTelemetry dependencies**<br></br>
|
||||
|
||||
```bash
|
||||
pip install opentelemetry-distro
|
||||
pip install opentelemetry-exporter-otlp
|
||||
```
|
||||
|
||||
The dependencies included are briefly explained below:
|
||||
|
||||
`opentelemetry-distro` - The distro provides a mechanism to automatically configure some of the more common options for users. It helps to get started with OpenTelemetry auto-instrumentation quickly.
|
||||
|
||||
`opentelemetry-exporter-otlp` - This library provides a way to install all OTLP exporters. You will need an exporter to send the data to SigNoz.
|
||||
|
||||
:::note
|
||||
💡 The `opentelemetry-exporter-otlp` is a convenience wrapper package to install all OTLP exporters. Currently, it installs:
|
||||
|
||||
- opentelemetry-exporter-otlp-proto-http
|
||||
- opentelemetry-exporter-otlp-proto-grpc
|
||||
|
||||
- (soon) opentelemetry-exporter-otlp-json-http
|
||||
|
||||
The `opentelemetry-exporter-otlp-proto-grpc` package installs the gRPC exporter which depends on the `grpcio` package. The installation of `grpcio` may fail on some platforms for various reasons. If you run into such issues, or you don't want to use gRPC, you can install the HTTP exporter instead by installing the `opentelemetry-exporter-otlp-proto-http` package. You need to set the `OTEL_EXPORTER_OTLP_PROTOCOL` environment variable to `http/protobuf` to use the HTTP exporter.
|
||||
:::
|
||||
|
||||
3. **Add automatic instrumentation**<br></br>
|
||||
The below command inspects the dependencies of your application and installs the instrumentation packages relevant for your Flask application.
|
||||
|
||||
```bash
|
||||
opentelemetry-bootstrap --action=install
|
||||
```
|
||||
|
||||
:::note
|
||||
Please make sure that you have installed all the dependencies of your application before running the above command. The command will not install instrumentation for the dependencies which are not installed.
|
||||
:::
|
||||
|
||||
4. **Run your application**<br></br>
|
||||
In the final run command, you can configure environment variables and flags. Flags for exporters:<br></br>
|
||||
|
||||
For running your application, there are a few things that you need to keep in mind. Below are the notes:
|
||||
:::note
|
||||
Don’t run app in reloader/hot-reload mode as it breaks instrumentation. For example, if you use `export Flask_ENV=development`, it enables the reloader mode which breaks OpenTelemetry instrumentation.
|
||||
:::
|
||||
|
||||
For running applications with application servers which are based on [pre fork model](#running-applications-with-gunicorn-uwsgi), like Gunicorn, uWSGI you have to add a post_fork hook or a @postfork decorator in your configuration.
|
||||
|
||||
To start sending data to SigNoz, use the following run command:
|
||||
|
||||
```bash
|
||||
OTEL_RESOURCE_ATTRIBUTES=service.name=<service_name> OTEL_EXPORTER_OTLP_ENDPOINT="http://<IP of SigNoz Backend>:4317" OTEL_EXPORTER_OTLP_PROTOCOL=grpc opentelemetry-instrument <your run command>
|
||||
```
|
||||
|
||||
*<service_name>* is the name of service you want
|
||||
|
||||
*<your_run_command>* can be `python3 app.py` or `flask run`
|
||||
|
||||
`IP of SigNoz backend` is the IP of the machine where you installed SigNoz. If you have installed SigNoz on `localhost`, the endpoint will be `http://localhost:4317` for gRPC exporter and `http://localhost:4318` for HTTP exporter.
|
||||
|
||||
:::note
|
||||
The port numbers are 4317 and 4318 for the gRPC and HTTP exporters respectively. Remember to allow incoming requests to port **4317**/**4318** of machine where SigNoz backend is hosted.
|
||||
:::
|
||||
|
||||
### Validating instrumentation by checking for traces
|
||||
|
||||
With your application running, you can verify that you’ve instrumented your application with OpenTelemetry correctly by confirming that tracing data is being reported to SigNoz.
|
||||
|
||||
To do this, you need to ensure that your application generates some data. Applications will not produce traces unless they are being interacted with, and OpenTelemetry will often buffer data before sending. So you need to interact with your application and wait for some time to see your tracing data in SigNoz.
|
||||
|
||||
Validate your traces in SigNoz:
|
||||
|
||||
1. Trigger an action in your app that generates a web request. Hit the endpoint a number of times to generate some data. Then, wait for some time.
|
||||
2. In SigNoz, open the `Services` tab. Hit the `Refresh` button on the top right corner, and your application should appear in the list of `Applications`.
|
||||
3. Go to the `Traces` tab, and apply relevant filters to see your application’s traces.
|
||||
|
||||
You might see other dummy applications if you’re using SigNoz for the first time. You can remove it by following the docs [here](https://signoz.io/docs/operate/docker-standalone/#remove-the-sample-application).
|
||||
|
||||
<figure data-zoomable align='center'>
|
||||
<img src="/img/docs/opentelemetry_python_app_instrumented.webp" alt="Python Application in the list of services being monitored in SigNoz"/>
|
||||
<figcaption><i>Python Application in the list of services being monitored in SigNoz</i></figcaption></figure>
|
||||
<br></br>
|
@ -0,0 +1,118 @@
|
||||
## Send Traces to SigNoz Cloud
|
||||
|
||||
Based on your application environment, you can choose the setup below to send traces to SigNoz Cloud.
|
||||
|
||||
From VMs, there are two ways to send data to SigNoz Cloud.
|
||||
|
||||
- [Send traces directly to SigNoz Cloud](#send-traces-directly-to-signoz-cloud)
|
||||
- [Send traces via OTel Collector binary](#send-traces-via-otel-collector-binary) (recommended)
|
||||
|
||||
#### **Send traces directly to SigNoz Cloud**
|
||||
|
||||
Step 1. Install the OpenTelemetry dependencies
|
||||
|
||||
```bash
|
||||
pip install opentelemetry-distro==0.38b0
|
||||
pip install opentelemetry-exporter-otlp==1.17.0
|
||||
```
|
||||
|
||||
Step 2. Add automatic instrumentation
|
||||
|
||||
```bash
|
||||
opentelemetry-bootstrap --action=install
|
||||
```
|
||||
|
||||
Step 3. Run your application
|
||||
|
||||
```bash
|
||||
OTEL_RESOURCE_ATTRIBUTES=service.name=<service_name> \
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT="https://ingest.{region}.signoz.cloud:443" \
|
||||
OTEL_EXPORTER_OTLP_HEADERS="signoz-access-token=SIGNOZ_INGESTION_KEY" \
|
||||
opentelemetry-instrument <your_run_command>
|
||||
```
|
||||
|
||||
- *`<service_name>`* is the name of the service you want
|
||||
- *`<your_run_command>`* can be `python3 app.py` or `flask run`
|
||||
- Replace `SIGNOZ_INGESTION_KEY` with the api token provided by SigNoz. You can find it in the email sent by SigNoz with your cloud account details.
|
||||
|
||||
Depending on the choice of your region for SigNoz cloud, the ingest endpoint will vary according to this table.
|
||||
|
||||
| Region | Endpoint |
|
||||
| ------ | -------------------------- |
|
||||
| US | ingest.us.signoz.cloud:443 |
|
||||
| IN | ingest.in.signoz.cloud:443 |
|
||||
| EU | ingest.eu.signoz.cloud:443 |
|
||||
|
||||
Step 4. Validate if your application is sending traces to SigNoz cloud by following the instructions [here](#validating-instrumentation-by-checking-for-traces).
|
||||
|
||||
---
|
||||
|
||||
#### **Send traces via OTel Collector binary**
|
||||
|
||||
OTel Collector binary helps to collect logs, hostmetrics, resource and infra attributes. It is recommended to install Otel Collector binary to collect and send traces to SigNoz cloud. You can correlate signals and have rich contextual data through this way.
|
||||
|
||||
You can find instructions to install OTel Collector binary [here](https://signoz.io/docs/tutorial/opentelemetry-binary-usage-in-virtual-machine/) in your VM. Once you are done setting up your OTel Collector binary, you can follow the below steps for instrumenting your Python application.
|
||||
|
||||
Step 1. Install the OpenTelemetry dependencies
|
||||
|
||||
```bash
|
||||
pip install opentelemetry-distro==0.38b0
|
||||
pip install opentelemetry-exporter-otlp==1.17.0
|
||||
```
|
||||
|
||||
Step 2. Add automatic instrumentation
|
||||
|
||||
```bash
|
||||
opentelemetry-bootstrap --action=install
|
||||
```
|
||||
|
||||
Step 3. To run your application and send data to collector in same VM:
|
||||
|
||||
```bash
|
||||
OTEL_RESOURCE_ATTRIBUTES=service.name=<service_name> \
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4317" \
|
||||
opentelemetry-instrument <your_run_command>
|
||||
```
|
||||
|
||||
where,
|
||||
|
||||
- *`<service_name>`* is the name of the service you want
|
||||
- *`<your_run_command>`* can be `python3 app.py` or `flask run`
|
||||
|
||||
In case you have OtelCollector Agent in different VM, replace localhost:4317 with `<IP Address of the VM>:4317`.
|
||||
|
||||
Step 4. You can validate if your application is sending traces to SigNoz cloud by following the instructions [here](#validating-instrumentation-by-checking-for-traces).
|
||||
|
||||
For Python application deployed on Kubernetes, you need to install OTel Collector agent in your k8s infra to collect and send traces to SigNoz Cloud. You can find the instructions to install OTel Collector agent [here](https://signoz.io/docs/tutorial/kubernetes-infra-metrics/).
|
||||
|
||||
Once you have set up OTel Collector agent, you can proceed with OpenTelemetry Python instrumentation by following the below steps:
|
||||
|
||||
Step 1. Install the OpenTelemetry dependencies
|
||||
|
||||
```bash
|
||||
pip install opentelemetry-distro==0.38b0
|
||||
pip install opentelemetry-exporter-otlp==1.17.0
|
||||
```
|
||||
|
||||
Step 2. Add automatic instrumentation
|
||||
|
||||
```bash
|
||||
opentelemetry-bootstrap --action=install
|
||||
```
|
||||
|
||||
Step 3. Run your application:
|
||||
|
||||
```bash
|
||||
OTEL_RESOURCE_ATTRIBUTES=service.name=<service_name> \
|
||||
OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4317" \
|
||||
opentelemetry-instrument <your_run_command>
|
||||
```
|
||||
|
||||
where,
|
||||
|
||||
- *`<service_name>`* is the name of the service you want
|
||||
- *`<your_run_command>`* can be `python3 app.py` or `flask run`
|
||||
|
||||
Step 4. Make sure to dockerise your application along with OpenTelemetry instrumentation.
|
||||
|
||||
You can validate if your application is sending traces to SigNoz cloud by following the instructions [here](#validating-instrumentation-by-checking-for-traces).
|
@ -0,0 +1,96 @@
|
||||
.connection-status-container {
|
||||
height: calc(100vh - 420px);
|
||||
|
||||
.full-docs-link {
|
||||
margin-bottom: 36px;
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
margin: 16px 0;
|
||||
|
||||
img {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 18px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #e5e7eb;
|
||||
gap: 16px;
|
||||
margin: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.status-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 24px;
|
||||
|
||||
.title {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
}
|
||||
|
||||
.service-info,
|
||||
.language-info,
|
||||
.status-info,
|
||||
.details-info {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.language-info {
|
||||
.language {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
}
|
||||
|
||||
.service-info {
|
||||
flex: 2;
|
||||
}
|
||||
|
||||
.language-info {
|
||||
flex: 2;
|
||||
}
|
||||
|
||||
.status-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.details-info {
|
||||
flex: 3;
|
||||
}
|
||||
|
||||
.status {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
|
||||
svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$lightModeFontColor: rgb(29, 29, 29);
|
||||
|
||||
.lightMode {
|
||||
.connection-status-container {
|
||||
.header .title {
|
||||
color: $lightModeFontColor;
|
||||
|
||||
h1 {
|
||||
color: $lightModeFontColor;
|
||||
}
|
||||
}
|
||||
|
||||
.status-container {
|
||||
color: $lightModeFontColor;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,185 @@
|
||||
import './ConnectionStatus.styles.scss';
|
||||
|
||||
import {
|
||||
CheckCircleTwoTone,
|
||||
CloseCircleTwoTone,
|
||||
LoadingOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import Header from 'container/OnboardingContainer/common/Header/Header';
|
||||
import { useQueryService } from 'hooks/useQueryService';
|
||||
import useResourceAttribute from 'hooks/useResourceAttribute';
|
||||
import { convertRawQueriesToTraceSelectedTags } from 'hooks/useResourceAttribute/utils';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { AppState } from 'store/reducers';
|
||||
import { PayloadProps as QueryServicePayloadProps } from 'types/api/metrics/getService';
|
||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
import { Tags } from 'types/reducer/trace';
|
||||
|
||||
interface ConnectionStatusProps {
|
||||
serviceName: string;
|
||||
language: string;
|
||||
framework: string;
|
||||
}
|
||||
|
||||
export default function ConnectionStatus({
|
||||
serviceName,
|
||||
language,
|
||||
framework,
|
||||
}: ConnectionStatusProps): JSX.Element {
|
||||
const { maxTime, minTime, selectedTime } = useSelector<
|
||||
AppState,
|
||||
GlobalReducer
|
||||
>((state) => state.globalTime);
|
||||
const { queries } = useResourceAttribute();
|
||||
const selectedTags = useMemo(
|
||||
() => (convertRawQueriesToTraceSelectedTags(queries) as Tags[]) || [],
|
||||
[queries],
|
||||
);
|
||||
|
||||
const [pollingInterval, setPollingInterval] = useState<number | false>(15000); // initial Polling interval of 15 secs , Set to false after 5 mins
|
||||
const [retryCount, setRetryCount] = useState(20); // Retry for 5 mins
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [isReceivingData, setIsReceivingData] = useState(false);
|
||||
|
||||
const { data, error, isFetching: isServiceLoading, isError } = useQueryService(
|
||||
{
|
||||
minTime,
|
||||
maxTime,
|
||||
selectedTime,
|
||||
selectedTags,
|
||||
options: {
|
||||
refetchInterval: pollingInterval,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const renderDocsReference = (): JSX.Element => {
|
||||
switch (language) {
|
||||
case 'java':
|
||||
return (
|
||||
<Header
|
||||
entity="java"
|
||||
heading="Java OpenTelemetry Instrumentation"
|
||||
imgURL="/Logos/java.png"
|
||||
docsURL="https://signoz.io/docs/instrumentation/java/"
|
||||
imgClassName="supported-language-img"
|
||||
/>
|
||||
);
|
||||
|
||||
case 'python':
|
||||
return (
|
||||
<Header
|
||||
entity="python"
|
||||
heading="Python OpenTelemetry Instrumentation"
|
||||
imgURL="/Logos/python.png"
|
||||
docsURL="https://signoz.io/docs/instrumentation/python/"
|
||||
imgClassName="supported-language-img"
|
||||
/>
|
||||
);
|
||||
|
||||
case 'javascript':
|
||||
return (
|
||||
<Header
|
||||
entity="javascript"
|
||||
heading="Javascript OpenTelemetry Instrumentation"
|
||||
imgURL="/Logos/javascript.png"
|
||||
docsURL="https://signoz.io/docs/instrumentation/javascript/"
|
||||
imgClassName="supported-language-img"
|
||||
/>
|
||||
);
|
||||
case 'go':
|
||||
return (
|
||||
<Header
|
||||
entity="go"
|
||||
heading="Go OpenTelemetry Instrumentation"
|
||||
imgURL="/Logos/go.png"
|
||||
docsURL="https://signoz.io/docs/instrumentation/golang/"
|
||||
imgClassName="supported-language-img"
|
||||
/>
|
||||
);
|
||||
|
||||
default:
|
||||
return <> </>;
|
||||
}
|
||||
};
|
||||
|
||||
const verifyApplicationData = (response?: QueryServicePayloadProps): void => {
|
||||
if (data || isError) {
|
||||
setRetryCount(retryCount - 1);
|
||||
|
||||
if (retryCount < 0) {
|
||||
setLoading(false);
|
||||
setPollingInterval(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (response && Array.isArray(response)) {
|
||||
for (let i = 0; i < response.length; i += 1) {
|
||||
if (response[i]?.serviceName === serviceName) {
|
||||
setLoading(false);
|
||||
setIsReceivingData(true);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
verifyApplicationData(data);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isServiceLoading, data, error, isError]);
|
||||
|
||||
return (
|
||||
<div className="connection-status-container">
|
||||
<div className="full-docs-link">{renderDocsReference()}</div>
|
||||
<div className="status-container">
|
||||
<div className="service-info">
|
||||
<div className="label"> Service Name </div>
|
||||
<div className="language">{serviceName}</div>
|
||||
</div>
|
||||
|
||||
<div className="language-info">
|
||||
<div className="label"> Language - Framework </div>
|
||||
<div className="language">
|
||||
{language} - {framework}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="status-info">
|
||||
<div className="label"> Status </div>
|
||||
|
||||
<div className="status">
|
||||
{(loading || isServiceLoading) && <LoadingOutlined />}
|
||||
{!(loading || isServiceLoading) && isReceivingData && (
|
||||
<>
|
||||
<CheckCircleTwoTone twoToneColor="#52c41a" />
|
||||
<span> Success </span>
|
||||
</>
|
||||
)}
|
||||
{!(loading || isServiceLoading) && !isReceivingData && (
|
||||
<>
|
||||
<CloseCircleTwoTone twoToneColor="#e84749" />
|
||||
<span> Failed </span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="details-info">
|
||||
<div className="label"> Details </div>
|
||||
|
||||
<div className="details">
|
||||
{(loading || isServiceLoading) && <div> Waiting for Update </div>}
|
||||
{!(loading || isServiceLoading) && isReceivingData && (
|
||||
<div> Received data from the application successfully. </div>
|
||||
)}
|
||||
{!(loading || isServiceLoading) && !isReceivingData && (
|
||||
<div> Could not detect the install </div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
.infrastructure-monitoring-module-container {
|
||||
padding: 48px 0;
|
||||
|
||||
.content-container {
|
||||
.heading {
|
||||
.title {
|
||||
a {
|
||||
color: rgb(232, 112, 64);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.subheading {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
margin-bottom: 16px;
|
||||
|
||||
.recevier-types {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 14px;
|
||||
font-weight: 300;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
import './InfrastructureMonitoring.styles.scss';
|
||||
|
||||
import { MDXProvider } from '@mdx-js/react';
|
||||
import { Tabs } from 'antd';
|
||||
|
||||
import Prometheus from './prometheus.md';
|
||||
import SpecificReceiver from './specific-metric-receiver.md';
|
||||
|
||||
const enum ReceiverType {
|
||||
specific_metric_receiver = 'Specific Metric Receiver',
|
||||
Prometheus = 'Prometheus',
|
||||
}
|
||||
|
||||
const supportedLanguages = [
|
||||
{
|
||||
name: 'specific_metric_receiver',
|
||||
label: 'Specific Metric Receiver',
|
||||
},
|
||||
{
|
||||
name: 'prometheus',
|
||||
label: 'Prometheus',
|
||||
},
|
||||
];
|
||||
|
||||
export default function InfrastructureMonitoring({
|
||||
activeStep,
|
||||
}: {
|
||||
activeStep: number;
|
||||
}): JSX.Element {
|
||||
const renderEnableReceiverByType = (receiverType: string): JSX.Element => {
|
||||
if (receiverType === ReceiverType.specific_metric_receiver) {
|
||||
return <SpecificReceiver />;
|
||||
}
|
||||
|
||||
return <Prometheus />;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="infrastructure-monitoring-module-container">
|
||||
{activeStep === 2 && (
|
||||
<div className="content-container">
|
||||
<div className="heading">
|
||||
<h2 className="title">
|
||||
By default, when you install SigNoz, only the
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href="https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/receiver/hostmetricsreceiver/README.md"
|
||||
>
|
||||
Hostmetric receiver
|
||||
</a>
|
||||
is enabled.
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div className="subheading">
|
||||
Before you can query other metrics, you must first enable additional
|
||||
receivers in SigNoz. There are two ways in which you can send metrics to
|
||||
SigNoz using OpenTelemetry:
|
||||
<br />
|
||||
<div className="recevier-types">
|
||||
<small> 1. Enable a Specific Metric Receiver </small>
|
||||
<small> 2. Enable a Prometheus Receiver </small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<MDXProvider>
|
||||
<Tabs
|
||||
defaultActiveKey="1"
|
||||
items={supportedLanguages.map((language, i) => {
|
||||
const id = String(i + 1);
|
||||
|
||||
return {
|
||||
label: <div className="language-tab-item">{language.label}</div>,
|
||||
key: id,
|
||||
children: renderEnableReceiverByType(language.name),
|
||||
};
|
||||
})}
|
||||
/>
|
||||
</MDXProvider>
|
||||
</div>
|
||||
)}
|
||||
{activeStep === 3 && <div> Infra Monitoring Step 3 </div>}
|
||||
</div>
|
||||
);
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
## Enable a Prometheus Receiver
|
||||
|
||||
SigNoz supports all the exporters that are listed on the [Exporters and Integrations](https://prometheus.io/docs/instrumenting/exporters/) page of the Prometheus documentation. If you have a running Prometheus instance, and you expose metrics in Prometheus, then you can scrape them in SigNoz by configuring Prometheus receivers in the `receivers.prometheus.config.scrape_configs` section of the `deploy/docker/clickhouse-setup/otel-collector-metrics-config.yaml` file.
|
||||
|
||||
To enable a Prometheus receiver, follow the steps below:
|
||||
|
||||
1. Open the `deploy/docker/clickhouse-setup/otel-collector-metrics-config.yaml` file in a plain-text editor.
|
||||
2. Enable a new Prometheus receiver. Depending on your use case, there are two ways in which you can enable a new Prometheus exporter:
|
||||
|
||||
- **By creating a new job**: The following example shows how you can enable a Prometheus receiver by creating a new job named `my-new-job`:
|
||||
|
||||
```yaml {15-18}
|
||||
receivers:
|
||||
otlp:
|
||||
protocols:
|
||||
grpc:
|
||||
http:
|
||||
|
||||
# Data sources: metrics
|
||||
prometheus:
|
||||
config:
|
||||
scrape_configs:
|
||||
- job_name: 'otel-collector'
|
||||
scrape_interval: 30s
|
||||
static_configs:
|
||||
- targets: ['otel-collector:8889']
|
||||
- job_name: 'my-new-job'
|
||||
scrape_interval: 30s
|
||||
static_configs:
|
||||
- targets: ['localhost:8080']
|
||||
processors:
|
||||
batch:
|
||||
send_batch_size: 1000
|
||||
timeout: 10s
|
||||
# This file was truncated for brevity.
|
||||
```
|
||||
|
||||
- **By adding a new target to an existing job**: The following example shows the default `otel-collector` job to which a new target (`localhost:8080`) was added:
|
||||
|
||||
```yaml {14}
|
||||
receivers:
|
||||
otlp:
|
||||
protocols:
|
||||
grpc:
|
||||
http:
|
||||
|
||||
# Data sources: metrics
|
||||
prometheus:
|
||||
config:
|
||||
scrape_configs:
|
||||
- job_name: 'otel-collector'
|
||||
scrape_interval: 30s
|
||||
static_configs:
|
||||
- targets: ['otel-collector:8889', 'localhost:8080']
|
||||
processors:
|
||||
batch:
|
||||
send_batch_size: 1000
|
||||
timeout: 10s
|
||||
# This file was truncated for brevity.
|
||||
```
|
||||
|
||||
Note that all the jobs are scraped in parallel, and all targets inside a job are scraped serially. For more details about configuring jobs and targets, see the following sections of the Prometheus documentation:
|
||||
|
||||
- [<Scrape_config>](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config)
|
||||
- [Jobs and Instances](https://prometheus.io/docs/concepts/jobs_instances/)
|
||||
|
||||
3. <SaveChangesRestart />
|
@ -0,0 +1,72 @@
|
||||
## Enable a Specific Metric Receiver
|
||||
|
||||
SigNoz supports all the receivers that are listed in the [opentelemetry-collector-contrib](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver) GitHub repository. To configure a new metric receiver, you must edit the `receivers` section of the `deploy/docker/clickhouse-setup/otel-collector-config.yaml` file. The following example shows the default configuration in which the `hostmetrics` receiver is enabled:
|
||||
|
||||
```yaml {14-22}
|
||||
receivers:
|
||||
otlp/spanmetrics:
|
||||
protocols:
|
||||
grpc:
|
||||
endpoint: 'localhost:12345'
|
||||
otlp:
|
||||
protocols:
|
||||
grpc:
|
||||
http:
|
||||
jaeger:
|
||||
protocols:
|
||||
grpc:
|
||||
thrift_http:
|
||||
hostmetrics:
|
||||
collection_interval: 30s
|
||||
scrapers:
|
||||
cpu:
|
||||
load:
|
||||
memory:
|
||||
disk:
|
||||
filesystem:
|
||||
network:
|
||||
processors:
|
||||
batch:
|
||||
send_batch_size: 1000
|
||||
timeout: 10s
|
||||
# This file was truncated for brevity
|
||||
```
|
||||
|
||||
To enable a new OpenTelemetry receiver, follow the steps below:
|
||||
|
||||
1. Move into the directory in which you installed SigNoz, and open the `deploy/docker/clickhouse-setup/otel-collector-config.yaml` file in a plain-text editor.
|
||||
2. Configure your receivers. The following example shows how you can enable a receiver named `examplereceiver`:
|
||||
|
||||
```yaml {23,24}
|
||||
receivers:
|
||||
otlp/spanmetrics:
|
||||
protocols:
|
||||
grpc:
|
||||
endpoint: 'localhost:12345'
|
||||
otlp:
|
||||
protocols:
|
||||
grpc:
|
||||
http:
|
||||
jaeger:
|
||||
protocols:
|
||||
grpc:
|
||||
thrift_http:
|
||||
hostmetrics:
|
||||
collection_interval: 30s
|
||||
scrapers:
|
||||
cpu:
|
||||
load:
|
||||
memory:
|
||||
disk:
|
||||
filesystem:
|
||||
network:
|
||||
examplereceiver:
|
||||
endpoint: 1.2.3.4:8080
|
||||
processors:
|
||||
batch:
|
||||
send_batch_size: 1000
|
||||
timeout: 10s
|
||||
# This file was truncated for brevity.
|
||||
```
|
||||
|
||||
For details about configuring OpenTelemetry receivers, see the [README](https://github.com/open-telemetry/opentelemetry-collector/blob/main/receiver/README.md) page of the `opentelemetry-collector` GitHub repository. 3. <SaveChangesRestart />
|
@ -0,0 +1,89 @@
|
||||
import { MDXProvider } from '@mdx-js/react';
|
||||
import { Tabs } from 'antd';
|
||||
import Header from 'container/OnboardingContainer/common/Header/Header';
|
||||
|
||||
import ConnectionStatus from '../common/LogsConnectionStatus/LogsConnectionStatus';
|
||||
import LogsFromLogFile from './applicationLogsFromLogFile.md';
|
||||
import LogsUsingJavaOtelSDK from './applicationLogsUsingJavaOtelSDK.md';
|
||||
import LogsUsingPythonOtelSDK from './applicationLogsUsingPythonOtelSDK.md';
|
||||
|
||||
interface ApplicationLogsProps {
|
||||
type: string;
|
||||
activeStep: number;
|
||||
}
|
||||
|
||||
const collectLogsFromFileURL =
|
||||
'https://signoz.io/docs/userguide/collect_logs_from_file/';
|
||||
const collectLogsFromOTELSDK =
|
||||
'https://signoz.io/docs/userguide/collecting_application_logs_otel_sdk_java/';
|
||||
|
||||
export default function ApplicationLogs({
|
||||
type,
|
||||
activeStep,
|
||||
}: ApplicationLogsProps): JSX.Element {
|
||||
function renderContentForCollectingLogsOtelSDK(language: string): JSX.Element {
|
||||
if (language === 'Java') {
|
||||
return <LogsUsingJavaOtelSDK />;
|
||||
}
|
||||
return <LogsUsingPythonOtelSDK />;
|
||||
}
|
||||
|
||||
enum ApplicationLogsType {
|
||||
FROM_LOG_FILE = 'from-log-file',
|
||||
USING_OTEL_COLLECTOR = 'using-otel-sdk',
|
||||
}
|
||||
|
||||
const docsURL =
|
||||
type === ApplicationLogsType.FROM_LOG_FILE
|
||||
? collectLogsFromFileURL
|
||||
: collectLogsFromOTELSDK;
|
||||
|
||||
return (
|
||||
<>
|
||||
{activeStep === 2 && (
|
||||
<div className="golang-setup-instructions-container">
|
||||
<Header
|
||||
entity="docker"
|
||||
heading={
|
||||
type === ApplicationLogsType.FROM_LOG_FILE
|
||||
? 'Collecting Application Logs from Log file'
|
||||
: 'Collecting Application Logs Using OTEL SDK'
|
||||
}
|
||||
imgURL={`/Logos/${
|
||||
type === ApplicationLogsType.FROM_LOG_FILE
|
||||
? 'software-window'
|
||||
: 'cmd-terminal'
|
||||
}.svg`}
|
||||
docsURL={docsURL}
|
||||
imgClassName="supported-logs-type-img"
|
||||
/>
|
||||
|
||||
<div className="content-container">
|
||||
<MDXProvider>
|
||||
{type === ApplicationLogsType.FROM_LOG_FILE && <LogsFromLogFile />}
|
||||
{type === ApplicationLogsType.USING_OTEL_COLLECTOR && (
|
||||
<Tabs
|
||||
defaultActiveKey="1"
|
||||
items={['Java', 'Python'].map((language, i) => {
|
||||
const id = String(i + 1);
|
||||
|
||||
return {
|
||||
label: <div className="language-tab-item">{language}</div>,
|
||||
key: id,
|
||||
children: renderContentForCollectingLogsOtelSDK(language),
|
||||
};
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
</MDXProvider>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{activeStep === 3 && (
|
||||
<div className="connection-status-container">
|
||||
<ConnectionStatus logType={type} />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
## Collect Application Logs from Log file in SigNoz cloud
|
||||
|
||||
If you don’t already have a SigNoz cloud account, you can sign up [here](https://signoz.io/teams/).
|
||||
|
||||
- Add otel collector binary to your VM by following this [guide](https://signoz.io/docs/tutorial/opentelemetry-binary-usage-in-virtual-machine/).
|
||||
|
||||
- Add the filelog reciever to `config.yaml`.
|
||||
|
||||
```yaml {3-15}
|
||||
receivers:
|
||||
...
|
||||
filelog/app:
|
||||
include: [ /tmp/app.log ]
|
||||
start_at: beginning
|
||||
...
|
||||
```
|
||||
|
||||
`start_at: beginning` can be removed once you are done testing.
|
||||
|
||||
For parsing logs of different formats you will have to use operators, you can read more about operators [here](https://signoz.io/docs/userguide/logs/#operators-for-parsing-and-manipulating-logs).
|
||||
|
||||
For more configurations that are available for filelog receiver please check [here](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/filelogreceiver).
|
||||
|
||||
- Next we will modify our pipeline inside `config.yaml` to include the receiver we have created above.
|
||||
|
||||
```yaml {4}
|
||||
service:
|
||||
....
|
||||
logs:
|
||||
receivers: [otlp, filelog/app]
|
||||
processors: [batch]
|
||||
exporters: [otlp]
|
||||
```
|
||||
|
||||
- Now we can restart the otel collector so that new changes are applied.
|
||||
|
||||
- The log will be exported, if you add more lines to the log file it will be exported as well
|
||||
- If there are no errors your logs will be visible on SigNoz UI.
|
@ -0,0 +1,33 @@
|
||||
# Collecting Application Logs Using OTEL Java Agent
|
||||
|
||||
You can directly send your application logs to SigNoz using Java Agent provided by opentlemetry.
|
||||
In this blog we will run a sample java application and send the application logs to SigNoz.
|
||||
|
||||
For collecting logs we will have to download the java agent from [here](https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar).
|
||||
|
||||
To sends logs from a Java application you will have to add the agent and add the environment variables for the agent
|
||||
|
||||
The command for it will look like
|
||||
|
||||
```bash
|
||||
OTEL_LOGS_EXPORTER=otlp OTEL_EXPORTER_OTLP_ENDPOINT="http://<IP of SigNoz Backend>:4317" OTEL_RESOURCE_ATTRIBUTES=service.name=<app_name> java -javaagent:/path/opentelemetry-javaagent.jar -jar <myapp>.jar
|
||||
```
|
||||
|
||||
<br></br>
|
||||
|
||||
In the below example we will configure a java application to send logs to SigNoz.
|
||||
|
||||
## How to Collect Application Logs Using OTEL Java Agent?
|
||||
|
||||
- Clone this [repository](https://github.com/SigNoz/spring-petclinic)
|
||||
- Build the application using `./mvnw package`
|
||||
- Now run the application
|
||||
|
||||
```
|
||||
OTEL_LOGS_EXPORTER=otlp OTEL_EXPORTER_OTLP_ENDPOINT="http://<host>:4317" OTEL_RESOURCE_ATTRIBUTES=service.name=myapp java -javaagent:/path/opentelemetry-javaagent.jar -jar target/*.jar
|
||||
```
|
||||
|
||||
You will have to replace your the value of `host` as `0.0.0.0` if SigNoz is running in the same host, for other configurations please check the
|
||||
[troubleshooting](../install/troubleshooting.md#signoz-otel-collector-address-grid) guide.
|
||||
|
||||
- Now if the application starts successfully the logs will be visible on SigNoz UI.
|
@ -0,0 +1,3 @@
|
||||
# Collecting Application Logs Using OTEL Python SDK
|
||||
|
||||
You can directly send logs of your application to SigNoz using the Python SDKs provided by opentlemetry. Please find an example [here](https://github.com/open-telemetry/opentelemetry-python/tree/main/docs/examples/logs).
|
@ -0,0 +1,38 @@
|
||||
import { MDXProvider } from '@mdx-js/react';
|
||||
import Header from 'container/OnboardingContainer/common/Header/Header';
|
||||
|
||||
import ConnectionStatus from '../common/LogsConnectionStatus/LogsConnectionStatus';
|
||||
import Post from './docker.md';
|
||||
|
||||
export default function Docker({
|
||||
activeStep,
|
||||
}: {
|
||||
activeStep: number;
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<>
|
||||
{activeStep === 2 && (
|
||||
<div className="golang-setup-instructions-container">
|
||||
<Header
|
||||
entity="docker"
|
||||
heading="Collecting Docker container logs"
|
||||
imgURL="/Logos/docker.svg"
|
||||
docsURL="https://signoz.io/docs/userguide/collect_docker_logs/"
|
||||
imgClassName="supported-logs-type-img"
|
||||
/>
|
||||
|
||||
<div className="content-container">
|
||||
<MDXProvider>
|
||||
<Post />
|
||||
</MDXProvider>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{activeStep === 3 && (
|
||||
<div className="connection-status-container">
|
||||
<ConnectionStatus logType="docker" />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
## Collect Syslogs in SigNoz cloud
|
||||
|
||||
### Setup Otel Collector as agent
|
||||
|
||||
- Add `config.yaml`
|
||||
```yaml {22-26}
|
||||
receivers:
|
||||
filelog:
|
||||
include: [/tmp/python.log]
|
||||
start_at: beginning
|
||||
operators:
|
||||
- type: json_parser
|
||||
timestamp:
|
||||
parse_from: attributes.time
|
||||
layout: '%Y-%m-%d,%H:%M:%S %z'
|
||||
- type: move
|
||||
from: attributes.message
|
||||
to: body
|
||||
- type: remove
|
||||
field: attributes.time
|
||||
processors:
|
||||
batch:
|
||||
send_batch_size: 10000
|
||||
send_batch_max_size: 11000
|
||||
timeout: 10s
|
||||
exporters:
|
||||
otlp:
|
||||
endpoint: 'ingest.{region}.signoz.cloud:443'
|
||||
tls:
|
||||
insecure: false
|
||||
headers:
|
||||
'signoz-access-token': '<SIGNOZ_INGESTION_KEY>'
|
||||
service:
|
||||
pipelines:
|
||||
logs:
|
||||
receivers: [filelog]
|
||||
processors: [batch]
|
||||
exporters: [otlp/log]
|
||||
```
|
||||
|
||||
````
|
||||
Depending on the choice of your region for SigNoz cloud, the otlp endpoint will vary according to this table.
|
||||
|
||||
| Region | Endpoint |
|
||||
| ------ | -------------------------- |
|
||||
| US | ingest.us.signoz.cloud:443 |
|
||||
| IN | ingest.in.signoz.cloud:443 |
|
||||
| EU | ingest.eu.signoz.cloud:443 |
|
||||
|
||||
* We will start our otel-collector container.
|
||||
```bash
|
||||
docker run -d --name signoz-host-otel-collector -p 2255:2255 --user root -v $(pwd)/config.yaml:/etc/otel/config.yaml signoz/signoz-otel-collector:0.79.0
|
||||
````
|
||||
|
||||
### Run logspout to collect docker container logs and send it to local otel collector.
|
||||
|
||||
Logspout helps in collecting Docker logs by connecting to Docker socket.
|
||||
|
||||
- Run logspout
|
||||
|
||||
```bash
|
||||
docker run --net=host --rm --name="logspout" \
|
||||
--volume=/var/run/docker.sock:/var/run/docker.sock \
|
||||
gliderlabs/logspout \
|
||||
syslog+tcp://<host>:2255
|
||||
```
|
||||
|
||||
For finding the right host for your SigNoz cluster please follow the guide [here](../install/troubleshooting.md#signoz-otel-collector-address-grid).
|
||||
|
||||
- If there are no errors your logs will be exported and will be visible on the SigNoz UI.
|
@ -0,0 +1,38 @@
|
||||
import { MDXProvider } from '@mdx-js/react';
|
||||
import Header from 'container/OnboardingContainer/common/Header/Header';
|
||||
|
||||
import ConnectionStatus from '../common/LogsConnectionStatus/LogsConnectionStatus';
|
||||
import Post from './kubernetes.md';
|
||||
|
||||
export default function Kubernetes({
|
||||
activeStep,
|
||||
}: {
|
||||
activeStep: number;
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<>
|
||||
{activeStep === 2 && (
|
||||
<div className="golang-setup-instructions-container">
|
||||
<Header
|
||||
entity="kubernetes"
|
||||
heading="Collecting Kubernetes Pod logs"
|
||||
imgURL="/Logos/kubernetes.svg"
|
||||
docsURL="https://signoz.io/docs/userguide/collect_kubernetes_pod_logs/#collect-kubernetes-pod-logs-in-signoz-cloud"
|
||||
imgClassName="supported-logs-type-img"
|
||||
/>
|
||||
|
||||
<div className="content-container">
|
||||
<MDXProvider>
|
||||
<Post />
|
||||
</MDXProvider>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{activeStep === 3 && (
|
||||
<div className="connection-status-container">
|
||||
<ConnectionStatus logType="kubernetes" />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
## Collect Kubernetes Pod Logs in SigNoz Cloud
|
||||
|
||||
To collect logs from your kubernetes cluster, you will need to deploy k8s-infra chart. Please follow the guide [here](/docs/tutorial/kubernetes-infra-metrics/). Log collection of pods from all namespaces is enabled by default except for pods in `kube-system` and `hotrod`. To modify the log collection mechanism, please follow the guides below.
|
||||
|
||||
- [Disable automatic pod logs collection](#steps-to-disable-automatic-pod-logs-collection)
|
||||
- [Filter/Exclude logs collection](#steps-to-filterexclude-logs-collection)
|
@ -0,0 +1,152 @@
|
||||
.logs-management-module-container {
|
||||
min-height: calc(100vh - 300px);
|
||||
padding: 48px 0;
|
||||
|
||||
.header {
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 14px;
|
||||
font-weight: 300;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.supported-logs-type-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.supported-logs-type {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
width: 300px;
|
||||
padding: 16px;
|
||||
box-sizing: border-box;
|
||||
height: 120px;
|
||||
background: #1d1d1d;
|
||||
border: 1px solid #424242;
|
||||
border-radius: 3px;
|
||||
color: #e5e7eb;
|
||||
cursor: pointer;
|
||||
|
||||
&.selected {
|
||||
background-color: #111a2c;
|
||||
border: 0.5px solid #3c89e8;
|
||||
}
|
||||
}
|
||||
|
||||
.supported-logs-type-img {
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
.selected-logs-type-setup-instructions {
|
||||
padding: 24px 0;
|
||||
}
|
||||
|
||||
div[class*='-setup-instructions-container'] {
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
|
||||
margin: 16px 0;
|
||||
|
||||
img {
|
||||
height: 32px;
|
||||
min-height: 32px;
|
||||
min-width: 32px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 18px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #e5e7eb;
|
||||
gap: 16px;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 14px;
|
||||
margin-bottom: 8px;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: #292d3e;
|
||||
padding: 8px;
|
||||
overflow: auto;
|
||||
border-radius: 3px;
|
||||
|
||||
code {
|
||||
overflow: auto;
|
||||
text-wrap: wrap;
|
||||
}
|
||||
}
|
||||
|
||||
.content-container {
|
||||
padding: 24px;
|
||||
margin: 16px 0;
|
||||
background: rgba(29, 29, 29, 1);
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.detailed-docs-link {
|
||||
display: flex;
|
||||
margin: 8px 0;
|
||||
font-size: 12px;
|
||||
|
||||
a {
|
||||
padding-left: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.language-tab-item {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
img {
|
||||
height: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
$lightModeFontColor: rgb(29, 29, 29);
|
||||
|
||||
.lightMode {
|
||||
.logs-management-module-container {
|
||||
.header {
|
||||
color: $lightModeFontColor;
|
||||
}
|
||||
|
||||
div[class*='-setup-instructions-container'] {
|
||||
.header {
|
||||
h1 {
|
||||
color: $lightModeFontColor;
|
||||
}
|
||||
}
|
||||
|
||||
.framework-selector {
|
||||
.label {
|
||||
color: $lightModeFontColor;
|
||||
}
|
||||
}
|
||||
|
||||
.service-name-container {
|
||||
.label {
|
||||
color: $lightModeFontColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,122 @@
|
||||
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
||||
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
||||
import './LogsManagement.styles.scss';
|
||||
|
||||
import cx from 'classnames';
|
||||
import { useState } from 'react';
|
||||
|
||||
import ApplicationLogs from './ApplicationLogs/ApplicationLogs';
|
||||
import Docker from './Docker/Docker';
|
||||
import Kubernetes from './Kubernetes/Kubernetes';
|
||||
import Nodejs from './Nodejs/Nodejs';
|
||||
import SysLogs from './SysLogs/SysLogs';
|
||||
|
||||
const supportedLogTypes = [
|
||||
{
|
||||
name: 'Kubernetes Pod Logs',
|
||||
id: 'kubernetes',
|
||||
imgURL: `Logos/kubernetes.svg`,
|
||||
},
|
||||
{
|
||||
name: 'Docker Container Logs',
|
||||
id: 'docker',
|
||||
imgURL: `Logos/docker.svg`,
|
||||
},
|
||||
{
|
||||
name: 'SysLogs',
|
||||
id: 'syslogs',
|
||||
imgURL: `Logos/syslogs.svg`,
|
||||
},
|
||||
{
|
||||
name: 'Application Logs',
|
||||
id: 'application_logs_log_file',
|
||||
imgURL: `Logos/software-window.svg`,
|
||||
},
|
||||
{
|
||||
name: 'NodeJS Winston Logs ',
|
||||
id: 'nodejs',
|
||||
imgURL: `Logos/node-js.svg`,
|
||||
},
|
||||
{
|
||||
name: 'Logs from existing Collectors',
|
||||
id: 'application_logs_otel_sdk',
|
||||
imgURL: `Logos/cmd-terminal.svg`,
|
||||
},
|
||||
];
|
||||
|
||||
export default function LogsManagement({
|
||||
activeStep,
|
||||
handleLogTypeSelect,
|
||||
}: {
|
||||
activeStep: number;
|
||||
handleLogTypeSelect: (id: string) => any;
|
||||
}): JSX.Element {
|
||||
const [selectedLogsType, setSelectedLogsType] = useState('kubernetes');
|
||||
|
||||
const renderSelectedLanguageSetupInstructions = ():
|
||||
| JSX.Element
|
||||
| undefined => {
|
||||
switch (selectedLogsType) {
|
||||
case 'kubernetes':
|
||||
return <Kubernetes activeStep={activeStep} />;
|
||||
case 'docker':
|
||||
return <Docker activeStep={activeStep} />;
|
||||
case 'application_logs_log_file':
|
||||
return <ApplicationLogs type="from-log-file" activeStep={activeStep} />;
|
||||
case 'application_logs_otel_sdk':
|
||||
return <ApplicationLogs type="using-otel-sdk" activeStep={activeStep} />;
|
||||
case 'syslogs':
|
||||
return <SysLogs activeStep={activeStep} />;
|
||||
case 'nodejs':
|
||||
return <Nodejs activeStep={activeStep} />;
|
||||
default:
|
||||
return <> </>;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="logs-management-module-container">
|
||||
{activeStep === 2 && (
|
||||
<>
|
||||
<div className="header">
|
||||
<h1>Select a Logs type</h1>
|
||||
<h4> Choose the logs that you want to receive on SigNoz </h4>
|
||||
</div>
|
||||
|
||||
<div className="supported-logs-type-container">
|
||||
{supportedLogTypes.map((logType) => (
|
||||
<div
|
||||
className={cx(
|
||||
'supported-logs-type',
|
||||
selectedLogsType === logType.id ? 'selected' : '',
|
||||
)}
|
||||
key={logType.name}
|
||||
onClick={() => {
|
||||
handleLogTypeSelect(logType.id);
|
||||
setSelectedLogsType(logType.id);
|
||||
}}
|
||||
>
|
||||
<img
|
||||
className={cx('supported-logs-type-img')}
|
||||
src={`${logType.imgURL}`}
|
||||
alt=""
|
||||
/>
|
||||
|
||||
<div> {logType.name} </div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
{selectedLogsType && (
|
||||
<div
|
||||
className={cx('selected-logs-type-setup-instructions', selectedLogsType)}
|
||||
>
|
||||
{renderSelectedLanguageSetupInstructions()}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
import { MDXProvider } from '@mdx-js/react';
|
||||
import Header from 'container/OnboardingContainer/common/Header/Header';
|
||||
|
||||
import ConnectionStatus from '../common/LogsConnectionStatus/LogsConnectionStatus';
|
||||
import Post from './nodejs.md';
|
||||
|
||||
export default function Nodejs({
|
||||
activeStep,
|
||||
}: {
|
||||
activeStep: number;
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<>
|
||||
{activeStep === 2 && (
|
||||
<div className="golang-setup-instructions-container">
|
||||
<Header
|
||||
entity="nodejs"
|
||||
heading="Collecting NodeJS winston logs"
|
||||
imgURL="/Logos/node-js.svg"
|
||||
docsURL="https://signoz.io/docs/userguide/collecting_nodejs_winston_logs/"
|
||||
imgClassName="supported-logs-type-img"
|
||||
/>
|
||||
|
||||
<div className="content-container">
|
||||
<MDXProvider>
|
||||
<Post />
|
||||
</MDXProvider>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{activeStep === 3 && (
|
||||
<div className="connection-status-container">
|
||||
<ConnectionStatus logType="nodejs" />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
# Collecting NodeJS winston logs
|
||||
|
||||
If you are using `winston` as your logging library in your Nodejs application, you can export these logs to SigNoz very easily using various transports provided by `winston`.
|
||||
|
||||
## Collecting Nodejs logs when application is deployed on Docker or Kubernetes
|
||||
|
||||
When your application is deployed in Docker or a Kubernetes cluster the logs from the console are automatically collected and stored in the node. The SigNoz collector will automatically collect the logs and it will be visible on the SigNoz UI.
|
||||
|
||||
You can add a console transport very easily as stated <a href="https://github.com/winstonjs/winston/blob/master/docs/transports.md#console-transport" rel="noopener noreferrer nofollow" target="_blank">here</a>.
|
||||
|
||||
```
|
||||
logger.add(new winston.transports.Console(options));
|
||||
```
|
||||
|
||||
## Collecting Nodejs logs when application is deployed on a Host
|
||||
|
||||
When you run your application directly on the host, you will be required to add a intermediary medium ex:- a file, where you can export your logs and the otel-collector can read them and push to signoz.
|
||||
|
||||
You can add a file transport very easily as stated <a href="https://github.com/winstonjs/winston/blob/master/docs/transports.md#file-transport" rel="noopener noreferrer nofollow" target="_blank">here</a>.
|
||||
|
||||
```
|
||||
logger.add(new winston.transports.File(options));
|
||||
```
|
||||
|
||||
Once you run your application and the logs are added to a file, you can configure otel collector to read from that file.
|
||||
|
||||
For configuring it you can follow the guide [here](./collecting_application_logs_file.md#collecting-application-logs-from-log-file).
|
||||
|
||||
Once you configure the otel collector the logs will be visible on the UI.
|
@ -0,0 +1,38 @@
|
||||
import { MDXProvider } from '@mdx-js/react';
|
||||
import Header from 'container/OnboardingContainer/common/Header/Header';
|
||||
|
||||
import ConnectionStatus from '../common/LogsConnectionStatus/LogsConnectionStatus';
|
||||
import Post from './syslogs.md';
|
||||
|
||||
export default function SysLogs({
|
||||
activeStep,
|
||||
}: {
|
||||
activeStep: number;
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<>
|
||||
{activeStep === 2 && (
|
||||
<div className="golang-setup-instructions-container">
|
||||
<Header
|
||||
entity="syslogs"
|
||||
heading="Collecting Syslogs"
|
||||
imgURL="/Logos/syslogs.svg"
|
||||
docsURL="https://signoz.io/docs/userguide/collecting_syslogs/"
|
||||
imgClassName="supported-logs-type-img"
|
||||
/>
|
||||
|
||||
<div className="content-container">
|
||||
<MDXProvider>
|
||||
<Post />
|
||||
</MDXProvider>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{activeStep === 3 && (
|
||||
<div className="connection-status-container">
|
||||
<ConnectionStatus logType="syslogs" />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
## Collect Syslogs in SigNoz cloud
|
||||
|
||||
If you don’t already have a SigNoz cloud account, you can sign up [here](https://signoz.io/teams/).
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="VM" label="VM" default>
|
||||
|
||||
- Add otel collector binary to your VM by following this [guide](https://signoz.io/docs/tutorial/opentelemetry-binary-usage-in-virtual-machine/).
|
||||
- Add the syslog reciever to `config.yaml` to otel-collector.
|
||||
|
||||
```yaml {2-10}
|
||||
receivers:
|
||||
syslog:
|
||||
tcp:
|
||||
listen_address: '0.0.0.0:54527'
|
||||
protocol: rfc3164
|
||||
location: UTC
|
||||
operators:
|
||||
- type: move
|
||||
from: attributes.message
|
||||
to: body
|
||||
```
|
||||
|
||||
Here we are collecting the logs and moving message from attributes to body using operators that are available.
|
||||
You can read more about operators [here](./logs.md#operators-for-parsing-and-manipulating-logs).
|
||||
|
||||
For more configurations that are available for syslog receiver please check [here](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/syslogreceiver).
|
||||
|
||||
- Next we will modify our pipeline inside `config.yaml` of otel-collector to include the receiver we have created above.
|
||||
|
||||
```yaml {4}
|
||||
service:
|
||||
....
|
||||
logs:
|
||||
receivers: [otlp, syslog]
|
||||
processors: [batch]
|
||||
exporters: [otlp]
|
||||
```
|
||||
|
||||
- Now we can restart the otel collector so that new changes are applied and we can forward our logs to port `54527`.
|
||||
|
||||
- Modify your `rsyslog.conf` file present inside `/etc/` by running the following command:
|
||||
|
||||
```bash
|
||||
sudo vim /etc/rsyslog.conf
|
||||
```
|
||||
|
||||
and adding the this line at the end
|
||||
|
||||
```
|
||||
template(
|
||||
name="UTCTraditionalForwardFormat"
|
||||
type="string"
|
||||
string="<%PRI%>%TIMESTAMP:::date-utc% %HOSTNAME% %syslogtag:1:32%%msg:::sp-if-no-1st-sp%%msg%"
|
||||
)
|
||||
|
||||
*.* action(type="omfwd" target="0.0.0.0" port="54527" protocol="tcp" template="UTCTraditionalForwardFormat")
|
||||
```
|
||||
|
||||
For production use cases it is recommended to use something like below:
|
||||
|
||||
```
|
||||
template(
|
||||
name="UTCTraditionalForwardFormat"
|
||||
type="string"
|
||||
string="<%PRI%>%TIMESTAMP:::date-utc% %HOSTNAME% %syslogtag:1:32%%msg:::sp-if-no-1st-sp%%msg%"
|
||||
)
|
||||
|
||||
*.* action(type="omfwd" target="0.0.0.0" port="54527" protocol="tcp"
|
||||
action.resumeRetryCount="10"
|
||||
queue.type="linkedList" queue.size="10000" template="UTCTraditionalForwardFormat")
|
||||
```
|
||||
|
||||
So that you have retires and queue in place to de-couple the sending from the other logging action.
|
||||
|
||||
The value of `target` might vary depending on where SigNoz is deployed, since it is deployed on the same host I am using `0.0.0.0` for more help you can visit [here](../install/troubleshooting.md#signoz-otel-collector-address-grid).
|
||||
|
||||
- Now restart your rsyslog service by running `sudo systemctl restart rsyslog.service`
|
||||
- You can check the status of service by running `sudo systemctl status rsyslog.service`
|
||||
- If there are no errors your logs will be visible on SigNoz UI.
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
@ -0,0 +1,98 @@
|
||||
.connection-status-container {
|
||||
.full-docs-link {
|
||||
margin-bottom: 36px;
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
margin: 16px 0;
|
||||
|
||||
img {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 18px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #e5e7eb;
|
||||
gap: 16px;
|
||||
margin: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.status-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 24px;
|
||||
|
||||
.title {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
}
|
||||
|
||||
.service-info,
|
||||
.language-info,
|
||||
.status-info,
|
||||
.details-info {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.language-info {
|
||||
.language {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
}
|
||||
|
||||
.service-info {
|
||||
flex: 2;
|
||||
}
|
||||
|
||||
.language-info {
|
||||
flex: 2;
|
||||
}
|
||||
|
||||
.status-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.details-info {
|
||||
flex: 3;
|
||||
}
|
||||
|
||||
.status {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
|
||||
svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$lightModeFontColor: rgb(29, 29, 29);
|
||||
|
||||
.lightMode {
|
||||
.connection-status-container {
|
||||
.header .title {
|
||||
color: $lightModeFontColor;
|
||||
|
||||
h1 {
|
||||
color: $lightModeFontColor;
|
||||
}
|
||||
}
|
||||
|
||||
.status-container {
|
||||
color: $lightModeFontColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.text-capitalize {
|
||||
text-transform: capitalize;
|
||||
}
|
@ -0,0 +1,250 @@
|
||||
import './LogsConnectionStatus.styles.scss';
|
||||
|
||||
import {
|
||||
CheckCircleTwoTone,
|
||||
CloseCircleTwoTone,
|
||||
LoadingOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import Header from 'container/OnboardingContainer/common/Header/Header';
|
||||
import { useGetExplorerQueryRange } from 'hooks/queryBuilder/useGetExplorerQueryRange';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { SuccessResponse } from 'types/api';
|
||||
import { ILog } from 'types/api/logs/log';
|
||||
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
|
||||
import { Query } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
interface ConnectionStatusProps {
|
||||
logType: string;
|
||||
}
|
||||
|
||||
const enum ApplicationLogsType {
|
||||
FROM_LOG_FILE = 'from-log-file',
|
||||
USING_OTEL_COLLECTOR = 'using-otel-sdk',
|
||||
}
|
||||
|
||||
export default function LogsConnectionStatus({
|
||||
logType,
|
||||
}: ConnectionStatusProps): JSX.Element {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [isReceivingData, setIsReceivingData] = useState(false);
|
||||
const [pollingInterval, setPollingInterval] = useState<number | false>(15000); // initial Polling interval of 15 secs , Set to false after 5 mins
|
||||
const [retryCount, setRetryCount] = useState(20); // Retry for 5 mins
|
||||
|
||||
const requestData: Query = {
|
||||
queryType: EQueryType.QUERY_BUILDER,
|
||||
builder: {
|
||||
queryData: [
|
||||
{
|
||||
dataSource: DataSource.LOGS,
|
||||
queryName: 'A',
|
||||
aggregateOperator: 'noop',
|
||||
aggregateAttribute: {
|
||||
id: '------false',
|
||||
dataType: '',
|
||||
key: '',
|
||||
isColumn: false,
|
||||
type: '',
|
||||
},
|
||||
filters: {
|
||||
items: [],
|
||||
op: 'AND',
|
||||
},
|
||||
expression: 'A',
|
||||
disabled: false,
|
||||
having: [],
|
||||
stepInterval: 60,
|
||||
limit: null,
|
||||
orderBy: [
|
||||
{
|
||||
columnName: 'timestamp',
|
||||
order: 'desc',
|
||||
},
|
||||
],
|
||||
groupBy: [],
|
||||
legend: '',
|
||||
reduceTo: 'sum',
|
||||
offset: 0,
|
||||
pageSize: 100,
|
||||
},
|
||||
],
|
||||
queryFormulas: [],
|
||||
},
|
||||
clickhouse_sql: [],
|
||||
id: '',
|
||||
promql: [],
|
||||
};
|
||||
|
||||
const { data, isFetching, error, isError } = useGetExplorerQueryRange(
|
||||
requestData,
|
||||
PANEL_TYPES.LIST,
|
||||
{
|
||||
keepPreviousData: true,
|
||||
refetchInterval: pollingInterval,
|
||||
enabled: true,
|
||||
},
|
||||
);
|
||||
|
||||
const verifyLogsData = (
|
||||
response?: SuccessResponse<MetricRangePayloadProps, unknown>,
|
||||
): void => {
|
||||
if (response || !isError) {
|
||||
setRetryCount(retryCount - 1);
|
||||
|
||||
if (retryCount < 0) {
|
||||
setLoading(false);
|
||||
setPollingInterval(false);
|
||||
}
|
||||
}
|
||||
|
||||
const currentData = data?.payload.data.newResult.data.result || [];
|
||||
if (currentData.length > 0 && currentData[0].list) {
|
||||
const currentLogs: ILog[] = currentData[0].list.map((item) => ({
|
||||
...item.data,
|
||||
timestamp: item.timestamp,
|
||||
}));
|
||||
|
||||
for (let index = 0; index < currentLogs.length; index += 1) {
|
||||
const log = currentLogs[index];
|
||||
|
||||
const attrStringObj = log?.attributes_string;
|
||||
|
||||
if (
|
||||
(logType === 'kubernetes' &&
|
||||
Object.prototype.hasOwnProperty.call(attrStringObj, 'k8s_pod_name')) ||
|
||||
(logType === 'docker' &&
|
||||
Object.prototype.hasOwnProperty.call(attrStringObj, 'container_id'))
|
||||
) {
|
||||
// Logs Found, stop polling
|
||||
setLoading(false);
|
||||
setIsReceivingData(true);
|
||||
setRetryCount(-1);
|
||||
setPollingInterval(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
verifyLogsData(data);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isFetching, data, error, isError]);
|
||||
|
||||
const renderDocsReference = (): JSX.Element => {
|
||||
switch (logType) {
|
||||
case 'kubernetes':
|
||||
return (
|
||||
<Header
|
||||
entity="kubernetes"
|
||||
heading="Collecting Kubernetes Pod logs"
|
||||
imgURL="/Logos/kubernetes.svg"
|
||||
docsURL="https://signoz.io/docs/userguide/collect_kubernetes_pod_logs/#collect-kubernetes-pod-logs-in-signoz-cloud"
|
||||
imgClassName="supported-logs-type-img"
|
||||
/>
|
||||
);
|
||||
|
||||
case 'docker':
|
||||
return (
|
||||
<Header
|
||||
entity="docker"
|
||||
heading="Collecting Docker container logs"
|
||||
imgURL="/Logos/docker.svg"
|
||||
docsURL="https://signoz.io/docs/userguide/collect_docker_logs/"
|
||||
imgClassName="supported-logs-type-img"
|
||||
/>
|
||||
);
|
||||
|
||||
case 'syslogs':
|
||||
return (
|
||||
<Header
|
||||
entity="syslog"
|
||||
heading="Collecting Syslogs"
|
||||
imgURL="/Logos/syslogs.svg"
|
||||
docsURL="https://signoz.io/docs/userguide/collecting_syslogs/"
|
||||
imgClassName="supported-logs-type-img"
|
||||
/>
|
||||
);
|
||||
case 'nodejs':
|
||||
return (
|
||||
<Header
|
||||
entity="nodejs"
|
||||
heading="Collecting NodeJS winston logs"
|
||||
imgURL="/Logos/node-js.svg"
|
||||
docsURL="https://signoz.io/docs/userguide/collecting_nodejs_winston_logs/"
|
||||
imgClassName="supported-logs-type-img"
|
||||
/>
|
||||
);
|
||||
|
||||
default:
|
||||
return (
|
||||
<Header
|
||||
entity="docker"
|
||||
heading={
|
||||
logType === ApplicationLogsType.FROM_LOG_FILE
|
||||
? 'Collecting Application Logs from Log file'
|
||||
: 'Collecting Application Logs Using OTEL SDK'
|
||||
}
|
||||
imgURL={`/Logos/${
|
||||
logType === ApplicationLogsType.FROM_LOG_FILE
|
||||
? 'software-window'
|
||||
: 'cmd-terminal'
|
||||
}.svg`}
|
||||
docsURL={
|
||||
logType === ApplicationLogsType.FROM_LOG_FILE
|
||||
? 'https://signoz.io/docs/userguide/collect_logs_from_file/'
|
||||
: 'https://signoz.io/docs/userguide/collecting_application_logs_otel_sdk_java/'
|
||||
}
|
||||
imgClassName="supported-logs-type-img"
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="connection-status-container">
|
||||
<div className="full-docs-link">{renderDocsReference()}</div>
|
||||
<div className="status-container">
|
||||
<div className="service-info">
|
||||
<div className="label"> Logs Type </div>
|
||||
<div className="language text-capitalize"> {logType} </div>
|
||||
</div>
|
||||
|
||||
<div className="status-info">
|
||||
<div className="label"> Status </div>
|
||||
|
||||
<div className="status">
|
||||
{(loading || isFetching) && <LoadingOutlined />}
|
||||
{!(loading || isFetching) && isReceivingData && (
|
||||
<>
|
||||
<CheckCircleTwoTone twoToneColor="#52c41a" />
|
||||
<span> Success </span>
|
||||
</>
|
||||
)}
|
||||
{!(loading || isFetching) && !isReceivingData && (
|
||||
<>
|
||||
<CloseCircleTwoTone twoToneColor="#e84749" />
|
||||
<span> Failed </span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="details-info">
|
||||
<div className="label"> Details </div>
|
||||
|
||||
<div className="details">
|
||||
{(loading || isFetching) && <div> Waiting for Update </div>}
|
||||
{!(loading || isFetching) && isReceivingData && (
|
||||
<div> Received logs successfully. </div>
|
||||
)}
|
||||
{!(loading || isFetching) && !isReceivingData && (
|
||||
<div> Could not detect the logs </div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -0,0 +1,119 @@
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 1440px;
|
||||
margin: 0 auto;
|
||||
|
||||
&.darkMode {
|
||||
}
|
||||
|
||||
&.lightMode {
|
||||
.onboardingHeader {
|
||||
color: #1d1d1d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.moduleSelectContainer {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.onboardingContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
color: #e5e7eb;
|
||||
}
|
||||
|
||||
.onboardingHeader {
|
||||
text-align: center;
|
||||
margin-top: 48px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.onboardingHeader h1 {
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.modulesContainer {
|
||||
display: block;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.moduleContainerRowStyles {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
gap: 36px;
|
||||
margin: 36px;
|
||||
}
|
||||
|
||||
.moduleStyles {
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
width: 400px;
|
||||
|
||||
.ant-card-body {
|
||||
padding: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.moduleTitleStyle {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
padding: 16px;
|
||||
margin: 0px !important;
|
||||
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.moduleStyles.selected {
|
||||
border: 1px solid rgb(232, 112, 64, 0.6) !important;
|
||||
|
||||
.moduleTitleStyle {
|
||||
border-bottom: 1px solid rgb(232, 112, 64, 0.6) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.moduleDesc {
|
||||
padding: 24px;
|
||||
margin: 0px !important;
|
||||
min-height: 100px;
|
||||
}
|
||||
|
||||
.modules-container {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.continue-to-next-step {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: 48px 0;
|
||||
}
|
||||
|
||||
.stepsContainer {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
padding: 48px;
|
||||
}
|
||||
|
||||
.actionButtonsContainer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding-bottom: 48px;
|
||||
box-sizing: border-box;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.ant-steps-item-description {
|
||||
font-size: 12px !important;
|
||||
max-width: 100% !important;
|
||||
}
|
@ -0,0 +1,279 @@
|
||||
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
||||
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
||||
import './Onboarding.styles.scss';
|
||||
|
||||
import { ArrowLeftOutlined, ArrowRightOutlined } from '@ant-design/icons';
|
||||
import { Button, Card, StepProps, Steps, Typography } from 'antd';
|
||||
import cx from 'classnames';
|
||||
import ROUTES from 'constants/routes';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import history from 'lib/history';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import APM from './APM/APM';
|
||||
import InfrastructureMonitoring from './InfrastructureMonitoring/InfrastructureMonitoring';
|
||||
import LogsManagement from './LogsManagement/LogsManagement';
|
||||
|
||||
enum ModulesMap {
|
||||
APM = 'APM',
|
||||
LogsManagement = 'LogsManagement',
|
||||
InfrastructureMonitoring = 'InfrastructureMonitoring',
|
||||
}
|
||||
|
||||
const defaultStepDesc = 'Configure data source';
|
||||
const getStarted = 'Get Started';
|
||||
const selectUseCase = 'Select the use-case';
|
||||
const instrumentApp = 'Instrument Application';
|
||||
const testConnection = 'Test Connection';
|
||||
const verifyConnectionDesc = 'Verify that you’ve instrumented your application';
|
||||
|
||||
const verifyableLogsType = ['kubernetes', 'docker'];
|
||||
|
||||
interface ModuleProps {
|
||||
id: string;
|
||||
title: string;
|
||||
desc: string;
|
||||
stepDesc: string;
|
||||
}
|
||||
|
||||
const useCases = {
|
||||
APM: {
|
||||
id: ModulesMap.APM,
|
||||
title: 'Application Monitoring',
|
||||
desc:
|
||||
'Monitor performance of your applications & troubleshoot problems by installing within your infra.',
|
||||
stepDesc: defaultStepDesc,
|
||||
},
|
||||
LogsManagement: {
|
||||
id: ModulesMap.LogsManagement,
|
||||
title: 'Logs Management',
|
||||
desc:
|
||||
'Easily search and filter logs with query builder and automatically detect logs from K8s cluster.',
|
||||
stepDesc: 'Choose the logs that you want to receive on SigNoz',
|
||||
},
|
||||
InfrastructureMonitoring: {
|
||||
id: ModulesMap.InfrastructureMonitoring,
|
||||
title: 'Infrastructure Monitoring',
|
||||
desc:
|
||||
'Easily search and filter logs with query builder and automatically detect logs from K8s cluster.',
|
||||
stepDesc: defaultStepDesc,
|
||||
},
|
||||
};
|
||||
|
||||
const defaultSteps: StepProps[] = [
|
||||
{
|
||||
title: getStarted,
|
||||
description: selectUseCase,
|
||||
},
|
||||
{
|
||||
title: instrumentApp,
|
||||
description: defaultStepDesc,
|
||||
},
|
||||
{
|
||||
title: testConnection,
|
||||
description: verifyConnectionDesc,
|
||||
},
|
||||
];
|
||||
|
||||
export default function Onboarding(): JSX.Element {
|
||||
const [selectedModule, setSelectedModule] = useState<ModuleProps>(
|
||||
useCases.APM,
|
||||
);
|
||||
const [steps, setsteps] = useState(defaultSteps);
|
||||
const [activeStep, setActiveStep] = useState(1);
|
||||
const [current, setCurrent] = useState(0);
|
||||
const [selectedLogsType, setSelectedLogsType] = useState<string | null>(
|
||||
'kubernetes',
|
||||
);
|
||||
const isDarkMode = useIsDarkMode();
|
||||
|
||||
const baseSteps = [
|
||||
{
|
||||
title: getStarted,
|
||||
description: selectUseCase,
|
||||
},
|
||||
{
|
||||
title: instrumentApp,
|
||||
description: selectedModule.stepDesc,
|
||||
},
|
||||
];
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedModule?.id === ModulesMap.InfrastructureMonitoring) {
|
||||
setsteps([...baseSteps]);
|
||||
} else if (selectedModule?.id === ModulesMap.LogsManagement) {
|
||||
if (selectedLogsType && verifyableLogsType?.indexOf(selectedLogsType) > -1) {
|
||||
setsteps([
|
||||
...baseSteps,
|
||||
{
|
||||
title: testConnection,
|
||||
description: verifyConnectionDesc,
|
||||
disabled: true,
|
||||
},
|
||||
]);
|
||||
} else {
|
||||
setsteps([...baseSteps]);
|
||||
}
|
||||
} else {
|
||||
setsteps([
|
||||
...baseSteps,
|
||||
{
|
||||
title: testConnection,
|
||||
description: verifyConnectionDesc,
|
||||
},
|
||||
]);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [selectedModule, selectedLogsType]);
|
||||
|
||||
const handleNext = (): void => {
|
||||
// Need to add logic to validate service name and then allow next step transition in APM module
|
||||
const isFormValid = true;
|
||||
|
||||
if (isFormValid && activeStep <= 3) {
|
||||
setActiveStep(activeStep + 1);
|
||||
setCurrent(current + 1);
|
||||
}
|
||||
};
|
||||
|
||||
const handlePrev = (): void => {
|
||||
if (activeStep >= 1) {
|
||||
setCurrent(current - 1);
|
||||
setActiveStep(activeStep - 1);
|
||||
}
|
||||
};
|
||||
|
||||
const handleOnboardingComplete = (): void => {
|
||||
switch (selectedModule.id) {
|
||||
case ModulesMap.APM:
|
||||
history.push(ROUTES.APPLICATION);
|
||||
break;
|
||||
case ModulesMap.LogsManagement:
|
||||
history.push(ROUTES.LOGS);
|
||||
break;
|
||||
case ModulesMap.InfrastructureMonitoring:
|
||||
history.push(ROUTES.APPLICATION);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
const handleStepChange = (value: number): void => {
|
||||
setCurrent(value);
|
||||
setActiveStep(value + 1);
|
||||
};
|
||||
|
||||
const handleModuleSelect = (module: ModuleProps): void => {
|
||||
setSelectedModule(module);
|
||||
};
|
||||
|
||||
const handleLogTypeSelect = (logType: string): void => {
|
||||
setSelectedLogsType(logType);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={cx('container', isDarkMode ? 'darkMode' : 'lightMode')}>
|
||||
{activeStep === 1 && (
|
||||
<>
|
||||
<div className="onboardingHeader">
|
||||
<h1>Get Started with SigNoz</h1>
|
||||
<div> Select a use-case to get started </div>
|
||||
</div>
|
||||
|
||||
<div className="modulesContainer">
|
||||
<div className="moduleContainerRowStyles">
|
||||
{Object.keys(ModulesMap).map((module) => {
|
||||
const selectedUseCase = (useCases as any)[module];
|
||||
|
||||
return (
|
||||
<Card
|
||||
className={cx(
|
||||
'moduleStyles',
|
||||
selectedModule.id === selectedUseCase.id ? 'selected' : '',
|
||||
)}
|
||||
style={{
|
||||
backgroundColor: isDarkMode ? '#000' : '#FFF',
|
||||
}}
|
||||
key={selectedUseCase.id}
|
||||
onClick={(): void => handleModuleSelect(selectedUseCase)}
|
||||
>
|
||||
<Typography.Title
|
||||
className="moduleTitleStyle"
|
||||
level={4}
|
||||
style={{
|
||||
borderBottom: isDarkMode ? '1px solid #303030' : '1px solid #ddd',
|
||||
backgroundColor: isDarkMode ? '#141414' : '#FFF',
|
||||
}}
|
||||
>
|
||||
{selectedUseCase.title}
|
||||
</Typography.Title>
|
||||
<Typography.Paragraph
|
||||
className="moduleDesc"
|
||||
style={{ backgroundColor: isDarkMode ? '#000' : '#FFF' }}
|
||||
>
|
||||
{selectedUseCase.desc}
|
||||
</Typography.Paragraph>
|
||||
</Card>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="continue-to-next-step">
|
||||
<Button type="primary" icon={<ArrowRightOutlined />} onClick={handleNext}>
|
||||
Continue to next step
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
{activeStep > 1 && (
|
||||
<div className="stepsContainer">
|
||||
<Steps
|
||||
current={current}
|
||||
onChange={handleStepChange}
|
||||
items={steps}
|
||||
size="small"
|
||||
/>
|
||||
<div className="step-content">
|
||||
{selectedModule.id === ModulesMap.APM && <APM activeStep={activeStep} />}
|
||||
{selectedModule.id === ModulesMap.LogsManagement && (
|
||||
<LogsManagement
|
||||
activeStep={activeStep}
|
||||
handleLogTypeSelect={handleLogTypeSelect}
|
||||
/>
|
||||
)}
|
||||
{selectedModule.id === ModulesMap.InfrastructureMonitoring && (
|
||||
<InfrastructureMonitoring activeStep={activeStep} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="actionButtonsContainer">
|
||||
{activeStep > 0 && (
|
||||
<Button icon={<ArrowLeftOutlined />} onClick={handlePrev}>
|
||||
Back
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{activeStep < steps.length && (
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<ArrowRightOutlined />}
|
||||
onClick={handleNext}
|
||||
>
|
||||
Continue to next step
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{activeStep === steps.length && (
|
||||
<Button type="primary" onClick={handleOnboardingComplete}>
|
||||
Done
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
import cx from 'classnames';
|
||||
|
||||
interface HeaderProps {
|
||||
entity: string;
|
||||
heading: string;
|
||||
imgURL: string;
|
||||
docsURL: string;
|
||||
imgClassName: string;
|
||||
}
|
||||
|
||||
export default function Header({
|
||||
entity,
|
||||
heading,
|
||||
imgURL,
|
||||
docsURL,
|
||||
imgClassName,
|
||||
}: HeaderProps): JSX.Element {
|
||||
return (
|
||||
<div className={cx('header', entity)}>
|
||||
<img className={imgClassName} src={imgURL} alt="" />
|
||||
<div className="title">
|
||||
<h1>{heading}</h1>
|
||||
|
||||
<div className="detailed-docs-link">
|
||||
View detailed docs
|
||||
<a target="_blank" href={docsURL} rel="noreferrer">
|
||||
here
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
3
frontend/src/container/OnboardingContainer/index.tsx
Normal file
3
frontend/src/container/OnboardingContainer/index.tsx
Normal file
@ -0,0 +1,3 @@
|
||||
import OnboardingContainer from './OnboardingContainer';
|
||||
|
||||
export default OnboardingContainer;
|
4
frontend/src/container/OnboardingContainer/typings.d.ts
vendored
Normal file
4
frontend/src/container/OnboardingContainer/typings.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
declare module '*.md' {
|
||||
const content: string;
|
||||
export = content;
|
||||
}
|
@ -2,6 +2,7 @@ import { CheckCircleTwoTone, WarningOutlined } from '@ant-design/icons';
|
||||
import { MenuProps } from 'antd';
|
||||
import getLocalStorageKey from 'api/browser/localstorage/get';
|
||||
import { IS_SIDEBAR_COLLAPSED } from 'constants/app';
|
||||
import { FeatureKeys } from 'constants/features';
|
||||
import ROUTES from 'constants/routes';
|
||||
import history from 'lib/history';
|
||||
import { useCallback, useLayoutEffect, useMemo, useState } from 'react';
|
||||
@ -14,7 +15,7 @@ import AppReducer from 'types/reducer/app';
|
||||
|
||||
import { routeConfig, styles } from './config';
|
||||
import { getQueryString } from './helper';
|
||||
import menuItems from './menuItems';
|
||||
import defaultMenuItems from './menuItems';
|
||||
import { MenuItem, SecondaryMenuItemKey } from './sideNav.types';
|
||||
import { getActiveMenuKeyFromPath } from './sideNav.utils';
|
||||
import Slack from './Slack';
|
||||
@ -32,10 +33,29 @@ function SideNav(): JSX.Element {
|
||||
const [collapsed, setCollapsed] = useState<boolean>(
|
||||
getLocalStorageKey(IS_SIDEBAR_COLLAPSED) === 'true',
|
||||
);
|
||||
const { currentVersion, latestVersion, isCurrentVersionError } = useSelector<
|
||||
AppState,
|
||||
AppReducer
|
||||
>((state) => state.app);
|
||||
const {
|
||||
currentVersion,
|
||||
latestVersion,
|
||||
isCurrentVersionError,
|
||||
featureResponse,
|
||||
} = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
|
||||
const menuItems = useMemo(
|
||||
() =>
|
||||
defaultMenuItems.filter((item) => {
|
||||
const isOnboardingEnabled =
|
||||
featureResponse.data?.find(
|
||||
(feature) => feature.name === FeatureKeys.ONBOARDING,
|
||||
)?.active || false;
|
||||
|
||||
if (!isOnboardingEnabled) {
|
||||
return item.key !== ROUTES.GET_STARTED;
|
||||
}
|
||||
|
||||
return true;
|
||||
}),
|
||||
[featureResponse],
|
||||
);
|
||||
|
||||
const { pathname, search } = useLocation();
|
||||
|
||||
@ -75,7 +95,17 @@ function SideNav(): JSX.Element {
|
||||
history.push(ROUTES.VERSION);
|
||||
};
|
||||
|
||||
const isNotCurrentVersion = currentVersion !== latestVersion;
|
||||
const checkVersionState = (): boolean => {
|
||||
const versionCore = currentVersion?.split('-')[0];
|
||||
|
||||
if (versionCore) {
|
||||
return versionCore !== latestVersion;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const isNotCurrentVersion = checkVersionState();
|
||||
|
||||
const secondaryMenuItems: MenuItem[] = [
|
||||
{
|
||||
|
@ -26,7 +26,7 @@ export const routeConfig: Record<string, QueryParams[]> = {
|
||||
[ROUTES.EDIT_ALERTS]: [QueryParams.resourceAttributes],
|
||||
[ROUTES.ERROR_DETAIL]: [QueryParams.resourceAttributes],
|
||||
[ROUTES.HOME_PAGE]: [QueryParams.resourceAttributes],
|
||||
[ROUTES.INSTRUMENTATION]: [QueryParams.resourceAttributes],
|
||||
[ROUTES.GET_STARTED]: [QueryParams.resourceAttributes],
|
||||
[ROUTES.LIST_ALL_ALERT]: [QueryParams.resourceAttributes],
|
||||
[ROUTES.LIST_LICENSES]: [QueryParams.resourceAttributes],
|
||||
[ROUTES.LOGIN]: [QueryParams.resourceAttributes],
|
||||
|
@ -1,13 +1,13 @@
|
||||
import {
|
||||
AlertOutlined,
|
||||
AlignLeftOutlined,
|
||||
ApiOutlined,
|
||||
BarChartOutlined,
|
||||
BugOutlined,
|
||||
DashboardFilled,
|
||||
DeploymentUnitOutlined,
|
||||
LineChartOutlined,
|
||||
MenuOutlined,
|
||||
RocketOutlined,
|
||||
SettingOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import ROUTES from 'constants/routes';
|
||||
@ -15,6 +15,11 @@ import ROUTES from 'constants/routes';
|
||||
import { SidebarMenu } from './sideNav.types';
|
||||
|
||||
const menuItems: SidebarMenu[] = [
|
||||
{
|
||||
key: ROUTES.GET_STARTED,
|
||||
label: 'Get Started',
|
||||
icon: <RocketOutlined rotate={45} />,
|
||||
},
|
||||
{
|
||||
key: ROUTES.APPLICATION,
|
||||
label: 'Services',
|
||||
@ -24,38 +29,11 @@ const menuItems: SidebarMenu[] = [
|
||||
key: ROUTES.TRACE,
|
||||
label: 'Traces',
|
||||
icon: <MenuOutlined />,
|
||||
// children: [
|
||||
// {
|
||||
// key: ROUTES.TRACE,
|
||||
// label: 'Traces',
|
||||
// },
|
||||
// TODO: uncomment when will be ready explorer
|
||||
// {
|
||||
// key: ROUTES.TRACES_EXPLORER,
|
||||
// label: "Explorer",
|
||||
// },
|
||||
// ],
|
||||
},
|
||||
{
|
||||
key: ROUTES.LOGS,
|
||||
label: 'Logs',
|
||||
icon: <AlignLeftOutlined />,
|
||||
// children: [
|
||||
// {
|
||||
// key: ROUTES.LOGS,
|
||||
// label: 'Search',
|
||||
// },
|
||||
// TODO: uncomment when will be ready explorer
|
||||
// {
|
||||
// key: ROUTES.LOGS_EXPLORER,
|
||||
// label: 'Views',
|
||||
// },
|
||||
// ],
|
||||
// {
|
||||
// key: ROUTES.PIPELINES,
|
||||
// label: 'Pipelines',
|
||||
// },
|
||||
// ],
|
||||
},
|
||||
{
|
||||
key: ROUTES.ALL_DASHBOARD,
|
||||
@ -87,11 +65,6 @@ const menuItems: SidebarMenu[] = [
|
||||
label: 'Settings',
|
||||
icon: <SettingOutlined />,
|
||||
},
|
||||
{
|
||||
key: ROUTES.INSTRUMENTATION,
|
||||
label: 'Get Started',
|
||||
icon: <ApiOutlined />,
|
||||
},
|
||||
];
|
||||
|
||||
/** Mapping of some newly added routes and their corresponding active sidebar menu key */
|
||||
|
@ -8,7 +8,7 @@ const breadcrumbNameMap = {
|
||||
[ROUTES.TRACES_EXPLORER]: 'Traces Explorer',
|
||||
[ROUTES.SERVICE_MAP]: 'Service Map',
|
||||
[ROUTES.USAGE_EXPLORER]: 'Usage Explorer',
|
||||
[ROUTES.INSTRUMENTATION]: 'Get Started',
|
||||
[ROUTES.GET_STARTED]: 'Get Started',
|
||||
[ROUTES.ALL_CHANNELS]: 'Channels',
|
||||
[ROUTES.SETTINGS]: 'Settings',
|
||||
[ROUTES.DASHBOARD]: 'Dashboard',
|
||||
|
@ -74,7 +74,7 @@ export const routesToSkip = [
|
||||
ROUTES.TRACE_DETAIL,
|
||||
ROUTES.ALL_CHANNELS,
|
||||
ROUTES.USAGE_EXPLORER,
|
||||
ROUTES.INSTRUMENTATION,
|
||||
ROUTES.GET_STARTED,
|
||||
ROUTES.VERSION,
|
||||
ROUTES.ALL_DASHBOARD,
|
||||
ROUTES.ORG_SETTINGS,
|
||||
|
@ -24,18 +24,15 @@ export const useGetExplorerQueryRange = (
|
||||
GlobalReducer
|
||||
>((state) => state.globalTime);
|
||||
|
||||
const key = useMemo(
|
||||
() =>
|
||||
const key =
|
||||
typeof options?.queryKey === 'string'
|
||||
? options?.queryKey
|
||||
: REACT_QUERY_KEY.GET_QUERY_RANGE,
|
||||
[options?.queryKey],
|
||||
);
|
||||
: REACT_QUERY_KEY.GET_QUERY_RANGE;
|
||||
|
||||
const isEnabled = useMemo(() => {
|
||||
if (!options) return isEnabledQuery;
|
||||
if (typeof options.enabled === 'boolean') {
|
||||
return isEnabledQuery && options.enabled;
|
||||
return isEnabledQuery || options.enabled;
|
||||
}
|
||||
|
||||
return isEnabledQuery;
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { FeatureKeys } from 'constants/features';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { AppState } from 'store/reducers';
|
||||
import { PayloadProps as FeatureFlagPayload } from 'types/api/features/getFeaturesFlags';
|
||||
import { FeatureFlagProps as FeatureFlagPayload } from 'types/api/features/getFeaturesFlags';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
|
||||
const useFeatureFlag = (
|
||||
flagKey: keyof typeof FeatureKeys,
|
||||
): FlatArray<FeatureFlagPayload, 1> | undefined => {
|
||||
): FeatureFlagPayload | undefined => {
|
||||
const { featureResponse = [] } = useSelector<AppState, AppReducer>(
|
||||
(state) => state.app,
|
||||
);
|
||||
@ -15,7 +15,7 @@ const useFeatureFlag = (
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
const featureResponseData = featureResponse.data as FeatureFlagPayload;
|
||||
const featureResponseData = featureResponse.data as FeatureFlagPayload[];
|
||||
|
||||
const feature = featureResponseData?.find((flag) => flag.name === flagKey);
|
||||
|
||||
|
23
frontend/src/hooks/useGetFeatureFlag.tsx
Normal file
23
frontend/src/hooks/useGetFeatureFlag.tsx
Normal file
@ -0,0 +1,23 @@
|
||||
import getFeaturesFlags from 'api/features/getFeatureFlags';
|
||||
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
||||
import { useQuery, UseQueryResult } from 'react-query';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { AppState } from 'store/reducers';
|
||||
import { FeatureFlagProps } from 'types/api/features/getFeaturesFlags';
|
||||
|
||||
const useGetFeatureFlag = (
|
||||
onSuccessHandler: (routes: FeatureFlagProps[]) => void,
|
||||
): UseQueryResult<FeatureFlagProps[], unknown> => {
|
||||
const userId: string = useSelector<AppState, string>(
|
||||
(state) => state.app.user?.userId || '',
|
||||
);
|
||||
|
||||
return useQuery<FeatureFlagProps[]>({
|
||||
queryFn: getFeaturesFlags,
|
||||
queryKey: [REACT_QUERY_KEY.GET_FEATURES_FLAGS, userId],
|
||||
onSuccess: onSuccessHandler,
|
||||
retryOnMount: false,
|
||||
});
|
||||
};
|
||||
|
||||
export default useGetFeatureFlag;
|
@ -1,7 +1,12 @@
|
||||
import getService from 'api/metrics/getService';
|
||||
import { AxiosError } from 'axios';
|
||||
import { Time } from 'container/TopNav/DateTimeSelection/config';
|
||||
import { useQuery, UseQueryResult } from 'react-query';
|
||||
import {
|
||||
QueryKey,
|
||||
useQuery,
|
||||
UseQueryOptions,
|
||||
UseQueryResult,
|
||||
} from 'react-query';
|
||||
import { PayloadProps } from 'types/api/metrics/getService';
|
||||
import { Tags } from 'types/reducer/trace';
|
||||
|
||||
@ -10,20 +15,18 @@ export const useQueryService = ({
|
||||
maxTime,
|
||||
selectedTime,
|
||||
selectedTags,
|
||||
}: UseQueryServiceProps): UseQueryResult<PayloadProps, AxiosError> => {
|
||||
const queryKey = [minTime, maxTime, selectedTime, selectedTags];
|
||||
return useQuery<PayloadProps, AxiosError>(queryKey, () =>
|
||||
getService({
|
||||
end: maxTime,
|
||||
start: minTime,
|
||||
selectedTags,
|
||||
}),
|
||||
);
|
||||
};
|
||||
options,
|
||||
}: UseQueryServiceProps): UseQueryResult<PayloadProps, AxiosError> =>
|
||||
useQuery<PayloadProps, AxiosError>({
|
||||
queryFn: () => getService({ end: maxTime, selectedTags, start: minTime }),
|
||||
queryKey: [minTime, maxTime, selectedTime, selectedTags],
|
||||
...options,
|
||||
});
|
||||
|
||||
interface UseQueryServiceProps {
|
||||
minTime: number;
|
||||
maxTime: number;
|
||||
selectedTime: Time;
|
||||
selectedTags: Tags[];
|
||||
options?: UseQueryOptions<PayloadProps, AxiosError, PayloadProps, QueryKey>;
|
||||
}
|
||||
|
@ -60,5 +60,44 @@
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
|
||||
<script>
|
||||
//Set your APP_ID
|
||||
const APP_ID = '<%= htmlWebpackPlugin.options.INTERCOM_APP_ID %>';
|
||||
|
||||
(function () {
|
||||
var w = window;
|
||||
var ic = w.Intercom;
|
||||
if (typeof ic === 'function') {
|
||||
ic('reattach_activator');
|
||||
ic('update', w.intercomSettings);
|
||||
} else {
|
||||
var d = document;
|
||||
var i = function () {
|
||||
i.c(arguments);
|
||||
};
|
||||
i.q = [];
|
||||
i.c = function (args) {
|
||||
i.q.push(args);
|
||||
};
|
||||
w.Intercom = i;
|
||||
var l = function () {
|
||||
var s = d.createElement('script');
|
||||
s.type = 'text/javascript';
|
||||
s.async = true;
|
||||
s.src = 'https://widget.intercom.io/widget/' + APP_ID;
|
||||
var x = d.getElementsByTagName('script')[0];
|
||||
x.parentNode.insertBefore(s, x);
|
||||
};
|
||||
if (document.readyState === 'complete') {
|
||||
l();
|
||||
} else if (w.attachEvent) {
|
||||
w.attachEvent('onload', l);
|
||||
} else {
|
||||
w.addEventListener('load', l, false);
|
||||
}
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -8,13 +8,8 @@ import { HelmetProvider } from 'react-helmet-async';
|
||||
import { QueryClient, QueryClientProvider } from 'react-query';
|
||||
import { ReactQueryDevtools } from 'react-query/devtools';
|
||||
import { Provider } from 'react-redux';
|
||||
import reportWebVitals from 'reportWebVitals';
|
||||
import store from 'store';
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
reportWebVitals(console.log);
|
||||
}
|
||||
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
|
@ -0,0 +1,7 @@
|
||||
.onboardingPageContainer {
|
||||
display: flex;
|
||||
// height: 100%;
|
||||
// min-height: calc(100vh - 50px);
|
||||
width: 100%;
|
||||
color: #fff;
|
||||
}
|
13
frontend/src/pages/OnboardingPage/OnboardingPage.tsx
Normal file
13
frontend/src/pages/OnboardingPage/OnboardingPage.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
import './OnboardingPage.styles.scss';
|
||||
|
||||
import OnboardingContainer from 'container/OnboardingContainer';
|
||||
|
||||
function OnboardingPage(): JSX.Element {
|
||||
return (
|
||||
<div className="onboardingPageContainer">
|
||||
<OnboardingContainer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default OnboardingPage;
|
3
frontend/src/pages/OnboardingPage/index.tsx
Normal file
3
frontend/src/pages/OnboardingPage/index.tsx
Normal file
@ -0,0 +1,3 @@
|
||||
import OnboardingPage from './OnboardingPage';
|
||||
|
||||
export default OnboardingPage;
|
@ -1,15 +1,7 @@
|
||||
export type FeaturesFlag =
|
||||
| 'DurationSort'
|
||||
| 'TimestampSort'
|
||||
| 'SMART_TRACE_DETAIL'
|
||||
| 'CUSTOM_METRICS_FUNCTION'
|
||||
| 'QUERY_BUILDER_PANELS'
|
||||
| 'QUERY_BUILDER_ALERTS'
|
||||
| 'DISABLE_UPSELL'
|
||||
| 'SSO';
|
||||
import { FeatureKeys } from 'constants/features';
|
||||
|
||||
interface FeatureFlagProps {
|
||||
name: FeaturesFlag;
|
||||
export interface FeatureFlagProps {
|
||||
name: FeatureKeys;
|
||||
active: boolean;
|
||||
usage: number;
|
||||
usage_limit: number;
|
||||
|
@ -10,6 +10,7 @@ export interface ILog {
|
||||
body: string;
|
||||
resources_string: Record<string, never>;
|
||||
attributesString: Record<string, never>;
|
||||
attributes_string: Record<string, never>;
|
||||
attributesInt: Record<string, never>;
|
||||
attributesFloat: Record<string, never>;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { QueryObserverBaseResult } from 'react-query';
|
||||
import { PayloadProps as ConfigPayload } from 'types/api/dynamicConfigs/getDynamicConfigs';
|
||||
import { PayloadProps as FeatureFlagPayload } from 'types/api/features/getFeaturesFlags';
|
||||
import { FeatureFlagProps as FeatureFlagPayload } from 'types/api/features/getFeaturesFlags';
|
||||
import { PayloadProps as OrgPayload } from 'types/api/user/getOrganization';
|
||||
import { PayloadProps as UserPayload } from 'types/api/user/getUser';
|
||||
import { UserFlags } from 'types/api/user/setFlags';
|
||||
@ -32,7 +32,7 @@ export default interface AppReducer {
|
||||
ee: 'Y' | 'N';
|
||||
setupCompleted: boolean;
|
||||
featureResponse: {
|
||||
data: FeatureFlagPayload | null;
|
||||
data: FeatureFlagPayload[] | null;
|
||||
refetch: QueryObserverBaseResult['refetch'];
|
||||
};
|
||||
}
|
||||
|
@ -56,7 +56,6 @@ export const routePermission: Record<keyof typeof ROUTES, ROLES[]> = {
|
||||
EDIT_ALERTS: ['ADMIN'],
|
||||
ERROR_DETAIL: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||
HOME_PAGE: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||
INSTRUMENTATION: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||
LIST_ALL_ALERT: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||
LOGIN: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||
NOT_FOUND: ['ADMIN', 'VIEWER', 'EDITOR'],
|
||||
@ -79,4 +78,5 @@ export const routePermission: Record<keyof typeof ROUTES, ROLES[]> = {
|
||||
LOGS_PIPELINE: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||
TRACE_EXPLORER: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||
PIPELINES: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||
GET_STARTED: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||
};
|
||||
|
@ -37,6 +37,7 @@
|
||||
"./webpack.config.js",
|
||||
"./webpack.config.prod.js",
|
||||
"./jest.setup.ts",
|
||||
"./tests/**.ts"
|
||||
"./tests/**.ts",
|
||||
"./**/*.d.ts"
|
||||
]
|
||||
}
|
||||
|
@ -17,13 +17,17 @@ const sassLoader = 'sass-loader';
|
||||
const styleLoader = 'style-loader';
|
||||
|
||||
const plugins = [
|
||||
new HtmlWebpackPlugin({ template: 'src/index.html.ejs' }),
|
||||
new HtmlWebpackPlugin({
|
||||
template: 'src/index.html.ejs',
|
||||
INTERCOM_APP_ID: process.env.INTERCOM_APP_ID,
|
||||
}),
|
||||
new webpack.ProvidePlugin({
|
||||
process: 'process/browser',
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': JSON.stringify({
|
||||
FRONTEND_API_ENDPOINT: process.env.FRONTEND_API_ENDPOINT,
|
||||
INTERCOM_APP_ID: process.env.INTERCOM_APP_ID,
|
||||
}),
|
||||
}),
|
||||
];
|
||||
@ -69,6 +73,20 @@ const config = {
|
||||
use: ['babel-loader'],
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
{
|
||||
test: /\.mdx?$/,
|
||||
use: [
|
||||
// `babel-loader` is optional:
|
||||
{ loader: 'babel-loader', options: {} },
|
||||
{
|
||||
loader: '@mdx-js/loader',
|
||||
/** @type {import('@mdx-js/loader').Options} */
|
||||
options: {
|
||||
/* jsxImportSource: …, otherOptions… */
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
@ -131,6 +149,9 @@ const config = {
|
||||
performance: {
|
||||
hints: false,
|
||||
},
|
||||
optimization: {
|
||||
minimize: false,
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
|
@ -79,6 +79,20 @@ const config = {
|
||||
use: ['babel-loader'],
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
{
|
||||
test: /\.mdx?$/,
|
||||
use: [
|
||||
// `babel-loader` is optional:
|
||||
{ loader: 'babel-loader', options: {} },
|
||||
{
|
||||
loader: '@mdx-js/loader',
|
||||
/** @type {import('@mdx-js/loader').Options} */
|
||||
options: {
|
||||
/* jsxImportSource: …, otherOptions… */
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
@ -91,6 +105,17 @@ const config = {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.s[ac]ss$/i,
|
||||
use: [
|
||||
// Creates `style` nodes from JS strings
|
||||
styleLoader,
|
||||
// Translates CSS into CommonJS
|
||||
cssLoader,
|
||||
// Compiles Sass to CSS
|
||||
sassLoader,
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.(jpe?g|png|gif|svg)$/i,
|
||||
use: [
|
||||
@ -124,17 +149,6 @@ const config = {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.s[ac]ss$/i,
|
||||
use: [
|
||||
// Creates `style` nodes from JS strings
|
||||
styleLoader,
|
||||
// Translates CSS into CommonJS
|
||||
cssLoader,
|
||||
// Compiles Sass to CSS
|
||||
sassLoader,
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins,
|
||||
|
1533
frontend/yarn.lock
1533
frontend/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user