Skip to main content

couchbase_core/memdx/
error.rs

1/*
2 *
3 *  * Copyright (c) 2025 Couchbase, Inc.
4 *  *
5 *  * Licensed under the Apache License, Version 2.0 (the "License");
6 *  * you may not use this file except in compliance with the License.
7 *  * You may obtain a copy of the License at
8 *  *
9 *  *    http://www.apache.org/licenses/LICENSE-2.0
10 *  *
11 *  * Unless required by applicable law or agreed to in writing, software
12 *  * distributed under the License is distributed on an "AS IS" BASIS,
13 *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  * See the License for the specific language governing permissions and
15 *  * limitations under the License.
16 *
17 */
18
19use serde::Deserialize;
20use std::error::Error as StdError;
21use std::fmt::{Display, Formatter, Pointer};
22use std::io;
23
24use crate::memdx::opcode::OpCode;
25use crate::memdx::status::Status;
26use crate::tracingcomponent::MetricsName;
27
28pub type Result<T> = std::result::Result<T, Error>;
29
30#[derive(Debug, PartialEq)]
31pub struct Error {
32    inner: ErrorImpl,
33}
34
35impl Error {
36    pub(crate) fn new_protocol_error(msg: impl Into<String>) -> Self {
37        Self {
38            inner: ErrorImpl {
39                kind: Box::new(ErrorKind::Protocol { msg: msg.into() }),
40                source: None,
41            },
42        }
43    }
44
45    pub(crate) fn new_decompression_error() -> Self {
46        Self {
47            inner: ErrorImpl {
48                kind: Box::new(ErrorKind::Decompression {}),
49                source: None,
50            },
51        }
52    }
53
54    pub(crate) fn new_message_error(msg: impl Into<String>) -> Self {
55        Self {
56            inner: ErrorImpl {
57                kind: Box::new(ErrorKind::Message(msg.into())),
58                source: None,
59            },
60        }
61    }
62
63    pub(crate) fn new_cancelled_error(cancellation_kind: CancellationErrorKind) -> Self {
64        Self {
65            inner: ErrorImpl {
66                kind: Box::new(ErrorKind::Cancelled(cancellation_kind)),
67                source: None,
68            },
69        }
70    }
71
72    pub(crate) fn new_invalid_argument_error(
73        msg: impl Into<String>,
74        arg: impl Into<Option<String>>,
75    ) -> Self {
76        Self {
77            inner: ErrorImpl {
78                kind: Box::new(ErrorKind::InvalidArgument {
79                    msg: msg.into(),
80                    arg: arg.into(),
81                }),
82                source: None,
83            },
84        }
85    }
86
87    pub(crate) fn new_connection_failed_error(
88        reason: impl Into<String>,
89        source: Box<io::Error>,
90    ) -> Self {
91        Self {
92            inner: ErrorImpl {
93                kind: Box::new(ErrorKind::ConnectionFailed { msg: reason.into() }),
94                source: Some(source),
95            },
96        }
97    }
98
99    pub(crate) fn new_dispatch_error(opaque: u32, op_code: OpCode, source: Box<Error>) -> Self {
100        Self {
101            inner: ErrorImpl {
102                kind: Box::new(ErrorKind::Dispatch { opaque, op_code }),
103                source: Some(source),
104            },
105        }
106    }
107
108    pub(crate) fn new_close_error(msg: String, source: Box<Error>) -> Self {
109        Self {
110            inner: ErrorImpl {
111                kind: Box::new(ErrorKind::Close { msg }),
112                source: Some(source),
113            },
114        }
115    }
116
117    pub fn has_server_config(&self) -> Option<&Vec<u8>> {
118        if let ErrorKind::Server(ServerError { config, .. }) = self.inner.kind.as_ref() {
119            config.as_ref()
120        } else {
121            None
122        }
123    }
124
125    pub fn has_server_error_context(&self) -> Option<&Vec<u8>> {
126        if let ErrorKind::Server(ServerError { context, .. }) = self.inner.kind.as_ref() {
127            context.as_ref()
128        } else if let ErrorKind::Resource(ResourceError { cause, .. }) = self.inner.kind.as_ref() {
129            cause.context.as_ref()
130        } else {
131            None
132        }
133    }
134
135    pub fn has_opaque(&self) -> Option<u32> {
136        let inner_kind = self.inner.kind.as_ref();
137        if let ErrorKind::Server(ServerError { opaque, .. }) = inner_kind {
138            Some(*opaque)
139        } else if let ErrorKind::Resource(e) = inner_kind {
140            Some(e.cause.opaque)
141        } else if let ErrorKind::Dispatch { opaque, .. } = inner_kind {
142            Some(*opaque)
143        } else {
144            None
145        }
146    }
147
148    pub fn is_cancellation_error(&self) -> bool {
149        matches!(self.inner.kind.as_ref(), ErrorKind::Cancelled { .. })
150    }
151
152    pub fn is_dispatch_error(&self) -> bool {
153        matches!(self.inner.kind.as_ref(), ErrorKind::Dispatch { .. })
154    }
155
156    pub fn is_server_error_kind(&self, kind: ServerErrorKind) -> bool {
157        match self.inner.kind.as_ref() {
158            ErrorKind::Server(e) => e.kind == kind,
159            ErrorKind::Resource(e) => e.cause.kind == kind,
160            _ => false,
161        }
162    }
163
164    pub fn kind(&self) -> &ErrorKind {
165        &self.inner.kind
166    }
167
168    pub(crate) fn with<C: Into<Source>>(mut self, source: C) -> Error {
169        self.inner.source = Some(source.into());
170        self
171    }
172}
173
174type Source = Box<dyn StdError + Send + Sync>;
175
176#[derive(Debug)]
177struct ErrorImpl {
178    kind: Box<ErrorKind>,
179    source: Option<Source>,
180}
181
182impl PartialEq for ErrorImpl {
183    fn eq(&self, other: &Self) -> bool {
184        self.kind == other.kind
185    }
186}
187
188impl Display for Error {
189    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
190        write!(f, "{}", self.inner.kind)?;
191        if let Some(source) = &self.inner.source {
192            write!(f, ": {source}")?;
193        }
194        Ok(())
195    }
196}
197
198impl StdError for Error {
199    fn source(&self) -> Option<&(dyn StdError + 'static)> {
200        self.inner
201            .source
202            .as_ref()
203            .map(|cause| &**cause as &(dyn StdError + 'static))
204    }
205}
206
207#[derive(Debug, Clone, PartialEq)]
208#[non_exhaustive]
209pub enum ErrorKind {
210    Server(ServerError),
211    Resource(ResourceError),
212    #[non_exhaustive]
213    Dispatch {
214        opaque: u32,
215        op_code: OpCode,
216    },
217    #[non_exhaustive]
218    Close {
219        msg: String,
220    },
221    #[non_exhaustive]
222    Protocol {
223        msg: String,
224    },
225    Cancelled(CancellationErrorKind),
226    #[non_exhaustive]
227    ConnectionFailed {
228        msg: String,
229    },
230    Io,
231    #[non_exhaustive]
232    InvalidArgument {
233        msg: String,
234        arg: Option<String>,
235    },
236    Decompression,
237    Message(String),
238}
239
240impl Display for ErrorKind {
241    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
242        match self {
243            ErrorKind::Server(e) => write!(f, "{e}"),
244            ErrorKind::Resource(e) => write!(f, "{e}"),
245            ErrorKind::Dispatch { opaque, op_code } => {
246                write!(f, "dispatch failed: opaque: {opaque}, op_code: {op_code}")
247            }
248            ErrorKind::Close { msg } => {
249                write!(f, "close error {msg}")
250            }
251            ErrorKind::Protocol { msg } => {
252                write!(f, "{msg}")
253            }
254            ErrorKind::Cancelled(kind) => {
255                write!(f, "request cancelled: {kind}")
256            }
257            ErrorKind::ConnectionFailed { msg } => {
258                write!(f, "connection failed {msg}")
259            }
260            ErrorKind::Io => {
261                write!(f, "connection error")
262            }
263            ErrorKind::InvalidArgument { msg, arg } => {
264                let base_msg = format!("invalid argument: {msg}");
265                if let Some(arg) = arg {
266                    write!(f, "{base_msg}, arg: {arg}")
267                } else {
268                    write!(f, "{base_msg}")
269                }
270            }
271            ErrorKind::Decompression => write!(f, "decompression error"),
272            ErrorKind::Message(msg) => write!(f, "{msg}"),
273        }
274    }
275}
276
277#[derive(Clone, Debug, PartialEq, Eq)]
278#[non_exhaustive]
279pub struct ResourceError {
280    cause: ServerError,
281    scope_name: String,
282    collection_name: String,
283}
284
285impl StdError for ResourceError {}
286
287impl ResourceError {
288    pub(crate) fn new(
289        cause: ServerError,
290        scope_name: impl Into<String>,
291        collection_name: impl Into<String>,
292    ) -> Self {
293        Self {
294            cause,
295            scope_name: scope_name.into(),
296            collection_name: collection_name.into(),
297        }
298    }
299
300    pub fn cause(&self) -> &ServerError {
301        &self.cause
302    }
303
304    pub fn scope_name(&self) -> &str {
305        &self.scope_name
306    }
307
308    pub fn collection_name(&self) -> &str {
309        &self.collection_name
310    }
311}
312
313impl Display for ResourceError {
314    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
315        write!(
316            f,
317            "Resource error: {}, scope: {}, collection: {}",
318            self.cause, self.scope_name, self.collection_name
319        )
320    }
321}
322
323#[derive(Clone, Debug, PartialEq, Eq)]
324#[non_exhaustive]
325pub struct ServerError {
326    kind: ServerErrorKind,
327    config: Option<Vec<u8>>,
328    context: Option<Vec<u8>>,
329    op_code: OpCode,
330    status: Status,
331    opaque: u32,
332}
333
334impl StdError for ServerError {}
335
336impl Display for ServerError {
337    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
338        let mut base_msg = format!(
339            "Server error: {}, status: 0x{:02x}, opcode: {}, opaque: {}",
340            self.kind,
341            u16::from(self.status),
342            self.op_code,
343            self.opaque
344        );
345
346        if let Some(context) = &self.context {
347            if let Some(parsed) = Self::parse_context(context) {
348                base_msg.push_str(" (");
349                if let Some(text) = &parsed.text {
350                    base_msg.push_str(&format!("context: {text}, "));
351                }
352
353                if let Some(error_ref) = &parsed.error_ref {
354                    base_msg.push_str(&format!("error_ref: {error_ref}"));
355                }
356                base_msg.push(')');
357            }
358        }
359
360        write!(f, "{base_msg}")
361    }
362}
363
364impl ServerError {
365    pub(crate) fn new(kind: ServerErrorKind, op_code: OpCode, status: Status, opaque: u32) -> Self {
366        Self {
367            kind,
368            config: None,
369            context: None,
370            op_code,
371            status,
372            opaque,
373        }
374    }
375
376    pub(crate) fn with_context(mut self, context: Vec<u8>) -> Self {
377        self.context = Some(context);
378        self
379    }
380
381    pub(crate) fn with_config(mut self, config: Vec<u8>) -> Self {
382        self.config = Some(config);
383        self
384    }
385
386    pub fn kind(&self) -> &ServerErrorKind {
387        &self.kind
388    }
389
390    pub fn config(&self) -> Option<&Vec<u8>> {
391        self.config.as_ref()
392    }
393
394    pub fn context(&self) -> Option<&Vec<u8>> {
395        self.context.as_ref()
396    }
397
398    pub fn op_code(&self) -> OpCode {
399        self.op_code
400    }
401
402    pub fn status(&self) -> Status {
403        self.status
404    }
405
406    pub fn opaque(&self) -> u32 {
407        self.opaque
408    }
409
410    pub fn parse_context(context: &[u8]) -> Option<ServerErrorContext> {
411        if context.is_empty() {
412            return None;
413        }
414
415        let context_json: ServerErrorContextJson = match serde_json::from_slice(context) {
416            Ok(c) => c,
417            Err(_) => {
418                return None;
419            }
420        };
421
422        let text = context_json.error.context;
423
424        let error_ref = context_json.error.error_ref;
425
426        let manifest_rev = context_json
427            .manifest_rev
428            .map(|manifest_rev| u64::from_str_radix(&manifest_rev, 16).unwrap_or_default());
429
430        Some(ServerErrorContext {
431            text,
432            error_ref,
433            manifest_rev,
434        })
435    }
436}
437
438#[derive(Clone, Debug, PartialEq, Eq)]
439#[non_exhaustive]
440pub struct ServerErrorContext {
441    pub text: Option<String>,
442    pub error_ref: Option<String>,
443    pub manifest_rev: Option<u64>,
444}
445
446#[derive(Clone, Debug, Eq, Hash, PartialEq)]
447#[non_exhaustive]
448pub enum ServerErrorKind {
449    KeyNotFound,
450    KeyExists,
451    TooBig,
452    NotStored,
453    BadDelta,
454    NotMyVbucket,
455    NoBucket,
456    Locked,
457    NotLocked,
458    Auth { msg: String },
459    RangeError,
460    Access,
461    RateLimitedNetworkIngress,
462    RateLimitedNetworkEgress,
463    RateLimitedMaxConnections,
464    RateLimitedMaxCommands,
465    RateLimitedScopeSizeLimitExceeded,
466    UnknownCommand,
467    NotSupported,
468    InternalError,
469    Busy,
470    TmpFail,
471    UnknownCollectionID,
472    UnknownScopeName,
473    UnknownCollectionName,
474    DurabilityInvalid,
475    DurabilityImpossible,
476    SyncWriteInProgress,
477    SyncWriteAmbiguous,
478    SyncWriteRecommitInProgress,
479    RangeScanCancelled,
480    RangeScanVBUUIDNotEqual,
481    InvalidArgs,
482    AuthStale,
483
484    ConfigNotSet,
485    UnknownBucketName,
486    CasMismatch,
487
488    Subdoc { error: SubdocError },
489
490    UnknownStatus { status: Status },
491}
492
493impl Display for ServerErrorKind {
494    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
495        match self {
496            ServerErrorKind::NotMyVbucket => write!(f, "not my vbucket"),
497            ServerErrorKind::KeyExists => write!(f, "key exists"),
498            ServerErrorKind::NotStored => write!(f, "key not stored"),
499            ServerErrorKind::KeyNotFound => write!(f, "key not found"),
500            ServerErrorKind::TmpFail => write!(f, "temporary failure"),
501            ServerErrorKind::CasMismatch => write!(f, "cas mismatch"),
502            ServerErrorKind::Locked => write!(f, "locked"),
503            ServerErrorKind::NotLocked => write!(f, "not locked"),
504            ServerErrorKind::TooBig => write!(f, "too big"),
505            ServerErrorKind::UnknownCollectionID => write!(f, "unknown collection id"),
506            ServerErrorKind::NoBucket => write!(f, "no bucket selected"),
507            ServerErrorKind::UnknownBucketName => write!(f, "unknown bucket name"),
508            ServerErrorKind::Access => write!(f, "access error"),
509            ServerErrorKind::Auth { msg } => write!(f, "auth error {msg}"),
510            ServerErrorKind::ConfigNotSet => write!(f, "config not set"),
511            ServerErrorKind::UnknownScopeName => write!(f, "scope name unknown"),
512            ServerErrorKind::UnknownCollectionName => write!(f, "collection name unknown"),
513            ServerErrorKind::Subdoc { error } => write!(f, "{error}"),
514            ServerErrorKind::UnknownStatus { status } => {
515                write!(f, "server status unexpected for operation: {status}")
516            }
517            ServerErrorKind::BadDelta => write!(f, "bad delta"),
518            ServerErrorKind::UnknownCommand => write!(f, "unknown command"),
519            ServerErrorKind::RangeError => write!(f, "range error"),
520            ServerErrorKind::RateLimitedNetworkIngress => {
521                write!(f, "rate limited: network ingress")
522            }
523            ServerErrorKind::RateLimitedNetworkEgress => write!(f, "rate limited: network egress"),
524            ServerErrorKind::RateLimitedMaxConnections => {
525                write!(f, "rate limited: max connections")
526            }
527            ServerErrorKind::RateLimitedMaxCommands => write!(f, "rate limited: max commands"),
528            ServerErrorKind::RateLimitedScopeSizeLimitExceeded => {
529                write!(f, "rate limited: scope size limit exceeded")
530            }
531            ServerErrorKind::NotSupported => write!(f, "not supported"),
532            ServerErrorKind::InternalError => write!(f, "internal error"),
533            ServerErrorKind::Busy => write!(f, "busy"),
534            ServerErrorKind::DurabilityInvalid => write!(f, "durability invalid"),
535            ServerErrorKind::DurabilityImpossible => write!(f, "durability impossible"),
536            ServerErrorKind::SyncWriteInProgress => write!(f, "sync write in progress"),
537            ServerErrorKind::SyncWriteAmbiguous => write!(f, "sync write ambiguous"),
538            ServerErrorKind::SyncWriteRecommitInProgress => {
539                write!(f, "sync write recommit in progress")
540            }
541            ServerErrorKind::RangeScanCancelled => write!(f, "range scan cancelled"),
542            ServerErrorKind::RangeScanVBUUIDNotEqual => write!(f, "range scan vbUUID not equal"),
543            ServerErrorKind::InvalidArgs => write!(f, "invalid args"),
544            ServerErrorKind::AuthStale => write!(f, "auth stale"),
545        }
546    }
547}
548
549#[derive(Clone, Debug, PartialEq, Eq, Hash)]
550#[non_exhaustive]
551pub struct SubdocError {
552    kind: SubdocErrorKind,
553    op_index: Option<u8>,
554}
555
556impl StdError for SubdocError {}
557
558impl SubdocError {
559    pub(crate) fn new(kind: SubdocErrorKind, op_index: impl Into<Option<u8>>) -> Self {
560        Self {
561            kind,
562            op_index: op_index.into(),
563        }
564    }
565
566    pub fn is_error_kind(&self, kind: SubdocErrorKind) -> bool {
567        self.kind == kind
568    }
569
570    pub fn kind(&self) -> &SubdocErrorKind {
571        &self.kind
572    }
573
574    pub fn op_index(&self) -> Option<u8> {
575        self.op_index
576    }
577}
578
579impl Display for SubdocError {
580    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
581        if let Some(op_index) = self.op_index {
582            let base_msg = format!("Subdoc error: {}, op_index: {}", self.kind, op_index);
583            write!(f, "{base_msg}")
584        } else {
585            let base_msg = format!("Subdoc error: {}", self.kind);
586            write!(f, "{base_msg}")
587        }
588    }
589}
590
591#[derive(Clone, Debug, Eq, Hash, PartialEq)]
592#[non_exhaustive]
593pub enum SubdocErrorKind {
594    PathNotFound,
595    PathMismatch,
596    PathInvalid,
597    PathTooBig,
598    DocTooDeep,
599    CantInsert,
600    NotJSON,
601    BadRange,
602    BadDelta,
603    PathExists,
604    ValueTooDeep,
605    InvalidCombo,
606    XattrInvalidFlagCombo,
607    XattrInvalidKeyCombo,
608    XattrUnknownMacro,
609    XattrUnknownVAttr,
610    XattrCannotModifyVAttr,
611    InvalidXattrOrder,
612    XattrUnknownVattrMacro,
613    CanOnlyReviveDeletedDocuments,
614    DeletedDocumentCantHaveValue,
615    UnknownStatus { status: Status },
616}
617
618impl Display for SubdocErrorKind {
619    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
620        match self {
621            SubdocErrorKind::PathNotFound => write!(f, "subdoc path not found"),
622            SubdocErrorKind::PathMismatch => write!(f, "subdoc path mismatch"),
623            SubdocErrorKind::PathInvalid => write!(f, "subdoc path invalid"),
624            SubdocErrorKind::PathTooBig => write!(f, "subdoc path too big"),
625            SubdocErrorKind::DocTooDeep => write!(f, "subdoc doc too deep"),
626            SubdocErrorKind::CantInsert => write!(f, "subdoc can't insert"),
627            SubdocErrorKind::NotJSON => write!(f, "subdoc not JSON"),
628            SubdocErrorKind::BadRange => write!(f, "subdoc bad range"),
629            SubdocErrorKind::BadDelta => write!(f, "subdoc bad delta"),
630            SubdocErrorKind::PathExists => write!(f, "subdoc path exists"),
631            SubdocErrorKind::ValueTooDeep => write!(f, "subdoc value too deep"),
632            SubdocErrorKind::InvalidCombo => write!(f, "subdoc invalid combo"),
633            SubdocErrorKind::XattrInvalidFlagCombo => write!(f, "subdoc xattr invalid flag combo"),
634            SubdocErrorKind::XattrInvalidKeyCombo => write!(f, "subdoc xattr invalid key combo"),
635            SubdocErrorKind::XattrUnknownMacro => write!(f, "subdoc xattr unknown macro"),
636            SubdocErrorKind::XattrUnknownVAttr => write!(f, "subdoc xattr unknown vattr"),
637            SubdocErrorKind::XattrCannotModifyVAttr => {
638                write!(f, "subdoc xattr cannot modify vattr")
639            }
640            SubdocErrorKind::InvalidXattrOrder => write!(f, "subdoc invalid xattr order"),
641            SubdocErrorKind::XattrUnknownVattrMacro => {
642                write!(f, "subdoc xattr unknown vattr macro")
643            }
644            SubdocErrorKind::CanOnlyReviveDeletedDocuments => {
645                write!(f, "subdoc can only revive deleted documents")
646            }
647            SubdocErrorKind::DeletedDocumentCantHaveValue => {
648                write!(f, "subdoc deleted document can't have value")
649            }
650            SubdocErrorKind::UnknownStatus { status } => write!(
651                f,
652                "subdoc unknown status unexpected for operation: {status}"
653            ),
654        }
655    }
656}
657
658#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
659#[non_exhaustive]
660pub enum CancellationErrorKind {
661    Timeout,
662    RequestCancelled,
663    ClosedInFlight,
664}
665
666impl Display for CancellationErrorKind {
667    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
668        let txt = match self {
669            CancellationErrorKind::Timeout => "Timeout",
670            CancellationErrorKind::RequestCancelled => "Request cancelled",
671            CancellationErrorKind::ClosedInFlight => "Closed in flight",
672        };
673
674        write!(f, "{txt}")
675    }
676}
677
678impl<E> From<E> for Error
679where
680    ErrorKind: From<E>,
681{
682    fn from(err: E) -> Self {
683        Self {
684            inner: ErrorImpl {
685                kind: Box::new(ErrorKind::from(err)),
686                source: None,
687            },
688        }
689    }
690}
691
692impl From<ServerError> for Error {
693    fn from(value: ServerError) -> Self {
694        Self {
695            inner: ErrorImpl {
696                kind: Box::new(ErrorKind::Server(value)),
697                source: None,
698            },
699        }
700    }
701}
702
703impl From<ResourceError> for Error {
704    fn from(value: ResourceError) -> Self {
705        Self {
706            inner: ErrorImpl {
707                kind: Box::new(ErrorKind::Resource(value)),
708                source: None,
709            },
710        }
711    }
712}
713
714impl From<io::Error> for Error {
715    fn from(value: io::Error) -> Self {
716        Self {
717            inner: ErrorImpl {
718                kind: Box::new(ErrorKind::Io),
719                source: Some(Box::new(value)),
720            },
721        }
722    }
723}
724
725#[derive(Deserialize, Clone, Debug, PartialEq, Eq, Default)]
726struct ServerErrorContextJsonContext {
727    #[serde(alias = "context")]
728    context: Option<String>,
729    #[serde(alias = "ref")]
730    pub error_ref: Option<String>,
731}
732
733#[derive(Deserialize, Clone, Debug, PartialEq, Eq)]
734struct ServerErrorContextJson {
735    #[serde(alias = "error", default)]
736    error: ServerErrorContextJsonContext,
737    #[serde(alias = "manifest_uid")]
738    pub manifest_rev: Option<String>,
739}
740
741impl MetricsName for Error {
742    fn metrics_name(&self) -> &'static str {
743        self.kind().metrics_name()
744    }
745}
746
747impl MetricsName for ErrorKind {
748    fn metrics_name(&self) -> &'static str {
749        match self {
750            ErrorKind::Server(err) => err.kind().metrics_name(),
751            ErrorKind::Resource(err) => err.cause().kind().metrics_name(),
752            ErrorKind::Dispatch { .. } => "memdx.Dispatch",
753            ErrorKind::Close { .. } => "memdx.Close",
754            ErrorKind::Protocol { .. } => "memdx.Protocol",
755            ErrorKind::Cancelled(_) => "memdx.Cancelled",
756            ErrorKind::ConnectionFailed { .. } => "memdx.ConnectionFailed",
757            ErrorKind::Io => "memdx.Io",
758            ErrorKind::InvalidArgument { .. } => "memdx.InvalidArgument",
759            ErrorKind::Decompression => "memdx.Decompression",
760            ErrorKind::Message(_) => "memdx._OTHER",
761        }
762    }
763}
764
765impl MetricsName for ServerErrorKind {
766    fn metrics_name(&self) -> &'static str {
767        match self {
768            ServerErrorKind::KeyNotFound => "memdx.KeyNotFound",
769            ServerErrorKind::KeyExists => "memdx.KeyExists",
770            ServerErrorKind::TooBig => "memdx.TooBig",
771            ServerErrorKind::NotStored => "memdx.NotStored",
772            ServerErrorKind::BadDelta => "memdx.BadDelta",
773            ServerErrorKind::NotMyVbucket => "memdx.NotMyVbucket",
774            ServerErrorKind::NoBucket => "memdx.NoBucket",
775            ServerErrorKind::Locked => "memdx.Locked",
776            ServerErrorKind::NotLocked => "memdx.NotLocked",
777            ServerErrorKind::Auth { .. } => "memdx.Auth",
778            ServerErrorKind::RangeError => "memdx.RangeError",
779            ServerErrorKind::Access => "memdx.Access",
780            ServerErrorKind::RateLimitedNetworkIngress => "memdx.RateLimitedNetworkIngress",
781            ServerErrorKind::RateLimitedNetworkEgress => "memdx.RateLimitedNetworkEgress",
782            ServerErrorKind::RateLimitedMaxConnections => "memdx.RateLimitedMaxConnections",
783            ServerErrorKind::RateLimitedMaxCommands => "memdx.RateLimitedMaxCommands",
784            ServerErrorKind::RateLimitedScopeSizeLimitExceeded => {
785                "memdx.RateLimitedScopeSizeLimitExceeded"
786            }
787            ServerErrorKind::UnknownCommand => "memdx.UnknownCommand",
788            ServerErrorKind::NotSupported => "memdx.NotSupported",
789            ServerErrorKind::InternalError => "memdx.InternalError",
790            ServerErrorKind::Busy => "memdx.Busy",
791            ServerErrorKind::TmpFail => "memdx.TmpFail",
792            ServerErrorKind::UnknownCollectionID => "memdx.UnknownCollectionID",
793            ServerErrorKind::UnknownScopeName => "memdx.UnknownScopeName",
794            ServerErrorKind::UnknownCollectionName => "memdx.UnknownCollectionName",
795            ServerErrorKind::DurabilityInvalid => "memdx.DurabilityInvalid",
796            ServerErrorKind::DurabilityImpossible => "memdx.DurabilityImpossible",
797            ServerErrorKind::SyncWriteInProgress => "memdx.SyncWriteInProgress",
798            ServerErrorKind::SyncWriteAmbiguous => "memdx.SyncWriteAmbiguous",
799            ServerErrorKind::SyncWriteRecommitInProgress => "memdx.SyncWriteRecommitInProgress",
800            ServerErrorKind::RangeScanCancelled => "memdx.RangeScanCancelled",
801            ServerErrorKind::RangeScanVBUUIDNotEqual => "memdx.RangeScanVBUUIDNotEqual",
802            ServerErrorKind::InvalidArgs => "memdx.InvalidArgs",
803            ServerErrorKind::AuthStale => "memdx.AuthStale",
804            ServerErrorKind::ConfigNotSet => "memdx.ConfigNotSet",
805            ServerErrorKind::UnknownBucketName => "memdx.UnknownBucketName",
806            ServerErrorKind::CasMismatch => "memdx.CasMismatch",
807            ServerErrorKind::Subdoc { error } => error.kind().metrics_name(),
808            ServerErrorKind::UnknownStatus { .. } => "memdx._OTHER",
809        }
810    }
811}
812
813impl MetricsName for SubdocErrorKind {
814    fn metrics_name(&self) -> &'static str {
815        match self {
816            SubdocErrorKind::PathNotFound => "memdx.subdoc.PathNotFound",
817            SubdocErrorKind::PathMismatch => "memdx.subdoc.PathMismatch",
818            SubdocErrorKind::PathInvalid => "memdx.subdoc.PathInvalid",
819            SubdocErrorKind::PathTooBig => "memdx.subdoc.PathTooBig",
820            SubdocErrorKind::DocTooDeep => "memdx.subdoc.DocTooDeep",
821            SubdocErrorKind::CantInsert => "memdx.subdoc.CantInsert",
822            SubdocErrorKind::NotJSON => "memdx.subdoc.NotJSON",
823            SubdocErrorKind::BadRange => "memdx.subdoc.BadRange",
824            SubdocErrorKind::BadDelta => "memdx.subdoc.BadDelta",
825            SubdocErrorKind::PathExists => "memdx.subdoc.PathExists",
826            SubdocErrorKind::ValueTooDeep => "memdx.subdoc.ValueTooDeep",
827            SubdocErrorKind::InvalidCombo => "memdx.subdoc.InvalidCombo",
828            SubdocErrorKind::XattrInvalidFlagCombo => "memdx.subdoc.XattrInvalidFlagCombo",
829            SubdocErrorKind::XattrInvalidKeyCombo => "memdx.subdoc.XattrInvalidKeyCombo",
830            SubdocErrorKind::XattrUnknownMacro => "memdx.subdoc.XattrUnknownMacro",
831            SubdocErrorKind::XattrUnknownVAttr => "memdx.subdoc.XattrUnknownVAttr",
832            SubdocErrorKind::XattrCannotModifyVAttr => "memdx.subdoc.XattrCannotModifyVAttr",
833            SubdocErrorKind::InvalidXattrOrder => "memdx.subdoc.InvalidXattrOrder",
834            SubdocErrorKind::XattrUnknownVattrMacro => "memdx.subdoc.XattrUnknownVattrMacro",
835            SubdocErrorKind::CanOnlyReviveDeletedDocuments => {
836                "memdx.subdoc.CanOnlyReviveDeletedDocuments"
837            }
838            SubdocErrorKind::DeletedDocumentCantHaveValue => {
839                "memdx.subdoc.DeletedDocumentCantHaveValue"
840            }
841            SubdocErrorKind::UnknownStatus { .. } => "memdx.subdoc._OTHER",
842        }
843    }
844}