feat(otel): support for custom resource attributes via config#telemetry.resource and OTEL_RESOURCE_ATTRIBUTES env var (#2704)
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@trigger.dev/sdk": patch
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
feat: add ability to set custom resource properties through trigger.config.ts or via the OTEL_RESOURCE_ATTRIBUTES env var
|
||||
@@ -497,7 +497,18 @@ export class SpanPresenter extends BasePresenter {
|
||||
duration: span.duration,
|
||||
events: span.events,
|
||||
style: span.style,
|
||||
properties: span.properties ? JSON.stringify(span.properties, null, 2) : undefined,
|
||||
properties:
|
||||
span.properties &&
|
||||
typeof span.properties === "object" &&
|
||||
Object.keys(span.properties).length > 0
|
||||
? JSON.stringify(span.properties, null, 2)
|
||||
: undefined,
|
||||
resourceProperties:
|
||||
span.resourceProperties &&
|
||||
typeof span.resourceProperties === "object" &&
|
||||
Object.keys(span.resourceProperties).length > 0
|
||||
? JSON.stringify(span.resourceProperties, null, 2)
|
||||
: undefined,
|
||||
entity: span.entity,
|
||||
metadata: span.metadata,
|
||||
triggeredRuns,
|
||||
|
||||
+11
@@ -1071,6 +1071,17 @@ function SpanEntity({ span }: { span: Span }) {
|
||||
showOpenInModal
|
||||
/>
|
||||
) : null}
|
||||
{span.resourceProperties !== undefined ? (
|
||||
<CodeBlock
|
||||
rowTitle="Resource properties"
|
||||
code={span.resourceProperties}
|
||||
maxLines={20}
|
||||
showLineNumbers={false}
|
||||
showCopyButton
|
||||
showTextWrapping
|
||||
showOpenInModal
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -825,12 +825,16 @@ export async function resolveVariablesForEnvironment(
|
||||
runtimeEnvironment: RuntimeEnvironmentForEnvRepo,
|
||||
parentEnvironment?: RuntimeEnvironmentForEnvRepo
|
||||
) {
|
||||
const projectSecrets = await environmentVariablesRepository.getEnvironmentVariables(
|
||||
let projectSecrets = await environmentVariablesRepository.getEnvironmentVariables(
|
||||
runtimeEnvironment.projectId,
|
||||
runtimeEnvironment.id,
|
||||
parentEnvironment?.id
|
||||
);
|
||||
|
||||
projectSecrets = renameVariables(projectSecrets, {
|
||||
OTEL_RESOURCE_ATTRIBUTES: "CUSTOM_OTEL_RESOURCE_ATTRIBUTES",
|
||||
});
|
||||
|
||||
const overridableTriggerVariables = await resolveOverridableTriggerVariables(runtimeEnvironment);
|
||||
|
||||
const builtInVariables =
|
||||
@@ -853,6 +857,15 @@ export async function resolveVariablesForEnvironment(
|
||||
return result;
|
||||
}
|
||||
|
||||
function renameVariables(variables: EnvironmentVariable[], renameMap: Record<string, string>) {
|
||||
return variables.map((variable) => {
|
||||
return {
|
||||
...variable,
|
||||
key: renameMap[variable.key] ?? variable.key,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
async function resolveOverridableTriggerVariables(
|
||||
runtimeEnvironment: RuntimeEnvironmentForEnvRepo
|
||||
) {
|
||||
|
||||
@@ -184,7 +184,10 @@ export class ClickhouseEventRepository implements IEventRepository {
|
||||
message: event.message,
|
||||
kind: this.createEventToTaskEventV1InputKind(event),
|
||||
status: this.createEventToTaskEventV1InputStatus(event),
|
||||
attributes: this.createEventToTaskEventV1InputAttributes(event.properties),
|
||||
attributes: this.createEventToTaskEventV1InputAttributes(
|
||||
event.properties,
|
||||
event.resourceProperties
|
||||
),
|
||||
metadata: this.createEventToTaskEventV1InputMetadata(event),
|
||||
expires_at: convertDateToClickhouseDateTime(
|
||||
new Date(Date.now() + 365 * 24 * 60 * 60 * 1000) // 1 year
|
||||
@@ -392,7 +395,24 @@ export class ClickhouseEventRepository implements IEventRepository {
|
||||
return "OK";
|
||||
}
|
||||
|
||||
private createEventToTaskEventV1InputAttributes(attributes: Attributes): Record<string, unknown> {
|
||||
private createEventToTaskEventV1InputAttributes(
|
||||
attributes: Attributes,
|
||||
resourceAttributes?: Attributes
|
||||
): Record<string, unknown> {
|
||||
if (!attributes && !resourceAttributes) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
...this.createAttributesToInputAttributes(attributes),
|
||||
...this.createAttributesToInputAttributes(resourceAttributes, "$resource"),
|
||||
};
|
||||
}
|
||||
|
||||
private createAttributesToInputAttributes(
|
||||
attributes: Attributes | undefined,
|
||||
key?: string
|
||||
): Record<string, unknown> {
|
||||
if (!attributes) {
|
||||
return {};
|
||||
}
|
||||
@@ -406,6 +426,12 @@ export class ClickhouseEventRepository implements IEventRepository {
|
||||
const unflattenedAttributes = unflattenAttributes(publicAttributes);
|
||||
|
||||
if (unflattenedAttributes && typeof unflattenedAttributes === "object") {
|
||||
if (key) {
|
||||
return {
|
||||
[key]: unflattenedAttributes,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...unflattenedAttributes,
|
||||
};
|
||||
@@ -1103,6 +1129,7 @@ export class ClickhouseEventRepository implements IEventRepository {
|
||||
events: [],
|
||||
style: {},
|
||||
properties: undefined,
|
||||
resourceProperties: undefined,
|
||||
entity: {
|
||||
type: undefined,
|
||||
id: undefined,
|
||||
@@ -1177,8 +1204,19 @@ export class ClickhouseEventRepository implements IEventRepository {
|
||||
}
|
||||
}
|
||||
|
||||
if (!span.properties && typeof record.attributes_text === "string") {
|
||||
span.properties = this.#parseAttributes(record.attributes_text);
|
||||
if (
|
||||
(span.properties == null ||
|
||||
(typeof span.properties === "object" && Object.keys(span.properties).length === 0)) &&
|
||||
typeof record.attributes_text === "string"
|
||||
) {
|
||||
const parsedAttributes = this.#parseAttributes(record.attributes_text);
|
||||
const resourceAttributes = parsedAttributes["$resource"];
|
||||
|
||||
// Remove the $resource key from the attributes
|
||||
delete parsedAttributes["$resource"];
|
||||
|
||||
span.properties = parsedAttributes;
|
||||
span.resourceProperties = resourceAttributes as Record<string, unknown> | undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ export type CreateEventInput = Omit<
|
||||
| "links"
|
||||
> & {
|
||||
properties: Attributes;
|
||||
resourceProperties?: Attributes;
|
||||
metadata: Attributes | undefined;
|
||||
style: Attributes | undefined;
|
||||
};
|
||||
@@ -209,6 +210,7 @@ export type SpanDetail = {
|
||||
events: SpanEvents; // Timeline events, SpanEvents component
|
||||
style: TaskEventStyle; // Icons, variants, accessories (RunIcon, SpanTitle)
|
||||
properties: Record<string, unknown> | string | number | boolean | null | undefined; // Displayed as JSON in span properties (CodeBlock)
|
||||
resourceProperties?: Record<string, unknown> | string | number | boolean | null | undefined; // Displayed as JSON in span resource properties (CodeBlock)
|
||||
|
||||
// ============================================================================
|
||||
// Entity & Relationships
|
||||
|
||||
@@ -204,6 +204,24 @@ function convertLogsToCreateableEvents(
|
||||
|
||||
const resourceProperties = extractEventProperties(resourceAttributes);
|
||||
|
||||
const userDefinedResourceAttributes = truncateAttributes(
|
||||
convertKeyValueItemsToMap(resourceAttributes ?? [], [], undefined, [
|
||||
SemanticInternalAttributes.USAGE,
|
||||
SemanticInternalAttributes.SPAN,
|
||||
SemanticInternalAttributes.METADATA,
|
||||
SemanticInternalAttributes.STYLE,
|
||||
SemanticInternalAttributes.METRIC_EVENTS,
|
||||
SemanticInternalAttributes.TRIGGER,
|
||||
"process",
|
||||
"sdk",
|
||||
"service",
|
||||
"ctx",
|
||||
"cli",
|
||||
"cloud",
|
||||
]),
|
||||
spanAttributeValueLengthLimit
|
||||
);
|
||||
|
||||
const taskEventStore =
|
||||
extractStringAttribute(resourceAttributes, [SemanticInternalAttributes.TASK_EVENT_STORE]) ??
|
||||
env.EVENT_REPOSITORY_DEFAULT_STORE;
|
||||
@@ -249,6 +267,7 @@ function convertLogsToCreateableEvents(
|
||||
status: logLevelToEventStatus(log.severityNumber),
|
||||
startTime: log.timeUnixNano,
|
||||
properties,
|
||||
resourceProperties: userDefinedResourceAttributes,
|
||||
style: convertKeyValueItemsToMap(
|
||||
pickAttributes(log.attributes ?? [], SemanticInternalAttributes.STYLE),
|
||||
[]
|
||||
@@ -285,6 +304,24 @@ function convertSpansToCreateableEvents(
|
||||
|
||||
const resourceProperties = extractEventProperties(resourceAttributes);
|
||||
|
||||
const userDefinedResourceAttributes = truncateAttributes(
|
||||
convertKeyValueItemsToMap(resourceAttributes ?? [], [], undefined, [
|
||||
SemanticInternalAttributes.USAGE,
|
||||
SemanticInternalAttributes.SPAN,
|
||||
SemanticInternalAttributes.METADATA,
|
||||
SemanticInternalAttributes.STYLE,
|
||||
SemanticInternalAttributes.METRIC_EVENTS,
|
||||
SemanticInternalAttributes.TRIGGER,
|
||||
"process",
|
||||
"sdk",
|
||||
"service",
|
||||
"ctx",
|
||||
"cli",
|
||||
"cloud",
|
||||
]),
|
||||
spanAttributeValueLengthLimit
|
||||
);
|
||||
|
||||
const taskEventStore =
|
||||
extractStringAttribute(resourceAttributes, [SemanticInternalAttributes.TASK_EVENT_STORE]) ??
|
||||
env.EVENT_REPOSITORY_DEFAULT_STORE;
|
||||
@@ -336,6 +373,7 @@ function convertSpansToCreateableEvents(
|
||||
events: spanEventsToEventEvents(span.events ?? []),
|
||||
duration: span.endTimeUnixNano - span.startTimeUnixNano,
|
||||
properties,
|
||||
resourceProperties: userDefinedResourceAttributes,
|
||||
style: convertKeyValueItemsToMap(
|
||||
pickAttributes(span.attributes ?? [], SemanticInternalAttributes.STYLE),
|
||||
[]
|
||||
|
||||
@@ -455,9 +455,6 @@ class DevSupervisor implements WorkerRuntime {
|
||||
TRIGGER_API_URL: this.options.client.apiURL,
|
||||
TRIGGER_SECRET_KEY: this.options.client.accessToken!,
|
||||
OTEL_EXPORTER_OTLP_COMPRESSION: "none",
|
||||
OTEL_RESOURCE_ATTRIBUTES: JSON.stringify({
|
||||
[SemanticInternalAttributes.PROJECT_DIR]: this.options.config.workingDir,
|
||||
}),
|
||||
OTEL_IMPORT_HOOK_INCLUDES,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -209,6 +209,7 @@ async function doBootstrap() {
|
||||
logExporters: config.telemetry?.logExporters ?? [],
|
||||
diagLogLevel: (env.TRIGGER_OTEL_LOG_LEVEL as TracingDiagnosticLogLevel) ?? "none",
|
||||
forceFlushTimeoutMillis: 30_000,
|
||||
resource: config.telemetry?.resource,
|
||||
});
|
||||
|
||||
const otelTracer: Tracer = tracingSDK.getTracer("trigger-dev-worker", VERSION);
|
||||
|
||||
@@ -188,6 +188,7 @@ async function doBootstrap() {
|
||||
forceFlushTimeoutMillis: 30_000,
|
||||
exporters: config.telemetry?.exporters ?? [],
|
||||
logExporters: config.telemetry?.logExporters ?? [],
|
||||
resource: config.telemetry?.resource,
|
||||
});
|
||||
|
||||
const otelTracer: Tracer = tracingSDK.getTracer("trigger-dev-worker", VERSION);
|
||||
|
||||
@@ -2,7 +2,13 @@ import dotenv from "dotenv";
|
||||
import { resolve } from "node:path";
|
||||
import { env } from "std-env";
|
||||
|
||||
const ENVVAR_FILES = [".env", ".env.development", ".env.local", ".env.development.local", "dev.vars"];
|
||||
const ENVVAR_FILES = [
|
||||
".env",
|
||||
".env.development",
|
||||
".env.local",
|
||||
".env.development.local",
|
||||
"dev.vars",
|
||||
];
|
||||
|
||||
export function resolveDotEnvVars(cwd?: string, envFile?: string) {
|
||||
const result: { [key: string]: string } = {};
|
||||
@@ -23,6 +29,11 @@ export function resolveDotEnvVars(cwd?: string, envFile?: string) {
|
||||
delete result.TRIGGER_SECRET_KEY;
|
||||
delete result.OTEL_EXPORTER_OTLP_ENDPOINT;
|
||||
|
||||
if (result.OTEL_RESOURCE_ATTRIBUTES) {
|
||||
result.CUSTOM_OTEL_RESOURCE_ATTRIBUTES = result.OTEL_RESOURCE_ATTRIBUTES;
|
||||
delete result.OTEL_RESOURCE_ATTRIBUTES;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import type {
|
||||
import type { LogLevel } from "./logger/taskLogger.js";
|
||||
import type { MachinePresetName } from "./schemas/common.js";
|
||||
import { LogRecordExporter } from "@opentelemetry/sdk-logs";
|
||||
import type { Resource } from "@opentelemetry/resources";
|
||||
|
||||
export type CompatibilityFlag = "run_engine_v2";
|
||||
|
||||
@@ -107,6 +108,13 @@ export type TriggerConfig = {
|
||||
* @see https://trigger.dev/docs/config/config-file#exporters
|
||||
*/
|
||||
logExporters?: Array<LogRecordExporter>;
|
||||
|
||||
/**
|
||||
* Resource to use for OpenTelemetry. This is useful if you want to add custom resources to your tasks.
|
||||
*
|
||||
* @see https://trigger.dev/docs/config/config-file#resource
|
||||
*/
|
||||
resource?: Resource;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,7 +10,12 @@ import { TraceState } from "@opentelemetry/core";
|
||||
import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
|
||||
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
|
||||
import { registerInstrumentations, type Instrumentation } from "@opentelemetry/instrumentation";
|
||||
import { detectResources, processDetector, resourceFromAttributes } from "@opentelemetry/resources";
|
||||
import {
|
||||
detectResources,
|
||||
processDetector,
|
||||
Resource,
|
||||
resourceFromAttributes,
|
||||
} from "@opentelemetry/resources";
|
||||
import {
|
||||
BatchLogRecordProcessor,
|
||||
LogRecordExporter,
|
||||
@@ -64,6 +69,7 @@ export type TracingSDKConfig = {
|
||||
exporters?: SpanExporter[];
|
||||
logExporters?: LogRecordExporter[];
|
||||
diagLogLevel?: TracingDiagnosticLogLevel;
|
||||
resource?: Resource;
|
||||
};
|
||||
|
||||
const idGenerator = new RandomIdGenerator();
|
||||
@@ -84,6 +90,10 @@ export class TracingSDK {
|
||||
? JSON.parse(envResourceAttributesSerialized)
|
||||
: {};
|
||||
|
||||
const customEnvResourceAttributes = parseOtelResourceAttributes(
|
||||
getEnvVar("CUSTOM_OTEL_RESOURCE_ATTRIBUTES")
|
||||
);
|
||||
|
||||
const commonResources = detectResources({
|
||||
detectors: [processDetector],
|
||||
})
|
||||
@@ -99,7 +109,9 @@ export class TracingSDK {
|
||||
})
|
||||
)
|
||||
.merge(resourceFromAttributes(envResourceAttributes))
|
||||
.merge(resourceFromAttributes(taskContext.resourceAttributes));
|
||||
.merge(resourceFromAttributes(customEnvResourceAttributes))
|
||||
.merge(resourceFromAttributes(taskContext.resourceAttributes))
|
||||
.merge(config.resource ?? resourceFromAttributes({}));
|
||||
|
||||
const spanExporter = new OTLPTraceExporter({
|
||||
url: `${config.url}/v1/traces`,
|
||||
@@ -489,3 +501,74 @@ function isTraceFlagSampled(traceFlags?: number): boolean {
|
||||
|
||||
return (traceFlags & TraceFlags.SAMPLED) === TraceFlags.SAMPLED;
|
||||
}
|
||||
|
||||
function isPrintableAscii(str: string): boolean {
|
||||
// printable ASCII: 0x20 (space) .. 0x7E (~)
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
const code = str.charCodeAt(i);
|
||||
if (code < 0x20 || code > 0x7e) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function isValid(name: string | undefined): boolean {
|
||||
if (!name) return false;
|
||||
return typeof name === "string" && name.length <= 255 && isPrintableAscii(name);
|
||||
}
|
||||
|
||||
function isValidAndNotEmpty(name: string | undefined): boolean {
|
||||
if (!name) return false;
|
||||
return isValid(name) && name.length > 0;
|
||||
}
|
||||
|
||||
export function parseOtelResourceAttributes(
|
||||
rawEnvAttributes: string | undefined | null
|
||||
): Record<string, string> {
|
||||
if (!rawEnvAttributes) return {};
|
||||
|
||||
const COMMA = ",";
|
||||
const KV = "=";
|
||||
const attributes: Record<string, string> = {};
|
||||
|
||||
// use negative limit to support trailing empty attribute
|
||||
const rawAttributes = rawEnvAttributes.split(COMMA, -1);
|
||||
for (const rawAttribute of rawAttributes) {
|
||||
const keyValuePair = rawAttribute.split(KV, -1);
|
||||
if (keyValuePair.length !== 2) {
|
||||
// skip invalid pair
|
||||
continue;
|
||||
}
|
||||
let [key, value] = keyValuePair;
|
||||
key = key?.trim();
|
||||
// trim and remove surrounding double quotes
|
||||
value = value?.trim().replace(/^"|"$/g, "");
|
||||
|
||||
if (!value || !key) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isValidAndNotEmpty(key)) {
|
||||
throw new Error(
|
||||
`Attribute key should be a ASCII string with a length greater than 0 and not exceed 255 characters.`
|
||||
);
|
||||
}
|
||||
if (!isValid(value)) {
|
||||
throw new Error(
|
||||
`Attribute value should be a ASCII string with a length not exceed 255 characters.`
|
||||
);
|
||||
}
|
||||
|
||||
// decode percent-encoding (deployment%20name -> deployment name)
|
||||
try {
|
||||
attributes[key] = decodeURIComponent(value);
|
||||
} catch (e: unknown) {
|
||||
// decodeURIComponent can throw for malformed sequences; rethrow or handle
|
||||
if (e instanceof Error) {
|
||||
throw new Error(`Failed to decode attribute value for key ${key}: ${e.message}`);
|
||||
}
|
||||
throw new Error(`Failed to decode attribute value for key ${key}`);
|
||||
}
|
||||
}
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
Generated
+40
@@ -2636,6 +2636,25 @@ importers:
|
||||
specifier: ^5
|
||||
version: 5.5.4
|
||||
|
||||
references/telemetry:
|
||||
dependencies:
|
||||
'@opentelemetry/resources':
|
||||
specifier: 2.2.0
|
||||
version: 2.2.0(@opentelemetry/api@1.9.0)
|
||||
'@trigger.dev/sdk':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/trigger-sdk
|
||||
devDependencies:
|
||||
'@types/node':
|
||||
specifier: ^20
|
||||
version: 20.14.14
|
||||
trigger.dev:
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/cli-v3
|
||||
typescript:
|
||||
specifier: ^5
|
||||
version: 5.5.4
|
||||
|
||||
references/test-tasks:
|
||||
dependencies:
|
||||
'@trigger.dev/sdk':
|
||||
@@ -9952,6 +9971,16 @@ packages:
|
||||
'@opentelemetry/semantic-conventions': 1.36.0
|
||||
dev: false
|
||||
|
||||
/@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0):
|
||||
resolution: {integrity: sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==}
|
||||
engines: {node: ^18.19.0 || >=20.6.0}
|
||||
peerDependencies:
|
||||
'@opentelemetry/api': '>=1.0.0 <1.10.0'
|
||||
dependencies:
|
||||
'@opentelemetry/api': 1.9.0
|
||||
'@opentelemetry/semantic-conventions': 1.36.0
|
||||
dev: false
|
||||
|
||||
/@opentelemetry/exporter-logs-otlp-grpc@0.203.0(@opentelemetry/api@1.9.0):
|
||||
resolution: {integrity: sha512-g/2Y2noc/l96zmM+g0LdeuyYKINyBwN6FJySoU15LHPLcMN/1a0wNk2SegwKcxrRdE7Xsm7fkIR5n6XFe3QpPw==}
|
||||
engines: {node: ^18.19.0 || >=20.6.0}
|
||||
@@ -10703,6 +10732,17 @@ packages:
|
||||
'@opentelemetry/semantic-conventions': 1.36.0
|
||||
dev: false
|
||||
|
||||
/@opentelemetry/resources@2.2.0(@opentelemetry/api@1.9.0):
|
||||
resolution: {integrity: sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==}
|
||||
engines: {node: ^18.19.0 || >=20.6.0}
|
||||
peerDependencies:
|
||||
'@opentelemetry/api': '>=1.3.0 <1.10.0'
|
||||
dependencies:
|
||||
'@opentelemetry/api': 1.9.0
|
||||
'@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0)
|
||||
'@opentelemetry/semantic-conventions': 1.36.0
|
||||
dev: false
|
||||
|
||||
/@opentelemetry/sdk-logs@0.203.0(@opentelemetry/api@1.9.0):
|
||||
resolution: {integrity: sha512-vM2+rPq0Vi3nYA5akQD2f3QwossDnTDLvKbea6u/A2NZ3XDkPxMfo/PNrDoXhDUD/0pPo2CdH5ce/thn9K0kLw==}
|
||||
engines: {node: ^18.19.0 || >=20.6.0}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "references-telemetry",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "trigger dev",
|
||||
"deploy": "trigger deploy"
|
||||
},
|
||||
"dependencies": {
|
||||
"@trigger.dev/sdk": "workspace:*",
|
||||
"@opentelemetry/resources": "2.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20",
|
||||
"trigger.dev": "workspace:*",
|
||||
"typescript": "^5"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { logger, task } from "@trigger.dev/sdk";
|
||||
|
||||
export const telemetryTestTask = task({
|
||||
id: "telemetry-test",
|
||||
run: async (payload: any, { ctx }) => {
|
||||
logger.info("Hello, world!", { payload, ctx });
|
||||
return { message: "Hello, world!" };
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
import { defineConfig } from "@trigger.dev/sdk";
|
||||
import { resourceFromAttributes } from "@opentelemetry/resources";
|
||||
|
||||
export default defineConfig({
|
||||
project: process.env.TRIGGER_PROJECT_REF!,
|
||||
dirs: ["./src/trigger"],
|
||||
maxDuration: 3600,
|
||||
telemetry: {
|
||||
resource: resourceFromAttributes({
|
||||
"foo.bar": "telemetry-test",
|
||||
"foo.baz": "1.0.0",
|
||||
}),
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2023",
|
||||
"module": "Node16",
|
||||
"moduleResolution": "Node16",
|
||||
"esModuleInterop": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"customConditions": ["@triggerdotdev/source"],
|
||||
"jsx": "preserve",
|
||||
"lib": ["DOM", "DOM.Iterable"],
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["./src/**/*.ts", "trigger.config.ts"]
|
||||
}
|
||||
Reference in New Issue
Block a user