Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(o11y): Inter-process tracing #8004

Merged
merged 109 commits into from Nov 11, 2022
Merged
Show file tree
Hide file tree
Changes from 107 commits
Commits
Show all changes
109 commits
Select commit Hold shift + click to select a range
b1af20a
Prototype
nikurt Oct 25, 2022
c1aaf21
move the check for is_height_processed forward (#7855)
mzhangmzz Oct 20, 2022
6e685fd
Added peer store information to network page (#7761)
mm-near Oct 20, 2022
34f847e
Do not use flat storage for storage_write (#7885)
mzhangmzz Oct 20, 2022
4c4b92c
feat: limit trie cache by memory consumption (#7749)
jakmeier Oct 21, 2022
485d840
feat: add a transaction mirror binary (#7183)
marcelo-gonzalez Oct 21, 2022
1f4192c
refactor: simplify error handling in main (#7897)
matklad Oct 21, 2022
2b1a8bb
doc: fix typos (#7904)
nujabes403 Oct 23, 2022
445ce05
crypto: Remove unused randomness module (#7907)
mina86 Oct 24, 2022
2f69ec3
doc: update logo (#7905)
al002 Oct 24, 2022
3cd74cd
[Debug UI] Fixed bug in network html when syncing (#7906)
mm-near Oct 24, 2022
90c943b
removed messages of unimplemented EpochSync (#7911)
pompon0 Oct 24, 2022
2667e4d
Prefer implementing `Display` to `From<T>` for `String` (#7914)
mina86 Oct 24, 2022
7698da9
replaced Client struct with async_trait (#7913)
pompon0 Oct 24, 2022
2a31f65
mirror: make it easier to see what happened in debug logs (#7900)
marcelo-gonzalez Oct 24, 2022
9683b6f
chain: remove TxStatusError::InvalidTx variant (#7915)
mina86 Oct 24, 2022
cb50b86
core: add chain Error → TxStatusError conversion (#7912)
mina86 Oct 24, 2022
e2856cf
doc: gas cost parameter chapter (#7918)
jakmeier Oct 25, 2022
b8fefd3
Changelog: include o11y changes (#7889)
nikurt Oct 25, 2022
01d2fde
store: introduce cold storage (#7871)
mina86 Oct 25, 2022
390f52b
moved Network(View)Client(Messages/Responses) to near_client (#7908)
pompon0 Oct 25, 2022
1d283bf
doc: Minor grammar fixes (#7922)
akhi3030 Oct 25, 2022
1e621ce
core: remove unused to_base58 function (#7920)
mina86 Oct 25, 2022
21a82cf
chain: remove unnecessary `mut` from self reference (#7924)
mina86 Oct 25, 2022
4777e77
store: Update cold storage with one column (Block) #7744 (#7745)
posvyatokum Oct 25, 2022
fc07881
[refactor] Refactor client and client actor to move the code for bloc…
mzhangmzz Oct 25, 2022
c45f615
Fix proposals shuffling implementation (#7921)
robin-near Oct 26, 2022
78836a9
[Debug UI] Improve last-blocks debug page (#7902)
robin-near Oct 26, 2022
df22fc7
doc: fix gas section links and other small fixes (#7931)
jakmeier Oct 26, 2022
c58fb7d
moved PeerStore from PeerManagerActor to NetworkState. (#7890)
pompon0 Oct 26, 2022
8b8d366
doc: parameter overview (#7934)
jakmeier Oct 26, 2022
df347d5
o11y: introduce pretty::Slice for formatting slices of arbitrary type…
mina86 Oct 26, 2022
1f075ab
split Network(View)ClientMessage enum into separate actix messages. (…
pompon0 Oct 26, 2022
ec1db8b
store: adding State to cold columns (#7926)
posvyatokum Oct 26, 2022
ec32beb
Change debug page to display error messages in block processing (#7930)
mzhangmzz Oct 26, 2022
480dfec
store: adding StateChanges to cold columns (#7937)
posvyatokum Oct 27, 2022
e5c2661
Changing peer selection process & show connection errors in debug pag…
mm-near Oct 27, 2022
5a80195
Split peer_manager tests into multiple files. (#7941)
pompon0 Oct 27, 2022
4161011
Removed the delay before the initial SyncRoutingTable. (#7940)
pompon0 Oct 27, 2022
156a6fc
Added test for genesis hash (#7909)
mm-near Oct 27, 2022
7c876a7
feat: add a neard amend-genesis command (#7939)
marcelo-gonzalez Oct 27, 2022
2a2f602
store: adding transactions & receipts columns to cold storage (#7943)
posvyatokum Oct 27, 2022
79c1fc1
chain: flatten match pattern to reduce indentation depth (#7945)
mina86 Oct 27, 2022
2629a4d
store: adding final cold columns (#7950)
posvyatokum Oct 27, 2022
b5eba16
docs: move docs about receipts from confluence (#7947)
matklad Oct 27, 2022
31e5909
chore: introduce `--profile prod` (#7923)
matklad Oct 27, 2022
9830540
crypto: move base58 formatting into single struct reducing duplicatio…
mina86 Oct 28, 2022
552a629
logic: improve test coverage and error messages of ed25519_verify (#7…
blasrodri Oct 28, 2022
9a42069
docs: review docs/practices/docs.md (#7957)
nagisa Oct 28, 2022
768bc85
docs: proof-read fast-builds nearcore book page (#7956)
nagisa Oct 28, 2022
6b4dae1
doc: how to add a new parameter (#7952)
jakmeier Oct 28, 2022
c71683a
feat: trie cache configuration (#7578)
jakmeier Oct 28, 2022
7dff269
refactor: cleanup ed25519_verify (#7955)
matklad Oct 31, 2022
501c4db
Speedy-sync - experimental tool for faster syncing (#6914)
mm-near Oct 31, 2022
aa20bc5
fixed compilation error in store_bench (#7963)
mm-near Oct 31, 2022
cc908cd
[DEBUG] move chain processing status to a separate API endpoint (#7962)
mm-near Oct 31, 2022
0a74127
Download records.json when initializing configs (#7946)
nikurt Oct 31, 2022
fc828eb
fix(amend-genesis): remove unwanted changes to the output genesis (#7…
marcelo-gonzalez Oct 31, 2022
b6f2106
feat: add a ping tool (#7541)
marcelo-gonzalez Oct 31, 2022
6d81781
fix(mocknet): Fix config.json (#7968)
nikurt Oct 31, 2022
c507750
[chunks] Move maintenance of ready-to-include chunks out of ShardsMan…
robin-near Oct 31, 2022
b57e88d
feat(o11y): Tracing of work caused by network messages received by Pe…
nikurt Nov 1, 2022
e9956d0
doc: move serialization docs over from confluence (#7951)
matklad Nov 2, 2022
9ea74ac
store: read BlockHeader from hot db when accessing through ColdDB (#7…
mina86 Nov 2, 2022
987b922
doc: estimator quick start and high-level overview (#7981)
jakmeier Nov 2, 2022
4724f6c
feat: estimate `ed25519` base and bytes separately (#7980)
jakmeier Nov 2, 2022
5e68c64
moved is_inbound_allowed to NetworkState (#7975)
pompon0 Nov 2, 2022
e35ba49
moved rayon utils to concurrency module (#7974)
pompon0 Nov 2, 2022
646aca8
docs: move proof docs over from confluence (#7959)
matklad Nov 2, 2022
c469837
refactor: simplify get_epoch_sync_data_hash (#7969)
matklad Nov 2, 2022
44203ff
refactor: move parts API to the epoch manager (#7967)
matklad Nov 2, 2022
1f917bd
store: disable refcount merge operator when opening cold RocksDB (#7954)
mina86 Nov 3, 2022
330d2f2
feat: design for flat storage creation (#7979)
Longarithm Nov 4, 2022
8d05056
fix: use new database version for flat state (#7984)
jakmeier Nov 4, 2022
352e653
docs: clarify that `Db::Receipts` doesn't store _all_ receipts (#7982)
matklad Nov 4, 2022
57facb8
moved fixing local edges to a background task. (#7977)
pompon0 Nov 4, 2022
de87cf6
chore: upgrade rust-version to 1.65.0 (#7993)
jakmeier Nov 4, 2022
1a95831
debug: add assertions to flat state get_ref (#7985)
jakmeier Nov 4, 2022
120f13c
refactor: simplify `split_method_names` in vm Logic (#7998)
matklad Nov 4, 2022
08e1085
feat: trie storage for parallel reads (#7987)
Longarithm Nov 4, 2022
28bc242
Add support for dynamic config and use it for expected shutdown (#7872)
yanganto Nov 5, 2022
c16f943
Fixed broadcasting of AnnounceAccounts (#7973)
pompon0 Nov 5, 2022
9a3c336
Prototype
nikurt Oct 25, 2022
4e799e2
removed messages of unimplemented EpochSync (#7911)
pompon0 Oct 24, 2022
0a2e8c0
replaced Client struct with async_trait (#7913)
pompon0 Oct 24, 2022
7b0da05
Prototype
nikurt Oct 25, 2022
498ac69
removed messages of unimplemented EpochSync (#7911)
pompon0 Oct 24, 2022
f806def
replaced Client struct with async_trait (#7913)
pompon0 Oct 24, 2022
227cfd9
Prototype
nikurt Oct 25, 2022
e829872
removed messages of unimplemented EpochSync (#7911)
pompon0 Oct 24, 2022
e58368d
replaced Client struct with async_trait (#7913)
pompon0 Oct 24, 2022
9838e06
Prototype
nikurt Oct 25, 2022
17dd33c
fix
nikurt Nov 3, 2022
c2ef0ab
fix
nikurt Nov 3, 2022
bf346b3
Use `add_link` to connect traces to the traces from other processes.
nikurt Nov 7, 2022
ad147e4
merge
nikurt Nov 7, 2022
6cfd237
Move to a separate file
nikurt Nov 7, 2022
8b8c376
Merge branch 'master' into nikurt-interprocess
nikurt Nov 7, 2022
81f933a
Use protobuf instead of serializing u128 and u64 to strings.
nikurt Nov 8, 2022
e218664
Merge branch 'master' into nikurt-interprocess
nikurt Nov 8, 2022
f63326d
changelog
nikurt Nov 8, 2022
3daf58c
order
nikurt Nov 8, 2022
4f7912e
Merge branch 'master' into nikurt-interprocess
nikurt Nov 8, 2022
da24895
Move enum to proto
nikurt Nov 9, 2022
739d41f
Merge branch 'master' into nikurt-interprocess
nikurt Nov 9, 2022
3d062e6
Simplify
nikurt Nov 9, 2022
735df61
Merge branch 'master' into nikurt-interprocess
nikurt Nov 9, 2022
0e64b25
Errors
nikurt Nov 11, 2022
978727a
Merge master into nikurt-interprocess
near-bulldozer[bot] Nov 11, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -67,6 +67,8 @@
information: [#7711](https://github.com/near/nearcore/pull/7711).
* Change exporter of tracing information from `opentelemetry-jaeger` to
`opentelemetry-otlp`: [#7563](https://github.com/near/nearcore/pull/7563).
* Tracing of requests across processes:
[#8004](https://github.com/near/nearcore/pull/8004).

## 1.29.0 [2022-08-15]

Expand Down
28 changes: 23 additions & 5 deletions chain/network/src/network_protocol/mod.rs
Expand Up @@ -19,10 +19,14 @@ mod _proto {

pub use _proto::network as proto;

use crate::network_protocol::proto_conv::trace_context::{
extract_span_context, inject_trace_context,
};
use crate::time;
use borsh::{BorshDeserialize as _, BorshSerialize as _};
use near_crypto::PublicKey;
use near_crypto::Signature;
use near_o11y::OpenTelemetrySpanExt;
use near_primitives::block::{Approval, Block, BlockHeader, GenesisId};
use near_primitives::challenge::Challenge;
use near_primitives::hash::CryptoHash;
Expand All @@ -40,7 +44,9 @@ use near_primitives::views::FinalExecutionOutcomeView;
use protobuf::Message as _;
use std::collections::HashSet;
use std::fmt;
use std::fmt::Debug;
use std::sync::Arc;
use tracing::Span;

#[derive(PartialEq, Eq, Clone, Debug, Hash)]
pub struct PeerAddr {
Expand Down Expand Up @@ -281,26 +287,38 @@ pub enum ParsePeerMessageError {
}

impl PeerMessage {
/// Serializes a message in the given encoding.
/// If the encoding is `Proto`, then also attaches current Span's context to the message.
pub(crate) fn serialize(&self, enc: Encoding) -> Vec<u8> {
nikurt marked this conversation as resolved.
Show resolved Hide resolved
match enc {
Encoding::Borsh => borsh_::PeerMessage::from(self).try_to_vec().unwrap(),
Encoding::Proto => proto::PeerMessage::from(self).write_to_bytes().unwrap(),
Encoding::Proto => {
let mut msg = proto::PeerMessage::from(self);
let cx = Span::current().context();
msg.trace_context = inject_trace_context(&cx);
msg.write_to_bytes().unwrap()
}
}
}

pub(crate) fn deserialize(
enc: Encoding,
data: &[u8],
) -> Result<PeerMessage, ParsePeerMessageError> {
let span = tracing::trace_span!(target: "network", "deserialize").entered();
Ok(match enc {
Encoding::Borsh => (&borsh_::PeerMessage::try_from_slice(data)
.map_err(ParsePeerMessageError::BorshDecode)?)
.try_into()
.map_err(ParsePeerMessageError::BorshConv)?,
Encoding::Proto => (&proto::PeerMessage::parse_from_bytes(data)
.map_err(ParsePeerMessageError::ProtoDecode)?)
.try_into()
.map_err(ParsePeerMessageError::ProtoConv)?,
Encoding::Proto => {
let proto_msg: proto::PeerMessage = proto::PeerMessage::parse_from_bytes(data)
.map_err(ParsePeerMessageError::ProtoDecode)?;
if let Ok(extracted_span_context) = extract_span_context(&proto_msg.trace_context) {
span.clone().or_current().add_link(extracted_span_context);
}
(&proto_msg).try_into().map_err(|err| ParsePeerMessageError::ProtoConv(err))?
}
})
}

Expand Down
19 changes: 19 additions & 0 deletions chain/network/src/network_protocol/network.proto
Expand Up @@ -317,6 +317,22 @@ message RoutingSyncV2 {
bytes borsh = 1;
}

// Inter-process tracing information.
message TraceContext {
enum SamplingPriority {
UNKNOWN = 0;
AutoReject = 1;
UserReject = 2;
AutoKeep = 3;
UserKeep = 4;
}
// 16 bytes representing TraceId: https://docs.rs/opentelemetry/latest/opentelemetry/trace/struct.TraceId.html
bytes trace_id = 1;
// 8 bytes representing SpanId: https://docs.rs/opentelemetry/latest/opentelemetry/trace/struct.SpanId.html
bytes span_id = 2;
nikurt marked this conversation as resolved.
Show resolved Hide resolved
SamplingPriority sampling_priority = 3;
}

// PeerMessage is a wrapper of all message types exchanged between NEAR nodes.
// The wire format of a single message M consists of len(M)+4 bytes:
// <len(M)> : 4 bytes : little endian uint32
Expand All @@ -329,6 +345,9 @@ message PeerMessage {
// Deprecated fields.
reserved 9,20,21,22,23,24;

// Inter-process tracing information.
TraceContext trace_context = 26;

oneof message_type {
Handshake handshake = 4;
HandshakeFailure handshake_failure = 5;
Expand Down
1 change: 1 addition & 0 deletions chain/network/src/network_protocol/proto_conv/mod.rs
Expand Up @@ -4,6 +4,7 @@ mod handshake;
mod net;
mod peer_message;
mod time;
pub mod trace_context;
/// Contains protobuf <-> network_protocol conversions.
mod util;

Expand Down
78 changes: 78 additions & 0 deletions chain/network/src/network_protocol/proto_conv/trace_context.rs
@@ -0,0 +1,78 @@
use crate::network_protocol::proto::trace_context::SamplingPriority;
use crate::network_protocol::proto::TraceContext;
use opentelemetry::trace::{SpanContext, SpanId, TraceContextExt, TraceFlags, TraceId, TraceState};
use opentelemetry::Context;
use protobuf::{EnumOrUnknown, MessageField};

/// Lowest available value.
/// 0x01 is reserved for `SAMPLED`: https://docs.rs/opentelemetry/latest/opentelemetry/trace/struct.TraceFlags.html#associatedconstant.SAMPLED
const TRACE_FLAG_DEFERRED: TraceFlags = TraceFlags::new(0x02);

#[derive(Debug)]
pub(crate) enum ExtractError {
// Malformed or invalid TraceId.
TraceId,
// Malformed or invalid SpanId.
SpanId,
// Missing trace_id or span_id.
Empty,
nikurt marked this conversation as resolved.
Show resolved Hide resolved
}

/// Extracts a `SpanContext` from a potentially empty `TraceContext`.
///
nikurt marked this conversation as resolved.
Show resolved Hide resolved
pub(crate) fn extract_span_context(
trace_context: &MessageField<TraceContext>,
) -> Result<SpanContext, ExtractError> {
if trace_context.is_some() {
let trace_id = extract_trace_id(&trace_context.trace_id)?;
// If we have a trace_id but can't get the parent span, we default it to invalid instead of completely erroring
// out so that the rest of the spans aren't completely lost.
let span_id = extract_span_id(&trace_context.span_id).unwrap_or(SpanId::INVALID);
let sampled = match trace_context.sampling_priority.enum_value() {
Ok(SamplingPriority::UserReject) | Ok(SamplingPriority::AutoReject) => {
TraceFlags::default()
}
Ok(SamplingPriority::UserKeep) | Ok(SamplingPriority::AutoKeep) => TraceFlags::SAMPLED,
// Treat the sampling as DEFERRED instead of erring on extracting the span context
Ok(SamplingPriority::UNKNOWN) | Err(_) => TRACE_FLAG_DEFERRED,
};
let trace_state = TraceState::default();
Ok(SpanContext::new(trace_id, span_id, sampled, true, trace_state))
} else {
Err(ExtractError::Empty)
}
}

/// Populates `TraceContext` representing the current span.
/// Returns `None` if no current span is available.
pub(crate) fn inject_trace_context(cx: &Context) -> MessageField<TraceContext> {
let span = cx.span();
let span_context = span.span_context();
if span_context.is_valid() {
let mut trace_context = TraceContext::new();

// Uses `u128::to_be_bytes()` internally.
trace_context.trace_id = span_context.trace_id().to_bytes().to_vec();
// Uses `u64::to_be_bytes()` internally.
trace_context.span_id = span_context.span_id().to_bytes().to_vec();

if span_context.trace_flags() & TRACE_FLAG_DEFERRED != TRACE_FLAG_DEFERRED {
let sampling_priority = if span_context.is_sampled() {
SamplingPriority::AutoKeep
} else {
SamplingPriority::AutoReject
};
trace_context.sampling_priority = EnumOrUnknown::new(sampling_priority);
}
MessageField::some(trace_context)
} else {
MessageField::none()
}
}
fn extract_trace_id(trace_id: &[u8]) -> Result<TraceId, ExtractError> {
Ok(TraceId::from_bytes(trace_id.try_into().map_err(|_| ExtractError::TraceId)?))
}

fn extract_span_id(span_id: &[u8]) -> Result<SpanId, ExtractError> {
Ok(SpanId::from_bytes(span_id.try_into().map_err(|_| ExtractError::SpanId)?))
}
3 changes: 1 addition & 2 deletions chain/network/src/peer/peer_actor.rs
Expand Up @@ -261,7 +261,6 @@ impl PeerActor {
}

fn parse_message(&mut self, msg: &[u8]) -> Result<PeerMessage, ParsePeerMessageError> {
let _span = tracing::trace_span!(target: "network", "parse_message").entered();
if let Some(e) = self.encoding() {
return PeerMessage::deserialize(e, msg);
}
Expand Down Expand Up @@ -1206,7 +1205,7 @@ impl actix::Handler<stream::Frame> for PeerActor {
type Result = ();
#[perf]
fn handle(&mut self, stream::Frame(msg): stream::Frame, ctx: &mut Self::Context) {
let _span = tracing::trace_span!(
let _span = tracing::debug_span!(
target: "network",
"handle",
handler = "bytes",
Expand Down
7 changes: 5 additions & 2 deletions chain/network/src/peer_manager/peer_manager_actor.rs
Expand Up @@ -24,7 +24,10 @@ use crate::types::{
use actix::fut::future::wrap_future;
use actix::{Actor, AsyncContext, Context, Handler, Running};
use anyhow::Context as _;
use near_o11y::{handler_trace_span, OpenTelemetrySpanExt, WithSpanContext, WithSpanContextExt};
use near_o11y::{
handler_debug_span, handler_trace_span, OpenTelemetrySpanExt, WithSpanContext,
WithSpanContextExt,
};
use near_performance_metrics_macros::perf;
use near_primitives::block::GenesisId;
use near_primitives::network::{AnnounceAccount, PeerId};
Expand Down Expand Up @@ -1068,7 +1071,7 @@ impl Handler<WithSpanContext<PeerManagerMessageRequest>> for PeerManagerActor {
ctx: &mut Self::Context,
) -> Self::Result {
let msg_type: &str = (&msg.msg).into();
let (_span, msg) = handler_trace_span!(target: "network", msg, msg_type);
let (_span, msg) = handler_debug_span!(target: "network", msg, msg_type);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the intent behind this change is to allow usable tracing with a debug level only?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, to allow tracing across nodes at both debug and trace levels.

let _timer =
metrics::PEER_MANAGER_MESSAGES_TIME.with_label_values(&[(&msg).into()]).start_timer();
self.handle_peer_manager_message(msg, ctx)
Expand Down
11 changes: 8 additions & 3 deletions core/o11y/src/lib.rs
Expand Up @@ -258,13 +258,18 @@ where
let (filter, handle) = reload::Layer::<LevelFilter, S>::new(filter);

let mut resource = vec![
KeyValue::new(SERVICE_NAME, "neard"),
KeyValue::new("chain_id", chain_id),
KeyValue::new("node_id", node_public_key.to_string()),
];
if let Some(account_id) = account_id {
// Prefer account name as the node name.
// Fallback to a node public key if a validator key is unavailable.
let service_name = if let Some(account_id) = account_id {
resource.push(KeyValue::new("account_id", account_id.to_string()));
}
format!("neard:{}", account_id)
} else {
format!("neard:{}", node_public_key)
};
resource.push(KeyValue::new(SERVICE_NAME, service_name));

let tracer = opentelemetry_otlp::new_pipeline()
.tracing()
Expand Down