Trace UI demo (#20297)
* Add integration with Jeager Add Jaeger datasource and modify derived fields in loki to allow for opening a trace in Jager in separate split. Modifies build so that this branch docker images are pushed to docker hub Add a traceui dir with docker-compose and provision files for demoing.:wq * Enable docker logger plugin to send logs to loki * Add placeholder zipkin datasource * Fixed rebase issues, added enhanceDataFrame to non-legacy code path * Trace selector for jaeger query field * Fix logs default mode for Loki * Fix loading jaeger query field services on split * Updated grafana image in traceui/compose file * Fix prettier error * Hide behind feature flag, clean up unused code. * Fix tests * Fix tests * Cleanup code and review feedback * Remove traceui directory * Remove circle build changes * Fix feature toggles object * Fix merge issues * Fix some null errors * Fix test after strict null changes * Review feedback fixes * Fix toggle name Co-authored-by: David Kaltschmidt <david.kaltschmidt@gmail.com>
This commit is contained in:
1 parent
b6f73e35a5
commit
ae09ccbf79
44 files changed
+984
-78
No files matched your search
@@ -26,7 +26,11 @@ export namespace dateMath {
|
||||
* @param roundUp See parseDateMath function.
|
||||
* @param timezone Only string 'utc' is acceptable here, for anything else, local timezone is used.
|
||||
*/
|
||||
export function parse(text: string | DateTime | Date, roundUp?: boolean, timezone?: TimeZone): DateTime | undefined {
|
||||
export function parse(
|
||||
text?: string | DateTime | Date | null,
|
||||
roundUp?: boolean,
|
||||
timezone?: TimeZone
|
||||
): DateTime | undefined {
|
||||
if (!text) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,9 @@ export interface DataLink {
|
||||
// 1: If exists, handle click directly
|
||||
// Not saved in JSON/DTO
|
||||
onClick?: (event: DataLinkClickEvent) => void;
|
||||
|
||||
// At the moment this is used for derived fields for metadata about internal linking.
|
||||
meta?: any;
|
||||
}
|
||||
|
||||
export type LinkTarget = '_blank' | '_self';
|
||||
|
||||
@@ -115,6 +115,7 @@ export interface DataSourcePluginMeta<T extends KeyValue = {}> extends PluginMet
|
||||
logs?: boolean;
|
||||
annotations?: boolean;
|
||||
alerting?: boolean;
|
||||
tracing?: boolean;
|
||||
mixed?: boolean;
|
||||
hasQueryHelp?: boolean;
|
||||
category?: string;
|
||||
@@ -316,6 +317,7 @@ export enum DataSourceStatus {
|
||||
export enum ExploreMode {
|
||||
Logs = 'Logs',
|
||||
Metrics = 'Metrics',
|
||||
Tracing = 'Tracing',
|
||||
}
|
||||
|
||||
export interface ExploreQueryFieldProps<
|
||||
|
||||
@@ -19,6 +19,7 @@ interface FeatureToggles {
|
||||
newEdit: boolean;
|
||||
meta: boolean;
|
||||
newVariables: boolean;
|
||||
tracingIntegration: boolean;
|
||||
}
|
||||
|
||||
interface LicenseInfo {
|
||||
@@ -71,6 +72,7 @@ export class GrafanaBootConfig {
|
||||
newEdit: false,
|
||||
meta: false,
|
||||
newVariables: false,
|
||||
tracingIntegration: false,
|
||||
};
|
||||
licenseInfo: LicenseInfo = {} as LicenseInfo;
|
||||
phantomJSRenderer = false;
|
||||
|
||||
@@ -24,7 +24,7 @@ import { LogDetailsRow } from './LogDetailsRow';
|
||||
type FieldDef = {
|
||||
key: string;
|
||||
value: string;
|
||||
links?: string[];
|
||||
links?: Array<LinkModel<Field>>;
|
||||
fieldIndex?: number;
|
||||
};
|
||||
|
||||
@@ -99,7 +99,7 @@ class UnThemedLogDetails extends PureComponent<Props> {
|
||||
return {
|
||||
key: field.name,
|
||||
value: field.values.get(row.rowIndex).toString(),
|
||||
links: links.map(link => link.href),
|
||||
links: links,
|
||||
fieldIndex: field.index,
|
||||
};
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { css, cx } from 'emotion';
|
||||
import { LogLabelStatsModel, GrafanaTheme } from '@grafana/data';
|
||||
import { Field, LinkModel, LogLabelStatsModel, GrafanaTheme } from '@grafana/data';
|
||||
|
||||
import { Themeable } from '../../types/theme';
|
||||
import { withTheme } from '../../themes/index';
|
||||
@@ -9,6 +9,7 @@ import { stylesFactory } from '../../themes/stylesFactory';
|
||||
|
||||
//Components
|
||||
import { LogLabelStats } from './LogLabelStats';
|
||||
import { LinkButton } from '../Button/Button';
|
||||
|
||||
export interface Props extends Themeable {
|
||||
parsedValue: string;
|
||||
@@ -16,7 +17,7 @@ export interface Props extends Themeable {
|
||||
isLabel?: boolean;
|
||||
onClickFilterLabel?: (key: string, value: string) => void;
|
||||
onClickFilterOutLabel?: (key: string, value: string) => void;
|
||||
links?: string[];
|
||||
links?: Array<LinkModel<Field>>;
|
||||
getStats: () => LogLabelStatsModel[] | null;
|
||||
}
|
||||
|
||||
@@ -122,11 +123,27 @@ class UnThemedLogDetailsRow extends PureComponent<Props, State> {
|
||||
{links &&
|
||||
links.map(link => {
|
||||
return (
|
||||
<span key={link}>
|
||||
|
||||
<a href={link} target={'_blank'}>
|
||||
<i className={'fa fa-external-link'} />
|
||||
</a>
|
||||
<span key={link.href}>
|
||||
<>
|
||||
|
||||
<LinkButton
|
||||
variant={'transparent'}
|
||||
size={'sm'}
|
||||
icon={cx('fa', link.onClick ? 'fa-list' : 'fa-external-link')}
|
||||
href={link.href}
|
||||
target={'_blank'}
|
||||
onClick={
|
||||
link.onClick
|
||||
? event => {
|
||||
if (!(event.ctrlKey || event.metaKey || event.shiftKey) && link.onClick) {
|
||||
event.preventDefault();
|
||||
link.onClick(event);
|
||||
}
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</>
|
||||
</span>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -92,7 +92,11 @@ func pluginScenario(desc string, t *testing.T, fn func()) {
|
||||
_, err := sec.NewKey("path", "testdata/test-app")
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
pm := &PluginManager{}
|
||||
pm := &PluginManager{
|
||||
Cfg: &setting.Cfg{
|
||||
FeatureToggles: map[string]bool{},
|
||||
},
|
||||
}
|
||||
err = pm.Init()
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
|
||||
@@ -18,7 +18,11 @@ func TestPluginDashboards(t *testing.T) {
|
||||
_, err := sec.NewKey("path", "testdata/test-app")
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
pm := &PluginManager{}
|
||||
pm := &PluginManager{
|
||||
Cfg: &setting.Cfg{
|
||||
FeatureToggles: map[string]bool{},
|
||||
},
|
||||
}
|
||||
err = pm.Init()
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ type DataSourcePlugin struct {
|
||||
Explore bool `json:"explore"`
|
||||
Table bool `json:"tables"`
|
||||
Logs bool `json:"logs"`
|
||||
Tracing bool `json:"tracing"`
|
||||
QueryOptions map[string]bool `json:"queryOptions,omitempty"`
|
||||
BuiltIn bool `json:"builtIn,omitempty"`
|
||||
Mixed bool `json:"mixed,omitempty"`
|
||||
|
||||
@@ -42,10 +42,12 @@ type PluginScanner struct {
|
||||
pluginPath string
|
||||
errors []error
|
||||
backendPluginManager backendplugin.Manager
|
||||
cfg *setting.Cfg
|
||||
}
|
||||
|
||||
type PluginManager struct {
|
||||
BackendPluginManager backendplugin.Manager `inject:""`
|
||||
Cfg *setting.Cfg `inject:""`
|
||||
log log.Logger
|
||||
}
|
||||
|
||||
@@ -164,6 +166,7 @@ func (pm *PluginManager) scan(pluginDir string) error {
|
||||
scanner := &PluginScanner{
|
||||
pluginPath: pluginDir,
|
||||
backendPluginManager: pm.BackendPluginManager,
|
||||
cfg: pm.Cfg,
|
||||
}
|
||||
|
||||
if err := util.Walk(pluginDir, true, true, scanner.walker); err != nil {
|
||||
@@ -213,6 +216,14 @@ func (scanner *PluginScanner) walker(currentPath string, f os.FileInfo, err erro
|
||||
return nil
|
||||
}
|
||||
|
||||
if !scanner.cfg.FeatureToggles["tracingIntegration"] {
|
||||
// Do not load tracing datasources if
|
||||
prefix := path.Join(setting.StaticRootPath, "app/plugins/datasource")
|
||||
if strings.Contains(currentPath, path.Join(prefix, "jaeger")) || strings.Contains(currentPath, path.Join(prefix, "zipkin")) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if f.Name() == "plugin.json" {
|
||||
err := scanner.loadPluginJson(currentPath)
|
||||
if err != nil {
|
||||
|
||||
@@ -15,7 +15,11 @@ func TestPluginScans(t *testing.T) {
|
||||
setting.StaticRootPath, _ = filepath.Abs("../../public/")
|
||||
setting.Raw = ini.Empty()
|
||||
|
||||
pm := &PluginManager{}
|
||||
pm := &PluginManager{
|
||||
Cfg: &setting.Cfg{
|
||||
FeatureToggles: map[string]bool{},
|
||||
},
|
||||
}
|
||||
err := pm.Init()
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
@@ -34,7 +38,11 @@ func TestPluginScans(t *testing.T) {
|
||||
_, err = sec.NewKey("path", "testdata/test-app")
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
pm := &PluginManager{}
|
||||
pm := &PluginManager{
|
||||
Cfg: &setting.Cfg{
|
||||
FeatureToggles: map[string]bool{},
|
||||
},
|
||||
}
|
||||
err = pm.Init()
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
|
||||
@@ -281,6 +281,7 @@ type Cfg struct {
|
||||
|
||||
ApiKeyMaxSecondsToLive int64
|
||||
|
||||
// Use to enable new features which may still be in alpha/beta stage.
|
||||
FeatureToggles map[string]bool
|
||||
}
|
||||
|
||||
|
||||
@@ -66,17 +66,17 @@ export interface GetExploreUrlArguments {
|
||||
datasourceSrv: DataSourceSrv;
|
||||
timeSrv: TimeSrv;
|
||||
}
|
||||
export async function getExploreUrl(args: GetExploreUrlArguments) {
|
||||
export async function getExploreUrl(args: GetExploreUrlArguments): Promise<string | undefined> {
|
||||
const { panel, panelTargets, panelDatasource, datasourceSrv, timeSrv } = args;
|
||||
let exploreDatasource = panelDatasource;
|
||||
let exploreTargets: DataQuery[] = panelTargets;
|
||||
let url: string;
|
||||
let url: string | undefined;
|
||||
|
||||
// Mixed datasources need to choose only one datasource
|
||||
if (panelDatasource.meta.id === 'mixed' && exploreTargets) {
|
||||
if (panelDatasource.meta?.id === 'mixed' && exploreTargets) {
|
||||
// Find first explore datasource among targets
|
||||
for (const t of exploreTargets) {
|
||||
const datasource = await datasourceSrv.get(t.datasource);
|
||||
const datasource = await datasourceSrv.get(t.datasource || undefined);
|
||||
if (datasource) {
|
||||
exploreDatasource = datasource;
|
||||
exploreTargets = panelTargets.filter(t => t.datasource === datasource.name);
|
||||
@@ -183,7 +183,7 @@ enum ParseUiStateIndex {
|
||||
Strategy = 3,
|
||||
}
|
||||
|
||||
export const safeParseJson = (text: string) => {
|
||||
export const safeParseJson = (text?: string): any | undefined => {
|
||||
if (!text) {
|
||||
return;
|
||||
}
|
||||
@@ -365,7 +365,7 @@ export function clearHistory(datasourceId: string) {
|
||||
}
|
||||
|
||||
export const getQueryKeys = (queries: DataQuery[], datasourceInstance: DataSourceApi): string[] => {
|
||||
const queryKeys = queries.reduce((newQueryKeys, query, index) => {
|
||||
const queryKeys = queries.reduce<string[]>((newQueryKeys, query, index) => {
|
||||
const primaryKey = datasourceInstance && datasourceInstance.name ? datasourceInstance.name : query.key;
|
||||
return newQueryKeys.concat(`${primaryKey}-${index}`);
|
||||
}, []);
|
||||
@@ -381,7 +381,7 @@ export const getTimeRange = (timeZone: TimeZone, rawRange: RawTimeRange): TimeRa
|
||||
};
|
||||
};
|
||||
|
||||
const parseRawTime = (value: any): TimeFragment => {
|
||||
const parseRawTime = (value: any): TimeFragment | null => {
|
||||
if (value === null) {
|
||||
return null;
|
||||
}
|
||||
@@ -442,7 +442,7 @@ export const getValueWithRefId = (value?: any): any => {
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export const getFirstQueryErrorWithoutRefId = (errors?: DataQueryError[]) => {
|
||||
export const getFirstQueryErrorWithoutRefId = (errors?: DataQueryError[]): DataQueryError | undefined => {
|
||||
if (!errors) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -530,7 +530,7 @@ export const stopQueryState = (querySubscription: Unsubscribable) => {
|
||||
}
|
||||
};
|
||||
|
||||
export function getIntervals(range: TimeRange, lowLimit: string, resolution: number): IntervalValues {
|
||||
export function getIntervals(range: TimeRange, lowLimit: string, resolution?: number): IntervalValues {
|
||||
if (!resolution) {
|
||||
return { interval: '1s', intervalMs: 1000 };
|
||||
}
|
||||
@@ -542,7 +542,7 @@ export function deduplicateLogRowsById(rows: LogRowModel[]) {
|
||||
return _.uniqBy(rows, 'uid');
|
||||
}
|
||||
|
||||
export const getFirstNonQueryRowSpecificError = (queryErrors?: DataQueryError[]) => {
|
||||
export const getFirstNonQueryRowSpecificError = (queryErrors?: DataQueryError[]): DataQueryError | undefined => {
|
||||
const refId = getValueWithRefId(queryErrors);
|
||||
return refId ? null : getFirstQueryErrorWithoutRefId(queryErrors);
|
||||
return refId ? undefined : getFirstQueryErrorWithoutRefId(queryErrors);
|
||||
};
|
||||
@@ -88,7 +88,7 @@ export const parseBody = (options: BackendSrvRequest, isAppJson: boolean) => {
|
||||
return isAppJson ? JSON.stringify(options.data) : new URLSearchParams(options.data);
|
||||
};
|
||||
|
||||
function serializeParams(data: Record<string, any>): string {
|
||||
export function serializeParams(data: Record<string, any>): string {
|
||||
return Object.keys(data)
|
||||
.map(key => {
|
||||
const value = data[key];
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import _ from 'lodash';
|
||||
import { DataQuery } from '@grafana/data';
|
||||
|
||||
export const getNextRefIdChar = (queries: DataQuery[]): string => {
|
||||
export const getNextRefIdChar = (queries: DataQuery[]): string | undefined => {
|
||||
const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
|
||||
return _.find(letters, refId => {
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
import { DataSourcePluginMeta, PluginType } from '@grafana/data';
|
||||
import { DataSourcePluginCategory } from 'app/types';
|
||||
import { config } from '@grafana/runtime';
|
||||
|
||||
export function buildCategories(plugins: DataSourcePluginMeta[]): DataSourcePluginCategory[] {
|
||||
const categories: DataSourcePluginCategory[] = [
|
||||
{ id: 'tsdb', title: 'Time series databases', plugins: [] },
|
||||
{ id: 'logging', title: 'Logging & document databases', plugins: [] },
|
||||
config.featureToggles.tracingIntegration ? { id: 'tracing', title: 'Distributed tracing', plugins: [] } : null,
|
||||
{ id: 'sql', title: 'SQL', plugins: [] },
|
||||
{ id: 'cloud', title: 'Cloud', plugins: [] },
|
||||
{ id: 'enterprise', title: 'Enterprise plugins', plugins: [] },
|
||||
{ id: 'other', title: 'Others', plugins: [] },
|
||||
];
|
||||
].filter(item => item);
|
||||
|
||||
const categoryIndex: Record<string, DataSourcePluginCategory> = {};
|
||||
const pluginIndex: Record<string, DataSourcePluginMeta> = {};
|
||||
@@ -66,6 +68,7 @@ function sortPlugins(plugins: DataSourcePluginMeta[]) {
|
||||
graphite: 95,
|
||||
loki: 90,
|
||||
mysql: 80,
|
||||
jaeger: 100,
|
||||
postgres: 79,
|
||||
gcloud: -1,
|
||||
};
|
||||
|
||||
@@ -148,13 +148,12 @@ describe('Explore', () => {
|
||||
it('should filter out a query-row-specific error when looking for non-query-row-specific errors', async () => {
|
||||
const queryErrors = setupErrors(true);
|
||||
const queryError = getFirstNonQueryRowSpecificError(queryErrors);
|
||||
expect(queryError).toBeNull();
|
||||
expect(queryError).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should not filter out a generic error when looking for non-query-row-specific errors', async () => {
|
||||
const queryErrors = setupErrors();
|
||||
const queryError = getFirstNonQueryRowSpecificError(queryErrors);
|
||||
expect(queryError).not.toBeNull();
|
||||
expect(queryError).toEqual({
|
||||
message: 'Error message',
|
||||
status: '400',
|
||||
|
||||
@@ -20,33 +20,33 @@ import {
|
||||
changeSize,
|
||||
initializeExplore,
|
||||
modifyQueries,
|
||||
refreshExplore,
|
||||
scanStart,
|
||||
setQueries,
|
||||
refreshExplore,
|
||||
updateTimeRange,
|
||||
toggleGraph,
|
||||
addQueryRow,
|
||||
updateTimeRange,
|
||||
} from './state/actions';
|
||||
// Types
|
||||
import {
|
||||
AbsoluteTimeRange,
|
||||
DataQuery,
|
||||
DataSourceApi,
|
||||
GraphSeriesXY,
|
||||
PanelData,
|
||||
RawTimeRange,
|
||||
TimeRange,
|
||||
GraphSeriesXY,
|
||||
TimeZone,
|
||||
AbsoluteTimeRange,
|
||||
LoadingState,
|
||||
ExploreMode,
|
||||
} from '@grafana/data';
|
||||
|
||||
import { ExploreItemState, ExploreUrlState, ExploreId, ExploreUpdateState, ExploreUIState } from 'app/types/explore';
|
||||
import { ExploreId, ExploreItemState, ExploreUIState, ExploreUpdateState, ExploreUrlState } from 'app/types/explore';
|
||||
import { StoreState } from 'app/types';
|
||||
import {
|
||||
ensureQueries,
|
||||
DEFAULT_RANGE,
|
||||
DEFAULT_UI_STATE,
|
||||
ensureQueries,
|
||||
getTimeRangeFromUrl,
|
||||
getTimeRange,
|
||||
lastUsedDatasourceKeyForOrgId,
|
||||
@@ -70,6 +70,18 @@ const getStyles = stylesFactory(() => {
|
||||
button: css`
|
||||
margin: 1em 4px 0 0;
|
||||
`,
|
||||
// Utility class for iframe parents so that we can show iframe content with reasonable height instead of squished
|
||||
// or some random explicit height.
|
||||
fullHeight: css`
|
||||
label: fullHeight;
|
||||
height: 100%;
|
||||
`,
|
||||
iframe: css`
|
||||
label: iframe;
|
||||
border: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
`,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -328,14 +340,14 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
||||
</button>
|
||||
</div>
|
||||
<ErrorContainer queryError={queryError} />
|
||||
<AutoSizer onResize={this.onResize} disableHeight>
|
||||
<AutoSizer className={styles.fullHeight} onResize={this.onResize} disableHeight>
|
||||
{({ width }) => {
|
||||
if (width === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<main className={`m-t-2 ${styles.logsMain}`} style={{ width }}>
|
||||
<main className={cx('m-t-2', styles.logsMain, styles.fullHeight)} style={{ width }}>
|
||||
<ErrorBoundaryAlert>
|
||||
{showStartPage && StartPage && (
|
||||
<div className={'grafana-info-box grafana-info-box--max-lg'}>
|
||||
@@ -379,6 +391,18 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
||||
onStopScanning={this.onStopScanning}
|
||||
/>
|
||||
)}
|
||||
{mode === ExploreMode.Tracing && (
|
||||
<div className={styles.fullHeight}>
|
||||
{queryResponse &&
|
||||
!!queryResponse.series.length &&
|
||||
queryResponse.series[0].fields[0].values.get(0) && (
|
||||
<iframe
|
||||
className={styles.iframe}
|
||||
src={queryResponse.series[0].fields[0].values.get(0)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{showRichHistory && (
|
||||
@@ -448,7 +472,7 @@ function mapStateToProps(state: StoreState, { exploreId }: ExploreProps): Partia
|
||||
newMode = supportedModes[0];
|
||||
}
|
||||
} else {
|
||||
newMode = [ExploreMode.Metrics, ExploreMode.Logs].includes(urlMode) ? urlMode : undefined;
|
||||
newMode = [ExploreMode.Metrics, ExploreMode.Logs, ExploreMode.Tracing].includes(urlMode) ? urlMode : undefined;
|
||||
}
|
||||
|
||||
const initialUI = ui || DEFAULT_UI_STATE;
|
||||
|
||||
@@ -366,7 +366,7 @@ const mapStateToProps = (state: StoreState, { exploreId }: OwnProps): StateProps
|
||||
containerWidth,
|
||||
} = exploreItem;
|
||||
|
||||
const hasLiveOption = datasourceInstance?.meta?.streaming && mode === ExploreMode.Logs;
|
||||
const hasLiveOption = !!(datasourceInstance?.meta?.streaming && mode === ExploreMode.Logs);
|
||||
|
||||
return {
|
||||
datasourceMissing,
|
||||
|
||||
@@ -14,12 +14,13 @@ import {
|
||||
TimeRange,
|
||||
LogsMetaItem,
|
||||
GraphSeriesXY,
|
||||
Field,
|
||||
} from '@grafana/data';
|
||||
|
||||
import { ExploreId, ExploreItemState } from 'app/types/explore';
|
||||
import { StoreState } from 'app/types';
|
||||
|
||||
import { changeDedupStrategy, updateTimeRange } from './state/actions';
|
||||
import { changeDedupStrategy, updateTimeRange, splitOpen } from './state/actions';
|
||||
import { toggleLogLevelAction } from 'app/features/explore/state/actionTypes';
|
||||
import { deduplicatedRowsSelector } from 'app/features/explore/state/selectors';
|
||||
import { getTimeZone } from '../profile/state/selectors';
|
||||
@@ -57,6 +58,7 @@ interface LogsContainerProps {
|
||||
syncedTimes: boolean;
|
||||
absoluteRange: AbsoluteTimeRange;
|
||||
isPaused: boolean;
|
||||
splitOpen: typeof splitOpen;
|
||||
}
|
||||
|
||||
export class LogsContainer extends PureComponent<LogsContainerProps> {
|
||||
@@ -87,6 +89,30 @@ export class LogsContainer extends PureComponent<LogsContainerProps> {
|
||||
return [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Get links from the filed of a dataframe that was given to as and in addition check if there is associated
|
||||
* metadata with datasource in which case we will add onClick to open the link in new split window. This assumes
|
||||
* that we just supply datasource name and field value and Explore split window will know how to render that
|
||||
* appropriately. This is for example used for transition from log with traceId to trace datasource to show that
|
||||
* trace.
|
||||
* @param field
|
||||
* @param rowIndex
|
||||
*/
|
||||
getFieldLinks = (field: Field, rowIndex: number) => {
|
||||
const data = getLinksFromLogsField(field, rowIndex);
|
||||
return data.map(d => {
|
||||
if (d.link.meta?.datasourceName) {
|
||||
return {
|
||||
...d.linkModel,
|
||||
onClick: () => {
|
||||
this.props.splitOpen(d.link.meta.datasourceName, field.values.get(rowIndex));
|
||||
},
|
||||
};
|
||||
}
|
||||
return d.linkModel;
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
loading,
|
||||
@@ -149,7 +175,7 @@ export class LogsContainer extends PureComponent<LogsContainerProps> {
|
||||
scanRange={range.raw}
|
||||
width={width}
|
||||
getRowContext={this.getLogRowContext}
|
||||
getFieldLinks={getLinksFromLogsField}
|
||||
getFieldLinks={this.getFieldLinks}
|
||||
/>
|
||||
</Collapse>
|
||||
</LogsCrossFadeTransition>
|
||||
@@ -199,6 +225,7 @@ const mapDispatchToProps = {
|
||||
changeDedupStrategy,
|
||||
toggleLogLevelAction,
|
||||
updateTimeRange,
|
||||
splitOpen,
|
||||
};
|
||||
|
||||
export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(LogsContainer));
|
||||
@@ -46,7 +46,7 @@ export class TableContainer extends PureComponent<TableContainerProps> {
|
||||
return (
|
||||
<Collapse label="Table" loading={loading} collapsible isOpen={showingTable} onToggle={this.onClickTableButton}>
|
||||
{hasTableResult ? (
|
||||
<Table data={tableResult} width={tableWidth} height={height} onCellClick={onClickCell} />
|
||||
<Table data={tableResult!} width={tableWidth} height={height} onCellClick={onClickCell} />
|
||||
) : (
|
||||
<MetaInfoText metaItems={[{ value: '0 series returned' }]} />
|
||||
)}
|
||||
|
||||
@@ -5,9 +5,9 @@ import { connect } from 'react-redux';
|
||||
import { StoreState } from 'app/types';
|
||||
import { ExploreId } from 'app/types/explore';
|
||||
|
||||
import Explore from './Explore';
|
||||
import { CustomScrollbar, ErrorBoundaryAlert } from '@grafana/ui';
|
||||
import { resetExploreAction } from './state/actionTypes';
|
||||
import Explore from './Explore';
|
||||
|
||||
interface WrapperProps {
|
||||
split: boolean;
|
||||
@@ -25,7 +25,7 @@ export class Wrapper extends Component<WrapperProps> {
|
||||
return (
|
||||
<div className="page-scrollbar-wrapper">
|
||||
<CustomScrollbar autoHeightMin={'100%'} autoHeightMax={''} className="custom-scrollbar--page">
|
||||
<div className="explore-wrapper">
|
||||
<div style={{ height: '100%' }} className="explore-wrapper">
|
||||
<ErrorBoundaryAlert style="page">
|
||||
<Explore exploreId={ExploreId.left} />
|
||||
</ErrorBoundaryAlert>
|
||||
|
||||
@@ -123,7 +123,7 @@ export function addQueryRow(exploreId: ExploreId, index: number): ThunkResult<vo
|
||||
*/
|
||||
export function changeDatasource(exploreId: ExploreId, datasource: string): ThunkResult<void> {
|
||||
return async (dispatch, getState) => {
|
||||
let newDataSourceInstance: DataSourceApi = null;
|
||||
let newDataSourceInstance: DataSourceApi;
|
||||
|
||||
if (!datasource) {
|
||||
newDataSourceInstance = await getDatasourceSrv().get();
|
||||
@@ -317,7 +317,7 @@ export const loadDatasourceReady = (
|
||||
instance: DataSourceApi,
|
||||
orgId: number
|
||||
): PayloadAction<LoadDatasourceReadyPayload> => {
|
||||
const historyKey = `grafana.explore.history.${instance.meta.id}`;
|
||||
const historyKey = `grafana.explore.history.${instance.meta?.id}`;
|
||||
const history = store.getObject(historyKey, []);
|
||||
// Save last-used datasource
|
||||
|
||||
@@ -340,7 +340,7 @@ export const loadDatasourceReady = (
|
||||
export const importQueries = (
|
||||
exploreId: ExploreId,
|
||||
queries: DataQuery[],
|
||||
sourceDataSource: DataSourceApi,
|
||||
sourceDataSource: DataSourceApi | undefined,
|
||||
targetDataSource: DataSourceApi
|
||||
): ThunkResult<void> => {
|
||||
return async dispatch => {
|
||||
@@ -352,7 +352,7 @@ export const importQueries = (
|
||||
|
||||
let importedQueries = queries;
|
||||
// Check if queries can be imported from previously selected datasource
|
||||
if (sourceDataSource.meta.id === targetDataSource.meta.id) {
|
||||
if (sourceDataSource.meta?.id === targetDataSource.meta?.id) {
|
||||
// Keep same queries if same type of datasource
|
||||
importedQueries = [...queries];
|
||||
} else if (targetDataSource.importQueries) {
|
||||
@@ -701,18 +701,31 @@ export function splitClose(itemId: ExploreId): ThunkResult<void> {
|
||||
* The right state is automatically initialized.
|
||||
* The copy keeps all query modifications but wipes the query results.
|
||||
*/
|
||||
export function splitOpen(): ThunkResult<void> {
|
||||
return (dispatch, getState) => {
|
||||
export function splitOpen(dataSourceName?: string, query?: string): ThunkResult<void> {
|
||||
return async (dispatch, getState) => {
|
||||
// Clone left state to become the right state
|
||||
const leftState = getState().explore[ExploreId.left];
|
||||
const leftState: ExploreItemState = getState().explore[ExploreId.left];
|
||||
const rightState: ExploreItemState = {
|
||||
...leftState,
|
||||
};
|
||||
const queryState = getState().location.query[ExploreId.left] as string;
|
||||
const urlState = parseUrlState(queryState);
|
||||
const itemState: ExploreItemState = {
|
||||
...leftState,
|
||||
queries: leftState.queries.slice(),
|
||||
urlState,
|
||||
};
|
||||
dispatch(splitOpenAction({ itemState }));
|
||||
rightState.queries = leftState.queries.slice();
|
||||
rightState.urlState = urlState;
|
||||
dispatch(splitOpenAction({ itemState: rightState }));
|
||||
|
||||
if (dataSourceName && query) {
|
||||
// This is hardcoded for Jaeger right now
|
||||
const queries = [
|
||||
{
|
||||
query,
|
||||
refId: 'A',
|
||||
} as DataQuery,
|
||||
];
|
||||
await dispatch(changeDatasource(ExploreId.right, dataSourceName));
|
||||
await dispatch(setQueriesAction({ exploreId: ExploreId.right, queries }));
|
||||
}
|
||||
|
||||
dispatch(stateSave());
|
||||
};
|
||||
}
|
||||
@@ -757,7 +770,8 @@ const togglePanelActionCreator = (
|
||||
}
|
||||
|
||||
dispatch(actionCreator({ exploreId }));
|
||||
dispatch(updateExploreUIState(exploreId, uiFragmentStateUpdate));
|
||||
// The switch further up is exhaustive so uiFragmentStateUpdate should definitely be initialized
|
||||
dispatch(updateExploreUIState(exploreId, uiFragmentStateUpdate!));
|
||||
|
||||
if (shouldRunQueries) {
|
||||
dispatch(runQueries(exploreId));
|
||||
|
||||
@@ -599,6 +599,7 @@ export const updateChildRefreshState = (
|
||||
const getModesForDatasource = (dataSource: DataSourceApi, currentMode: ExploreMode): [ExploreMode[], ExploreMode] => {
|
||||
const supportsGraph = dataSource.meta.metrics;
|
||||
const supportsLogs = dataSource.meta.logs;
|
||||
const supportsTracing = dataSource.meta.tracing;
|
||||
|
||||
let mode = currentMode || ExploreMode.Metrics;
|
||||
const supportedModes: ExploreMode[] = [];
|
||||
@@ -611,13 +612,17 @@ const getModesForDatasource = (dataSource: DataSourceApi, currentMode: ExploreMo
|
||||
supportedModes.push(ExploreMode.Logs);
|
||||
}
|
||||
|
||||
if (supportsTracing) {
|
||||
supportedModes.push(ExploreMode.Tracing);
|
||||
}
|
||||
|
||||
if (supportedModes.length === 1) {
|
||||
mode = supportedModes[0];
|
||||
}
|
||||
|
||||
// HACK: Used to set Loki's default explore mode to Logs mode.
|
||||
// A better solution would be to introduce a "default" or "preferred" mode to the datasource config
|
||||
if (dataSource.meta.name === 'Loki' && !currentMode) {
|
||||
if (dataSource.meta.name === 'Loki' && (!currentMode || supportedModes.indexOf(currentMode) === -1)) {
|
||||
mode = ExploreMode.Logs;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,8 +54,8 @@ describe('getLinksFromLogsField', () => {
|
||||
};
|
||||
const links = getLinksFromLogsField(field, 2);
|
||||
expect(links.length).toBe(2);
|
||||
expect(links[0].href).toBe('http://domain.com/3');
|
||||
expect(links[1].href).toBe('http://anotherdomain.sk/3');
|
||||
expect(links[0].linkModel.href).toBe('http://domain.com/3');
|
||||
expect(links[1].linkModel.href).toBe('http://anotherdomain.sk/3');
|
||||
});
|
||||
|
||||
it('handles zero links', () => {
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
LinkModel,
|
||||
formattedValueToString,
|
||||
DisplayValue,
|
||||
DataLink,
|
||||
} from '@grafana/data';
|
||||
import { getLinkSrv } from './link_srv';
|
||||
import { getFieldDisplayValuesProxy } from './fieldDisplayValuesProxy';
|
||||
@@ -143,7 +144,10 @@ export const getPanelLinksSupplier = (value: PanelModel): LinkModelSupplier<Pane
|
||||
};
|
||||
};
|
||||
|
||||
export const getLinksFromLogsField = (field: Field, rowIndex: number): Array<LinkModel<Field>> => {
|
||||
export const getLinksFromLogsField = (
|
||||
field: Field,
|
||||
rowIndex: number
|
||||
): Array<{ linkModel: LinkModel<Field>; link: DataLink }> => {
|
||||
const scopedVars: any = {};
|
||||
scopedVars['__value'] = {
|
||||
value: {
|
||||
@@ -153,6 +157,11 @@ export const getLinksFromLogsField = (field: Field, rowIndex: number): Array<Lin
|
||||
};
|
||||
|
||||
return field.config.links
|
||||
? field.config.links.map(link => getLinkSrv().getDataLinkUIModel(link, scopedVars, field))
|
||||
? field.config.links.map(link => {
|
||||
return {
|
||||
link,
|
||||
linkModel: getLinkSrv().getDataLinkUIModel(link, scopedVars, field),
|
||||
};
|
||||
})
|
||||
: [];
|
||||
};
|
||||
@@ -13,6 +13,8 @@ const grafanaPlugin = async () =>
|
||||
const influxdbPlugin = async () =>
|
||||
await import(/* webpackChunkName: "influxdbPlugin" */ 'app/plugins/datasource/influxdb/module');
|
||||
const lokiPlugin = async () => await import(/* webpackChunkName: "lokiPlugin" */ 'app/plugins/datasource/loki/module');
|
||||
const jaegerPlugin = async () =>
|
||||
await import(/* webpackChunkName: "jaegerPlugin" */ 'app/plugins/datasource/jaeger/module');
|
||||
const mixedPlugin = async () =>
|
||||
await import(/* webpackChunkName: "mixedPlugin" */ 'app/plugins/datasource/mixed/module');
|
||||
const mysqlPlugin = async () =>
|
||||
@@ -64,6 +66,7 @@ const builtInPlugins: any = {
|
||||
'app/plugins/datasource/grafana/module': grafanaPlugin,
|
||||
'app/plugins/datasource/influxdb/module': influxdbPlugin,
|
||||
'app/plugins/datasource/loki/module': lokiPlugin,
|
||||
'app/plugins/datasource/jaeger/module': jaegerPlugin,
|
||||
'app/plugins/datasource/mixed/module': mixedPlugin,
|
||||
'app/plugins/datasource/mysql/module': mysqlPlugin,
|
||||
'app/plugins/datasource/postgres/module': postgresPlugin,
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import React from 'react';
|
||||
import { DataSourcePluginOptionsEditorProps } from '@grafana/data';
|
||||
import { DataSourceHttpSettings } from '@grafana/ui';
|
||||
|
||||
export type Props = DataSourcePluginOptionsEditorProps;
|
||||
|
||||
export const ConfigEditor: React.FC<Props> = ({ options, onOptionsChange }) => {
|
||||
return (
|
||||
<>
|
||||
<DataSourceHttpSettings
|
||||
defaultUrl={'http://localhost:16686'}
|
||||
dataSourceConfig={options}
|
||||
showAccessOptions={true}
|
||||
onChange={onOptionsChange}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,202 @@
|
||||
import React from 'react';
|
||||
import { JaegerDatasource, JaegerQuery } from './datasource';
|
||||
import { ButtonCascader, CascaderOption } from '@grafana/ui';
|
||||
|
||||
import { ExploreQueryFieldProps } from '@grafana/data';
|
||||
|
||||
const ALL_OPERATIONS_KEY = '__ALL__';
|
||||
const NO_TRACES_KEY = '__NO_TRACES__';
|
||||
|
||||
type Props = ExploreQueryFieldProps<JaegerDatasource, JaegerQuery>;
|
||||
interface State {
|
||||
serviceOptions: CascaderOption[];
|
||||
}
|
||||
|
||||
function getLabelFromTrace(trace: any): string {
|
||||
const firstSpan = trace.spans && trace.spans[0];
|
||||
if (firstSpan) {
|
||||
return `${firstSpan.operationName} [${firstSpan.duration} ms]`;
|
||||
}
|
||||
return trace.traceID;
|
||||
}
|
||||
|
||||
export class JaegerQueryField extends React.PureComponent<Props, State> {
|
||||
constructor(props: Props, context: React.Context<any>) {
|
||||
super(props, context);
|
||||
this.state = {
|
||||
serviceOptions: [],
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.getServices();
|
||||
}
|
||||
|
||||
async getServices() {
|
||||
const url = '/api/services';
|
||||
const { datasource } = this.props;
|
||||
try {
|
||||
const res = await datasource.metadataRequest(url);
|
||||
if (res) {
|
||||
const services = res as string[];
|
||||
const serviceOptions: CascaderOption[] = services.sort().map(service => ({
|
||||
label: service,
|
||||
value: service,
|
||||
isLeaf: false,
|
||||
}));
|
||||
this.setState({ serviceOptions });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
onLoadOptions = async (selectedOptions: CascaderOption[]) => {
|
||||
const service = selectedOptions[0].value;
|
||||
if (selectedOptions.length === 1) {
|
||||
// Load operations
|
||||
const operations: string[] = await this.findOperations(service);
|
||||
const allOperationsOption: CascaderOption = {
|
||||
label: '[ALL]',
|
||||
value: ALL_OPERATIONS_KEY,
|
||||
};
|
||||
const operationOptions: CascaderOption[] = [
|
||||
allOperationsOption,
|
||||
...operations.sort().map(operation => ({
|
||||
label: operation,
|
||||
value: operation,
|
||||
isLeaf: false,
|
||||
})),
|
||||
];
|
||||
this.setState(state => {
|
||||
const serviceOptions = state.serviceOptions.map(serviceOption => {
|
||||
if (serviceOption.value === service) {
|
||||
return {
|
||||
...serviceOption,
|
||||
children: operationOptions,
|
||||
};
|
||||
}
|
||||
return serviceOption;
|
||||
});
|
||||
return { serviceOptions };
|
||||
});
|
||||
} else if (selectedOptions.length === 2) {
|
||||
// Load traces
|
||||
const operationValue = selectedOptions[1].value;
|
||||
const operation = operationValue === ALL_OPERATIONS_KEY ? '' : operationValue;
|
||||
const traces: any[] = await this.findTraces(service, operation);
|
||||
let traceOptions: CascaderOption[] = traces.map(trace => ({
|
||||
label: getLabelFromTrace(trace),
|
||||
value: trace.traceID,
|
||||
}));
|
||||
if (traceOptions.length === 0) {
|
||||
traceOptions = [
|
||||
{
|
||||
label: '[No traces in time range]',
|
||||
value: NO_TRACES_KEY,
|
||||
},
|
||||
];
|
||||
}
|
||||
this.setState(state => {
|
||||
// Place new traces into the correct service/operation sub-tree
|
||||
const serviceOptions = state.serviceOptions.map(serviceOption => {
|
||||
if (serviceOption.value === service) {
|
||||
const operationOptions = serviceOption.children.map(operationOption => {
|
||||
if (operationOption.value === operationValue) {
|
||||
return {
|
||||
...operationOption,
|
||||
children: traceOptions,
|
||||
};
|
||||
}
|
||||
return operationOption;
|
||||
});
|
||||
return {
|
||||
...serviceOption,
|
||||
children: operationOptions,
|
||||
};
|
||||
}
|
||||
return serviceOption;
|
||||
});
|
||||
return { serviceOptions };
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
findOperations = async (service: string) => {
|
||||
const { datasource } = this.props;
|
||||
const url = `/api/services/${service}/operations`;
|
||||
try {
|
||||
return await datasource.metadataRequest(url);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
findTraces = async (service: string, operation?: string) => {
|
||||
const { datasource } = this.props;
|
||||
const { start, end } = datasource.getTimeRange();
|
||||
|
||||
const traceSearch = {
|
||||
start,
|
||||
end,
|
||||
service,
|
||||
operation,
|
||||
limit: 10,
|
||||
lookback: '1h',
|
||||
maxDuration: '',
|
||||
minDuration: '',
|
||||
};
|
||||
const url = '/api/traces';
|
||||
try {
|
||||
return await datasource.metadataRequest(url, traceSearch);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
onSelectTrace = (values: string[], selectedOptions: CascaderOption[]) => {
|
||||
const { query, onChange, onRunQuery } = this.props;
|
||||
if (selectedOptions.length === 3) {
|
||||
const traceID = selectedOptions[2].value;
|
||||
onChange({ ...query, query: traceID });
|
||||
onRunQuery();
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { query, onChange } = this.props;
|
||||
const { serviceOptions } = this.state;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="gf-form-inline gf-form-inline--nowrap">
|
||||
<div className="gf-form flex-shrink-0">
|
||||
<ButtonCascader options={serviceOptions} onChange={this.onSelectTrace} loadData={this.onLoadOptions}>
|
||||
Traces
|
||||
</ButtonCascader>
|
||||
</div>
|
||||
<div className="gf-form gf-form--grow flex-shrink-1">
|
||||
<div className={'slate-query-field__wrapper'}>
|
||||
<div className="slate-query-field">
|
||||
<input
|
||||
style={{ width: '100%' }}
|
||||
value={query.query || ''}
|
||||
onChange={e =>
|
||||
onChange({
|
||||
...query,
|
||||
query: e.currentTarget.value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default JaegerQueryField;
|
||||
@@ -0,0 +1,85 @@
|
||||
import {
|
||||
dateMath,
|
||||
DateTime,
|
||||
MutableDataFrame,
|
||||
DataSourceApi,
|
||||
DataSourceInstanceSettings,
|
||||
DataQueryRequest,
|
||||
DataQueryResponse,
|
||||
DataQuery,
|
||||
} from '@grafana/data';
|
||||
import { getBackendSrv } from '@grafana/runtime';
|
||||
|
||||
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||
import { DatasourceRequestOptions } from 'app/core/services/backend_srv';
|
||||
import { serializeParams } from '../../../core/utils/fetch';
|
||||
|
||||
import { Observable, from, of } from 'rxjs';
|
||||
|
||||
export type JaegerQuery = {
|
||||
query: string;
|
||||
} & DataQuery;
|
||||
|
||||
export class JaegerDatasource extends DataSourceApi<JaegerQuery> {
|
||||
constructor(private instanceSettings: DataSourceInstanceSettings) {
|
||||
super(instanceSettings);
|
||||
}
|
||||
|
||||
_request(apiUrl: string, data?: any, options?: DatasourceRequestOptions): Observable<Record<string, any>> {
|
||||
// Hack for proxying metadata requests
|
||||
const baseUrl = `/api/datasources/proxy/${this.instanceSettings.id}`;
|
||||
const params = data ? serializeParams(data) : '';
|
||||
const url = `${baseUrl}${apiUrl}${params.length ? `?${params}` : ''}`;
|
||||
const req = {
|
||||
...options,
|
||||
url,
|
||||
};
|
||||
|
||||
return from(getBackendSrv().datasourceRequest(req));
|
||||
}
|
||||
|
||||
async metadataRequest(url: string, params?: Record<string, any>) {
|
||||
const res = await this._request(url, params, { silent: true }).toPromise();
|
||||
return res.data.data;
|
||||
}
|
||||
|
||||
query(options: DataQueryRequest<JaegerQuery>): Observable<DataQueryResponse> {
|
||||
//http://localhost:16686/search?end=1573338717880000&limit=20&lookback=6h&maxDuration&minDuration&service=app&start=1573317117880000
|
||||
const url =
|
||||
options.targets.length && options.targets[0].query
|
||||
? `${this.instanceSettings.url}/trace/${options.targets[0].query}?uiEmbed=v0`
|
||||
: '';
|
||||
|
||||
return of({
|
||||
data: [
|
||||
new MutableDataFrame({
|
||||
fields: [
|
||||
{
|
||||
name: 'url',
|
||||
values: [url],
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
async testDatasource(): Promise<any> {
|
||||
return true;
|
||||
}
|
||||
|
||||
getTime(date: string | DateTime, roundUp: boolean) {
|
||||
if (typeof date === 'string') {
|
||||
date = dateMath.parse(date, roundUp);
|
||||
}
|
||||
return date.valueOf() * 1000;
|
||||
}
|
||||
|
||||
getTimeRange(): { start: number; end: number } {
|
||||
const range = getTimeSrv().timeRange();
|
||||
return {
|
||||
start: this.getTime(range.from, false),
|
||||
end: this.getTime(range.to, true),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="svg3941"
|
||||
xml:space="preserve"
|
||||
width="886.66669"
|
||||
height="1013.3333"
|
||||
viewBox="0 0 886.66669 1013.3333"
|
||||
sodipodi:docname="Jaeger_Logo_Final_PANTONE REVERSE.svg"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)"><metadata
|
||||
id="metadata3947"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs3945" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1016"
|
||||
id="namedview3943"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.73437691"
|
||||
inkscape:cx="535.56442"
|
||||
inkscape:cy="530.61636"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g3949" /><g
|
||||
id="g3949"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="ink_ext_XXXXXX"
|
||||
transform="matrix(1.3333333,0,0,-1.3333333,0,1013.3333)"><g
|
||||
id="g3951"
|
||||
transform="matrix(0.11564109,0,0,0.11564109,-51.116401,-60.457467)"><path
|
||||
d="m 2671.93,2504.33 c 32.47,-61.24 75.27,-113.74 127.39,-113.74 10.62,0 21.57,2.16 32.87,6.84 53.5,22.09 55.85,115.25 43.49,204.99 -77.04,-24.64 -144.33,-62.43 -203.75,-98.09"
|
||||
style="fill:#78d3e0;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3953"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 3652.56,3440.03 c -105.48,0 -204.11,29.37 -288.16,80.37 -160.74,97.53 -268.13,274.18 -268.13,475.93 0,307.23 249.06,556.3 556.29,556.3 105.93,0 204.93,-29.63 289.21,-81.02 160.15,-97.66 267.09,-273.98 267.09,-475.28 0,-307.23 -249.07,-556.3 -556.3,-556.3 z m -74.23,-779.49 c -57.39,-24.91 -141.23,-35.96 -273.54,-37.14 0.51,-11.76 1.01,-22.53 1.59,-30.59 5.71,-75.82 -12.28,-136.77 -53.46,-181.13 -37.2,-40.13 -91.16,-62.24 -151.92,-62.24 -27.41,0 -54.47,4.49 -76.21,12.64 -23.55,8.84 -44.03,24.5 -62.67,48.6 -17.38,-49.77 -48.33,-84.2 -92.97,-102.65 -22.76,-9.39 -46.24,-14.15 -69.83,-14.15 -82.21,0 -152.5,55.71 -210.07,161.77 -7.48,-4.3 -16.33,-9.9 -23.33,-13.67 -39.59,-21.25 -87.96,-32.47 -139.86,-32.47 -97.56,0 -188.98,38.07 -244.61,101.84 -45.26,51.88 -64.87,118.96 -55.3,188.9 29.33,213.17 311.14,299.71 343.18,308.88 l 65.63,18.78 43.71,-52.44 c 5.31,-6.34 37.78,-38 157.99,-38 45.47,0 98.1,4.64 156.43,13.8 192.92,30.26 267.44,184.75 271.81,194.16 l 27.41,62.87 69.28,-0.57 c 419.03,-3.45 483.22,-187.43 492.9,-243.85 22.61,-132.29 -43.27,-245.68 -176.16,-303.34 z m -1937.94,458.92 c -160.74,97.53 -268.14,274.18 -268.14,475.93 0,307.24 249.06,556.3 556.3,556.3 105.93,0 204.93,-29.62 289.2,-81.01 160.16,-97.67 267.09,-273.98 267.09,-475.29 0,-307.23 -249.06,-556.29 -556.29,-556.29 -105.49,0 -204.11,29.36 -288.16,80.36 z m 3691.96,-918.85 c -0.17,1.08 -0.38,2.35 -0.51,3.3 -22.33,163.72 -92.16,237.16 -153.77,301.97 -57.36,60.34 -111.56,117.34 -94.11,221.99 16.13,96.74 93.09,156.26 218.85,171.75 -76.38,516.24 -188.3,1167.54 -332.18,1723.17 -71.84,277.49 -185.48,470.23 -337.88,598.37 -174.4,-89.22 -384.19,-187.3 -618.36,-288.84 -169.21,-73.37 -343.91,-145.25 -510.04,-210.56 -133.74,-143.49 -279.87,-284.91 -369.43,-325.21 -63.76,-28.69 -120.42,-40.11 -169.67,-40.11 -106.62,0 -178.6,53.48 -213.45,101.04 -40.39,-10.67 -72.66,-17.59 -94.61,-19.91 -26.25,-2.76 -64.92,-6.04 -113.3,-9.53 18.59,-48.67 11.19,-105.66 -24.46,-148.6 -39.21,-47.23 -102.39,-70.96 -191.93,-70.96 -128.84,0 -312.28,49.14 -557.55,148.21 -36.09,14.57 -69.22,27.52 -99.65,39.07 -18.78,-0.1 -37.56,-0.17 -56.33,-0.17 -0.05,0 -0.11,0 -0.17,0 -234.33,0.01 -417.46,7.37 -561.02,19.13 -157.233,-325.48 -88.905,-686.49 -31.35,-984.71 55.15,-285.79 246.5,-794.3 423.98,-1231.21 65.85,-162.09 129.76,-314.28 184.13,-441.63 480.48,-42.5 1096.51,-68.03 1768.21,-68.03 799.34,0 1519.36,36.21 2026.38,94.09 -36.94,152.03 -83.74,363.57 -91.78,417.38"
|
||||
style="fill:#78d3e0;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3955"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 3260.73,3102.88 c 0,0 -93.7,-214.77 -351.38,-255.19 -67.15,-10.54 -124.22,-15.07 -172.69,-15.07 -137.51,0 -205.78,36.48 -238.51,75.7 0,0 -247.28,-70.74 -268.12,-222.35 -15.56,-113.36 96.95,-171.62 196.03,-171.62 33.45,0 65.34,6.64 90.3,20.02 98.93,53.06 247.24,169.29 445.04,194.55 17.88,2.29 42.58,3.09 71.91,3.08 67.69,0 159.94,-4.24 249.38,-4.24 101.71,0 199.81,5.5 253.92,28.97 122.31,53.06 122.31,144.02 114.54,189.49 -8.67,50.41 -83.33,154.14 -390.42,156.66"
|
||||
style="fill:#78d3e0;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3957"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 3207.99,2624.15 c -23.33,0.44 -47.39,0.58 -69.64,1.14 -38.4,0.96 -74.3,1.87 -105.04,1.87 -23.55,0 -43.27,-0.4 -57.76,-2.2 22.72,-81.15 52.49,-160.81 83.19,-172.32 8.78,-3.28 24.35,-6.48 42.26,-6.48 49.7,0 117.57,24.49 108.94,139.42 -0.76,10.23 -1.37,23.86 -1.95,38.57"
|
||||
style="fill:#78d3e0;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3959"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="M 1902.38,1168.94 C 1807.16,1147.18 1526.94,994.828 1284.81,948.57 1042.68,902.32 833.188,877.84 759.734,850.629 686.281,823.43 629.145,769.02 773.34,714.602 c 144.191,-54.411 843.38,-73.454 905.95,0 62.58,73.461 -43.15,105.296 -195.88,103.39 -108.82,-1.363 -95.47,36.559 -95.22,40.809 0,0 6.8,47.609 174.12,70.73 167.04,23.09 905.95,92.499 892.35,171.399 -13.6,78.89 -457.06,89.78 -552.28,68.01"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3961"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 1413.91,627.941 c -78.18,-17.011 -137.54,-49.25 -132.59,-72.011 4.95,-22.75 72.35,-27.41 150.52,-10.399 78.18,17.02 137.55,49.25 132.6,72.008 -4.96,22.762 -72.35,27.41 -150.53,10.402"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3963"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 1084.33,646.461 c -83.88,-6.672 -150.428,-30.301 -148.639,-52.77 1.789,-22.472 71.239,-35.269 155.109,-28.589 83.88,6.679 150.43,30.308 148.64,52.769 -1.79,22.469 -71.24,35.27 -155.11,28.59"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3965"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="M 815.273,670.781 C 759.445,663.18 716.117,642.832 718.5,625.34 c 2.383,-17.488 49.57,-25.512 105.402,-17.91 55.828,7.609 99.157,27.949 96.774,45.449 -2.383,17.492 -49.574,25.512 -105.403,17.902"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3967"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 617.953,695.289 c -53.906,-7.82 -95.937,-25.617 -93.887,-39.738 2.051,-14.129 47.411,-19.242 101.313,-11.41 53.902,7.82 95.934,25.621 93.883,39.738 -2.051,14.133 -47.407,19.242 -101.309,11.41"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3969"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 580.488,699.91 c 53.903,7.82 95.938,25.621 93.887,39.75 -2.055,14.121 -47.41,19.231 -101.312,11.399 -53.903,-7.821 -95.934,-25.618 -93.887,-39.739 2.051,-14.129 47.41,-19.238 101.312,-11.41"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3971"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 568.273,766.32 c 46.856,6.801 83.399,22.27 81.614,34.551 -1.782,12.277 -41.215,16.719 -88.071,9.918 -46.859,-6.809 -83.402,-22.277 -81.621,-34.547 1.782,-12.293 41.215,-16.73 88.078,-9.922"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3973"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 3355.18,1092.77 c -165.96,-8.16 -541.4,10.88 -593.09,-76.18 -51.69,-87.059 152.35,-119.711 473.38,-92.5 321.03,27.211 775.37,62.57 794.41,160.52 19.05,97.94 -84.34,78.89 -95.22,141.46 -10.88,62.58 114.27,62.58 138.75,155.08 24.49,92.5 -168.68,81.62 -340.07,81.62 -171.4,0 -457.06,-16.33 -484.27,-106.11 -27.2,-89.78 130.59,-89.78 242.14,-111.54 111.54,-21.76 78.89,-62.57 78.89,-62.57 -5.44,-57.14 -48.97,-81.62 -214.92,-89.78"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3975"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 2911.38,900.969 c -79.45,0 -143.85,-21.02 -143.85,-46.93 0,-25.918 64.4,-46.93 143.85,-46.93 79.45,0 143.85,21.012 143.85,46.93 0,25.91 -64.4,46.93 -143.85,46.93"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3977"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 3281.72,907.09 c -52.96,0 -95.9,-19.192 -95.9,-42.848 0,-23.672 42.94,-42.851 95.9,-42.851 52.97,0 95.9,19.179 95.9,42.851 0,23.656 -42.93,42.848 -95.9,42.848"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3979"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 3580.64,929.531 c -58.03,0 -105.08,-15.531 -105.08,-34.691 0,-19.149 47.05,-34.68 105.08,-34.68 58.04,0 105.09,15.531 105.09,34.68 0,19.16 -47.05,34.691 -105.09,34.691"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3981"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 3811.21,970.34 c -42.25,0 -76.51,-16.438 -76.51,-36.731 0,-20.277 34.26,-36.73 76.51,-36.73 42.26,0 76.52,16.453 76.52,36.73 0,20.293 -34.26,36.731 -76.52,36.731"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3983"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 4010.16,1011.15 c -42.83,0 -77.54,-15.99 -77.54,-35.709 0,-19.722 34.71,-35.711 77.54,-35.711 42.82,0 77.53,15.989 77.53,35.711 0,19.719 -34.71,35.709 -77.53,35.709"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3985"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 627.063,1978.65 c 0,-46.39 101.183,-90.26 280.898,-129.29 -12.801,93.08 -4.891,186.96 7.102,260.1 -184.153,-39.42 -288,-83.82 -288,-130.81"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3987"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 5930.11,2098.84 c -2.72,-7.53 -5.62,-14.97 -8.74,-22.28 -22.1,-51.7 -53.82,-97.35 -94.26,-135.66 -81.18,-76.89 -152.35,-122.96 -215.93,-139.76 351.23,49.36 559.72,110.84 559.72,177.51 0,42.82 -86.24,83.49 -240.79,120.19"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3989"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 1240.47,1605.14 c 130.42,0 222.25,71 286.69,163.12 -73.75,171.04 -195.11,459.23 -310.18,762.53 -31.15,-26.5 -67.14,-66.51 -106.08,-126.87 -96.95,-150.26 -176.798,-499.88 -76.24,-684.41 41.92,-76.97 109.26,-114.37 205.81,-114.37"
|
||||
style="fill:#dec795;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3991"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 5844.76,2471.43 c -76.45,197.81 -239.03,338.23 -395.36,341.49 l -5.59,0.49 c -0.25,0.04 -30.29,4.52 -70.65,4.52 -85.15,0 -189.66,-18.18 -204.09,-104.72 -10.02,-60.05 16.25,-90.81 71.81,-149.25 63.49,-66.76 150.41,-158.2 176.46,-349.18 29.82,-218.71 83.22,-329.62 158.69,-329.64 h 0.01 c 35.24,0 99.52,21.13 205.78,121.78 130.85,123.97 118.31,321.23 62.94,464.51"
|
||||
style="fill:#dec795;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3993"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 3753.83,3810.25 c 0,-96.87 -78.53,-175.41 -175.41,-175.41 -96.87,0 -175.4,78.54 -175.4,175.41 0,96.88 78.53,175.41 175.4,175.41 96.88,0 175.41,-78.53 175.41,-175.41 z m -656.53,185.43 c 0,-201.3 106.94,-377.62 267.1,-475.28 84.05,-51 182.68,-80.37 288.16,-80.37 307.23,0 556.3,249.07 556.3,556.3 0,201.3 -106.94,377.62 -267.09,475.28 -84.05,51 -182.68,80.37 -288.17,80.37 -307.23,0 -556.3,-249.06 -556.3,-556.3"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3995"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 2054.87,3399.29 c 0,-96.87 -78.53,-175.4 -175.41,-175.4 -96.87,0 -175.41,78.53 -175.41,175.4 0,96.88 78.54,175.41 175.41,175.41 96.88,0 175.41,-78.53 175.41,-175.41 z m -681.59,195.46 c 0,-201.31 106.95,-377.63 267.11,-475.29 84.05,-51 182.67,-80.36 288.16,-80.36 307.23,0 556.29,249.06 556.29,556.29 0,201.31 -106.93,377.62 -267.09,475.29 -84.05,51 -182.68,80.37 -288.17,80.37 -307.23,0 -556.3,-249.07 -556.3,-556.3"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3997"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 1704.05,3399.29 c 0,-96.87 78.54,-175.4 175.41,-175.4 96.88,0 175.41,78.53 175.41,175.4 0,96.88 -78.53,175.41 -175.41,175.41 -96.87,0 -175.41,-78.53 -175.41,-175.41"
|
||||
style="fill:#211c1d;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path3999"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 3403.02,3810.25 c 0,-96.87 78.53,-175.41 175.4,-175.41 96.88,0 175.41,78.54 175.41,175.41 0,96.88 -78.53,175.41 -175.41,175.41 -96.87,0 -175.4,-78.53 -175.4,-175.41"
|
||||
style="fill:#211c1d;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4001"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 1396.75,4482.59 c -19.42,4.05 -30.3,5.3 -34.76,5.67 -74.01,-4.57 -141.85,47.19 -155.52,122.25 -1.39,7.63 -1.98,15.2 -2.19,22.72 -40.26,-22.84 -80.55,-47.55 -118.26,-73.65 l -67.06,-46.43 -49.339,64.96 c -14.867,19.57 -83.508,112.19 -146.766,234.02 -118.808,-56.06 -211.628,-117.35 -234.285,-175.41 -4.289,-10.99 -2.554,-16.93 1.895,-23.45 19.394,-28.38 134.422,-115.17 806.285,-130.68"
|
||||
style="fill:#588e2f;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4003"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 4575.9,5583.11 c -22.32,-133.03 -65.22,-279.06 -93.67,-318.9 l -26.7,-37.35 c 120.88,58.85 228.71,114.68 320.24,166 318.25,178.44 357.82,256.58 362.37,276.29 2.98,12.9 -0.19,16.88 -1.54,18.59 -3.47,4.34 -25.81,26.03 -126.33,26.03 -109.85,0 -263.63,-25.12 -424.12,-59.95 -2.79,-22.91 -6.18,-46.46 -10.25,-70.71"
|
||||
style="fill:#588e2f;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4005"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 4451.83,5225.06 -45.9,3.74 c -0.84,0.07 -85.1,6.82 -199.36,6.82 -118.71,0 -275.22,-7.16 -403.66,-37.57 24.52,-50.97 18.97,-113.7 -19.55,-160.04 -31.48,-37.89 -84.66,-101.04 -148.35,-173.48 112.97,45.85 229.54,94.62 346.5,145.34 171.58,74.39 329.74,146.83 470.32,215.19"
|
||||
style="fill:#588e2f;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4007"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 1403.64,5358.88 c 136.88,-36.95 291.64,-55.68 459.99,-55.68 654.08,0 1373.77,283.13 1652.83,404.86 l 17.66,7.7 c -2.7,42.07 0.91,87.42 10.91,132.9 17.89,81.42 53.35,150.41 96.9,196.11 -8.4,31.22 -15.31,54.03 -20.13,65.61 -93.14,49.65 -861.11,335.72 -1261.61,335.72 -40.01,0 -74.95,-2.98 -103.85,-8.89 -354.96,-72.44 -894.3,-689.51 -913.67,-776.99 -5.81,-37.84 -4.05,-156.66 0.2,-284.94 l 60.77,-16.4"
|
||||
style="fill:#588e2f;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4009"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 2791.69,4672.82 c 59,37.56 134.37,28.46 182.85,-17.68 7.47,1.18 20.17,4.36 39,12.84 73.54,34.95 338.83,318.17 540.36,560.7 7.25,8.72 15.33,16.32 23.97,22.91 C 3117.3,5052.58 2473.75,4835.08 1861,4835.08 c -98.49,0 -192,5.75 -278.81,16.98 l 13.45,-39.61 -76.62,-29.35 c -0.56,-0.22 -13.73,-5.3 -35.76,-14.46 98.63,-23.04 231.97,-68.34 399.43,-135.98 306.53,-123.79 423.76,-128.51 453.09,-126.77 41.69,22.09 92.06,22.95 135.17,1.89 79.51,5.09 141.36,10.02 178.36,13.92 16.82,1.77 41.82,7 73.63,15.22 -3.51,52.66 21.08,105.57 68.75,135.9"
|
||||
style="fill:#588e2f;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4011"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 3550.54,5629.93 c -8.93,-3.9 -18.27,-7.93 -27.79,-12.02 -2.06,-0.88 -4.09,-1.76 -6.17,-2.65 -9.5,-4.07 -19.23,-8.21 -29.28,-12.45 -1.67,-0.7 -3.38,-1.42 -5.07,-2.13 -9.2,-3.87 -18.63,-7.8 -28.26,-11.79 -1.87,-0.78 -3.69,-1.54 -5.57,-2.31 -10.67,-4.41 -21.62,-8.89 -32.79,-13.43 -2.35,-0.96 -4.73,-1.92 -7.11,-2.88 -11.45,-4.64 -23.08,-9.32 -35.03,-14.07 -0.22,-0.08 -0.42,-0.17 -0.64,-0.25 -11.99,-4.77 -24.32,-9.6 -36.8,-14.47 -2.68,-1.04 -5.36,-2.09 -8.07,-3.14 -12.41,-4.82 -25.02,-9.67 -37.88,-14.56 -1.87,-0.71 -3.78,-1.43 -5.67,-2.14 -11.93,-4.52 -24.05,-9.07 -36.34,-13.65 -2.28,-0.84 -4.52,-1.69 -6.82,-2.54 -13.35,-4.94 -26.93,-9.91 -40.68,-14.89 -2.82,-1.03 -5.66,-2.05 -8.5,-3.07 -13.79,-4.97 -27.72,-9.95 -41.89,-14.93 -0.53,-0.19 -1.06,-0.38 -1.6,-0.57 -14.47,-5.09 -29.19,-10.18 -44.05,-15.27 -3.13,-1.08 -6.26,-2.15 -9.41,-3.23 -14.79,-5.03 -29.72,-10.07 -44.85,-15.08 -2.01,-0.67 -4.04,-1.33 -6.05,-1.99 -13.94,-4.61 -28.02,-9.19 -42.24,-13.76 -2.85,-0.92 -5.69,-1.84 -8.55,-2.76 -15.38,-4.92 -30.91,-9.81 -46.59,-14.67 -3.19,-0.99 -6.39,-1.97 -9.59,-2.95 -15.41,-4.75 -30.92,-9.46 -46.59,-14.13 -0.98,-0.3 -1.94,-0.59 -2.92,-0.88 -16.28,-4.84 -32.74,-9.63 -49.29,-14.37 -3.56,-1.02 -7.12,-2.04 -10.69,-3.05 -16.51,-4.7 -33.11,-9.35 -49.87,-13.93 -2.06,-0.56 -4.14,-1.11 -6.2,-1.67 -15.57,-4.23 -31.24,-8.4 -47,-12.52 -3.08,-0.8 -6.15,-1.61 -9.23,-2.41 -16.9,-4.38 -33.9,-8.68 -51,-12.91 -3.44,-0.84 -6.88,-1.68 -10.32,-2.52 -16.45,-4.02 -32.96,-7.99 -49.57,-11.85 -1.42,-0.33 -2.83,-0.68 -4.25,-1.01 -17.49,-4.05 -35.09,-7.98 -52.74,-11.84 -3.85,-0.84 -7.69,-1.68 -11.55,-2.51 -17.65,-3.81 -35.35,-7.54 -53.14,-11.14 -2.04,-0.41 -4.08,-0.8 -6.12,-1.21 -16.5,-3.31 -33.05,-6.5 -49.65,-9.62 -3.49,-0.65 -6.96,-1.31 -10.44,-1.96 -17.72,-3.27 -35.49,-6.42 -53.3,-9.44 -3.58,-0.61 -7.17,-1.2 -10.76,-1.8 -16.87,-2.81 -33.77,-5.53 -50.71,-8.11 -1.88,-0.29 -3.76,-0.59 -5.64,-0.88 -18.07,-2.72 -36.18,-5.27 -54.32,-7.71 -4.04,-0.54 -8.07,-1.08 -12.12,-1.6 -18.19,-2.39 -36.41,-4.65 -54.65,-6.73 -1.86,-0.21 -3.73,-0.39 -5.59,-0.6 -17.01,-1.9 -34.02,-3.65 -51.04,-5.27 -3.68,-0.35 -7.36,-0.71 -11.03,-1.05 -18,-1.64 -36.01,-3.13 -54,-4.44 -3.59,-0.26 -7.18,-0.49 -10.77,-0.74 -16.85,-1.16 -33.69,-2.19 -50.52,-3.04 -2.17,-0.11 -4.34,-0.25 -6.51,-0.36 -18.12,-0.87 -36.21,-1.51 -54.28,-2.01 -4.06,-0.11 -8.12,-0.21 -12.18,-0.3 -18.18,-0.41 -36.35,-0.68 -54.46,-0.69 -0.39,0 -0.78,-0.02 -1.17,-0.02 -1.18,0 -2.36,0.05 -3.54,0.05 -17.34,0.03 -34.63,0.28 -51.89,0.69 -3.59,0.09 -7.19,0.15 -10.78,0.25 -17.94,0.52 -35.83,1.25 -53.66,2.2 -3.54,0.19 -7.07,0.42 -10.61,0.63 -17.15,1 -34.26,2.18 -51.29,3.6 -1.55,0.13 -3.1,0.23 -4.65,0.36 -17.92,1.55 -35.75,3.4 -53.52,5.43 -3.88,0.45 -7.76,0.9 -11.64,1.36 -17.61,2.13 -35.15,4.46 -52.59,7.09 -2.43,0.37 -4.84,0.78 -7.26,1.16 -16.15,2.5 -32.22,5.25 -48.21,8.2 -3.02,0.56 -6.05,1.08 -9.07,1.65 -17.12,3.26 -34.12,6.82 -51.03,10.62 -3.57,0.8 -7.12,1.64 -10.68,2.46 -17.37,4.03 -34.66,8.25 -51.78,12.87 v 0 c 15.94,-24.13 31.74,-49.88 47.37,-77.34 56.81,-99.78 98.37,-198.36 121,-256.53 9.85,-1.54 20.08,-3.05 30.68,-4.5 3.4,-0.46 7.07,-0.89 10.55,-1.34 7.37,-0.97 14.7,-1.94 22.42,-2.84 4.17,-0.49 8.63,-0.93 12.9,-1.4 7.36,-0.81 14.63,-1.64 22.28,-2.39 4.87,-0.47 10.05,-0.88 15.05,-1.33 7.41,-0.67 14.71,-1.36 22.39,-1.96 5.49,-0.43 11.3,-0.78 16.93,-1.18 7.53,-0.52 14.94,-1.08 22.72,-1.54 6.03,-0.36 12.37,-0.62 18.55,-0.93 7.76,-0.4 15.42,-0.82 23.41,-1.14 6.45,-0.26 13.21,-0.41 19.81,-0.61 8.08,-0.25 16.07,-0.54 24.38,-0.71 6.9,-0.14 14.1,-0.17 21.16,-0.25 8.4,-0.1 16.69,-0.23 25.3,-0.24 0.91,0 1.76,-0.03 2.67,-0.03 13.07,0 26.45,0.13 40.03,0.35 3.51,0.05 7.12,0.15 10.66,0.23 11.55,0.23 23.27,0.54 35.18,0.93 4.76,0.16 9.54,0.33 14.36,0.52 12.51,0.48 25.22,1.06 38.12,1.74 3.35,0.17 6.62,0.31 10,0.5 16.07,0.9 32.47,1.97 49.14,3.18 4.16,0.31 8.42,0.67 12.62,0.99 13.01,1.01 26.18,2.11 39.55,3.32 5.34,0.48 10.69,0.98 16.08,1.49 14.44,1.38 29.08,2.89 43.92,4.52 3.43,0.38 6.77,0.7 10.22,1.09 18.09,2.05 36.53,4.3 55.22,6.73 4.84,0.63 9.78,1.33 14.66,1.99 14.41,1.93 28.98,3.98 43.74,6.16 5.98,0.88 11.97,1.77 18.01,2.69 16.46,2.51 33.14,5.17 50.02,7.99 3.39,0.57 6.69,1.08 10.09,1.65 20.13,3.42 40.61,7.09 61.35,10.97 5.49,1.02 11.08,2.13 16.62,3.18 15.89,3.04 31.95,6.22 48.19,9.53 6.54,1.33 13.08,2.67 19.67,4.05 18.59,3.89 37.41,7.96 56.46,12.22 3.28,0.73 6.48,1.41 9.77,2.15 22.12,5.01 44.61,10.32 67.34,15.85 6.28,1.52 12.65,3.14 18.97,4.7 17.26,4.28 34.68,8.71 52.27,13.29 7.18,1.87 14.35,3.73 21.58,5.65 21,5.58 42.22,11.36 63.71,17.39 2.83,0.8 5.6,1.53 8.45,2.34 24.19,6.83 48.76,14.03 73.56,21.45 6.98,2.09 14.06,4.28 21.09,6.42 18.72,5.69 37.62,11.55 56.68,17.59 7.74,2.45 15.45,4.89 23.24,7.39 23.62,7.6 47.46,15.43 71.6,23.57 2.23,0.75 4.4,1.45 6.64,2.2 26.25,8.9 52.9,18.2 79.77,27.75 7.69,2.74 15.48,5.57 23.23,8.36 20.22,7.28 40.6,14.76 61.17,22.42 8.26,3.08 16.5,6.14 24.82,9.28 26.48,10 53.18,20.25 80.23,30.9 1.4,0.54 2.75,1.05 4.15,1.61 28.32,11.17 57.04,22.81 85.98,34.71 8.4,3.45 16.89,7.01 25.34,10.53 21.Line truncated
|
||||
style="fill:#dec795;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4013"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 1864.8,5217.98 c -1.57,0 -3.14,0.03 -4.71,0.03 1.18,0 2.36,-0.05 3.54,-0.05 0.39,0 0.78,0.02 1.17,0.02"
|
||||
style="fill:#588e2f;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4015"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 1018.35,5494.06 h -0.01 l 0.01,-42.62 z"
|
||||
style="fill:#78d3e0;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4017"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 3785.29,6101.17 c 51.98,-11.42 91.37,-55.46 110.95,-123.96 3.12,-10.96 5.5,-22.52 7.5,-34.33 119.4,168.02 249.63,252.97 388.85,252.97 58.58,0 110.01,-13.8 153.14,-40.47 73.34,89.18 120,150.69 120,150.69 -55.13,-10.02 -170.4,-25.06 -170.4,-25.06 436.01,160.38 400.93,596.39 400.93,596.39 0,-75.17 -225.52,-255.59 -225.52,-255.59 10.02,65.15 -25.06,150.35 -25.06,150.35 10.02,-85.2 -260.61,-305.72 -260.61,-305.72 20.05,40.1 5.01,110.26 5.01,110.26 -15.03,-80.19 -135.31,-110.26 -135.31,-110.26 75.17,90.21 215.5,566.33 110.25,596.4 -105.24,30.06 -250.58,-310.73 -250.58,-310.73 -5.01,80.19 -50.12,80.19 -50.12,80.19 20.05,-250.59 -180.42,-451.05 -180.42,-451.05 -15.03,50.11 -95.22,75.17 -95.22,75.17 18.64,-40.39 8.39,-184.76 -2.09,-288.69 -4,-39.57 -8,-73.14 -10.48,-93 26.6,18.78 55.04,29.2 83.64,29.2 8.6,0 17.2,-0.92 25.54,-2.76"
|
||||
style="fill:#dec795;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4019"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 3675.53,5601.9 c 16.37,-3.62 36.26,5.07 56.1,23.61 13.18,30.75 27.34,62.15 42.53,93.64 13.99,29 28.16,56.65 42.51,83.02 10.33,54.85 9.63,109.48 -2.41,151.63 -10.25,35.9 -27.91,59.86 -47.26,64.12 -2.38,0.53 -4.76,0.78 -7.25,0.78 -43.49,0 -106.7,-75.68 -131.47,-188.34 -12.98,-59.03 -13,-118.94 -0.03,-164.34 10.25,-35.9 27.92,-59.86 47.28,-64.12"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4021"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 4297.65,5829.03 -0.97,0.46 -0.45,0.2 c 0.07,-0.09 0.12,-0.2 0.2,-0.28 0.04,-0.02 0.07,-0.09 0.11,-0.11 0.21,-0.09 0.42,-0.18 0.65,-0.22 l 0.46,-0.05"
|
||||
style="fill:#78d3e0;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4023"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 4378.39,5804.7 c -2.39,-29.65 -10.07,-54.09 -18.43,-76.25 -8.51,-22.11 -18.16,-41.71 -27.78,-59.26 -19.36,-35.02 -38.84,-61.72 -53.31,-79.81 -14.34,-18.14 -23.87,-27.54 -23.87,-27.54 0,0 3.02,13.01 8.7,35.1 5.47,22.16 13.76,53.42 22.44,90.17 4.3,18.34 8.62,38.12 11.99,58.52 3.48,20.28 5.71,41.7 4.67,60.26 -0.82,8.99 -2.51,17.11 -4.8,21.21 -0.46,1.06 -0.94,1.86 -1.46,2.2 -0.07,0.02 -0.14,0.03 -0.2,0.06 -0.26,0.13 -0.4,0.38 -0.6,0.56 l -3.36,1.55 -10.68,2.88 c -4.53,1.47 -8.89,1.41 -13.29,2.49 -4.39,0.79 -8.62,0.3 -12.92,0.76 -4.23,-0.36 -8.41,-0.76 -12.6,-1.27 -16.63,-2.68 -33.31,-10.8 -49.63,-22.65 -16.19,-11.99 -31.54,-27.5 -45.51,-44.14 -27.9,-33.56 -50.92,-70.59 -70.19,-102.9 -19.12,-32.52 -34.64,-60.78 -45.7,-80.69 -11.09,-20.13 -17.42,-31.63 -17.42,-31.63 0,0 -0.19,3.34 -0.09,9.56 0.25,6.18 0.17,15.41 1.35,26.89 1.81,23.12 6.17,56.01 16.44,94.71 10.48,38.59 26.33,83.33 54.52,128.2 14.19,22.31 31.68,44.81 54.99,64.45 22.97,19.69 53.12,36.24 87.3,42.26 8.48,1.21 17.17,1.79 25.71,2.09 8.47,-0.53 17.17,-0.49 25.36,-1.94 8.07,-1.67 16.62,-2.63 24.11,-5.42 l 11.37,-3.9 5.64,-1.99 0.7,-0.25 0.35,-0.13 3.98,-1.73 1.04,-0.56 2.1,-1.11 c 1.58,-0.13 21.95,-12.93 27.13,-21.21 l 5.49,-6.97 4.16,-7.25 c 2.91,-4.94 4.84,-9.74 6.38,-14.48 6.42,-19.14 6.85,-35.84 5.92,-50.84 z m -85.8,305.91 c -336.87,0 -552.93,-688.23 -594.16,-831.1 11.99,-2.44 23.73,-6.51 35.01,-11.97 144.62,43.29 331.78,53.32 473.13,53.32 119.6,0 206.3,-7.1 206.3,-7.1 37.59,52.62 255.6,796.85 -120.28,796.85"
|
||||
style="fill:#78d3e0;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4025"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 4295.86,5830.24 c -0.25,0 -0.42,0.04 -0.57,0.1 0.12,-0.17 0.3,-0.28 0.45,-0.42 l 0.49,-0.23 c -0.13,0.18 -0.27,0.35 -0.37,0.55"
|
||||
style="fill:#78d3e0;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4027"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 4296.23,5829.69 -0.49,0.23 c 0.2,-0.18 0.34,-0.43 0.6,-0.56 0.06,-0.03 0.13,-0.04 0.2,-0.06 -0.04,0.02 -0.07,0.09 -0.11,0.11 -0.08,0.08 -0.13,0.19 -0.2,0.28"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4029"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 2966.29,4446 c 40.58,0 85.21,10.82 132.65,32.17 98.89,44.51 340.3,286.89 615.05,617.5 10.05,12.1 14.8,27.41 13.34,43.09 -1.44,15.68 -8.91,29.87 -21.01,39.92 -13.55,11.26 -27.92,13.63 -37.6,13.63 -17.63,0 -34.2,-7.75 -45.44,-21.29 -119.61,-143.94 -455.36,-529.55 -571.01,-584.52 l -1.71,-0.79 c -22.52,-10.13 -43.38,-16.75 -62.01,-19.68 l -43.96,-6.91 -32.23,30.67 c -10.81,10.28 -25.64,16.17 -40.73,16.17 -11.12,0 -22,-3.21 -31.51,-9.25 -13.29,-8.45 -22.48,-21.57 -25.9,-36.95 -3.41,-15.37 -0.63,-31.15 7.82,-44.44 4.51,-7.09 46.92,-69.32 144.25,-69.32"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4031"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 2405.75,4433.04 c -9.68,0 -19.27,-2.38 -27.72,-6.86 l -17.32,-9.18 -19.57,-1.16 c -3.77,-0.22 -8.44,-0.39 -14.09,-0.39 -55.05,0 -190.36,17.35 -478.14,133.57 -317.34,128.16 -443.05,147.31 -489.74,147.31 -8.89,0 -14.11,-0.72 -16.49,-1.15 -15.49,-2.82 -28.96,-11.49 -37.93,-24.44 -8.95,-12.94 -12.35,-28.61 -9.53,-44.07 5.02,-27.64 29.84,-48.48 57.69,-48.48 1.16,0 2.34,0.03 3.53,0.1 l 6.51,0.41 6.51,-0.54 c 34.99,-2.91 147.46,-22.23 435.31,-138.47 232.71,-93.98 408.93,-141.64 523.78,-141.64 60.15,0 101.36,12.9 122.51,38.38 10.06,12.11 14.78,27.41 13.33,43.09 -1.45,15.68 -8.93,29.86 -21.03,39.91 -13.56,11.24 -27.94,13.61 -37.61,13.61"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4033"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 983.938,5022.49 c -8.153,16.52 -16.125,35.07 -22.481,56.26 -5.801,21.44 -11.559,44.96 -8.769,74.3 1.355,14.54 5.167,30.93 14.937,47.19 9.523,16.37 26.316,30.48 43.445,37.51 l 3.24,1.45 1.63,0.72 5.51,1.62 4.17,1.13 4.18,1.13 c 1.59,0.4 6.08,0.9 9.07,1.16 3.34,0.29 6.73,0.44 10.1,0.46 l 5.02,-0.07 3.74,-0.5 c 4.93,-0.77 9.96,-1.69 14.76,-2.84 18.12,-5.46 32.24,-13.91 44.48,-22.63 23.61,-18.16 40.6,-37.99 55.55,-58.16 14.99,-20.03 27.23,-40.58 38.14,-60.67 21.58,-40.27 37.1,-79.27 48.25,-113.39 11.22,-34.09 17.96,-63.32 21.76,-84.06 2.17,-10.25 3.04,-18.62 3.93,-24.19 0.64,-5.67 0.98,-8.69 0.98,-8.69 0,0 -7.84,9.39 -20.42,26.02 -12.74,16.54 -30.22,40.35 -50.4,68.76 -20.19,28.37 -43.19,61.42 -68.05,95.24 -12.46,16.84 -25.64,33.7 -39.07,49.72 -13.59,15.64 -27.77,31.07 -41.48,41.01 -6.59,4.99 -12.86,8.31 -16.96,9.85 -0.86,0.09 -1.56,0.14 -2.31,0.48 l -0.54,0.29 c 0.22,-0.07 0.45,-0.11 0.69,-0.11 0.48,-0.02 0.97,0.1 1.43,0.35 0.11,0.1 1.67,0.97 0.45,0.79 l -4.24,-0.86 -2.6,-0.53 c -3.5,-1.24 -5.47,-2.06 -7.89,-4.51 -2.48,-2.73 -5.05,-8.14 -7,-15.1 -3.92,-14.04 -3.93,-33.15 -2.92,-51 1.22,-18.17 3.69,-36.12 6.39,-52.82 5.49,-33.48 11.52,-62.25 15.47,-82.62 4.17,-20.31 6.41,-32.33 6.41,-32.33 0,0 -2.21,2.12 -5.99,6.36 -3.66,4.31 -9.45,10.45 -15.73,18.9 -13.03,16.7 -30.46,41.42 -46.882,74.38 z m 504.612,-159.78 c 0,0 -200.14,588.8 -470.25,588.73 -35.101,-0.01 -71.421,-9.96 -108.597,-32.44 -323.254,-195.45 127.797,-789.34 127.797,-789.34 195.46,135.32 451.05,233.05 451.05,233.05"
|
||||
style="fill:#78d3e0;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4035"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 2879.05,3040.41 c 3.26,0.54 6.47,1.16 9.7,1.76 3.58,0.66 7.13,1.35 10.66,2.08 142.77,29.38 247.77,111.82 248.93,194.35 0.08,5.76 -0.35,11.52 -1.3,17.26 -1.79,10.8 -5.4,21.05 -10.59,30.7 -1.92,3.59 -4.2,7.04 -6.57,10.45 -1.03,1.49 -2.12,2.95 -3.23,4.41 -1.13,1.48 -2.38,2.91 -3.59,4.36 -3.43,4.07 -7.15,8.01 -11.2,11.79 -0.02,0.03 -0.05,0.06 -0.08,0.09 -0.01,0.01 -0.02,0.01 -0.03,0.02 -3.17,2.97 -6.54,5.83 -10.07,8.61 -0.15,0.12 -0.3,0.23 -0.45,0.35 -17.52,13.67 -39.29,25.02 -64.36,33.71 -1.19,0.41 -2.36,0.84 -3.56,1.24 -4.03,1.34 -8.14,2.6 -12.32,3.8 -1.85,0.53 -3.71,1.04 -5.59,1.54 -3.94,1.06 -7.91,2.09 -11.98,3.02 -2.3,0.53 -4.66,1 -7,1.49 -3.88,0.82 -7.75,1.65 -11.73,2.35 -3.13,0.55 -6.35,0.99 -9.53,1.47 -5.64,0.85 -11.35,1.61 -17.16,2.24 -4.19,0.45 -8.38,0.92 -12.66,1.26 -3.01,0.24 -6.07,0.38 -9.12,0.56 -4.22,0.25 -8.46,0.47 -12.76,0.61 -3.05,0.09 -6.11,0.14 -9.2,0.17 -4.49,0.05 -9.02,0.04 -13.58,-0.03 -2.94,-0.05 -5.87,-0.1 -8.83,-0.2 -5.08,-0.17 -10.21,-0.46 -15.36,-0.79 -2.52,-0.16 -5.01,-0.28 -7.54,-0.48 -7.71,-0.61 -15.47,-1.36 -23.3,-2.33 -7.24,-0.9 -14.51,-1.9 -21.84,-3.11 -6.78,-1.13 -13.46,-2.42 -20.08,-3.78 -1.66,-0.34 -3.32,-0.69 -4.96,-1.04 -6.5,-1.4 -12.95,-2.87 -19.28,-4.48 -0.07,-0.02 -0.14,-0.04 -0.21,-0.05 -6.46,-1.65 -12.79,-3.45 -19.06,-5.31 -1.47,-0.44 -2.93,-0.88 -4.39,-1.33 -6.17,-1.89 -12.27,-3.85 -18.24,-5.94 -0.02,-0.01 -0.04,-0.02 -0.07,-0.02 -6.09,-2.14 -12.04,-4.4 -17.92,-6.73 -1.24,-0.5 -2.47,-1 -3.71,-1.5 -11.64,-4.74 -22.82,-9.84 -33.47,-15.28 -1.05,-0.53 -2.09,-1.07 -3.13,-1.62 -5.25,-2.73 -10.4,-5.52 -15.38,-8.41 -0.01,-0.01 -0.02,-0.01 -0.02,-0.01 0,0 -0.01,0 -0.01,-0.01 -4.42,-2.56 -8.71,-5.19 -12.9,-7.87 -0.78,-0.49 -1.52,-1 -2.28,-1.49 -3.28,-2.13 -6.49,-4.29 -9.62,-6.48 -1.06,-0.74 -2.09,-1.48 -3.13,-2.23 -2.91,-2.09 -5.76,-4.21 -8.53,-6.36 -0.9,-0.69 -1.81,-1.37 -2.69,-2.06 -7.17,-5.68 -13.88,-11.52 -20.07,-17.52 -0.68,-0.66 -1.33,-1.34 -2,-2 -2.34,-2.33 -4.62,-4.67 -6.8,-7.03 -0.84,-0.9 -1.65,-1.81 -2.46,-2.71 -2.03,-2.27 -3.97,-4.55 -5.85,-6.85 -0.7,-0.85 -1.41,-1.69 -2.08,-2.54 -2.42,-3.06 -4.74,-6.14 -6.89,-9.25 -0.03,-0.04 -0.06,-0.08 -0.08,-0.11 -2.21,-3.19 -4.24,-6.4 -6.15,-9.64 -0.51,-0.85 -0.96,-1.71 -1.45,-2.57 -1.34,-2.36 -2.61,-4.73 -3.79,-7.12 -0.52,-1.05 -1.03,-2.11 -1.52,-3.17 -1.08,-2.32 -2.07,-4.65 -3,-6.99 -0.38,-0.97 -0.79,-1.94 -1.15,-2.91 -1.17,-3.19 -2.23,-6.39 -3.11,-9.6 -0.02,-0.07 -0.05,-0.15 -0.07,-0.23 -0.89,-3.28 -1.59,-6.58 -2.16,-9.87 -0.18,-1 -0.29,-1.99 -0.43,-2.98 -0.34,-2.34 -0.61,-4.67 -0.79,-7.01 -0.09,-1.15 -0.15,-2.29 -0.2,-3.43 -0.09,-2.32 -0.09,-4.63 -0.02,-6.94 0.03,-1.03 0.03,-2.07 0.09,-3.1 0.21,-3.3 0.53,-6.59 1.08,-9.88 0.87,-5.27 2.22,-10.39 3.93,-15.39 28.02,-82.24 165.39,-127.46 319.29,-101.91"
|
||||
style="fill:#211c1d;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4037"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 2521.85,3144.41 c 4.8,-28.85 22.03,-53.88 48.26,-74.1 2.7,-2.09 5.59,-4.08 8.52,-6.07 44.36,-30.36 110.53,-48.32 186.24,-48.98 29.69,-0.27 60.79,2.11 92.54,7.38 95.35,15.83 176.48,54.44 226.4,102.17 11.09,10.61 20.66,21.67 28.46,33.02 7.8,11.36 13.91,23.02 18.1,34.83 4.19,11.81 6.46,23.77 6.61,35.73 0.07,5.98 -0.36,11.96 -1.34,17.93 -3.97,23.85 -16.33,45.14 -35.29,63.22 -4.73,4.52 -9.89,8.85 -15.42,12.96 -11.09,8.21 -23.7,15.59 -37.6,22.05 -19.22,8.91 -41.11,15.92 -64.73,21.09 -10.62,2.32 -21.46,4.38 -32.8,5.89 -17.91,2.38 -36.7,3.68 -56.42,3.9 0,0 -0.36,0.04 -0.76,0.05 -19.75,0.17 -40.2,-0.83 -61,-3.08 -10.44,-1.12 -20.95,-2.56 -31.54,-4.31 -31.78,-5.28 -61.98,-13.09 -89.97,-22.92 -121.29,-42.61 -201.12,-123.25 -188.26,-200.76"
|
||||
style="fill:#211c1d;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4039"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 2799.32,2390.59 c 10.63,0 21.57,2.16 32.87,6.84 53.5,22.09 55.85,115.25 43.49,204.99 -77.04,-24.64 -144.33,-62.43 -203.75,-98.09 32.47,-61.24 75.27,-113.74 127.39,-113.74"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4041"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 3058.74,2452.64 c 8.78,-3.28 24.35,-6.48 42.26,-6.48 49.7,0 117.57,24.49 108.94,139.42 -0.76,10.23 -1.37,23.86 -1.95,38.57 -23.33,0.44 -47.39,0.58 -69.64,1.14 -38.4,0.96 -74.3,1.87 -105.04,1.87 -23.55,0 -43.27,-0.4 -57.75,-2.2 22.72,-81.15 52.48,-160.81 83.18,-172.32"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4043"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 3260.73,3102.88 c 0,0 -93.7,-214.77 -351.38,-255.19 -67.15,-10.54 -124.22,-15.07 -172.69,-15.07 -137.51,0 -205.78,36.48 -238.51,75.7 0,0 -247.27,-70.74 -268.12,-222.35 -15.56,-113.36 96.95,-171.62 196.03,-171.62 33.45,0 65.34,6.64 90.3,20.02 98.93,53.06 247.24,169.29 445.04,194.55 17.88,2.29 42.58,3.09 71.91,3.08 67.69,0 159.94,-4.24 249.38,-4.24 101.71,0 199.81,5.5 253.92,28.97 122.31,53.06 122.31,144.02 114.54,189.49 -8.67,50.41 -83.33,154.14 -390.42,156.66"
|
||||
style="fill:#dec795;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path4045"
|
||||
inkscape:connector-curvature="0" /></g></g></svg>
|
||||
|
After Width: | Height: | Size: 34 KiB |
@@ -0,0 +1,8 @@
|
||||
import { DataSourcePlugin } from '@grafana/data';
|
||||
import { JaegerDatasource } from './datasource';
|
||||
import { JaegerQueryField } from './QueryField';
|
||||
import { ConfigEditor } from './ConfigEditor';
|
||||
|
||||
export const plugin = new DataSourcePlugin(JaegerDatasource)
|
||||
.setConfigEditor(ConfigEditor)
|
||||
.setExploreQueryField(JaegerQueryField);
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"type": "datasource",
|
||||
"name": "Jaeger",
|
||||
"id": "jaeger",
|
||||
"category": "tracing",
|
||||
|
||||
"metrics": false,
|
||||
"alerting": false,
|
||||
"annotations": false,
|
||||
"logs": false,
|
||||
"streaming": false,
|
||||
"tracing": true,
|
||||
|
||||
"info": {
|
||||
"description": "Open source, end-to-end distributed tracing",
|
||||
"author": {
|
||||
"name": "Grafana Project",
|
||||
"url": "https://grafana.com"
|
||||
},
|
||||
"logos": {
|
||||
"small": "img/jaeger_logo.svg",
|
||||
"large": "img/jaeger_logo.svg"
|
||||
},
|
||||
"links": [
|
||||
{
|
||||
"name": "Learn more",
|
||||
"url": "https://www.jaegertracing.io"
|
||||
},
|
||||
{
|
||||
"name": "GitHub Project",
|
||||
"url": "https://github.com/jaegertracing/jaeger"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import cx from 'classnames';
|
||||
import { FormField } from '@grafana/ui';
|
||||
import { DerivedFieldConfig } from '../types';
|
||||
import { getLinksFromLogsField } from '../../../../features/panel/panellinks/linkSuppliers';
|
||||
import { ArrayVector, FieldType } from '@grafana/data';
|
||||
import { ArrayVector, Field, FieldType, LinkModel } from '@grafana/data';
|
||||
|
||||
type Props = {
|
||||
derivedFields: DerivedFieldConfig[];
|
||||
@@ -90,7 +90,7 @@ function makeDebugFields(derivedFields: DerivedFieldConfig[], debugText: string)
|
||||
try {
|
||||
const testMatch = debugText.match(field.matcherRegex);
|
||||
const value = testMatch && testMatch[1];
|
||||
let link;
|
||||
let link: LinkModel<Field>;
|
||||
|
||||
if (field.url && value) {
|
||||
link = getLinksFromLogsField(
|
||||
@@ -103,7 +103,7 @@ function makeDebugFields(derivedFields: DerivedFieldConfig[], debugText: string)
|
||||
},
|
||||
},
|
||||
0
|
||||
)[0];
|
||||
)[0].linkModel;
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { css } from 'emotion';
|
||||
import { Button, FormField, DataLinkInput, stylesFactory } from '@grafana/ui';
|
||||
import { Button, FormField, DataLinkInput, stylesFactory, Switch } from '@grafana/ui';
|
||||
import { VariableSuggestion } from '@grafana/data';
|
||||
import { DataSourceSelectItem } from '@grafana/data';
|
||||
|
||||
import { DerivedFieldConfig } from '../types';
|
||||
import DataSourcePicker from 'app/core/components/Select/DataSourcePicker';
|
||||
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
||||
import { config } from 'app/core/config';
|
||||
|
||||
const getStyles = stylesFactory(() => ({
|
||||
firstRow: css`
|
||||
row: css`
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
`,
|
||||
@@ -27,6 +32,7 @@ type Props = {
|
||||
export const DerivedField = (props: Props) => {
|
||||
const { value, onChange, onDelete, suggestions, className } = props;
|
||||
const styles = getStyles();
|
||||
const [hasIntenalLink, setHasInternalLink] = useState(!!value.datasourceName);
|
||||
|
||||
const handleChange = (field: keyof typeof value) => (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
onChange({
|
||||
@@ -37,7 +43,7 @@ export const DerivedField = (props: Props) => {
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<div className={styles.firstRow}>
|
||||
<div className={styles.row}>
|
||||
<FormField
|
||||
className={styles.nameField}
|
||||
labelWidth={5}
|
||||
@@ -93,6 +99,64 @@ export const DerivedField = (props: Props) => {
|
||||
width: 100%;
|
||||
`}
|
||||
/>
|
||||
|
||||
{config.featureToggles.tracingIntegration && (
|
||||
<div className={styles.row}>
|
||||
<Switch
|
||||
label="Internal link"
|
||||
checked={hasIntenalLink}
|
||||
onChange={() => {
|
||||
if (hasIntenalLink) {
|
||||
onChange({
|
||||
...value,
|
||||
datasourceName: undefined,
|
||||
});
|
||||
}
|
||||
setHasInternalLink(!hasIntenalLink);
|
||||
}}
|
||||
/>
|
||||
|
||||
{hasIntenalLink && (
|
||||
<DataSourceSection
|
||||
onChange={datasourceName => {
|
||||
onChange({
|
||||
...value,
|
||||
datasourceName,
|
||||
});
|
||||
}}
|
||||
datasourceName={value.datasourceName}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
type DataSourceSectionProps = {
|
||||
datasourceName?: string;
|
||||
onChange: (name: string) => void;
|
||||
};
|
||||
const DataSourceSection = (props: DataSourceSectionProps) => {
|
||||
const { datasourceName, onChange } = props;
|
||||
const datasources: DataSourceSelectItem[] = getDatasourceSrv()
|
||||
.getExternal()
|
||||
.map(
|
||||
(ds: any) =>
|
||||
({
|
||||
value: ds.name,
|
||||
name: ds.name,
|
||||
meta: ds.meta,
|
||||
} as DataSourceSelectItem)
|
||||
);
|
||||
const selectedDatasource = datasourceName && datasources.find(d => d.name === datasourceName);
|
||||
return (
|
||||
<DataSourcePicker
|
||||
onChange={newValue => {
|
||||
onChange(newValue.name);
|
||||
}}
|
||||
datasources={datasources}
|
||||
current={selectedDatasource}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -51,6 +51,7 @@ import {
|
||||
} from './types';
|
||||
import { LegacyTarget, LiveStreams } from './live_streams';
|
||||
import LanguageProvider from './language_provider';
|
||||
import { serializeParams } from '../../../core/utils/fetch';
|
||||
|
||||
export type RangeQueryOptions = Pick<DataQueryRequest<LokiQuery>, 'range' | 'intervalMs' | 'maxDataPoints' | 'reverse'>;
|
||||
export const DEFAULT_MAX_LINES = 1000;
|
||||
@@ -68,12 +69,6 @@ const DEFAULT_QUERY_PARAMS: Partial<LokiLegacyQueryRequest> = {
|
||||
query: '',
|
||||
};
|
||||
|
||||
function serializeParams(data: Record<string, any>) {
|
||||
return Object.keys(data)
|
||||
.map(k => `${encodeURIComponent(k)}=${encodeURIComponent(data[k])}`)
|
||||
.join('&');
|
||||
}
|
||||
|
||||
interface LokiContextQueryOptions {
|
||||
direction?: 'BACKWARD' | 'FORWARD';
|
||||
limit?: number;
|
||||
|
||||
@@ -395,11 +395,16 @@ export const enhanceDataFrame = (dataFrame: DataFrame, config: LokiOptions | nul
|
||||
|
||||
const fields = derivedFields.reduce((acc, field) => {
|
||||
const config: FieldConfig = {};
|
||||
if (field.url) {
|
||||
if (field.url || field.datasourceName) {
|
||||
config.links = [
|
||||
{
|
||||
url: field.url,
|
||||
title: '',
|
||||
meta: field.datasourceName
|
||||
? {
|
||||
datasourceName: field.datasourceName,
|
||||
}
|
||||
: undefined,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -127,6 +127,7 @@ export type DerivedFieldConfig = {
|
||||
matcherRegex: string;
|
||||
name: string;
|
||||
url?: string;
|
||||
datasourceName?: string;
|
||||
};
|
||||
|
||||
export interface TransformerOptions {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import React from 'react';
|
||||
import { DataSourcePluginOptionsEditorProps } from '@grafana/data';
|
||||
import { DataSourceHttpSettings } from '@grafana/ui';
|
||||
|
||||
export type Props = DataSourcePluginOptionsEditorProps;
|
||||
|
||||
export const ConfigEditor: React.FC<Props> = ({ options, onOptionsChange }) => {
|
||||
return (
|
||||
<DataSourceHttpSettings
|
||||
defaultUrl={'http://localhost:3100'}
|
||||
dataSourceConfig={options}
|
||||
showAccessOptions={true}
|
||||
onChange={onOptionsChange}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
import React from 'react';
|
||||
import { ZipkinDatasource, ZipkinQuery } from './datasource';
|
||||
import { ExploreQueryFieldProps } from '@grafana/data';
|
||||
|
||||
type Props = ExploreQueryFieldProps<ZipkinDatasource, ZipkinQuery>;
|
||||
|
||||
export const QueryField = (props: Props) => (
|
||||
<div className={'slate-query-field__wrapper'}>
|
||||
<div className="slate-query-field">
|
||||
<input
|
||||
style={{ width: '100%' }}
|
||||
value={props.query.query || ''}
|
||||
onChange={e =>
|
||||
props.onChange({
|
||||
...props.query,
|
||||
query: e.currentTarget.value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -0,0 +1,38 @@
|
||||
import {
|
||||
MutableDataFrame,
|
||||
DataSourceApi,
|
||||
DataSourceInstanceSettings,
|
||||
DataQueryRequest,
|
||||
DataQueryResponse,
|
||||
DataQuery,
|
||||
} from '@grafana/data';
|
||||
import { Observable, of } from 'rxjs';
|
||||
|
||||
export type ZipkinQuery = {
|
||||
query: string;
|
||||
} & DataQuery;
|
||||
|
||||
export class ZipkinDatasource extends DataSourceApi<ZipkinQuery> {
|
||||
constructor(instanceSettings: DataSourceInstanceSettings) {
|
||||
super(instanceSettings);
|
||||
}
|
||||
|
||||
query(options: DataQueryRequest<ZipkinQuery>): Observable<DataQueryResponse> {
|
||||
return of({
|
||||
data: [
|
||||
new MutableDataFrame({
|
||||
fields: [
|
||||
{
|
||||
name: 'url',
|
||||
values: [],
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
async testDatasource(): Promise<any> {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 418 442"><title>자산 1</title><g id="레이어_2" data-name="레이어 2"><g id="레이어_1-2" data-name="레이어 1"><image width="418" height="442" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAaIAAAG6CAYAAABKjkKZAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3BpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQwIDc5LjE2MDQ1MSwgMjAxNy8wNS8wNi0wMTowODoyMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo5ZDlkMzkwMy0xOGJlLTQyMTYtYTkzOC0yZDkxNTIxOGU2M2EiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MEFCM0I3OENDNjhEMTFFOTk2RTg4QzkzMzBFRTMwNjkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MEFCM0I3OEJDNjhEMTFFOTk2RTg4QzkzMzBFRTMwNjkiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTggKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDozQUYzQUMyOUFCMkExMUU5OTIxN0UzMTZDQjEzQkNFOSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDozQUYzQUMyQUFCMkExMUU5OTIxN0UzMTZDQjEzQkNFOSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Puv6uNIAADfWSURBVHja7J0HuB1VuYYXITQhocOFSO8Q6QoBRKp0CO0SiZQoSgohBBJaAgmE9HICpCGIgPQqCggKggoceu9SFLmCCNKkCuF+f2aiJ2TPnr3P2XvWmpn3fZ7/mdxryN77X2vmm39mrf9b4Msvv3QAAAC+6EQKAAAAIQIAAIQIAAAAAHLG7ME9tlUMIxMA7WcBUgDQbhHqrMMjinUUG3VqaX2ZrADUD4/mANrPcYpvKBZVnEs6AKiIALKshlbR4RnFEm3+3weqKrqe7ABQEQFkwdSviJBxtgRqcVIDgBABNLsa2lOHAyr8T19XjCRDAPXBozmA+kRoMR2eVqyR8Fc+V2zWqaX1KbIFQEUE0AyGVREhw1bSzZRgcZMHgBABNLwaWk+HoTX81e0UR5AxAIQIoNHMUCxc49+dIOFahpQBIEQAjaqGDtVhpzr+k+UVY8kcQDo8xwZIF6EldXhesWKd/6l5rPTo1NJ6P1kEoCIC6Aij2yFCc2/0ZknIFiSFAAgRQHuroS106NeBf2JTxQAyCVD9jg0AKouQ3ajZY7UtO/hPfaBYr1NL6+tkFYCKCKAe+jZAhIwuiimkE4CKCKCeasjeCdkChSUb+M/uqqrodrILQEUEUAuTGyxCxnQJ3CKkFgAhAkirhnbUoXcT/ul1XW2dGQBKBY/mAOYVIeuc8Lhi/SZ9xCcON1cAKiKAKgxpoggZuLkCUBEBJFZD1lXbLB4Wy+DjcHMFoCICmI9zMxIhAzdXAIQIYJ5qqKcOe2X4kbi5AsTwaA4QoagyeVaxSsYfjZsrABURwBxGeBAhw9xcZ+DmCggRQLmroe46DPb4Fb6tOJyRgDLDnRiUWYRs/v/BRdbePvmHi5qivsOoABURQLk4IgARMnBzBSoigBJWQ8u4qKnpcoF8JdxcgYoIoGSMC0iE5t4UzsTNFRAigHJUQz10OCrAr7aZoj8jBGWDR3NQNhGyJdMPKTYJ9Cu+r1gfN1egIgIoLscELEJGVxd5IQFQEQEUsBrq5qIOCl1y8HV3UVV0B6MGVEQAxaIlJyJk4OYKCBFAwaqh3XQ4OEdfeT0XeSMBFB4ezUEZRMjM6Kyx6Fo5++rm5rphp5bWVxhFoCICyDen5FCEDBPQaQwfUBEB5LsaWkeHJxV5ft9ygKqiGxhNoCICyCfTcy5CBm6ugBAB5LQaOkSHXQvwU8wraQQjCkWFR3NQVBGyjaHPKVYqyE8yN9dNO7W0Ps3oAhURQD4YVSARMqw10UzcXAEhAshHNWTNQwcU8Kfh5gqFhLsrKJoI2c3VvYqtCvoTcXMFKiKAwPlRgUXIwM0VqIgAAq6GVnDRAoWlC/5TcXMFKiKAQJlYAhGaewOJmysgRACBVUPbu3K9yMfNFQp1ZwWQdxFaSIfHFBuW7Kfj5gpURACBcHwJRcjAzRWoiAACqIZW0+EZxddKnAbcXIGKCMAj55RchAzcXAEhAvBUDe2jw75kAjdXyDc8moO8ipBVQfZIbjWyMQfcXIGKCCBjTkOE5gE3V6AiAsiwGrIVcrZceyGyMR+4uQJCBNBkEbI5e6fiO2SjIn9VbCAx+pBUQF7g0Rzkje8jQlXBzRWoiACaWA1ZHzlraroC2agKbq5ARQTQJMYgQjVhbq4zcHMFhAigsdXQt3Q4mkzUjDWBPYw0QB7gjgnyIEJmd/CgizpOQ+3g5gpURAANoj8i1C7MzXUMaQAqIoCOVUMruWiBQley0S7MzXVrVUUPkAqgIgJoH1MQoQ7fbOLmCggRQDuroV106EUmOszmin6kAUK+WwIIUYTM1uBJxTpkoyGYm6stXHiDVAAVEUBtnIgINRTcXIGKCKCOamgtHZ5yUUdpaCw7qyr6HWkAKiKA6kxDhJqGdVxYmDQAQgSQXA0dpMPuZKJpmJvrUNIAIcGjOQhJhLro8KyiG9loKh8rNsLNFaiIAOZnJCKUCYspziUNQEUEMG81tIkODyvYeJkd+6sq+gVpAIQIEKHIruAeRQ+ykSmvKjbEzRV8w6M5CIEfIkJeWFVxOmkAKiIoezW0nA7PK5YhG14wN9dNVBU9QyqAigjKynhEyCvm5joTN1dAiKCs1dB2OvyATHgHN1fwCndB4EuE7E78UUV3shEEuLkCFRGUjuMQoaDAzRWoiKBU1dAqLuqgsDjZCArcXIGKCErDVEQo2BtT3FwBIYLCV0N76XAAmQgW3FzByx0QQFYiZD3OnlasQTaCBjdXoCKCwjIMEcoFuLkCFREUshpaX4fHFZiy5QfcXIGKCArFdEQod+DmCggRFKYa6q3DTmQid+DmCpnAozlotggt6aKmpiuSjVyCmytQEUHuGY0I5RrcXIGKCHJdDW2pw/3c8BQC3FwBIYLciVCnWIS2JBuFADdXaBrcqUKz6IcIFQrcXIGKCHJVDdk7IVugsCTZKBS4uQIVEeSGyYhQIcHNFRAiyEU1ZPuFepOJwoKbKzQc7mygkSJku/Ctjc/6ZKPQvGljjJsrUBFBiAxFhErBCi7aHwZARQRBVUPWVdssHhYjG6XA3Fy3UlX0IKkAKiIIhXMRodLdxOLmCggRBFMN7a/DXmSidGyh6EsaoBF3NQAdEaHFdXhWsQrZKCXm5rpup5bWv5MKoCICX4xEhEqNublOIQ1ARQS+qqHuOjzqoo2OUG5wcwWECDIXIZs7f1RsSzZAPOei9j+fkQqoFx7NQXs5EhGCNtj+sSGkAaiIIKtqaBkXNTVdjmxAG8zN1awi/kwqgIoIms14RAgqgJsrUBFBJtVQDx3uYe5AFXqqKrqRNABCBM0QIVsd97BiY7IBVTA31w0kRh+RCqgFHs1BPQxEhKAGcHMFKiJoSjXUzUUdFLqQDagB3FyBiggazlRECOrAHuPOwM0VECJoVDW0mw4HkQmok+8ovk8aIA3uViBNhBZ1kc/QmmQD2gFurkBFBB3mFEQIOgBurkBFBB2qhtbR4UnFImSjItcqdlYsTSqqgpsrUBFBu5mBCCXytotM4U4hFTXd8OLmCggR1F0NHaLDLmQikZN0h29idL7iftKRCm6ugBBBXSJkZmdTyUQi1uLowjknUEvr7PgC+wVpSWWM5taKpAEQIqiFUYr/IQ0VMcHpJwH68j8nUUvrY45mn7WAmysgRFBTNbSZDgPIRCJTJTxPVvj/j1D8jfSkcqjm2E6kARAiSBIhmw+zFLxUrsxrijMqnkgtre/rcBwpqonpmmsLkwZAiKASP1J8izQkMliC80HiydTSeo0Ot5KmVHBzhXlgHxHMrYZs46G5ri5FNipyq4RmjxryuJaLOlGw7L06uLkCFRHMx0REKJFPFcfUdEK1tL7k6CRQC7i5AkIE89zFb6/D4WQikTGxwNTKBMULpC2VvTX39iMNgBAhQgu5aIECVOZFxfi6TqqWVqug+pO6mjhHc/BrpAEhgnJzvGILine truncated
|
||||
|
After Width: | Height: | Size: 20 KiB |
@@ -0,0 +1,8 @@
|
||||
import { DataSourcePlugin } from '@grafana/data';
|
||||
import { ZipkinDatasource } from './datasource';
|
||||
import { QueryField } from './QueryField';
|
||||
import { ConfigEditor } from './ConfigEditor';
|
||||
|
||||
export const plugin = new DataSourcePlugin(ZipkinDatasource)
|
||||
.setConfigEditor(ConfigEditor)
|
||||
.setExploreQueryField(QueryField);
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"type": "datasource",
|
||||
"name": "Zipkin",
|
||||
"id": "zipkin",
|
||||
"category": "tracing",
|
||||
|
||||
"metrics": false,
|
||||
"alerting": false,
|
||||
"annotations": false,
|
||||
"logs": false,
|
||||
"streaming": false,
|
||||
"tracing": true,
|
||||
|
||||
"info": {
|
||||
"description": "Placeholder for the distributed tracing system.",
|
||||
"author": {
|
||||
"name": "Grafana Project",
|
||||
"url": "https://grafana.com"
|
||||
},
|
||||
"logos": {
|
||||
"small": "img/zipkin-logo.svg",
|
||||
"large": "img/zipkin-logo.svg"
|
||||
},
|
||||
"links": [
|
||||
{
|
||||
"name": "Learn more",
|
||||
"url": "https://zipkin.io"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user