LogoLogo
StackState.comDownloadSupportExplore playground
StackState v5.1
StackState v5.1
  • Welcome to the StackState docs!
  • StackState self-hosted v5.1 docs
  • Getting Started
  • 🚀Setup
    • Install StackState
      • Requirements
      • Kubernetes / OpenShift
        • Kubernetes install
        • OpenShift install
        • Required Permissions
        • Non-high availability setup
        • Override default configuration
        • Configure storage
        • Configure Ingress
        • Install from custom image registry
        • Migrate from Linux install
      • Linux
        • Before you install
        • Download
        • Install StackState
        • Install with production configuration
        • Install with development configuration
        • Install with POC configuration
        • Set up a reverse proxy
        • Set up TLS without reverse proxy
      • Initial run guide
      • Troubleshooting
    • Upgrade StackState
      • Steps to upgrade
      • Version specific upgrade instructions
      • StackPack versions
      • StackState release notes
    • StackState Agent
      • About StackState Agent V3
      • Docker
      • Kubernetes / OpenShift
      • Linux
      • Windows
      • Advanced Agent configuration
      • Use an HTTP/HTTPS proxy
      • Agent V1 (legacy)
      • Migrate Agent V1 to Agent V2
        • Linux
        • Docker
    • StackState CLI
      • CLI: sts
      • CLI: stac (deprecated)
      • Comparison between CLIs
    • Data management
      • Backup and Restore
        • Kubernetes backup
        • Linux backup
        • Configuration backup
      • Data retention
      • Clear stored data
  • 👤Use
    • Concepts
      • The 4T data model
      • Components
      • Relations
      • Health state
      • Layers, Domains and Environments
      • Perspectives
      • Anomaly detection
      • StackState architecture
    • StackState UI
      • Explore mode
      • Filters
      • Views
        • About views
        • Configure the view health
        • Create and edit views
        • Visualization settings
      • Perspectives
        • Topology Perspective
        • Events Perspective
        • Traces Perspective
        • Metrics Perspective
      • Timeline and time travel
      • Analytics
      • Keyboard shortcuts
    • Checks and monitors
      • Checks
      • Add a health check
      • Anomaly health checks
      • Monitors
      • Manage monitors
    • Problem analysis
      • About problems
      • Problem lifecycle
      • Investigate a problem
      • Problem notifications
    • Metrics
      • Telemetry streams
      • Golden signals
      • Top metrics
      • Add a telemetry stream
      • Browse telemetry
      • Set telemetry stream priority
    • Events
      • About events
      • Event notifications
      • Manage event handlers
    • Glossary
  • 🧩StackPacks
    • About StackPacks
    • Add-ons
      • Autonomous Anomaly Detector
      • Health Forecast
    • Integrations
      • About integrations
      • 💠StackState Agent V2
      • 💠AWS
        • AWS
        • AWS ECS
        • AWS X-ray
        • StackState/Agent IAM role: EC2
        • StackState/Agent IAM role: EKS
        • Policies for AWS
        • AWS (legacy)
        • Migrate AWS (legacy) to AWS
      • 💠Dynatrace
      • 💠Kubernetes
      • 💠OpenShift
      • 💠OpenTelemetry
        • About instrumentations
        • AWS NodeJS Instrumentation
        • Manual Instrumentation
          • Prerequisites
          • Tracer and span mappings
          • Relations between components
          • Span health state
          • Merging components
          • Code examples
      • 💠ServiceNow
      • 💠Slack
      • 💠Splunk
        • Splunk
        • Splunk Events
        • Splunk Health
        • Splunk Metrics
        • Splunk Topology
      • 💠VMWare vSphere
      • Apache Tomcat
      • Azure
      • Cloudera
      • Custom Synchronization
      • DotNet APM
      • Elasticsearch
      • Humio
      • Java APM
      • JMX
      • Logz.io
      • MySQL
      • Nagios
      • OpenMetrics
      • PostgreSQL
      • Prometheus
      • SAP
      • SCOM
      • SolarWinds
      • Static Health
      • Static Topology
      • Traefik
      • WMI
      • Zabbix
    • Develop your own StackPacks
  • 🔧Configure
    • Topology
      • Component actions
      • Identifiers
      • Topology naming guide
      • Topology sources
      • Create a topology manually
      • Configure topology synchronizations
      • Enable email event notifications
      • Send topology data over HTTP
      • Set the topology filtering limit
      • Use a proxy for event handlers
      • Use tags
      • Tune topology synchronization
      • Debug topology synchronization
    • Telemetry
      • Add telemetry during topology synchronization
      • Data sources
        • Elasticsearch
        • Prometheus mirror
      • Send events over HTTP
      • Send metrics data over HTTP
      • Set the default telemetry interval
      • Debug telemetry synchronization
    • Traces
      • Set up traces
      • Advanced configuration for traces
    • Health
      • Health synchronization
      • Send health data over HTTP
        • Send health data
        • Repeat Snapshots JSON
        • Repeat States JSON
        • Transactional Increments JSON
      • Debug health synchronization
    • Anomaly Detection
      • Export anomaly feedback
      • Scale the AAD up and down
      • The AAD status UI
    • Security
      • Authentication
        • Authentication options
        • File based
        • LDAP
        • Open ID Connect (OIDC)
        • KeyCloak
        • Service tokens
      • RBAC
        • Role-based Access Control
        • Permissions
        • Roles
        • Scopes
        • Subjects
      • Secrets management
      • Self-signed certificates
      • Set up a security backend for Linux
      • Set up a security backend for Windows
    • Logging
      • Kubernetes logs
      • Linux logs
      • Enable logging for functions
  • 📖Develop
    • Developer guides
      • Agent checks
        • About Agent checks
        • Agent check API
        • Agent check state
        • How to develop Agent checks
        • Connect an Agent check to StackState
      • Custom functions and scripts
        • StackState functions
        • Check functions
        • Component actions
        • Event handler functions
        • ID extractor functions
        • Mapping functions
        • Monitor functions
        • Propagation functions
        • Template functions
        • View health state configuration functions
      • Custom Synchronization StackPack
        • About the Custom Synchronization StackPack
        • How to customize elements created by the Custom Synchronization StackPack
        • How to configure a custom synchronization
      • Integrate external services
      • Mirroring Telemetry
      • Monitors
        • Create monitors
        • Monitor STJ file format
      • StackPack development
        • How to create a StackPack
        • Packaging
        • How to get a template file
        • How to make a multi-instance StackPack
        • Prepare a multi-instance provisioning script
        • Upload a StackPack file
        • Prepare a shared template
        • Customize a StackPack
        • Prepare instance template files
        • Prepare a StackPack provisioning script
        • Resources in a StackPack
        • StackState Common Layer
      • Synchronizations and templated files
    • Reference
      • StackState OpenAPI docs
      • StackState Template JSON (STJ)
        • Using STJ
        • Template functions
      • StackState Markup Language (STML)
        • Using STML
        • STML Tags
      • StackState Query Language (STQL)
      • StackState Scripting Language (STSL)
        • Scripting in StackState
        • Script result: Async
        • Script result: Streaming
        • Time in scripts
        • Script APIs
          • Async - script API
          • Component - script API
          • HTTP - script API
          • Prediction - script API
          • StackPack - script API
          • Telemetry - script API
          • Time - script API
          • Topology - script API
          • UI - script API
          • View - script API
    • Tutorials
      • Create a simple StackPack
      • Push data to StackState from an external system
      • Send events to StackState from an external system
      • Set up a mirror to pull telemetry data from an external system
Powered by GitBook
LogoLogo

Legal notices

  • Privacy
  • Cookies
  • Responsible disclosure
  • SOC 2/SOC 3
On this page
  • Overview
  • Example: JavaScript and NodeJS
  • Prerequisites
  • What the StackState Agent expects
  • 1 - Import
  • 2 - Core definitions
  • 3 - OpenTelemetry provider and span processor
  • 4 - Root span / parent span
  • 5 - Child span
  • 6 - Close the parent and child span
  • 7 - Flush the data
  • The complete example
  1. StackPacks
  2. Integrations
  3. OpenTelemetry
  4. Manual Instrumentation

Code examples

StackState Self-hosted v5.1.x

PreviousMerging componentsNextServiceNow

Last updated 2 years ago

Overview

Below is a code snippet showing the basics required to send custom instrumentation to StackState.

We will create two components.

  • RDS Database

  • RDS Table

And we want a flowing down from the database to the table. This will allow the up to the database if something is wrong with the table.

This is where your best judgment will come into play; best would be to play around with the parent spans, child spans, etc., and see what result do you receive on StackState.

Example: JavaScript and NodeJS

The following example implements a solution that crates the above-mentioned components.

Prerequisites

To set up a OpenTelemetry manual instrumentations, you need to have:

  • v2.17 (or later)

  • on StackState Agent. If traces aren't enabled on the Agent, OpenTelemetry won't generate any data.

  • The should be installed in StackState.

For NodeJS and Javascript, we aren't explaining the setup to get to this point but rather the code example and libraries that was used.

You should install the following npm libraries using npm or yarn

What the StackState Agent expects

  • trace.perspective.name

  • service.name

  • service.type

  • service.identifier

  • resource.name

In this NodeJs / Javascript example, The protobuf module responsible for handling Protobuf is the following line:

import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';

1 - Import

The first step is to import the libraries that we will be using from OpenTelemetry. (Modules mentioned above)

import * as openTelemetry from '@opentelemetry/api';
import { BasicTracerProvider, BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { OTLPTraceExporter as OTLPTraceProtoExporter } from '@opentelemetry/exporter-trace-otlp-proto';

2 - Core definitions

Now let's define a few values that we will use within the OpenTelemetry API code.

The first one will be where your StackState Trace Agent lives in the following format: http://<host>:<trace port>/open-telemetry

// If you are using a env variable you can access the variable by using process.env.ENV_VARIABLE_NAME
const stsTraceAgentOpenTelemetryEndpoint = "http://localhost:8126/open-telemetry"

The second part is OpenTelemetry tracer definitions. StackState uses these to determine what type of interpretation will be used for your trace. You need to specify the following:

const tracerIdentifier = {
    name: "@opentelemetry/instrumentation-stackstate",
    version: "1.0.0"
}

3 - OpenTelemetry provider and span processor

The next step is to create the basics that OpenTelemetry requires to start a trace provider and something that can process spans

const provider = new BasicTracerProvider();
const otlpTraceExporter = new OTLPTraceProtoExporter({ url: stsTraceAgentOpenTelemetryEndpoint })
const batchSpanProcessor = new BatchSpanProcessor(otlpTraceExporter)
provider.addSpanProcessor(batchSpanProcessor);
provider.register();

// Creating the tracer based on the identifier specified
const tracer = openTelemetry.trace.getTracer(
    tracerIdentifier.name,
    tracerIdentifier.version
);

4 - Root span / parent span

Now let's create the root span, For the root span we are creating a custom RDS Database entry (This database doesn't have to exist you control the span values).

Example Database

  • Database Name: Hello World

  • Database Type: AWS RDS

// Creating a parent span. You need a identifier for this span inside the code
// we will use the value 'RDS Database' but this doesn't matter.
const rdsDatabase = tracer.startSpan('RDS Database', {
    root: true,
});

// Adding attributes to the rds database span
rdsDatabase.setAttribute('trace.perspective.name', 'RDS Database: Hello World');
rdsDatabase.setAttribute('service.name', 'RDS Database');
rdsDatabase.setAttribute('service.type', 'Database');
rdsDatabase.setAttribute('service.identifier', 'rds:database:hello-world');
rdsDatabase.setAttribute('resource.name', 'AWS RDS');

Example of how the parent component will look like if you create the with the above code


5 - Child span

Now let's create a span that will have a relation with the parent span. Thus meaning if anything is wrong with the child span then the error will propagate up into the parent.

Let's use a Table from the non exist Database as a child, this allows us to add a CRITICAL health state on the child if a write operation to this table failed.

Example Table

  • Table Name: Users

  • Database Type: AWS RDS

// Creating a child span. You need a identifier for this span inside the code
// we will use the value 'RDS Table' but this doesn't matter.
const rdsDatabaseTable = tracer.startSpan(
    'RDS Table',
    undefined,
    openTelemetryAPI.trace.setSpan(openTelemetryAPI.context.active(), rdsDatabase)
);

// Adding attributes to the child span
rdsDatabaseTable.setAttribute('trace.perspective.name', 'RDS Table: Users');
rdsDatabaseTable.setAttribute('service.name', 'RDS Table');
rdsDatabaseTable.setAttribute('service.type', 'Database Tables');
rdsDatabaseTable.setAttribute('service.identifier', 'rds:database:table:users');
rdsDatabaseTable.setAttribute('resource.name', 'AWS RDS');

Example of how the child component will look like if you create the with the above code, and the relation to the parent


6 - Close the parent and child span

When you are done with a Span for example you have written into the database table, you need to close those spans.

You need to close the spans in the opposite order in which you opened them For example we started with the database and then the database table, thus we need to close the database table span first then the database span.

NB: If you don't close your spans in the correct order then Trace will still be sent to StackState but, there might be a missing span, thus showing the incomplete data in StackState.

// First we close the table span
rdsDatabaseTable.end();

// Then we close the database span
rdsDatabase.end();

7 - Flush the data

This step isn't always required, but good to know about. Sometimes a script might attempt to end before the actual span was sent away.

A good example of this will be a Lambda execution, StackState will never receive the data as the execution stopped the second the Lambda was done. To get past this you can force flush the Trace Provider to definitely makes sure that StackState received the trace.

If you don't use the following code and don't see your value in StackState this might be the issue.

// NB: Optional Flush
// For example, required in a Lambda environment to force the OLTP HTTP to post before the script ends.
provider.forceFlush().finally(() => {
    console.log('Successfully Force Flushed The OTEL Provider')
});

The complete example

Below is the complete example for JavaScript and NodeJS, including all of the code snippets above.

// Base Imports for OpenTelemetry
import * as openTelemetry from '@opentelemetry/api';
import { BasicTracerProvider, BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { OTLPTraceExporter as OTLPTraceProtoExporter } from '@opentelemetry/exporter-trace-otlp-proto';

// Change this variable to point to your StackState Trace Agent followed by the port and path
// If you are using an env variable you can access the variable by using process.env.ENV_VARIABLE_NAME
const stsTraceAgentOpenTelemetryEndpoint = process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT

// The tracer identifier to allow StackState to identify this instrumentation.
// The name and version below should not be changed
const tracerIdentifier = {
    name: "@opentelemetry/instrumentation-stackstate",
    version: "1.0.0"
}

// Creating a trace provider and exporter
const provider = new BasicTracerProvider();
const otlpTraceExporter = new OTLPTraceProtoExporter({ url: stsTraceAgentOpenTelemetryEndpoint })
const batchSpanProcessor = new BatchSpanProcessor(otlpTraceExporter)
provider.addSpanProcessor(batchSpanProcessor);
provider.register();

// Creating the tracer based on the identifier specified
const tracer = openTelemetry.trace.getTracer(
    tracerIdentifier.name,
    tracerIdentifier.version
);

// Creating a parent span. You need an identifier for this span inside the code
// we will use the value 'RDS Database' but this doesn't matter.
const rdsDatabase = tracer.startSpan('RDS Database', {
    root: true,
});

// Adding attributes to the rds database span
rdsDatabase.setAttribute('trace.perspective.name', 'RDS Database: Hello World');
rdsDatabase.setAttribute('service.name', 'RDS Database');
rdsDatabase.setAttribute('service.type', 'Database');
rdsDatabase.setAttribute('service.identifier', 'rds:database:hello-world');
rdsDatabase.setAttribute('resource.name', 'AWS RDS');


// Creating a child span. You need a identifier for this span inside the code
// we will use the value 'RDS Table' but this doesn't matter.
const rdsDatabaseTable = tracer.startSpan(
    'RDS Table',
    undefined,
    openTelemetry.trace.setSpan(openTelemetry.context.active(), rdsDatabase)
);

// Adding attributes to the child span
rdsDatabaseTable.setAttribute('trace.perspective.name', 'RDS Table: Users');
rdsDatabaseTable.setAttribute('service.name', 'RDS Table');
rdsDatabaseTable.setAttribute('service.type', 'Database Tables');
rdsDatabaseTable.setAttribute('service.identifier', 'rds:database:table:users');
rdsDatabaseTable.setAttribute('resource.name', 'AWS RDS');

// Closing the spans in order
// You need to close the spans in the opposite order in which you opended them
// For example we started with the parent and then the child, thus we need to close the child first
// and then the parent span

// NB: If you don't close your spans in the correct order then then Trace will still be sent to StackState but,
// there might be a missing span, thus showing the incomplete data in StackState.
rdsDatabaseTable.end();
rdsDatabase.end();

// NB: Optional Flush
// For example, required in a Lambda environment to force the OLTP HTTP to post before the script ends.
provider.forceFlush().finally(() => {
    console.log('Success')
});

The StackState Agent expects you to send the :

The most important part to remember is that the StackState Agent only accept the data in a , Our examples below will use this format but if you do attempt to write something from scratch remember that this is a requirement.

🧩
💠
@opentelemetry/api
@opentelemetry/sdk-trace-base
@opentelemetry/exporter-trace-otlp-proto
following keys in every single span
Protobuf Format
relationship between the database and table
health state propagates
StackState Agent
Agent StackPack
Traces enabled
Parent Component after StackState received the trace
Parent Component after StackState received the trace