@od-oneapp/observability 2026.1.1301

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/README.md +523 -0
  2. package/dist/client-next.d.mts +20 -0
  3. package/dist/client-next.d.mts.map +1 -0
  4. package/dist/client-next.mjs +64 -0
  5. package/dist/client-next.mjs.map +1 -0
  6. package/dist/client.d.mts +11 -0
  7. package/dist/client.d.mts.map +1 -0
  8. package/dist/client.mjs +47 -0
  9. package/dist/client.mjs.map +1 -0
  10. package/dist/env.d.mts +15 -0
  11. package/dist/env.d.mts.map +1 -0
  12. package/dist/env.mjs +45 -0
  13. package/dist/env.mjs.map +1 -0
  14. package/dist/factory-DkY353r8.mjs +380 -0
  15. package/dist/factory-DkY353r8.mjs.map +1 -0
  16. package/dist/hooks-useObservability.d.mts +11 -0
  17. package/dist/hooks-useObservability.d.mts.map +1 -0
  18. package/dist/hooks-useObservability.mjs +174 -0
  19. package/dist/hooks-useObservability.mjs.map +1 -0
  20. package/dist/index-CpcdzWrF.d.mts +24 -0
  21. package/dist/index-CpcdzWrF.d.mts.map +1 -0
  22. package/dist/index.d.mts +88 -0
  23. package/dist/index.d.mts.map +1 -0
  24. package/dist/index.mjs +97 -0
  25. package/dist/index.mjs.map +1 -0
  26. package/dist/manager-BxQqOPEg.d.mts +33 -0
  27. package/dist/manager-BxQqOPEg.d.mts.map +1 -0
  28. package/dist/plugin-Bfq-o3nr.d.mts +60 -0
  29. package/dist/plugin-Bfq-o3nr.d.mts.map +1 -0
  30. package/dist/plugin-Bt-ygG1m.d.mts +254 -0
  31. package/dist/plugin-Bt-ygG1m.d.mts.map +1 -0
  32. package/dist/plugin-CLFwRERa.mjs +593 -0
  33. package/dist/plugin-CLFwRERa.mjs.map +1 -0
  34. package/dist/plugin-CP895lBx.mjs +534 -0
  35. package/dist/plugin-CP895lBx.mjs.map +1 -0
  36. package/dist/plugin-CaQxviDs.d.mts +61 -0
  37. package/dist/plugin-CaQxviDs.d.mts.map +1 -0
  38. package/dist/plugin-lPdJirTY.mjs +234 -0
  39. package/dist/plugin-lPdJirTY.mjs.map +1 -0
  40. package/dist/plugins-betterstack-env.d.mts +29 -0
  41. package/dist/plugins-betterstack-env.d.mts.map +1 -0
  42. package/dist/plugins-betterstack-env.mjs +75 -0
  43. package/dist/plugins-betterstack-env.mjs.map +1 -0
  44. package/dist/plugins-betterstack.d.mts +4 -0
  45. package/dist/plugins-betterstack.mjs +4 -0
  46. package/dist/plugins-console.d.mts +37 -0
  47. package/dist/plugins-console.d.mts.map +1 -0
  48. package/dist/plugins-console.mjs +196 -0
  49. package/dist/plugins-console.mjs.map +1 -0
  50. package/dist/plugins-sentry-env.d.mts +37 -0
  51. package/dist/plugins-sentry-env.d.mts.map +1 -0
  52. package/dist/plugins-sentry-env.mjs +79 -0
  53. package/dist/plugins-sentry-env.mjs.map +1 -0
  54. package/dist/plugins-sentry-microfrontend-env.d.mts +49 -0
  55. package/dist/plugins-sentry-microfrontend-env.d.mts.map +1 -0
  56. package/dist/plugins-sentry-microfrontend-env.mjs +80 -0
  57. package/dist/plugins-sentry-microfrontend-env.mjs.map +1 -0
  58. package/dist/plugins-sentry-microfrontend.d.mts +2 -0
  59. package/dist/plugins-sentry-microfrontend.mjs +3 -0
  60. package/dist/plugins-sentry.d.mts +5 -0
  61. package/dist/plugins-sentry.mjs +6 -0
  62. package/dist/server-edge.d.mts +15 -0
  63. package/dist/server-edge.d.mts.map +1 -0
  64. package/dist/server-edge.mjs +53 -0
  65. package/dist/server-edge.mjs.map +1 -0
  66. package/dist/server-next.d.mts +17 -0
  67. package/dist/server-next.d.mts.map +1 -0
  68. package/dist/server-next.mjs +64 -0
  69. package/dist/server-next.mjs.map +1 -0
  70. package/dist/server.d.mts +11 -0
  71. package/dist/server.d.mts.map +1 -0
  72. package/dist/server.mjs +48 -0
  73. package/dist/server.mjs.map +1 -0
  74. package/dist/utils-CuGrTcD6.d.mts +77 -0
  75. package/dist/utils-CuGrTcD6.d.mts.map +1 -0
  76. package/env.ts +67 -0
  77. package/package.json +147 -0
  78. package/src/client-next.ts +131 -0
  79. package/src/client.ts +70 -0
  80. package/src/core/index.ts +15 -0
  81. package/src/core/manager.ts +361 -0
  82. package/src/core/plugin.ts +61 -0
  83. package/src/core/types.ts +151 -0
  84. package/src/factory/builder.ts +132 -0
  85. package/src/factory/index.ts +67 -0
  86. package/src/factory/presets.ts +78 -0
  87. package/src/hooks/useObservability.ts +206 -0
  88. package/src/plugins/betterstack/env.ts +101 -0
  89. package/src/plugins/betterstack/index.ts +15 -0
  90. package/src/plugins/betterstack/plugin.ts +373 -0
  91. package/src/plugins/console/index.ts +323 -0
  92. package/src/plugins/sentry/__tests__/plugin-tracing.test.ts +511 -0
  93. package/src/plugins/sentry/env.ts +93 -0
  94. package/src/plugins/sentry/index.ts +28 -0
  95. package/src/plugins/sentry/plugin.ts +953 -0
  96. package/src/plugins/sentry/types.ts +252 -0
  97. package/src/plugins/sentry-microfrontend/env.ts +105 -0
  98. package/src/plugins/sentry-microfrontend/index.ts +12 -0
  99. package/src/plugins/sentry-microfrontend/multiplexed-transport.ts +221 -0
  100. package/src/plugins/sentry-microfrontend/plugin.ts +500 -0
  101. package/src/plugins/sentry-microfrontend/sentry-types.ts +140 -0
  102. package/src/plugins/sentry-microfrontend/types.ts +130 -0
  103. package/src/plugins/sentry-microfrontend/utils.ts +326 -0
  104. package/src/server-edge.ts +113 -0
  105. package/src/server-next.ts +114 -0
  106. package/src/server.ts +71 -0
  107. package/src/shared.ts +148 -0
@@ -0,0 +1,67 @@
1
+ /**
2
+ * @fileoverview Factory functions for creating observability instances
3
+ * Factory functions for creating observability instances
4
+ */
5
+
6
+ import { ObservabilityManager } from '../core/manager';
7
+
8
+ import { ObservabilityBuilder } from './builder';
9
+
10
+ import type { ObservabilityPlugin, ObservabilityServerPlugin } from '../core/plugin';
11
+
12
+ export { ObservabilityManager } from '../core/manager';
13
+ export { ObservabilityBuilder } from './builder';
14
+
15
+ /**
16
+ * Create an observability instance with the provided plugins.
17
+ *
18
+ * Factory function that creates a configured ObservabilityManager with the given plugins.
19
+ * Provides a simpler API than using ObservabilityBuilder directly.
20
+ *
21
+ * @param plugins - Array of observability plugins to include
22
+ * @param options - Optional configuration options
23
+ * @param options.autoInitialize - Whether to auto-initialize plugins (default: true)
24
+ * @returns Configured ObservabilityManager instance
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * const obs = createObservability([
29
+ * createConsolePlugin(),
30
+ * createSentryPlugin({ dsn: '...' }),
31
+ * ], { autoInitialize: true });
32
+ * ```
33
+ */
34
+ export function createObservability(
35
+ plugins: (ObservabilityPlugin | ObservabilityServerPlugin)[],
36
+ options?: {
37
+ autoInitialize?: boolean;
38
+ },
39
+ ): ObservabilityManager {
40
+ const builder = new ObservabilityBuilder();
41
+
42
+ if (options?.autoInitialize !== undefined) {
43
+ builder.withAutoInitialize(options.autoInitialize);
44
+ }
45
+
46
+ return builder.withPlugins(plugins).build();
47
+ }
48
+
49
+ /**
50
+ * Create a no-op observability instance for testing or when observability is disabled.
51
+ *
52
+ * Returns an ObservabilityManager with no plugins configured. All observability methods
53
+ * will be no-ops. Useful for testing or when observability should be disabled.
54
+ *
55
+ * Note: For logging, use @repo/shared/logger instead.
56
+ *
57
+ * @returns Empty ObservabilityManager instance
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * const obs = createNoOpObservability();
62
+ * obs.captureMessage('This will not be logged'); // No-op
63
+ * ```
64
+ */
65
+ export function createNoOpObservability(): ObservabilityManager {
66
+ return new ObservabilityManager();
67
+ }
@@ -0,0 +1,78 @@
1
+ /**
2
+ * @fileoverview Common observability configurations and presets
3
+ * Common observability configurations and presets
4
+ */
5
+
6
+ import { env } from '../../env';
7
+ import { createBetterStackPlugin } from '../plugins/betterstack';
8
+ import { env as betterStackEnv } from '../plugins/betterstack/env';
9
+ import { createConsolePlugin } from '../plugins/console';
10
+ import { createSentryPlugin } from '../plugins/sentry';
11
+ import { env as sentryEnv } from '../plugins/sentry/env';
12
+
13
+ import { ObservabilityBuilder } from './builder';
14
+
15
+ /**
16
+ * Create development preset observability configuration.
17
+ *
18
+ * Configures observability for development environments with console logging enabled.
19
+ * Automatically detects development mode and adds appropriate plugins.
20
+ *
21
+ * @returns ObservabilityBuilder configured for development
22
+ */
23
+ export async function createDevelopmentObservability(): Promise<ObservabilityBuilder> {
24
+ const builder = ObservabilityBuilder.create();
25
+
26
+ // Always add console in development
27
+ if (env.NEXT_PUBLIC_NODE_ENV === 'development') {
28
+ builder.withPlugin(createConsolePlugin());
29
+ }
30
+
31
+ return builder;
32
+ }
33
+
34
+ /**
35
+ * Create production preset observability configuration.
36
+ *
37
+ * Configures observability for production environments with error tracking (Sentry)
38
+ * and logging (Better Stack) if configured. Only adds plugins when credentials are available.
39
+ *
40
+ * @returns ObservabilityBuilder configured for production
41
+ */
42
+ export async function createProductionObservability(): Promise<ObservabilityBuilder> {
43
+ const builder = ObservabilityBuilder.create();
44
+
45
+ // Add Sentry if DSN is configured
46
+ if (sentryEnv.SENTRY_DSN || sentryEnv.NEXT_PUBLIC_SENTRY_DSN) {
47
+ builder.withPlugin(createSentryPlugin());
48
+ }
49
+
50
+ // Add Better Stack if token is configured
51
+ const hasToken =
52
+ betterStackEnv.BETTER_STACK_SOURCE_TOKEN ??
53
+ betterStackEnv.BETTERSTACK_SOURCE_TOKEN ??
54
+ betterStackEnv.LOGTAIL_SOURCE_TOKEN;
55
+
56
+ if (hasToken) {
57
+ builder.withPlugin(createBetterStackPlugin());
58
+ }
59
+
60
+ return builder;
61
+ }
62
+
63
+ /**
64
+ * Create observability configuration based on environment.
65
+ *
66
+ * Automatically selects the appropriate preset (development or production) based on
67
+ * the NODE_ENV environment variable. Provides a convenient way to get environment-appropriate
68
+ * observability configuration.
69
+ *
70
+ * @returns ObservabilityBuilder configured for the current environment
71
+ */
72
+ export async function createAutoConfiguredObservability(): Promise<ObservabilityBuilder> {
73
+ if (env.NEXT_PUBLIC_NODE_ENV === 'production') {
74
+ return createProductionObservability();
75
+ } else {
76
+ return createDevelopmentObservability();
77
+ }
78
+ }
@@ -0,0 +1,206 @@
1
+ /**
2
+ * @fileoverview React hooks for observability integration
3
+ * React hooks for observability integration
4
+ * Optimized for React 19 features including use() hook and automatic error boundaries
5
+ */
6
+
7
+ 'use client';
8
+
9
+ import { use, useEffect, useSyncExternalStore } from 'react';
10
+
11
+ import { logDebug, logError } from '@repo/shared/logs';
12
+
13
+ import type { ObservabilityManager } from '../core/manager';
14
+
15
+ /**
16
+ * Global observability instance promise for React 19's use() hook
17
+ * This allows components to suspend while waiting for initialization
18
+ */
19
+ let observabilityPromise: Promise<ObservabilityManager> | null = null;
20
+
21
+ /**
22
+ * Set the observability promise for React 19 Suspense integration
23
+ * @param promise - Promise that resolves to ObservabilityManager
24
+ */
25
+ export function setObservabilityPromise(promise: Promise<ObservabilityManager>): void {
26
+ observabilityPromise = promise;
27
+ }
28
+
29
+ /**
30
+ * React 19+ hook that suspends until observability is ready
31
+ * Uses the new use() hook for automatic Suspense integration
32
+ *
33
+ * @example
34
+ * ```tsx
35
+ * 'use client';
36
+ *
37
+ * import { Suspense } from 'react';
38
+ * import { useObservability } from '@repo/observability/hooks/useObservability';
39
+ * import { logInfo } from '@repo/shared/logs';
40
+ *
41
+ * function MyComponent() {
42
+ * const observability = useObservability();
43
+ *
44
+ * useEffect(() => {
45
+ * logInfo('Component mounted');
46
+ * }, [observability]);
47
+ *
48
+ * return <div>Hello</div>;
49
+ * }
50
+ *
51
+ * export default function Page() {
52
+ * return (
53
+ * <Suspense fallback={<div>Loading...</div>}>
54
+ * <MyComponent />
55
+ * </Suspense>
56
+ * );
57
+ * }
58
+ * ```
59
+ */
60
+ export function useObservability(): ObservabilityManager {
61
+ if (!observabilityPromise) {
62
+ throw new Error(
63
+ 'Observability promise not set. Call setObservabilityPromise() during module initialization.',
64
+ );
65
+ }
66
+
67
+ // React 19's use() hook automatically suspends until promise resolves
68
+ return use(observabilityPromise);
69
+ }
70
+
71
+ // Module-level state for legacy hook (fixes state recreation bug)
72
+ let legacyCurrentInstance: ObservabilityManager | undefined = undefined;
73
+ const legacyListeners = new Set<() => void>();
74
+ let legacyInitialized = false;
75
+
76
+ /**
77
+ * Legacy hook for React 18 compatibility
78
+ * Returns observability instance once available, undefined during initialization
79
+ * Does not use Suspense
80
+ *
81
+ * @deprecated Use useObservability() with Suspense for React 19+
82
+ */
83
+ export function useObservabilityLegacy(): ObservabilityManager | undefined {
84
+ const subscribe = (callback: () => void) => {
85
+ legacyListeners.add(callback);
86
+
87
+ // If promise exists and instance not yet resolved, wait for it
88
+ if (observabilityPromise && !legacyInitialized) {
89
+ legacyInitialized = true;
90
+ void (async () => {
91
+ try {
92
+ const instance = await observabilityPromise;
93
+ legacyCurrentInstance = instance;
94
+ legacyListeners.forEach(listener => {
95
+ listener();
96
+ });
97
+ } catch {
98
+ legacyInitialized = false; // Allow retry on failure
99
+ }
100
+ })();
101
+ }
102
+
103
+ return () => {
104
+ legacyListeners.delete(callback);
105
+ };
106
+ };
107
+
108
+ const getSnapshot = (): ObservabilityManager | undefined => {
109
+ return legacyCurrentInstance;
110
+ };
111
+
112
+ return useSyncExternalStore(subscribe, getSnapshot);
113
+ }
114
+
115
+ /**
116
+ * Hook to track component lifecycle events
117
+ * Automatically logs mount, update, and unmount events
118
+ *
119
+ * @param componentName - Name of the component for logging
120
+ * @param deps - Dependencies to track for updates
121
+ *
122
+ * @example
123
+ * ```tsx
124
+ * 'use client';
125
+ *
126
+ * import { useObservabilityLifecycle } from '@repo/observability/hooks/useObservability';
127
+ *
128
+ * function UserProfile({ userId }: { userId: string }) {
129
+ * useObservabilityLifecycle('UserProfile', [userId]);
130
+ *
131
+ * return <div>User {userId}</div>;
132
+ * }
133
+ * ```
134
+ */
135
+ export function useObservabilityLifecycle(
136
+ componentName: string,
137
+ deps: readonly unknown[] = [],
138
+ ): void {
139
+ useEffect(() => {
140
+ // Log mount
141
+ logDebug(`Component mounted: ${componentName}`, {
142
+ component: componentName,
143
+ event: 'mount',
144
+ });
145
+
146
+ // Log unmount
147
+ return () => {
148
+ logDebug(`Component unmounted: ${componentName}`, {
149
+ component: componentName,
150
+ event: 'unmount',
151
+ });
152
+ };
153
+ }, deps);
154
+ }
155
+
156
+ /**
157
+ * Hook to automatically report errors to observability
158
+ * Compatible with React 19 error boundaries
159
+ *
160
+ * @param error - Error to report
161
+ * @param errorInfo - Additional error information
162
+ *
163
+ * @example
164
+ * ```tsx
165
+ * 'use client';
166
+ *
167
+ * import { useObservabilityError } from '@repo/observability/hooks/useObservability';
168
+ *
169
+ * function MyComponent() {
170
+ * const [error, setError] = useState<Error | null>(null);
171
+ *
172
+ * useObservabilityError(error, { component: 'MyComponent' });
173
+ *
174
+ * if (error) {
175
+ * return <div>Error occurred</div>;
176
+ * }
177
+ *
178
+ * return <div>Hello</div>;
179
+ * }
180
+ * ```
181
+ */
182
+ export function useObservabilityError(
183
+ error: Error | null | undefined,
184
+ errorInfo?: Record<string, unknown>,
185
+ ): void {
186
+ useEffect(() => {
187
+ if (error && observabilityPromise) {
188
+ void (async () => {
189
+ try {
190
+ const obs = await observabilityPromise;
191
+ obs.captureException(error, {
192
+ extra: errorInfo,
193
+ tags: {
194
+ source: 'react-component',
195
+ },
196
+ });
197
+ } catch (reportError) {
198
+ logError('Failed to report error to observability', {
199
+ error: reportError,
200
+ originalError: error,
201
+ });
202
+ }
203
+ })();
204
+ }
205
+ }, [error, errorInfo]);
206
+ }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * @fileoverview Better Stack (Logtail) environment configuration
3
+ * Better Stack (Logtail) environment configuration
4
+ * Updated to support official @logtail packages
5
+ */
6
+
7
+ import { logWarn } from '@repo/shared/logger';
8
+ import { createEnv } from '@t3-oss/env-core';
9
+ import { z } from 'zod/v4';
10
+
11
+ // Create validated env object
12
+ export const env = createEnv({
13
+ server: {
14
+ // Legacy support
15
+ LOGTAIL_SOURCE_TOKEN: z.string().optional(),
16
+ BETTERSTACK_SOURCE_TOKEN: z.string().optional(),
17
+
18
+ // Official Better Stack environment variables
19
+ BETTER_STACK_SOURCE_TOKEN: z.string().optional(),
20
+ BETTER_STACK_INGESTING_URL: z.string().url().optional(),
21
+ BETTER_STACK_LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error', 'off']).optional(),
22
+ },
23
+ client: {
24
+ // Legacy support
25
+ NEXT_PUBLIC_LOGTAIL_TOKEN: z.string().optional(),
26
+ NEXT_PUBLIC_BETTERSTACK_TOKEN: z.string().optional(),
27
+
28
+ // Official Better Stack client environment variables
29
+ NEXT_PUBLIC_BETTER_STACK_SOURCE_TOKEN: z.string().optional(),
30
+ NEXT_PUBLIC_BETTER_STACK_INGESTING_URL: z.string().url().optional(),
31
+ NEXT_PUBLIC_BETTER_STACK_LOG_LEVEL: z
32
+ .enum(['debug', 'info', 'warn', 'error', 'off'])
33
+ .optional(),
34
+ },
35
+ clientPrefix: 'NEXT_PUBLIC_',
36
+ runtimeEnv: process.env,
37
+ emptyStringAsUndefined: true,
38
+ onInvalidAccess: (variable: string) => {
39
+ throw new Error(
40
+ `❌ Attempted to access a server-side environment variable on the client: ${variable}`,
41
+ );
42
+ },
43
+ onValidationError: error => {
44
+ logWarn('Better Stack environment validation failed', { error });
45
+ // Don't throw in packages - use fallbacks
46
+ return undefined as never;
47
+ },
48
+ });
49
+
50
+ /**
51
+ * Safe environment access for non-Next.js contexts.
52
+ *
53
+ * Provides fallback environment variable access for Node.js, workers, and test environments
54
+ * where the validated env object may not be available. Returns fallback values with proper
55
+ * priority handling for legacy and official Better Stack variable names.
56
+ *
57
+ * @returns Environment object with Better Stack configuration values
58
+ */
59
+ export function safeEnv() {
60
+ if (env) return env;
61
+
62
+ // Fallback values for resilience with proper priority
63
+ return {
64
+ // Legacy support
65
+ LOGTAIL_SOURCE_TOKEN:
66
+ process.env.LOGTAIL_SOURCE_TOKEN ?? process.env.BETTERSTACK_SOURCE_TOKEN ?? '',
67
+ BETTERSTACK_SOURCE_TOKEN:
68
+ process.env.BETTERSTACK_SOURCE_TOKEN ?? process.env.LOGTAIL_SOURCE_TOKEN ?? '',
69
+ NEXT_PUBLIC_LOGTAIL_TOKEN:
70
+ process.env.NEXT_PUBLIC_LOGTAIL_TOKEN ?? process.env.NEXT_PUBLIC_BETTERSTACK_TOKEN ?? '',
71
+ NEXT_PUBLIC_BETTERSTACK_TOKEN:
72
+ process.env.NEXT_PUBLIC_BETTERSTACK_TOKEN ?? process.env.NEXT_PUBLIC_LOGTAIL_TOKEN ?? '',
73
+
74
+ // Official Better Stack (preferred)
75
+ BETTER_STACK_SOURCE_TOKEN:
76
+ process.env.BETTER_STACK_SOURCE_TOKEN ??
77
+ process.env.LOGTAIL_SOURCE_TOKEN ??
78
+ process.env.BETTERSTACK_SOURCE_TOKEN ??
79
+ '',
80
+ BETTER_STACK_INGESTING_URL: process.env.BETTER_STACK_INGESTING_URL ?? '',
81
+ BETTER_STACK_LOG_LEVEL:
82
+ (process.env.BETTER_STACK_LOG_LEVEL as 'debug' | 'info' | 'warn' | 'error' | 'off') ?? 'info',
83
+ NEXT_PUBLIC_BETTER_STACK_SOURCE_TOKEN:
84
+ process.env.NEXT_PUBLIC_BETTER_STACK_SOURCE_TOKEN ??
85
+ process.env.NEXT_PUBLIC_LOGTAIL_TOKEN ??
86
+ process.env.NEXT_PUBLIC_BETTERSTACK_TOKEN ??
87
+ '',
88
+ NEXT_PUBLIC_BETTER_STACK_INGESTING_URL:
89
+ process.env.NEXT_PUBLIC_BETTER_STACK_INGESTING_URL ?? '',
90
+ NEXT_PUBLIC_BETTER_STACK_LOG_LEVEL:
91
+ (process.env.NEXT_PUBLIC_BETTER_STACK_LOG_LEVEL as
92
+ | 'debug'
93
+ | 'info'
94
+ | 'warn'
95
+ | 'error'
96
+ | 'off') ?? 'info',
97
+ };
98
+ }
99
+
100
+ // Export type
101
+ export type Env = typeof env;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @fileoverview Better Stack (Logtail) plugin exports
3
+ * Better Stack (Logtail) plugin exports
4
+ */
5
+
6
+ // Export plugin and factory
7
+ export { BetterStackPlugin, createBetterStackPlugin } from './plugin';
8
+ export type { BetterStackPluginConfig } from './plugin';
9
+
10
+ // Re-export Better Stack environment configuration
11
+ export { env, safeEnv } from './env';
12
+ export type { Env } from './env';
13
+
14
+ // Export types
15
+ export type { ObservabilityPlugin, ObservabilityServerPlugin } from '../../core/plugin';