mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-07-24 03:54:25 +08:00
commit
93a11b2031
@ -146,7 +146,7 @@ services:
|
|||||||
condition: on-failure
|
condition: on-failure
|
||||||
|
|
||||||
query-service:
|
query-service:
|
||||||
image: signoz/query-service:0.34.0
|
image: signoz/query-service:0.34.1
|
||||||
command:
|
command:
|
||||||
[
|
[
|
||||||
"-config=/root/config/prometheus.yml",
|
"-config=/root/config/prometheus.yml",
|
||||||
@ -186,7 +186,7 @@ services:
|
|||||||
<<: *db-depend
|
<<: *db-depend
|
||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
image: signoz/frontend:0.34.0
|
image: signoz/frontend:0.34.1
|
||||||
deploy:
|
deploy:
|
||||||
restart_policy:
|
restart_policy:
|
||||||
condition: on-failure
|
condition: on-failure
|
||||||
@ -199,7 +199,7 @@ services:
|
|||||||
- ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf
|
- ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
otel-collector:
|
otel-collector:
|
||||||
image: signoz/signoz-otel-collector:0.88.0
|
image: signoz/signoz-otel-collector:0.88.1
|
||||||
command:
|
command:
|
||||||
[
|
[
|
||||||
"--config=/etc/otel-collector-config.yaml",
|
"--config=/etc/otel-collector-config.yaml",
|
||||||
@ -237,7 +237,7 @@ services:
|
|||||||
- query-service
|
- query-service
|
||||||
|
|
||||||
otel-collector-migrator:
|
otel-collector-migrator:
|
||||||
image: signoz/signoz-schema-migrator:0.88.0
|
image: signoz/signoz-schema-migrator:0.88.1
|
||||||
deploy:
|
deploy:
|
||||||
restart_policy:
|
restart_policy:
|
||||||
condition: on-failure
|
condition: on-failure
|
||||||
@ -250,7 +250,7 @@ services:
|
|||||||
# - clickhouse-3
|
# - clickhouse-3
|
||||||
|
|
||||||
otel-collector-metrics:
|
otel-collector-metrics:
|
||||||
image: signoz/signoz-otel-collector:0.88.0
|
image: signoz/signoz-otel-collector:0.88.1
|
||||||
command:
|
command:
|
||||||
[
|
[
|
||||||
"--config=/etc/otel-collector-metrics-config.yaml",
|
"--config=/etc/otel-collector-metrics-config.yaml",
|
||||||
|
@ -66,7 +66,7 @@ services:
|
|||||||
- --storage.path=/data
|
- --storage.path=/data
|
||||||
|
|
||||||
otel-collector-migrator:
|
otel-collector-migrator:
|
||||||
image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.88.0}
|
image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.88.1}
|
||||||
container_name: otel-migrator
|
container_name: otel-migrator
|
||||||
command:
|
command:
|
||||||
- "--dsn=tcp://clickhouse:9000"
|
- "--dsn=tcp://clickhouse:9000"
|
||||||
@ -81,7 +81,7 @@ services:
|
|||||||
# Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md`
|
# Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md`
|
||||||
otel-collector:
|
otel-collector:
|
||||||
container_name: signoz-otel-collector
|
container_name: signoz-otel-collector
|
||||||
image: signoz/signoz-otel-collector:0.88.0
|
image: signoz/signoz-otel-collector:0.88.1
|
||||||
command:
|
command:
|
||||||
[
|
[
|
||||||
"--config=/etc/otel-collector-config.yaml",
|
"--config=/etc/otel-collector-config.yaml",
|
||||||
@ -118,7 +118,7 @@ services:
|
|||||||
|
|
||||||
otel-collector-metrics:
|
otel-collector-metrics:
|
||||||
container_name: signoz-otel-collector-metrics
|
container_name: signoz-otel-collector-metrics
|
||||||
image: signoz/signoz-otel-collector:0.88.0
|
image: signoz/signoz-otel-collector:0.88.1
|
||||||
command:
|
command:
|
||||||
[
|
[
|
||||||
"--config=/etc/otel-collector-metrics-config.yaml",
|
"--config=/etc/otel-collector-metrics-config.yaml",
|
||||||
|
@ -164,7 +164,7 @@ services:
|
|||||||
# Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md`
|
# Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md`
|
||||||
|
|
||||||
query-service:
|
query-service:
|
||||||
image: signoz/query-service:${DOCKER_TAG:-0.34.0}
|
image: signoz/query-service:${DOCKER_TAG:-0.34.1}
|
||||||
container_name: signoz-query-service
|
container_name: signoz-query-service
|
||||||
command:
|
command:
|
||||||
[
|
[
|
||||||
@ -203,7 +203,7 @@ services:
|
|||||||
<<: *db-depend
|
<<: *db-depend
|
||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
image: signoz/frontend:${DOCKER_TAG:-0.34.0}
|
image: signoz/frontend:${DOCKER_TAG:-0.34.1}
|
||||||
container_name: signoz-frontend
|
container_name: signoz-frontend
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
depends_on:
|
depends_on:
|
||||||
@ -215,7 +215,7 @@ services:
|
|||||||
- ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf
|
- ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
otel-collector-migrator:
|
otel-collector-migrator:
|
||||||
image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.88.0}
|
image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.88.1}
|
||||||
container_name: otel-migrator
|
container_name: otel-migrator
|
||||||
command:
|
command:
|
||||||
- "--dsn=tcp://clickhouse:9000"
|
- "--dsn=tcp://clickhouse:9000"
|
||||||
@ -229,7 +229,7 @@ services:
|
|||||||
|
|
||||||
|
|
||||||
otel-collector:
|
otel-collector:
|
||||||
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.88.0}
|
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.88.1}
|
||||||
container_name: signoz-otel-collector
|
container_name: signoz-otel-collector
|
||||||
command:
|
command:
|
||||||
[
|
[
|
||||||
@ -269,7 +269,7 @@ services:
|
|||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
|
||||||
otel-collector-metrics:
|
otel-collector-metrics:
|
||||||
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.88.0}
|
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.88.1}
|
||||||
container_name: signoz-otel-collector-metrics
|
container_name: signoz-otel-collector-metrics
|
||||||
command:
|
command:
|
||||||
[
|
[
|
||||||
|
BIN
frontend/public/Logos/fluent-bit.png
Normal file
BIN
frontend/public/Logos/fluent-bit.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
BIN
frontend/public/Logos/fluentd.png
Normal file
BIN
frontend/public/Logos/fluentd.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
1
frontend/public/Logos/logstash.svg
Normal file
1
frontend/public/Logos/logstash.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80" width="2500" height="2500"><style>.st0{fill:#f3bd19}.st1{fill:#231f20}.st2{fill:#3ebeb0}.st3{fill:#37a595}.st4{fill:none}</style><path class="st0" d="M41.1 41.9H15.6V12.5h7.7c9.9 0 17.8 8 17.8 17.8v11.6z"/><path class="st1" d="M41.1 67.5c-14.1 0-25.6-11.4-25.6-25.6h25.6v25.6z"/><path class="st2" d="M41.1 41.9h23.3v25.6H41.1z"/><path class="st3" d="M41.1 41.9h5.4v25.6h-5.4z"/><path class="st4" d="M0 0h80v80H0z"/></svg>
|
After Width: | Height: | Size: 494 B |
@ -5,6 +5,7 @@
|
|||||||
"create": "Create",
|
"create": "Create",
|
||||||
"reorder": "Reorder",
|
"reorder": "Reorder",
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
|
"learn_more": "Learn more about pipelines",
|
||||||
"reorder_pipeline": "Do you want to reorder pipeline?",
|
"reorder_pipeline": "Do you want to reorder pipeline?",
|
||||||
"reorder_pipeline_description": "Logs are processed sequentially in processors and pipelines. Reordering it may change how data is processed by them.",
|
"reorder_pipeline_description": "Logs are processed sequentially in processors and pipelines. Reordering it may change how data is processed by them.",
|
||||||
"delete_pipeline": "Do you want to delete pipeline",
|
"delete_pipeline": "Do you want to delete pipeline",
|
||||||
|
@ -7,6 +7,7 @@ import { FeatureKeys } from 'constants/features';
|
|||||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||||
import ROUTES from 'constants/routes';
|
import ROUTES from 'constants/routes';
|
||||||
import AppLayout from 'container/AppLayout';
|
import AppLayout from 'container/AppLayout';
|
||||||
|
import useAnalytics from 'hooks/analytics/useAnalytics';
|
||||||
import { useThemeConfig } from 'hooks/useDarkMode';
|
import { useThemeConfig } from 'hooks/useDarkMode';
|
||||||
import useGetFeatureFlag from 'hooks/useGetFeatureFlag';
|
import useGetFeatureFlag from 'hooks/useGetFeatureFlag';
|
||||||
import useLicense, { LICENSE_PLAN_KEY } from 'hooks/useLicense';
|
import useLicense, { LICENSE_PLAN_KEY } from 'hooks/useLicense';
|
||||||
@ -25,7 +26,6 @@ import AppActions from 'types/actions';
|
|||||||
import { UPDATE_FEATURE_FLAG_RESPONSE } from 'types/actions/app';
|
import { UPDATE_FEATURE_FLAG_RESPONSE } from 'types/actions/app';
|
||||||
import AppReducer, { User } from 'types/reducer/app';
|
import AppReducer, { User } from 'types/reducer/app';
|
||||||
import { extractDomain, isCloudUser, isEECloudUser } from 'utils/app';
|
import { extractDomain, isCloudUser, isEECloudUser } from 'utils/app';
|
||||||
import { trackPageView } from 'utils/segmentAnalytics';
|
|
||||||
|
|
||||||
import PrivateRoute from './Private';
|
import PrivateRoute from './Private';
|
||||||
import defaultRoutes, { AppRoutes, SUPPORT_ROUTE } from './routes';
|
import defaultRoutes, { AppRoutes, SUPPORT_ROUTE } from './routes';
|
||||||
@ -41,6 +41,8 @@ function App(): JSX.Element {
|
|||||||
|
|
||||||
const dispatch = useDispatch<Dispatch<AppActions>>();
|
const dispatch = useDispatch<Dispatch<AppActions>>();
|
||||||
|
|
||||||
|
const { trackPageView } = useAnalytics();
|
||||||
|
|
||||||
const { hostname, pathname } = window.location;
|
const { hostname, pathname } = window.location;
|
||||||
|
|
||||||
const isCloudUserVal = isCloudUser();
|
const isCloudUserVal = isCloudUser();
|
||||||
@ -156,6 +158,7 @@ function App(): JSX.Element {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
trackPageView(pathname);
|
trackPageView(pathname);
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [pathname]);
|
}, [pathname]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -220,7 +220,11 @@ function ExplorerCard({
|
|||||||
open={isOpen}
|
open={isOpen}
|
||||||
onOpenChange={handleOpenChange}
|
onOpenChange={handleOpenChange}
|
||||||
>
|
>
|
||||||
<Button type={saveButtonType} icon={saveButtonIcon}>
|
<Button
|
||||||
|
type={saveButtonType}
|
||||||
|
icon={saveButtonIcon}
|
||||||
|
data-testid="traces-save-view-action"
|
||||||
|
>
|
||||||
{isQueryUpdated
|
{isQueryUpdated
|
||||||
? SaveButtonText.SAVE_AS_NEW_VIEW
|
? SaveButtonText.SAVE_AS_NEW_VIEW
|
||||||
: SaveButtonText.SAVE_VIEW}
|
: SaveButtonText.SAVE_VIEW}
|
||||||
|
@ -64,7 +64,12 @@ function SaveViewWithName({
|
|||||||
>
|
>
|
||||||
<Input placeholder="Enter Name" />
|
<Input placeholder="Enter Name" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<SaveButton htmlType="submit" type="primary" loading={isLoading}>
|
<SaveButton
|
||||||
|
htmlType="submit"
|
||||||
|
type="primary"
|
||||||
|
loading={isLoading}
|
||||||
|
data-testid="save-view-name-action-button"
|
||||||
|
>
|
||||||
Save
|
Save
|
||||||
</SaveButton>
|
</SaveButton>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
.code-snippet-container {
|
.code-snippet-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
background-color: rgb(43, 43, 43);
|
// background-color: rgb(43, 43, 43);
|
||||||
|
background-color: #111a2c;
|
||||||
|
border-color: #111a2c;
|
||||||
}
|
}
|
||||||
|
|
||||||
.code-copy-btn {
|
.code-copy-btn {
|
||||||
|
@ -3,6 +3,7 @@ import './uplot.scss';
|
|||||||
|
|
||||||
import { Typography } from 'antd';
|
import { Typography } from 'antd';
|
||||||
import { ToggleGraphProps } from 'components/Graph/types';
|
import { ToggleGraphProps } from 'components/Graph/types';
|
||||||
|
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
|
||||||
import {
|
import {
|
||||||
forwardRef,
|
forwardRef,
|
||||||
memo,
|
memo,
|
||||||
@ -11,6 +12,7 @@ import {
|
|||||||
useImperativeHandle,
|
useImperativeHandle,
|
||||||
useRef,
|
useRef,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
|
import { ErrorBoundary } from 'react-error-boundary';
|
||||||
import UPlot from 'uplot';
|
import UPlot from 'uplot';
|
||||||
|
|
||||||
import { dataMatch, optionsUpdateState } from './utils';
|
import { dataMatch, optionsUpdateState } from './utils';
|
||||||
@ -119,6 +121,7 @@ const Uplot = forwardRef<ToggleGraphProps | undefined, UplotProps>(
|
|||||||
}, [data, resetScales, create]);
|
}, [data, resetScales, create]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<ErrorBoundary FallbackComponent={ErrorBoundaryFallback}>
|
||||||
<div className="uplot-graph-container" ref={targetRef}>
|
<div className="uplot-graph-container" ref={targetRef}>
|
||||||
{data && data[0] && data[0]?.length === 0 ? (
|
{data && data[0] && data[0]?.length === 0 ? (
|
||||||
<div className="not-found">
|
<div className="not-found">
|
||||||
@ -126,6 +129,7 @@ const Uplot = forwardRef<ToggleGraphProps | undefined, UplotProps>(
|
|||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
|
</ErrorBoundary>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -5,7 +5,7 @@ export const Layout = styled(LayoutComponent)`
|
|||||||
&&& {
|
&&& {
|
||||||
display: flex;
|
display: flex;
|
||||||
position: relative;
|
position: relative;
|
||||||
min-height: calc(100vh - 4rem);
|
min-height: calc(100vh - 8rem);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import getUsage from 'api/billing/getUsage';
|
|||||||
import manageCreditCardApi from 'api/billing/manage';
|
import manageCreditCardApi from 'api/billing/manage';
|
||||||
import { SOMETHING_WENT_WRONG } from 'constants/api';
|
import { SOMETHING_WENT_WRONG } from 'constants/api';
|
||||||
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
||||||
|
import useAnalytics from 'hooks/analytics/useAnalytics';
|
||||||
import useAxiosError from 'hooks/useAxiosError';
|
import useAxiosError from 'hooks/useAxiosError';
|
||||||
import useLicense from 'hooks/useLicense';
|
import useLicense from 'hooks/useLicense';
|
||||||
import { useNotifications } from 'hooks/useNotifications';
|
import { useNotifications } from 'hooks/useNotifications';
|
||||||
@ -109,9 +110,11 @@ export default function BillingContainer(): JSX.Element {
|
|||||||
const [data, setData] = useState<any[]>([]);
|
const [data, setData] = useState<any[]>([]);
|
||||||
const billCurrency = '$';
|
const billCurrency = '$';
|
||||||
|
|
||||||
|
const { trackEvent } = useAnalytics();
|
||||||
|
|
||||||
const { isFetching, data: licensesData, error: licenseError } = useLicense();
|
const { isFetching, data: licensesData, error: licenseError } = useLicense();
|
||||||
|
|
||||||
const { user } = useSelector<AppState, AppReducer>((state) => state.app);
|
const { user, org } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||||
const { notifications } = useNotifications();
|
const { notifications } = useNotifications();
|
||||||
|
|
||||||
const handleError = useAxiosError();
|
const handleError = useAxiosError();
|
||||||
@ -301,18 +304,29 @@ export default function BillingContainer(): JSX.Element {
|
|||||||
|
|
||||||
const handleBilling = useCallback(async () => {
|
const handleBilling = useCallback(async () => {
|
||||||
if (isFreeTrial && !licensesData?.payload?.trialConvertedToSubscription) {
|
if (isFreeTrial && !licensesData?.payload?.trialConvertedToSubscription) {
|
||||||
|
trackEvent('Billing : Upgrade Plan', {
|
||||||
|
user,
|
||||||
|
org,
|
||||||
|
});
|
||||||
|
|
||||||
updateCreditCard({
|
updateCreditCard({
|
||||||
licenseKey: activeLicense?.key || '',
|
licenseKey: activeLicense?.key || '',
|
||||||
successURL: window.location.href,
|
successURL: window.location.href,
|
||||||
cancelURL: window.location.href,
|
cancelURL: window.location.href,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
trackEvent('Billing : Manage Billing', {
|
||||||
|
user,
|
||||||
|
org,
|
||||||
|
});
|
||||||
|
|
||||||
manageCreditCard({
|
manageCreditCard({
|
||||||
licenseKey: activeLicense?.key || '',
|
licenseKey: activeLicense?.key || '',
|
||||||
successURL: window.location.href,
|
successURL: window.location.href,
|
||||||
cancelURL: window.location.href,
|
cancelURL: window.location.href,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [
|
}, [
|
||||||
activeLicense?.key,
|
activeLicense?.key,
|
||||||
isFreeTrial,
|
isFreeTrial,
|
||||||
@ -432,7 +446,12 @@ export default function BillingContainer(): JSX.Element {
|
|||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={4} style={{ display: 'flex', justifyContent: 'flex-end' }}>
|
<Col span={4} style={{ display: 'flex', justifyContent: 'flex-end' }}>
|
||||||
<Button type="primary" size="middle">
|
<Button
|
||||||
|
type="primary"
|
||||||
|
size="middle"
|
||||||
|
loading={isLoadingBilling || isLoadingManageBilling}
|
||||||
|
onClick={handleBilling}
|
||||||
|
>
|
||||||
Upgrade Plan
|
Upgrade Plan
|
||||||
</Button>
|
</Button>
|
||||||
</Col>
|
</Col>
|
||||||
|
@ -7,8 +7,8 @@ import { Time } from 'container/TopNav/DateTimeSelection/config';
|
|||||||
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
|
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
|
||||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||||
import { useResizeObserver } from 'hooks/useDimensions';
|
import { useResizeObserver } from 'hooks/useDimensions';
|
||||||
import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartData';
|
import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartOptions';
|
||||||
import { getUPlotChartData } from 'lib/uPlotLib/utils/getChartData';
|
import { getUPlotChartData } from 'lib/uPlotLib/utils/getUplotChartData';
|
||||||
import { useMemo, useRef } from 'react';
|
import { useMemo, useRef } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
|
@ -15,8 +15,8 @@ import { useStepInterval } from 'hooks/queryBuilder/useStepInterval';
|
|||||||
import { useChartMutable } from 'hooks/useChartMutable';
|
import { useChartMutable } from 'hooks/useChartMutable';
|
||||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||||
import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariables';
|
import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariables';
|
||||||
import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartData';
|
import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartOptions';
|
||||||
import { getUPlotChartData } from 'lib/uPlotLib/utils/getChartData';
|
import { getUPlotChartData } from 'lib/uPlotLib/utils/getUplotChartData';
|
||||||
import { useDashboard } from 'providers/Dashboard/Dashboard';
|
import { useDashboard } from 'providers/Dashboard/Dashboard';
|
||||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
|
@ -5,8 +5,8 @@ import { useIsDarkMode } from 'hooks/useDarkMode';
|
|||||||
import { useResizeObserver } from 'hooks/useDimensions';
|
import { useResizeObserver } from 'hooks/useDimensions';
|
||||||
import { useIntersectionObserver } from 'hooks/useIntersectionObserver';
|
import { useIntersectionObserver } from 'hooks/useIntersectionObserver';
|
||||||
import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariables';
|
import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariables';
|
||||||
import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartData';
|
import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartOptions';
|
||||||
import { getUPlotChartData } from 'lib/uPlotLib/utils/getChartData';
|
import { getUPlotChartData } from 'lib/uPlotLib/utils/getUplotChartData';
|
||||||
import isEmpty from 'lodash-es/isEmpty';
|
import isEmpty from 'lodash-es/isEmpty';
|
||||||
import _noop from 'lodash-es/noop';
|
import _noop from 'lodash-es/noop';
|
||||||
import { memo, useCallback, useMemo, useRef, useState } from 'react';
|
import { memo, useCallback, useMemo, useRef, useState } from 'react';
|
||||||
@ -28,6 +28,7 @@ function GridCardGraph({
|
|||||||
isQueryEnabled,
|
isQueryEnabled,
|
||||||
threshold,
|
threshold,
|
||||||
variables,
|
variables,
|
||||||
|
filterNaN,
|
||||||
}: GridCardGraphProps): JSX.Element {
|
}: GridCardGraphProps): JSX.Element {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const [errorMessage, setErrorMessage] = useState<string>();
|
const [errorMessage, setErrorMessage] = useState<string>();
|
||||||
@ -89,7 +90,11 @@ function GridCardGraph({
|
|||||||
|
|
||||||
const containerDimensions = useResizeObserver(graphRef);
|
const containerDimensions = useResizeObserver(graphRef);
|
||||||
|
|
||||||
const chartData = getUPlotChartData(queryResponse?.data?.payload);
|
const chartData = getUPlotChartData(
|
||||||
|
queryResponse?.data?.payload,
|
||||||
|
undefined,
|
||||||
|
filterNaN,
|
||||||
|
);
|
||||||
|
|
||||||
const isDarkMode = useIsDarkMode();
|
const isDarkMode = useIsDarkMode();
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ export interface GridCardGraphProps {
|
|||||||
headerMenuList?: WidgetGraphComponentProps['headerMenuList'];
|
headerMenuList?: WidgetGraphComponentProps['headerMenuList'];
|
||||||
isQueryEnabled: boolean;
|
isQueryEnabled: boolean;
|
||||||
variables?: Dashboard['data']['variables'];
|
variables?: Dashboard['data']['variables'];
|
||||||
|
filterNaN?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GetGraphVisibilityStateOnLegendClickProps {
|
export interface GetGraphVisibilityStateOnLegendClickProps {
|
||||||
|
@ -118,7 +118,11 @@ function GraphLayout({ onAddPanelHandler }: GraphLayoutProps): JSX.Element {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{addPanelPermission && (
|
{addPanelPermission && (
|
||||||
<Button onClick={onAddPanelHandler} icon={<PlusOutlined />}>
|
<Button
|
||||||
|
onClick={onAddPanelHandler}
|
||||||
|
icon={<PlusOutlined />}
|
||||||
|
data-testid="add-panel"
|
||||||
|
>
|
||||||
{t('dashboard:add_panel')}
|
{t('dashboard:add_panel')}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
@ -203,7 +203,7 @@ function WidgetHeader({
|
|||||||
onClick={onClickHandler}
|
onClick={onClickHandler}
|
||||||
>
|
>
|
||||||
<HeaderContentContainer>
|
<HeaderContentContainer>
|
||||||
<Typography.Text style={{ maxWidth: '80%' }} ellipsis>
|
<Typography.Text style={{ maxWidth: '80%' }} ellipsis data-testid={title}>
|
||||||
{title}
|
{title}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
<ArrowContainer hover={parentHover}>
|
<ArrowContainer hover={parentHover}>
|
||||||
|
@ -135,14 +135,13 @@ function HeaderContainer(): JSX.Element {
|
|||||||
<>
|
<>
|
||||||
{showTrialExpiryBanner && (
|
{showTrialExpiryBanner && (
|
||||||
<div className="trial-expiry-banner">
|
<div className="trial-expiry-banner">
|
||||||
You are in free trial period. Your free trial will end on{' '}
|
You are in free trial period. Your free trial will end on
|
||||||
<span>
|
<span>
|
||||||
{getFormattedDate(licenseData?.payload?.trialEnd || Date.now())}.
|
{getFormattedDate(licenseData?.payload?.trialEnd || Date.now())}.
|
||||||
</span>
|
</span>
|
||||||
{role === 'ADMIN' ? (
|
{role === 'ADMIN' ? (
|
||||||
<span>
|
<span>
|
||||||
{' '}
|
Please
|
||||||
Please{' '}
|
|
||||||
<Button className="upgrade-link" type="link" onClick={handleUpgrade}>
|
<Button className="upgrade-link" type="link" onClick={handleUpgrade}>
|
||||||
upgrade
|
upgrade
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -3,6 +3,8 @@ import styled from 'styled-components';
|
|||||||
|
|
||||||
export const Header = styled(Layout.Header)`
|
export const Header = styled(Layout.Header)`
|
||||||
background: #1f1f1f !important;
|
background: #1f1f1f !important;
|
||||||
|
padding-left: 16px;
|
||||||
|
padding-right: 16px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const Container = styled.div`
|
export const Container = styled.div`
|
||||||
|
@ -7,14 +7,14 @@ import ApplyLicenseForm from './ApplyLicenseForm';
|
|||||||
import ListLicenses from './ListLicenses';
|
import ListLicenses from './ListLicenses';
|
||||||
|
|
||||||
function Licenses(): JSX.Element {
|
function Licenses(): JSX.Element {
|
||||||
const { t } = useTranslation(['licenses']);
|
const { t, ready: translationsReady } = useTranslation(['licenses']);
|
||||||
const { data, isError, isLoading, refetch } = useLicense();
|
const { data, isError, isLoading, refetch } = useLicense();
|
||||||
|
|
||||||
if (isError || data?.error) {
|
if (isError || data?.error) {
|
||||||
return <Typography>{data?.error}</Typography>;
|
return <Typography>{data?.error}</Typography>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLoading || data?.payload === undefined) {
|
if (isLoading || data?.payload === undefined || !translationsReady) {
|
||||||
return <Spinner tip={t('loading_licenses')} height="90vh" />;
|
return <Spinner tip={t('loading_licenses')} height="90vh" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { DeleteOutlined, ExclamationCircleOutlined } from '@ant-design/icons';
|
import { DeleteOutlined, ExclamationCircleOutlined } from '@ant-design/icons';
|
||||||
import { Modal, Tooltip } from 'antd';
|
import { Modal, Tooltip, Typography } from 'antd';
|
||||||
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
||||||
import { useDeleteDashboard } from 'hooks/dashboard/useDeleteDashboard';
|
import { useDeleteDashboard } from 'hooks/dashboard/useDeleteDashboard';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
@ -10,10 +10,22 @@ import { AppState } from 'store/reducers';
|
|||||||
import AppReducer from 'types/reducer/app';
|
import AppReducer from 'types/reducer/app';
|
||||||
import { USER_ROLES } from 'types/roles';
|
import { USER_ROLES } from 'types/roles';
|
||||||
|
|
||||||
import { Data } from '../index';
|
import { Data } from '..';
|
||||||
import { TableLinkText } from './styles';
|
import { TableLinkText } from './styles';
|
||||||
|
|
||||||
function DeleteButton({ id, createdBy, isLocked }: Data): JSX.Element {
|
interface DeleteButtonProps {
|
||||||
|
createdBy: string;
|
||||||
|
name: string;
|
||||||
|
id: string;
|
||||||
|
isLocked: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
function DeleteButton({
|
||||||
|
createdBy,
|
||||||
|
name,
|
||||||
|
id,
|
||||||
|
isLocked,
|
||||||
|
}: DeleteButtonProps): JSX.Element {
|
||||||
const [modal, contextHolder] = Modal.useModal();
|
const [modal, contextHolder] = Modal.useModal();
|
||||||
const { role, user } = useSelector<AppState, AppReducer>((state) => state.app);
|
const { role, user } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||||
const isAuthor = user?.email === createdBy;
|
const isAuthor = user?.email === createdBy;
|
||||||
@ -26,7 +38,13 @@ function DeleteButton({ id, createdBy, isLocked }: Data): JSX.Element {
|
|||||||
|
|
||||||
const openConfirmationDialog = useCallback((): void => {
|
const openConfirmationDialog = useCallback((): void => {
|
||||||
modal.confirm({
|
modal.confirm({
|
||||||
title: 'Do you really want to delete this dashboard?',
|
title: (
|
||||||
|
<Typography.Title level={5}>
|
||||||
|
Are you sure you want to delete the
|
||||||
|
<span style={{ color: '#e42b35', fontWeight: 500 }}> {name} </span>
|
||||||
|
dashboard?
|
||||||
|
</Typography.Title>
|
||||||
|
),
|
||||||
icon: <ExclamationCircleOutlined style={{ color: '#e42b35' }} />,
|
icon: <ExclamationCircleOutlined style={{ color: '#e42b35' }} />,
|
||||||
onOk() {
|
onOk() {
|
||||||
deleteDashboardMutation.mutateAsync(undefined, {
|
deleteDashboardMutation.mutateAsync(undefined, {
|
||||||
@ -39,7 +57,7 @@ function DeleteButton({ id, createdBy, isLocked }: Data): JSX.Element {
|
|||||||
okButtonProps: { danger: true },
|
okButtonProps: { danger: true },
|
||||||
centered: true,
|
centered: true,
|
||||||
});
|
});
|
||||||
}, [modal, deleteDashboardMutation, queryClient]);
|
}, [modal, name, deleteDashboardMutation, queryClient]);
|
||||||
|
|
||||||
const getDeleteTooltipContent = (): string => {
|
const getDeleteTooltipContent = (): string => {
|
||||||
if (isLocked) {
|
if (isLocked) {
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import { PlusOutlined } from '@ant-design/icons';
|
import { PlusOutlined } from '@ant-design/icons';
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
|
Col,
|
||||||
Dropdown,
|
Dropdown,
|
||||||
|
Input,
|
||||||
MenuProps,
|
MenuProps,
|
||||||
Row,
|
Row,
|
||||||
TableColumnProps,
|
TableColumnProps,
|
||||||
Typography,
|
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import { ItemType } from 'antd/es/menu/hooks/useItems';
|
import { ItemType } from 'antd/es/menu/hooks/useItems';
|
||||||
import createDashboard from 'api/dashboard/create';
|
import createDashboard from 'api/dashboard/create';
|
||||||
@ -18,9 +19,9 @@ import DynamicColumnTable from 'components/ResizeTable/DynamicColumnTable';
|
|||||||
import LabelColumn from 'components/TableRenderer/LabelColumn';
|
import LabelColumn from 'components/TableRenderer/LabelColumn';
|
||||||
import TextToolTip from 'components/TextToolTip';
|
import TextToolTip from 'components/TextToolTip';
|
||||||
import ROUTES from 'constants/routes';
|
import ROUTES from 'constants/routes';
|
||||||
import SearchFilter from 'container/ListOfDashboard/SearchFilter';
|
|
||||||
import { useGetAllDashboard } from 'hooks/dashboard/useGetAllDashboard';
|
import { useGetAllDashboard } from 'hooks/dashboard/useGetAllDashboard';
|
||||||
import useComponentPermission from 'hooks/useComponentPermission';
|
import useComponentPermission from 'hooks/useComponentPermission';
|
||||||
|
import useDebouncedFn from 'hooks/useDebouncedFunction';
|
||||||
import history from 'lib/history';
|
import history from 'lib/history';
|
||||||
import { Key, useCallback, useEffect, useMemo, useState } from 'react';
|
import { Key, useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -38,6 +39,8 @@ import DeleteButton from './TableComponents/DeleteButton';
|
|||||||
import Name from './TableComponents/Name';
|
import Name from './TableComponents/Name';
|
||||||
|
|
||||||
function ListOfAllDashboard(): JSX.Element {
|
function ListOfAllDashboard(): JSX.Element {
|
||||||
|
const { Search } = Input;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: dashboardListResponse = [],
|
data: dashboardListResponse = [],
|
||||||
isLoading: isDashboardListLoading,
|
isLoading: isDashboardListLoading,
|
||||||
@ -59,12 +62,21 @@ function ListOfAllDashboard(): JSX.Element {
|
|||||||
] = useState<boolean>(false);
|
] = useState<boolean>(false);
|
||||||
|
|
||||||
const [uploadedGrafana, setUploadedGrafana] = useState<boolean>(false);
|
const [uploadedGrafana, setUploadedGrafana] = useState<boolean>(false);
|
||||||
|
const [isFilteringDashboards, setIsFilteringDashboards] = useState(false);
|
||||||
|
|
||||||
const [filteredDashboards, setFilteredDashboards] = useState<Dashboard[]>();
|
const [dashboards, setDashboards] = useState<Dashboard[]>();
|
||||||
|
|
||||||
|
const sortDashboardsByCreatedAt = (dashboards: Dashboard[]): void => {
|
||||||
|
const sortedDashboards = dashboards.sort(
|
||||||
|
(a, b) =>
|
||||||
|
new Date(b.created_at).getTime() - new Date(a.created_at).getTime(),
|
||||||
|
);
|
||||||
|
setDashboards(sortedDashboards);
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (dashboardListResponse.length) {
|
if (dashboardListResponse.length) {
|
||||||
setFilteredDashboards(dashboardListResponse);
|
sortDashboardsByCreatedAt(dashboardListResponse);
|
||||||
}
|
}
|
||||||
}, [dashboardListResponse]);
|
}, [dashboardListResponse]);
|
||||||
|
|
||||||
@ -150,7 +162,7 @@ function ListOfAllDashboard(): JSX.Element {
|
|||||||
}, [action]);
|
}, [action]);
|
||||||
|
|
||||||
const data: Data[] =
|
const data: Data[] =
|
||||||
filteredDashboards?.map((e) => ({
|
dashboards?.map((e) => ({
|
||||||
createdAt: e.created_at,
|
createdAt: e.created_at,
|
||||||
description: e.data.description || '',
|
description: e.data.description || '',
|
||||||
id: e.uuid,
|
id: e.uuid,
|
||||||
@ -255,11 +267,50 @@ function ListOfAllDashboard(): JSX.Element {
|
|||||||
[getMenuItems],
|
[getMenuItems],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const searchArrayOfObjects = (searchValue: string): any[] => {
|
||||||
|
// Convert the searchValue to lowercase for case-insensitive search
|
||||||
|
const searchValueLowerCase = searchValue.toLowerCase();
|
||||||
|
|
||||||
|
// Use the filter method to find matching objects
|
||||||
|
return dashboardListResponse.filter((item: any) => {
|
||||||
|
// Convert each property value to lowercase for case-insensitive search
|
||||||
|
const itemValues = Object.values(item?.data).map((value: any) =>
|
||||||
|
value.toString().toLowerCase(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check if any property value contains the searchValue
|
||||||
|
return itemValues.some((value) => value.includes(searchValueLowerCase));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSearch = useDebouncedFn((event: unknown): void => {
|
||||||
|
setIsFilteringDashboards(true);
|
||||||
|
const searchText = (event as React.BaseSyntheticEvent)?.target?.value || '';
|
||||||
|
const filteredDashboards = searchArrayOfObjects(searchText);
|
||||||
|
setDashboards(filteredDashboards);
|
||||||
|
setIsFilteringDashboards(false);
|
||||||
|
}, 500);
|
||||||
|
|
||||||
const GetHeader = useMemo(
|
const GetHeader = useMemo(
|
||||||
() => (
|
() => (
|
||||||
<Row justify="space-between">
|
<Row gutter={16} align="middle">
|
||||||
<Typography>Dashboard List</Typography>
|
<Col span={18}>
|
||||||
|
<Search
|
||||||
|
disabled={isDashboardListLoading}
|
||||||
|
placeholder="Search by Name, Description, Tags"
|
||||||
|
onChange={handleSearch}
|
||||||
|
loading={isFilteringDashboards}
|
||||||
|
style={{ marginBottom: 16, marginTop: 16 }}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
<Col
|
||||||
|
span={6}
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'flex-end',
|
||||||
|
}}
|
||||||
|
>
|
||||||
<ButtonContainer>
|
<ButtonContainer>
|
||||||
<TextToolTip
|
<TextToolTip
|
||||||
{...{
|
{...{
|
||||||
@ -277,6 +328,7 @@ function ListOfAllDashboard(): JSX.Element {
|
|||||||
<NewDashboardButton
|
<NewDashboardButton
|
||||||
icon={<PlusOutlined />}
|
icon={<PlusOutlined />}
|
||||||
type="primary"
|
type="primary"
|
||||||
|
data-testid="create-new-dashboard"
|
||||||
loading={newDashboardState.loading}
|
loading={newDashboardState.loading}
|
||||||
danger={newDashboardState.error}
|
danger={newDashboardState.error}
|
||||||
>
|
>
|
||||||
@ -285,11 +337,15 @@ function ListOfAllDashboard(): JSX.Element {
|
|||||||
</Dropdown>
|
</Dropdown>
|
||||||
)}
|
)}
|
||||||
</ButtonContainer>
|
</ButtonContainer>
|
||||||
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
),
|
),
|
||||||
[
|
[
|
||||||
newDashboard,
|
Search,
|
||||||
isDashboardListLoading,
|
isDashboardListLoading,
|
||||||
|
handleSearch,
|
||||||
|
isFilteringDashboards,
|
||||||
|
newDashboard,
|
||||||
menu,
|
menu,
|
||||||
newDashboardState.loading,
|
newDashboardState.loading,
|
||||||
newDashboardState.error,
|
newDashboardState.error,
|
||||||
@ -301,13 +357,6 @@ function ListOfAllDashboard(): JSX.Element {
|
|||||||
<Card>
|
<Card>
|
||||||
{GetHeader}
|
{GetHeader}
|
||||||
|
|
||||||
{!isDashboardListLoading && (
|
|
||||||
<SearchFilter
|
|
||||||
searchData={dashboardListResponse}
|
|
||||||
filterDashboards={setFilteredDashboards}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<TableContainer>
|
<TableContainer>
|
||||||
<ImportJSON
|
<ImportJSON
|
||||||
isImportJSONModalVisible={isImportJSONModalVisible}
|
isImportJSONModalVisible={isImportJSONModalVisible}
|
||||||
@ -319,8 +368,9 @@ function ListOfAllDashboard(): JSX.Element {
|
|||||||
dynamicColumns={dynamicColumns}
|
dynamicColumns={dynamicColumns}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
pagination={{
|
pagination={{
|
||||||
pageSize: 9,
|
pageSize: 10,
|
||||||
defaultPageSize: 9,
|
defaultPageSize: 10,
|
||||||
|
total: data?.length || 0,
|
||||||
}}
|
}}
|
||||||
showHeader
|
showHeader
|
||||||
bordered
|
bordered
|
||||||
|
@ -41,6 +41,7 @@ import {
|
|||||||
import { DataSource, LogsAggregatorOperator } from 'types/common/queryBuilder';
|
import { DataSource, LogsAggregatorOperator } from 'types/common/queryBuilder';
|
||||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||||
import { generateExportToDashboardLink } from 'utils/dashboard/generateExportToDashboardLink';
|
import { generateExportToDashboardLink } from 'utils/dashboard/generateExportToDashboardLink';
|
||||||
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
import { ActionsWrapper } from './LogsExplorerViews.styled';
|
import { ActionsWrapper } from './LogsExplorerViews.styled';
|
||||||
|
|
||||||
@ -268,9 +269,12 @@ function LogsExplorerViews(): JSX.Element {
|
|||||||
? panelType
|
? panelType
|
||||||
: PANEL_TYPES.TIME_SERIES;
|
: PANEL_TYPES.TIME_SERIES;
|
||||||
|
|
||||||
|
const widgetId = v4();
|
||||||
|
|
||||||
const updatedDashboard = addEmptyWidgetInDashboardJSONWithQuery(
|
const updatedDashboard = addEmptyWidgetInDashboardJSONWithQuery(
|
||||||
dashboard,
|
dashboard,
|
||||||
exportDefaultQuery,
|
exportDefaultQuery,
|
||||||
|
widgetId,
|
||||||
panelTypeParam,
|
panelTypeParam,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -304,6 +308,7 @@ function LogsExplorerViews(): JSX.Element {
|
|||||||
query: exportDefaultQuery,
|
query: exportDefaultQuery,
|
||||||
panelType: panelTypeParam,
|
panelType: panelTypeParam,
|
||||||
dashboardId: data.payload?.uuid || '',
|
dashboardId: data.payload?.uuid || '',
|
||||||
|
widgetId,
|
||||||
});
|
});
|
||||||
|
|
||||||
history.push(dashboardEditView);
|
history.push(dashboardEditView);
|
||||||
|
@ -107,6 +107,7 @@ function DBCall(): JSX.Element {
|
|||||||
<Card data-testid="database_call_rps">
|
<Card data-testid="database_call_rps">
|
||||||
<GraphContainer>
|
<GraphContainer>
|
||||||
<Graph
|
<Graph
|
||||||
|
filterNaN
|
||||||
name="database_call_rps"
|
name="database_call_rps"
|
||||||
widget={databaseCallsRPSWidget}
|
widget={databaseCallsRPSWidget}
|
||||||
onClickHandler={(xValue, yValue, mouseX, mouseY): void => {
|
onClickHandler={(xValue, yValue, mouseX, mouseY): void => {
|
||||||
@ -140,6 +141,7 @@ function DBCall(): JSX.Element {
|
|||||||
<Card data-testid="database_call_avg_duration">
|
<Card data-testid="database_call_avg_duration">
|
||||||
<GraphContainer>
|
<GraphContainer>
|
||||||
<Graph
|
<Graph
|
||||||
|
filterNaN
|
||||||
name="database_call_avg_duration"
|
name="database_call_avg_duration"
|
||||||
widget={databaseCallsAverageDurationWidget}
|
widget={databaseCallsAverageDurationWidget}
|
||||||
headerMenuList={MENU_ITEMS}
|
headerMenuList={MENU_ITEMS}
|
||||||
|
@ -148,6 +148,7 @@ function External(): JSX.Element {
|
|||||||
<Card data-testid="external_call_error_percentage">
|
<Card data-testid="external_call_error_percentage">
|
||||||
<GraphContainer>
|
<GraphContainer>
|
||||||
<Graph
|
<Graph
|
||||||
|
filterNaN
|
||||||
headerMenuList={MENU_ITEMS}
|
headerMenuList={MENU_ITEMS}
|
||||||
name="external_call_error_percentage"
|
name="external_call_error_percentage"
|
||||||
widget={externalCallErrorWidget}
|
widget={externalCallErrorWidget}
|
||||||
@ -183,6 +184,7 @@ function External(): JSX.Element {
|
|||||||
<Card data-testid="external_call_duration">
|
<Card data-testid="external_call_duration">
|
||||||
<GraphContainer>
|
<GraphContainer>
|
||||||
<Graph
|
<Graph
|
||||||
|
filterNaN
|
||||||
name="external_call_duration"
|
name="external_call_duration"
|
||||||
headerMenuList={MENU_ITEMS}
|
headerMenuList={MENU_ITEMS}
|
||||||
widget={externalCallDurationWidget}
|
widget={externalCallDurationWidget}
|
||||||
@ -219,6 +221,7 @@ function External(): JSX.Element {
|
|||||||
<Card data-testid="external_call_rps_by_address">
|
<Card data-testid="external_call_rps_by_address">
|
||||||
<GraphContainer>
|
<GraphContainer>
|
||||||
<Graph
|
<Graph
|
||||||
|
filterNaN
|
||||||
name="external_call_rps_by_address"
|
name="external_call_rps_by_address"
|
||||||
widget={externalCallRPSWidget}
|
widget={externalCallRPSWidget}
|
||||||
headerMenuList={MENU_ITEMS}
|
headerMenuList={MENU_ITEMS}
|
||||||
@ -257,6 +260,7 @@ function External(): JSX.Element {
|
|||||||
name="external_call_duration_by_address"
|
name="external_call_duration_by_address"
|
||||||
widget={externalCallDurationAddressWidget}
|
widget={externalCallDurationAddressWidget}
|
||||||
headerMenuList={MENU_ITEMS}
|
headerMenuList={MENU_ITEMS}
|
||||||
|
filterNaN
|
||||||
onClickHandler={(xValue, yValue, mouseX, mouseY): void => {
|
onClickHandler={(xValue, yValue, mouseX, mouseY): void => {
|
||||||
onGraphClickHandler(setSelectedTimeStamp)(
|
onGraphClickHandler(setSelectedTimeStamp)(
|
||||||
xValue,
|
xValue,
|
||||||
|
@ -84,6 +84,7 @@ function ApDexMetrics({
|
|||||||
return (
|
return (
|
||||||
<Graph
|
<Graph
|
||||||
name="apdex"
|
name="apdex"
|
||||||
|
filterNaN
|
||||||
widget={apDexMetricsWidget}
|
widget={apDexMetricsWidget}
|
||||||
onDragSelect={onDragSelect}
|
onDragSelect={onDragSelect}
|
||||||
onClickHandler={handleGraphClick('ApDex')}
|
onClickHandler={handleGraphClick('ApDex')}
|
||||||
|
@ -88,6 +88,7 @@ function ServiceOverview({
|
|||||||
widget={latencyWidget}
|
widget={latencyWidget}
|
||||||
onClickHandler={handleGraphClick('Service')}
|
onClickHandler={handleGraphClick('Service')}
|
||||||
isQueryEnabled={isQueryEnabled}
|
isQueryEnabled={isQueryEnabled}
|
||||||
|
filterNaN
|
||||||
/>
|
/>
|
||||||
</GraphContainer>
|
</GraphContainer>
|
||||||
</Card>
|
</Card>
|
||||||
|
@ -27,6 +27,7 @@ function TopLevelOperation({
|
|||||||
) : (
|
) : (
|
||||||
<GraphContainer>
|
<GraphContainer>
|
||||||
<Graph
|
<Graph
|
||||||
|
filterNaN
|
||||||
name={name}
|
name={name}
|
||||||
widget={widget}
|
widget={widget}
|
||||||
onClickHandler={handleGraphClick(opName)}
|
onClickHandler={handleGraphClick(opName)}
|
||||||
|
@ -18,7 +18,12 @@ function SettingsDrawer({ drawerTitle }: { drawerTitle: string }): JSX.Element {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button type="dashed" onClick={showDrawer} style={{ width: '100%' }}>
|
<Button
|
||||||
|
type="dashed"
|
||||||
|
onClick={showDrawer}
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
data-testid="show-drawer"
|
||||||
|
>
|
||||||
<SettingOutlined /> Configure
|
<SettingOutlined /> Configure
|
||||||
</Button>
|
</Button>
|
||||||
<DrawerContainer
|
<DrawerContainer
|
||||||
|
@ -51,7 +51,11 @@ function DashboardDescription(): JSX.Element {
|
|||||||
<Card>
|
<Card>
|
||||||
<Row gutter={16}>
|
<Row gutter={16}>
|
||||||
<Col flex={1} span={12}>
|
<Col flex={1} span={12}>
|
||||||
<Typography.Title level={4} style={{ padding: 0, margin: 0 }}>
|
<Typography.Title
|
||||||
|
level={4}
|
||||||
|
style={{ padding: 0, margin: 0 }}
|
||||||
|
data-testid="dashboard-landing-name"
|
||||||
|
>
|
||||||
{isDashboardLocked && (
|
{isDashboardLocked && (
|
||||||
<Tooltip title="Dashboard Locked" placement="top">
|
<Tooltip title="Dashboard Locked" placement="top">
|
||||||
<LockFilled />
|
<LockFilled />
|
||||||
@ -60,7 +64,12 @@ function DashboardDescription(): JSX.Element {
|
|||||||
{title}
|
{title}
|
||||||
</Typography.Title>
|
</Typography.Title>
|
||||||
{description && (
|
{description && (
|
||||||
<Typography className="dashboard-description">{description}</Typography>
|
<Typography
|
||||||
|
className="dashboard-description"
|
||||||
|
data-testid="dashboard-landing-desc"
|
||||||
|
>
|
||||||
|
{description}
|
||||||
|
</Typography>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{tags && (
|
{tags && (
|
||||||
|
@ -63,6 +63,7 @@ function GeneralDashboardSettings(): JSX.Element {
|
|||||||
<div>
|
<div>
|
||||||
<Typography style={{ marginBottom: '0.5rem' }}>Name</Typography>
|
<Typography style={{ marginBottom: '0.5rem' }}>Name</Typography>
|
||||||
<Input
|
<Input
|
||||||
|
data-testid="dashboard-name"
|
||||||
value={updatedTitle}
|
value={updatedTitle}
|
||||||
onChange={(e): void => setUpdatedTitle(e.target.value)}
|
onChange={(e): void => setUpdatedTitle(e.target.value)}
|
||||||
/>
|
/>
|
||||||
@ -71,6 +72,7 @@ function GeneralDashboardSettings(): JSX.Element {
|
|||||||
<div>
|
<div>
|
||||||
<Typography style={{ marginBottom: '0.5rem' }}>Description</Typography>
|
<Typography style={{ marginBottom: '0.5rem' }}>Description</Typography>
|
||||||
<Input.TextArea
|
<Input.TextArea
|
||||||
|
data-testid="dashboard-desc"
|
||||||
rows={5}
|
rows={5}
|
||||||
value={updatedDescription}
|
value={updatedDescription}
|
||||||
onChange={(e): void => setUpdatedDescription(e.target.value)}
|
onChange={(e): void => setUpdatedDescription(e.target.value)}
|
||||||
@ -88,6 +90,7 @@ function GeneralDashboardSettings(): JSX.Element {
|
|||||||
disabled={updateDashboardMutation.isLoading}
|
disabled={updateDashboardMutation.isLoading}
|
||||||
loading={updateDashboardMutation.isLoading}
|
loading={updateDashboardMutation.isLoading}
|
||||||
icon={<SaveOutlined />}
|
icon={<SaveOutlined />}
|
||||||
|
data-testid="save-dashboard-config"
|
||||||
onClick={onSaveHandler}
|
onClick={onSaveHandler}
|
||||||
type="primary"
|
type="primary"
|
||||||
>
|
>
|
||||||
|
@ -181,6 +181,7 @@ function VariablesSetting(): JSX.Element {
|
|||||||
<>
|
<>
|
||||||
<Row style={{ flexDirection: 'row-reverse', padding: '0.5rem 0' }}>
|
<Row style={{ flexDirection: 'row-reverse', padding: '0.5rem 0' }}>
|
||||||
<Button
|
<Button
|
||||||
|
data-testid="add-new-variable"
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={(): void =>
|
onClick={(): void =>
|
||||||
onVariableViewModeEnter('ADD', {} as IDashboardVariable)
|
onVariableViewModeEnter('ADD', {} as IDashboardVariable)
|
||||||
|
@ -3,12 +3,16 @@ import { Tabs } from 'antd';
|
|||||||
import GeneralDashboardSettings from './General';
|
import GeneralDashboardSettings from './General';
|
||||||
import VariablesSetting from './Variables';
|
import VariablesSetting from './Variables';
|
||||||
|
|
||||||
const items = [
|
|
||||||
{ label: 'General', key: 'general', children: <GeneralDashboardSettings /> },
|
|
||||||
{ label: 'Variables', key: 'variables', children: <VariablesSetting /> },
|
|
||||||
];
|
|
||||||
|
|
||||||
function DashboardSettingsContent(): JSX.Element {
|
function DashboardSettingsContent(): JSX.Element {
|
||||||
|
const items = [
|
||||||
|
{
|
||||||
|
label: 'General',
|
||||||
|
key: 'general',
|
||||||
|
children: <GeneralDashboardSettings />,
|
||||||
|
},
|
||||||
|
{ label: 'Variables', key: 'variables', children: <VariablesSetting /> },
|
||||||
|
];
|
||||||
|
|
||||||
return <Tabs items={items} />;
|
return <Tabs items={items} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ function NewExplorerCTA(): JSX.Element | null {
|
|||||||
icon={<CompassOutlined />}
|
icon={<CompassOutlined />}
|
||||||
onClick={onClickHandler}
|
onClick={onClickHandler}
|
||||||
danger
|
danger
|
||||||
|
data-testid="newExplorerCTA"
|
||||||
type="primary"
|
type="primary"
|
||||||
>
|
>
|
||||||
{buttonText[location.pathname]}
|
{buttonText[location.pathname]}
|
||||||
|
@ -4,8 +4,8 @@ import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
|||||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||||
import { useResizeObserver } from 'hooks/useDimensions';
|
import { useResizeObserver } from 'hooks/useDimensions';
|
||||||
import useUrlQuery from 'hooks/useUrlQuery';
|
import useUrlQuery from 'hooks/useUrlQuery';
|
||||||
import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartData';
|
import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartOptions';
|
||||||
import { getUPlotChartData } from 'lib/uPlotLib/utils/getChartData';
|
import { getUPlotChartData } from 'lib/uPlotLib/utils/getUplotChartData';
|
||||||
import { useCallback, useMemo, useRef } from 'react';
|
import { useCallback, useMemo, useRef } from 'react';
|
||||||
import { UseQueryResult } from 'react-query';
|
import { UseQueryResult } from 'react-query';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
|
@ -261,7 +261,12 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{!isSaveDisabled && (
|
{!isSaveDisabled && (
|
||||||
<Button type="primary" disabled={isSaveDisabled} onClick={onSaveDashboard}>
|
<Button
|
||||||
|
type="primary"
|
||||||
|
data-testid="new-widget-save"
|
||||||
|
disabled={isSaveDisabled}
|
||||||
|
onClick={onSaveDashboard}
|
||||||
|
>
|
||||||
Save
|
Save
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
@ -1,144 +0,0 @@
|
|||||||
.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,147 +0,0 @@
|
|||||||
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
|
||||||
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
|
||||||
import './APM.styles.scss';
|
|
||||||
|
|
||||||
import getIngestionData from 'api/settings/getIngestionData';
|
|
||||||
import cx from 'classnames';
|
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
import { useQuery } from 'react-query';
|
|
||||||
import { trackEvent } from 'utils/segmentAnalytics';
|
|
||||||
|
|
||||||
import GoLang from './GoLang/GoLang';
|
|
||||||
import Java from './Java/Java';
|
|
||||||
import Javascript from './Javascript/Javascript';
|
|
||||||
import Python from './Python/Python';
|
|
||||||
import RoR from './RubyOnRails/ROR';
|
|
||||||
|
|
||||||
interface IngestionInfoProps {
|
|
||||||
SIGNOZ_INGESTION_KEY?: string;
|
|
||||||
REGION?: string;
|
|
||||||
}
|
|
||||||
export interface LangProps {
|
|
||||||
ingestionInfo: IngestionInfoProps;
|
|
||||||
activeStep: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
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`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'rails',
|
|
||||||
imgURL: `Logos/rails.png`,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function APM({
|
|
||||||
activeStep,
|
|
||||||
}: {
|
|
||||||
activeStep: number;
|
|
||||||
}): JSX.Element {
|
|
||||||
const [selectedLanguage, setSelectedLanguage] = useState('java');
|
|
||||||
|
|
||||||
const [ingestionInfo, setIngestionInfo] = useState<IngestionInfoProps>({});
|
|
||||||
|
|
||||||
const { status, data: ingestionData } = useQuery({
|
|
||||||
queryFn: () => getIngestionData(),
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (
|
|
||||||
status === 'success' &&
|
|
||||||
ingestionData.payload &&
|
|
||||||
Array.isArray(ingestionData.payload)
|
|
||||||
) {
|
|
||||||
const payload = ingestionData.payload[0] || {
|
|
||||||
ingestionKey: '',
|
|
||||||
dataRegion: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
setIngestionInfo({
|
|
||||||
SIGNOZ_INGESTION_KEY: payload?.ingestionKey,
|
|
||||||
REGION: payload?.dataRegion,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [status, ingestionData?.payload]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// on language select
|
|
||||||
trackEvent('Onboarding: APM', {
|
|
||||||
selectedLanguage,
|
|
||||||
activeStep,
|
|
||||||
});
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [selectedLanguage]);
|
|
||||||
|
|
||||||
const renderSelectedLanguageSetupInstructions = (): JSX.Element => {
|
|
||||||
switch (selectedLanguage) {
|
|
||||||
case 'java':
|
|
||||||
return <Java ingestionInfo={ingestionInfo} activeStep={activeStep} />;
|
|
||||||
case 'python':
|
|
||||||
return <Python ingestionInfo={ingestionInfo} activeStep={activeStep} />;
|
|
||||||
case 'javascript':
|
|
||||||
return <Javascript ingestionInfo={ingestionInfo} activeStep={activeStep} />;
|
|
||||||
case 'go':
|
|
||||||
return <GoLang ingestionInfo={ingestionInfo} activeStep={activeStep} />;
|
|
||||||
case 'rails':
|
|
||||||
return <RoR ingestionInfo={ingestionInfo} 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>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
import './GoLang.styles.scss';
|
|
||||||
|
|
||||||
import { Form, Input } from 'antd';
|
|
||||||
import { MarkdownRenderer } from 'components/MarkdownRenderer/MarkdownRenderer';
|
|
||||||
import Header from 'container/OnboardingContainer/common/Header/Header';
|
|
||||||
|
|
||||||
import { LangProps } from '../APM';
|
|
||||||
import ConnectionStatus from '../common/ConnectionStatus/ConnectionStatus';
|
|
||||||
import GoLangDocs from './goLang.md';
|
|
||||||
|
|
||||||
export default function GoLang({
|
|
||||||
ingestionInfo,
|
|
||||||
activeStep,
|
|
||||||
}: LangProps): JSX.Element {
|
|
||||||
const [form] = Form.useForm();
|
|
||||||
const serviceName = Form.useWatch('Service Name', form);
|
|
||||||
|
|
||||||
const variables = {
|
|
||||||
MYAPP: serviceName || '<service-name>',
|
|
||||||
SIGNOZ_INGESTION_KEY:
|
|
||||||
ingestionInfo.SIGNOZ_INGESTION_KEY || '<SIGNOZ_INGESTION_KEY>',
|
|
||||||
REGION: ingestionInfo.REGION || 'region',
|
|
||||||
};
|
|
||||||
|
|
||||||
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">
|
|
||||||
<MarkdownRenderer markdownContent={GoLangDocs} variables={variables} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{activeStep === 3 && (
|
|
||||||
<ConnectionStatus
|
|
||||||
serviceName={form.getFieldValue('Service Name')}
|
|
||||||
framework="go"
|
|
||||||
language="go"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
.form-container {
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
width: 100%;
|
|
||||||
gap: 16px;
|
|
||||||
|
|
||||||
& .ant-form-item {
|
|
||||||
margin-bottom: 0px;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,146 +0,0 @@
|
|||||||
import './Java.styles.scss';
|
|
||||||
|
|
||||||
import { Form, Input, Select } from 'antd';
|
|
||||||
import { MarkdownRenderer } from 'components/MarkdownRenderer/MarkdownRenderer';
|
|
||||||
import Header from 'container/OnboardingContainer/common/Header/Header';
|
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
import { trackEvent } from 'utils/segmentAnalytics';
|
|
||||||
import { popupContainer } from 'utils/selectPopupContainer';
|
|
||||||
|
|
||||||
import { LangProps } from '../APM';
|
|
||||||
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({
|
|
||||||
ingestionInfo,
|
|
||||||
activeStep,
|
|
||||||
}: LangProps): JSX.Element {
|
|
||||||
const [selectedFrameWork, setSelectedFrameWork] = useState('spring_boot');
|
|
||||||
const [selectedFrameWorkDocs, setSelectedFrameWorkDocs] = useState(
|
|
||||||
SprintBootDocs,
|
|
||||||
);
|
|
||||||
|
|
||||||
const [form] = Form.useForm();
|
|
||||||
const serviceName = Form.useWatch('Service Name', form);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// on language select
|
|
||||||
trackEvent('Onboarding: APM : Java', {
|
|
||||||
selectedFrameWork,
|
|
||||||
});
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [selectedFrameWork]);
|
|
||||||
|
|
||||||
const handleFrameworkChange = (selectedFrameWork: string): void => {
|
|
||||||
setSelectedFrameWork(selectedFrameWork);
|
|
||||||
|
|
||||||
switch (selectedFrameWork) {
|
|
||||||
case 'tomcat':
|
|
||||||
setSelectedFrameWorkDocs(TomcatDocs);
|
|
||||||
break;
|
|
||||||
case 'spring_boot':
|
|
||||||
setSelectedFrameWorkDocs(SprintBootDocs);
|
|
||||||
break;
|
|
||||||
case 'jboss':
|
|
||||||
setSelectedFrameWorkDocs(JbossDocs);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
setSelectedFrameWorkDocs(JavaDocs);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const variables = {
|
|
||||||
MYAPP: serviceName || '<service-name>',
|
|
||||||
SIGNOZ_INGESTION_KEY:
|
|
||||||
ingestionInfo.SIGNOZ_INGESTION_KEY || '<SIGNOZ_INGESTION_KEY>',
|
|
||||||
REGION: ingestionInfo.REGION || 'region',
|
|
||||||
};
|
|
||||||
|
|
||||||
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
|
|
||||||
getPopupContainer={popupContainer}
|
|
||||||
defaultValue="spring_boot"
|
|
||||||
style={{ minWidth: 120 }}
|
|
||||||
placeholder="Select Framework"
|
|
||||||
onChange={(value): void => handleFrameworkChange(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">
|
|
||||||
<MarkdownRenderer
|
|
||||||
markdownContent={selectedFrameWorkDocs}
|
|
||||||
variables={variables}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{activeStep === 3 && (
|
|
||||||
<ConnectionStatus
|
|
||||||
serviceName={form.getFieldValue('Service Name')}
|
|
||||||
language="java"
|
|
||||||
framework={(FrameworksMap as any)[selectedFrameWork]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,143 +0,0 @@
|
|||||||
import './Javascript.styles.scss';
|
|
||||||
|
|
||||||
import { Form, Input, Select } from 'antd';
|
|
||||||
import { MarkdownRenderer } from 'components/MarkdownRenderer/MarkdownRenderer';
|
|
||||||
import Header from 'container/OnboardingContainer/common/Header/Header';
|
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
import { trackEvent } from 'utils/segmentAnalytics';
|
|
||||||
import { popupContainer } from 'utils/selectPopupContainer';
|
|
||||||
|
|
||||||
import { LangProps } from '../APM';
|
|
||||||
import ConnectionStatus from '../common/ConnectionStatus/ConnectionStatus';
|
|
||||||
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',
|
|
||||||
nodejs: 'Nodejs',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function Javascript({
|
|
||||||
ingestionInfo,
|
|
||||||
activeStep,
|
|
||||||
}: LangProps): JSX.Element {
|
|
||||||
const [selectedFrameWork, setSelectedFrameWork] = useState('express');
|
|
||||||
const [selectedFrameWorkDocs, setSelectedFrameWorkDocs] = useState(
|
|
||||||
ExpressDocs,
|
|
||||||
);
|
|
||||||
const [form] = Form.useForm();
|
|
||||||
const serviceName = Form.useWatch('Service Name', form);
|
|
||||||
|
|
||||||
const variables = {
|
|
||||||
MYAPP: serviceName || '<service-name>',
|
|
||||||
SIGNOZ_INGESTION_KEY:
|
|
||||||
ingestionInfo.SIGNOZ_INGESTION_KEY || '<SIGNOZ_INGESTION_KEY>',
|
|
||||||
REGION: ingestionInfo.REGION || 'region',
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// on language select
|
|
||||||
trackEvent('Onboarding: APM : Javascript', {
|
|
||||||
selectedFrameWork,
|
|
||||||
});
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [selectedFrameWork]);
|
|
||||||
|
|
||||||
const handleFrameworkChange = (selectedFrameWork: string): void => {
|
|
||||||
setSelectedFrameWork(selectedFrameWork);
|
|
||||||
|
|
||||||
switch (selectedFrameWork) {
|
|
||||||
case 'nodejs':
|
|
||||||
setSelectedFrameWorkDocs(JavascriptDocs);
|
|
||||||
break;
|
|
||||||
case 'nestjs':
|
|
||||||
setSelectedFrameWorkDocs(NestJsDocs);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
setSelectedFrameWorkDocs(ExpressDocs);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
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
|
|
||||||
getPopupContainer={popupContainer}
|
|
||||||
defaultValue="express"
|
|
||||||
style={{ minWidth: 120 }}
|
|
||||||
placeholder="Select Framework"
|
|
||||||
onChange={(value): void => handleFrameworkChange(value)}
|
|
||||||
options={[
|
|
||||||
{
|
|
||||||
value: 'nodejs',
|
|
||||||
label: frameworksMap.nodejs,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'express',
|
|
||||||
label: frameworksMap.express,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'nestjs',
|
|
||||||
label: frameworksMap.nestjs,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="service-name-container">
|
|
||||||
<div className="label"> Service Name </div>
|
|
||||||
|
|
||||||
<Form
|
|
||||||
form={form}
|
|
||||||
name="service-name"
|
|
||||||
style={{ minWidth: '300px' }}
|
|
||||||
scrollToFirstError
|
|
||||||
requiredMark
|
|
||||||
>
|
|
||||||
<Form.Item
|
|
||||||
hasFeedback
|
|
||||||
name="Service Name"
|
|
||||||
rules={[{ required: true }]}
|
|
||||||
validateTrigger="onBlur"
|
|
||||||
required
|
|
||||||
>
|
|
||||||
<Input autoFocus />
|
|
||||||
</Form.Item>
|
|
||||||
</Form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="content-container">
|
|
||||||
<MarkdownRenderer
|
|
||||||
markdownContent={selectedFrameWorkDocs}
|
|
||||||
variables={variables}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{activeStep === 3 && (
|
|
||||||
<ConnectionStatus
|
|
||||||
serviceName={form.getFieldValue('Service Name')}
|
|
||||||
language="javascript"
|
|
||||||
framework={selectedFrameWork}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,152 +0,0 @@
|
|||||||
import './Python.styles.scss';
|
|
||||||
|
|
||||||
import { Form, Input, Select } from 'antd';
|
|
||||||
import { MarkdownRenderer } from 'components/MarkdownRenderer/MarkdownRenderer';
|
|
||||||
import Header from 'container/OnboardingContainer/common/Header/Header';
|
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
import { trackEvent } from 'utils/segmentAnalytics';
|
|
||||||
import { popupContainer } from 'utils/selectPopupContainer';
|
|
||||||
|
|
||||||
import { LangProps } from '../APM';
|
|
||||||
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({
|
|
||||||
ingestionInfo,
|
|
||||||
activeStep,
|
|
||||||
}: LangProps): JSX.Element {
|
|
||||||
const [selectedFrameWork, setSelectedFrameWork] = useState('django');
|
|
||||||
const [selectedFrameWorkDocs, setSelectedFrameWorkDocs] = useState(DjangoDocs);
|
|
||||||
const [form] = Form.useForm();
|
|
||||||
const serviceName = Form.useWatch('Service Name', form);
|
|
||||||
|
|
||||||
const variables = {
|
|
||||||
MYAPP: serviceName || '<service-name>',
|
|
||||||
SIGNOZ_INGESTION_KEY:
|
|
||||||
ingestionInfo.SIGNOZ_INGESTION_KEY || '<SIGNOZ_INGESTION_KEY>',
|
|
||||||
REGION: ingestionInfo.REGION || 'region',
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// on language select
|
|
||||||
trackEvent('Onboarding: APM : Python', {
|
|
||||||
selectedFrameWork,
|
|
||||||
});
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [selectedFrameWork]);
|
|
||||||
|
|
||||||
const handleFrameworkChange = (selectedFrameWork: string): void => {
|
|
||||||
setSelectedFrameWork(selectedFrameWork);
|
|
||||||
|
|
||||||
switch (selectedFrameWork) {
|
|
||||||
case 'django':
|
|
||||||
setSelectedFrameWorkDocs(DjangoDocs);
|
|
||||||
break;
|
|
||||||
case 'fastAPI':
|
|
||||||
setSelectedFrameWorkDocs(FastAPIDocs);
|
|
||||||
break;
|
|
||||||
case 'flask':
|
|
||||||
setSelectedFrameWorkDocs(FlaskDocs);
|
|
||||||
break;
|
|
||||||
case 'falcon':
|
|
||||||
setSelectedFrameWorkDocs(FalconDocs);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
setSelectedFrameWorkDocs(PythonDocs);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
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
|
|
||||||
getPopupContainer={popupContainer}
|
|
||||||
defaultValue="Django"
|
|
||||||
style={{ minWidth: 120 }}
|
|
||||||
placeholder="Select Framework"
|
|
||||||
onChange={(value): void => handleFrameworkChange(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">
|
|
||||||
<MarkdownRenderer
|
|
||||||
markdownContent={selectedFrameWorkDocs}
|
|
||||||
variables={variables}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{activeStep === 3 && (
|
|
||||||
<ConnectionStatus
|
|
||||||
serviceName={form.getFieldValue('Service Name')}
|
|
||||||
language="python"
|
|
||||||
framework={selectedFrameWork}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
import './ROR.styles.scss';
|
|
||||||
|
|
||||||
import { Form, Input } from 'antd';
|
|
||||||
import { MarkdownRenderer } from 'components/MarkdownRenderer/MarkdownRenderer';
|
|
||||||
import Header from 'container/OnboardingContainer/common/Header/Header';
|
|
||||||
|
|
||||||
import { LangProps } from '../APM';
|
|
||||||
import ConnectionStatus from '../common/ConnectionStatus/ConnectionStatus';
|
|
||||||
import RORDocs from './RubyOnRails.md';
|
|
||||||
|
|
||||||
export default function RoR({
|
|
||||||
ingestionInfo,
|
|
||||||
activeStep,
|
|
||||||
}: LangProps): JSX.Element {
|
|
||||||
const [form] = Form.useForm();
|
|
||||||
const serviceName = Form.useWatch('Service Name', form);
|
|
||||||
|
|
||||||
const variables = {
|
|
||||||
MYAPP: serviceName || '<service-name>',
|
|
||||||
SIGNOZ_INGESTION_KEY:
|
|
||||||
ingestionInfo.SIGNOZ_INGESTION_KEY || '<SIGNOZ_INGESTION_KEY>',
|
|
||||||
REGION: ingestionInfo.REGION || 'region',
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{activeStep === 2 && (
|
|
||||||
<div className="ror-setup-instructions-container">
|
|
||||||
<Header
|
|
||||||
entity="rails"
|
|
||||||
heading="Ruby on Rails OpenTelemetry Instrumentation"
|
|
||||||
imgURL="/Logos/rails.png"
|
|
||||||
docsURL="https://signoz.io/docs/instrumentation/ruby-on-rails/"
|
|
||||||
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">
|
|
||||||
<MarkdownRenderer markdownContent={RORDocs} variables={variables} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{activeStep === 3 && (
|
|
||||||
<ConnectionStatus
|
|
||||||
serviceName={form.getFieldValue('Service Name')}
|
|
||||||
framework="rails"
|
|
||||||
language="rails"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
.infrastructure-monitoring-module-container {
|
|
||||||
padding: 48px 0;
|
|
||||||
|
|
||||||
.module-header {
|
|
||||||
h1 {
|
|
||||||
font-size: 24px;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 300;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
display: flex;
|
|
||||||
gap: 16px;
|
|
||||||
justify-content: flex-start;
|
|
||||||
align-items: center;
|
|
||||||
margin: 16px 0;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,154 +0,0 @@
|
|||||||
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
|
||||||
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
|
||||||
import './InfrastructureMonitoring.styles.scss';
|
|
||||||
|
|
||||||
import cx from 'classnames';
|
|
||||||
import { Code, Pre } from 'components/MarkdownRenderer/MarkdownRenderer';
|
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
import ReactMarkdown from 'react-markdown';
|
|
||||||
import { trackEvent } from 'utils/segmentAnalytics';
|
|
||||||
|
|
||||||
import Header from '../common/Header/Header';
|
|
||||||
import hostMetricsMonitoring from './md-docs/hostMetricsMonitoring.md';
|
|
||||||
import k8sInfraMonitoringDocs from './md-docs/kubernetesInfraMonitoring.md';
|
|
||||||
import otherMetrics from './md-docs/otherMetrics.md';
|
|
||||||
|
|
||||||
export default function InfrastructureMonitoring({
|
|
||||||
activeStep,
|
|
||||||
}: {
|
|
||||||
activeStep: number;
|
|
||||||
}): JSX.Element {
|
|
||||||
const [selectedInfraMetrics, setSelectedInfraMetrics] = useState('kubernetes');
|
|
||||||
const [selectedInfraMetricsDocs, setSelectedInfraMetricsDocs] = useState(
|
|
||||||
k8sInfraMonitoringDocs,
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// on metrics Type select
|
|
||||||
trackEvent('Onboarding: APM : Java', {
|
|
||||||
selectedInfraMetrics,
|
|
||||||
});
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [selectedInfraMetrics]);
|
|
||||||
|
|
||||||
const supportedInfraMetrics = [
|
|
||||||
{
|
|
||||||
name: 'Kubernetes Infra Metrics',
|
|
||||||
id: 'kubernetes',
|
|
||||||
imgURL: `Logos/kubernetes.svg`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'HostMetrics',
|
|
||||||
id: 'hostMetrics',
|
|
||||||
imgURL: `Logos/software-window.svg`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Other Metrics',
|
|
||||||
id: 'otherMetrics',
|
|
||||||
imgURL: `Logos/cmd-terminal.svg`,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const handleMetricsTypeChange = (selectedMetricsType: string): void => {
|
|
||||||
setSelectedInfraMetrics(selectedMetricsType);
|
|
||||||
|
|
||||||
switch (selectedMetricsType) {
|
|
||||||
case 'kubernetes':
|
|
||||||
setSelectedInfraMetricsDocs(k8sInfraMonitoringDocs);
|
|
||||||
break;
|
|
||||||
case 'hostMetrics':
|
|
||||||
setSelectedInfraMetricsDocs(hostMetricsMonitoring);
|
|
||||||
break;
|
|
||||||
case 'otherMetrics':
|
|
||||||
setSelectedInfraMetricsDocs(otherMetrics);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
setSelectedInfraMetricsDocs(otherMetrics);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getHeaderBasedOnType = (): JSX.Element => {
|
|
||||||
switch (selectedInfraMetrics) {
|
|
||||||
case 'hostMetrics':
|
|
||||||
return (
|
|
||||||
<Header
|
|
||||||
entity="hostMetrics"
|
|
||||||
heading="Host Metrics"
|
|
||||||
imgURL="/Logos/software-window.svg"
|
|
||||||
docsURL="https://signoz.io/docs/tutorial/opentelemetry-binary-usage-in-virtual-machine/"
|
|
||||||
imgClassName="supported-logs-type-img"
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
case 'otherMetrics':
|
|
||||||
return (
|
|
||||||
<Header
|
|
||||||
entity="otherMetrics"
|
|
||||||
heading="Other Metrics"
|
|
||||||
imgURL="/Logos/cmd-terminal.svg"
|
|
||||||
docsURL="https://signoz.io/docs/userguide/send-metrics-cloud/"
|
|
||||||
imgClassName="supported-logs-type-img"
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
default:
|
|
||||||
return (
|
|
||||||
<Header
|
|
||||||
entity="kubernetes"
|
|
||||||
heading="Kubernetes Metrics"
|
|
||||||
imgURL="/Logos/kubernetes.svg"
|
|
||||||
docsURL="https://signoz.io/docs/tutorial/kubernetes-infra-metrics/"
|
|
||||||
imgClassName="supported-logs-type-img"
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="infrastructure-monitoring-module-container">
|
|
||||||
{activeStep === 2 && (
|
|
||||||
<>
|
|
||||||
<div className="module-header">
|
|
||||||
<h1>Select an Infra Metrics type</h1>
|
|
||||||
{/* <h4> Choose the logs that you want to receive on SigNoz </h4> */}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="supported-logs-type-container">
|
|
||||||
{supportedInfraMetrics.map((logType) => (
|
|
||||||
<div
|
|
||||||
className={cx(
|
|
||||||
'supported-logs-type',
|
|
||||||
selectedInfraMetrics === logType.id ? 'selected' : '',
|
|
||||||
)}
|
|
||||||
key={logType.name}
|
|
||||||
onClick={(): void => handleMetricsTypeChange(logType.id)}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
className={cx('supported-logs-type-img')}
|
|
||||||
src={`${logType.imgURL}`}
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div> {logType.name} </div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{getHeaderBasedOnType()}
|
|
||||||
|
|
||||||
<div className="content-container">
|
|
||||||
<ReactMarkdown
|
|
||||||
components={{
|
|
||||||
pre: Pre,
|
|
||||||
code: Code,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{selectedInfraMetricsDocs}
|
|
||||||
</ReactMarkdown>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
## Hostmetrics Monitoring
|
|
||||||
You can collect Hostmetrics from your VM and send it to SigNoz cloud using OpenTelemetry Collector.
|
|
||||||
|
|
||||||
Steps to send hostmetrics to SigNoz Cloud:
|
|
||||||
|
|
||||||
- Install OpenTelemetry Collector binary agent. Please find instructions [here](https://signoz.io/docs/tutorial/opentelemetry-binary-usage-in-virtual-machine/#setup-otel-collector-as-agent).
|
|
||||||
|
|
||||||
- Import Hostmetrics Dashboard in SigNoz. Please find instructions [here](https://signoz.io/docs/tutorial/opentelemetry-binary-usage-in-virtual-machine/#hostmetrics-dashboard).
|
|
||||||
|
|
||||||
Learn how to create dashboards and panels [here](https://signoz.io/docs/userguide/manage-dashboards-and-panels/).
|
|
@ -1,9 +0,0 @@
|
|||||||
## Kubernetes Infra Metrics
|
|
||||||
|
|
||||||
You can collect Kubernetes infra metrics from your k8s cluster and send it to SigNoz cloud using k8s-infra chart.
|
|
||||||
|
|
||||||
Steps to send kubernetes infra metrics to SigNoz Cloud:
|
|
||||||
|
|
||||||
- Install OpenTelemetry Collectors in your k8s infra. Please find instructions [here](https://signoz.io/docs/tutorial/kubernetes-infra-metrics/).
|
|
||||||
|
|
||||||
- Plot metrics in SigNoz UI by following the instructions [here](https://signoz.io/docs/tutorial/kubernetes-infra-metrics/#plot-metrics-in-signoz-ui).
|
|
@ -1,195 +0,0 @@
|
|||||||
## Send metrics from any third-party integrations
|
|
||||||
|
|
||||||
This document helps you to send metrics from any third-party integrations such as RabbitMQ, Nginx, MySQL, etc.
|
|
||||||
|
|
||||||
There are two ways in which you can send metrics to SigNoz using OpenTelemetry:
|
|
||||||
|
|
||||||
- From your application
|
|
||||||
- From OpenTelemetry Collector
|
|
||||||
|
|
||||||
In this document, we will cover how to send metrics from OpenTelemetry Collector. The Collector is a swiss-army knife that can collect metrics from various sources and send them to SigNoz.
|
|
||||||
|
|
||||||
- Enable a Specific Metric Receiver
|
|
||||||
- Enable a Prometheus Receiver
|
|
||||||
|
|
||||||
## 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` and `service::pipelines` sections of the `otel-collector-config.yaml` file. The following example shows the default configuration in which the `hostmetrics` receiver is enabled:
|
|
||||||
|
|
||||||
```yaml {8-20,52}
|
|
||||||
receivers:
|
|
||||||
otlp:
|
|
||||||
protocols:
|
|
||||||
grpc:
|
|
||||||
endpoint: localhost:4317
|
|
||||||
http:
|
|
||||||
endpoint: localhost:4318
|
|
||||||
hostmetrics:
|
|
||||||
collection_interval: 30s
|
|
||||||
scrapers:
|
|
||||||
cpu: {}
|
|
||||||
disk: {}
|
|
||||||
load: {}
|
|
||||||
filesystem: {}
|
|
||||||
memory: {}
|
|
||||||
network: {}
|
|
||||||
paging: {}
|
|
||||||
process:
|
|
||||||
mute_process_name_error: true
|
|
||||||
processes: {}
|
|
||||||
processors:
|
|
||||||
batch:
|
|
||||||
send_batch_size: 1000
|
|
||||||
timeout: 10s
|
|
||||||
# Ref: https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/processor/resourcedetectionprocessor/README.md
|
|
||||||
resourcedetection:
|
|
||||||
detectors: [env, system, ec2] # include ec2 for AWS, gce for GCP and azure for Azure.
|
|
||||||
# Using OTEL_RESOURCE_ATTRIBUTES envvar, env detector adds custom labels.
|
|
||||||
timeout: 2s
|
|
||||||
override: false
|
|
||||||
system:
|
|
||||||
hostname_sources: [os] # alternatively, use [dns,os] for setting FQDN as host.name and os as fallback
|
|
||||||
exporters:
|
|
||||||
otlp:
|
|
||||||
endpoint: 'ingest.{region}.signoz.cloud:443' # replace {region} with your region
|
|
||||||
tls:
|
|
||||||
insecure: false
|
|
||||||
headers:
|
|
||||||
'signoz-access-token': '<SIGNOZ_INGESTION_KEY>'
|
|
||||||
logging:
|
|
||||||
loglevel: debug
|
|
||||||
service:
|
|
||||||
telemetry:
|
|
||||||
metrics:
|
|
||||||
address: localhost:8888
|
|
||||||
pipelines:
|
|
||||||
metrics:
|
|
||||||
receivers: [otlp]
|
|
||||||
processors: [batch]
|
|
||||||
exporters: [otlp]
|
|
||||||
metrics/hostmetrics:
|
|
||||||
receivers: [hostmetrics]
|
|
||||||
processors: [resourcedetection, batch]
|
|
||||||
exporters: [otlp]
|
|
||||||
```
|
|
||||||
|
|
||||||
Depending on the choice of your region for SigNoz cloud, the ingest endpoint will vary according to this table.
|
|
||||||
|
|
||||||
US - ingest.us.signoz.cloud:443
|
|
||||||
|
|
||||||
IN - ingest.in.signoz.cloud:443
|
|
||||||
|
|
||||||
EU - ingest.eu.signoz.cloud:443
|
|
||||||
|
|
||||||
To enable a new OpenTelemetry receiver, follow the steps below:
|
|
||||||
|
|
||||||
1. Open the `otel-collector-config.yaml` file in a plain-text editor.
|
|
||||||
2. Configure your receivers. The following example shows how you can enable a `rabbitmq` receiver:
|
|
||||||
|
|
||||||
```yaml {21-25,53}
|
|
||||||
receivers:
|
|
||||||
otlp:
|
|
||||||
protocols:
|
|
||||||
grpc:
|
|
||||||
endpoint: localhost:4317
|
|
||||||
http:
|
|
||||||
endpoint: localhost:4318
|
|
||||||
hostmetrics:
|
|
||||||
collection_interval: 30s
|
|
||||||
scrapers:
|
|
||||||
cpu: {}
|
|
||||||
disk: {}
|
|
||||||
load: {}
|
|
||||||
filesystem: {}
|
|
||||||
memory: {}
|
|
||||||
network: {}
|
|
||||||
paging: {}
|
|
||||||
process:
|
|
||||||
mute_process_name_error: true
|
|
||||||
processes: {}
|
|
||||||
rabbitmq:
|
|
||||||
endpoint: http://localhost:15672
|
|
||||||
username: <RABBITMQ_USERNAME>
|
|
||||||
password: <RABBITMQ_PASSWORD>
|
|
||||||
collection_interval: 10s
|
|
||||||
processors:
|
|
||||||
batch:
|
|
||||||
send_batch_size: 1000
|
|
||||||
timeout: 10s
|
|
||||||
# Ref: https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/processor/resourcedetectionprocessor/README.md
|
|
||||||
resourcedetection:
|
|
||||||
detectors: [env, system, ec2] # include ec2 for AWS, gce for GCP and azure for Azure.
|
|
||||||
# Using OTEL_RESOURCE_ATTRIBUTES envvar, env detector adds custom labels.
|
|
||||||
timeout: 2s
|
|
||||||
override: false
|
|
||||||
system:
|
|
||||||
hostname_sources: [os] # alternatively, use [dns,os] for setting FQDN as host.name and os as fallback
|
|
||||||
exporters:
|
|
||||||
otlp:
|
|
||||||
endpoint: 'ingest.{region}.signoz.cloud:443' # replace {region} with your region
|
|
||||||
tls:
|
|
||||||
insecure: false
|
|
||||||
headers:
|
|
||||||
'signoz-access-token': '<SIGNOZ_INGESTION_KEY>'
|
|
||||||
logging:
|
|
||||||
loglevel: debug
|
|
||||||
service:
|
|
||||||
telemetry:
|
|
||||||
metrics:
|
|
||||||
address: localhost:8888
|
|
||||||
pipelines:
|
|
||||||
metrics:
|
|
||||||
receivers: [otlp, rabbitmq]
|
|
||||||
processors: [batch]
|
|
||||||
exporters: [otlp]
|
|
||||||
metrics/hostmetrics:
|
|
||||||
receivers: [hostmetrics]
|
|
||||||
processors: [resourcedetection, batch]
|
|
||||||
exporters: [otlp]
|
|
||||||
```
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
## 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 `otel-collector-config.yaml` file.
|
|
||||||
|
|
||||||
To enable a Prometheus receiver, follow the steps below:
|
|
||||||
|
|
||||||
1. Open the `otel-collector-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 {10-13}
|
|
||||||
...
|
|
||||||
# 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"]
|
|
||||||
...
|
|
||||||
# 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 {9}
|
|
||||||
...
|
|
||||||
# Data sources: metrics
|
|
||||||
prometheus:
|
|
||||||
config:
|
|
||||||
scrape_configs:
|
|
||||||
- job_name: "otel-collector"
|
|
||||||
scrape_interval: 30s
|
|
||||||
static_configs:
|
|
||||||
- targets: ["otel-collector:8889", "localhost:8080"]
|
|
||||||
...
|
|
||||||
# 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/)
|
|
@ -1,53 +0,0 @@
|
|||||||
import { Code, Pre } from 'components/MarkdownRenderer/MarkdownRenderer';
|
|
||||||
import Header from 'container/OnboardingContainer/common/Header/Header';
|
|
||||||
import ReactMarkdown from 'react-markdown';
|
|
||||||
|
|
||||||
import ConnectionStatus from '../common/LogsConnectionStatus/LogsConnectionStatus';
|
|
||||||
import LogsFromLogFile from './applicationLogsFromLogFile.md';
|
|
||||||
|
|
||||||
interface ApplicationLogsProps {
|
|
||||||
type: string;
|
|
||||||
activeStep: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
const collectLogsFromFileURL =
|
|
||||||
'https://signoz.io/docs/userguide/collect_logs_from_file/';
|
|
||||||
|
|
||||||
export default function ApplicationLogs({
|
|
||||||
type,
|
|
||||||
activeStep,
|
|
||||||
}: ApplicationLogsProps): JSX.Element {
|
|
||||||
const docsURL = collectLogsFromFileURL;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{activeStep === 2 && (
|
|
||||||
<div className="golang-setup-instructions-container">
|
|
||||||
<Header
|
|
||||||
entity="docker"
|
|
||||||
heading="Collecting Application Logs from Log file"
|
|
||||||
imgURL={`/Logos/${'software-window'}.svg`}
|
|
||||||
docsURL={docsURL}
|
|
||||||
imgClassName="supported-logs-type-img"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className="content-container">
|
|
||||||
<ReactMarkdown
|
|
||||||
components={{
|
|
||||||
pre: Pre,
|
|
||||||
code: Code,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{LogsFromLogFile}
|
|
||||||
</ReactMarkdown>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{activeStep === 3 && (
|
|
||||||
<div className="connection-status-container">
|
|
||||||
<ConnectionStatus logType={type} />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
import { Code, Pre } from 'components/MarkdownRenderer/MarkdownRenderer';
|
|
||||||
import Header from 'container/OnboardingContainer/common/Header/Header';
|
|
||||||
import ReactMarkdown from 'react-markdown';
|
|
||||||
|
|
||||||
import ConnectionStatus from '../common/LogsConnectionStatus/LogsConnectionStatus';
|
|
||||||
import DockerDocs 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">
|
|
||||||
<ReactMarkdown
|
|
||||||
components={{
|
|
||||||
pre: Pre,
|
|
||||||
code: Code,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{DockerDocs}
|
|
||||||
</ReactMarkdown>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{activeStep === 3 && (
|
|
||||||
<div className="connection-status-container">
|
|
||||||
<ConnectionStatus logType="docker" />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,97 +0,0 @@
|
|||||||
import { Select } from 'antd';
|
|
||||||
import { Code, Pre } from 'components/MarkdownRenderer/MarkdownRenderer';
|
|
||||||
import Header from 'container/OnboardingContainer/common/Header/Header';
|
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
import ReactMarkdown from 'react-markdown';
|
|
||||||
import { trackEvent } from 'utils/segmentAnalytics';
|
|
||||||
import { popupContainer } from 'utils/selectPopupContainer';
|
|
||||||
|
|
||||||
import FluentBit from './md-docs/fluentBit.md';
|
|
||||||
import FluentD from './md-docs/fluentD.md';
|
|
||||||
import LogStashDocs from './md-docs/logStash.md';
|
|
||||||
|
|
||||||
enum FrameworksMap {
|
|
||||||
fluent_d = 'FluentD',
|
|
||||||
fluent_bit = 'FluentBit',
|
|
||||||
logstash = 'Logstash',
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function ExistingCollectors(): JSX.Element {
|
|
||||||
const [selectedFrameWork, setSelectedFrameWork] = useState('fluent_d');
|
|
||||||
const [selectedFrameWorkDocs, setSelectedFrameWorkDocs] = useState(FluentD);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// on language select
|
|
||||||
trackEvent('Onboarding: Logs Management: Existing Collectors', {
|
|
||||||
selectedFrameWork,
|
|
||||||
});
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [selectedFrameWork]);
|
|
||||||
|
|
||||||
const handleFrameworkChange = (selectedFrameWork: string): void => {
|
|
||||||
setSelectedFrameWork(selectedFrameWork);
|
|
||||||
|
|
||||||
switch (selectedFrameWork) {
|
|
||||||
case 'fluent_d':
|
|
||||||
setSelectedFrameWorkDocs(FluentD);
|
|
||||||
break;
|
|
||||||
case 'fluent_bit':
|
|
||||||
setSelectedFrameWorkDocs(FluentBit);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
setSelectedFrameWorkDocs(LogStashDocs);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="java-setup-instructions-container">
|
|
||||||
<Header
|
|
||||||
entity="existing_collectors"
|
|
||||||
heading="Logs from existing collectors"
|
|
||||||
imgURL="/Logos/cmd-terminal.svg"
|
|
||||||
docsURL="https://signoz.io/docs/userguide/fluentbit_to_signoz/"
|
|
||||||
imgClassName="supported-language-img"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className="form-container">
|
|
||||||
<div className="framework-selector">
|
|
||||||
<div className="label"> Select Framework </div>
|
|
||||||
|
|
||||||
<Select
|
|
||||||
getPopupContainer={popupContainer}
|
|
||||||
defaultValue="fluent_d"
|
|
||||||
style={{ minWidth: 120 }}
|
|
||||||
placeholder="Select Framework"
|
|
||||||
onChange={(value): void => handleFrameworkChange(value)}
|
|
||||||
options={[
|
|
||||||
{
|
|
||||||
value: 'fluent_d',
|
|
||||||
label: FrameworksMap.fluent_d,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'fluent_bit',
|
|
||||||
label: FrameworksMap.fluent_bit,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'logstash',
|
|
||||||
label: FrameworksMap.logstash,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="content-container">
|
|
||||||
<ReactMarkdown
|
|
||||||
components={{
|
|
||||||
pre: Pre,
|
|
||||||
code: Code,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{selectedFrameWorkDocs}
|
|
||||||
</ReactMarkdown>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,58 +0,0 @@
|
|||||||
## Collect Logs Using FluentBit in SigNoz cloud
|
|
||||||
|
|
||||||
If you use fluentBit to collect logs in your stack, you will be able to send logs from fluentBit to SigNoz.
|
|
||||||
|
|
||||||
At SigNoz we use opentelemetry collector to recieve logs which supports the fluentforward protocol. So you can forward your logs from your fluentBit agent to opentelemetry collector using fluentforward protocol.
|
|
||||||
|
|
||||||
* Add otel collector binary to your VM by following this [guide](https://signoz.io/docs/tutorial/opentelemetry-binary-usage-in-virtual-machine/).
|
|
||||||
|
|
||||||
* Add fluentforward reciever to your `config.yaml`
|
|
||||||
```yaml
|
|
||||||
receivers:
|
|
||||||
fluentforward:
|
|
||||||
endpoint: 0.0.0.0:24224
|
|
||||||
```
|
|
||||||
Here we have used port 24224 for listening in fluentforward protocol, but you can change it to a port you want.
|
|
||||||
You can read more about fluentforward receiver [here](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/fluentforwardreceiver).
|
|
||||||
|
|
||||||
* Modify your `config.yaml` and add the above receiver
|
|
||||||
```yaml {4}
|
|
||||||
service:
|
|
||||||
....
|
|
||||||
logs:
|
|
||||||
receivers: [otlp, fluentforward]
|
|
||||||
processors: [batch]
|
|
||||||
exporters: [otlp]
|
|
||||||
```
|
|
||||||
|
|
||||||
* Add the following to your fluentBit config to forward the logs to otel collector.
|
|
||||||
```
|
|
||||||
[OUTPUT]
|
|
||||||
Name forward
|
|
||||||
Match *
|
|
||||||
Host localhost
|
|
||||||
Port 24224
|
|
||||||
```
|
|
||||||
In this config we are forwarding the logs to the otel collector which is listening on port 24224.
|
|
||||||
Also we are assuming that you are running the fluentBit binary on the host. If not, the value of `host` might change depending on your environment.
|
|
||||||
|
|
||||||
* Once you make this changes you can restart fluentBit and otel-binary, and you will be able to see the logs in SigNoz.
|
|
||||||
|
|
||||||
* To properly transform your existing log model into opentelemetry [log](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md) model you can use the different processors provided by opentelemetry. ([link](https://signoz.io/docs/userguide/logs/#processors-available-for-processing-logs))
|
|
||||||
|
|
||||||
eg:-
|
|
||||||
```yaml
|
|
||||||
processors:
|
|
||||||
logstransform:
|
|
||||||
operators:
|
|
||||||
- type: trace_parser
|
|
||||||
trace_id:
|
|
||||||
parse_from: attributes.trace_id
|
|
||||||
span_id:
|
|
||||||
parse_from: attributes.span_id
|
|
||||||
- type: remove
|
|
||||||
field: attributes.trace_id
|
|
||||||
- type: remove
|
|
||||||
field: attributes.span_id
|
|
||||||
```
|
|
||||||
The operations in the above processor will parse the trace_id and span_id from log to opentelemetry log model and remove them from attributes.
|
|
@ -1,66 +0,0 @@
|
|||||||
## Collect Logs Using FluentD in SigNoz cloud
|
|
||||||
|
|
||||||
If you use fluentD to collect logs in your stack, you will be able to send logs from fluentD to SigNoz.
|
|
||||||
|
|
||||||
At SigNoz, we use opentelemetry collector to recieve logs which supports the fluentforward protocol. So you can forward your logs from your fluentD agent to opentelemetry collector.
|
|
||||||
|
|
||||||
* Add otel collector binary to your VM by following this [guide](https://signoz.io/docs/tutorial/opentelemetry-binary-usage-in-virtual-machine/).
|
|
||||||
|
|
||||||
* Add fluentforward reciever to your `config.yaml`
|
|
||||||
```yaml
|
|
||||||
receivers:
|
|
||||||
fluentforward:
|
|
||||||
endpoint: 0.0.0.0:24224
|
|
||||||
```
|
|
||||||
Here we have used port 24224 for listening in fluentforward protocol, but you can change it to a port you want.
|
|
||||||
You can read more about fluentforward receiver [here](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/fluentforwardreceiver).
|
|
||||||
|
|
||||||
* Modify your `config.yaml` and add the above receiver
|
|
||||||
```yaml {4}
|
|
||||||
service:
|
|
||||||
....
|
|
||||||
logs:
|
|
||||||
receivers: [otlp, fluentforward]
|
|
||||||
processors: [batch]
|
|
||||||
exporters: [otlp]
|
|
||||||
```
|
|
||||||
|
|
||||||
* Add the following to your fluentD config to forward the logs to otel collector.
|
|
||||||
```
|
|
||||||
<match <directive>>
|
|
||||||
@type forward
|
|
||||||
send_timeout 60s
|
|
||||||
recover_wait 10s
|
|
||||||
hard_timeout 60s
|
|
||||||
|
|
||||||
<server>
|
|
||||||
name myserver1
|
|
||||||
host localhost
|
|
||||||
port 24224
|
|
||||||
</server>
|
|
||||||
</match>
|
|
||||||
```
|
|
||||||
In this config we are matching a directive and forwarding logs to the otel collector which is listening on port 24224. Replace `<directive>` with your directive name.
|
|
||||||
Also we are assuming that you are running the fluentD binary on the host. If not, the value of `host` might change depending on your environment.
|
|
||||||
* Once you make this changes you can restart fluentD and otel-binary, and you will be able to see the logs in SigNoz.
|
|
||||||
|
|
||||||
* To properly transform your existing log model into opentelemetry [log](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md) model you can use the different processors provided by opentelemetry. ([link](https://signoz.io/docs/userguide/logs/#processors-available-for-processing-logs))
|
|
||||||
|
|
||||||
eg:-
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
processors:
|
|
||||||
logstransform:
|
|
||||||
operators:
|
|
||||||
- type: trace_parser
|
|
||||||
trace_id:
|
|
||||||
parse_from: attributes.trace_id
|
|
||||||
span_id:
|
|
||||||
parse_from: attributes.span_id
|
|
||||||
- type: remove
|
|
||||||
field: attributes.trace_id
|
|
||||||
- type: remove
|
|
||||||
field: attributes.span_id
|
|
||||||
```
|
|
||||||
|
|
||||||
The operations in the above processor will parse the trace_id and span_id from log to opentelemetry log model and remove them from attributes.
|
|
@ -1,48 +0,0 @@
|
|||||||
## Collect Logs Using Logstash in SigNoz cloud
|
|
||||||
|
|
||||||
If you use logstash to collect logs in your stack, you will be able to send logs from Logstash to SigNoz.
|
|
||||||
|
|
||||||
At SigNoz we use OpenTelemetry Collector to recieve logs which supports the TCP protocol. So you can forward your logs from the logstash agent to opentelemetry collector.
|
|
||||||
|
|
||||||
* Add otel collector binary to your VM by following this [guide](https://signoz.io/docs/tutorial/opentelemetry-binary-usage-in-virtual-machine/).
|
|
||||||
|
|
||||||
* Add the reciever to your `config.yaml`
|
|
||||||
```yaml
|
|
||||||
receivers:
|
|
||||||
tcplog/logstash:
|
|
||||||
max_log_size: 1MiB
|
|
||||||
listen_address: "0.0.0.0:2255"
|
|
||||||
attributes: {}
|
|
||||||
resource: {}
|
|
||||||
add_attributes: false
|
|
||||||
operators: []
|
|
||||||
```
|
|
||||||
Here we have used port 2255 for listening in TCP protocol, but you can change it to a port you want.
|
|
||||||
You can read more about tcplog reciver [here](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/tcplogreceiver).
|
|
||||||
|
|
||||||
* Modify your `config.yaml` and add the above receiver
|
|
||||||
```yaml {4}
|
|
||||||
service:
|
|
||||||
....
|
|
||||||
logs:
|
|
||||||
receivers: [otlp, tcplog/logstash]
|
|
||||||
processors: [batch]
|
|
||||||
exporters: [otlp]
|
|
||||||
```
|
|
||||||
|
|
||||||
* Change the logstash config to forward the logs to otel collector.
|
|
||||||
```
|
|
||||||
output {
|
|
||||||
tcp {
|
|
||||||
codec => json_lines # this is required otherwise it will send eveything in a single line
|
|
||||||
host => "localhost"
|
|
||||||
port => 2255
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
Here we are configuring logstash to send logs to otel-collector that we ran in the previous step, which is listening on port 2255.
|
|
||||||
Also we are assuming that you are running the logstash binary on the host. If not, the value of `host` might change depending on your environment.
|
|
||||||
|
|
||||||
* Once you make this changes you can otel binary and logstash, and you will be able to see the logs in SigNoz.
|
|
||||||
|
|
||||||
* To properly transform your existing log model into opentelemetry [log](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md) model you can use the different processors provided by opentelemetry ([link](https://signoz.io/docs/userguide/logs/#processors-available-for-processing-logs)).
|
|
@ -1,44 +0,0 @@
|
|||||||
import { Code, Pre } from 'components/MarkdownRenderer/MarkdownRenderer';
|
|
||||||
import Header from 'container/OnboardingContainer/common/Header/Header';
|
|
||||||
import ReactMarkdown from 'react-markdown';
|
|
||||||
|
|
||||||
import ConnectionStatus from '../common/LogsConnectionStatus/LogsConnectionStatus';
|
|
||||||
import KubernetesDocs 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">
|
|
||||||
<ReactMarkdown
|
|
||||||
components={{
|
|
||||||
pre: Pre,
|
|
||||||
code: Code,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{KubernetesDocs}
|
|
||||||
</ReactMarkdown>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{activeStep === 3 && (
|
|
||||||
<div className="connection-status-container">
|
|
||||||
<ConnectionStatus logType="kubernetes" />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,152 +0,0 @@
|
|||||||
.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,130 +0,0 @@
|
|||||||
/* 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 { useEffect, useState } from 'react';
|
|
||||||
import { trackEvent } from 'utils/segmentAnalytics';
|
|
||||||
|
|
||||||
import ApplicationLogs from './ApplicationLogs/ApplicationLogs';
|
|
||||||
import Docker from './Docker/Docker';
|
|
||||||
import ExistingCollectors from './ExistingCollectors/ExistingCollectors';
|
|
||||||
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: 'Logs from existing collectors',
|
|
||||||
id: 'existing_collectors',
|
|
||||||
imgURL: `Logos/cmd-terminal.svg`,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function LogsManagement({
|
|
||||||
activeStep,
|
|
||||||
handleLogTypeSelect,
|
|
||||||
}: {
|
|
||||||
activeStep: number;
|
|
||||||
handleLogTypeSelect: (id: string) => any;
|
|
||||||
}): JSX.Element {
|
|
||||||
const [selectedLogsType, setSelectedLogsType] = useState('kubernetes');
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// on language select
|
|
||||||
trackEvent('Onboarding: Logs Management', {
|
|
||||||
selectedLogsType,
|
|
||||||
activeStep,
|
|
||||||
});
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [selectedLogsType]);
|
|
||||||
|
|
||||||
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} />;
|
|
||||||
case 'existing_collectors':
|
|
||||||
return <ExistingCollectors />;
|
|
||||||
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>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
import { Code, Pre } from 'components/MarkdownRenderer/MarkdownRenderer';
|
|
||||||
import Header from 'container/OnboardingContainer/common/Header/Header';
|
|
||||||
import ReactMarkdown from 'react-markdown';
|
|
||||||
|
|
||||||
import ConnectionStatus from '../common/LogsConnectionStatus/LogsConnectionStatus';
|
|
||||||
import NodeJsDocs 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">
|
|
||||||
<ReactMarkdown
|
|
||||||
components={{
|
|
||||||
pre: Pre,
|
|
||||||
code: Code,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{NodeJsDocs}
|
|
||||||
</ReactMarkdown>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{activeStep === 3 && (
|
|
||||||
<div className="connection-status-container">
|
|
||||||
<ConnectionStatus logType="nodejs" />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
import { Code, Pre } from 'components/MarkdownRenderer/MarkdownRenderer';
|
|
||||||
import Header from 'container/OnboardingContainer/common/Header/Header';
|
|
||||||
import ReactMarkdown from 'react-markdown';
|
|
||||||
|
|
||||||
import ConnectionStatus from '../common/LogsConnectionStatus/LogsConnectionStatus';
|
|
||||||
import SysLogsDocs 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">
|
|
||||||
<ReactMarkdown
|
|
||||||
components={{
|
|
||||||
pre: Pre,
|
|
||||||
code: Code,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{SysLogsDocs}
|
|
||||||
</ReactMarkdown>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{activeStep === 3 && (
|
|
||||||
<div className="connection-status-container">
|
|
||||||
<ConnectionStatus logType="syslogs" />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
@ -0,0 +1,21 @@
|
|||||||
|
### Install otel-collector in your Kubernetes infra
|
||||||
|
|
||||||
|
Add the SigNoz Helm Chart repository
|
||||||
|
```bash
|
||||||
|
helm repo add signoz https://charts.signoz.io
|
||||||
|
```
|
||||||
|
|
||||||
|
If the chart is already present, update the chart to the latest using:
|
||||||
|
```bash
|
||||||
|
helm repo update
|
||||||
|
```
|
||||||
|
|
||||||
|
Install the Kubernetes Infrastructure chart provided by SigNoz
|
||||||
|
```bash
|
||||||
|
helm install my-release signoz/k8s-infra \
|
||||||
|
--set otelCollectorEndpoint=ingest.{{REGION}}.signoz.cloud:443 \
|
||||||
|
--set otelInsecure=false \
|
||||||
|
--set signozApiKey={{SIGNOZ_INGESTION_KEY}} \
|
||||||
|
--set global.clusterName=<CLUSTER_NAME>
|
||||||
|
```
|
||||||
|
- Replace `<CLUSTER_NAME>` with the name of the Kubernetes cluster or a unique identifier of the cluster.
|
@ -0,0 +1,116 @@
|
|||||||
|
After setting up the Otel collector agent, follow the steps below to instrumnet your Go Application
|
||||||
|
|
||||||
|
### Step 1: Install OpenTelemetry Dependencies
|
||||||
|
Dependencies related to OpenTelemetry exporter and SDK have to be installed first
|
||||||
|
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** Note that we are assuming you are using gin request router. If you are using other request routers, check out the [corresponding package](https://signoz.io/docs/instrumentation/golang/#request-routers).
|
||||||
|
|
||||||
|
### Step 2: Declare environment variables for configuring OpenTelemetry
|
||||||
|
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")
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Instrument your Go application
|
||||||
|
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.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 4: Initialise the tracer in `main.go`
|
||||||
|
Modify the main function to initialise the tracer in main.go. Initiate the tracer at the very beginning of our main function.
|
||||||
|
```bash
|
||||||
|
func main() {
|
||||||
|
cleanup := initTracer()
|
||||||
|
defer cleanup(context.Background())
|
||||||
|
|
||||||
|
......
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 5: Add the OpenTelemetry Gin middleware
|
||||||
|
Configure Gin to use the middleware by adding the following lines in `main.go`
|
||||||
|
```bash
|
||||||
|
import (
|
||||||
|
....
|
||||||
|
"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
......
|
||||||
|
r := gin.Default()
|
||||||
|
r.Use(otelgin.Middleware(serviceName))
|
||||||
|
......
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
|||||||
|
To run your Go Gin application, use the below command :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
SERVICE_NAME={{MYAPP}} INSECURE_MODE=true OTEL_EXPORTER_OTLP_ENDPOINT=localhost:4317 go run main.go
|
||||||
|
```
|
@ -0,0 +1,115 @@
|
|||||||
|
|
||||||
|
### Step 1: Install OpenTelemetry Dependencies
|
||||||
|
Dependencies related to OpenTelemetry exporter and SDK have to be installed first
|
||||||
|
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** Note that we are assuming you are using gin request router. If you are using other request routers, check out the [corresponding package](https://signoz.io/docs/instrumentation/golang/#request-routers).
|
||||||
|
|
||||||
|
### Step 2: Declare environment variables for configuring OpenTelemetry
|
||||||
|
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")
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Instrument your Go application
|
||||||
|
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.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 4: Initialise the tracer in `main.go`
|
||||||
|
Modify the main function to initialise the tracer in main.go. Initiate the tracer at the very beginning of our main function.
|
||||||
|
```bash
|
||||||
|
func main() {
|
||||||
|
cleanup := initTracer()
|
||||||
|
defer cleanup(context.Background())
|
||||||
|
|
||||||
|
......
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 5: Add the OpenTelemetry Gin middleware
|
||||||
|
Configure Gin to use the middleware by adding the following lines in `main.go`
|
||||||
|
```bash
|
||||||
|
import (
|
||||||
|
....
|
||||||
|
"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
......
|
||||||
|
r := gin.Default()
|
||||||
|
r.Use(otelgin.Middleware(serviceName))
|
||||||
|
......
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
|||||||
|
To run your Go Gin application, use the below command :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
SERVICE_NAME={{MYAPP}} INSECURE_MODE=false OTEL_EXPORTER_OTLP_HEADERS=signoz-access-token={{SIGNOZ_INGESTION_KEY}} OTEL_EXPORTER_OTLP_ENDPOINT=ingest.{{REGION}}.signoz.cloud:443 go run main.go
|
||||||
|
```
|
@ -0,0 +1,93 @@
|
|||||||
|
### Setup OpenTelemetry Binary as an agent
|
||||||
|
|
||||||
|
### Step 1: Download otel-collector tar.gz
|
||||||
|
```bash
|
||||||
|
wget https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v0.79.0/otelcol-contrib_0.79.0_linux_amd64.tar.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2: Extract otel-collector tar.gz to the `otelcol-contrib` folder
|
||||||
|
```bash
|
||||||
|
mkdir otelcol-contrib && tar xvzf otelcol-contrib_0.79.0_linux_amd64.tar.gz -C otelcol-contrib
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Create config.yaml in folder otelcol-contrib with the below content in it
|
||||||
|
```bash
|
||||||
|
receivers:
|
||||||
|
otlp:
|
||||||
|
protocols:
|
||||||
|
grpc:
|
||||||
|
endpoint: 0.0.0.0:4317
|
||||||
|
http:
|
||||||
|
endpoint: 0.0.0.0:4318
|
||||||
|
hostmetrics:
|
||||||
|
collection_interval: 60s
|
||||||
|
scrapers:
|
||||||
|
cpu: {}
|
||||||
|
disk: {}
|
||||||
|
load: {}
|
||||||
|
filesystem: {}
|
||||||
|
memory: {}
|
||||||
|
network: {}
|
||||||
|
paging: {}
|
||||||
|
process:
|
||||||
|
mute_process_name_error: true
|
||||||
|
mute_process_exe_error: true
|
||||||
|
mute_process_io_error: true
|
||||||
|
processes: {}
|
||||||
|
prometheus:
|
||||||
|
config:
|
||||||
|
global:
|
||||||
|
scrape_interval: 60s
|
||||||
|
scrape_configs:
|
||||||
|
- job_name: otel-collector-binary
|
||||||
|
static_configs:
|
||||||
|
- targets:
|
||||||
|
# - localhost:8888
|
||||||
|
processors:
|
||||||
|
batch:
|
||||||
|
send_batch_size: 1000
|
||||||
|
timeout: 10s
|
||||||
|
# Ref: https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/processor/resourcedetectionprocessor/README.md
|
||||||
|
resourcedetection:
|
||||||
|
detectors: [env, system] # Before system detector, include ec2 for AWS, gcp for GCP and azure for Azure.
|
||||||
|
# Using OTEL_RESOURCE_ATTRIBUTES envvar, env detector adds custom labels.
|
||||||
|
timeout: 2s
|
||||||
|
system:
|
||||||
|
hostname_sources: [os] # alternatively, use [dns,os] for setting FQDN as host.name and os as fallback
|
||||||
|
extensions:
|
||||||
|
health_check: {}
|
||||||
|
zpages: {}
|
||||||
|
exporters:
|
||||||
|
otlp:
|
||||||
|
endpoint: "ingest.{{REGION}}.signoz.cloud:443"
|
||||||
|
tls:
|
||||||
|
insecure: false
|
||||||
|
headers:
|
||||||
|
"signoz-access-token": "{{SIGNOZ_INGESTION_KEY}}"
|
||||||
|
logging:
|
||||||
|
verbosity: normal
|
||||||
|
service:
|
||||||
|
telemetry:
|
||||||
|
metrics:
|
||||||
|
address: 0.0.0.0:8888
|
||||||
|
extensions: [health_check, zpages]
|
||||||
|
pipelines:
|
||||||
|
metrics:
|
||||||
|
receivers: [otlp]
|
||||||
|
processors: [batch]
|
||||||
|
exporters: [otlp]
|
||||||
|
metrics/internal:
|
||||||
|
receivers: [prometheus, hostmetrics]
|
||||||
|
processors: [resourcedetection, batch]
|
||||||
|
exporters: [otlp]
|
||||||
|
traces:
|
||||||
|
receivers: [otlp]
|
||||||
|
processors: [batch]
|
||||||
|
exporters: [otlp]
|
||||||
|
logs:
|
||||||
|
receivers: [otlp]
|
||||||
|
processors: [batch]
|
||||||
|
exporters: [otlp]
|
||||||
|
```
|
||||||
|
|
||||||
|
|
@ -0,0 +1,116 @@
|
|||||||
|
After setting up the Otel collector agent, follow the steps below to instrumnet your Go Application
|
||||||
|
|
||||||
|
### Step 1: Install OpenTelemetry Dependencies
|
||||||
|
Dependencies related to OpenTelemetry exporter and SDK have to be installed first
|
||||||
|
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** Note that we are assuming you are using gin request router. If you are using other request routers, check out the [corresponding package](https://signoz.io/docs/instrumentation/golang/#request-routers).
|
||||||
|
|
||||||
|
### Step 2: Declare environment variables for configuring OpenTelemetry
|
||||||
|
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")
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Instrument your Go application
|
||||||
|
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.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 4: Initialise the tracer in `main.go`
|
||||||
|
Modify the main function to initialise the tracer in main.go. Initiate the tracer at the very beginning of our main function.
|
||||||
|
```bash
|
||||||
|
func main() {
|
||||||
|
cleanup := initTracer()
|
||||||
|
defer cleanup(context.Background())
|
||||||
|
|
||||||
|
......
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 5: Add the OpenTelemetry Gin middleware
|
||||||
|
Configure Gin to use the middleware by adding the following lines in `main.go`
|
||||||
|
```bash
|
||||||
|
import (
|
||||||
|
....
|
||||||
|
"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
......
|
||||||
|
r := gin.Default()
|
||||||
|
r.Use(otelgin.Middleware(serviceName))
|
||||||
|
......
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
|||||||
|
Once you are done intrumenting your Go Gin application, you can run it using the below commands
|
||||||
|
|
||||||
|
### Step 1: Run OTel Collector
|
||||||
|
Run this command inside the `otelcol-contrib` directory that you created in the install Otel Collector step
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./otelcol-contrib --config ./config.yaml &> otelcol-output.log & echo "$!" > otel-pid
|
||||||
|
```
|
||||||
|
### (Optional Step): View last 50 lines of `otelcol` logs
|
||||||
|
```bash
|
||||||
|
tail -f -n 50 otelcol-output.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### (Optional Step): Stop `otelcol`
|
||||||
|
```bash
|
||||||
|
kill "$(< otel-pid)"
|
||||||
|
```
|
||||||
|
### Step 2: Set environment variables and run your Go Gin application
|
||||||
|
```bash
|
||||||
|
SERVICE_NAME={{MYAPP}} INSECURE_MODE=true OTEL_EXPORTER_OTLP_ENDPOINT=localhost:4317 go run main.go
|
||||||
|
```
|
@ -0,0 +1,115 @@
|
|||||||
|
|
||||||
|
### Step 1: Install OpenTelemetry Dependencies
|
||||||
|
Dependencies related to OpenTelemetry exporter and SDK have to be installed first
|
||||||
|
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** Note that we are assuming you are using gin request router. If you are using other request routers, check out the [corresponding package](https://signoz.io/docs/instrumentation/golang/#request-routers).
|
||||||
|
|
||||||
|
### Step 2: Declare environment variables for configuring OpenTelemetry
|
||||||
|
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")
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Instrument your Go application
|
||||||
|
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.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 4: Initialise the tracer in `main.go`
|
||||||
|
Modify the main function to initialise the tracer in main.go. Initiate the tracer at the very beginning of our main function.
|
||||||
|
```bash
|
||||||
|
func main() {
|
||||||
|
cleanup := initTracer()
|
||||||
|
defer cleanup(context.Background())
|
||||||
|
|
||||||
|
......
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 5: Add the OpenTelemetry Gin middleware
|
||||||
|
Configure Gin to use the middleware by adding the following lines in `main.go`
|
||||||
|
```bash
|
||||||
|
import (
|
||||||
|
....
|
||||||
|
"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
......
|
||||||
|
r := gin.Default()
|
||||||
|
r.Use(otelgin.Middleware(serviceName))
|
||||||
|
......
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
|||||||
|
To run your Go Gin application, use the below command :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
SERVICE_NAME={{MYAPP}} INSECURE_MODE=false OTEL_EXPORTER_OTLP_HEADERS=signoz-access-token={{SIGNOZ_INGESTION_KEY}} OTEL_EXPORTER_OTLP_ENDPOINT=ingest.{{REGION}}.signoz.cloud:443 go run main.go
|
||||||
|
```
|
@ -0,0 +1,93 @@
|
|||||||
|
### Setup OpenTelemetry Binary as an agent
|
||||||
|
|
||||||
|
### Step 1: Download otel-collector tar.gz
|
||||||
|
```bash
|
||||||
|
wget https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v0.79.0/otelcol-contrib_0.79.0_linux_arm64.tar.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2: Extract otel-collector tar.gz to the `otelcol-contrib` folder
|
||||||
|
```bash
|
||||||
|
mkdir otelcol-contrib && tar xvzf otelcol-contrib_0.79.0_linux_arm64.tar.gz -C otelcol-contrib
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Create config.yaml in folder otelcol-contrib with the below content in it
|
||||||
|
```bash
|
||||||
|
receivers:
|
||||||
|
otlp:
|
||||||
|
protocols:
|
||||||
|
grpc:
|
||||||
|
endpoint: 0.0.0.0:4317
|
||||||
|
http:
|
||||||
|
endpoint: 0.0.0.0:4318
|
||||||
|
hostmetrics:
|
||||||
|
collection_interval: 60s
|
||||||
|
scrapers:
|
||||||
|
cpu: {}
|
||||||
|
disk: {}
|
||||||
|
load: {}
|
||||||
|
filesystem: {}
|
||||||
|
memory: {}
|
||||||
|
network: {}
|
||||||
|
paging: {}
|
||||||
|
process:
|
||||||
|
mute_process_name_error: true
|
||||||
|
mute_process_exe_error: true
|
||||||
|
mute_process_io_error: true
|
||||||
|
processes: {}
|
||||||
|
prometheus:
|
||||||
|
config:
|
||||||
|
global:
|
||||||
|
scrape_interval: 60s
|
||||||
|
scrape_configs:
|
||||||
|
- job_name: otel-collector-binary
|
||||||
|
static_configs:
|
||||||
|
- targets:
|
||||||
|
# - localhost:8888
|
||||||
|
processors:
|
||||||
|
batch:
|
||||||
|
send_batch_size: 1000
|
||||||
|
timeout: 10s
|
||||||
|
# Ref: https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/processor/resourcedetectionprocessor/README.md
|
||||||
|
resourcedetection:
|
||||||
|
detectors: [env, system] # Before system detector, include ec2 for AWS, gcp for GCP and azure for Azure.
|
||||||
|
# Using OTEL_RESOURCE_ATTRIBUTES envvar, env detector adds custom labels.
|
||||||
|
timeout: 2s
|
||||||
|
system:
|
||||||
|
hostname_sources: [os] # alternatively, use [dns,os] for setting FQDN as host.name and os as fallback
|
||||||
|
extensions:
|
||||||
|
health_check: {}
|
||||||
|
zpages: {}
|
||||||
|
exporters:
|
||||||
|
otlp:
|
||||||
|
endpoint: "ingest.{{REGION}}.signoz.cloud:443"
|
||||||
|
tls:
|
||||||
|
insecure: false
|
||||||
|
headers:
|
||||||
|
"signoz-access-token": "{{SIGNOZ_INGESTION_KEY}}"
|
||||||
|
logging:
|
||||||
|
verbosity: normal
|
||||||
|
service:
|
||||||
|
telemetry:
|
||||||
|
metrics:
|
||||||
|
address: 0.0.0.0:8888
|
||||||
|
extensions: [health_check, zpages]
|
||||||
|
pipelines:
|
||||||
|
metrics:
|
||||||
|
receivers: [otlp]
|
||||||
|
processors: [batch]
|
||||||
|
exporters: [otlp]
|
||||||
|
metrics/internal:
|
||||||
|
receivers: [prometheus, hostmetrics]
|
||||||
|
processors: [resourcedetection, batch]
|
||||||
|
exporters: [otlp]
|
||||||
|
traces:
|
||||||
|
receivers: [otlp]
|
||||||
|
processors: [batch]
|
||||||
|
exporters: [otlp]
|
||||||
|
logs:
|
||||||
|
receivers: [otlp]
|
||||||
|
processors: [batch]
|
||||||
|
exporters: [otlp]
|
||||||
|
```
|
||||||
|
|
||||||
|
|
@ -0,0 +1,116 @@
|
|||||||
|
After setting up the Otel collector agent, follow the steps below to instrumnet your Go Application
|
||||||
|
|
||||||
|
### Step 1: Install OpenTelemetry Dependencies
|
||||||
|
Dependencies related to OpenTelemetry exporter and SDK have to be installed first
|
||||||
|
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** Note that we are assuming you are using gin request router. If you are using other request routers, check out the [corresponding package](https://signoz.io/docs/instrumentation/golang/#request-routers).
|
||||||
|
|
||||||
|
### Step 2: Declare environment variables for configuring OpenTelemetry
|
||||||
|
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")
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Instrument your Go application
|
||||||
|
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.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 4: Initialise the tracer in `main.go`
|
||||||
|
Modify the main function to initialise the tracer in main.go. Initiate the tracer at the very beginning of our main function.
|
||||||
|
```bash
|
||||||
|
func main() {
|
||||||
|
cleanup := initTracer()
|
||||||
|
defer cleanup(context.Background())
|
||||||
|
|
||||||
|
......
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 5: Add the OpenTelemetry Gin middleware
|
||||||
|
Configure Gin to use the middleware by adding the following lines in `main.go`
|
||||||
|
```bash
|
||||||
|
import (
|
||||||
|
....
|
||||||
|
"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
......
|
||||||
|
r := gin.Default()
|
||||||
|
r.Use(otelgin.Middleware(serviceName))
|
||||||
|
......
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
|||||||
|
Once you are done intrumenting your Go Gin application, you can run it using the below commands
|
||||||
|
|
||||||
|
### Step 1: Run OTel Collector
|
||||||
|
Run this command inside the `otelcol-contrib` directory that you created in the install Otel Collector step
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./otelcol-contrib --config ./config.yaml &> otelcol-output.log & echo "$!" > otel-pid
|
||||||
|
```
|
||||||
|
### (Optional Step): View last 50 lines of `otelcol` logs
|
||||||
|
```bash
|
||||||
|
tail -f -n 50 otelcol-output.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### (Optional Step): Stop `otelcol`
|
||||||
|
```bash
|
||||||
|
kill "$(< otel-pid)"
|
||||||
|
```
|
||||||
|
### Step 2: Set environment variables and run your Go Gin application
|
||||||
|
```bash
|
||||||
|
SERVICE_NAME={{MYAPP}} INSECURE_MODE=true OTEL_EXPORTER_OTLP_ENDPOINT=localhost:4317 go run main.go
|
||||||
|
```
|
@ -0,0 +1,115 @@
|
|||||||
|
|
||||||
|
### Step 1: Install OpenTelemetry Dependencies
|
||||||
|
Dependencies related to OpenTelemetry exporter and SDK have to be installed first
|
||||||
|
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** Note that we are assuming you are using gin request router. If you are using other request routers, check out the [corresponding package](https://signoz.io/docs/instrumentation/golang/#request-routers).
|
||||||
|
|
||||||
|
### Step 2: Declare environment variables for configuring OpenTelemetry
|
||||||
|
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")
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Instrument your Go application
|
||||||
|
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.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 4: Initialise the tracer in `main.go`
|
||||||
|
Modify the main function to initialise the tracer in main.go. Initiate the tracer at the very beginning of our main function.
|
||||||
|
```bash
|
||||||
|
func main() {
|
||||||
|
cleanup := initTracer()
|
||||||
|
defer cleanup(context.Background())
|
||||||
|
|
||||||
|
......
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 5: Add the OpenTelemetry Gin middleware
|
||||||
|
Configure Gin to use the middleware by adding the following lines in `main.go`
|
||||||
|
```bash
|
||||||
|
import (
|
||||||
|
....
|
||||||
|
"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
......
|
||||||
|
r := gin.Default()
|
||||||
|
r.Use(otelgin.Middleware(serviceName))
|
||||||
|
......
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
|||||||
|
To run your Go Gin application, use the below command :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
SERVICE_NAME={{MYAPP}} INSECURE_MODE=false OTEL_EXPORTER_OTLP_HEADERS=signoz-access-token={{SIGNOZ_INGESTION_KEY}} OTEL_EXPORTER_OTLP_ENDPOINT=ingest.{{REGION}}.signoz.cloud:443 go run main.go
|
||||||
|
```
|
@ -0,0 +1,93 @@
|
|||||||
|
### Setup OpenTelemetry Binary as an agent
|
||||||
|
|
||||||
|
### Step 1: Download otel-collector tar.gz
|
||||||
|
```bash
|
||||||
|
wget https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v0.79.0/otelcol-contrib_0.79.0_darwin_amd64.tar.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2: Extract otel-collector tar.gz to the `otelcol-contrib` folder
|
||||||
|
```bash
|
||||||
|
mkdir otelcol-contrib && tar xvzf otelcol-contrib_0.79.0_darwin_amd64.tar.gz -C otelcol-contrib
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Create config.yaml in folder otelcol-contrib with the below content in it
|
||||||
|
```bash
|
||||||
|
receivers:
|
||||||
|
otlp:
|
||||||
|
protocols:
|
||||||
|
grpc:
|
||||||
|
endpoint: 0.0.0.0:4317
|
||||||
|
http:
|
||||||
|
endpoint: 0.0.0.0:4318
|
||||||
|
hostmetrics:
|
||||||
|
collection_interval: 60s
|
||||||
|
scrapers:
|
||||||
|
cpu: {}
|
||||||
|
disk: {}
|
||||||
|
load: {}
|
||||||
|
filesystem: {}
|
||||||
|
memory: {}
|
||||||
|
network: {}
|
||||||
|
paging: {}
|
||||||
|
process:
|
||||||
|
mute_process_name_error: true
|
||||||
|
mute_process_exe_error: true
|
||||||
|
mute_process_io_error: true
|
||||||
|
processes: {}
|
||||||
|
prometheus:
|
||||||
|
config:
|
||||||
|
global:
|
||||||
|
scrape_interval: 60s
|
||||||
|
scrape_configs:
|
||||||
|
- job_name: otel-collector-binary
|
||||||
|
static_configs:
|
||||||
|
- targets:
|
||||||
|
# - localhost:8888
|
||||||
|
processors:
|
||||||
|
batch:
|
||||||
|
send_batch_size: 1000
|
||||||
|
timeout: 10s
|
||||||
|
# Ref: https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/processor/resourcedetectionprocessor/README.md
|
||||||
|
resourcedetection:
|
||||||
|
detectors: [env, system] # Before system detector, include ec2 for AWS, gcp for GCP and azure for Azure.
|
||||||
|
# Using OTEL_RESOURCE_ATTRIBUTES envvar, env detector adds custom labels.
|
||||||
|
timeout: 2s
|
||||||
|
system:
|
||||||
|
hostname_sources: [os] # alternatively, use [dns,os] for setting FQDN as host.name and os as fallback
|
||||||
|
extensions:
|
||||||
|
health_check: {}
|
||||||
|
zpages: {}
|
||||||
|
exporters:
|
||||||
|
otlp:
|
||||||
|
endpoint: "ingest.{{REGION}}.signoz.cloud:443"
|
||||||
|
tls:
|
||||||
|
insecure: false
|
||||||
|
headers:
|
||||||
|
"signoz-access-token": "{{SIGNOZ_INGESTION_KEY}}"
|
||||||
|
logging:
|
||||||
|
verbosity: normal
|
||||||
|
service:
|
||||||
|
telemetry:
|
||||||
|
metrics:
|
||||||
|
address: 0.0.0.0:8888
|
||||||
|
extensions: [health_check, zpages]
|
||||||
|
pipelines:
|
||||||
|
metrics:
|
||||||
|
receivers: [otlp]
|
||||||
|
processors: [batch]
|
||||||
|
exporters: [otlp]
|
||||||
|
metrics/internal:
|
||||||
|
receivers: [prometheus, hostmetrics]
|
||||||
|
processors: [resourcedetection, batch]
|
||||||
|
exporters: [otlp]
|
||||||
|
traces:
|
||||||
|
receivers: [otlp]
|
||||||
|
processors: [batch]
|
||||||
|
exporters: [otlp]
|
||||||
|
logs:
|
||||||
|
receivers: [otlp]
|
||||||
|
processors: [batch]
|
||||||
|
exporters: [otlp]
|
||||||
|
```
|
||||||
|
|
||||||
|
|
@ -0,0 +1,116 @@
|
|||||||
|
After setting up the Otel collector agent, follow the steps below to instrumnet your Go Application
|
||||||
|
|
||||||
|
### Step 1: Install OpenTelemetry Dependencies
|
||||||
|
Dependencies related to OpenTelemetry exporter and SDK have to be installed first
|
||||||
|
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** Note that we are assuming you are using gin request router. If you are using other request routers, check out the [corresponding package](https://signoz.io/docs/instrumentation/golang/#request-routers).
|
||||||
|
|
||||||
|
### Step 2: Declare environment variables for configuring OpenTelemetry
|
||||||
|
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")
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Instrument your Go application
|
||||||
|
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.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 4: Initialise the tracer in `main.go`
|
||||||
|
Modify the main function to initialise the tracer in main.go. Initiate the tracer at the very beginning of our main function.
|
||||||
|
```bash
|
||||||
|
func main() {
|
||||||
|
cleanup := initTracer()
|
||||||
|
defer cleanup(context.Background())
|
||||||
|
|
||||||
|
......
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 5: Add the OpenTelemetry Gin middleware
|
||||||
|
Configure Gin to use the middleware by adding the following lines in `main.go`
|
||||||
|
```bash
|
||||||
|
import (
|
||||||
|
....
|
||||||
|
"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
......
|
||||||
|
r := gin.Default()
|
||||||
|
r.Use(otelgin.Middleware(serviceName))
|
||||||
|
......
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
|||||||
|
Once you are done intrumenting your Go Gin application, you can run it using the below commands
|
||||||
|
|
||||||
|
### Step 1: Run OTel Collector
|
||||||
|
Run this command inside the `otelcol-contrib` directory that you created in the install Otel Collector step
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./otelcol-contrib --config ./config.yaml &> otelcol-output.log & echo "$!" > otel-pid
|
||||||
|
```
|
||||||
|
### (Optional Step): View last 50 lines of `otelcol` logs
|
||||||
|
```bash
|
||||||
|
tail -f -n 50 otelcol-output.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### (Optional Step): Stop `otelcol`
|
||||||
|
```bash
|
||||||
|
kill "$(< otel-pid)"
|
||||||
|
```
|
||||||
|
### Step 2: Set environment variables and run your Go Gin application
|
||||||
|
```bash
|
||||||
|
SERVICE_NAME={{MYAPP}} INSECURE_MODE=true OTEL_EXPORTER_OTLP_ENDPOINT=localhost:4317 go run main.go
|
||||||
|
```
|
@ -0,0 +1,115 @@
|
|||||||
|
|
||||||
|
### Step 1: Install OpenTelemetry Dependencies
|
||||||
|
Dependencies related to OpenTelemetry exporter and SDK have to be installed first
|
||||||
|
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** Note that we are assuming you are using gin request router. If you are using other request routers, check out the [corresponding package](https://signoz.io/docs/instrumentation/golang/#request-routers).
|
||||||
|
|
||||||
|
### Step 2: Declare environment variables for configuring OpenTelemetry
|
||||||
|
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")
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Instrument your Go application
|
||||||
|
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.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 4: Initialise the tracer in `main.go`
|
||||||
|
Modify the main function to initialise the tracer in main.go. Initiate the tracer at the very beginning of our main function.
|
||||||
|
```bash
|
||||||
|
func main() {
|
||||||
|
cleanup := initTracer()
|
||||||
|
defer cleanup(context.Background())
|
||||||
|
|
||||||
|
......
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 5: Add the OpenTelemetry Gin middleware
|
||||||
|
Configure Gin to use the middleware by adding the following lines in `main.go`
|
||||||
|
```bash
|
||||||
|
import (
|
||||||
|
....
|
||||||
|
"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
......
|
||||||
|
r := gin.Default()
|
||||||
|
r.Use(otelgin.Middleware(serviceName))
|
||||||
|
......
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
|||||||
|
To run your Go Gin application, use the below command :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
SERVICE_NAME={{MYAPP}} INSECURE_MODE=false OTEL_EXPORTER_OTLP_HEADERS=signoz-access-token={{SIGNOZ_INGESTION_KEY}} OTEL_EXPORTER_OTLP_ENDPOINT=ingest.{{REGION}}.signoz.cloud:443 go run main.go
|
||||||
|
```
|
@ -0,0 +1,92 @@
|
|||||||
|
### Setup OpenTelemetry Binary as an agent
|
||||||
|
|
||||||
|
### Step 1: Download otel-collector tar.gz
|
||||||
|
```bash
|
||||||
|
wget https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v0.79.0/otelcol-contrib_0.79.0_darwin_arm64.tar.gz
|
||||||
|
|
||||||
|
### Step 2: Extract otel-collector tar.gz to the `otelcol-contrib` folder
|
||||||
|
```bash
|
||||||
|
mkdir otelcol-contrib && tar xvzf otelcol-contrib_0.79.0_darwin_arm64.tar.gz -C otelcol-contrib
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Create config.yaml in folder otelcol-contrib with the below content in it
|
||||||
|
```bash
|
||||||
|
receivers:
|
||||||
|
otlp:
|
||||||
|
protocols:
|
||||||
|
grpc:
|
||||||
|
endpoint: 0.0.0.0:4317
|
||||||
|
http:
|
||||||
|
endpoint: 0.0.0.0:4318
|
||||||
|
hostmetrics:
|
||||||
|
collection_interval: 60s
|
||||||
|
scrapers:
|
||||||
|
cpu: {}
|
||||||
|
disk: {}
|
||||||
|
load: {}
|
||||||
|
filesystem: {}
|
||||||
|
memory: {}
|
||||||
|
network: {}
|
||||||
|
paging: {}
|
||||||
|
process:
|
||||||
|
mute_process_name_error: true
|
||||||
|
mute_process_exe_error: true
|
||||||
|
mute_process_io_error: true
|
||||||
|
processes: {}
|
||||||
|
prometheus:
|
||||||
|
config:
|
||||||
|
global:
|
||||||
|
scrape_interval: 60s
|
||||||
|
scrape_configs:
|
||||||
|
- job_name: otel-collector-binary
|
||||||
|
static_configs:
|
||||||
|
- targets:
|
||||||
|
# - localhost:8888
|
||||||
|
processors:
|
||||||
|
batch:
|
||||||
|
send_batch_size: 1000
|
||||||
|
timeout: 10s
|
||||||
|
# Ref: https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/processor/resourcedetectionprocessor/README.md
|
||||||
|
resourcedetection:
|
||||||
|
detectors: [env, system] # Before system detector, include ec2 for AWS, gcp for GCP and azure for Azure.
|
||||||
|
# Using OTEL_RESOURCE_ATTRIBUTES envvar, env detector adds custom labels.
|
||||||
|
timeout: 2s
|
||||||
|
system:
|
||||||
|
hostname_sources: [os] # alternatively, use [dns,os] for setting FQDN as host.name and os as fallback
|
||||||
|
extensions:
|
||||||
|
health_check: {}
|
||||||
|
zpages: {}
|
||||||
|
exporters:
|
||||||
|
otlp:
|
||||||
|
endpoint: "ingest.{{REGION}}.signoz.cloud:443"
|
||||||
|
tls:
|
||||||
|
insecure: false
|
||||||
|
headers:
|
||||||
|
"signoz-access-token": "{{SIGNOZ_INGESTION_KEY}}"
|
||||||
|
logging:
|
||||||
|
verbosity: normal
|
||||||
|
service:
|
||||||
|
telemetry:
|
||||||
|
metrics:
|
||||||
|
address: 0.0.0.0:8888
|
||||||
|
extensions: [health_check, zpages]
|
||||||
|
pipelines:
|
||||||
|
metrics:
|
||||||
|
receivers: [otlp]
|
||||||
|
processors: [batch]
|
||||||
|
exporters: [otlp]
|
||||||
|
metrics/internal:
|
||||||
|
receivers: [prometheus, hostmetrics]
|
||||||
|
processors: [resourcedetection, batch]
|
||||||
|
exporters: [otlp]
|
||||||
|
traces:
|
||||||
|
receivers: [otlp]
|
||||||
|
processors: [batch]
|
||||||
|
exporters: [otlp]
|
||||||
|
logs:
|
||||||
|
receivers: [otlp]
|
||||||
|
processors: [batch]
|
||||||
|
exporters: [otlp]
|
||||||
|
```
|
||||||
|
|
||||||
|
|
@ -0,0 +1,116 @@
|
|||||||
|
After setting up the Otel collector agent, follow the steps below to instrumnet your Go Application
|
||||||
|
|
||||||
|
### Step 1: Install OpenTelemetry Dependencies
|
||||||
|
Dependencies related to OpenTelemetry exporter and SDK have to be installed first
|
||||||
|
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** Note that we are assuming you are using gin request router. If you are using other request routers, check out the [corresponding package](https://signoz.io/docs/instrumentation/golang/#request-routers).
|
||||||
|
|
||||||
|
### Step 2: Declare environment variables for configuring OpenTelemetry
|
||||||
|
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")
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Instrument your Go application
|
||||||
|
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.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 4: Initialise the tracer in `main.go`
|
||||||
|
Modify the main function to initialise the tracer in main.go. Initiate the tracer at the very beginning of our main function.
|
||||||
|
```bash
|
||||||
|
func main() {
|
||||||
|
cleanup := initTracer()
|
||||||
|
defer cleanup(context.Background())
|
||||||
|
|
||||||
|
......
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 5: Add the OpenTelemetry Gin middleware
|
||||||
|
Configure Gin to use the middleware by adding the following lines in `main.go`
|
||||||
|
```bash
|
||||||
|
import (
|
||||||
|
....
|
||||||
|
"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
......
|
||||||
|
r := gin.Default()
|
||||||
|
r.Use(otelgin.Middleware(serviceName))
|
||||||
|
......
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
|||||||
|
Once you are done intrumenting your Go Gin application, you can run it using the below commands
|
||||||
|
|
||||||
|
### Step 1: Run OTel Collector
|
||||||
|
Run this command inside the `otelcol-contrib` directory that you created in the install Otel Collector step
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./otelcol-contrib --config ./config.yaml &> otelcol-output.log & echo "$!" > otel-pid
|
||||||
|
```
|
||||||
|
### (Optional Step): View last 50 lines of `otelcol` logs
|
||||||
|
```bash
|
||||||
|
tail -f -n 50 otelcol-output.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### (Optional Step): Stop `otelcol`
|
||||||
|
```bash
|
||||||
|
kill "$(< otel-pid)"
|
||||||
|
```
|
||||||
|
### Step 2: Set environment variables and run your Go Gin application
|
||||||
|
```bash
|
||||||
|
SERVICE_NAME={{MYAPP}} INSECURE_MODE=true OTEL_EXPORTER_OTLP_ENDPOINT=localhost:4317 go run main.go
|
||||||
|
```
|
@ -0,0 +1,21 @@
|
|||||||
|
### Install otel-collector in your Kubernetes infra
|
||||||
|
|
||||||
|
Add the SigNoz Helm Chart repository
|
||||||
|
```bash
|
||||||
|
helm repo add signoz https://charts.signoz.io
|
||||||
|
```
|
||||||
|
|
||||||
|
If the chart is already present, update the chart to the latest using:
|
||||||
|
```bash
|
||||||
|
helm repo update
|
||||||
|
```
|
||||||
|
|
||||||
|
Install the Kubernetes Infrastructure chart provided by SigNoz
|
||||||
|
```bash
|
||||||
|
helm install my-release signoz/k8s-infra \
|
||||||
|
--set otelCollectorEndpoint=ingest.{{REGION}}.signoz.cloud:443 \
|
||||||
|
--set otelInsecure=false \
|
||||||
|
--set signozApiKey={{SIGNOZ_INGESTION_KEY}} \
|
||||||
|
--set global.clusterName=<CLUSTER_NAME>
|
||||||
|
```
|
||||||
|
- Replace `<CLUSTER_NAME>` with the name of the Kubernetes cluster or a unique identifier of the cluster.
|
@ -0,0 +1,10 @@
|
|||||||
|
After setting up the Otel collector agent, follow the steps below to instrumnet your JavaScript Application
|
||||||
|
|
||||||
|
#### Requirements
|
||||||
|
- Java 8 or higher
|
||||||
|
|
||||||
|
### Download otel java binary
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
|
||||||
|
```
|
@ -0,0 +1,14 @@
|
|||||||
|
### Open `standalone.conf` Configuration File
|
||||||
|
```bash
|
||||||
|
vim /opt/jboss-eap-7.1/bin/standalone.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
### Update `JAVA_OPTS` environment variable
|
||||||
|
```bash
|
||||||
|
JAVA_OPTS="-javaagent:/<path>/opentelemetry-javaagent.jar"
|
||||||
|
```
|
||||||
|
|
||||||
|
<path> - update it to the path where you downloaded the Java JAR agent in previous step
|
||||||
|
|
||||||
|
**Note:**
|
||||||
|
- In case you're dockerising your application, make sure to dockerise it along with OpenTelemetry instrumentation done in previous step.
|
@ -0,0 +1,8 @@
|
|||||||
|
#### Requirements
|
||||||
|
- Java 8 or higher
|
||||||
|
|
||||||
|
### Download otel java binary
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
|
||||||
|
```
|
@ -0,0 +1,23 @@
|
|||||||
|
### Open `standalone.conf` Configuration File
|
||||||
|
```bash
|
||||||
|
vim /opt/jboss-eap-7.1/bin/standalone.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
### 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={{MYAPP}}""
|
||||||
|
```
|
||||||
|
|
||||||
|
<path> - update it to the path where you downloaded the Java JAR agent in previous step
|
||||||
|
|
||||||
|
|
||||||
|
### (Optional step) 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 &
|
||||||
|
|
||||||
|
```
|
@ -0,0 +1,93 @@
|
|||||||
|
### Setup OpenTelemetry Binary as an agent
|
||||||
|
|
||||||
|
### Step 1: Download otel-collector tar.gz
|
||||||
|
```bash
|
||||||
|
wget https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v0.79.0/otelcol-contrib_0.79.0_linux_amd64.tar.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2: Extract otel-collector tar.gz to the `otelcol-contrib` folder
|
||||||
|
```bash
|
||||||
|
mkdir otelcol-contrib && tar xvzf otelcol-contrib_0.79.0_linux_amd64.tar.gz -C otelcol-contrib
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Create config.yaml in folder otelcol-contrib with the below content in it
|
||||||
|
```bash
|
||||||
|
receivers:
|
||||||
|
otlp:
|
||||||
|
protocols:
|
||||||
|
grpc:
|
||||||
|
endpoint: 0.0.0.0:4317
|
||||||
|
http:
|
||||||
|
endpoint: 0.0.0.0:4318
|
||||||
|
hostmetrics:
|
||||||
|
collection_interval: 60s
|
||||||
|
scrapers:
|
||||||
|
cpu: {}
|
||||||
|
disk: {}
|
||||||
|
load: {}
|
||||||
|
filesystem: {}
|
||||||
|
memory: {}
|
||||||
|
network: {}
|
||||||
|
paging: {}
|
||||||
|
process:
|
||||||
|
mute_process_name_error: true
|
||||||
|
mute_process_exe_error: true
|
||||||
|
mute_process_io_error: true
|
||||||
|
processes: {}
|
||||||
|
prometheus:
|
||||||
|
config:
|
||||||
|
global:
|
||||||
|
scrape_interval: 60s
|
||||||
|
scrape_configs:
|
||||||
|
- job_name: otel-collector-binary
|
||||||
|
static_configs:
|
||||||
|
- targets:
|
||||||
|
# - localhost:8888
|
||||||
|
processors:
|
||||||
|
batch:
|
||||||
|
send_batch_size: 1000
|
||||||
|
timeout: 10s
|
||||||
|
# Ref: https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/processor/resourcedetectionprocessor/README.md
|
||||||
|
resourcedetection:
|
||||||
|
detectors: [env, system] # Before system detector, include ec2 for AWS, gcp for GCP and azure for Azure.
|
||||||
|
# Using OTEL_RESOURCE_ATTRIBUTES envvar, env detector adds custom labels.
|
||||||
|
timeout: 2s
|
||||||
|
system:
|
||||||
|
hostname_sources: [os] # alternatively, use [dns,os] for setting FQDN as host.name and os as fallback
|
||||||
|
extensions:
|
||||||
|
health_check: {}
|
||||||
|
zpages: {}
|
||||||
|
exporters:
|
||||||
|
otlp:
|
||||||
|
endpoint: "ingest.{{REGION}}.signoz.cloud:443"
|
||||||
|
tls:
|
||||||
|
insecure: false
|
||||||
|
headers:
|
||||||
|
"signoz-access-token": "{{SIGNOZ_INGESTION_KEY}}"
|
||||||
|
logging:
|
||||||
|
verbosity: normal
|
||||||
|
service:
|
||||||
|
telemetry:
|
||||||
|
metrics:
|
||||||
|
address: 0.0.0.0:8888
|
||||||
|
extensions: [health_check, zpages]
|
||||||
|
pipelines:
|
||||||
|
metrics:
|
||||||
|
receivers: [otlp]
|
||||||
|
processors: [batch]
|
||||||
|
exporters: [otlp]
|
||||||
|
metrics/internal:
|
||||||
|
receivers: [prometheus, hostmetrics]
|
||||||
|
processors: [resourcedetection, batch]
|
||||||
|
exporters: [otlp]
|
||||||
|
traces:
|
||||||
|
receivers: [otlp]
|
||||||
|
processors: [batch]
|
||||||
|
exporters: [otlp]
|
||||||
|
logs:
|
||||||
|
receivers: [otlp]
|
||||||
|
processors: [batch]
|
||||||
|
exporters: [otlp]
|
||||||
|
```
|
||||||
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
|||||||
|
After setting up the Otel collector agent, follow the steps below to instrumnet your JavaScript Application
|
||||||
|
|
||||||
|
#### Requirements
|
||||||
|
- Java 8 or higher
|
||||||
|
|
||||||
|
### Download otel java binary
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
|
||||||
|
```
|
@ -0,0 +1,30 @@
|
|||||||
|
Once you are done intrumenting your Java application, you can run it using the below commands
|
||||||
|
|
||||||
|
### Step 1: Run OTel Collector
|
||||||
|
Run this command inside the `otelcol-contrib` directory that you created in the install Otel Collector step
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./otelcol-contrib --config ./config.yaml &> otelcol-output.log & echo "$!" > otel-pid
|
||||||
|
```
|
||||||
|
### (Optional Step): View last 50 lines of `otelcol` logs
|
||||||
|
```bash
|
||||||
|
tail -f -n 50 otelcol-output.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### (Optional Step): Stop `otelcol`
|
||||||
|
```bash
|
||||||
|
kill "$(< otel-pid)"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2: Open `standalone.conf` Configuration File
|
||||||
|
```bash
|
||||||
|
vim /opt/jboss-eap-7.1/bin/standalone.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Update `JAVA_OPTS` environment variable
|
||||||
|
```bash
|
||||||
|
JAVA_OPTS="-javaagent:/<path>/opentelemetry-javaagent.jar"
|
||||||
|
```
|
||||||
|
|
||||||
|
<path> - update it to the path where you downloaded the Java JAR agent in previous step
|
||||||
|
|
@ -0,0 +1,8 @@
|
|||||||
|
#### Requirements
|
||||||
|
- Java 8 or higher
|
||||||
|
|
||||||
|
### Download otel java binary
|
||||||
|
|
||||||
|
```bash
|
||||||
|
wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
|
||||||
|
```
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user