
Opentelemetry Instrumentation
- 20 installs
- 4 repo stars
- Updated June 9, 2026
- coralogix/cx-skills
Instrument Java, Python, Node.js, .NET, and Go apps with OpenTelemetry SDKs to send traces, metrics, and logs to Coralogix.
About
Guides SDK-side OpenTelemetry setup, covering OTLP exporter env vars, Coralogix resource attributes, samplers, and Kubernetes Operator injection. A developer uses it to wire an application's telemetry to Coralogix or debug missing traces, metrics, or logs.
- Covers Java, Python, Node.js, .NET, and Go SDK instrumentation
- Handles OTLP env vars, resource attributes, and Kubernetes Operator injection
Opentelemetry Instrumentation by the numbers
- 20 all-time installs (skills.sh)
- Ranked #915 of 1,435 DevOps & CI/CD skills by installs in the Skillselion catalog
- Data as of Jul 29, 2026 (Skillselion catalog sync)
npx skills add https://github.com/coralogix/cx-skills --skill opentelemetry-instrumentationAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 20 |
|---|---|
| repo stars | ★ 4 |
| Last updated | June 9, 2026 |
| Repository | coralogix/cx-skills ↗ |
What it does
Instrument Java, Python, Node.js, .NET, and Go apps with OpenTelemetry SDKs to send traces, metrics, and logs to Coralogix.
Files
OpenTelemetry SDK Instrumentation for Coralogix
When to Use This Skill
| Use case | What to do |
|---|---|
| Choose a language / decide where to start | Load language-selector.md first — it has the decision tree for language, signal, mode, and export path |
| Generate setup for a specific language | Load the language reference after confirming the SDK: java.md, python.md, nodejs.md, dotnet.md, go.md |
| Configure OTLP endpoint, region, or authentication | Load coralogix-endpoints.md — covers regional domains, OTLP host:port, auth header format |
| Generate a complete user-facing answer | Load output-templates.md — checklist structure with assumptions, code, validation steps |
| Diagnose missing traces, metrics, or logs from the SDK | Load troubleshooting.md — symptom → root-cause table for SDK-side failures |
Load order: language-selector.md → language ref → coralogix-endpoints.md → output-templates.md (always last). Load troubleshooting.md only for debugging.
Answer Rules
Before answering (agent mode):
- Always call `list_references()` first, then `read_reference(...)` for the relevant files (language selector + the target language + endpoints; add troubleshooting only when debugging). Do not answer from memory if the references could affect correctness.
- Use the structure/checklists in [output-templates.md](references/output-templates.md) for any user-facing response; keep your own prose minimal and actionable.
Always include in generated answers:
- Required env vars (names only) — include these in any “copy/paste” setup:
OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_HEADERS, OTEL_SERVICE_NAME, OTEL_RESOURCE_ATTRIBUTES (plus OTEL_*_EXPORTER / OTEL_EXPORTER_OTLP_*_PROTOCOL when choosing signals/protocol). For exact per-language endpoint formats and the Python %20 env-var rule, use coralogix-endpoints.md.
- Required resource attributes —
service.name(APM catalog/transactions),cx.application.name+cx.subsystem.name(routing, TCO, APM grouping),telemetry.sdk.language(auto-set; do not strip). Missing any silently degrades APM. Additional k8s/host attributes are covered in each language reference.
- Telemetry quality. Low-cardinality span names, no sensitive data, bounded metric attributes, structured single-line logs with trace/span IDs, validation steps for the signal. Never approve user-scoped values (
user_id,tenant_id,request_id,session_id) as metric labels — they cause unbounded cardinality and will explode metric storage. - Direct vs collector routing rule: Default to direct OTLP for dev/test environments, simple single-service production deployments, or when no collector infrastructure exists. Default to via-collector for Kubernetes workloads needing pod/namespace enrichment (
k8sattributes), tail sampling, multi-service shared key management, or buffered retry/file persistence requirements. When the deployment context is unknown, show both options using the tradeoff table in language-selector.md. - Collector config is out of scope. Redirect to
opentelemetry-collector— do not partially answer pipeline or processor questions.
High-Risk Gotchas (Do Not Guess)
Keep this list short and only use it when the user’s symptom matches. For details, defer to the language references.
- Java agent:
opentelemetry-javaagent.jar+JAVA_TOOL_OPTIONS="-javaagent:/path/to/opentelemetry-javaagent.jar". - Java/.NET gRPC endpoint: must be a full URI
https://ingress.<region>.coralogix.com:443(URI parsing breaks barehost:port). - Python auth header: env var needs
%20(Authorization=Bearer%20<KEY>); programmatic headers use a tuple sequence with lowercase key + literal space (("authorization", f"Bearer {token}")). - Node.js HTTP/proto: exporter
urlmust include/v1/traces(https://ingress.<region>.coralogix.com:443/v1/traces); gRPC doesn’t. - Go gRPC:
credentials.NewTLS(nil)and bare endpointingress.<region>.coralogix.com:443(nohttps://inWithEndpoint). - Go metrics cardinality:
sdk/metricdefaults to a cardinality limit of2000; useWithCardinalityLimit(0)only when you intentionally need unlimited series, and expectotel.metric.overflow=truewhen the limit is hit. - .NET OTLP disk retry:
OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY=disknow requiresOTEL_DOTNET_EXPERIMENTAL_OTLP_DISK_RETRY_DIRECTORY_PATH; do not rely on an implicit temp-directory fallback. - Transactions: require
CoralogixTransactionSampler(Node.js:@coralogix/opentelemetry); bundledNODE_OPTIONSauto-instr doesn’t support Transactions. - Short-lived Python scripts:
SimpleSpanProcessorvsBatchSpanProcessor; metrics needPeriodicExportingMetricReaderflush/wait. - .NET Framework incoming propagation:
OpenTelemetry.Instrumentation.AspNet+AddAspNetInstrumentation().
Workflow
- New setup: language-selector.md → language ref + coralogix-endpoints.md → generate with output-templates.md.
- Code review: language ref → review checklist in output-templates.md.
- Debugging: troubleshooting.md first; escalate to language ref only if SDK-side cause confirmed.
Limitations
- OTel Collector / OTTL — use
opentelemetry-collectororopentelemetry-ottl. - Lambda / serverless — use Coralogix Lambda layer docs;
Payload Too LargeOTLP errors are Lambda-layer concerns, not SDK. - PHP, eBPF auto-instrumentation — not covered.
- Coralogix platform internals (data routing, index policies, APM UI config) — platform topics.
Deprecated native SDKs
Native Coralogix SDKs are EOL June 30, 2026 — redirect to OTel and do not provide configuration for legacy packages.
Upstream references
Coralogix OTel instrumentation: Java · Python · Node.js · .NET · Go
export-path-decision
{
"context": "Evaluating a Coralogix support response for this user question:\n\nShould I use the OpenTelemetry Collector or send directly from my app SDK to Coralogix?",
"type": "weighted_checklist",
"checklist": [
{
"name": "mentions-collector",
"description": "The response contains \"collector\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-direct",
"description": "The response contains \"direct\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "no-if-it-recommends-one-path-without-mentioni",
"description": "Explains the tradeoffs: direct export is simpler and good for getting started, while via-collector adds batching, retry, enrichment (k8sattributes, resource detection), and tail sampling. Does not recommend one over the other without asking about the user's context. FAIL if it recommends one path without mentioning the tradeoff.",
"max_score": 2,
"category": "MUST_NOT"
}
]
}
direct-vs-collector-tradeoffs
You are a Coralogix support expert. A user has asked the following question:
---
Should I use the OpenTelemetry Collector or send directly from my app SDK to Coralogix?
---
dotnet-auto-endpoint-https
{
"context": "Evaluating a Coralogix support response for this user question:\n\nMy .NET auto-instrumented service has these env vars set but no traces appear:\n OTEL_EXPORTER_OTLP_ENDPOINT=ingress.eu1.coralogix.com:443\n OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer myKey\nWhat am I missing?",
"type": "weighted_checklist",
"checklist": [
{
"name": "mentions-https",
"description": "The response contains \"https://\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "no-only-response-identifies-otel-traces-expor",
"description": "Identifies that OTEL_EXPORTER_OTLP_ENDPOINT is missing the https:// URI scheme \u2014 the .NET OTLP exporter requires a full URI, so the correct value is https://ingress.eu1.coralogix.com:443, not the bare host:port accepted by Python, Node.js, and Go (Java also requires https://, so do not cite Java as an example of bare host:port being valid). OTEL_TRACES_EXPORTER defaults to \"otlp\" in .NET auto-instrumentation and is NOT a root cause. FAIL only if the response identifies OTEL_TRACES_EXPORTER as the PRIMARY or SOLE root cause and does not mention the missing https:// scheme \u2014 mentioning OTEL_TRACES_EXPORTER as a secondary note is acceptable as long as the missing https:// scheme is clearly identified as the fix.",
"max_score": 2,
"category": "MUST_NOT"
}
]
}
dotnet-auto-endpoint-missing-https-scheme
You are a Coralogix support expert. A user has asked the following question:
---
My .NET auto-instrumented service has these env vars set but no traces appear: OTEL_EXPORTER_OTLP_ENDPOINT=ingress.eu1.coralogix.com:443 OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer myKey What am I missing?
---
legacy-sdk-deprecation
{
"context": "Evaluating a Coralogix support response for this user question:\n\nWe have a .NET Core service using CoralogixCoreSDK. We want to add trace correlation to our logs. How do we do that with CoralogixCoreSDK?",
"type": "weighted_checklist",
"checklist": [
{
"name": "mentions-deprecated",
"description": "The response contains \"deprecated\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-opentelemetry",
"description": "The response contains \"opentelemetry\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-june-30",
"description": "The response contains \"June 30\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "no-if-it-provides-any-coralogixcoresdk-config",
"description": "Recognizes that CoralogixCoreSDK is a deprecated Coralogix .NET SDK (EOL June 30, 2026) and redirects the user to OpenTelemetry .NET instrumentation rather than explaining how to add trace correlation within the legacy SDK. FAIL if it provides any CoralogixCoreSDK configuration guidance without immediately flagging the deprecation and redirecting to OTel.",
"max_score": 2,
"category": "MUST_NOT"
}
]
}
dotnet-coralogixcoresdk-deprecation-redirect
You are a Coralogix support expert. A user has asked the following question:
---
We have a .NET Core service using CoralogixCoreSDK. We want to add trace correlation to our logs. How do we do that with CoralogixCoreSDK?
---
dotnet-manual-instrumentation
{
"context": "Evaluating a Coralogix support response for this user question:\n\nI've set up .NET OpenTelemetry manual instrumentation for my eu1 service. My OTLP exporter reports 200 OK responses, so data is arriving at Coralogix. But nothing appears in the APM views \u2014 no service in the Service Catalog, no traces in Explore. My endpoint is https://ingress.eu1.coralogix.com:443. What resource attributes could cause data to arrive successfully but not appear in APM?",
"type": "weighted_checklist",
"checklist": [
{
"name": "mentions-cx-application-name",
"description": "The response contains \"cx.application.name\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-cx-subsystem-name",
"description": "The response contains \"cx.subsystem.name\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-service-name",
"description": "The response contains \"service.name\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "no-if-it-suggests-the-issue-is-in-the-endpoin",
"description": "Identifies that missing resource attributes are the cause: all three of service.name, (required for APM Service Catalog entry and transaction grouping), cx.application.name (required for data routing to the correct Coralogix team), and cx.subsystem.name (required for TCO policy and APM grouping) must be set. Data arrives (200 OK) but is not visible in APM or routed correctly when any of these are missing. FAIL if it suggests the issue is in the endpoint format or authentication, or if it omits any of the three required attributes.",
"max_score": 2,
"category": "MUST_NOT"
}
]
}
dotnet-manual-sdk-https-scheme-eu1
You are a Coralogix support expert. A user has asked the following question:
---
I've set up .NET OpenTelemetry manual instrumentation for my eu1 service. My OTLP exporter reports 200 OK responses, so data is arriving at Coralogix. But nothing appears in the APM views — no service in the Service Catalog, no traces in Explore. My endpoint is https://ingress.eu1.coralogix.com:443. What resource attributes could cause data to arrive successfully but not appear in APM?
---
legacy-sdk-deprecation
{
"context": "Evaluating a Coralogix support response for this user question:\n\nWe're currently using go-coralogix-sdk to send logs from our Go service to Coralogix. Is this still supported and should we keep using it?",
"type": "weighted_checklist",
"checklist": [
{
"name": "mentions-deprecated",
"description": "The response contains \"deprecated\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-opentelemetry",
"description": "The response contains \"opentelemetry\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-june-30",
"description": "The response contains \"June 30\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "no-if-it-explains-how-to-continue-using-go-co",
"description": "Informs the user that go-coralogix-sdk is deprecated with an end-of-life date of June 30, 2026, and directs them to use the OpenTelemetry Go SDK instead. FAIL if it explains how to continue using go-coralogix-sdk, omits the deprecation, or does not redirect to OpenTelemetry.",
"max_score": 2,
"category": "MUST_NOT"
}
]
}
go-legacy-sdk-deprecation-redirect
You are a Coralogix support expert. A user has asked the following question:
---
We're currently using go-coralogix-sdk to send logs from our Go service to Coralogix. Is this still supported and should we keep using it?
---
go-manual-tls-setup
{
"context": "Evaluating a Coralogix support response for this user question:\n\nHow do I instrument a Go application to send metrics and traces to Coralogix ap2 region?",
"type": "weighted_checklist",
"checklist": [
{
"name": "mentions-ingress-ap2-coralogix-com-443",
"description": "The response contains \"ingress.ap2.coralogix.com:443\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-credentials-newtls-nil",
"description": "The response contains \"credentials.NewTLS(nil)\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-cx-application-name",
"description": "The response contains \"cx.application.name\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-coralogix-api-key",
"description": "The response contains \"CORALOGIX_API_KEY\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "no-if-it-recommends-go-auto-instrumentation-o",
"description": "Covers Go manual instrumentation (code or detailed prose both acceptable) with: TLS credentials (credentials.NewTLS(nil)) on all exporters, an Authorization header map (\"Bearer \" + token \u2014 note literal space), the coralogix-opentelemetry-go sampler for APM transactions, and the endpoint ingress.ap2.coralogix.com:443 without an https:// scheme in the gRPC dial options. FAIL if it recommends Go auto-instrumentation, omits credentials.NewTLS(nil), or uses https:// in the gRPC endpoint.",
"max_score": 2,
"category": "MUST_NOT"
}
]
}
go-manual-tls-sampler-ap2-setup
You are a Coralogix support expert. A user has asked the following question:
---
How do I instrument a Go application to send metrics and traces to Coralogix ap2 region?
---
go-required-env-vars
{
"context": "Evaluating a Coralogix support response for this user question:\n\nGive me the required direct-export environment variables for sending OpenTelemetry traces from a Go service to Coralogix in eu2.",
"type": "weighted_checklist",
"checklist": [
{
"name": "mentions-otel-exporter-otlp-endpoint",
"description": "The response contains \"OTEL_EXPORTER_OTLP_ENDPOINT\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-ingress-eu2-coralogix-com-443",
"description": "The response contains \"ingress.eu2.coralogix.com:443\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-otel-exporter-otlp-headers",
"description": "The response contains \"OTEL_EXPORTER_OTLP_HEADERS\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-otel-service-name",
"description": "The response contains \"OTEL_SERVICE_NAME\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-otel-resource-attributes",
"description": "The response contains \"OTEL_RESOURCE_ATTRIBUTES\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "no-if-it-uses-eu2-coralogix-com-443-without-t",
"description": "Shows all required env vars: OTEL_EXPORTER_OTLP_ENDPOINT using the gRPC endpoint ingress.eu2.coralogix.com:443, OTEL_EXPORTER_OTLP_HEADERS with Authorization=Bearer, OTEL_SERVICE_NAME, and OTEL_RESOURCE_ATTRIBUTES containing cx.application.name and cx.subsystem.name. FAIL if it uses eu2.coralogix.com:443 without the ingress prefix.",
"max_score": 2,
"category": "MUST_NOT"
}
]
}
go-required-env-vars-direct-eu2
You are a Coralogix support expert. A user has asked the following question:
---
Give me the required direct-export environment variables for sending OpenTelemetry traces from a Go service to Coralogix in eu2.
---
java-agent-setup
{
"context": "Evaluating a Coralogix support response for this user question:\n\nI want to instrument my Java Spring Boot application to send traces to Coralogix. We're on the eu2 region. How do I set it up?",
"type": "weighted_checklist",
"checklist": [
{
"name": "mentions-opentelemetry-javaagent-jar",
"description": "The response contains \"opentelemetry-javaagent.jar\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-ingress-eu2-coralogix-com-443",
"description": "The response contains \"ingress.eu2.coralogix.com:443\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-otel-exporter-otlp-headers",
"description": "The response contains \"OTEL_EXPORTER_OTLP_HEADERS\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-cx-application-name",
"description": "The response contains \"cx.application.name\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-cx-subsystem-name",
"description": "The response contains \"cx.subsystem.name\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "no-if-it-uses-bare-ingress-eu2-coralogix-com",
"description": "Provides a complete Java agent setup: links to the official OpenTelemetry Java getting-started docs for installation, sets JAVA_TOOL_OPTIONS with -javaagent, sets OTEL_EXPORTER_OTLP_ENDPOINT to https://ingress.eu2.coralogix.com:443 (full URI with https:// scheme \u2014 required because the Java OTLP exporter performs URI parsing and rejects bare host:port), and sets OTEL_EXPORTER_OTLP_HEADERS with Authorization=Bearer. Uses a placeholder for the API key. FAIL if it uses bare ingress.eu2.coralogix.com:443 without the https:// scheme, or if it omits cx.application.name/cx.subsystem.name.",
"max_score": 2,
"category": "MUST_NOT"
}
]
}
java-agent-spring-boot-setup
You are a Coralogix support expert. A user has asked the following question:
---
I want to instrument my Java Spring Boot application to send traces to Coralogix. We're on the eu2 region. How do I set it up?
---
k8s-operator-injection
{
"context": "Evaluating a Coralogix support response for this user question:\n\nI'm running a Java service in Kubernetes and want to use the OpenTelemetry Operator to auto-instrument it without changing the application code. How do I configure it?",
"type": "weighted_checklist",
"checklist": [
{
"name": "mentions-instrumentation",
"description": "The response contains \"Instrumentation\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-inject-java",
"description": "The response contains \"inject-java\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-cx-application-name",
"description": "The response contains \"cx.application.name\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-cx-subsystem-name",
"description": "The response contains \"cx.subsystem.name\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "no-if-it-omits-the-instrumentation-crd-omits",
"description": "Explains the OpenTelemetry Operator injection flow: create an Instrumentation CRD that specifies the exporter endpoint and resource attributes including cx.application.name, cx.subsystem.name, and service.name; then add the instrumentation.opentelemetry.io/inject-java: \"true\" annotation to the pod or deployment. The endpoint may point to a local OTel Collector or directly to the Coralogix ingress \u2014 both are valid; auth headers can be set in Instrumentation.spec.exporter.headers when going direct. Must NOT instruct the user to set JAVA_TOOL_OPTIONS or download the JAR manually \u2014 those are bypassed by the Operator. FAIL if it omits the Instrumentation CRD, omits the pod annotation, or instructs manual JAR setup.",
"max_score": 2,
"category": "MUST_NOT"
}
]
}
java-k8s-operator-injection
You are a Coralogix support expert. A user has asked the following question:
---
I'm running a Java service in Kubernetes and want to use the OpenTelemetry Operator to auto-instrument it without changing the application code. How do I configure it?
---
java-withspan-annotation
{
"context": "Evaluating a Coralogix support response for this user question:\n\nMy Java app sends traces fine but I want to add a custom span to a specific method. How do I do it without changing the exporter setup?",
"type": "weighted_checklist",
"checklist": [
{
"name": "mentions-withspan",
"description": "The response contains \"@WithSpan\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-opentelemetry-instrumentation-annotations",
"description": "The response contains \"opentelemetry-instrumentation-annotations\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "no-if-it-suggests-rewriting-the-exporter-setu",
"description": "Describes the @WithSpan annotation approach \u2014 noting that the opentelemetry-instrumentation-annotations dependency is required without listing installation commands, and annotating the target method. Mentions that the Java agent must already be running for @WithSpan to work. FAIL if it suggests rewriting the exporter setup or adding manual SDK init code.",
"max_score": 2,
"category": "MUST_NOT"
}
]
}
java-withspan-custom-span-annotation
You are a Coralogix support expert. A user has asked the following question:
---
My Java app sends traces fine but I want to add a custom span to a specific method. How do I do it without changing the exporter setup?
---
nodejs-transaction-sampler
{
"context": "Evaluating a Coralogix support response for this user question:\n\nI'm using Node.js with the bundled auto-instrumentation approach (@opentelemetry/auto-instrumentations-node via NODE_OPTIONS). My traces are appearing in Coralogix, but I don't see any data in the Transactions view in APM. Why?",
"type": "weighted_checklist",
"checklist": [
{
"name": "mentions-transaction",
"description": "The response contains \"transaction\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-coralogixtransactionsampler",
"description": "The response contains \"CoralogixTransactionSampler\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-bundled",
"description": "The response contains \"bundled\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-coralogix-opentelemetry",
"description": "The response contains \"@coralogix/opentelemetry\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "no-if-it-suggests-any-other-root-cause-mentio",
"description": "Explains that bundled auto-instrumentation is NOT supported for Coralogix transactions, and the user must switch to the individual auto-instrumentation method (custom instrumentation.js) or manual instrumentation, install the \"@coralogix/opentelemetry\" npm package, and add CoralogixTransactionSampler to the sampler chain. FAIL if it suggests any other root cause, does not mention the bundled limitation, or does not name the \"@coralogix/opentelemetry\" package.",
"max_score": 2,
"category": "MUST_NOT"
}
]
}
nodejs-bundled-auto-no-transactions
You are a Coralogix support expert. A user has asked the following question:
---
I'm using Node.js with the bundled auto-instrumentation approach (@opentelemetry/auto-instrumentations-node via NODE_OPTIONS). My traces are appearing in Coralogix, but I don't see any data in the Transactions view in APM. Why?
---
legacy-sdk-deprecation
{
"context": "Evaluating a Coralogix support response for this user question:\n\nI'm using the coralogix-logger npm package to send logs from my Node.js app. How do I configure it to send to a different Coralogix region?",
"type": "weighted_checklist",
"checklist": [
{
"name": "deprecated-end-of-life-end",
"description": "The response matches the pattern: (?i)deprecated|end.of.life|end of life",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-opentelemetry",
"description": "The response contains \"opentelemetry\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-june-30",
"description": "The response contains \"June 30\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "no-if-it-provides-region-configuration-instru",
"description": "Informs the user that coralogix-logger is deprecated (EOL June 30, 2026) and redirects them to OpenTelemetry Node.js SDK instrumentation instead of answering the region configuration question for the legacy package. FAIL if it provides region configuration instructions for coralogix-logger, or does not mention the deprecation.",
"max_score": 2,
"category": "MUST_NOT"
}
]
}
nodejs-coralogix-logger-deprecation-redirect
You are a Coralogix support expert. A user has asked the following question:
---
I'm using the coralogix-logger npm package to send logs from my Node.js app. How do I configure it to send to a different Coralogix region?
---
nodejs-http-proto-endpoint
{
"context": "Evaluating a Coralogix support response for this user question:\n\nMy Node.js app uses OTLPTraceExporter (HTTP/proto) with url set to 'https://ingress.eu2.coralogix.com:443'. Traces are not arriving in Coralogix and the exporter returns no errors. What is the correct endpoint URL to use, and why does the current one fail silently?",
"type": "weighted_checklist",
"checklist": [
{
"name": "mentions-v1-traces",
"description": "The response contains \"/v1/traces\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-https-ingress-eu2-coralogix-com-443-v1-traces",
"description": "The response contains \"https://ingress.eu2.coralogix.com:443/v1/traces\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "no-only-response-recommends-a-url-without-v1",
"description": "Identifies that OTLPTraceExporter (HTTP/proto) requires the /v1/traces path suffix \u2014 the correct url is \"https://ingress.eu2.coralogix.com:443/v1/traces\". Explains that the base URL without the path sends to the wrong endpoint and gets no error because the server returns a non-export response that the SDK ignores. The critical distinction is that HTTP/proto exporters require the signal path suffix (/v1/traces) while gRPC exporters do not. The user's current URL \"https://ingress.eu2.coralogix.com:443\" is correctly cited as the WRONG URL \u2014 do not FAIL for mentioning it as the broken config. FAIL only if the response RECOMMENDS a URL without /v1/traces as the correct HTTP/proto endpoint, or if it does not mention the /v1/traces path suffix at all.",
"max_score": 2,
"category": "MUST_NOT"
}
]
}
nodejs-http-proto-missing-v1traces-path
You are a Coralogix support expert. A user has asked the following question:
---
My Node.js app uses OTLPTraceExporter (HTTP/proto) with url set to 'https://ingress.eu2.coralogix.com:443'. Traces are not arriving in Coralogix and the exporter returns no errors. What is the correct endpoint URL to use, and why does the current one fail silently?
---
context-propagation-cross-language
{
"context": "Evaluating a Coralogix support response for this user question:\n\nMy Node.js service injects a traceparent header into outgoing HTTP requests, but when the request reaches our .NET Framework backend I see independent spans in Coralogix instead of child spans \u2014 the trace is broken at the service boundary. What's wrong?",
"type": "weighted_checklist",
"checklist": [
{
"name": "mentions-propagat",
"description": "The response contains \"propagat\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-w3c",
"description": "The response contains \"W3C\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-addaspnetinstrumentation",
"description": "The response contains \"AddAspNetInstrumentation\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "no-if-it-identifies-the-node-js-injection-as",
"description": "Explains that .NET Framework does not extract incoming W3C traceparent headers automatically and requires server-side instrumentation: OpenTelemetry.Instrumentation.AspNet must be installed and AddAspNetInstrumentation() called on the TracerProvider so the server reads and continues the incoming trace context. Must NOT suggest AddHttpClientInstrumentation \u2014 that only instruments outgoing HttpClient calls and does nothing for incoming request propagation. Should also recommend confirming the upstream Node.js service sends W3C format headers (not B3/Zipkin) and that no intermediaries strip the traceparent header. FAIL if it identifies the Node.js injection as the problem, if it does not mention AddAspNetInstrumentation (or AddAspNetCoreInstrumentation for .NET Core), or if it recommends AddHttpClientInstrumentation as the fix.",
"max_score": 2,
"category": "MUST_NOT"
}
]
}
nodejs-traceparent-not-propagated-to-dotnet-framework
You are a Coralogix support expert. A user has asked the following question:
---
My Node.js service injects a traceparent header into outgoing HTTP requests, but when the request reaches our .NET Framework backend I see independent spans in Coralogix instead of child spans — the trace is broken at the service boundary. What's wrong?
---
scope-deflection
{
"context": "Evaluating a Coralogix support response for this user question:\n\nHow do I configure the OpenTelemetry Collector to batch spans before sending to Coralogix?",
"type": "weighted_checklist",
"checklist": [
{
"name": "no-if-it-attempts-to-answer-the-collector-con",
"description": "Redirects the user to the opentelemetry-collector skill \u2014 this is a collector configuration question, not an SDK instrumentation question. FAIL if it attempts to answer the collector config question directly without noting the scope boundary.",
"max_score": 2,
"category": "MUST_NOT"
}
]
}
out-of-scope-collector-config-deflection
You are a Coralogix support expert. A user has asked the following question:
---
How do I configure the OpenTelemetry Collector to batch spans before sending to Coralogix?
---
python-env-var-headers-encoding
{
"context": "Evaluating a Coralogix support response for this user question:\n\nI set up Python auto-instrumentation with opentelemetry-instrument for my Flask app and I'm sending to Coralogix (us1 region). My env vars are:\n OTEL_EXPORTER_OTLP_HEADERS=\"Authorization=Bearer mySecretKey123\"\n OTEL_EXPORTER_OTLP_ENDPOINT=\"https://ingress.us1.coralogix.com:443\"\n OTEL_TRACES_EXPORTER=otlp_proto_grpc\nNothing shows up in Coralogix. What's wrong?",
"type": "weighted_checklist",
"checklist": [
{
"name": "mentions-bearer-20",
"description": "The response contains \"Bearer%20\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "no-if-it-identifies-the-endpoint-scheme-as-th",
"description": "Identifies that OTEL_EXPORTER_OTLP_HEADERS contains a literal space between \"Bearer\" and the key \u2014 the Python SDK env var parser requires the space to be percent-encoded as \"Bearer%20mySecretKey123\". FAIL if it does not identify the Bearer encoding as the root cause. Do NOT flag https://ingress.us1.coralogix.com:443 as a bug \u2014 the Python gRPC exporter accepts both https:// and bare host:port forms; the https:// scheme is valid and is not the cause of the missing traces. FAIL if it identifies the endpoint scheme as the root cause instead of the missing %20 encoding.",
"max_score": 2,
"category": "MUST_NOT"
}
]
}
python-bearer-space-url-encoded-env-var
You are a Coralogix support expert. A user has asked the following question:
---
I set up Python auto-instrumentation with opentelemetry-instrument for my Flask app and I'm sending to Coralogix (us1 region). My env vars are: OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer mySecretKey123" OTEL_EXPORTER_OTLP_ENDPOINT="https://ingress.us1.coralogix.com:443" OTEL_TRACES_EXPORTER=otlp_proto_grpc Nothing shows up in Coralogix. What's wrong?
---
python-logs-setup
{
"context": "Evaluating a Coralogix support response for this user question:\n\nHow do I send Python application logs to Coralogix using OpenTelemetry? We're on the eu2 region.",
"type": "weighted_checklist",
"checklist": [
{
"name": "mentions-loggerprovider",
"description": "The response contains \"LoggerProvider\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-logginghandler",
"description": "The response contains \"LoggingHandler\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-setlevel",
"description": "The response contains \"setLevel\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-otlplogexporter",
"description": "The response contains \"OTLPLogExporter\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-ingress-eu2-coralogix-com-443",
"description": "The response contains \"ingress.eu2.coralogix.com:443\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "no-if-it-says-https-is-invalid-for-the-python",
"description": "Covers: LoggerProvider with OTLPLogExporter pointing to the Coralogix eu2 ingress endpoint using the standard Coralogix gRPC format \"ingress.eu2.coralogix.com:443\" (bare host:port; https://ingress.eu2.coralogix.com:443 is also valid for Python gRPC and must not be treated as the root cause), with Authorization Bearer header. LoggingHandler bridging stdlib logging to the OTel provider, and the critical note that the root logger level must be set explicitly (e.g. setLevel(logging.INFO)) BEFORE adding the OTel handler \u2014 if level is not set, INFO records are filtered by the root logger before they reach any handler. FAIL if it says https:// is invalid for the Python gRPC endpoint, omits the logger-level-setting requirement, or omits the Coralogix endpoint and auth header.",
"max_score": 2,
"category": "MUST_NOT"
}
]
}
python-logs-loggerprovider-setlevel
You are a Coralogix support expert. A user has asked the following question:
---
How do I send Python application logs to Coralogix using OpenTelemetry? We're on the eu2 region.
---
python-programmatic-headers-shape
{
"context": "Evaluating a Coralogix support response for this user question:\n\nI'm reviewing my Python programmatic instrumentation. Here's my exporter setup:\n headers = {\n 'Authorization': 'Bearer myKey',\n 'CX-Application-Name': 'myapp',\n }\n exporter = OTLPSpanExporter(endpoint='ingress.eu1.coralogix.com:443', headers=headers)\nWhat's wrong with this?",
"type": "weighted_checklist",
"checklist": [
{
"name": "mentions-sequence",
"description": "The response contains \"sequence\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-dict",
"description": "The response contains \"dict\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-lowercase",
"description": "The response contains \"lowercase\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-cx-subsystem-name",
"description": "The response contains \"cx.subsystem.name\" (case-sensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "no-if-it-misses-both-the-dict-shape-and-the-k",
"description": "Identifies at least two of these three issues (all three is ideal): (1) headers is a dict \u2014 must be a sequence of (key, value) tuples; (2) gRPC/HTTP2 requires lowercase header keys \u2014 CX-Application-Name is rejected with \"Illegal header key\"; recommend resource attributes cx.application.name and cx.subsystem.name instead; (3) cx.subsystem.name is missing (may be bundled into issue 2 as an acceptable combined fix \u2014 that counts). FAIL if it misses both the dict shape AND the key-case issue, or if it says the \"Bearer myKey\" value is wrong (a literal space is correct for programmatic tuple headers \u2014 %20 encoding only applies to the OTEL_EXPORTER_OTLP_HEADERS env var).",
"max_score": 2,
"category": "MUST_NOT"
}
]
}
python-programmatic-headers-dict-case
You are a Coralogix support expert. A user has asked the following question:
---
I'm reviewing my Python programmatic instrumentation. Here's my exporter setup: headers = { 'Authorization': 'Bearer myKey', 'CX-Application-Name': 'myapp', } exporter = OTLPSpanExporter(endpoint='ingress.eu1.coralogix.com:443', headers=headers) What's wrong with this?
---
python-short-lived-script
{
"context": "Evaluating a Coralogix support response for this user question:\n\nI wrote a Python script that records some spans and a counter metric, then exits. The script finishes in about half a second. Nothing shows up in Coralogix \u2014 no traces, no metrics. What should I check?",
"type": "weighted_checklist",
"checklist": [
{
"name": "mentions-simplespanprocessor",
"description": "The response contains \"SimpleSpanProcessor\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-batchspanprocessor",
"description": "The response contains \"BatchSpanProcessor\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-periodicexporting",
"description": "The response contains \"PeriodicExporting\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "no-if-it-only-identifies-one-issue-or-if-it-m",
"description": "Identifies TWO root causes specific to short-lived scripts: (1) BatchSpanProcessor queues spans and may not flush before the process exits \u2014 for scripts use SimpleSpanProcessor which exports synchronously on span.end(); (2) PeriodicExportingMetricReader only exports on its timed interval \u2014 a script that exits before the interval fires exports zero metrics; fix by sleeping longer than the export interval or calling force_flush() on the reader before shutdown(). FAIL if it only identifies one issue, or if it does not mention both the span processor and the metric reader export timing problem.",
"max_score": 2,
"category": "MUST_NOT"
}
]
}
python-short-lived-script-flush-timing
You are a Coralogix support expert. A user has asked the following question:
---
I wrote a Python script that records some spans and a counter metric, then exits. The script finishes in about half a second. Nothing shows up in Coralogix — no traces, no metrics. What should I check?
---
python-programmatic-headers-encoding
{
"context": "Evaluating a Coralogix support response for this user question:\n\nMy Python app is sending traces to Coralogix using OTLPSpanExporter with these programmatic headers:\n headers = (\n (\"authorization\", \"Bearer%20myApiKey123\"),\n )\nI'm getting StatusCode.UNAUTHENTICATED from the exporter. What's wrong?",
"type": "weighted_checklist",
"checklist": [
{
"name": "mentions-literal",
"description": "The response contains \"literal\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-env-var",
"description": "The response contains \"env var\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "no-if-it-only-says-use-a-space-without-explai",
"description": "Identifies that Bearer%20 is wrong in programmatic gRPC tuple headers AND explains the asymmetry: %20 is only needed in the OTEL_EXPORTER_OTLP_HEADERS env var because the Python SDK parses that string as a comma-separated list where a literal space acts as a delimiter. In programmatic tuple headers the value is passed directly to gRPC without parsing, so a literal space must be used: (\"authorization\", f\"Bearer {token}\"). FAIL if it only says \"use a space\" without explaining why %20 is correct in env vars but wrong in tuples, or if it does not distinguish the two contexts.",
"max_score": 2,
"category": "MUST_NOT"
}
]
}
python-tuple-headers-bearer-percent20-bug
You are a Coralogix support expert. A user has asked the following question:
---
My Python app is sending traces to Coralogix using OTLPSpanExporter with these programmatic headers: headers = ( ("authorization", "Bearer%20myApiKey123"), ) I'm getting StatusCode.UNAUTHENTICATED from the exporter. What's wrong?
---
telemetry-quality-safeguards
{
"context": "Evaluating a Coralogix support response for this user question:\n\nI'm adding custom metrics and logs to my Coralogix-monitored service. I want to add user.id and tenant.id as attributes on every metric and span. I also want to log full request and response bodies as structured fields. Are there any risks specific to how Coralogix handles this data?",
"type": "weighted_checklist",
"checklist": [
{
"name": "mentions-cardinality",
"description": "The response contains \"cardinality\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "mentions-sensitive",
"description": "The response contains \"sensitive\" (case-insensitive).",
"max_score": 3,
"category": "INTENT"
},
{
"name": "no-if-it-approves-user-id-or-tenant-id-as-met",
"description": "Warns that unbounded identifiers like user.id and tenant.id as metric attributes cause cardinality explosion \u2014 one metric series per unique value \u2014 which inflates Coralogix ingestion volume and may trigger TCO policy throttling. For per-tenant observability in Coralogix, cx.application.name and cx.subsystem.name are the correct mechanism for data routing and grouping \u2014 these are bounded resource attributes, not per-request metric labels. Warns that full request/response bodies in logs risk logging PII, credentials, or sensitive data. Recommends bounded metric attributes and explicitly selected safe structured log fields instead. FAIL if it approves user.id or tenant.id as metric label attributes, or if it approves logging full request/response bodies without filtering.",
"max_score": 2,
"category": "MUST_NOT"
}
]
}
telemetry-quality-cardinality-sensitive
You are a Coralogix support expert. A user has asked the following question:
---
I'm adding custom metrics and logs to my Coralogix-monitored service. I want to add user.id and tenant.id as attributes on every metric and span. I also want to log full request and response bodies as structured fields. Are there any risks specific to how Coralogix handles this data?
---
Coralogix Endpoints for SDK Instrumentation
Contents
- OTLP Endpoint for Direct SDK Export
- Regional Domains
- Authentication Header
- Coralogix-Specific OTLP Headers
- Endpoint vs Domain — SDK vs Collector
- PrivateLink
OTLP Endpoint for Direct SDK Export
When exporting directly from the SDK (not via a collector), the required endpoint format depends on the language:
Java and .NET — the SDK's URI parser requires a full URI with https:// scheme:
https://ingress.<region>.coralogix.com:443Python and Node.js — the standard Coralogix gRPC form is bare host:port:
ingress.<region>.coralogix.com:443The OpenTelemetry gRPC exporter spec also requires SDKs to accept https://host:port. So https://ingress.<region>.coralogix.com:443 is valid for Python and Node.js gRPC, but prefer the bare form in generated Coralogix examples.
Go — WithEndpoint uses bare host:port with no scheme or path:
ingress.<region>.coralogix.com:443Use credentials.NewTLS(nil) with Go gRPC exporters. Do not pass https:// to WithEndpoint; use WithEndpointURL only when intentionally using a full URL option.
TLS is always enabled on port 443. Do not use http:// for direct Coralogix export — all Coralogix OTLP endpoints require TLS.
For HTTP/protobuf exporters (e.g. Node.js @opentelemetry/exporter-trace-otlp-proto), append the signal path:
https://ingress.<region>.coralogix.com:443/v1/traces
https://ingress.<region>.coralogix.com:443/v1/metrics
https://ingress.<region>.coralogix.com:443/v1/logsEvery generated direct-export setup must show these required environment variables. Choose the block that matches the language and protocol:
gRPC — Java and .NET (full URI with https:// scheme required):
export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingress.<CORALOGIX_REGION>.coralogix.com:443"
export OTEL_EXPORTER_OTLP_PROTOCOL="grpc"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <CORALOGIX_API_KEY>"
export OTEL_SERVICE_NAME="<SERVICE_NAME>"
export OTEL_RESOURCE_ATTRIBUTES="cx.application.name=<CX_APPLICATION_NAME>,cx.subsystem.name=<CX_SUBSYSTEM_NAME>"gRPC — Python, Node.js, and Go (bare host:port; no https:// for Go WithEndpoint):
export OTEL_EXPORTER_OTLP_ENDPOINT="ingress.<CORALOGIX_REGION>.coralogix.com:443"
export OTEL_EXPORTER_OTLP_PROTOCOL="grpc"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <CORALOGIX_API_KEY>"
export OTEL_SERVICE_NAME="<SERVICE_NAME>"
export OTEL_RESOURCE_ATTRIBUTES="cx.application.name=<CX_APPLICATION_NAME>,cx.subsystem.name=<CX_SUBSYSTEM_NAME>"Python env var exception: Authorization=Bearer%20<CORALOGIX_API_KEY> (URL-encoded space).
HTTP/protobuf — all languages (base URL only; SDK auto-appends /v1/traces etc.):
export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingress.<CORALOGIX_REGION>.coralogix.com:443"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <CORALOGIX_API_KEY>"
export OTEL_SERVICE_NAME="<SERVICE_NAME>"
export OTEL_RESOURCE_ATTRIBUTES="cx.application.name=<CX_APPLICATION_NAME>,cx.subsystem.name=<CX_SUBSYSTEM_NAME>"Do NOT include /v1/traces in OTEL_EXPORTER_OTLP_ENDPOINT — the SDK appends the signal path automatically for HTTP/proto, so including it results in double-pathing (/v1/traces/v1/traces). Use signal-specific OTEL_EXPORTER_OTLP_TRACES_ENDPOINT if you need to set the full URL explicitly.
Regional Domains
| Region name | Domain | OTLP gRPC endpoint |
|---|---|---|
| US1 | us1.coralogix.com | ingress.us1.coralogix.com:443 |
| US2 | us2.coralogix.com | ingress.us2.coralogix.com:443 |
| EU1 | eu1.coralogix.com | ingress.eu1.coralogix.com:443 |
| EU2 | eu2.coralogix.com | ingress.eu2.coralogix.com:443 |
| AP1 | ap1.coralogix.com | ingress.ap1.coralogix.com:443 |
| AP2 | ap2.coralogix.com | ingress.ap2.coralogix.com:443 |
| AP3 | ap3.coralogix.com | ingress.ap3.coralogix.com:443 |
How to find your region: Your Coralogix platform URL shows the region — e.g. https://dashboard.eu2.coralogix.com → region is eu2, domain is eu2.coralogix.com, OTLP endpoint is ingress.eu2.coralogix.com:443.
Legacy endpoint aliases (old shipper configs only — redirect new setups to the regional form):
| Legacy endpoint | Maps to region |
|---|---|
ingress.coralogix.com | EU1 |
ingress.coralogix.us | US1 |
ingress.cx498.coralogix.com | US2 |
ingress.coralogix.in | AP1 |
ingress.coralogixsg.com | AP2 |
If a user shows one of these hostnames, identify their region and replace with ingress.<region>.coralogix.com:443.
Authentication Header
All direct OTLP export to Coralogix requires a Send-Your-Data API key passed as an OTLP header:
Authorization=Bearer <CORALOGIX_API_KEY>The key is found in the Coralogix platform under Settings → Users and Teams → API Keys. Only Send-Your-Data keys work for telemetry ingestion. Team keys and personal keys do not.
Setting the header per language
Environment variable (Java, Node.js, Go, most gRPC SDK env config):
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <CORALOGIX_API_KEY>"
export OTEL_SERVICE_NAME="<SERVICE_NAME>"
export OTEL_RESOURCE_ATTRIBUTES="cx.application.name=<CX_APPLICATION_NAME>,cx.subsystem.name=<CX_SUBSYSTEM_NAME>"Python — URL encoding required in env vars:
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer%20<CORALOGIX_API_KEY>"
export OTEL_SERVICE_NAME="<SERVICE_NAME>"
export OTEL_RESOURCE_ATTRIBUTES="cx.application.name=<CX_APPLICATION_NAME>,cx.subsystem.name=<CX_SUBSYSTEM_NAME>"Note: %20 = space between Bearer and the key value.
Java — env var or JVM system property:
# env var
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <CORALOGIX_API_KEY>"
# or JVM property
-Dotel.exporter.otlp.headers="Authorization=Bearer <CORALOGIX_API_KEY>"Go — programmatic (headers map):
headers: map[string]string{"Authorization": "Bearer " + token}.NET — programmatic (OTLP options):
options.Endpoint = new Uri("https://ingress.<CORALOGIX_REGION>.coralogix.com:443");
options.Protocol = OtlpExportProtocol.Grpc;
options.Headers = $"Authorization=Bearer {config.ApiKey}";Coralogix-Specific OTLP Headers
When calling the Coralogix OTLP endpoint directly, you may pass application and subsystem names as OTLP headers in addition to resource attributes. Both mechanisms work; resource attributes are the standard approach:
| Header | Purpose |
|---|---|
CX-Application-Name | Alternative to cx.application.name resource attribute |
CX-Subsystem-Name | Alternative to cx.subsystem.name resource attribute |
Prefer setting these as resource attributes (cx.application.name, cx.subsystem.name) in the SDK — they propagate to all signals. Header-based values only reach the signals on that specific exporter.
Endpoint vs Domain — SDK vs Collector
The OTel Collector's coralogix exporter uses domain: eu2.coralogix.com (bare hostname, no ingress. prefix, no port). SDK endpoints use ingress. prefix and port 443. The required format varies by language and protocol.
| Shipper | Format | Example |
|---|---|---|
| OTel SDK direct gRPC (Python, Node.js) | Prefer ingress.<region>.coralogix.com:443; https://host:port also accepted | ingress.eu2.coralogix.com:443 |
OTel SDK direct gRPC (Go WithEndpoint) | ingress.<region>.coralogix.com:443 | ingress.eu2.coralogix.com:443 |
| OTel SDK direct gRPC (Java, .NET) | https://ingress.<region>.coralogix.com:443 | https://ingress.eu2.coralogix.com:443 |
| OTel SDK direct HTTP/protobuf | https://ingress.<region>.coralogix.com:443/v1/<signal> | https://ingress.eu2.coralogix.com:443/v1/traces |
OTel Collector coralogix exporter | domain: <region>.coralogix.com | domain: eu2.coralogix.com |
PrivateLink
When using AWS PrivateLink, replace ingress.<region> with ingress.private.<region>:
ingress.private.eu2.coralogix.com:443.NET OpenTelemetry Instrumentation
Contents
- Overview
- Auto-Instrumentation (Zero-Code)
- Manual Instrumentation
- Traces
- Metrics
- Logs
- Exception Logging
- Log Framework Bridges (NLog, log4net)
- Kubernetes Injection
- Common Mistakes
Source: Coralogix .NET OpenTelemetry Instrumentation documentation.
Legacy SDK Deprecation
The Coralogix .NET SDKs — Coralogix.SDK (for .NET Framework) and CoralogixCoreSDK (for .NET Core) — are deprecated and reach end-of-life on June 30, 2026. This also covers the Coralogix NLog SDK, log4net SDK, and Serilog SDK. If a user asks about CoralogixLogger, CORALOGIX_LOG_URL, or any Coralogix-branded .NET NuGet package, redirect them to OTel .NET instrumentation immediately. Do not explain how to configure the deprecated SDKs.
See: https://coralogix.com/docs/user-guides/latest-updates/deprecations/dotnet-sdk-deprecation/
Overview
.NET supports: 1. Auto-instrumentation (zero-code) — OpenTelemetry .NET Auto-Instrumentation profiler. 2. Manual instrumentation — explicit TracerProvider, MeterProvider, LoggerProvider via NuGet SDK packages.
Both paths export traces, metrics, and logs to Coralogix via OTLP/gRPC.
Requirements: .NET SDK 8.0 or later (for .NET Framework: 4.6.2 or later).
Auto-Instrumentation (Zero-Code)
The OpenTelemetry .NET Auto-Instrumentation instruments .NET applications without modifying source code.
Required environment variables
export OTEL_TRACES_EXPORTER="otlp"
export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingress.<CORALOGIX_REGION>.coralogix.com:443"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <CORALOGIX_API_KEY>"
export OTEL_EXPORTER_OTLP_PROTOCOL="grpc"
export OTEL_SERVICE_NAME="<SERVICE_NAME>"
export OTEL_RESOURCE_ATTRIBUTES="cx.application.name=<CX_APPLICATION_NAME>,cx.subsystem.name=<CX_SUBSYSTEM_NAME>"Note: For .NET auto-instrumentation, OTEL_EXPORTER_OTLP_ENDPOINT uses https:// scheme (unlike gRPC where the scheme is normally implicit). Follow the OpenTelemetry .NET Auto-Instrumentation docs for profiler setup and OS-specific installation.
Region values
Replace <CORALOGIX_REGION> with: eu1, eu2, us1, us2, ap1, ap2, or ap3.
Manual Instrumentation
Follow the official OpenTelemetry .NET getting-started guide for SDK installation: https://opentelemetry.io/docs/languages/dotnet/getting-started/
Relevant NuGet package artifacts to name in manual setup answers: OpenTelemetry, OpenTelemetry.Exporter.OpenTelemetryProtocol, OpenTelemetry.Extensions.Hosting, and any signal-specific instrumentation package such as OpenTelemetry.Instrumentation.Runtime. Name the NuGet artifacts, but do not include dotnet add package install commands unless the user explicitly asks for commands.
Important: .NET OTLP exporters require the full https:// URI scheme — use https://ingress.<region>.coralogix.com:443, not the bare host:port form used by Go WithEndpoint and commonly shown in Python/Node.js Coralogix gRPC examples. Java also requires the https:// URI form.
Step 1: Create and configure the app
dotnet new console -n CoralogixOtelExample
cd CoralogixOtelExampleStep 2: Set environment variables
export CORALOGIX_API_KEY="your-send-your-data-key"
export CORALOGIX_SERVICE_NAME="<SERVICE_NAME>"
export CORALOGIX_APP_NAME="<CX_APPLICATION_NAME>"
export CORALOGIX_SUBSYSTEM_NAME="<CX_SUBSYSTEM_NAME>"
export CORALOGIX_DOMAIN="<REGION>" # e.g. eu2 — do not include .coralogix.comStep 3: Shared configuration setup
using OpenTelemetry;
using OpenTelemetry.Resources;
private static CoralogixConfig LoadConfiguration()
{
var domain = Environment.GetEnvironmentVariable("CORALOGIX_DOMAIN") ?? "EU1";
var apiKey = Environment.GetEnvironmentVariable("CORALOGIX_API_KEY")
?? throw new InvalidOperationException("CORALOGIX_API_KEY is required");
var serviceName = Environment.GetEnvironmentVariable("CORALOGIX_SERVICE_NAME") ?? "dotnet-service";
var applicationName = Environment.GetEnvironmentVariable("CORALOGIX_APP_NAME") ?? "dotnet-app";
var subsystemName = Environment.GetEnvironmentVariable("CORALOGIX_SUBSYSTEM_NAME") ?? "default";
return new CoralogixConfig { Domain = domain, ApiKey = apiKey,
ServiceName = serviceName, ApplicationName = applicationName, SubsystemName = subsystemName };
}
private static ResourceBuilder BuildResourceAttributes(CoralogixConfig config)
{
return ResourceBuilder.CreateDefault()
.AddService(serviceName: config.ServiceName, serviceNamespace: config.ApplicationName)
.AddAttributes(new Dictionary<string, object>
{
["cx.application.name"] = config.ApplicationName,
["cx.subsystem.name"] = config.SubsystemName,
});
}
// Shared OTLP exporter config
private static void ConfigureOtlpExporter(
OpenTelemetry.Exporter.OtlpExporterOptions options, CoralogixConfig config)
{
options.Endpoint = new Uri($"https://ingress.{config.Domain.ToLower()}.coralogix.com:443");
options.Protocol = OpenTelemetry.Exporter.OtlpExportProtocol.Grpc;
options.Headers = $"Authorization=Bearer {config.ApiKey}";
}Traces
No extra package artifact is needed beyond the base NuGet artifacts above for this minimal manual trace example.
using OpenTelemetry.Trace;
using System.Diagnostics;
private static readonly ActivitySource ActivitySource = new("CoralogixOtelExample", "1.0.0");
private static TracerProvider ConfigureTracing(ResourceBuilder resourceBuilder, CoralogixConfig config)
{
return Sdk.CreateTracerProviderBuilder()
.SetResourceBuilder(resourceBuilder)
.AddSource(ActivitySource.Name)
.AddOtlpExporter(options => ConfigureOtlpExporter(options, config))
.Build();
}
// Usage in main:
using (var activity = ActivitySource.StartActivity("SampleOperation"))
{
activity?.SetTag("user.id", "user-123");
activity?.SetStatus(ActivityStatusCode.Ok);
}
Thread.Sleep(1000); // allow export before process exitValidation: Coralogix UI → Explore → Tracing.
Metrics
using OpenTelemetry.Metrics;
using System.Diagnostics.Metrics;
private static readonly Meter Meter = new("CoralogixOtelExample", "1.0.0");
private static MeterProvider ConfigureMetrics(ResourceBuilder resourceBuilder, CoralogixConfig config)
{
return Sdk.CreateMeterProviderBuilder()
.SetResourceBuilder(resourceBuilder)
.AddMeter("CoralogixOtelExample")
.AddRuntimeInstrumentation()
.AddOtlpExporter(options => ConfigureOtlpExporter(options, config))
.Build();
}
// Create and record a counter
var requestCounter = Meter.CreateCounter<long>("sample.counter", "requests", "Sample counter");
requestCounter.Add(1, new KeyValuePair<string, object?>("status", "success"));
Thread.Sleep(1000);Validation: Coralogix Grafana → Explore → Metric Browser.
Logs
using Microsoft.Extensions.Logging;
using OpenTelemetry.Logs;
private static ILoggerFactory ConfigureLogging(ResourceBuilder resourceBuilder, CoralogixConfig config)
{
return LoggerFactory.Create(builder =>
{
builder.SetMinimumLevel(LogLevel.Information);
builder.AddOpenTelemetry(options =>
{
options.SetResourceBuilder(resourceBuilder);
options.AddOtlpExporter(otlpOptions => ConfigureOtlpExporter(otlpOptions, config));
options.IncludeFormattedMessage = true;
options.IncludeScopes = true;
});
});
}
// Usage
var logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("Hello from Coralogix .NET OpenTelemetry!");
logger.LogError(new InvalidOperationException("db failed"), "request failed");
Thread.Sleep(5000); // allow exportValidation: Coralogix UI → Logs.
Exception Logging
Pass the exception object to the logger — do not format it into the message string:
try { /* ... */ }
catch (Exception ex)
{
logger.LogError(ex, "Could not process item {ItemId}", 42);
}Requires OpenTelemetry.Exporter.OpenTelemetryProtocol >= 1.8.0 for exception semantic convention support.
Log Framework Bridges (for auto-instrumentation)
NLog bridge
export OTEL_DOTNET_AUTO_LOGS_ENABLED=true
export OTEL_DOTNET_AUTO_LOGS_ENABLE_NLOG_BRIDGE=trueSupported NLog: >= 5.0.0 and < 7.0.0. Available in auto-instrumentation >= 1.14.0.
log4net bridge
export OTEL_DOTNET_AUTO_LOGS_ENABLED=true
export OTEL_DOTNET_AUTO_LOGS_ENABLE_LOG4NET_BRIDGE=trueSupported log4net: >= 2.0.13 and < 4.0.0. Available in auto-instrumentation >= 1.10.0.
If NLog or log4net is already configured as a Microsoft.Extensions.Logging provider, use the Microsoft.Extensions.Logging path instead of enabling the bridge — enabling both causes duplicate logs.
Kubernetes Injection
The OpenTelemetry Operator supports .NET auto-instrumentation injection:
annotations:
instrumentation.opentelemetry.io/inject-dotnet: "true"Span Status
.NET does not automatically set span status to Error when an exception is thrown. Without explicit status setting, spanmetrics will report STATUS_CODE_UNSET for all spans including those that caught exceptions — making error-rate metrics unreliable.
Always set span status explicitly in catch blocks:
using (var activity = ActivitySource.StartActivity("ProcessOrder"))
{
try
{
// ... do work ...
activity?.SetStatus(ActivityStatusCode.Ok);
}
catch (Exception ex)
{
activity?.SetStatus(ActivityStatusCode.Error, ex.Message);
activity?.RecordException(ex);
throw;
}
}RecordException attaches the exception as a span event following OTel semantic conventions. Requires OpenTelemetry.Exporter.OpenTelemetryProtocol >= 1.8.0.
Context Propagation (.NET Framework)
.NET 5+ (ASP.NET Core) propagates W3C traceparent on incoming requests automatically via OpenTelemetry.Instrumentation.AspNetCore. Classic .NET Framework (ASP.NET) requires explicit server-side setup. If traces from upstream Node.js or Java services are not continuing into a .NET Framework backend (independent spans created instead of child spans), confirm:
1. OpenTelemetry.Instrumentation.AspNet NuGet package is installed (not the Http package — that instruments outgoing client calls, not incoming requests) 2. .AddAspNetInstrumentation() is called on the TracerProvider so the server reads and continues the incoming traceparent header 3. The upstream service sends W3C format headers (not B3/Zipkin)
Note: AddHttpClientInstrumentation() / OpenTelemetry.Instrumentation.Http instruments outgoing HttpClient calls and does NOT fix broken incoming trace propagation.
Common Mistakes
| Mistake | Symptom | Fix |
|---|---|---|
Wrong domain casing (e.g. EU2 instead of eu2 in URI) | Connection failure | Lowercase the domain in the Uri constructor |
Thread.Sleep too short | No data exported | Allow at least 1–5 seconds before process exit for async export |
Missing cx.application.name / cx.subsystem.name | APM features degraded | Add to AddAttributes in ResourceBuilder |
OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY=disk without OTEL_DOTNET_EXPERIMENTAL_OTLP_DISK_RETRY_DIRECTORY_PATH | Disk retry fails to initialize | Set an explicit directory path; do not rely on the old shared temp-directory fallback |
NLog bridge + Microsoft.Extensions.Logging NLog provider both active | Duplicate logs | Use only one path |
OpenTelemetry.Exporter.OpenTelemetryProtocol < 1.8.0 | Exceptions not emitted as semantic convention fields | Upgrade to >= 1.8.0 |
Exceptions thrown but spanmetrics show STATUS_CODE_UNSET | Span status not set explicitly | Call activity.SetStatus(ActivityStatusCode.Error, message) in every catch block |
| Auto-instrumentation on musl-based systems (Alpine) | glibc build fails on musl libc | Use the musl-specific build of the auto-instrumentation profiler |
Go OpenTelemetry Instrumentation
Contents
- Overview
- Prerequisites
- Required environment variables
- Step 1: Initialize Go module and shared setup
- Traces
- Metrics
- Logs (beta)
- Exception Logging
- Common Mistakes
Source: Coralogix Golang OpenTelemetry Instrumentation documentation.
Legacy SDK Deprecation
The Coralogix Go SDK (go-coralogix-sdk, github.com/coralogix/go-coralogix-sdk) is deprecated and reaches end-of-life on June 30, 2026. No bug fixes, security patches, or new features will be provided after that date. If a user asks about go-coralogix-sdk, coralogix.NewCoralogixLogger, or the CORALOGIX_LOG_URL pattern, redirect them to this OpenTelemetry Go instrumentation guide immediately. Do not explain how to configure or use the deprecated SDK.
See: https://coralogix.com/docs/user-guides/latest-updates/deprecations/
Overview
This skill covers manual Go SDK instrumentation. OpenTelemetry also has Go zero-code/eBPF options such as OBI and the Auto SDK, but those are out of scope here.
FIPS / boringcrypto note: Go auto-instrumentation (eBPF/OBI) is incompatible with boringcrypto-compiled (GOEXPERIMENT=boringcrypto) binaries and panics with "invalid semantic version" since v0.21.0. If a user asks why Go auto-instrumentation fails on a FIPS-compliant build, redirect them to this manual SDK guide — it works correctly on FIPS builds. All three signals (traces, metrics, logs) use a shared setup pattern with reusable provider constructors.
Go OTel signal stability:
- Traces: stable
- Metrics: stable
- Logs: beta (API and behavior may change)
Prerequisites
- Go 1.21+
- Coralogix Send-Your-Data API key and OTLP endpoint.
Required environment variables
export OTEL_EXPORTER_OTLP_ENDPOINT="ingress.<CORALOGIX_REGION>.coralogix.com:443"
export CORALOGIX_API_KEY="your-send-your-data-key"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <CORALOGIX_API_KEY>"
export OTEL_SERVICE_NAME="<SERVICE_NAME>"
export OTEL_RESOURCE_ATTRIBUTES="cx.application.name=<CX_APPLICATION_NAME>,cx.subsystem.name=<CX_SUBSYSTEM_NAME>"Step 1: Initialize Go module and shared setup
Use the official OpenTelemetry Go getting-started guide for SDK installation: https://opentelemetry.io/docs/languages/go/getting-started/
Semconv version must match the installed OTel SDK. The semconv/vX.Y.Z packages are part of the go.opentelemetry.io/otel module — do not add them as separate go.mod require entries. Import the package version that matches SchemaURL used by resource.Default() (same as the otel SDK version). A mismatch panics at runtime with "conflicting Schema URL". To find the right version: check which semconv/v* directories exist under your installed go.opentelemetry.io/otel module in $(go env GOPATH)/pkg/mod.
package main
import (
"errors"
"os"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/sdk/resource"
semconv "go.opentelemetry.io/otel/semconv/v1.40.0" // match your SDK version
)
type OtelSetup struct {
Resource *resource.Resource
endpoint string
headers map[string]string
}
func Configure() (*OtelSetup, error) {
endpoint := os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT") // e.g. ingress.eu2.coralogix.com:443
token := os.Getenv("CORALOGIX_API_KEY")
if endpoint == "" || token == "" {
return nil, errors.New("OTEL_EXPORTER_OTLP_ENDPOINT and CORALOGIX_API_KEY must be set")
}
res, err := resource.Merge(
resource.Default(),
resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceName("<SERVICE_NAME>"),
semconv.ServiceVersion("0.1.0"),
attribute.String("cx.application.name", "<CX_APPLICATION_NAME>"),
attribute.String("cx.subsystem.name", "<CX_SUBSYSTEM_NAME>"),
),
)
if err != nil {
return nil, err
}
return &OtelSetup{
Resource: res,
endpoint: endpoint,
headers: map[string]string{"Authorization": "Bearer " + token},
}, nil
}Traces
Use the official OpenTelemetry Go getting-started guide for trace SDK setup: https://opentelemetry.io/docs/languages/go/getting-started/
Package artifacts used by this trace setup: go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc, go.opentelemetry.io/otel/sdk/trace, google.golang.org/grpc/credentials, and github.com/coralogix/coralogix-opentelemetry-go/sampler. The Coralogix sampler package enables APM Transactions; do not omit it when transactions matter.
import (
"context"
"time"
"github.com/coralogix/coralogix-opentelemetry-go/sampler"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
"google.golang.org/grpc/credentials"
)
func (s *OtelSetup) NewTracerProvider(ctx context.Context) (*sdktrace.TracerProvider, error) {
exp, err := otlptracegrpc.New(ctx,
otlptracegrpc.WithEndpoint(s.endpoint),
otlptracegrpc.WithHeaders(s.headers),
otlptracegrpc.WithTLSCredentials(credentials.NewTLS(nil)),
otlptracegrpc.WithTimeout(5*time.Second),
)
if err != nil {
return nil, err
}
return sdktrace.NewTracerProvider(
// CoralogixSampler enables Coralogix APM transactions
sdktrace.WithSampler(sampler.NewCoralogixSampler(sdktrace.AlwaysSample())),
sdktrace.WithResource(s.Resource),
sdktrace.WithSpanProcessor(sdktrace.NewBatchSpanProcessor(exp)),
), nil
}Creating spans
import (
"go.opentelemetry.io/otel"
otel_trace "go.opentelemetry.io/otel/trace"
"go.opentelemetry.io/otel/attribute"
)
const tracerName = "my-service"
func handleRequest(ctx context.Context) {
tracer := otel.Tracer(tracerName)
ctx, span := tracer.Start(ctx, "handle-request",
otel_trace.WithSpanKind(otel_trace.SpanKindServer),
)
defer span.End()
span.SetAttributes(
attribute.String("http.method", "GET"),
attribute.String("http.route", "/roll"),
)
// ... do work ...
}Wire up and shutdown
func main() {
ctx := context.Background()
setup, err := Configure()
if err != nil { panic(err) }
tp, err := setup.NewTracerProvider(ctx)
if err != nil { panic(err) }
defer func() {
if err := tp.Shutdown(ctx); err != nil { fmt.Println(err) }
}()
otel.SetTracerProvider(tp)
// ... register handlers, start server ...
}Validation: Coralogix UI → Explore → Tracing.
Metrics
Use the official OpenTelemetry Go getting-started guide for metric SDK setup: https://opentelemetry.io/docs/languages/go/getting-started/
Package artifacts used by this metric setup: go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc, go.opentelemetry.io/otel/sdk/metric, and google.golang.org/grpc/credentials. Use credentials.NewTLS(nil) on this exporter too.
import (
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc"
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
)
func (s *OtelSetup) NewMeterProvider(ctx context.Context) (*sdkmetric.MeterProvider, error) {
exp, err := otlpmetricgrpc.New(ctx,
otlpmetricgrpc.WithEndpoint(s.endpoint),
otlpmetricgrpc.WithHeaders(s.headers),
otlpmetricgrpc.WithTLSCredentials(credentials.NewTLS(nil)),
otlpmetricgrpc.WithTimeout(5*time.Second),
)
if err != nil {
return nil, err
}
return sdkmetric.NewMeterProvider(
sdkmetric.WithResource(s.Resource),
sdkmetric.WithReader(sdkmetric.NewPeriodicReader(exp)),
), nil
}// In main:
otel.SetMeterProvider(mp)
meter := otel.Meter("my-service")
reqCounter, _ := meter.Int64Counter("http.server.requests",
metric.WithDescription("Total HTTP requests"),
)
reqCounter.Add(ctx, 1, metric.WithAttributes(attribute.String("method", "GET")))Validation: Coralogix Grafana → Explore → Metric Browser.
Logs (beta)
Use the official OpenTelemetry Go getting-started guide for log SDK setup: https://opentelemetry.io/docs/languages/go/getting-started/
Package artifacts used by this log setup: go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc, go.opentelemetry.io/otel/sdk/log, go.opentelemetry.io/otel/log/global, go.opentelemetry.io/contrib/bridges/otelslog, and google.golang.org/grpc/credentials. Use credentials.NewTLS(nil) on this exporter too.
import (
"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc"
logsdk "go.opentelemetry.io/otel/sdk/log"
"go.opentelemetry.io/otel/log/global"
"go.opentelemetry.io/contrib/bridges/otelslog"
"log/slog"
)
func (s *OtelSetup) NewLoggerProvider(ctx context.Context) (*logsdk.LoggerProvider, error) {
exp, err := otlploggrpc.New(ctx,
otlploggrpc.WithEndpoint(s.endpoint),
otlploggrpc.WithHeaders(s.headers),
otlploggrpc.WithTLSCredentials(credentials.NewTLS(nil)),
otlploggrpc.WithTimeout(5*time.Second),
)
if err != nil {
return nil, err
}
return logsdk.NewLoggerProvider(
logsdk.WithResource(s.Resource),
logsdk.WithProcessor(logsdk.NewBatchProcessor(exp)),
), nil
}
// Wire slog bridge in main:
global.SetLoggerProvider(lp)
h := otelslog.NewHandler("my-app", otelslog.WithLoggerProvider(lp))
slog.SetDefault(slog.New(h))
slog.Info("Hello from Coralogix Go OTel")Validation: Coralogix UI → Logs.
Exception Logging
import "go.opentelemetry.io/otel/log"
func emitException(ctx context.Context, logger log.Logger) {
err := errors.New("database connection failed")
record := log.Record{}
record.SetSeverity(log.SeverityError)
record.SetBody(log.StringValue("request failed"))
record.SetErr(err) // available in go.opentelemetry.io/otel/log >= v0.18.0
logger.Emit(ctx, record)
}Using otelzap bridge
Use the official OpenTelemetry Go documentation for bridge installation details: https://opentelemetry.io/docs/languages/go/getting-started/
core := otelzap.NewCore("my-app", otelzap.WithLoggerProvider(lp))
logger := zap.New(core)
logger.Error("request failed", zap.Error(errors.New("db failed")))Use zap.Error(err) — named errors like zap.NamedError("db", err) emit as regular attributes, not exception semantic convention fields.
Common Mistakes
| Mistake | Symptom | Fix |
|---|---|---|
| Missing TLS credentials | TLS handshake failure | Use credentials.NewTLS(nil) on all exporters |
OTEL_EXPORTER_OTLP_ENDPOINT includes https:// | Dial error | Use bare host:port ingress.<region>.coralogix.com:443; keep the required :443 port |
| Semconv version mismatches installed SDK | panic: conflicting Schema URL at startup | Import semconv/vX.Y.Z that matches your go.opentelemetry.io/otel version; do not add semconv as a separate go.mod require entry |
sdk/metric drops new attribute sets at 2000 series | Missing metric dimensions and otel.metric.overflow=true | Use WithCardinalityLimit(0) only when unlimited cardinality is intentional; otherwise remove or normalize high-cardinality labels |
Missing CoralogixSampler (Go sampler) | No Transactions in APM | Wrap sampler: sampler.NewCoralogixSampler(sdktrace.AlwaysSample()) |
No tp.Shutdown() deferred | Last spans dropped | Always defer Shutdown with a timeout context |
Logs API used below v0.18.0 | SetErr not available | Upgrade go.opentelemetry.io/otel/log to >= v0.18.0 |
Java OpenTelemetry Instrumentation
Contents
- Overview
- Auto-Instrumentation
- Additional Instrumentation with
@WithSpan - Exception Logging
- Enabling Metrics and Logs
- Verification
- Common Mistakes
- Kubernetes Injection
Source: Coralogix Java OpenTelemetry Instrumentation documentation.
Overview
Java instrumentation uses the OpenTelemetry Java Agent — a JAR that attaches to any Java 8+ application and injects bytecode to capture telemetry automatically. No manual SDK init code is required for auto-instrumentation. Manual span additions use the @WithSpan annotation while the agent is attached.
Use the latest stable OpenTelemetry Java agent from the releases page.
Auto-Instrumentation
Step 1: Follow the OpenTelemetry Java setup guide
Use the official OpenTelemetry Java getting-started guide for SDK and agent installation: https://opentelemetry.io/docs/languages/java/getting-started/
Distribute the JAR to each service host or container that needs instrumentation. The JVM must have access to the JAR at startup.
Step 2: Set environment variables (recommended)
export JAVA_TOOL_OPTIONS="-javaagent:/path/to/opentelemetry-javaagent.jar"
export OTEL_TRACES_EXPORTER="otlp"
export OTEL_METRICS_EXPORTER="none" # set to "otlp" to enable metrics
export OTEL_LOGS_EXPORTER="none" # set to "otlp" to enable logs
export OTEL_EXPORTER_OTLP_TRACES_PROTOCOL="grpc"
export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingress.<CORALOGIX_REGION>.coralogix.com:443"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <CORALOGIX_API_KEY>"
export OTEL_SERVICE_NAME="<SERVICE_NAME>"
export OTEL_RESOURCE_ATTRIBUTES="cx.application.name=<CX_APPLICATION_NAME>,cx.subsystem.name=<CX_SUBSYSTEM_NAME>"
java -jar myapp.jarStep 2 (alternative): JVM system properties
java -javaagent:/path/to/opentelemetry-javaagent.jar \
-Dotel.traces.exporter=otlp \
-Dotel.metrics.exporter=none \
-Dotel.logs.exporter=none \
-Dotel.exporter.otlp.traces.protocol=grpc \
-Dotel.exporter.otlp.traces.endpoint="https://ingress.<CORALOGIX_REGION>.coralogix.com:443" \
-Dotel.exporter.otlp.traces.headers="Authorization=Bearer <CORALOGIX_API_KEY>" \
-Dotel.service.name="<SERVICE_NAME>" \
-Dotel.resource.attributes="cx.application.name=<CX_APPLICATION_NAME>,cx.subsystem.name=<CX_SUBSYSTEM_NAME>" \
-jar myapp.jarResource attributes note
Use the current identity attributes consistently:
service.name=<SERVICE_NAME>
cx.application.name=<CX_APPLICATION_NAME>
cx.subsystem.name=<CX_SUBSYSTEM_NAME>Additional Instrumentation with @WithSpan
While the agent handles framework-level spans, you can add custom spans to any method using the @WithSpan annotation without touching the tracer API.
Dependency reference
Use the official OpenTelemetry Java getting-started guide for dependency setup: https://opentelemetry.io/docs/languages/java/getting-started/
Required package artifact for @WithSpan: opentelemetry-instrumentation-annotations. Name this artifact explicitly when explaining custom spans, but do not include install commands unless the user asks for them.
Usage
import io.opentelemetry.instrumentation.annotations.WithSpan;
public class CartService {
@WithSpan // creates a span named "CartService.addItem" automatically
public void addItem(String itemId) {
// method body — span auto-closes when method returns
}
}The @WithSpan annotation only creates spans when the agent is running. Without the agent, the annotation is a no-op.
Exception Logging
Via OpenTelemetry Logs API
import io.opentelemetry.api.logs.Logger;
import io.opentelemetry.api.logs.Severity;
logger.logRecordBuilder()
.setSeverity(Severity.ERROR)
.setBody("request failed")
.setException(new IllegalStateException("database connection failed"))
.emit();Via Log4j 2 appender (opentelemetry-log4j-appender-2.17)
Use the official OpenTelemetry Java getting-started guide for appender dependency setup: https://opentelemetry.io/docs/languages/java/getting-started/
log4j2.xml:
<Configuration>
<Appenders>
<OpenTelemetry name="OpenTelemetryAppender"/>
</Appenders>
<Loggers>
<Root level="all">
<AppenderRef ref="OpenTelemetryAppender"/>
</Root>
</Loggers>
</Configuration>import io.opentelemetry.instrumentation.log4j.appender.v2_17.OpenTelemetryAppender;
// Call once at startup:
OpenTelemetryAppender.install(openTelemetry);Enabling Metrics and Logs
By default, only traces are enabled in the examples. To enable metrics and/or logs:
export OTEL_METRICS_EXPORTER="otlp" # enables metrics
export OTEL_LOGS_EXPORTER="otlp" # enables logs (requires log bridge setup)Verification
1. Start the application with the agent attached. 2. Look for this log line confirming agent attachment:
[otel.javaagent ...] INFO io.opentelemetry.javaagent.tooling.VersionLogger - opentelemetry-javaagent - version: <agent-version>3. Generate traffic to the application. 4. In Coralogix UI: Explore → Tracing — traces should appear within ~30 seconds. 5. If metrics are enabled: Grafana → Explore → Metric Browser.
Common Mistakes
| Mistake | Symptom | Fix |
|---|---|---|
Missing -javaagent flag | No agent log line at startup; no traces | Add -javaagent: to JAVA_TOOL_OPTIONS or command line |
Wrong endpoint format (bare host:port without scheme) | URI parse error or silent export failure | Java SDK requires a URI — use https://ingress.<region>.coralogix.com:443 (unlike Python/Go/Node.js which accept bare host:port) |
Missing cx.application.name / cx.subsystem.name | Telemetry lands under defaults; invisible in APM | Add both to OTEL_RESOURCE_ATTRIBUTES |
@WithSpan without agent running | No custom spans, no error | Confirm agent is attached; annotation is a no-op without agent |
| Wrong API key type (not Send-Your-Data) | 401 / auth failure | Use Send-Your-Data key from Settings → API Keys |
Kubernetes Injection
The OpenTelemetry Operator supports injection of the Java agent into pods via the Instrumentation CRD — no JAR download or JAVA_TOOL_OPTIONS needed in the pod spec. Do NOT instruct users to set JAVA_TOOL_OPTIONS or download the JAR manually when the Operator is in use — those steps are bypassed by the injector.
Option A: via OTel Collector (recommended for Kubernetes — collector handles auth and enrichment):
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
name: coralogix-instrumentation
spec:
exporter:
endpoint: http://otel-collector.monitoring.svc.cluster.local:4317
java:
image: ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-java:latestOption B: direct to Coralogix (auth headers injected via spec.env):
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
name: coralogix-instrumentation
spec:
exporter:
endpoint: https://ingress.<CORALOGIX_REGION>.coralogix.com:443
env:
- name: OTEL_EXPORTER_OTLP_HEADERS
value: "Authorization=Bearer <CORALOGIX_API_KEY>"
- name: OTEL_SERVICE_NAME
value: "<SERVICE_NAME>"
- name: OTEL_RESOURCE_ATTRIBUTES
value: "cx.application.name=<CX_APPLICATION_NAME>,cx.subsystem.name=<CX_SUBSYSTEM_NAME>"
java:
image: ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-java:latestOpt in via pod annotation:
annotations:
instrumentation.opentelemetry.io/inject-java: "true"The agent env vars (OTEL_EXPORTER_OTLP_*, OTEL_RESOURCE_ATTRIBUTES) are injected automatically from the Instrumentation CRD spec. For Option B, use a Kubernetes Secret for the API key value rather than a plain-text value: field.
Language Selector — Decision Tree
Contents
- Step 1: Identify the Target Language / Runtime
- Step 2: Identify Telemetry Signals
- Step 3: Identify Instrumentation Mode
- Step 4: Identify Export Path
- Step 5: Collect Required Variables
Use this file to identify the language, signal, instrumentation mode, and export path before loading any language-specific reference. Walk each decision in order.
Step 1: Identify the Target Language / Runtime
| Language / runtime | Reference file to load next |
|---|---|
| Java (any JVM, Spring, Quarkus, etc.) | java.md |
| Python (Flask, Django, FastAPI, etc.) | python.md |
| Node.js / TypeScript (Express, Fastify, etc.) | nodejs.md |
| .NET / C# (ASP.NET Core, console apps) | dotnet.md |
| Go / Golang | go.md |
| Kubernetes injection (no specific lang yet) | Use java.md, python.md, nodejs.md, or dotnet.md — Operator supports all four |
| PHP | Not in scope for this skill — refer to Coralogix PHP docs |
| Lambda / serverless | Not in scope — refer to Coralogix Lambda OTel docs |
| Unknown | Show the matrix in Step 1b and ask |
Step 1b: Matrix when language is unknown
| Language | Auto-instr | Programmatic | Manual | K8s injection | Coralogix sampler pkg |
|---|---|---|---|---|---|
| Java | Agent JAR (opentelemetry-javaagent.jar) | ✗ | @WithSpan annotation (extends agent) | Yes (Operator) | None needed |
| Python | opentelemetry-instrument CLI | Yes | Yes | Yes (Operator) | coralogix-opentelemetry |
| Node.js | Bundled or individual | Via NodeSDK | Yes | Yes (Operator) | @coralogix/opentelemetry |
| .NET | Zero-code installer (dotnet-auto) | ✗ | Yes (NuGet SDK) | Yes (Operator) | None needed |
| Go | Out of scope here (OBI/Auto SDK exist) | ✗ | Covered by this skill | ✗ | coralogix-opentelemetry-go |
Step 2: Identify Telemetry Signals
Ask or infer which signals the user needs:
| Signal | Key requirement |
|---|---|
| Traces | Always needed for APM; require CoralogixTransactionSampler for Coralogix transactions |
| Metrics | Needed for Coralogix platform metric-dependent features; not required for APM traces-only |
| Logs | Via OTel log bridge (Log4j, SLF4J, slog, zap, NLog, log4net) — SDK logs pipeline, not file-based |
| All signals | Start with traces; metrics and logs can be added incrementally |
Step 3: Identify Instrumentation Mode
| Mode | When to use it |
|---|---|
| Auto-instrumentation | User wants minimal code changes; frameworks are well-supported |
| Programmatic | User wants some control (e.g. Python + custom samplers) without rewriting app |
| Manual | Full control over span creation; no existing auto-instrumentation library for the framework |
| Code review | Load language reference and output-templates.md review section |
| Troubleshooting | Load troubleshooting.md |
| Kubernetes injection | User deploys on K8s and wants no-code injection via OpenTelemetry Operator |
Mode notes by language
Java: Coralogix guidance emphasizes the Java agent plus @WithSpan annotation-based span additions. Upstream OpenTelemetry Java also supports pure SDK manual instrumentation, but that path is not the default Coralogix setup in this skill.
Python: Three distinct paths are documented: auto (opentelemetry-instrument wrapper), programmatic (SDK init inside app + FlaskInstrumentor), and manual (explicit tracer/span creation). All three can use CoralogixTransactionSampler from coralogix-opentelemetry.
Node.js: Bundled auto (@opentelemetry/auto-instrumentations-node via NODE_OPTIONS) vs individual auto (custom instrumentation.js with chosen libraries). Bundled does NOT support Coralogix transactions — use individual or manual for transaction support.
Go: This skill covers manual SDK instrumentation. Go zero-code/eBPF options exist, but they are out of scope for this SDK instrumentation skill.
Step 4: Identify Export Path
Do not make a final recommendation until you know the user's scale, runtime, deployment environment, enrichment needs, retry/buffering requirements, and sampling needs.
| Export path | Good fit when |
|---|---|
| Direct OTLP to Coralogix | Getting started, dev/test, simple deploys |
| Via OTel Collector | Existing collector, production/Kubernetes, enrichment, retry/buffering, or tail sampling needed |
| Unknown | Explain tradeoffs and ask for context |
Export path tradeoffs
| Aspect | Direct | Via Collector |
|---|---|---|
| Auth | SDK sets Authorization: Bearer <key> header | Collector holds the key; SDK exports unauthed to collector |
| Enrichment | Resource attrs in SDK only | Collector can add k8sattributes, detect host/cloud |
| Retry / buffer | SDK retry only | Collector sending_queue + file_storage |
| Sampling | SDK-side head sampling only | Collector can do tail sampling |
| Complexity | Low | Higher (collector deployment) |
Step 5: Collect Required Variables
Before generating any code or config, confirm these are known (or use placeholders):
| Variable | Placeholder |
|---|---|
| Coralogix region / domain | <CORALOGIX_REGION> (e.g. eu1, eu2, us1, us2, ap1, ap2, ap3) |
| Send-Your-Data API key | CORALOGIX_API_KEY env var |
| Service name | <SERVICE_NAME> |
| Application name (Coralogix) | <CX_APPLICATION_NAME> |
| Subsystem name (Coralogix) | <CX_SUBSYSTEM_NAME> |
| Runtime / framework | (e.g. Flask, Spring Boot, Express, ASP.NET Core) |
| Deployment target | (e.g. bare metal, Docker, Kubernetes, ECS) |
If the region is unknown, instruct the user to find it from their Coralogix platform URL: https://dashboard.<region>.coralogix.com → the region is the subdomain prefix before .coralogix.com. Always load coralogix-endpoints.md when generating endpoint config.
Node.js OpenTelemetry Instrumentation
Contents
- Overview
- Required packages
- Bundled Auto-Instrumentation
- Individual Auto-Instrumentation (supports Coralogix transactions)
- Manual Instrumentation
- Exception Logging
- Kubernetes Injection
- Common Mistakes
Source: Coralogix Node.js OpenTelemetry Instrumentation documentation.
Legacy SDK Deprecation
The Coralogix Node.js SDK (coralogix-logger, @coralogix/coralogix-sdk) and the Coralogix Winston and Bunyan integrations are deprecated and reach end-of-life on June 30, 2026. The official Coralogix Node.js SDK docs page has already been rewritten to show OpenTelemetry as the replacement. If a user asks about coralogix-logger, the Coralogix Winston integration, or the Coralogix Bunyan integration, redirect them to OTel Node.js instrumentation immediately. Do not explain how to configure the deprecated packages.
See: https://coralogix.com/docs/user-guides/latest-updates/deprecations/
Prerequisites
- Node.js
^18.19.0 || >=20.6.0(required by OTel JS SDK 2.x — Node 14/16 are not supported) - Coralogix Send-Your-Data API key and region/domain.
Overview
Node.js supports three approaches:
1. Bundled auto-instrumentation — loads all available auto-instrumentation libraries via NODE_OPTIONS. 2. Individual auto-instrumentation — custom instrumentation.js with chosen libraries. 3. Manual instrumentation — explicit BasicTracerProvider + span creation.
Coralogix transactions caveat: Bundled auto-instrumentation is NOT supported for Coralogix transactions (APM → Transactions view). Use individual auto-instrumentation or manual instrumentation to enable CoralogixTransactionSampler.
Required packages
Use the official OpenTelemetry Node.js getting-started guide for SDK installation: https://opentelemetry.io/docs/languages/js/getting-started/nodejs/
For Coralogix APM Transactions, include @coralogix/opentelemetry in the same dependency management flow.
Bundled Auto-Instrumentation
Set environment variables and use NODE_OPTIONS to load the registration library:
export OTEL_TRACES_EXPORTER="otlp"
export OTEL_EXPORTER_OTLP_PROTOCOL="grpc"
export OTEL_EXPORTER_OTLP_COMPRESSION="gzip"
# gRPC endpoint: bare host:port is the standard Coralogix form; https://host:port is also accepted
export OTEL_EXPORTER_OTLP_ENDPOINT="ingress.<CORALOGIX_REGION>.coralogix.com:443"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <CORALOGIX_API_KEY>"
export OTEL_NODE_RESOURCE_DETECTORS="all"
export OTEL_SERVICE_NAME="<SERVICE_NAME>"
export OTEL_RESOURCE_ATTRIBUTES="cx.application.name=<CX_APPLICATION_NAME>,cx.subsystem.name=<CX_SUBSYSTEM_NAME>"
node --require @opentelemetry/auto-instrumentations-node/register YourApp.jsOr using NODE_OPTIONS:
export NODE_OPTIONS="--require @opentelemetry/auto-instrumentations-node/register"
node YourApp.jsReminder: Env vars cannot be set inside the application code — they must be available before the auto-instrumentation library starts at process startup.
Limitation: Bundled auto-instrumentation does NOT support Coralogix transactions. Switch to individual method below if transactions are needed.
ESM apps (using `import` syntax): --require does not fire for ES modules — auto-instrumentation silently does nothing. Use --import plus the loader hook instead:
node --experimental-loader=@opentelemetry/instrumentation/hook.mjs \
--import @opentelemetry/auto-instrumentations-node/register YourApp.mjsIndividual Auto-Instrumentation (supports Coralogix transactions)
Create an instrumentation.js file:
// instrumentation.js
const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http');
const { ExpressInstrumentation } = require('@opentelemetry/instrumentation-express');
const opentelemetry = require("@opentelemetry/sdk-node");
const { CoralogixTransactionSampler } = require("@coralogix/opentelemetry");
const { AlwaysOnSampler } = require("@opentelemetry/sdk-trace-base");
// Exporter is configured via env vars (OTEL_TRACES_EXPORTER, OTEL_EXPORTER_OTLP_PROTOCOL,
// OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_HEADERS) — same as the bundled approach.
const sdk = new opentelemetry.NodeSDK({
sampler: new CoralogixTransactionSampler(new AlwaysOnSampler()),
instrumentations: [
new HttpInstrumentation(),
new ExpressInstrumentation(),
// add more individual instrumentation libraries as needed
],
});
sdk.start();Use the same environment variables as bundled (above), then run:
node --require ./instrumentation.js YourApp.jsThis approach allows CoralogixTransactionSampler to be wired into the sampler chain, enabling Coralogix Transactions support.
Manual Instrumentation
Full manual control over span creation using NodeTracerProvider:
const opentelemetry = require('@opentelemetry/api');
const { resourceFromAttributes } = require('@opentelemetry/resources');
const { ATTR_SERVICE_NAME } = require('@opentelemetry/semantic-conventions');
const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
const { SimpleSpanProcessor, AlwaysOnSampler } = require('@opentelemetry/sdk-trace-base');
const { OTLPTraceExporter } = require("@opentelemetry/exporter-trace-otlp-proto");
const { CoralogixTransactionSampler } = require('@coralogix/opentelemetry');
const exporter = new OTLPTraceExporter({
timeoutMillis: 15000,
// HTTP/proto exporter requires /v1/traces path
url: 'https://ingress.<CORALOGIX_REGION>.coralogix.com:443/v1/traces',
headers: {
Authorization: `Bearer ${process.env.CORALOGIX_API_KEY}`,
},
});
const provider = new NodeTracerProvider({
resource: resourceFromAttributes({
[ATTR_SERVICE_NAME]: '<SERVICE_NAME>',
'cx.application.name': '<CX_APPLICATION_NAME>',
'cx.subsystem.name': '<CX_SUBSYSTEM_NAME>',
}),
sampler: new CoralogixTransactionSampler(new AlwaysOnSampler()),
spanProcessors: [new SimpleSpanProcessor(exporter)],
});
provider.register();
// Graceful shutdown
['SIGINT', 'SIGTERM'].forEach(signal => {
process.on(signal, () => provider.shutdown().catch(console.error));
});
const tracer = opentelemetry.trace.getTracer('<SERVICE_NAME>');
const span = tracer.startSpan('main');
// ... do work ...
span.end();Required package artifacts for manual
Name these package artifacts when explaining the manual setup, but use the official OpenTelemetry Node.js getting-started guide for installation details and current versions:
@opentelemetry/api@opentelemetry/exporter-trace-otlp-proto@opentelemetry/resources@opentelemetry/sdk-trace-base@opentelemetry/sdk-trace-node@coralogix/opentelemetry
Exception Logging
const { logs, SeverityNumber } = require('@opentelemetry/api-logs');
const { LoggerProvider, SimpleLogRecordProcessor } = require('@opentelemetry/sdk-logs');
const loggerProvider = new LoggerProvider({
processors: [new SimpleLogRecordProcessor(/* add OTLP exporter here */)],
});
logs.setGlobalLoggerProvider(loggerProvider);
const logger = logs.getLogger('my-logger', '1.0.0');
const error = new Error('database connection failed');
logger.emit({
severityNumber: SeverityNumber.ERROR,
severityText: 'ERROR',
body: 'request failed',
exception: error,
});Exception support requires @opentelemetry/api-logs and @opentelemetry/sdk-logs >= 0.212.0.
Kubernetes Injection
The OpenTelemetry Operator supports Node.js auto-instrumentation injection:
annotations:
instrumentation.opentelemetry.io/inject-nodejs: "true"Context Propagation
OTel Node.js propagates W3C traceparent headers automatically on outgoing HTTP requests via @opentelemetry/instrumentation-http. To verify propagation is working:
1. Enable SDK debug logging — look for traceparent in outgoing request headers in the output 2. Confirm the downstream service uses W3C TraceContext propagator (not B3/Zipkin only) 3. Verify intermediaries (load balancers, API gateways) are not stripping traceparent
If the downstream service creates independent spans despite receiving traceparent:
- .NET Framework backends need
OpenTelemetry.Instrumentation.AspNet+AddAspNetInstrumentation()on the server-sideTracerProviderto read incomingtraceparentheaders (AddHttpClientInstrumentationinstruments outgoing calls, not incoming) - Java Spring backends need
opentelemetry-spring-webmvc-instrumentationon the receiver - Some frameworks require
TextMapPropagatorto be configured explicitly to read the header
Common Mistakes
| Mistake | Symptom | Fix |
|---|---|---|
Using --require in an ESM app | Auto-instrumentation silently does nothing | Use --import + --experimental-loader=@opentelemetry/instrumentation/hook.mjs for ESM |
| Setting env vars inside the app | Auto-instrumentation ignores them | Set env vars before process start |
| Bundled auto-instr + expects Transactions | Transactions view empty in Coralogix | Switch to individual method with CoralogixTransactionSampler |
HTTP exporter URL missing /v1/traces path | 404 from Coralogix | Append /v1/traces to the HTTP/proto endpoint URL |
gRPC exporter URL includes /v1/traces path | Connection or export failure | gRPC endpoints have no signal path. Prefer ingress.<region>.coralogix.com:443; https://host:port is also accepted. HTTP/proto uses https://...:443/v1/<signal> |
OTEL_NODE_RESOURCE_DETECTORS=all on local machine | Resource detector errors | Use env,host,os,process locally to suppress errors |
Missing cx.application.name / cx.subsystem.name | APM features degraded | Set as resource attributes in SDK or as OTLP headers |
Output Templates
Contents
- Template 1: New Instrumentation Setup
- Template 2: Code Review
- Template 3: Troubleshooting
- Complete Examples (per-language)
- Formatting rules for all templates
Use these templates when generating a final user-facing instrumentation answer. Choose the appropriate template based on the request type.
Template 1: New Instrumentation Setup
Use for: "How do I instrument my X app with OpenTelemetry to send to Coralogix?"
---
Assumptions
- Language:
<language> - Signal(s):
<traces | metrics | logs | all> - Instrumentation mode:
<auto | programmatic | manual> - Export path:
<direct to Coralogix | via OTel Collector> - Coralogix region:
<region>(e.g.eu2) - Framework:
<framework if known>
Required inputs (use placeholders)
CORALOGIX_API_KEY— Send-Your-Data API key from Settings → API Keys<SERVICE_NAME>— your service name (appears in APM service map)<CX_APPLICATION_NAME>— Coralogix application name (groups services)<CX_SUBSYSTEM_NAME>— Coralogix subsystem name (refines routing)
Install reference
- Link to
https://opentelemetry.io/docs/languages/<language>/getting-started/for SDK installation.
Environment variables
# All required env vars with placeholders
# HTTP/protobuf — base URL only; SDK auto-appends /v1/traces, /v1/metrics, /v1/logs
export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingress.<CORALOGIX_REGION>.coralogix.com:443"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <CORALOGIX_API_KEY>"
# gRPC endpoint: standard bare form for Python/Node.js/Go; Java/.NET use https://host:port
# export OTEL_EXPORTER_OTLP_ENDPOINT="ingress.<CORALOGIX_REGION>.coralogix.com:443"
# Python exception: URL-encode the space in env-var headers
# export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer%20<CORALOGIX_API_KEY>"
export OTEL_SERVICE_NAME="<SERVICE_NAME>"
export OTEL_RESOURCE_ATTRIBUTES="cx.application.name=<CX_APPLICATION_NAME>,cx.subsystem.name=<CX_SUBSYSTEM_NAME>"Code / config snippet
# Minimal working example — copy, paste, replace placeholdersRun command
# How to start the instrumented applicationValidation steps 1. Start the application and generate some traffic. 2. Traces → Coralogix UI Explore → Tracing (allow ~30s for first trace). 3. Metrics (if enabled) → Grafana → Explore → Metric Browser. 4. Logs (if enabled) → Coralogix UI Logs.
Security reminders
- Never commit the
CORALOGIX_API_KEYvalue to source control. Use a secrets manager or env var. - Rotate Send-Your-Data keys if they are exposed.
---
Template 2: Code Review
Use for: "Review my OTel instrumentation code" or "What am I missing?"
---
Review findings for `<language>` instrumentation
| Item | Status | Notes |
|---|---|---|
| OTLP endpoint format | ✅ / ❌ | gRPC Java/.NET: https://ingress.<region>.coralogix.com:443 (URI required); gRPC Python/Node.js: prefer ingress.<region>.coralogix.com:443, but https://host:port is accepted; Go WithEndpoint: bare host:port only; HTTP/proto: https://ingress.<region>.coralogix.com:443/v1/<signal> |
| Auth header present | ✅ / ❌ | Authorization=Bearer <key>; Python env vars require Authorization=Bearer%20<key> |
cx.application.name set | ✅ / ❌ | Required resource attribute |
cx.subsystem.name set | ✅ / ❌ | Required resource attribute |
service.name set | ✅ / ❌ | Required for APM service map |
| CoralogixTransactionSampler | ✅ / ❌ / N/A | Required for APM Transactions view |
| Protocol matches exporter | ✅ / ❌ | gRPC vs HTTP/proto |
| No hardcoded secrets | ✅ / ❌ | Keys should be in env vars |
| Telemetry quality | ✅ / ❌ | Low-cardinality span names, bounded metric attributes, no sensitive data, structured logs with trace/span correlation |
Issues found 1. <specific issue and fix> 2. <specific issue and fix>
Corrected snippet
# Corrected minimal working code---
Template 3: Troubleshooting
Use for: "I'm not seeing any traces / metrics / logs in Coralogix."
---
Troubleshooting: missing `<signal>` from `<language>` app
Load troubleshooting.md for the full symptom table. Quick checklist:
1. Enable SDK debug logging — see troubleshooting.md for per-language instructions. 2. Verify endpoint — is OTEL_EXPORTER_OTLP_ENDPOINT set to https://ingress.<region>.coralogix.com:443/v1/traces for HTTP/protobuf or ingress.<region>.coralogix.com:443 for gRPC? 3. Verify auth — does OTEL_EXPORTER_OTLP_HEADERS contain Authorization=Bearer <key>? 4. Verify region — does the region match the Coralogix account's region? 5. Check for Python URL encoding — is the header value URL encoded (%20 not space)? 6. Check network — can the app reach ingress.<region>.coralogix.com:443? 7. Check signal is enabled — are trace/metric/log exporters set (not "none")? 8. Check correlation and safety — do logs include trace/span context, and are sensitive fields excluded?
---
Complete Examples (per-language)
Use these as the basis for Template 1 answers. Replace eu2 with the user's actual region. All examples send traces only (direct to Coralogix, gRPC). Enable metrics/logs by changing the exporter env vars per the language reference.
---
Java — auto-instrumentation, traces, EU2
export JAVA_TOOL_OPTIONS="-javaagent:/path/to/opentelemetry-javaagent.jar"
export OTEL_TRACES_EXPORTER="otlp"
export OTEL_METRICS_EXPORTER="none"
export OTEL_LOGS_EXPORTER="none"
export OTEL_EXPORTER_OTLP_TRACES_PROTOCOL="grpc"
export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingress.eu2.coralogix.com:443"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <CORALOGIX_API_KEY>"
export OTEL_SERVICE_NAME="order-service"
export OTEL_RESOURCE_ATTRIBUTES="cx.application.name=ecommerce,cx.subsystem.name=orders"
java -jar myapp.jarValidation: Coralogix UI → Explore → Tracing (look for [otel.javaagent ...] log line at startup).
---
Python — auto-instrumentation, traces, EU2
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer%20<CORALOGIX_API_KEY>"
export OTEL_EXPORTER_OTLP_ENDPOINT="ingress.eu2.coralogix.com:443"
export OTEL_TRACES_EXPORTER="otlp_proto_grpc"
export OTEL_SERVICE_NAME="order-service"
export OTEL_RESOURCE_ATTRIBUTES="cx.application.name=ecommerce,cx.subsystem.name=orders"
opentelemetry-instrument python app.pyNote: %20 in OTEL_EXPORTER_OTLP_HEADERS is the URL-encoded space — required for Python env var auth. Do not use %20 in programmatic code.
Validation: Coralogix UI → Explore → Tracing.
---
Node.js — individual auto-instrumentation with Coralogix transactions, EU2
instrumentation.js:
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { HttpInstrumentation } = require('@opentelemetry/instrumentation-http');
const { ExpressInstrumentation } = require('@opentelemetry/instrumentation-express');
const { CoralogixTransactionSampler } = require('@coralogix/opentelemetry');
const { AlwaysOnSampler } = require('@opentelemetry/sdk-trace-base');
const sdk = new NodeSDK({
sampler: new CoralogixTransactionSampler(new AlwaysOnSampler()),
instrumentations: [new HttpInstrumentation(), new ExpressInstrumentation()],
});
sdk.start();export OTEL_EXPORTER_OTLP_PROTOCOL="grpc"
export OTEL_EXPORTER_OTLP_ENDPOINT="ingress.eu2.coralogix.com:443"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <CORALOGIX_API_KEY>"
export OTEL_SERVICE_NAME="order-service"
export OTEL_RESOURCE_ATTRIBUTES="cx.application.name=ecommerce,cx.subsystem.name=orders"
node --require ./instrumentation.js app.jsValidation: Coralogix UI → Explore → Tracing; APM → Transactions (requires CoralogixTransactionSampler).
---
.NET — auto-instrumentation (zero-code), traces, EU2
export OTEL_TRACES_EXPORTER="otlp"
export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingress.eu2.coralogix.com:443"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <CORALOGIX_API_KEY>"
export OTEL_EXPORTER_OTLP_PROTOCOL="grpc"
export OTEL_SERVICE_NAME="order-service"
export OTEL_RESOURCE_ATTRIBUTES="cx.application.name=ecommerce,cx.subsystem.name=orders"Run the OpenTelemetry .NET Auto-Instrumentation profiler per the official docs.
Validation: Coralogix UI → Explore → Tracing.
---
Go — manual SDK, traces, EU2
package main
import (
"context"
"fmt"
"os"
"github.com/coralogix/coralogix-opentelemetry-go/sampler"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
"google.golang.org/grpc/credentials"
)
func main() {
ctx := context.Background()
endpoint := os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT") // ingress.eu2.coralogix.com:443
token := os.Getenv("CORALOGIX_API_KEY")
res, _ := resource.Merge(resource.Default(), resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceName("order-service"),
attribute.String("cx.application.name", "ecommerce"),
attribute.String("cx.subsystem.name", "orders"),
))
exp, _ := otlptracegrpc.New(ctx,
otlptracegrpc.WithEndpoint(endpoint),
otlptracegrpc.WithHeaders(map[string]string{"Authorization": "Bearer " + token}),
otlptracegrpc.WithTLSCredentials(credentials.NewTLS(nil)),
)
tp := sdktrace.NewTracerProvider(
sdktrace.WithSampler(sampler.NewCoralogixSampler(sdktrace.AlwaysSample())),
sdktrace.WithResource(res),
sdktrace.WithSpanProcessor(sdktrace.NewBatchSpanProcessor(exp)),
)
defer tp.Shutdown(ctx)
otel.SetTracerProvider(tp)
tracer := otel.Tracer("order-service")
_, span := tracer.Start(ctx, "process-order")
span.SetAttributes(attribute.String("order.id", "42"))
// ... do work ...
span.End()
fmt.Println("done")
}export OTEL_EXPORTER_OTLP_ENDPOINT="ingress.eu2.coralogix.com:443"
export CORALOGIX_API_KEY="your-send-your-data-key"
go run main.goValidation: Coralogix UI → Explore → Tracing.
---
Formatting rules for all templates
- Always use code blocks with the correct language identifier.
- Replace
{{ endpoints.opentelemetry }}template variables (from the docs source) with
the actual regional endpoint. Use the base URL for OTEL_EXPORTER_OTLP_ENDPOINT — do NOT include /v1/traces in the base env var (SDK appends signal path automatically for HTTP/proto):
- gRPC Java/.NET:
https://ingress.<CORALOGIX_REGION>.coralogix.com:443 - gRPC Python/Node.js:
ingress.<CORALOGIX_REGION>.coralogix.com:443 - gRPC Go
WithEndpoint:ingress.<CORALOGIX_REGION>.coralogix.com:443(bare only) - HTTP/proto
OTEL_EXPORTER_OTLP_ENDPOINT:https://ingress.<CORALOGIX_REGION>.coralogix.com:443 - HTTP/proto programmatic exporter URL:
https://ingress.<CORALOGIX_REGION>.coralogix.com:443/v1/traces - For the API key, reference
<CORALOGIX_API_KEY>(shell) oros.environ["CORALOGIX_API_KEY"](code) — never generate example key values. - Use inline comments in code blocks only where the line is non-obvious.
- Include validation steps in every new instrumentation answer.
- Keep the "security reminder" section — teams often overlook secret management.
- Do not document SDK installation steps inline; link to the official OpenTelemetry language
getting-started page.
Troubleshooting — SDK Instrumentation to Coralogix
Contents
- Symptom → Root Cause Table
- Enable SDK Debug Logging
- Connectivity Check
- Decision Flow
- Out-of-Scope Issues
Use this reference for "no data", "missing traces", "missing metrics", or "missing logs" reports from the application SDK side (not collector-side issues).
Symptom → Root Cause Table
| Symptom | Most likely cause | First action |
|---|---|---|
| No traces in Coralogix, no error in app | Endpoint wrong or auth header missing | Enable SDK debug logging; check OTEL_EXPORTER_OTLP_ENDPOINT and OTEL_EXPORTER_OTLP_HEADERS |
| 401 / Unauthorized from Coralogix | Wrong API key type or malformed auth header | Confirm key is Send-Your-Data; check Authorization=Bearer <key> format |
connection refused or timeout | Wrong region / DNS failure / port blocked | Verify endpoint ingress.<region>.coralogix.com:443; test connectivity with curl or nc |
| TLS handshake failure or silent export failure | Go: missing credentials.NewTLS; Java/.NET: endpoint missing https:// scheme | Add TLS credentials (Go); for Java and .NET ensure endpoint is https://ingress.<region>.coralogix.com:443 — bare host:port fails because the Java/dotnet OTLP exporter performs URI parsing |
| Traces arrive but no APM Transactions | Missing CoralogixTransactionSampler | Add CoralogixTransactionSampler to sampler chain (Python, Node.js, Go) |
| Python: traces arrive but auth fails intermittently | OTLP header not URL encoded | Replace Bearer <key> with Bearer%20<key> in OTEL_EXPORTER_OTLP_HEADERS |
| Node.js: no transactions despite setting up CoralogixTransactionSampler | Using bundled auto-instrumentation | Switch to individual instrumentation.js method |
| HTTP/proto exporter: no traces, no error (any language) | Programmatic exporter URL missing /v1/traces path, or OTEL_EXPORTER_OTLP_ENDPOINT contains /v1/traces (double-path for env var form) | Programmatic: append /v1/traces to the URL passed to the exporter constructor. Env var: use OTEL_EXPORTER_OTLP_ENDPOINT as base URL without signal path — the SDK appends /v1/traces automatically for HTTP/proto. |
| Python: short-lived script exports no traces and/or no metrics | BatchSpanProcessor drops spans before timer fires; PeriodicExportingMetricReader never fires its interval before exit | For traces: use SimpleSpanProcessor instead of BatchSpanProcessor. For metrics: call metric_reader.force_flush() before provider.shutdown(), or sleep past export_interval_millis. |
| Go/Java/.NET: last spans or metrics missing at process exit | Provider not shut down before process exits | Go: always defer tp.Shutdown(ctx). .NET: add Thread.Sleep(1000) or call provider.Shutdown() before exit. Java: agent handles shutdown automatically; no action needed. |
| Java: no traces at startup | Agent JAR not attached | Check for [otel.javaagent ...] log line; verify -javaagent: path in JAVA_TOOL_OPTIONS |
Traces visible but no cx.application.name / cx.subsystem.name in Coralogix | Missing resource attributes | Add cx.application.name and cx.subsystem.name to OTEL_RESOURCE_ATTRIBUTES |
| Metrics not appearing in Grafana | Metrics exporter set to "none" | Set OTEL_METRICS_EXPORTER=otlp (or otlp_proto_grpc for Python) |
| Go: last spans missing at process exit | No deferred tp.Shutdown() | Always defer tp.Shutdown(ctx) with a timeout context |
| .NET: no data exported before process exit | Thread.Sleep too short | Add 1–5 second sleep after span/metric creation before exit |
| .NET: no traces exported despite endpoint/auth set | OTEL_TRACES_EXPORTER is empty or "none" | Set OTEL_TRACES_EXPORTER=otlp |
| Logs cannot be correlated with traces | Missing trace/span context in structured logs | Include trace_id and span_id in log records emitted inside active spans |
| Metrics are too expensive or unusable | High-cardinality metric attributes | Keep metric attributes bounded; avoid user IDs, request IDs, raw paths, and timestamps |
| Data in wrong Coralogix account / team | Wrong region for the account | Confirm region from Coralogix UI URL (dashboard.<region>.coralogix.com) |
APM Service Catalog empty; all spans show as internal or client, no server spans | Auto-instrumentation missing server-side framework library, or framework not instrumented | Verify the HTTP server framework instrumentation library is loaded (e.g. @opentelemetry/instrumentation-express, Spring MVC, ASP.NET Core); check SDK debug logs for active instrumentations list |
Spanmetrics show STATUS_CODE_UNSET for error spans | SDK not explicitly setting span status on exceptions | Java and Node.js auto-set span status via exception handlers; .NET requires explicit activity.SetStatus(ActivityStatusCode.Error, message) in catch blocks |
| Distributed trace broken: downstream service creates independent spans instead of continuing the trace | W3C TraceContext propagation not configured on the receiving service | Verify all services in the chain use W3C traceparent (not B3/Zipkin); .NET Framework specifically needs OpenTelemetry.Instrumentation.AspNet + AddAspNetInstrumentation() on the receiving TracerProvider to extract incoming trace context |
Enable SDK Debug Logging
Debug logging from the OTel SDK is the fastest way to see what is happening at export time.
Java
export OTEL_LOG_LEVEL=debug
# or JVM property:
-Dotel.log.level=debugLook for io.opentelemetry.exporter.otlp log messages showing export attempts.
Python
export OTEL_PYTHON_LOG_LEVEL=debugOr in code before setting up providers:
import logging
logging.basicConfig(level=logging.DEBUG)Node.js
const { diag, DiagConsoleLogger, DiagLogLevel } = require('@opentelemetry/api');
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG);Add this before any SDK initialization.
.NET
export OTEL_LOG_LEVEL=debugFor SDK self-diagnostics, create OTEL_DIAGNOSTICS.json in the process working directory:
{
"LogDirectory": ".",
"FileSize": 32768,
"LogLevel": "Warning",
"FormatMessage": "true"
}Or configure application logging via appsettings.json for ASP.NET Core:
{
"Logging": {
"LogLevel": {
"OpenTelemetry": "Debug"
}
}
}Go
The Go SDK does not have a built-in env var for debug logging. Use the OTel error handler:
otel.SetErrorHandler(otel.ErrorHandlerFunc(func(err error) {
fmt.Fprintf(os.Stderr, "OTEL error: %v\n", err)
}))Connectivity Check
Test OTLP endpoint reachability from the application host:
# Check TCP connectivity to the OTLP gRPC endpoint
nc -zv ingress.<CORALOGIX_REGION>.coralogix.com 443
# Or with curl (HTTP/proto)
curl -v https://ingress.<CORALOGIX_REGION>.coralogix.com:443/v1/traces \
-H "Authorization: Bearer <CORALOGIX_API_KEY>" \
-H "Content-Type: application/x-protobuf" \
-d "" 2>&1 | head -20A 400 response from Coralogix (empty body) confirms connectivity and auth work. A timeout or connection refused points to a network or firewall issue.
Decision Flow
No data in Coralogix?
│
├─ Is this a short-lived Python script (exits in under a second)?
│ ├─ Traces missing → BatchSpanProcessor queues spans on a background timer and silently drops
│ │ them if the process exits before the timer fires; use SimpleSpanProcessor instead
│ └─ Metrics missing → PeriodicExportingMetricReader only exports on its configured interval
│ (default 60 s); a script that exits before the interval fires exports zero metrics;
│ fix: call metric_reader.force_flush() before provider.shutdown(), or sleep past the interval
│
├─ Does SDK debug log show export attempts?
│ ├─ No → SDK not initialized or signal exporter = "none" → fix init / exporter config
│ └─ Yes → export errors shown?
│ ├─ 401/403 → wrong key or malformed auth header
│ ├─ timeout/refused → network, firewall, wrong endpoint
│ └─ No errors, 0 spans exported → nothing instrumented; no traffic; sampler dropping all
│
├─ Is OTEL_EXPORTER_OTLP_ENDPOINT correct?
│ Format: https://ingress.<region>.coralogix.com:443 (Java/.NET gRPC),
│ ingress.<region>.coralogix.com:443 (standard Python/Node.js/Go gRPC),
│ or https://....:443/v1/traces (HTTP/protobuf)
│
├─ Is OTEL_EXPORTER_OTLP_HEADERS correct?
│ Format: Authorization=Bearer <key>
│ Python: Authorization=Bearer%20<key> (URL-encoded space)
│
├─ Are service identity attributes present?
│ Check OTEL_SERVICE_NAME plus cx.application.name and cx.subsystem.name in OTEL_RESOURCE_ATTRIBUTES
│
├─ Is telemetry safe and queryable?
│ Avoid sensitive data, keep span names low-cardinality, and keep metric labels bounded
│
└─ Is the region correct?
Check: Coralogix platform URL → dashboard.<region>.coralogix.comOut-of-Scope Issues
If the SDK is exporting successfully (no export errors, data visible in Coralogix) but:
- Data is missing enrichment (no pod name, no namespace) — this is a collector-side or
k8sattributes issue; use the opentelemetry-collector skill.
- Broken distributed trace propagation (downstream creates independent spans despite receiving
traceparent) — check that all services use W3C TraceContext propagator; .NET Framework needsOpenTelemetry.Instrumentation.AspNet+AddAspNetInstrumentation()on the receiving service (notAddHttpClientInstrumentation, which only covers outgoing calls); verify intermediaries (load balancers, API gateways) are not stripping thetraceparentheader. - Span data is malformed (wrong span kind, missing parent) — instrumentation library or propagator configuration issue in the app, not a Coralogix issue.
- Platform features not working (APM service map incomplete, Infrastructure Explorer
empty) — verify resource attributes first; then check collector config.