mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-07-23 20:24:30 +08:00
commit
93a11b2031
@ -146,7 +146,7 @@ services:
|
||||
condition: on-failure
|
||||
|
||||
query-service:
|
||||
image: signoz/query-service:0.34.0
|
||||
image: signoz/query-service:0.34.1
|
||||
command:
|
||||
[
|
||||
"-config=/root/config/prometheus.yml",
|
||||
@ -186,7 +186,7 @@ services:
|
||||
<<: *db-depend
|
||||
|
||||
frontend:
|
||||
image: signoz/frontend:0.34.0
|
||||
image: signoz/frontend:0.34.1
|
||||
deploy:
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
@ -199,7 +199,7 @@ services:
|
||||
- ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf
|
||||
|
||||
otel-collector:
|
||||
image: signoz/signoz-otel-collector:0.88.0
|
||||
image: signoz/signoz-otel-collector:0.88.1
|
||||
command:
|
||||
[
|
||||
"--config=/etc/otel-collector-config.yaml",
|
||||
@ -237,7 +237,7 @@ services:
|
||||
- query-service
|
||||
|
||||
otel-collector-migrator:
|
||||
image: signoz/signoz-schema-migrator:0.88.0
|
||||
image: signoz/signoz-schema-migrator:0.88.1
|
||||
deploy:
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
@ -250,7 +250,7 @@ services:
|
||||
# - clickhouse-3
|
||||
|
||||
otel-collector-metrics:
|
||||
image: signoz/signoz-otel-collector:0.88.0
|
||||
image: signoz/signoz-otel-collector:0.88.1
|
||||
command:
|
||||
[
|
||||
"--config=/etc/otel-collector-metrics-config.yaml",
|
||||
|
@ -66,7 +66,7 @@ services:
|
||||
- --storage.path=/data
|
||||
|
||||
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
|
||||
command:
|
||||
- "--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`
|
||||
otel-collector:
|
||||
container_name: signoz-otel-collector
|
||||
image: signoz/signoz-otel-collector:0.88.0
|
||||
image: signoz/signoz-otel-collector:0.88.1
|
||||
command:
|
||||
[
|
||||
"--config=/etc/otel-collector-config.yaml",
|
||||
@ -118,7 +118,7 @@ services:
|
||||
|
||||
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:
|
||||
[
|
||||
"--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`
|
||||
|
||||
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
|
||||
command:
|
||||
[
|
||||
@ -203,7 +203,7 @@ services:
|
||||
<<: *db-depend
|
||||
|
||||
frontend:
|
||||
image: signoz/frontend:${DOCKER_TAG:-0.34.0}
|
||||
image: signoz/frontend:${DOCKER_TAG:-0.34.1}
|
||||
container_name: signoz-frontend
|
||||
restart: on-failure
|
||||
depends_on:
|
||||
@ -215,7 +215,7 @@ services:
|
||||
- ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf
|
||||
|
||||
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
|
||||
command:
|
||||
- "--dsn=tcp://clickhouse:9000"
|
||||
@ -229,7 +229,7 @@ services:
|
||||
|
||||
|
||||
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
|
||||
command:
|
||||
[
|
||||
@ -269,7 +269,7 @@ services:
|
||||
condition: service_healthy
|
||||
|
||||
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
|
||||
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",
|
||||
"reorder": "Reorder",
|
||||
"cancel": "Cancel",
|
||||
"learn_more": "Learn more about pipelines",
|
||||
"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.",
|
||||
"delete_pipeline": "Do you want to delete pipeline",
|
||||
|
@ -7,6 +7,7 @@ import { FeatureKeys } from 'constants/features';
|
||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import ROUTES from 'constants/routes';
|
||||
import AppLayout from 'container/AppLayout';
|
||||
import useAnalytics from 'hooks/analytics/useAnalytics';
|
||||
import { useThemeConfig } from 'hooks/useDarkMode';
|
||||
import useGetFeatureFlag from 'hooks/useGetFeatureFlag';
|
||||
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 AppReducer, { User } from 'types/reducer/app';
|
||||
import { extractDomain, isCloudUser, isEECloudUser } from 'utils/app';
|
||||
import { trackPageView } from 'utils/segmentAnalytics';
|
||||
|
||||
import PrivateRoute from './Private';
|
||||
import defaultRoutes, { AppRoutes, SUPPORT_ROUTE } from './routes';
|
||||
@ -41,6 +41,8 @@ function App(): JSX.Element {
|
||||
|
||||
const dispatch = useDispatch<Dispatch<AppActions>>();
|
||||
|
||||
const { trackPageView } = useAnalytics();
|
||||
|
||||
const { hostname, pathname } = window.location;
|
||||
|
||||
const isCloudUserVal = isCloudUser();
|
||||
@ -156,6 +158,7 @@ function App(): JSX.Element {
|
||||
|
||||
useEffect(() => {
|
||||
trackPageView(pathname);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [pathname]);
|
||||
|
||||
return (
|
||||
|
@ -220,7 +220,11 @@ function ExplorerCard({
|
||||
open={isOpen}
|
||||
onOpenChange={handleOpenChange}
|
||||
>
|
||||
<Button type={saveButtonType} icon={saveButtonIcon}>
|
||||
<Button
|
||||
type={saveButtonType}
|
||||
icon={saveButtonIcon}
|
||||
data-testid="traces-save-view-action"
|
||||
>
|
||||
{isQueryUpdated
|
||||
? SaveButtonText.SAVE_AS_NEW_VIEW
|
||||
: SaveButtonText.SAVE_VIEW}
|
||||
|
@ -64,7 +64,12 @@ function SaveViewWithName({
|
||||
>
|
||||
<Input placeholder="Enter Name" />
|
||||
</Form.Item>
|
||||
<SaveButton htmlType="submit" type="primary" loading={isLoading}>
|
||||
<SaveButton
|
||||
htmlType="submit"
|
||||
type="primary"
|
||||
loading={isLoading}
|
||||
data-testid="save-view-name-action-button"
|
||||
>
|
||||
Save
|
||||
</SaveButton>
|
||||
</Form>
|
||||
|
@ -1,6 +1,8 @@
|
||||
.code-snippet-container {
|
||||
position: relative;
|
||||
background-color: rgb(43, 43, 43);
|
||||
// background-color: rgb(43, 43, 43);
|
||||
background-color: #111a2c;
|
||||
border-color: #111a2c;
|
||||
}
|
||||
|
||||
.code-copy-btn {
|
||||
|
@ -3,6 +3,7 @@ import './uplot.scss';
|
||||
|
||||
import { Typography } from 'antd';
|
||||
import { ToggleGraphProps } from 'components/Graph/types';
|
||||
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
|
||||
import {
|
||||
forwardRef,
|
||||
memo,
|
||||
@ -11,6 +12,7 @@ import {
|
||||
useImperativeHandle,
|
||||
useRef,
|
||||
} from 'react';
|
||||
import { ErrorBoundary } from 'react-error-boundary';
|
||||
import UPlot from 'uplot';
|
||||
|
||||
import { dataMatch, optionsUpdateState } from './utils';
|
||||
@ -119,13 +121,15 @@ const Uplot = forwardRef<ToggleGraphProps | undefined, UplotProps>(
|
||||
}, [data, resetScales, create]);
|
||||
|
||||
return (
|
||||
<div className="uplot-graph-container" ref={targetRef}>
|
||||
{data && data[0] && data[0]?.length === 0 ? (
|
||||
<div className="not-found">
|
||||
<Typography>No Data</Typography>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<ErrorBoundary FallbackComponent={ErrorBoundaryFallback}>
|
||||
<div className="uplot-graph-container" ref={targetRef}>
|
||||
{data && data[0] && data[0]?.length === 0 ? (
|
||||
<div className="not-found">
|
||||
<Typography>No Data</Typography>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</ErrorBoundary>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -5,7 +5,7 @@ export const Layout = styled(LayoutComponent)`
|
||||
&&& {
|
||||
display: flex;
|
||||
position: relative;
|
||||
min-height: calc(100vh - 4rem);
|
||||
min-height: calc(100vh - 8rem);
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import getUsage from 'api/billing/getUsage';
|
||||
import manageCreditCardApi from 'api/billing/manage';
|
||||
import { SOMETHING_WENT_WRONG } from 'constants/api';
|
||||
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
||||
import useAnalytics from 'hooks/analytics/useAnalytics';
|
||||
import useAxiosError from 'hooks/useAxiosError';
|
||||
import useLicense from 'hooks/useLicense';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
@ -109,9 +110,11 @@ export default function BillingContainer(): JSX.Element {
|
||||
const [data, setData] = useState<any[]>([]);
|
||||
const billCurrency = '$';
|
||||
|
||||
const { trackEvent } = useAnalytics();
|
||||
|
||||
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 handleError = useAxiosError();
|
||||
@ -301,18 +304,29 @@ export default function BillingContainer(): JSX.Element {
|
||||
|
||||
const handleBilling = useCallback(async () => {
|
||||
if (isFreeTrial && !licensesData?.payload?.trialConvertedToSubscription) {
|
||||
trackEvent('Billing : Upgrade Plan', {
|
||||
user,
|
||||
org,
|
||||
});
|
||||
|
||||
updateCreditCard({
|
||||
licenseKey: activeLicense?.key || '',
|
||||
successURL: window.location.href,
|
||||
cancelURL: window.location.href,
|
||||
});
|
||||
} else {
|
||||
trackEvent('Billing : Manage Billing', {
|
||||
user,
|
||||
org,
|
||||
});
|
||||
|
||||
manageCreditCard({
|
||||
licenseKey: activeLicense?.key || '',
|
||||
successURL: window.location.href,
|
||||
cancelURL: window.location.href,
|
||||
});
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
activeLicense?.key,
|
||||
isFreeTrial,
|
||||
@ -432,7 +446,12 @@ export default function BillingContainer(): JSX.Element {
|
||||
</Typography.Text>
|
||||
</Col>
|
||||
<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
|
||||
</Button>
|
||||
</Col>
|
||||
|
@ -7,8 +7,8 @@ import { Time } from 'container/TopNav/DateTimeSelection/config';
|
||||
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import { useResizeObserver } from 'hooks/useDimensions';
|
||||
import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartData';
|
||||
import { getUPlotChartData } from 'lib/uPlotLib/utils/getChartData';
|
||||
import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartOptions';
|
||||
import { getUPlotChartData } from 'lib/uPlotLib/utils/getUplotChartData';
|
||||
import { useMemo, useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
@ -15,8 +15,8 @@ import { useStepInterval } from 'hooks/queryBuilder/useStepInterval';
|
||||
import { useChartMutable } from 'hooks/useChartMutable';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariables';
|
||||
import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartData';
|
||||
import { getUPlotChartData } from 'lib/uPlotLib/utils/getChartData';
|
||||
import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartOptions';
|
||||
import { getUPlotChartData } from 'lib/uPlotLib/utils/getUplotChartData';
|
||||
import { useDashboard } from 'providers/Dashboard/Dashboard';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
@ -5,8 +5,8 @@ import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import { useResizeObserver } from 'hooks/useDimensions';
|
||||
import { useIntersectionObserver } from 'hooks/useIntersectionObserver';
|
||||
import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariables';
|
||||
import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartData';
|
||||
import { getUPlotChartData } from 'lib/uPlotLib/utils/getChartData';
|
||||
import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartOptions';
|
||||
import { getUPlotChartData } from 'lib/uPlotLib/utils/getUplotChartData';
|
||||
import isEmpty from 'lodash-es/isEmpty';
|
||||
import _noop from 'lodash-es/noop';
|
||||
import { memo, useCallback, useMemo, useRef, useState } from 'react';
|
||||
@ -28,6 +28,7 @@ function GridCardGraph({
|
||||
isQueryEnabled,
|
||||
threshold,
|
||||
variables,
|
||||
filterNaN,
|
||||
}: GridCardGraphProps): JSX.Element {
|
||||
const dispatch = useDispatch();
|
||||
const [errorMessage, setErrorMessage] = useState<string>();
|
||||
@ -89,7 +90,11 @@ function GridCardGraph({
|
||||
|
||||
const containerDimensions = useResizeObserver(graphRef);
|
||||
|
||||
const chartData = getUPlotChartData(queryResponse?.data?.payload);
|
||||
const chartData = getUPlotChartData(
|
||||
queryResponse?.data?.payload,
|
||||
undefined,
|
||||
filterNaN,
|
||||
);
|
||||
|
||||
const isDarkMode = useIsDarkMode();
|
||||
|
||||
|
@ -39,6 +39,7 @@ export interface GridCardGraphProps {
|
||||
headerMenuList?: WidgetGraphComponentProps['headerMenuList'];
|
||||
isQueryEnabled: boolean;
|
||||
variables?: Dashboard['data']['variables'];
|
||||
filterNaN?: boolean;
|
||||
}
|
||||
|
||||
export interface GetGraphVisibilityStateOnLegendClickProps {
|
||||
|
@ -118,7 +118,11 @@ function GraphLayout({ onAddPanelHandler }: GraphLayoutProps): JSX.Element {
|
||||
)}
|
||||
|
||||
{addPanelPermission && (
|
||||
<Button onClick={onAddPanelHandler} icon={<PlusOutlined />}>
|
||||
<Button
|
||||
onClick={onAddPanelHandler}
|
||||
icon={<PlusOutlined />}
|
||||
data-testid="add-panel"
|
||||
>
|
||||
{t('dashboard:add_panel')}
|
||||
</Button>
|
||||
)}
|
||||
|
@ -203,7 +203,7 @@ function WidgetHeader({
|
||||
onClick={onClickHandler}
|
||||
>
|
||||
<HeaderContentContainer>
|
||||
<Typography.Text style={{ maxWidth: '80%' }} ellipsis>
|
||||
<Typography.Text style={{ maxWidth: '80%' }} ellipsis data-testid={title}>
|
||||
{title}
|
||||
</Typography.Text>
|
||||
<ArrowContainer hover={parentHover}>
|
||||
|
@ -135,14 +135,13 @@ function HeaderContainer(): JSX.Element {
|
||||
<>
|
||||
{showTrialExpiryBanner && (
|
||||
<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>
|
||||
{getFormattedDate(licenseData?.payload?.trialEnd || Date.now())}.
|
||||
</span>
|
||||
{role === 'ADMIN' ? (
|
||||
<span>
|
||||
{' '}
|
||||
Please{' '}
|
||||
Please
|
||||
<Button className="upgrade-link" type="link" onClick={handleUpgrade}>
|
||||
upgrade
|
||||
</Button>
|
||||
|
@ -3,6 +3,8 @@ import styled from 'styled-components';
|
||||
|
||||
export const Header = styled(Layout.Header)`
|
||||
background: #1f1f1f !important;
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
`;
|
||||
|
||||
export const Container = styled.div`
|
||||
|
@ -7,14 +7,14 @@ import ApplyLicenseForm from './ApplyLicenseForm';
|
||||
import ListLicenses from './ListLicenses';
|
||||
|
||||
function Licenses(): JSX.Element {
|
||||
const { t } = useTranslation(['licenses']);
|
||||
const { t, ready: translationsReady } = useTranslation(['licenses']);
|
||||
const { data, isError, isLoading, refetch } = useLicense();
|
||||
|
||||
if (isError || data?.error) {
|
||||
return <Typography>{data?.error}</Typography>;
|
||||
}
|
||||
|
||||
if (isLoading || data?.payload === undefined) {
|
||||
if (isLoading || data?.payload === undefined || !translationsReady) {
|
||||
return <Spinner tip={t('loading_licenses')} height="90vh" />;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 { useDeleteDashboard } from 'hooks/dashboard/useDeleteDashboard';
|
||||
import { useCallback } from 'react';
|
||||
@ -10,10 +10,22 @@ import { AppState } from 'store/reducers';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
import { USER_ROLES } from 'types/roles';
|
||||
|
||||
import { Data } from '../index';
|
||||
import { Data } from '..';
|
||||
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 { role, user } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
const isAuthor = user?.email === createdBy;
|
||||
@ -26,7 +38,13 @@ function DeleteButton({ id, createdBy, isLocked }: Data): JSX.Element {
|
||||
|
||||
const openConfirmationDialog = useCallback((): void => {
|
||||
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' }} />,
|
||||
onOk() {
|
||||
deleteDashboardMutation.mutateAsync(undefined, {
|
||||
@ -39,7 +57,7 @@ function DeleteButton({ id, createdBy, isLocked }: Data): JSX.Element {
|
||||
okButtonProps: { danger: true },
|
||||
centered: true,
|
||||
});
|
||||
}, [modal, deleteDashboardMutation, queryClient]);
|
||||
}, [modal, name, deleteDashboardMutation, queryClient]);
|
||||
|
||||
const getDeleteTooltipContent = (): string => {
|
||||
if (isLocked) {
|
||||
|
@ -1,11 +1,12 @@
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import {
|
||||
Card,
|
||||
Col,
|
||||
Dropdown,
|
||||
Input,
|
||||
MenuProps,
|
||||
Row,
|
||||
TableColumnProps,
|
||||
Typography,
|
||||
} from 'antd';
|
||||
import { ItemType } from 'antd/es/menu/hooks/useItems';
|
||||
import createDashboard from 'api/dashboard/create';
|
||||
@ -18,9 +19,9 @@ import DynamicColumnTable from 'components/ResizeTable/DynamicColumnTable';
|
||||
import LabelColumn from 'components/TableRenderer/LabelColumn';
|
||||
import TextToolTip from 'components/TextToolTip';
|
||||
import ROUTES from 'constants/routes';
|
||||
import SearchFilter from 'container/ListOfDashboard/SearchFilter';
|
||||
import { useGetAllDashboard } from 'hooks/dashboard/useGetAllDashboard';
|
||||
import useComponentPermission from 'hooks/useComponentPermission';
|
||||
import useDebouncedFn from 'hooks/useDebouncedFunction';
|
||||
import history from 'lib/history';
|
||||
import { Key, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@ -38,6 +39,8 @@ import DeleteButton from './TableComponents/DeleteButton';
|
||||
import Name from './TableComponents/Name';
|
||||
|
||||
function ListOfAllDashboard(): JSX.Element {
|
||||
const { Search } = Input;
|
||||
|
||||
const {
|
||||
data: dashboardListResponse = [],
|
||||
isLoading: isDashboardListLoading,
|
||||
@ -59,12 +62,21 @@ function ListOfAllDashboard(): JSX.Element {
|
||||
] = 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(() => {
|
||||
if (dashboardListResponse.length) {
|
||||
setFilteredDashboards(dashboardListResponse);
|
||||
sortDashboardsByCreatedAt(dashboardListResponse);
|
||||
}
|
||||
}, [dashboardListResponse]);
|
||||
|
||||
@ -150,7 +162,7 @@ function ListOfAllDashboard(): JSX.Element {
|
||||
}, [action]);
|
||||
|
||||
const data: Data[] =
|
||||
filteredDashboards?.map((e) => ({
|
||||
dashboards?.map((e) => ({
|
||||
createdAt: e.created_at,
|
||||
description: e.data.description || '',
|
||||
id: e.uuid,
|
||||
@ -255,41 +267,85 @@ function ListOfAllDashboard(): JSX.Element {
|
||||
[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(
|
||||
() => (
|
||||
<Row justify="space-between">
|
||||
<Typography>Dashboard List</Typography>
|
||||
|
||||
<ButtonContainer>
|
||||
<TextToolTip
|
||||
{...{
|
||||
text: `More details on how to create dashboards`,
|
||||
url: 'https://signoz.io/docs/userguide/dashboards',
|
||||
}}
|
||||
<Row gutter={16} align="middle">
|
||||
<Col span={18}>
|
||||
<Search
|
||||
disabled={isDashboardListLoading}
|
||||
placeholder="Search by Name, Description, Tags"
|
||||
onChange={handleSearch}
|
||||
loading={isFilteringDashboards}
|
||||
style={{ marginBottom: 16, marginTop: 16 }}
|
||||
/>
|
||||
{newDashboard && (
|
||||
<Dropdown
|
||||
getPopupContainer={popupContainer}
|
||||
disabled={isDashboardListLoading}
|
||||
trigger={['click']}
|
||||
menu={menu}
|
||||
>
|
||||
<NewDashboardButton
|
||||
icon={<PlusOutlined />}
|
||||
type="primary"
|
||||
loading={newDashboardState.loading}
|
||||
danger={newDashboardState.error}
|
||||
</Col>
|
||||
|
||||
<Col
|
||||
span={6}
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-end',
|
||||
}}
|
||||
>
|
||||
<ButtonContainer>
|
||||
<TextToolTip
|
||||
{...{
|
||||
text: `More details on how to create dashboards`,
|
||||
url: 'https://signoz.io/docs/userguide/dashboards',
|
||||
}}
|
||||
/>
|
||||
{newDashboard && (
|
||||
<Dropdown
|
||||
getPopupContainer={popupContainer}
|
||||
disabled={isDashboardListLoading}
|
||||
trigger={['click']}
|
||||
menu={menu}
|
||||
>
|
||||
{getText()}
|
||||
</NewDashboardButton>
|
||||
</Dropdown>
|
||||
)}
|
||||
</ButtonContainer>
|
||||
<NewDashboardButton
|
||||
icon={<PlusOutlined />}
|
||||
type="primary"
|
||||
data-testid="create-new-dashboard"
|
||||
loading={newDashboardState.loading}
|
||||
danger={newDashboardState.error}
|
||||
>
|
||||
{getText()}
|
||||
</NewDashboardButton>
|
||||
</Dropdown>
|
||||
)}
|
||||
</ButtonContainer>
|
||||
</Col>
|
||||
</Row>
|
||||
),
|
||||
[
|
||||
newDashboard,
|
||||
Search,
|
||||
isDashboardListLoading,
|
||||
handleSearch,
|
||||
isFilteringDashboards,
|
||||
newDashboard,
|
||||
menu,
|
||||
newDashboardState.loading,
|
||||
newDashboardState.error,
|
||||
@ -301,13 +357,6 @@ function ListOfAllDashboard(): JSX.Element {
|
||||
<Card>
|
||||
{GetHeader}
|
||||
|
||||
{!isDashboardListLoading && (
|
||||
<SearchFilter
|
||||
searchData={dashboardListResponse}
|
||||
filterDashboards={setFilteredDashboards}
|
||||
/>
|
||||
)}
|
||||
|
||||
<TableContainer>
|
||||
<ImportJSON
|
||||
isImportJSONModalVisible={isImportJSONModalVisible}
|
||||
@ -319,8 +368,9 @@ function ListOfAllDashboard(): JSX.Element {
|
||||
dynamicColumns={dynamicColumns}
|
||||
columns={columns}
|
||||
pagination={{
|
||||
pageSize: 9,
|
||||
defaultPageSize: 9,
|
||||
pageSize: 10,
|
||||
defaultPageSize: 10,
|
||||
total: data?.length || 0,
|
||||
}}
|
||||
showHeader
|
||||
bordered
|
||||
|
@ -41,6 +41,7 @@ import {
|
||||
import { DataSource, LogsAggregatorOperator } from 'types/common/queryBuilder';
|
||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
import { generateExportToDashboardLink } from 'utils/dashboard/generateExportToDashboardLink';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { ActionsWrapper } from './LogsExplorerViews.styled';
|
||||
|
||||
@ -268,9 +269,12 @@ function LogsExplorerViews(): JSX.Element {
|
||||
? panelType
|
||||
: PANEL_TYPES.TIME_SERIES;
|
||||
|
||||
const widgetId = v4();
|
||||
|
||||
const updatedDashboard = addEmptyWidgetInDashboardJSONWithQuery(
|
||||
dashboard,
|
||||
exportDefaultQuery,
|
||||
widgetId,
|
||||
panelTypeParam,
|
||||
);
|
||||
|
||||
@ -304,6 +308,7 @@ function LogsExplorerViews(): JSX.Element {
|
||||
query: exportDefaultQuery,
|
||||
panelType: panelTypeParam,
|
||||
dashboardId: data.payload?.uuid || '',
|
||||
widgetId,
|
||||
});
|
||||
|
||||
history.push(dashboardEditView);
|
||||
|
@ -107,6 +107,7 @@ function DBCall(): JSX.Element {
|
||||
<Card data-testid="database_call_rps">
|
||||
<GraphContainer>
|
||||
<Graph
|
||||
filterNaN
|
||||
name="database_call_rps"
|
||||
widget={databaseCallsRPSWidget}
|
||||
onClickHandler={(xValue, yValue, mouseX, mouseY): void => {
|
||||
@ -140,6 +141,7 @@ function DBCall(): JSX.Element {
|
||||
<Card data-testid="database_call_avg_duration">
|
||||
<GraphContainer>
|
||||
<Graph
|
||||
filterNaN
|
||||
name="database_call_avg_duration"
|
||||
widget={databaseCallsAverageDurationWidget}
|
||||
headerMenuList={MENU_ITEMS}
|
||||
|
@ -148,6 +148,7 @@ function External(): JSX.Element {
|
||||
<Card data-testid="external_call_error_percentage">
|
||||
<GraphContainer>
|
||||
<Graph
|
||||
filterNaN
|
||||
headerMenuList={MENU_ITEMS}
|
||||
name="external_call_error_percentage"
|
||||
widget={externalCallErrorWidget}
|
||||
@ -183,6 +184,7 @@ function External(): JSX.Element {
|
||||
<Card data-testid="external_call_duration">
|
||||
<GraphContainer>
|
||||
<Graph
|
||||
filterNaN
|
||||
name="external_call_duration"
|
||||
headerMenuList={MENU_ITEMS}
|
||||
widget={externalCallDurationWidget}
|
||||
@ -219,6 +221,7 @@ function External(): JSX.Element {
|
||||
<Card data-testid="external_call_rps_by_address">
|
||||
<GraphContainer>
|
||||
<Graph
|
||||
filterNaN
|
||||
name="external_call_rps_by_address"
|
||||
widget={externalCallRPSWidget}
|
||||
headerMenuList={MENU_ITEMS}
|
||||
@ -257,6 +260,7 @@ function External(): JSX.Element {
|
||||
name="external_call_duration_by_address"
|
||||
widget={externalCallDurationAddressWidget}
|
||||
headerMenuList={MENU_ITEMS}
|
||||
filterNaN
|
||||
onClickHandler={(xValue, yValue, mouseX, mouseY): void => {
|
||||
onGraphClickHandler(setSelectedTimeStamp)(
|
||||
xValue,
|
||||
|
@ -84,6 +84,7 @@ function ApDexMetrics({
|
||||
return (
|
||||
<Graph
|
||||
name="apdex"
|
||||
filterNaN
|
||||
widget={apDexMetricsWidget}
|
||||
onDragSelect={onDragSelect}
|
||||
onClickHandler={handleGraphClick('ApDex')}
|
||||
|
@ -88,6 +88,7 @@ function ServiceOverview({
|
||||
widget={latencyWidget}
|
||||
onClickHandler={handleGraphClick('Service')}
|
||||
isQueryEnabled={isQueryEnabled}
|
||||
filterNaN
|
||||
/>
|
||||
</GraphContainer>
|
||||
</Card>
|
||||
|
@ -27,6 +27,7 @@ function TopLevelOperation({
|
||||
) : (
|
||||
<GraphContainer>
|
||||
<Graph
|
||||
filterNaN
|
||||
name={name}
|
||||
widget={widget}
|
||||
onClickHandler={handleGraphClick(opName)}
|
||||
|
@ -18,7 +18,12 @@ function SettingsDrawer({ drawerTitle }: { drawerTitle: string }): JSX.Element {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button type="dashed" onClick={showDrawer} style={{ width: '100%' }}>
|
||||
<Button
|
||||
type="dashed"
|
||||
onClick={showDrawer}
|
||||
style={{ width: '100%' }}
|
||||
data-testid="show-drawer"
|
||||
>
|
||||
<SettingOutlined /> Configure
|
||||
</Button>
|
||||
<DrawerContainer
|
||||
|
@ -51,7 +51,11 @@ function DashboardDescription(): JSX.Element {
|
||||
<Card>
|
||||
<Row gutter={16}>
|
||||
<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 && (
|
||||
<Tooltip title="Dashboard Locked" placement="top">
|
||||
<LockFilled />
|
||||
@ -60,7 +64,12 @@ function DashboardDescription(): JSX.Element {
|
||||
{title}
|
||||
</Typography.Title>
|
||||
{description && (
|
||||
<Typography className="dashboard-description">{description}</Typography>
|
||||
<Typography
|
||||
className="dashboard-description"
|
||||
data-testid="dashboard-landing-desc"
|
||||
>
|
||||
{description}
|
||||
</Typography>
|
||||
)}
|
||||
|
||||
{tags && (
|
||||
|
@ -63,6 +63,7 @@ function GeneralDashboardSettings(): JSX.Element {
|
||||
<div>
|
||||
<Typography style={{ marginBottom: '0.5rem' }}>Name</Typography>
|
||||
<Input
|
||||
data-testid="dashboard-name"
|
||||
value={updatedTitle}
|
||||
onChange={(e): void => setUpdatedTitle(e.target.value)}
|
||||
/>
|
||||
@ -71,6 +72,7 @@ function GeneralDashboardSettings(): JSX.Element {
|
||||
<div>
|
||||
<Typography style={{ marginBottom: '0.5rem' }}>Description</Typography>
|
||||
<Input.TextArea
|
||||
data-testid="dashboard-desc"
|
||||
rows={5}
|
||||
value={updatedDescription}
|
||||
onChange={(e): void => setUpdatedDescription(e.target.value)}
|
||||
@ -88,6 +90,7 @@ function GeneralDashboardSettings(): JSX.Element {
|
||||
disabled={updateDashboardMutation.isLoading}
|
||||
loading={updateDashboardMutation.isLoading}
|
||||
icon={<SaveOutlined />}
|
||||
data-testid="save-dashboard-config"
|
||||
onClick={onSaveHandler}
|
||||
type="primary"
|
||||
>
|
||||
|
@ -181,6 +181,7 @@ function VariablesSetting(): JSX.Element {
|
||||
<>
|
||||
<Row style={{ flexDirection: 'row-reverse', padding: '0.5rem 0' }}>
|
||||
<Button
|
||||
data-testid="add-new-variable"
|
||||
type="primary"
|
||||
onClick={(): void =>
|
||||
onVariableViewModeEnter('ADD', {} as IDashboardVariable)
|
||||
|
@ -3,12 +3,16 @@ import { Tabs } from 'antd';
|
||||
import GeneralDashboardSettings from './General';
|
||||
import VariablesSetting from './Variables';
|
||||
|
||||
const items = [
|
||||
{ label: 'General', key: 'general', children: <GeneralDashboardSettings /> },
|
||||
{ label: 'Variables', key: 'variables', children: <VariablesSetting /> },
|
||||
];
|
||||
|
||||
function DashboardSettingsContent(): JSX.Element {
|
||||
const items = [
|
||||
{
|
||||
label: 'General',
|
||||
key: 'general',
|
||||
children: <GeneralDashboardSettings />,
|
||||
},
|
||||
{ label: 'Variables', key: 'variables', children: <VariablesSetting /> },
|
||||
];
|
||||
|
||||
return <Tabs items={items} />;
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@ function NewExplorerCTA(): JSX.Element | null {
|
||||
icon={<CompassOutlined />}
|
||||
onClick={onClickHandler}
|
||||
danger
|
||||
data-testid="newExplorerCTA"
|
||||
type="primary"
|
||||
>
|
||||
{buttonText[location.pathname]}
|
||||
|
@ -4,8 +4,8 @@ import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import { useResizeObserver } from 'hooks/useDimensions';
|
||||
import useUrlQuery from 'hooks/useUrlQuery';
|
||||
import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartData';
|
||||
import { getUPlotChartData } from 'lib/uPlotLib/utils/getChartData';
|
||||
import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartOptions';
|
||||
import { getUPlotChartData } from 'lib/uPlotLib/utils/getUplotChartData';
|
||||
import { useCallback, useMemo, useRef } from 'react';
|
||||
import { UseQueryResult } from 'react-query';
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
@ -261,7 +261,12 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
|
||||
)}
|
||||
|
||||
{!isSaveDisabled && (
|
||||
<Button type="primary" disabled={isSaveDisabled} onClick={onSaveDashboard}>
|
||||
<Button
|
||||
type="primary"
|
||||
data-testid="new-widget-save"
|
||||
disabled={isSaveDisabled}
|
||||
onClick={onSaveDashboard}
|
||||
>
|
||||
Save
|
||||
</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